# Lighting in WebGL

## 在3D空间中模拟现实灯光

1. 需要在每个顶点信息中加入面的朝向法线。这个法线是一个垂直于这个顶点所在平面的向量。
2. 需要明确方向光的传播方向，可以使用一个方向向量来定义。

## 建立顶点法线

```cubeVerticesNormalBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVerticesNormalBuffer);

var vertexNormals = [
// Front
0.0,  0.0,  1.0,
0.0,  0.0,  1.0,
0.0,  0.0,  1.0,
0.0,  0.0,  1.0,

// Back
0.0,  0.0, -1.0,
0.0,  0.0, -1.0,
0.0,  0.0, -1.0,
0.0,  0.0, -1.0,

// Top
0.0,  1.0,  0.0,
0.0,  1.0,  0.0,
0.0,  1.0,  0.0,
0.0,  1.0,  0.0,

// Bottom
0.0, -1.0,  0.0,
0.0, -1.0,  0.0,
0.0, -1.0,  0.0,
0.0, -1.0,  0.0,

// Right
1.0,  0.0,  0.0,
1.0,  0.0,  0.0,
1.0,  0.0,  0.0,
1.0,  0.0,  0.0,

// Left
-1.0,  0.0,  0.0,
-1.0,  0.0,  0.0,
-1.0,  0.0,  0.0,
-1.0,  0.0,  0.0
];

gl.bufferData(gl.ARRAY_BUFFER, new WebGLFloatArray(vertexNormals), gl.STATIC_DRAW);
```

（此处变量 vertexNormalAttribute 应该在initShader()函数中声明， 并赋值： vertexNormalAttribute = gl.getAttribLocation(shaderProgram, "aVertexNormal"）; gl.enableVertexAttribArray(vertexNormalAttribute);)

```gl.bindBuffer(gl.ARRAY_BUFFER, cubeVerticesNormalBuffer);
gl.vertexAttribPointer(vertexNormalAttribute, 3, gl.FLOAT, false, 0, 0);
```

```var normalMatrix = mvMatrix.inverse();
normalMatrix = normalMatrix.transpose();
var nUniform = gl.getUniformLocation(shaderProgram, "uNormalMatrix");
gl.uniformMatrix4fv(nUniform, false, new WebGLFloatArray(normalMatrix.flatten()));
```

## 更新着色器

### 顶点着色器

```<script id="shader-vs" type="x-shader/x-vertex">
attribute highp vec3 aVertexNormal;
attribute highp vec3 aVertexPosition;
attribute highp vec2 aTextureCoord;

uniform highp mat4 uNormalMatrix;
uniform highp mat4 uMVMatrix;
uniform highp mat4 uPMatrix;

varying highp vec2 vTextureCoord;
varying highp vec3 vLighting;

void main(void) {
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
vTextureCoord = aTextureCoord;

// Apply lighting effect

highp vec3 ambientLight = vec3(0.6, 0.6, 0.6);
highp vec3 directionalLightColor = vec3(0.5, 0.5, 0.75);
highp vec3 directionalVector = vec3(0.85, 0.8, 0.75);

highp vec4 transformedNormal = uNormalMatrix * vec4(aVertexNormal, 1.0);

highp float directional = max(dot(transformedNormal.xyz, directionalVector), 0.0);
vLighting = ambientLight + (directionalLightColor * directional);
}
</script>
```

### 片段着色器

```<script id="shader-fs" type="x-shader/x-fragment">
varying highp vec2 vTextureCoord;
varying highp vec3 vLighting;

uniform sampler2D uSampler;

void main(void) {
mediump vec4 texelColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));

gl_FragColor = vec4(texelColor.rgb * vLighting, texelColor.a);
}
</script>
```