tags:

views:

52

answers:

3

In a tutorial there was a diffuse value calculation of the type

float diffuse_value = max(dot(vertex_normal, vertex_light_position), 0.0);

..on the vertex shader.

That was supposed to be making per vertex lighting if later on the fragment shader..

gl_FragColor = gl_Color * diffuse_value;

Then when he moved the first line - appropriately (by outputting vertex_normal and vertex_light_position to fragment) - to the the fragment shader, it is supposed to be transforming the method to "per pixel shading".

How is that so? The first method appears to be doing the diffuse_value calculation every pixel anyway!

A: 

Well ... Code in a vertex shader is only evaluated per-vertex, with the input values of that vertex.

But when moved to a fragment shader, it is evaluated per-fragment, i.e. per pixel, with input values appropriately interpolated between vertices.

At least that is my understanding, I'm quite rusty with shader programming though.

unwind
A: 

If diffuse_value is computed in vertex shader, that means it is computed per vertex. Then, it is linearly interpolated on pixels of triangle and feed into pixel shader. (If you don't have per-pixel normals, that's all you can do.) Then, in pixel shader, polygon color (interpolated too) is modulated with that diffuse_value.

alxx
+2  A: 

diffuse_value in the first case is computed in the vertex shader. So it's only done per vertex.

After the vertex shader outputs values, the rasterizer takes those values (3 per triangle for each vector) and interpolates (in a perspective correct manner) them to provide different values for each pixel. As it happens, interpolating vectors like that (the normal and the light direction vectors) is not proper, because it loses their normalized property. Many implementations will actually normalize the vectors first thing in the fragment shader.

But it's worse to interpolate the dot of the 2 vectors (what the vector lighting effectively does). Say for example that your is N=+Z for all your vertices and L=norm(Z-X) on one and L=norm(Z+X) on another.

N.L = 1/sqrt(2) for both vertices. 

Interpolating that will give you a flat lighting, whereas actually interpolating N and L separately and renormalizing will give you the result you'd expect, a lighting that peaks exactly in the middle of the polygon. (because the interpolation of norm(Z-X) and norm(Z+X) will give exactly Z once normalized).

Bahbar
I can vouch for this answer. +1
Mads Elvheim
I wish it was more explained.
Lela Dax