Illumination and Shading with GLSL/WebGL
Illumination with Shaders! Remember the local illumination model (Phong illumination) Illumination = ambient + diffuse + specular = Ka x Ia + Kd x Id x (N.L) + Ks x Is x (R.V) n Ambient Diffuse Specular
What you need to do in your WebGL code! Define the light(s ) position and its ambient, diffuse, and specular intensities (Ia, Id, Is in R,G,B)! Define the vertex normals (create a VBO)! Define object material properties (ambient, diffuse, and specular reflectance coefficients Ka, Kd, Ks)! Compute the normal transformation matrix (inverse-transpose of modelview matrix)
Uniforms or Attributes?! The light properties are definitely defined as uniforms (do not change per vertex)! The normals are attributes each vertex has its own normal! The material properties can be attributes or uniforms depends on whether you want to change them (Ka, Kd, Ks) per vertex
Define and Pass Lights var light_ambient = [0,0,0,1]; var light_diffuse= [.8,.8,.8,1]; var light_specular = [1,1,1,1]; var light_pos = [10,10,0,1]; Variables defined in your shaders var l1 = gl.getuniformlocation(programobject, "light_ambient"); var l2 = gl.getuniformlocation(programobject, "light_diffuse"); var l3 = gl.getuniformlocation(programobject, "light_specular"); var lp = gl.getuniformlocation(programobject, "light_pos"); gl.uniform4f(l1, light_ambient[0], light_ambient[1], light_ambient[2], 1.0); gl.uniform4f(l2, light_diffuse[0], light_diffuse[1], light_diffuse[2], 1.0); gl.uniform4f(l3, light_specular[0], light_specular[1], light_specular[2],1.0); gl.uniform4f(lp, light_pos[0], light_pos[1], light_pos[2], light_pos[3]);
Define and Pass Materials Here I am setting materials as uniforms (not per vertex) var mat_ambient = [0, 0, 0, 1]; var mat_diffuse= [1, 1, 0, 1]; var mat_specular = [.9,.9,.9,1]; Var mat_shine = [50]; Variables defined in your shaders var d1 = gl.getuniformlocation(programobject, "ambient_coef"); var d2 = gl.getuniformlocation(programobject, "diffuse_coef"); var d3 = gl.getuniformlocation(programobject, "specular_coef"); var d4 = gl.getuniformlocation(programobject, "mat_shininess"); gl.uniform4f(d1, mat_ambient[0], mat_ambient[1], mat_ambient[2], 1.0); gl.uniform4f(d2, mat_diffuse[0], mat_diffuse[1], mat_diffuse[2], 1.0); gl.uniform4f(d3, mat_specular[0], mat_specular[1], mat_specular[2],1.0); gl.uniform1f(d4, mat_shine[0]);
Define a normal for each vertex and pass with the VBO /// Define the Vertex attributes location[4]; normal[4]; color[4]; v2 Create VBOs for normals as well n v1 The vertex normal n = v 1 cross product v2 Note:make the fourth component of the normal Normal[3] = 0.0
Where do I calculate lighting! You need to calculate lighting in eye space! Lighting cannot be calculated in clip space because the shape of the object, therefore all the angles, are distorted! This means that you need to pass the modelview matrix to the shader as uniforms! Why? Modelview matrix transforms your vertices from local space to eye space
Normals need to be transformed too! Like you vertex positions need to be transformed to eye space, the normals need to be transformed too! The normal [u,v,w] will have the form [u,v,w,0] in the homogeneous space! The matrix to transform the normal is the inverse transpose of the modelview matrix normal matrix = (modelview -1 ) T normal_matrix = mat4.inverse(modelview); normal_matrix = mat4.transpose(normal_matrix);
Pass the matrices var m1 = gl.getuniformlocation(programobject, ummatrix"); // model matrix var m2 = gl.getuniformlocation(programobject, uvmatrix"); // view matrix var m3 = gl.getuniformlocation(programobject, upmatrix"); // projection matrix var m4 = gl.getuniformlocation(programobject, unmatrix); // normal matrix gl.uniformmatrix4fv(m1, false, mmatrix); gl.uniformmatrix4fv(m2, false, vmatrix); gl.uniformmatrix4fv(m3, false, pmatrix); gl.uniformmatrix4fv(m4, false, nmatrix); Variables defined in your javascript
Vertex Shader precision mediump float; attribute vec3 avertexposition; attribute vec3 avertexnormal; attribute vec4 avertexcolor; uniform mat4 ummatrix; uniform mat4 uvmatrix; uniform mat4 upmatrix; uniform mat4 unmatrix; uniform vec4 ambient_coef; uniform vec4 diffuse_coef; uniform vec4 specular_coef; uniform float mat_shininess; uniform vec4 light_pos; uniform vec4 light_ambient; uniform vec4 light_diffuse; uniform vec4 light_specular; varying vec4 eye_pos; //vertex position in eye space varying vec3 v_normal; // vertex normal main(){ // will discuss the implementation in class }
Fragment Shader precision mediump float; uniform mat4 ummatrix; uniform mat4 uvmatrix; uniform mat4 upmatrix; uniform mat4 unmatrix; uniform vec4 ambient_coef; uniform vec4 diffuse_coef; uniform vec4 specular_coef; uniform float mat_shininess; uniform vec4 light_pos; uniform vec4 light_ambient; uniform vec4 light_diffuse; uniform vec4 light_specular; varying vec4 eye_pos; //vertex position in eye space varying vec3 v_normal; // vertex normal main(){ // will discuss the implementation in class }