kfriddile

11-17-2010, 07:36 PM

I've run into another problem with my per-pixel spotlight shader. I've attached a video that demonstrates the issue pretty clearly. As you can see, the plane is made up of two large triangles. As I move the light over the plane, it distorts strangely. The light is always pointing straight down at the plane. The guy standing on the plane is fairly high-poly, and the the lit area on him looks like it might be correct, but maybe I just can't tell because he's so high poly? All values being passed to the shader have been verified in the debugger. I'm really pulling my hair out over this one because my shader code looks like every tutorial I've seen. Here's the video:

<object width="425" height="350"> <param name="movie" value="http://www.youtube.com/v/GjJeUh-X0HU"></param> <param name="wmode" value="transparent"></param> <embed src="http://www.youtube.com/v/GjJeUh-X0HU" type="application/x-shockwave-flash" wmode="transparent" width="425" height="350"> </embed></object>

You can't see the wireframe well in the video, but the split between the plane's triangles runs from the lower-left to the upper-right (you can see the lit area distort when moving across it)

light parameters:

"ambientColor" : [0,0,0,255],

"diffuseColor" : [255,255,255,255],

"specularColor" : [255,255,255,255],

"coneAngle" : 15, // degrees

"rateOfDecay" : 0,

"constantAttenuation" : 1,

"linearAttenuation" : 0,

"quadraticAttenuation" : 0

vertex shader:

#version 130

uniform mat4x4 projectionMatrix;

uniform mat4x4 modelViewMatrix;

uniform mat2x2 textureMatrix;

uniform vec4 globalAmbient;

uniform vec3 lightPosition; // in view space

uniform vec4 lightAmbient;

uniform vec4 lightDiffuse;

uniform vec4 materialAmbient;

uniform vec4 materialDiffuse;

in vec4 position;

in vec2 textureCoordinate;

in vec3 normal;

out vec2 vertexTextureCoordinate;

out vec3 vertexNormal;

out vec4 vertexGlobalAmbient;

out vec3 vertexLightDirection;

out float vertexLightDistance;

out vec4 vertexAmbientColor;

out vec4 vertexDiffuseColor;

void main()

{

vertexNormal = mat3x3(modelViewMatrix) * normal; // We assume no non-uniform scaling here

// Compute the light direction

gl_Position = modelViewMatrix * position;

vec3 lightVector = lightPosition - gl_Position.xyz;

vertexLightDirection = normalize( lightVector );

vertexLightDistance = length( lightVector );

// Compute ambient and diffuse colors

vertexGlobalAmbient = globalAmbient * materialAmbient;

vertexAmbientColor = materialAmbient * lightAmbient;

vertexDiffuseColor = materialDiffuse * lightDiffuse;

gl_Position = projectionMatrix * gl_Position;

vertexTextureCoordinate = textureMatrix * textureCoordinate;

}

fragment shader:

#version 130

uniform sampler2D texture;

uniform vec4 lightSpecular;

uniform float lightConstantAttenuation;

uniform float lightLinearAttenuation;

uniform float lightQuadraticAttenuation;

uniform vec3 lightDirection; // in view space

uniform vec3 lightHalfVector; // in view space

uniform float lightConeAngleCosine;

uniform uint lightRateOfDecay;

uniform vec4 materialSpecular;

uniform int materialShininess;

in vec2 vertexTextureCoordinate;

in vec3 vertexNormal;

in vec4 vertexGlobalAmbient;

in vec3 vertexLightDirection;

in float vertexLightDistance;

in vec4 vertexAmbientColor;

in vec4 vertexDiffuseColor;

out vec4 fragmentColor;

void main()

{

fragmentColor = vertexGlobalAmbient;

vec3 normal = normalize( vertexNormal );

float normalDotLightDirection = max( dot( normal, normalize(vertexLightDirection) ), 0 );

if( normalDotLightDirection > 0 )

{

float spotEffect = dot( normalize(lightDirection), normalize(-vertexLightDirection) );

if( spotEffect > lightConeAngleCosine )

{

spotEffect = pow( spotEffect, lightRateOfDecay );

float attenuation = spotEffect / ( lightConstantAttenuation +

lightLinearAttenuation * vertexLightDistance +

lightQuadraticAttenuation * vertexLightDistance * vertexLightDistance );

fragmentColor += attenuation * ( vertexDiffuseColor * normalDotLightDirection + vertexAmbientColor );

float normalDotHalfVector = max( dot(normal, lightHalfVector), 0 );

fragmentColor += attenuation * materialSpecular * lightSpecular * pow( normalDotHalfVector, materialShininess );

}

}

vec4 texel = texture2D( texture, vertexTextureCoordinate );

fragmentColor *= texel;

fragmentColor.a = texel.a;

}

<object width="425" height="350"> <param name="movie" value="http://www.youtube.com/v/GjJeUh-X0HU"></param> <param name="wmode" value="transparent"></param> <embed src="http://www.youtube.com/v/GjJeUh-X0HU" type="application/x-shockwave-flash" wmode="transparent" width="425" height="350"> </embed></object>

You can't see the wireframe well in the video, but the split between the plane's triangles runs from the lower-left to the upper-right (you can see the lit area distort when moving across it)

light parameters:

"ambientColor" : [0,0,0,255],

"diffuseColor" : [255,255,255,255],

"specularColor" : [255,255,255,255],

"coneAngle" : 15, // degrees

"rateOfDecay" : 0,

"constantAttenuation" : 1,

"linearAttenuation" : 0,

"quadraticAttenuation" : 0

vertex shader:

#version 130

uniform mat4x4 projectionMatrix;

uniform mat4x4 modelViewMatrix;

uniform mat2x2 textureMatrix;

uniform vec4 globalAmbient;

uniform vec3 lightPosition; // in view space

uniform vec4 lightAmbient;

uniform vec4 lightDiffuse;

uniform vec4 materialAmbient;

uniform vec4 materialDiffuse;

in vec4 position;

in vec2 textureCoordinate;

in vec3 normal;

out vec2 vertexTextureCoordinate;

out vec3 vertexNormal;

out vec4 vertexGlobalAmbient;

out vec3 vertexLightDirection;

out float vertexLightDistance;

out vec4 vertexAmbientColor;

out vec4 vertexDiffuseColor;

void main()

{

vertexNormal = mat3x3(modelViewMatrix) * normal; // We assume no non-uniform scaling here

// Compute the light direction

gl_Position = modelViewMatrix * position;

vec3 lightVector = lightPosition - gl_Position.xyz;

vertexLightDirection = normalize( lightVector );

vertexLightDistance = length( lightVector );

// Compute ambient and diffuse colors

vertexGlobalAmbient = globalAmbient * materialAmbient;

vertexAmbientColor = materialAmbient * lightAmbient;

vertexDiffuseColor = materialDiffuse * lightDiffuse;

gl_Position = projectionMatrix * gl_Position;

vertexTextureCoordinate = textureMatrix * textureCoordinate;

}

fragment shader:

#version 130

uniform sampler2D texture;

uniform vec4 lightSpecular;

uniform float lightConstantAttenuation;

uniform float lightLinearAttenuation;

uniform float lightQuadraticAttenuation;

uniform vec3 lightDirection; // in view space

uniform vec3 lightHalfVector; // in view space

uniform float lightConeAngleCosine;

uniform uint lightRateOfDecay;

uniform vec4 materialSpecular;

uniform int materialShininess;

in vec2 vertexTextureCoordinate;

in vec3 vertexNormal;

in vec4 vertexGlobalAmbient;

in vec3 vertexLightDirection;

in float vertexLightDistance;

in vec4 vertexAmbientColor;

in vec4 vertexDiffuseColor;

out vec4 fragmentColor;

void main()

{

fragmentColor = vertexGlobalAmbient;

vec3 normal = normalize( vertexNormal );

float normalDotLightDirection = max( dot( normal, normalize(vertexLightDirection) ), 0 );

if( normalDotLightDirection > 0 )

{

float spotEffect = dot( normalize(lightDirection), normalize(-vertexLightDirection) );

if( spotEffect > lightConeAngleCosine )

{

spotEffect = pow( spotEffect, lightRateOfDecay );

float attenuation = spotEffect / ( lightConstantAttenuation +

lightLinearAttenuation * vertexLightDistance +

lightQuadraticAttenuation * vertexLightDistance * vertexLightDistance );

fragmentColor += attenuation * ( vertexDiffuseColor * normalDotLightDirection + vertexAmbientColor );

float normalDotHalfVector = max( dot(normal, lightHalfVector), 0 );

fragmentColor += attenuation * materialSpecular * lightSpecular * pow( normalDotHalfVector, materialShininess );

}

}

vec4 texel = texture2D( texture, vertexTextureCoordinate );

fragmentColor *= texel;

fragmentColor.a = texel.a;

}