0
\$\begingroup\$

This is the relevant section of my fragment shader

  varying vec3 normal;
  varying vec3 halfv;
  ...
    vec4 color = ambient * gl_LightSource[0].ambient;
    vec3 n = normalize(normal);

    float nl = max(dot(n, gl_LightSource[0].position.xyz), 0.0);

    if (nl > 0.0)
      color += (diffuse * gl_LightSource[0].diffuse * nl)
            +  (specular * gl_LightSource[0].specular * pow(max(dot(n, normalize(halfVector)), 0.0), shininess));

    gl_FragColor = color;

Where ambient, diffuse, specular, and shininess are all already defined. normal and halfv are defined in my vertex shader as

normal         = normalize(gl_NormalMatrix * gl_Normal);
halfv          = gl_LightSource[0].halfVector.xyz;

My light is directional, position is set to 100, 100, 100, 0. Ambient, diffuse, and specular values are 1, 1, 1, 1, .01, .01, .01, 1, and 0, 0, 0, 1, respectively. When might light vector is 100, 100, 100, 0, the entire mesh appears ambient lit. Any other position or magnitude causes the mesh to go dark, only showing the ambient component.

EDIT

This is the updated fragment shader:

  vec4 color = ambient * gl_LightSource[0].ambient;
  vec3 n = normalize(normal);
  vec3 ldir = normalize(gl_LightSource[0].position.xyz);
  vec3 halfv = normalize(normalize(cam) + ldir);

  float nl = max(dot(n, ldir), 0.0);

  if (nl > 0.0)
    color += (diffuse * gl_LightSource[0].diffuse * nl)
          +  (specular * gl_LightSource[0].specular * pow(max(dot(n, normalize(halfv)), 0.0), shininess));

  gl_FragColor = color;

and vertex shader:

normal         = normalize(gl_NormalMatrix * gl_Normal);
cam            = camera_pos.xyz - gl_Vertex.xyz;

I'm still seeing a dark, ambient tone only. I've also normalized my vector CPU side, now as 1, 1, 1, 1

\$\endgroup\$
1
\$\begingroup\$

The problem is here:

dot(n, gl_LightSource[0].position.xyz)

The light vector needs to be normalized. For a directional light, this can be precomputed as a unit vector pointing toward the light (note that directional lights don't have a position, only a direction). For point lights you would subtract the light's position and the vertex position in the vertex shader, then normalize that in the pixel shader.

Similarly, the half-angle vector for specular lighting needs to be normalized, and it needs to be computed per-pixel based on the camera vector and the light vector at that pixel. It can't be precomputed (except in the very special case of a parallel projection with a directional light).

\$\endgroup\$
  • \$\begingroup\$ How might I calculate the half vector? What specific operations need to be applied? How do I get the camera vector? I am normalizing halfv in the fragment shader \$\endgroup\$ – Outurnate Jul 4 '13 at 21:59
  • \$\begingroup\$ The camera vector can be calculated as camera_pos - vertex_pos in the vertex shader, then sent down to the fragment shader and normalized. Then the half vector is normalize(camera vector + light vector) where the camera and light vectors are both already normalized. \$\endgroup\$ – Nathan Reed Jul 4 '13 at 22:13
  • 1
    \$\begingroup\$ It's time for you to start from the simplest shader and add one feature at a time until you find the problem. Verify correct output at each step, etc... Right now it feels like you're just throwing spaghetti at the wall to see what sticks =) \$\endgroup\$ – Patrick Hughes Jul 5 '13 at 1:51
  • 2
    \$\begingroup\$ Well put. What would be a good starting point? Per-vertex directional shading? \$\endgroup\$ – Outurnate Jul 5 '13 at 2:20
  • 1
    \$\begingroup\$ @Hernán It can be done per-vertex, but it's an approximation. It may look ok on finely tessellated models, not so great on low-poly ones. \$\endgroup\$ – Nathan Reed Mar 15 '16 at 17:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.