I’m seeing some very strange artifacts in my per-fragment lighting.
This Youtube shows the issue; watch in 480p to get the best view of the problem. You can see the edges of the triangles that make up the sphere, but only certain ones. And only when the light is at certain angles relative to the camera.
Specifically, notice how the lines appear as the light rotates around the object. Rotating the camera also changes when and how the dark lines appear.
The problem definitely seems to be coming from the vertex normals. Here are some images of me rendering the normals directly, from three different angles:
<div class=“ubbcode-block”><div class=“ubbcode-header”>Click to reveal… <input type=“button” class=“form-button” value=“Show me!” onclick=“toggle_spoiler(this, ‘Yikes, my eyes!’, ‘Show me!’)” />]<div style=“display: none;”>
Now you might thing that these are the camera-space normals; they are not. I’m rendering the object-space normals, taken directly from the vertex attributes and interpolated across the surface. There should be no change one way or the other from changing the viewing angle.
Here are my shaders. The shaders all have some extraneous defines, as they were adapted and stripped down from shaders that were doing other computations.
<div class=“ubbcode-block”><div class=“ubbcode-header”>Click to reveal… <input type=“button” class=“form-button” value=“Show me!” onclick=“toggle_spoiler(this, ‘Yikes, my eyes!’, ‘Show me!’)” />]<div style=“display: none;”>
Vertex shader for both:
#version 330
layout(location = 0) in vec3 position;
layout(location = 1) in vec4 inDiffuseColor;
layout(location = 2) in vec3 normal;
out vec4 diffuseColor;
out vec3 vertexNormal;
out vec3 modelSpaceNormal;
out vec3 cameraSpacePosition;
uniform mat4 cameraToClipMatrix;
uniform mat4 modelToCameraMatrix;
uniform mat3 normalModelToCameraMatrix;
void main()
{
vec4 tempCamPosition = (modelToCameraMatrix * vec4(position, 1.0));
gl_Position = cameraToClipMatrix * tempCamPosition;
vertexNormal = normalize(normalModelToCameraMatrix * normal);
modelSpaceNormal = normalize(normal);
diffuseColor = inDiffuseColor;
cameraSpacePosition = vec3(tempCamPosition);
}
Fragment shader showing dot(N, L):
#version 330
in vec4 diffuseColor;
in vec3 vertexNormal;
in vec3 modelSpaceNormal;
in vec3 cameraSpacePosition;
out vec4 outputColor;
uniform vec3 modelSpaceLightPos;
uniform vec4 lightIntensity;
uniform vec4 ambientIntensity;
uniform vec3 cameraSpaceLightPos;
uniform float lightAttenuation;
const vec4 specularColor = vec4(0.25, 0.25, 0.25, 1.0);
uniform float shininessFactor;
void main()
{
vec3 lightDir = normalize(cameraSpaceLightPos - cameraSpacePosition);
vec3 surfaceNormal = normalize(vertexNormal);
outputColor = vec4(dot(surfaceNormal, lightDir));
}
Fragment shader showing the normals:
#version 330
in vec4 diffuseColor;
in vec3 vertexNormal;
in vec3 modelSpaceNormal;
in vec3 cameraSpacePosition;
out vec4 outputColor;
uniform vec3 modelSpaceLightPos;
uniform vec4 lightIntensity;
uniform vec4 ambientIntensity;
uniform vec3 cameraSpaceLightPos;
uniform float lightAttenuation;
const vec4 specularColor = vec4(0.25, 0.25, 0.25, 1.0);
uniform float shininessFactor;
void main()
{
outputColor = vec4(normalize(modelSpaceNormal), 1.0);
}
[/QUOTE]</div>
If you want to run the code yourself, you can grab this zip file from my tutorials (it’s larger than it looks). Run Tutorial 12, and you’ll see the problem. You can use the mouse to control the camera, ‘b’ will stop/start the light rotation, and ‘h’ will switch between viewing the model-space normals and the NdotL.
To run them, you’ll have to build FreeGLUT, glloader, and TinyXML, which come with the distribution. Instructions for doing so can be found here.
If you’ve got any ideas about what’s going on, I’d love to hear them.
[edit]
BTW, it’s not hardware-specific. I see this problem on my Radeon HD 3300, as well as my GeForce GT-250.