It's meant to look like this:

but on some graphics cards, our planet shader didn't work properly and produced the top image instead. The good news is, this is fixed in tonight's build. The bad news is that the same problem may be affecting other shaders, so I thought I'd explain what the problem was and how to get around it. If you're not a shader programmer you can ignore the rest of this post.

OpenGL defines a few built in uniforms that you can use in shaders, such as gl_ModelViewMatrix and gl_ProjectionMatrix. Unfortunately, use of these matrices is deprecated, which leads to some graphics cards taking shortcuts. The problem with the planet shader was that some cards don't bother calculating the uniform gl_NormalMatrix, which in our case affects the normal mapping, erasing the bumps (the problem originally caused the razor sharp day-night terminator, if you remember that. But we tweaked it to affect the normal mapping instead.) If your shader uses this uniform it probably won't work on affected cards either.

The way round this (from tonight's build, of course) is to replace the built in gl_NormalMatrix uniform with the new ooliteNormalMatrix uniform. There are two simple steps to this. Firstly, declare the uniform at the top of your shader:

Code: Select all

`uniform mat3 ooliteNormalMatrix;`

Code: Select all

```
ooliteModelView
ooliteProjection
ooliteModelViewProjection
ooliteNormalMatrix
ooliteModelViewInverse
ooliteProjectionInverse
ooliteModelViewProjectionInverse
ooliteModelViewTranspose
ooliteProjectionTranspose
ooliteModelViewProjectionTranspose
ooliteModelViewInverseTranspose
ooliteProjectionInverseTranspose
ooliteModelViewProjectionInverseTranspose
```

As an example, here's the original planet vertex shader:

Code: Select all

```
// No vNormal, because normal is always 0,0,1 in tangent space.
varying vec3 vEyeVector;
varying vec2 vTexCoords;
varying vec3 vLight1Vector;
varying vec3 vCoords;
void main(void)
{
vCoords = gl_Vertex.xyz;
// Build tangent basis.
vec3 normal = normalize(gl_NormalMatrix * gl_Normal);
vec3 binormal = cross(normal, gl_NormalMatrix * vec3(0, 1, 0));
vec3 tangent = -cross(normal, binormal);
mat3 TBN = mat3(tangent, binormal, normal);
vec3 eyeVector = -vec3(gl_ModelViewMatrix * gl_Vertex);
vEyeVector = eyeVector * TBN;
vec3 light1Vector = gl_LightSource[1].position.xyz + eyeVector;
vLight1Vector = light1Vector * TBN;
vTexCoords = gl_MultiTexCoord0.st;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
```

Code: Select all

```
// No vNormal, because normal is always 0,0,1 in tangent space.
uniform mat3 ooliteNormalMatrix;
uniform mat4 ooliteModelView;
uniform mat4 ooliteModelViewProjection;
varying vec3 vEyeVector;
varying vec2 vTexCoords;
varying vec3 vLight1Vector;
varying vec3 vCoords;
void main(void)
{
vCoords = gl_Vertex.xyz;
// Build tangent basis.
vec3 normal = normalize(ooliteNormalMatrix * gl_Normal);
vec3 binormal = normalize(cross(normal, ooliteNormalMatrix * vec3(0, 1, 0))); // ignore the extra normalize() here - that's another fix
vec3 tangent = -cross(normal, binormal);
mat3 TBN = mat3(tangent, binormal, normal);
vec3 eyeVector = -vec3(ooliteModelView * gl_Vertex);
vEyeVector = eyeVector * TBN;
vec3 light1Vector = gl_LightSource[1].position.xyz + eyeVector;
vLight1Vector = light1Vector * TBN;
vTexCoords = gl_MultiTexCoord0.st;
gl_Position = ooliteModelViewProjection * gl_Vertex;
}
```