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]