PDA

View Full Version : Specular Reflections

12-17-2014, 09:45 AM
Still working out the kinks in my lighting system. I have ambient, direct, and point lights all working properly. But the correct specular reflection calculation still eludes me. See image:

Direction Light pointing (-1,-1, 0) then normalized. Look almost parallel to that. Directional light is illuminating the proper wall faces but the specular component is acting super weird. I never can make heads or tails of the equation from all the tuts online. Helps?

1558

vec3 calcDirectLight(float intensity, vec3 color, vec3 direction, vec3 normal)
{
//. Initialize
vec3 diffuseColor = vec3(0.0f);
vec3 specularColor = vec3(0.0f);

//. Calculate Specular Reflection
//vec3 cameraPosition = (projection * vec4(eyePosition, 1.0f)).xyz;

vec3 directionToEye = normalize(eyePosition - vPosition);
vec3 reflection = normalize(reflect(direction, normal));

//. Diffuse/Specular Factors
float diffuseFactor = max(0.0f, dot(normal, -direction));
float specularFactor = max(0.0f, dot(directionToEye, reflection));

//. Calculate Specular Lighting
specularFactor = pow(specularFactor, specularPower);

//. Save Diffuse & Specular
diffuseColor = color * intensity * diffuseFactor;
specularColor = color * specularIntensity * specularFactor;

return diffuseColor + specularColor;
}

Like should I be using the transformed camera position or the original position? I know I got my reflect vector right I believe. But what bout the directions for the dot product? Something big is wrong?

DragonForce99
12-21-2014, 09:20 AM
try to add uniform camera position varible and pass it to glsl

GClements
12-21-2014, 12:27 PM
Directional light is illuminating the proper wall faces but the specular component is acting super weird. I never can make heads or tails of the equation from all the tuts online..
The specular component is a model of an imperfect mirror.

The specular component is at its peak when the vector from the surface to the light is the reflection of the vector from the surface to the observer. IOW, when the vector half-way between the two has the same direction to the surface normal. Assuming that all vectors are normalised, this can be formulated as either

dot(normalize(light_vector + eye_vector), normal)

or

dot(reflect(-light_vector,normal), eye_vector)

or

dot(reflect(-eye_vector,normal), light_vector)

Note that light_vector points from the surface to the light, so for a directional light it's the negation of the light direction.

The result of the dot product is then raised to an exponent which determines the shininess. A larger exponent causes the intensity to fall off more quickly, resulting in "harder" reflections, i.e. a more perfect mirror.

Like should I be using the transformed camera position or the original position? I know I got my reflect vector right I believe. But what bout the directions for the dot product? Something big is wrong?
The vectors (light direction, eye direction, surface normal) must all be in the same coordinate system, which should be affine (i.e. they will typically be transformed by the model-view matrix but not the projection matrix).

This is why legacy OpenGL has separate model-view and projection matrices, and why most non-trivial shader programs do likewise. Lighting calculations don't work correctly in a projective space.

If individual objects have their own transformations, then their normals (and vertex positions, from which the eye direction is calculated) will need to be transformed according to the object transformation, but the light position or direction would normally stored in "world" space or eye space (in legacy OpenGL, glLightfv(GL_POSITION) takes a position in object space, transforms it via the current model-view matrix, and stores the resulting eye-space position).

Also, if the model-view matrix contains non-uniform scaling or shear, normals must be transformed by the inverse of the transpose of the model-view matrix (or rather, the top-left 3x3 submatrix), so that they remain normal to the surface. If the model-view matrix is orthonormal (consists only of rotations and translations), the inverse and the transpose are identical, so the inverse-transpose is equal to the original matrix.