Shader buggy or graphics card too weak? [solved]

Started by
3 comments, last by Hydrael 18 years, 8 months ago
Hello everyone, I've been playing around with shaders for a few weeks now and I'm pretty amazed how powerful they are. I've implemented a ground type blending shader which I use for rendering terrain. I pass several textures to the shader as well as vertex alpha values (how much of groundtype n is visible on this vertex). The alpha values I pass via TexCoord units 6 and 7, so that the values will get interpolated over a triangle. First I tried blending together two groundtypes, which worked perfectly and looked very nice (only used TexCoord unit 7 for the alpha values back then). But only two groundtypes are often just not enough, so I pumped it up to four grounddtypes. And here lies the problem. As soon as I start my program with the 4 layer blender it almost freezes - I roughly get one frame rendered every 10-15 seconds. I really can't explain why, because the shader code doesn't really differ from the 2-layer implementation. I'm using a Radeon Mobility 9700 - this surely isn't a highend card, but I can't imagine that it is not powerful enough to use 4 multitexturing units. Here is the code: Vertex Shader:

/*
GroundBlender Shader Program 
	4 Layer support
---------Vertex Shader---------
*/

varying vec2 texCoords1;
varying vec2 texCoords2;
varying vec2 texCoords3;
varying vec2 texCoords4;
varying vec2 vertexalpha1;
varying vec2 vertexalpha2;

void main()
{
   	gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
   
   	texCoords1   = gl_MultiTexCoord0.xy;
   	texCoords2   = gl_MultiTexCoord1.xy;
	texCoords3   = gl_MultiTexCoord2.xy;
   	texCoords4   = gl_MultiTexCoord3.xy;
   	vertexalpha1 = gl_MultiTexCoord6.xy;
	vertexalpha2 = gl_MultiTexCoord7.xy;

}


Pixel Shader:

/*
GroundBlender Shader Program 
	4 Layer support
---------Pixel Shader---------
*/

varying vec2 texCoords1;
varying vec2 texCoords2;
varying vec2 texCoords3;
varying vec2 texCoords4;
varying vec2 vertexalpha1;
varying vec2 vertexalpha2;

uniform sampler2D GroundTexture1;
uniform sampler2D GroundTexture2;
uniform sampler2D GroundTexture3;
uniform sampler2D GroundTexture4;
   
void main()
{
	float alpha1=vertexalpha1.x;
	float alpha2=vertexalpha1.y;
	float alpha3=vertexalpha2.x;
	float alpha4=vertexalpha2.y;

	vec4 col1=texture2D(GroundTexture1,texCoords1)*alpha1;
	vec4 col2=texture2D(GroundTexture2,texCoords2)*alpha2;
	vec4 col3=texture2D(GroundTexture3,texCoords3)*alpha3;
	vec4 col4=texture2D(GroundTexture4,texCoords4)*alpha4;
	vec4 col=col1+col2+col3+col4;
   
      	gl_FragColor = col;
}


Calling OpenGL function:

void COpenGLWindow::DrawVertexBufferSolid(CFrustum *Frustum)
{
	GLuint size=0;
	GLuint from=0;

	glEnable(GL_TEXTURE_2D);
	glEnableClientState( GL_VERTEX_ARRAY ); 
	glEnableClientState( GL_NORMAL_ARRAY ); 
	glVertexPointer( 3, GL_FLOAT, 0, VertexBuffer); 
	glNormalPointer(GL_FLOAT, 0, NormalBuffer); 

//Activate Shader
	GroundBlender->Activate();

//Layer 1
	glClientActiveTextureARB(GL_TEXTURE0_ARB);
	glTexCoordPointer(2,GL_FLOAT,0,TexCoordBuffer);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);

//Layer 2
	glClientActiveTextureARB(GL_TEXTURE1_ARB);
	glTexCoordPointer(2,GL_FLOAT,0,TexCoordBuffer);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);

//Layer 3
	glClientActiveTextureARB(GL_TEXTURE2_ARB);
	glTexCoordPointer(2,GL_FLOAT,0,TexCoordBuffer);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);

//Layer 4
	glClientActiveTextureARB(GL_TEXTURE3_ARB);
	glTexCoordPointer(2,GL_FLOAT,0,TexCoordBuffer);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);

//Layer 7 -> VertexAlpha Layer 1 und 2
	glClientActiveTextureARB(GL_TEXTURE6_ARB);
	glTexCoordPointer(2,GL_FLOAT,0,VertexAlpha1);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);

//Layer 8 -> VertexAlpha Layer 3 und 4
	glClientActiveTextureARB(GL_TEXTURE7_ARB);
	glTexCoordPointer(2,GL_FLOAT,0,VertexAlpha2);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	
	unsigned int ActTex0=Texture[0].Layer[0];
	unsigned int ActTex1=Texture[0].Layer[1];
	unsigned int ActTex2=Texture[0].Layer[2];
	unsigned int ActTex3=Texture[0].Layer[3];

	glActiveTextureARB(GL_TEXTURE0_ARB);
	glBindTexture(GL_TEXTURE_2D,BasicSpriteFile[ActTex0]->TexID);
	
	glActiveTextureARB(GL_TEXTURE1_ARB);
	glBindTexture(GL_TEXTURE_2D,BasicSpriteFile[ActTex1]->TexID);

	glActiveTextureARB(GL_TEXTURE2_ARB);
	glBindTexture(GL_TEXTURE_2D,BasicSpriteFile[ActTex2]->TexID);
	
	glActiveTextureARB(GL_TEXTURE3_ARB);
	glBindTexture(GL_TEXTURE_2D,BasicSpriteFile[ActTex3]->TexID);
	
	IncrementSun(0);

//Pass uniform variables to Vertex Shader
	glUniform1iARB(glGetUniformLocationARB(GroundBlender->Program(),"GroundTexture1"),0);
	glUniform1iARB(glGetUniformLocationARB(GroundBlender->Program(),"GroundTexture2"),1);
	glUniform1iARB(glGetUniformLocationARB(GroundBlender->Program(),"GroundTexture3"),2);
	glUniform1iARB(glGetUniformLocationARB(GroundBlender->Program(),"GroundTexture4"),3);

	float radius=0;
	int count=0;
	BOOL change=FALSE;
	if(LU)
	{
		for(int x=0;x<LUCount*LUCount;x++)
		{
			radius=LURadius+LUDiff[x];
			if(Frustum->SphereInFrustum(LUMid[x].GetX(),LUMid[x].GetY(),LUMid[x].GetZ(),radius))
			{
				size=LUSpecificSize[x];
				from=LUArray[x];
				int Offset=0;
				count=0;
				change=FALSE;
				for(unsigned int i=0;i<size;i+=6)
				{
					if(TextureChanges())
					{
						if(i!=0)
							glDrawElements(GL_TRIANGLES,count,GL_UNSIGNED_INT,&LUPointer[from+Offset]);
						count=6;

						ActTex0=Texture[LUPointer[from+i]].Layer[0];
						ActTex1=Texture[LUPointer[from+i]].Layer[1];
						ActTex2=Texture[LUPointer[from+i]].Layer[2];
						ActTex3=Texture[LUPointer[from+i]].Layer[3];

						glActiveTextureARB(GL_TEXTURE0_ARB);
						glBindTexture(GL_TEXTURE_2D,BasicSpriteFile[ActTex0]->TexID);

						glActiveTextureARB(GL_TEXTURE1_ARB);
						glBindTexture(GL_TEXTURE_2D,BasicSpriteFile[ActTex1]->TexID);

						glActiveTextureARB(GL_TEXTURE2_ARB);
						glBindTexture(GL_TEXTURE_2D,BasicSpriteFile[ActTex2]->TexID);

						glActiveTextureARB(GL_TEXTURE3_ARB);
						glBindTexture(GL_TEXTURE_2D,BasicSpriteFile[ActTex3]->TexID);

						glUniform1iARB(glGetUniformLocationARB(GroundBlender->Program(),"GroundTexture1"),0);
						glUniform1iARB(glGetUniformLocationARB(GroundBlender->Program(),"GroundTexture2"),1);
						glUniform1iARB(glGetUniformLocationARB(GroundBlender->Program(),"GroundTexture3"),2);
						glUniform1iARB(glGetUniformLocationARB(GroundBlender->Program(),"GroundTexture4"),3);

						change=TRUE;
						Offset=i;
					}
					else
						count+=6;
				}
				if(!change)
					glDrawElements(GL_TRIANGLES,size,GL_UNSIGNED_INT,&LUPointer[from]);
				else
					glDrawElements(GL_TRIANGLES,count,GL_UNSIGNED_INT,&LUPointer[from+Offset]);
				
			}
		}
	}

	glDisableClientState( GL_VERTEX_ARRAY ); 
	glDisableClientState( GL_NORMAL_ARRAY ); 
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	glDisable(GL_TEXTURE_2D);

//Deactivate Shader
	GroundBlender->Deactivate();
}



The outer LUCount loop is somewhat simlilar to a quadtree and only used to minimize visibility checks. Can anyone spot something I did wrong? Thanks for any help in advance Chris [Edited by - Hydrael on August 17, 2005 10:47:10 AM]
Advertisement
hmmm it shouldnt be a problem, however heres a couple of tips for you;

- texture coords are really 4 floating point values (x,y,z,w) as such you can pass all 4 alpha values in one texture coordinate set.
- same goes for the varying variables, they always take up a vec4, so instead of using two vec2s pack them into a vec4.
- you might even be better off making a generic vertex attribute so that the code is a bit clearer.
- you dont have to assign each of the values to a float in your fragment program, you can just read them directly;
vec4 col1=texture2D(GroundTexture1,texCoords1)*vertexalpha1[0];

- As you are summing the results you'll probably be better off just declaring one vec4 for the final color and doing += instead of having 4 values and then adding them into another vector.

As for your problem, check the compiler logs, thats the first port of call when something doesnt appear to be working right
Ah, thanks a lot. That will be the first subjects to change as soon as I get home from work.

One question left regarding this:
Quote:Original post by phantom
hmmm it shouldnt be a problem, however heres a couple of tips for you;

- texture coords are really 4 floating point values (x,y,z,w) as such you can pass all 4 alpha values in one texture coordinate set.


When setting up the TexCoord Pointer then I'd have to change

glTexCoordPointer(2,GL_FLOAT,0,VertexAlpha1);
to
glTexCoordPointer(4,GL_FLOAT,0,VertexAlpha);

right?
yes, thats correct
Thanks a lot phantom.
Your hints helped a lot solving the problem.
After checking the info log, I've found out, that the fragment shader was running in software mode because of unsupported language elements.
After changing some values from vec2 to vec4 (and some other finetuning) it worked :D

This topic is closed to new replies.

Advertisement