From 43ab6827a3af85e21c7897c3cdb76cde33cd94d1 Mon Sep 17 00:00:00 2001 From: Tim Moore Date: Wed, 30 Jun 2010 18:01:59 +0200 Subject: [PATCH 1/2] eliminate constantColor from varying values --- Shaders/model-default.frag | 5 +++-- Shaders/model-default.vert | 7 ++----- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/Shaders/model-default.frag b/Shaders/model-default.frag index 2cf37e2a1..f430f542b 100644 --- a/Shaders/model-default.frag +++ b/Shaders/model-default.frag @@ -1,6 +1,6 @@ // -*-C++-*- -varying vec4 diffuse, constantColor; +varying vec4 diffuse; varying vec3 normal, lightDir, halfVector; varying float fogCoord, alpha; @@ -17,7 +17,8 @@ void main() { vec3 n, halfV; float NdotL, NdotHV, fogFactor; - vec4 color = constantColor; + vec4 color = gl_FrontLightModelProduct.sceneColor + + gl_FrontMaterial.ambient * gl_LightSource[0].ambient; vec4 texel; vec4 fragColor; vec4 specular = vec4(0.0); diff --git a/Shaders/model-default.vert b/Shaders/model-default.vert index 924f90c38..cef6e6e24 100644 --- a/Shaders/model-default.vert +++ b/Shaders/model-default.vert @@ -8,7 +8,7 @@ // Diffuse colors come from the gl_Color, ambient from the material. This is // equivalent to osg::Material::DIFFUSE. -varying vec4 diffuse, constantColor; +varying vec4 diffuse; varying vec3 normal, lightDir, halfVector; varying float alpha, fogCoord; @@ -17,7 +17,6 @@ uniform bool twoSideHack; void main() { vec4 ecPosition = gl_ModelViewMatrix * gl_Vertex; - vec3 ecPosition3 = vec3(gl_ModelViewMatrix * gl_Vertex) / ecPosition.w; gl_Position = ftransform(); gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; normal = gl_NormalMatrix * gl_Normal; @@ -36,7 +35,5 @@ void main() gl_FrontColor = vec4(0.0, 0.0, 0.0, 1.0); gl_BackColor = vec4(0.0, 0.0, 0.0, 0.0); } - constantColor = gl_FrontLightModelProduct.sceneColor - + gl_FrontMaterial.ambient * gl_LightSource[0].ambient; - fogCoord = abs(ecPosition3.z); + fogCoord = abs(ecPosition.z / ecPosition.w); } From d27174028e3bad6076bc7665bca5cecf59fd7d14 Mon Sep 17 00:00:00 2001 From: Tim Moore Date: Fri, 13 Aug 2010 18:49:25 +0200 Subject: [PATCH 2/2] shader optimizations Use two-pass rendering for some shaders to reduce the cost of expensive shaders. Implement some material animations using a shader uniform. Eliminate use of gl_FrontFacing. It's too buggy on ATI/ Macintosh. --- Effects/landmass.eff | 57 ++++++++++++++++++++++++++++++++++++ Effects/material-diffuse.eff | 12 +++++--- Effects/material-off.eff | 10 +++---- Effects/model-default.eff | 10 +++---- Effects/terrain-default.eff | 56 ++++++++++++++++++++++++++++++++--- Shaders/default.frag | 23 +++++++++------ Shaders/default.vert | 53 +++++++++++++++++++++++++-------- Shaders/mat-anim.frag | 4 ++- Shaders/mat-anim.vert | 4 +-- Shaders/model-default.frag | 23 ++++++++------- Shaders/model-default.vert | 42 ++++++++++++++++++-------- Shaders/terrain-default.frag | 6 ++-- Shaders/terrain-nocolor.frag | 15 ++++++++++ 13 files changed, 245 insertions(+), 70 deletions(-) create mode 100644 Shaders/terrain-nocolor.frag diff --git a/Effects/landmass.eff b/Effects/landmass.eff index 1f6114987..e2c82b644 100644 --- a/Effects/landmass.eff +++ b/Effects/landmass.eff @@ -43,6 +43,59 @@ GL_EXT_geometry_shader4 + + true + + material/ambient + material/diffuse + material/specular + ambient-and-diffuse + + transparent + smooth + back + + -1 + RenderBin + + + 1 + texture[0]/image + texture[0]/filter + texture[0]/wrap-s + texture[0]/wrap-t + + texture[0]/internal-format + + + + Shaders/landmass-g.vert + Shaders/landmass.geom + Shaders/terrain-nocolor.frag + 18 + triangles + triangle-strip + + tangent + 6 + + + binormal + 7 + + + + texture + sampler-2d + 1 + + + canopy_height + float + canopy-height + + 0 0 0 0 + true @@ -134,6 +187,10 @@ float quality-level + + lequal + false + diff --git a/Effects/material-diffuse.eff b/Effects/material-diffuse.eff index 0d612451c..79963a9a1 100644 --- a/Effects/material-diffuse.eff +++ b/Effects/material-diffuse.eff @@ -1,14 +1,18 @@ - Effects/material-off + Effects/material-diffuse Effects/model-default - Shaders/mode-diffuse.vert - Shaders/mat-anim.vert - Shaders/mat-anim.frag + Shaders/default.vert + Shaders/default.frag + + colorMode + int + 1 + diff --git a/Effects/material-off.eff b/Effects/material-off.eff index 1d08cc3fc..1e6e3e6db 100644 --- a/Effects/material-off.eff +++ b/Effects/material-off.eff @@ -4,11 +4,11 @@ Effects/model-default - - Shaders/mode-off.vert - Shaders/mat-anim.vert - Shaders/mat-anim.frag - + + colorMode + int + 0 + diff --git a/Effects/model-default.eff b/Effects/model-default.eff index ece38c79e..7cbdb3948 100644 --- a/Effects/model-default.eff +++ b/Effects/model-default.eff @@ -65,8 +65,8 @@ vertex-program-two-side - Shaders/model-default.vert - Shaders/model-default.frag + Shaders/default.vert + Shaders/default.frag texture @@ -74,9 +74,9 @@ 0 - twoSideHack - bool - vertex-program-two-side + colorMode + int + 1 diff --git a/Effects/terrain-default.eff b/Effects/terrain-default.eff index a7e27512a..fa48f7a4e 100644 --- a/Effects/terrain-default.eff +++ b/Effects/terrain-default.eff @@ -57,6 +57,44 @@ + + true + + material/ambient + material/diffuse + material/specular + material/emissive + material/shininess + ambient-and-diffuse + + transparent + smooth + back + + -1 + RenderBin + + + 0 + texture[0]/image + texture[0]/filter + texture[0]/wrap-s + texture[0]/wrap-t + + texture[0]/internal-format + + + + Shaders/default.vert + Shaders/terrain-nocolor.frag + + + texture + sampler-2d + 0 + + 0 0 0 0 + true @@ -87,12 +125,22 @@ Shaders/default.vert - Shaders/terrain-default.frag + Shaders/default.frag - texture - sampler-2d - 0 + texture + sampler-2d + 0 + + + colorMode + int + 2 + + + lequal + false + diff --git a/Shaders/default.frag b/Shaders/default.frag index 53d3fc20d..3b01a6676 100644 --- a/Shaders/default.frag +++ b/Shaders/default.frag @@ -1,8 +1,9 @@ // -*-C++-*- -varying vec4 diffuse, constantColor; -varying vec3 normal, lightDir, halfVector; -varying float fogCoord, alpha; +// Ambient term comes in gl_Color.rgb. +varying vec4 diffuse_term; +varying vec3 normal; +varying float fogCoord; uniform sampler2D texture; @@ -15,24 +16,28 @@ void main() { vec3 n, halfV; float NdotL, NdotHV, fogFactor; - vec4 color = constantColor; + vec4 color = gl_Color; + vec3 lightDir = gl_LightSource[0].position.xyz; + vec3 halfVector = gl_LightSource[0].halfVector.xyz; vec4 texel; vec4 fragColor; vec4 specular = vec4(0.0); n = normalize(normal); - if (!gl_FrontFacing) - n = -n; + // If gl_Color.a == 0, this is a back-facing polygon and the + // normal should be reversed. + + n = (2.0 * gl_Color.a - 1.0) * n; NdotL = max(dot(n, lightDir), 0.0); if (NdotL > 0.0) { - color += diffuse * NdotL; - halfV = normalize(halfVector); + color += diffuse_term * NdotL; + halfV = halfVector; NdotHV = max(dot(n, halfV), 0.0); if (gl_FrontMaterial.shininess > 0.0) specular.rgb = (gl_FrontMaterial.specular.rgb * gl_LightSource[0].specular.rgb * pow(NdotHV, gl_FrontMaterial.shininess)); } - color.a = alpha; + color.a = diffuse_term.a; // This shouldn't be necessary, but our lighting becomes very // saturated. Clamping the color before modulating by the texture // is closer to what the OpenGL fixed function pipeline does. diff --git a/Shaders/default.vert b/Shaders/default.vert index 7665077c9..74089f070 100644 --- a/Shaders/default.vert +++ b/Shaders/default.vert @@ -5,24 +5,51 @@ // The only light used is gl_LightSource[0], which is assumed to be // directional. // -// Diffuse and ambient colors come from the gl_Color. This is -// equivalent to osg::Material::AMBIENT_AND_DIFFUSE. +// Diffuse colors come from the gl_Color, ambient from the material. This is +// equivalent to osg::Material::DIFFUSE. -varying vec4 diffuse, constantColor; -varying vec3 normal, lightDir, halfVector; -varying float fogCoord, alpha; +#define MODE_OFF 0 +#define MODE_DIFFUSE 1 +#define MODE_AMBIENT_AND_DIFFUSE 2 + +// The constant term of the lighting equation that doesn't depend on +// the surface normal is passed in gl_{Front,Back}Color. The alpha +// component is set to 1 for front, 0 for back in order to work around +// bugs with gl_FrontFacing in the fragment shader. +varying vec4 diffuse_term; +varying vec3 normal; +varying float fogCoord; +uniform int colorMode; void main() { - vec3 ecPosition = vec3(gl_ModelViewMatrix * gl_Vertex); + vec4 ecPosition = gl_ModelViewMatrix * gl_Vertex; gl_Position = ftransform(); gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; normal = gl_NormalMatrix * gl_Normal; - lightDir = normalize(vec3(gl_LightSource[0].position)); - halfVector = normalize(gl_LightSource[0].halfVector.xyz); - diffuse = gl_Color * gl_LightSource[0].diffuse; - alpha = gl_Color.a; - constantColor = gl_FrontMaterial.emission - + gl_Color * (gl_LightModel.ambient + gl_LightSource[0].ambient); - fogCoord = abs(ecPosition.z); + vec4 ambient_color, diffuse_color; + if (colorMode == MODE_DIFFUSE) { + diffuse_color = gl_Color; + ambient_color = gl_FrontMaterial.ambient; + } else if (colorMode == MODE_AMBIENT_AND_DIFFUSE) { + diffuse_color = gl_Color; + ambient_color = gl_Color; + } else { + diffuse_color = gl_FrontMaterial.diffuse; + ambient_color = gl_FrontMaterial.ambient; + } + diffuse_term = diffuse_color * gl_LightSource[0].diffuse; + vec4 constant_term = gl_FrontMaterial.emission + ambient_color * + (gl_LightModel.ambient + gl_LightSource[0].ambient); + // Super hack: if diffuse material alpha is less than 1, assume a + // transparency animation is at work + if (gl_FrontMaterial.diffuse.a < 1.0) + diffuse_term.a = gl_FrontMaterial.diffuse.a; + else + diffuse_term.a = gl_Color.a; + // Another hack for supporting two-sided lighting without using + // gl_FrontFacing in the fragment shader. + gl_FrontColor.rgb = constant_term.rgb; gl_FrontColor.a = 1.0; + gl_BackColor.rgb = constant_term.rgb; gl_BackColor.a = 0.0; + fogCoord = abs(ecPosition.z / ecPosition.w); } diff --git a/Shaders/mat-anim.frag b/Shaders/mat-anim.frag index e6b5683e0..a52daeec6 100644 --- a/Shaders/mat-anim.frag +++ b/Shaders/mat-anim.frag @@ -2,7 +2,7 @@ // Shader for use with material animations varying vec4 diffuse, constantColor, matSpecular; -varying vec3 normal, lightDir, halfVector; +varying vec3 normal; varying float fogCoord, alpha; uniform sampler2D texture; @@ -12,6 +12,8 @@ void main() vec3 n, halfV; float NdotL, NdotHV, fogFactor; vec4 color = constantColor; + vec3 lightDir = gl_LightSource[0].position.xyz; + vec3 halfVector = gl_LightSource[0].halfVector.xyz; vec4 texel; vec4 fragColor; vec4 specular = vec4(0.0); diff --git a/Shaders/mat-anim.vert b/Shaders/mat-anim.vert index 5b76f0907..3a3667d38 100644 --- a/Shaders/mat-anim.vert +++ b/Shaders/mat-anim.vert @@ -13,7 +13,7 @@ vec4 specularColor(); vec4 emissionColor(); varying vec4 diffuse, constantColor, matSpecular; -varying vec3 normal, lightDir, halfVector; +varying vec3 normal; varying float alpha, fogCoord; void main() @@ -23,8 +23,6 @@ void main() gl_Position = ftransform(); gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; normal = gl_NormalMatrix * gl_Normal; - lightDir = normalize(vec3(gl_LightSource[0].position)); - halfVector = normalize(gl_LightSource[0].halfVector.xyz); diffuse = diffuseColor() * gl_LightSource[0].diffuse; // Super hack: if diffuse material alpha is less than 1, assume a // transparency animation is at work diff --git a/Shaders/model-default.frag b/Shaders/model-default.frag index f430f542b..5ed50a642 100644 --- a/Shaders/model-default.frag +++ b/Shaders/model-default.frag @@ -1,10 +1,9 @@ // -*-C++-*- -varying vec4 diffuse; -varying vec3 normal, lightDir, halfVector; -varying float fogCoord, alpha; - -uniform bool twoSideHack; +// Ambient term comes in gl_Color.rgb. +varying vec4 diffuse_term; +varying vec3 normal; +varying float fogCoord; uniform sampler2D texture; @@ -17,17 +16,19 @@ void main() { vec3 n, halfV; float NdotL, NdotHV, fogFactor; - vec4 color = gl_FrontLightModelProduct.sceneColor - + gl_FrontMaterial.ambient * gl_LightSource[0].ambient; + vec4 color = gl_FrontLightModelProduct.sceneColor + gl_Color; + vec3 lightDir = gl_LightSource[0].position.xyz; + vec3 halfVector = gl_LightSource[0].halfVector.xyz; vec4 texel; vec4 fragColor; vec4 specular = vec4(0.0); n = normalize(normal); - if (twoSideHack && gl_Color.a == 0.0) - n = -n; + // If gl_Color.a == 0, this is a back-facing polygon and the + // normal should be reversed. + n = (2.0 * gl_Color.a - 1.0) * n; NdotL = max(dot(n, lightDir), 0.0); if (NdotL > 0.0) { - color += diffuse * NdotL; + color += diffuse_term * NdotL; halfV = normalize(halfVector); NdotHV = max(dot(n, halfV), 0.0); if (gl_FrontMaterial.shininess > 0.0) @@ -35,7 +36,7 @@ void main() * gl_LightSource[0].specular.rgb * pow(NdotHV, gl_FrontMaterial.shininess)); } - color.a = alpha; + color.a = diffuse_term.a; // This shouldn't be necessary, but our lighting becomes very // saturated. Clamping the color before modulating by the texture // is closer to what the OpenGL fixed function pipeline does. diff --git a/Shaders/model-default.vert b/Shaders/model-default.vert index cef6e6e24..0202419e9 100644 --- a/Shaders/model-default.vert +++ b/Shaders/model-default.vert @@ -8,11 +8,19 @@ // Diffuse colors come from the gl_Color, ambient from the material. This is // equivalent to osg::Material::DIFFUSE. -varying vec4 diffuse; -varying vec3 normal, lightDir, halfVector; -varying float alpha, fogCoord; +#define MODE_OFF 0 +#define MODE_DIFFUSE 1 +#define MODE_AMBIENT_AND_DIFFUSE 2 -uniform bool twoSideHack; +// The ambient term of the lighting equation that doesn't depend on +// the surface normal is passed in gl_{Front,Back}Color. The alpha +// component is set to 1 for front, 0 for back in order to work around +// bugs with gl_FrontFacing in the fragment shader. +varying vec4 diffuse_term; +varying vec3 normal; +varying float fogCoord; + +uniform int colorMode; void main() { @@ -20,20 +28,28 @@ void main() gl_Position = ftransform(); gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; normal = gl_NormalMatrix * gl_Normal; - lightDir = normalize(vec3(gl_LightSource[0].position)); - halfVector = normalize(gl_LightSource[0].halfVector.xyz); - diffuse = gl_Color * gl_LightSource[0].diffuse; + vec4 ambient_color, diffuse_color; + if (colorMode == MODE_DIFFUSE) { + diffuse_color = gl_Color; + ambient_color = gl_FrontMaterial.ambient; + } else if (colorMode == MODE_AMBIENT_AND_DIFFUSE) { + diffuse_color = gl_Color; + ambient_color = gl_Color; + } else { + diffuse_color = gl_FrontMaterial.diffuse; + ambient_color = gl_FrontMaterial.ambient; + } + diffuse_term = diffuse_color * gl_LightSource[0].diffuse; + vec4 ambient_term = ambient_color * gl_LightSource[0].ambient; // Super hack: if diffuse material alpha is less than 1, assume a // transparency animation is at work if (gl_FrontMaterial.diffuse.a < 1.0) - alpha = gl_FrontMaterial.diffuse.a; + diffuse_term.a = gl_FrontMaterial.diffuse.a; else - alpha = gl_Color.a; + diffuse_term.a = gl_Color.a; // Another hack for supporting two-sided lighting without using // gl_FrontFacing in the fragment shader. - if (twoSideHack) { - gl_FrontColor = vec4(0.0, 0.0, 0.0, 1.0); - gl_BackColor = vec4(0.0, 0.0, 0.0, 0.0); - } + gl_FrontColor.rgb = ambient_term.rgb; gl_FrontColor.a = 1.0; + gl_BackColor.rgb = ambient_term.rgb; gl_FrontColor.a = 0.0; fogCoord = abs(ecPosition.z / ecPosition.w); } diff --git a/Shaders/terrain-default.frag b/Shaders/terrain-default.frag index ba189d8dd..f3571459a 100644 --- a/Shaders/terrain-default.frag +++ b/Shaders/terrain-default.frag @@ -5,7 +5,6 @@ varying vec3 normal, lightDir, halfVector; varying float fogCoord, alpha; uniform sampler2D texture; -uniform sampler3D noise; float luminance(vec3 color) { @@ -16,7 +15,10 @@ void main() { vec3 n, halfV; float NdotL, NdotHV, fogFactor; - vec4 color = constantColor; + vec4 color = gl_FrontMaterial.emission + + gl_Color * (gl_LightModel.ambient + gl_LightSource[0].ambient); + vec3 lightDir = gl_LightSource[0].position.xyz; + vec3 halfVector = gl_LightSource[0].halfVector.xyz; vec4 texel; vec4 fragColor; vec4 specular = vec4(0.0); diff --git a/Shaders/terrain-nocolor.frag b/Shaders/terrain-nocolor.frag new file mode 100644 index 000000000..d5a215b00 --- /dev/null +++ b/Shaders/terrain-nocolor.frag @@ -0,0 +1,15 @@ +// -*-C++-*- +uniform sampler2D texture; + +void main() +{ + vec4 color = vec4(1.0, 1.0, 1.0, 1.0); + vec4 texel; + vec4 fragColor; + + texel = texture2D(texture, gl_TexCoord[0].st); + fragColor = color * texel; + + gl_FragColor = fragColor; + +}