Hello, I have a terrain system that alpha blends 8 texture layers using a GLSL shader. I plan to add parralax mapping to the shader, but cannot until the current shader can give decent performance.
The current shader uses the alpha values between all 8 textures to blend the terrain.
It has been giving really poor performance
Here is the fragment shader:
[start]
uniform sampler2D Texture0;
uniform sampler2D Texture1;
uniform sampler2D Texture2;
uniform sampler2D Texture3;
uniform sampler2D Texture4;
uniform sampler2D Texture5;
uniform sampler2D Texture6;
uniform sampler2D Texture7;
varying vec4 normal;
vec4 GenerateTerrainColor() {
vec4 outcolor;
vec4 c1, c2;
c1 = texture2D(Texture0, gl_TexCoord[0].st);
c2 = texture2D(Texture1, gl_TexCoord[1].st);
outcolor = mix(c1, c2, c2.a);
c1 = outcolor;
c2 = texture2D(Texture2, gl_TexCoord[2].st);
outcolor = mix(c1, c2, c2.a);
c1 = outcolor;
c2 = texture2D(Texture3, gl_TexCoord[3].st);
outcolor = mix(c1, c2, c2.a);
c1 = outcolor;
c2 = texture2D(Texture4, gl_TexCoord[4].st);
outcolor = mix(c1, c2, c2.a);
c1 = outcolor;
c2 = texture2D(Texture5, gl_TexCoord[5].st);
outcolor = mix(c1, c2, c2.a);
c1 = outcolor;
c2 = texture2D(Texture6, gl_TexCoord[6].st);
outcolor = mix(c1, c2, c2.a);
c1 = outcolor;
c2 = texture2D(Texture7, gl_TexCoord[7].st);
outcolor = mix(c1, c2, c2.a);
return outcolor;
}
void main() {
vec3 n = normalize(normal.xyz);
float nDotL = max(0.0, dot(n, gl_LightSource[0].position.xyz));
vec4 ambient = gl_FrontLightProduct[0].ambient;
vec4 diffuse = gl_FrontLightProduct[0].diffuse * nDotL;
vec4 color = gl_FrontLightModelProduct.sceneColor + ambient + diffuse;
gl_FragColor = color * GenerateTerrainColor();
}
[end]
Here is the vertex shader
[start]
varying vec4 normal;
void main() {
normal.xyz = normalize(gl_NormalMatrix * gl_Normal);
normal.w = gl_Vertex.y;
gl_TexCoord[0].st = gl_MultiTexCoord0.st;
gl_TexCoord[1].st = gl_MultiTexCoord1.st;
gl_TexCoord[2].st = gl_MultiTexCoord2.st;
gl_TexCoord[3].st = gl_MultiTexCoord3.st;
gl_TexCoord[4].st = gl_MultiTexCoord4.st;
gl_TexCoord[5].st = gl_MultiTexCoord5.st;
gl_TexCoord[6].st = gl_MultiTexCoord6.st;
gl_TexCoord[7].st = gl_MultiTexCoord7.st;
gl_Position = ftransform();
}
[end]
And here is the C+ code associated with rendering the terrain:
void Terrain::renderTerrain() {
glColor4ub(255, 255, 255, 255);
useShaderProgram(terrainShader);
setShaderConstant1i(terrainShader, "Texture0", 0);
setShaderConstant1i(terrainShader, "Texture1", 1);
setShaderConstant1i(terrainShader, "Texture2", 2);
setShaderConstant1i(terrainShader, "Texture3", 3);
setShaderConstant1i(terrainShader, "Texture4", 4);
setShaderConstant1i(terrainShader, "Texture5", 5);
setShaderConstant1i(terrainShader, "Texture6", 6);
setShaderConstant1i(terrainShader, "Texture7", 7);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
for (s32 i = 0; i < 8; i++) {
enableTextureLayer(TerrainTilesets, i);
glTexCoordPointer(2, GL_FLOAT, 0, &TextureCoordBuffer[0]);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}
glNormalPointer(GL_FLOAT, 0, NormalBuffer);
glVertexPointer(3, GL_FLOAT, 0, VertexBuffer);
glDrawElements(GL_QUADS, IndexCount, GL_UNSIGNED_INT, IndexBuffer);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
disableAllTextureLayers();
useShaderProgram(0);
}
Any ideas on how to optimize this shader, or re-implement it in a faster way?
Thanks!