这一篇跟上一篇差不多,只是改成了per-fragment lighting.
把对光的计算从vertex shader移到了fragment shader.
可以看到效果,在光移动到立方体顶点时,立方体面的顶点周围扇形比较亮,接近真实世界的效果。
因改动较小,只修改了shader source部分,所以只给出这部分的代码吧。
1 private String getVertexShader() 2 { 3 final String vertexShader = 4 "uniform mat4 u_MVPMatrix; \n" // A constant representing the combined model/view/projection matrix. 5 + "uniform mat4 u_MVMatrix; \n" // A constant representing the combined model/view matrix. 6 7 + "attribute vec4 a_Position; \n" // Per-vertex position information we will pass in. 8 + "attribute vec4 a_Color; \n" // Per-vertex color information we will pass in. 9 + "attribute vec3 a_Normal; \n" // Per-vertex normal information we will pass in. 10 11 + "varying vec3 v_Position; \n" // This will be passed into the fragment shader. 12 + "varying vec4 v_Color; \n" // This will be passed into the fragment shader. 13 + "varying vec3 v_Normal; \n" // This will be passed into the fragment shader. 14 15 + "void main() \n" // The entry point for our vertex shader. 16 + "{ \n" 17 // Transform the vertex into eye space. 18 + " v_Position = vec3(u_MVMatrix * a_Position); \n" 19 // Pass through the color. 20 + " v_Color = a_Color; \n" 21 // Transform the normal's orientation into eye space. 22 + " v_Normal = vec3(u_MVMatrix * vec4(a_Normal, 0.0)); \n" 23 // gl_Position is a special variable used to store the final position. 24 // Multiply the vertex by the matrix to get the final point in normalized screen coordinates. 25 + " gl_Position = u_MVPMatrix * a_Position; \n" 26 + "} \n"; 27 28 return vertexShader; 29 } 30 31 private String getFragmentShader() 32 { 33 final String fragmentShader = 34 "precision mediump float; \n" // Set the default precision to medium. We don't need as high of a 35 // precision in the fragment shader. 36 + "uniform vec3 u_LightPos; \n" // The position of the light in eye space. 37 38 + "varying vec3 v_Position; \n" // Interpolated position for this fragment. 39 + "varying vec4 v_Color; \n" // This is the color from the vertex shader interpolated across the 40 // triangle per fragment. 41 + "varying vec3 v_Normal; \n" // Interpolated normal for this fragment. 42 43 + "void main() \n" // The entry point for our fragment shader. 44 + "{ \n" 45 // Will be used for attenuation. 46 + " float distance = length(u_LightPos - v_Position); \n" 47 // Get a lighting direction vector from the light to the vertex. 48 + " vec3 lightVector = normalize(u_LightPos - v_Position); \n" 49 // Calculate the dot product of the light vector and vertex normal. If the normal and light vector are 50 // pointing in the same direction then it will get max illumination. 51 + " float diffuse = max(dot(v_Normal, lightVector), 0.1); \n" 52 // Add attenuation. 53 + " diffuse = diffuse * (1.0 / (1.0 + (0.25 * distance * distance))); \n" 54 // Multiply the color by the diffuse illumination level to get final output color. 55 + " gl_FragColor = v_Color * diffuse; \n" 56 + "} \n"; 57 58 return fragmentShader; 59 }
看看效果图: