I have a custom GLSL shader that I made by combining different shaders from the Blender wikibooks site. It does exactly what I want to to except for the lack of surface normals. I’ve gone of the code several times, but I’m unable to determine the cause. Maybe GLSL is unable to handle multiple lights with a normal map, but the default (non game) renderer has no problems with them. Any advice on how to fix the problem?
import bgefrom bge.logic import getOuterScaleColor//these functions are defined in an initialization script that runs before this one
from bge.logic import getBellyScaleColor
from bge.logic import getEyeColor
cont = bge.logic.getCurrentController()
own = cont.owner
VertexShader = """
attribute vec4 tangent;
varying vec4 position;
// position of the vertex (and fragment) in view space
//varying vec3 varyingNormalDirection;
// surface normal vector in view space
varying vec4 texCoords; // the texture coordinates
varying mat3 localSurface2View;
void main()
{
position = gl_ModelViewMatrix * gl_Vertex;
//varyingNormalDirection =
normalize(gl_NormalMatrix * gl_Normal);
localSurface2View[0] = normalize(gl_NormalMatrix
* tangent.xyz);
localSurface2View[2] =
normalize(gl_NormalMatrix * gl_Normal);
localSurface2View[1] = normalize(
cross(localSurface2View[2], localSurface2View[0])
* tangent.w);
texCoords = gl_MultiTexCoord0;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}"""
FragmentShader = """
const int numberOfLights = gl_MaxLights;
// up to gl_MaxLights (often 8)
varying mat3 localSurface2View;
varying vec4 position;
// position of the vertex (and fragment) in view space
//varying vec3 varyingNormalDirection;
// surface normal vector in view space
uniform sampler2D bgTexture;
uniform sampler2D guideTexture;
uniform sampler2D specularity;
uniform sampler2D normalMap;
uniform vec3 skinColor1;
uniform vec3 skinColor2;
uniform vec3 eyeColor;
varying vec4 texCoords;
//varying vec4 bg_tex_at_loc;
void main()
{
vec4 bg_tex_at_loc = texture2D(bgTexture, texCoords.xy);
vec4 guide_tex_at_loc = texture2D(guideTexture, texCoords.xy);
vec4 prim_spec_at_loc = texture2D(specularity, texCoords.xy);
vec3 localTexture = vec3(bg_tex_at_loc) * (1.0 - guide_tex_at_loc.g) + (skinColor1 * guide_tex_at_loc.g);
localTexture = localTexture * (1.0 - guide_tex_at_loc.r) + (skinColor2 * guide_tex_at_loc.r);
localTexture = localTexture * (1.0 - guide_tex_at_loc.b) + (eyeColor * guide_tex_at_loc.b);
float shineLocalTexture = (prim_spec_at_loc.r);
vec4 encodedNormal = texture2D(normalMap, vec2(texCoords));
vec3 localCoords =
normalize(vec3(2.0, 2.0, 1.0) * vec3(encodedNormal)
- vec3(1.0, 1.0, 0.0));
// constants depend on encoding
vec3 normalDirection = normalize(localSurface2View * localCoords);
vec3 viewDirection = -normalize(vec3(position));
vec3 lightDirection = vec3(0.0, 0.0, 0.0);
float attenuation = 1.0;
// initialize total lighting with ambient lighting
vec3 totalLighting = vec3(gl_LightModel.ambient)
* localTexture;
for (int index = 0; index < numberOfLights; index++) //For loop for dealing with multiple lights
// for all light sources
{
if (0.0 == gl_LightSource[index].position.w)
// directional light?
{
attenuation = 1.0; // no attenuation
lightDirection =
normalize(vec3(gl_LightSource[index].position));
}
if (0.0 != gl_LightSource[index].position.w
&& gl_LightSource[index].spotCutoff > 90.0)
// point light?
{
vec3 positionToLightSource =
vec3(gl_LightSource[index].position - position);
float distance = length(positionToLightSource);
attenuation = 1.0 / distance; // linear attenuation
lightDirection = normalize(positionToLightSource);
}
if (0.0 != gl_LightSource[index].position.w
&& gl_LightSource[index].spotCutoff <= 90.0)
// spotlight?
{
vec3 positionToLightSource =
vec3(gl_LightSource[index].position - position);
float distance = length(positionToLightSource);
attenuation = 1.0 / distance; // linear attenuation
lightDirection = normalize(positionToLightSource);
float clampedCosine = max(0.0, dot(-lightDirection,
gl_LightSource[index].spotDirection));
if (clampedCosine < gl_LightSource[index].spotCosCutoff)
// outside of spotlight cone?
{
attenuation = 0.0;
}
else
{
attenuation = attenuation * pow(clampedCosine,
gl_LightSource[index].spotExponent);
}
}
vec3 diffuseReflection = attenuation
* vec3(gl_LightSource[index].diffuse)
* localTexture
* max(0.0, dot(normalDirection, lightDirection));
vec3 specularReflection;
if (dot(normalDirection, lightDirection) < 0.0)
// light source on the wrong side?
{
specularReflection = vec3(0.0, 0.0, 0.0);
// no specular reflection
}
else // light source on the right side
{
specularReflection = attenuation
* vec3(gl_LightSource[index].specular)
* (shineLocalTexture * vec3(gl_FrontMaterial.specular))
* pow(max(0.0, dot(reflect(-lightDirection,
normalDirection), viewDirection)),
gl_FrontMaterial.shininess);
}
totalLighting = totalLighting + diffuseReflection
+ specularReflection;
}
gl_FragColor = vec4(totalLighting, 1.0);
}"""
mesh = own.meshes[0]
for mat in mesh.materials:
shader = mat.getShader()
if shader != None:
if not shader.isValid():
shader.setSource(VertexShader, FragmentShader, 1)
shader.setSampler('guideTexture', 0)
shader.setSampler('bgTexture', 1)
shader.setSampler('specularity', 2)
shader.setSampler('normalMap', 3)
shader.setUniformfv('skinColor1', getOuterScaleColor())
shader.setUniformfv('skinColor2', getBellyScaleColor())
shader.setUniformfv('eyeColor', getEyeColor())
Attachments
GLSLNormalMap.blend (784 KB)