CS184 Section 4
Phong Illumination Model and GLSL
Brandon Wang
February 14, 2012
Material adapted from Fu-Chung Huang, Carlo Sequin, Niels Joubert.
Brandon Wang
February 14, 2012
Material adapted from Fu-Chung Huang, Carlo Sequin, Niels Joubert.
What is it?
How we determine the color of what we see
i.e. Given our representations of geometry and lights, what color is at a specific pixel?
Does not depend on direction of light, or direction to viewer!
Ambient Term
Diffuse Term
Specular Term
The vertex shader operates on vertices. You typically do transformations, texture coordinates, and per-vertex lighting on it.
The fragment shader operates on fragments, or visible pixels. The values you receive are interpolated from the vertex shader, and you typically add effects, compute per-fragment lighting, and output the actual pixel values.
The vertex shader typically comes before the fragment shader, and are two separate programs.
Like a class or tuple.
Access it using:
vec4 color; color.rgb = vec3(1.0 , 1.0 , 0.0 ); color.a = 0.5 color = vec4(1.0 , 1.0 , 0.0 , 0.5); color.xy = vec2(1.0 , 1.0); color.zw =vec2(0.0 , 0.5);
Qualifiers (in addition to variable type) specify the special attributes that vertex and fragment shaders have
# version 120 varying vec4 color ; varying vec3 mynormal ; varying vec4 myvertex ; void main() { gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex ; color = gl_Color ; mynormal = gl_Normal ; myvertex = gl_Vertex ; }
# version 120 varying vec4 color ; varying vec3 mynormal ; varying vec4 myvertex ; uniform int islight ; // are we lighting. uniform vec4 light0posn ; uniform vec4 light0color ; uniform vec4 light1posn ; uniform vec4 light1color ; uniform vec4 ambient ; uniform vec4 diffuse ; uniform vec4 specular ; uniform float shininess ; vec4 ComputeLight (const in vec3 direction, const in vec4 lightcolor, const in vec3 normal, const in vec3 halfvec, const in vec4 mydiffuse, const in vec4 myspecular, const in float myshininess) { float nDotL = dot(normal, direction) ; vec4 lambert = mydiffuse * lightcolor * max (nDotL, 0.0) ; float nDotH = dot(normal, halfvec) ; vec4 phong = myspecular * lightcolor * pow (max(nDotH, 0.0), myshininess) ; vec4 retval = lambert + phong ; return retval ; }
void main (void) { if (islight == 0) gl_FragColor = color ; else { // They eye is always at (0,0,0) looking down -z axis // Also compute current fragment position and direction to eye const vec3 eyepos = vec3(0,0,0) ; vec4 _mypos = gl_ModelViewMatrix * myvertex ; vec3 mypos = _mypos.xyz / _mypos.w ; // Dehomogenize current location vec3 eyedirn = normalize(eyepos - mypos) ; // Compute normal, needed for shading. // Simpler is vec3 normal = normalize(gl_NormalMatrix * mynormal) ; vec3 _normal = (gl_ModelViewMatrixInverseTranspose*vec4(mynormal,0.0)).xyz ; vec3 normal = normalize(_normal) ; // Light 0, point vec3 position0 = light0posn.xyz / light0posn.w ; vec3 direction0 = normalize (position0 - mypos) ; // no attenuation vec3 half0 = normalize (direction0 + eyedirn) ; vec4 col0 = ComputeLight(direction0, light0color, normal, half0, diffuse, specular, shininess) ; // Light 1, point vec3 position1 = light1posn.xyz / light1posn.w ; vec3 direction1 = normalize (position1 - mypos) ; // no attenuation vec3 half1 = normalize (direction1 + eyedirn) ; vec4 col1 = ComputeLight(direction1, light1color, normal, half1, diffuse, specular, shininess) ; gl_FragColor = ambient + col0 + col1 ; } }
GLSL is highly hardware dependent. Some versions of GLSL work on some GPUs, and not on others. Usually, you will face issues with control flow statements (if, else, for, while, etc). For HW2, you can try to use a for loop, but your mileage may vary.
It is very difficult to debug GLSL programs! You don't have any print statements, and the debuggers for GLSL are usually not that great. Something simple may be to set a pixel to be red if it is incorrect, but that's not that great of a debug tool.
Bump Mapping
Environment Mapping
Shadow Mapping
const GLfloat wd = 0.1 ; const GLfloat ht = 0.5 ; const GLfloat _cubecol[4][3] = { {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}, {1.0, 1.0, 0.0} } ; const GLfloat cubeverts[8][3] = { {-wd, -wd, 0.0}, {-wd, wd, 0.0}, {wd, wd, 0.0}, {wd, -wd, 0.0}, {-wd, -wd, ht}, {wd, -wd, ht}, {wd, wd, ht}, {-wd, wd, ht} } ; GLfloat cubecol[8][3] ; const GLubyte cubeinds[6][4] = { {0, 1, 2, 3}, // BOTTOM {4, 5, 6, 7}, // TOP {0, 4, 7, 1}, // LEFT {0, 3, 5, 4}, // FRONT {3, 2, 6, 5}, // RIGHT {1, 7, 6, 2} // BACK } ;
// Simple function to set the color separately. Takes out colors void initobjectnocol(GLuint object, GLfloat * vert, GLint sizevert, GLubyte * inds, GLint sizeind, GLenum type) { int offset = object * numperobj ; glBindBuffer(GL_ARRAY_BUFFER, buffers[Vertices+offset]) ; glBufferData(GL_ARRAY_BUFFER, sizevert, vert,GL_STATIC_DRAW); glVertexPointer(3, GL_FLOAT, 0, BUFFER_OFFSET(0)) ; glEnableClientState(GL_VERTEX_ARRAY) ; glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,buffers[Elements+offset]) ; glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeind, inds,GL_STATIC_DRAW); PrimType[object] = type ; NumElems[object] = sizeind ; } //in init initcolorscube() ; initobjectnocol(CUBE, (GLfloat *) cubeverts, sizeof(cubeverts), (GLubyte *) cubeinds, sizeof (cubeinds), GL_QUADS) ;