CS184 Section 4
Phong Illumination Model and GLSL

Brandon Wang
September 19, 2012
Material adapted from Fu-Chung Huang, Carlo Sequin, Niels Joubert.

Logistics

Today

Phong Illumination Model

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?

  • Ambient
  • Diffuse
  • Specular

Ambient term

\mathbf{I}_{A} = \mathbf{C}_{mat} \cdot \mathbf{L}_{amb}

\mathbf{C}_{mat}
Color of the material
\mathbf{L}_{amb}
Ambient light color

Does not depend on direction of light, or direction to viewer!

Diffuse term

\mathbf{I}_{D} = \mathbf{C}_{diff} \cdot \mathbf{L}_{col} \cdot max\left(\mathbf{N} \cdot \mathbf{L}_{dir}, 0\right)

\mathbf{C}_{diff}
Diffuse color of the material
\mathbf{L}_{col}
Light color
\mathbf{N}
Surface normal
\mathbf{L}_{dir}
Light direction

Specular Term

\mathbf{I}_{S} = \mathbf{C}_{spec} \cdot \mathbf{L}_{col} \cdot max\left(\mathbf{N} \cdot \mathbf{H}, 0\right)^{k_{sp}}

\mathbf{C}_{spec}
Specular color of the material
\mathbf{L}_{col}
Light color
\mathbf{N}
Surface normal
\mathbf{H}
Half angle
k_{sp}
Shininess

Phong Illumination Model

\mathbf{\rho} = \mathbf{C}_{a}\mathbf{L}_{a} + \sum_{Lights} \left( \mathbf{C}_{d}\mathbf{L}_{col}\,\mathrm{max}(\hat{\mathbf{L}_{dir}} \cdot \hat{\mathbf{n}}, 0) + \mathbf{C}_s\mathbf{L}_{col}\,\mathrm{max}(\hat{\mathbf{N}} \cdot \hat{\mathbf{r}}, 0)^{k_{sp}} \right) \\

Ambient Term

\mathbf{\rho} = \underline{\mathbf{C}_{a}\mathbf{L}_{a}} + \sum_{Lights} \left( \mathbf{C}_{d}\mathbf{L}_{col}\,\mathrm{max}(\hat{\mathbf{L}_{dir}} \cdot \hat{\mathbf{n}}, 0) + \mathbf{C}_s\mathbf{L}_{col}\,\mathrm{max}(\hat{\mathbf{N}} \cdot \hat{\mathbf{r}}, 0)^{k_{sp}} \right) \\

Diffuse Term

\mathbf{\rho} = \mathbf{C}_{a}\mathbf{L}_{a} + \sum_{Lights} \left( \underline{\mathbf{C}_{d}\mathbf{L}_{col}\,\mathrm{max}(\hat{\mathbf{L}_{dir}} \cdot \hat{\mathbf{n}}, 0)} + \mathbf{C}_s\mathbf{L}_{col}\,\mathrm{max}(\hat{\mathbf{N}} \cdot \hat{\mathbf{r}}, 0)^{k_{sp}} \right) \\

Specular Term

\mathbf{\rho} = \mathbf{C}_{a}\mathbf{L}_{a} + \sum_{Lights} \left( \mathbf{C}_{d}\mathbf{L}_{col}\,\mathrm{max}(\hat{\mathbf{L}_{dir}} \cdot \hat{\mathbf{n}}, 0) + \underline{\mathbf{C}_s\mathbf{L}_{col}\,\mathrm{max}(\hat{\mathbf{N}} \cdot \hat{\mathbf{r}}, 0)^{k_{sp}}} \right) \\

Questions

  1. How would the diffuse and specular term look like for a matte object? (Think chalk). What would some other objects be that have similar terms?
  2. How would the diffuse and specular term look like for a shiny plastic? (Think metal). What would some other objects be that have similar terms?
  3. What is flat shading?
  4. What is Gouraud shading?
  5. What is Phong shading?
  6. What is a point light?

GLSL

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.

GLSL

Was my phong illumination calculation done at vertex or fragment here?

Data Types

Vector

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);

Variable Qualifiers

Qualifiers (in addition to variable type) specify the special attributes that vertex and fragment shaders have

Vertex Shader (HW1/2)

# 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 ; 
}
  

Fragment Shader (HW2)


# version 120 
varying vec4 color ;
varying vec3 mynormal ; 
varying vec4 myvertex ; 

const int numLights = 10 ; 
uniform bool enablelighting ; // are we lighting at all (global).
uniform vec4 lightposn[numLights] ; // positions of lights 
uniform vec4 lightcolor[numLights] ; // colors of lights
uniform int numused ;               // number of lights used
uniform vec4 ambient ; 
uniform vec4 diffuse ; 
uniform vec4 specular ; 
uniform vec4 emission ; 
uniform float shininess ; 
void main (void)
{       
    if (enablelighting) {      
        vec4 finalcolor ; 
        //Color all pixels blue for now, remove this in your implementation
        finalcolor = vec4(0,0,1,1); 
        gl_FragColor = finalcolor ; 
        }
    else gl_FragColor = color ; 
}

  

Warning on a few things

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.

Demonstration of shader effects

Bump Mapping

Demonstration of shader effects

Environment Mapping

Demonstration of shader effects

Shadow Mapping

Modern OpenGL Clarification

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
} ; 

Modern OpenGL Clarification

// 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) ;