# CSharpGL(13)用GLSL实现点光源(point light)和平行光源(directional light)的漫反射(diffuse reflection)

CSharpGL(13)用GLSL实现点光源(point light)和平行光源(directional light)的漫反射(diffuse reflection)

# 点光源(point light)

 1 #version 150 core
2
3 in vec3 in_Position;
4 in vec3 in_Normal;
5 out vec4 pass_Position;
6 out vec4 pass_Color;
7 uniform mat4 modelMatrix;
8 uniform mat4 viewMatrix;
9 uniform mat4 projectionMatrix;
10 uniform vec3 lightPosition;
11 uniform vec3 lightColor;
12 uniform vec3 globalAmbient;
13 uniform float Kd;
14
15 void main(void)
16 {
17     gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(in_Position, 1.0f);
18     vec3 worldPos = (viewMatrix * modelMatrix * vec4(in_Position, 1.0f)).xyz;
19     vec3 N = (transpose(inverse(viewMatrix * modelMatrix)) * vec4(in_Normal, 1.0f)).xyz;
20     N = normalize(N);
21     // light's direction
22     vec3 L = (viewMatrix * vec4(lightPosition, 1.0f)).xyz - worldPos;// point light
23     L = normalize(L);
24     // diffuse color from directional light
25     vec3 diffuseColor = Kd * lightColor * max(dot(N, L), 0);
26     // ambient color
27     vec3 ambientColor = Kd * globalAmbient;
28     pass_Color.xyz = diffuseColor + ambientColor;
29     pass_Color.w = 1;
30 }

## 重要知识点

### 法线(normal)

Normals are funny.  They're vec3's, since you don't want perspective on normals.   And they don't actually scale quite right--a 45 degree surface with a 45 degree normal, scaled by glScalef(1,0.1,1), drops the surface down to near 0 degrees, but actually tilts the normal *up*, in the opposite direction from the surface, to near 90 degrees.

Mathematically, if between two points a and b on the surface, dot(n,b-a)==0, then after applying a matrix M to the points, you want the normal to still be perpendicular.  The question is, what matrix N do you have to apply to the normal to make this happen?  In other words, find N such that
dot( N * n , M * a - M * b) == 0

We can solve this by noting that dot product can be expresed as matrix multiplication--dot(x,y) = transpose(x) * y, where we treat an ordinary column-vector as a little matrix, and flip it horizontally.  So
transpose(N * n) * (M*a - M*b) == 0         (as above, but write using transpose and matrix multiplication)
transpose(N * n) * M * (a-b) == 0              (collect both copies of M)
transpose(n) * transpose(N) * M * (a-b) == 0    (transpose-of-product is product-of-transposes in opposite order)

OK.  This is really similar to our assumption that the original normal was perpendicular to the surface--that dot(n,b-a) == transpose(n) * (a-b) == 0.  In fact, the only difference is the new matrices wedged in the middle.  If we pick N to make the term in the middle the identity, then our new normal will be perpendicular to the surface too:
transpose(N) * M == I   (the identity matrix)
This is the definition for matrix inverses, so the "normal matrix" N = transpose(inverse(M)).

If you look up the GLSL definition for "gl_NormalMatrix", it's defined as "the transpose of the inverse of the gl_ModelViewMatrix".  Now you know why!
normal

### 光源的位置

1 #version 150 core
2
3 in vec4 pass_Color;
4 out vec4 out_Color;
5
6 void main(void)
7 {
8     out_Color = pass_Color;
9 }

# 平行光源(directional light)

 1 #version 150 core
2
3 in vec3 in_Position;
4 in vec3 in_Normal;
5 out vec4 pass_Position;
6 out vec4 pass_Color;
7 uniform mat4 modelMatrix;
8 uniform mat4 viewMatrix;
9 uniform mat4 projectionMatrix;
10 uniform vec3 lightPosition;
11 uniform vec3 lightColor;
12 uniform vec3 globalAmbient;
13 uniform float Kd;
14
15 void main(void)
16 {
17     gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(in_Position, 1.0f);
18     vec3 worldPos = (viewMatrix * modelMatrix * vec4(in_Position, 1.0f)).xyz;
19     vec3 N = (transpose(inverse(viewMatrix * modelMatrix)) * vec4(in_Normal, 1.0f)).xyz;
20     N = normalize(N);
21     // light's direction
22     vec3 L = (transpose(inverse(viewMatrix)) * vec4(lightPosition, 1.0f)).xyz;// directional light
23     L = normalize(L);
24     // diffuse color from directional light
25     vec3 diffuseColor = Kd * lightColor * max(dot(N, L), 0);
26     // ambient color
27     vec3 ambientColor = Kd * globalAmbient;
28     pass_Color.xyz = diffuseColor + ambientColor;
29     pass_Color.w = 1;
30 }

# 总结

posted @ 2016-02-12 15:18 BIT祝威 阅读(...) 评论(...) 编辑 收藏