From 8db0ca44ef787f7a8f78cb94f83dcb9883f4c3d7 Mon Sep 17 00:00:00 2001 From: Gijs de Rooy Date: Fri, 11 Feb 2011 18:33:53 +0100 Subject: [PATCH] An initial lightmap shader --- Effects/lightmap.eff | 145 ++++++++++++++++++++++++++++++++++++++++++ Shaders/lightmap.frag | 52 +++++++++++++++ Shaders/lightmap.vert | 55 ++++++++++++++++ 3 files changed, 252 insertions(+) create mode 100644 Effects/lightmap.eff create mode 100644 Shaders/lightmap.frag create mode 100644 Shaders/lightmap.vert diff --git a/Effects/lightmap.eff b/Effects/lightmap.eff new file mode 100644 index 000000000..d0fa581f9 --- /dev/null +++ b/Effects/lightmap.eff @@ -0,0 +1,145 @@ + + + Effects/lightmap + + + white + + false + + 1 + + + + + + /sim/rendering/shader-effects + + + 2.0 + + + + GL_ARB_shader_objects + GL_ARB_shading_language_100 + GL_ARB_vertex_shader + GL_ARB_fragment_shader + + + + + + true + + material/active + material/ambient + material/diffuse + material/specular + material/emissive + material/shininess + material/color-mode + + + blend/active + blend/source + blend/destination + + shade-model + cull-face + rendering-hint + + + 0 + + texture[0]/type + texture[0]/image + texture[0]/filter + texture[0]/wrap-s + texture[0]/wrap-t + + + + + 1 + + texture[1]/type + texture[1]/image + linear-mipmap-linear + repeat + repeat + + + vertex-program-two-side + + + Shaders/lightmap.vert + Shaders/lightmap.frag + + + texture + sampler-2d + 0 + + + lightmap_texture + sampler-2d + 1 + + + colorMode + int + material/color-mode-uniform + + + + + + true + + material/active + material/ambient + material/diffuse + material/specular + material/emissive + material/shininess + material/color-mode + + + blend/active + blend/source + blend/destination + + shade-model + cull-face + rendering-hint + + texture[0]/active + 0 + texture[0]/image + texture[0]/filter + texture[0]/wrap-s + texture[0]/wrap-t + + + modulate + + + + + + diff --git a/Shaders/lightmap.frag b/Shaders/lightmap.frag new file mode 100644 index 000000000..740ddcd93 --- /dev/null +++ b/Shaders/lightmap.frag @@ -0,0 +1,52 @@ +// -*-C++-*- + +// Ambient term comes in gl_Color.rgb. +varying vec4 diffuse_term; +varying vec3 normal; +varying float fogCoord; + +uniform sampler2D texture; +uniform sampler2D lightmap_texture; + +float luminance(vec3 color) +{ + return dot(vec3(0.212671, 0.715160, 0.072169), color); +} + +void main() +{ + vec3 n, halfV; + float NdotL, NdotHV, fogFactor; + 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_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_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 = 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. + color = clamp(color, 0.0, 1.0); + texel = texture2D(texture, gl_TexCoord[0].st); + fragColor = color * texel + specular; + vec3 lightmapTexel = texture2D(lightmap_texture, gl_TexCoord[0].st).rgb; + fragColor.rgb = max(fragColor.rgb, lightmapTexel*gl_FrontMaterial.diffuse*texel); + fogFactor = exp(-gl_Fog.density * gl_Fog.density * fogCoord * fogCoord); + gl_FragColor = mix(gl_Fog.color, fragColor, fogFactor); +} \ No newline at end of file diff --git a/Shaders/lightmap.vert b/Shaders/lightmap.vert new file mode 100644 index 000000000..74089f070 --- /dev/null +++ b/Shaders/lightmap.vert @@ -0,0 +1,55 @@ +// -*-C++-*- + +// Shader that uses OpenGL state values to do per-pixel lighting +// +// The only light used is gl_LightSource[0], which is assumed to be +// directional. +// +// Diffuse colors come from the gl_Color, ambient from the material. This is +// equivalent to osg::Material::DIFFUSE. + +#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() +{ + vec4 ecPosition = gl_ModelViewMatrix * gl_Vertex; + gl_Position = ftransform(); + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + normal = gl_NormalMatrix * gl_Normal; + 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); +}