Problems with transparency/texturing for grass

Started by
13 comments, last by zedzeek 18 years, 8 months ago
Hi, I have a problem with my speed. I recently asked about VBO's. It seems to work finally but I'm not really sure I'm doing it right. I had a demo that could render a landscape with 2 million triangle strips on 20/30 fps. The landscape wasn't textured or litten, it only a color per vertex. Now I tried VBO's on grass. I have a large list of quads on the videocard that are placed pretty close to each other. With 200.000 polygons, I got 20/30 fps or something. Isn't that a little bit slow? I assume quads are slower than strips but this is 10 times slower than that demo. Although... If I turn the camera in such a way that I can't see quads, I get a 60 frames per second. I think the real problem is the texturing/transparency and that's what this question is mainly about. I'm trying to render grass so each quad has a transparent texture and a pixel shader that does this:

	fixed4	d	= h4tex2D( decal, iTex0.xy ); // get the texture
	color.rgb	= d.rgb * inputCol; 	// multiply 2 vectors
	color.a		= d.a;			// alpha channel
Seems pretty simple to me but the grass is really slow. My framerate easily drops below the 30 when there are many quads in my view, especially from really close. I can't cull the quads on a further distance away, as this is a top-view game. So there's always pretty much in sight. There are 3000/4000 quads in sight. It's not much geometry, so I think its a texturing and/or transparency problem. When I disable transparency, its much faster. Normally I enable transparency with
	
	glEnable( GL_ALPHA_TEST );
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Does somebody know how to improve the grass speed? Maybe there is a faster transparency method? Using "glAlphaFunc(GL_GEQUAL, 0.8);" or something seemed to be a little bit faster (4/6 frames) but I found it still too slow. Maybe 4000 quads is just too much for my old GeForce 5700 ultra but I wanted to make sure if I'm doing it right. I saw pretty much transparent stuff in games like Farcry or Age Of Empires3(and its also reflected there)... Greetings, Rick
Advertisement
The application probably is fillrate limited.

Also this code does nothing:
glEnable(GL_ALPHA_TEST);glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

Alpha testing and alpha blending are two different things.

For grass you can probably just use alpha testing. In that case use glAlphaFunc with glEnable(GL_ALPHA_TEST).
I'm sorry, I forgot to say blending is enabled as well. The grass can fade away if its too far away from the camera.

But you're telling there's not much I can do about the problem (Except reducing the amount of quads maybe)?

Greetings,
Rick
I have been working on a similar demo that renders large amounts of grass and at a given point I started to experience major slow downs; it's only logic with the massive polygon count and pixel shading and not to forget multisampling to smooth out the grass blades. One of the tricks that I've done is to split my scene into portals and use frustum and occlusion culling to throw away stuff that doesn't need to be rendered.
I can post a screenshot and few code snippets if requested (that way I won't be accused of hijacking this thread [wink] )
My terrain is divided in small cells, only the cells around the camera are rendered so that's my way of culling. The problem is that the camera has a top-down view, so there's always much in sight. The amount of polygons isn't much of a problem, especially not with the VBO approach. But only a thousand quads will already slow down the scene. As far as I know, the transparency is the big FPS killer, because if I switch if off, the framerate is doubled.

As for the stuff you liked to post, go ahead, I'm curious!

Greetings,
Rick
Screen 1
Screen 2

It looks like you're doing the right thing with the cell division approach, I would suggest that you drop QUADs and go ahead with TRIANGLES; it will run faster [smile]
as for grass rendering I read a post of Yann L somewhere
he said he creates one VBO where he puts the grass geometry into it

and in order to render it over a curved patch he does the vertex transformation in the vertex shader just translating the quads/triangles

thus you need only a single VBO to render the same grass type this should also work with trees and other things like stones ....

just use the control points of your patch and a cubic interpolation function to calculate the transformation offsets for the grass quads

I hope that helps, basically you only need the code inside the 2nd for loop

Heres the code:

cubic interpolation function
//cubic weight function	float	cubic(float a, float b, float c, float d, float fact)	{		float s0,s1,s2,s3,m;		m = fact*fact;		s0 = (d-c)-(a-b);		s1 = (a-b)-s0;		s2 = c-a;		s3 = b;		return (s0*m*fact+s1*m+s2*fact+s3);	};


here is the bicubic interpolation function from my perlin noise library
which can easily be taken as a foundation for a decent vertex shader implementation *I suggest using the CG toolkit for API independence*
//sample image up( powers of 2)	template<class U, class W> void sample_bicubic(const U& s, W& d)	{		uint32	i,j;		int32	is,js;		float x,y,dx,dy;		int32	XCoords[4];		int32	YCoords[4];		float	weights[4];		dx = dy = static_cast<float>(U::MAP_SIZE)/ static_cast<float>(W::MAP_SIZE);		for(i=0;i<W::MAP_SIZE;i++)		{			//calculate source coordinates			x	= i*dy;			is	= static_cast<int32>(x);			x	= x - (is);			XCoords[0] = (is-1 + U::MAP_SIZE)%U::MAP_SIZE;			XCoords[1] = (is + U::MAP_SIZE)%U::MAP_SIZE;			XCoords[2] = (is+1 + U::MAP_SIZE)%U::MAP_SIZE;			XCoords[3] = (is+2 + U::MAP_SIZE)%U::MAP_SIZE;			for(j=0;j<W::MAP_SIZE;j++)			{				//calculate source coordinates				y	= j*dy;				js	= static_cast<int32>(y);				y	= y - (js);				YCoords[0] = (js-1 + U::MAP_SIZE)%U::MAP_SIZE;				YCoords[1] = (js + U::MAP_SIZE)%U::MAP_SIZE;				YCoords[2] = (js+1 + U::MAP_SIZE)%U::MAP_SIZE;				YCoords[3] = (js+2 + U::MAP_SIZE)%U::MAP_SIZE;				//interpolate the y axis				weights[0] = cubicweight2(					s.m_Map[XCoords[0]][YCoords[0]],					s.m_Map[XCoords[0]][YCoords[1]],					s.m_Map[XCoords[0]][YCoords[2]],					s.m_Map[XCoords[0]][YCoords[3]],					y);				weights[1] = cubicweight2(					s.m_Map[XCoords[1]][YCoords[0]],					s.m_Map[XCoords[1]][YCoords[1]],					s.m_Map[XCoords[1]][YCoords[2]],					s.m_Map[XCoords[1]][YCoords[3]],					y);				weights[2] = cubicweight2(					s.m_Map[XCoords[2]][YCoords[0]],					s.m_Map[XCoords[2]][YCoords[1]],					s.m_Map[XCoords[2]][YCoords[2]],					s.m_Map[XCoords[2]][YCoords[3]],					y);				weights[3] = cubicweight2(					s.m_Map[XCoords[3]][YCoords[0]],					s.m_Map[XCoords[3]][YCoords[1]],					s.m_Map[XCoords[3]][YCoords[2]],					s.m_Map[XCoords[3]][YCoords[3]],					y);				//interpolate the x axis				d.m_Map[j] = cubicweight2(weights[0],weights[1],weights[2],weights[3],x);			}		}	};


Big thanks goes to outrider for presenting the correct weight factors
The bicubic interpolation thread
http://www.8ung.at/basiror/theironcross.html
Quote:Now I tried VBO's on grass. I have a large list of quads on the videocard that are placed pretty close to each other. With 200.000 polygons, I got 20/30 fps or something. Isn't that a little bit slow? I assume quads are slower than strips but this is 10 times slower than that demo. Although... If I turn the camera in such a way that I can't see quads, I get a 60 frames per second. I think the real problem is the texturing/transparency and that's what this question is mainly about.


yes thats most likely true, DLs VBOs aint gonna help much at all.
try
texture compression
/mipmapping
/lower aniostropic setting
/alphatest
/lower quality texture
/fade out polygons if they take up to much screenspace
etc

Quote:
When I disable transparency, its much faster. Normally I enable transparency with
glEnable( GL_ALPHA_TEST );
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

note those are 2 different things ones an alpha test and the other is blending
[Thread-jack]
Hey Zed, are you using a pixel shader to simulate the illumination of your explosions trails or is it simply a sequence of packed textures?
[/Thread-jack]
Thanks everybody!

Java dude, may I ask how many grass there is on that screens? And what FPS on what kind of videocard? The screens looked good by the way!

I shall try to mess around with the texture settings. Its probably not gonna help very much, even a shader that doesn't do texturing at all (just set the color on 1 or something) is slow with 4000 quads. I didn't thought transparency would so heavy.

Greetings,
Rick

This topic is closed to new replies.

Advertisement