MENU
Specular Lighting
Specular lighting causes a bright spot of light to appear on a surface, making the surface looks shiny.
In the Phong Reflection Model, the intensity of the specular highlight is given by
where R is the mirror reflection of the light vector off the surface, and V is the viewpoint vector. As n increases, the size of the spot decreases.
The middle of the triangle 'lights up', as it reflects the light directly in front of it, making the material looks shiny.
RESETRUNFULL
RESETRUNFULL
<!DOCTYPE html><html>
<head>
<script src="/shared/webgl-library.js"></script>
<script id="vs" type="x-shader/x-vertex">
uniform mat4 u_perspectiveMatrix;
uniform mat4 u_modelMatrix;
uniform mat4 u_viewMatrix;
attribute vec4 a_Position;
attribute vec3 a_Normal;
varying vec4 v_Position;
varying vec3 v_Normal;
void main() {
mat4 modelViewMatrix = u_viewMatrix * u_modelMatrix;
v_Position = modelViewMatrix * a_Position;
gl_Position = u_perspectiveMatrix * v_Position;
v_Normal = normalize( mat3(modelViewMatrix) *
a_Normal);
}
</script>
<script id="fs" type="x-shader/x-fragment">
#ifdef GL_ES
precision mediump float;
#endif
uniform mat4 u_fViewMatrix;
uniform vec3 u_lightPosition;
varying vec4 v_Position;
varying vec3 v_Normal;
void main() {
vec3 normal = normalize(v_Normal);
vec3 lightPosition = vec3(u_fViewMatrix * vec4(u_lightPosition, 1) - v_Position);
vec3 lightDir = normalize(lightPosition);
float lightDist = length(lightPosition);
float specular = 0.0;
float d = max(dot(v_Normal, lightDir), 0.0);
if (d > 0.0) {
vec3 viewVec = vec3(0,0,1.0);
vec3 reflectVec = reflect(-lightDir, normal);
specular = pow(max(dot(reflectVec, viewVec), 0.0), 120.0);
}
gl_FragColor.rgb = vec3(0.1,0.1,0.1) + vec3(0.4, 0.4, 0.4) * d + specular;
gl_FragColor.a = 1.0;
}
</script>
<script>
var g_perspectiveMatrix = new Matrix4();
var g_modelMatrix = new Matrix4();
var g_viewMatrix = new Matrix4();
function main() {
var canvas = document.getElementById("myCanvas");
var gl = canvas.getContext("webgl");
initShaders(gl, "vs", "fs");
var perspectiveMatrixShaderLocation = gl.getUniformLocation(gl.program, 'u_perspectiveMatrix');
var modelMatrixShaderLocation = gl.getUniformLocation(gl.program, 'u_modelMatrix');
var viewMatrixShaderLocation = gl.getUniformLocation(gl.program, 'u_viewMatrix');
var lightPositionShaderLocation = gl.getUniformLocation(gl.program, 'u_lightPosition');
var f_viewMatrixShaderLocation = gl.getUniformLocation(gl.program, 'u_fViewMatrix');
gl.enable(gl.DEPTH_TEST);
gl.clearColor(0, 0, 0, 1);
drawCommon(gl, canvas,
perspectiveMatrixShaderLocation,
viewMatrixShaderLocation,
lightPositionShaderLocation,
f_viewMatrixShaderLocation);
drawCube(gl, canvas,
perspectiveMatrixShaderLocation,
modelMatrixShaderLocation,
lightPositionShaderLocation);
}
function drawCommon(gl, canvas,
perspectiveMatrixShaderLocation,
viewMatrixShaderLocation,
lightPositionShaderLocation,
f_viewMatrixShaderLocation) {
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
g_perspectiveMatrix.perspective(30, canvas.width/canvas.height, 1, 10000);
g_viewMatrix.lookAt(0, 3, 10,
0, 0, 0,
0, 1, 0);
gl.uniformMatrix4fv(perspectiveMatrixShaderLocation, false, g_perspectiveMatrix.entries);
gl.uniformMatrix4fv(viewMatrixShaderLocation, false, g_viewMatrix.entries);
gl.uniformMatrix4fv(f_viewMatrixShaderLocation, false, g_viewMatrix.entries);
var lightPosition = new Float32Array([0, 0, 2]);
gl.uniform3fv(lightPositionShaderLocation, lightPosition);
}
function drawCube(gl, canvas,
perspectiveMatrixShaderLocation,
modelMatrixShaderLocation,
lightPositionShaderLocation) {
var vertices = new Float32Array([-1.5,1.5,0.0,
1.5,1.5,0.0,
0.0,-1.5,0.0]);
var normals = new Float32Array([0.0,0.0,1.0,
0.0,0.0,1.0,
0.0,0.0,1.0]);
initArrayBuffer(gl,'a_Position',vertices,3);
initArrayBuffer(gl,'a_Normal',normals,3);
gl.uniformMatrix4fv(modelMatrixShaderLocation, false, g_modelMatrix.entries);
gl.drawArrays(gl.TRIANGLES,0,3);
}
</script>
</head>
<body onload="main()">
<canvas id="myCanvas" width="500" height="500"></canvas>
</body>
</html>