lecture note - image processing - |...

57
Render complex scenes Hanyang University

Upload: lamnga

Post on 30-Aug-2018

221 views

Category:

Documents


0 download

TRANSCRIPT

Render complex scenes

Hanyang University

How to render a complex 3D scene

• Typical rendering loop for a 3D environment1. Initialize modelview matrix (glIdentity)

2. Change viewpoint (gluLookat or glTranslate,glRotate)

3. Save the current modelview matrix (glPushMatrix)

4. Place stuff on the scene (glTranslate,glRotate)

5. Draw stuff

6. Restore the modelview matrix from matrix stack

(glPopMatrix)Repeat 3~6

Example

void RenderScene(void){ glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f, 1.0f, 1.0f, 1000.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0.0, 200.0, 200.0, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f); glViewport(0, 0, windowWidth, windowHeight); glEnable(GL_DEPTH_TEST); // Clear the window with current clearing color glClear(GL_COLOR_BUFFER_BIT |

GL_DEPTH_BUFFER_BIT);

// Draw objects in the scene DrawModels();

// Flush drawing commands glutSwapBuffers();

}

void DrawModels(void){ // Draw plane that the objects rest on glColor3f(0.0f, 0.0f, 0.90f); // Blue glNormal3f(0.0f, 1.0f, 0.0f); glBegin(GL_QUADS); glVertex3f(-100.0f, -25.0f, -100.0f); glVertex3f(-100.0f, -25.0f, 100.0f); glVertex3f(100.0f, -25.0f, 100.0f); glVertex3f(100.0f, -25.0f, -100.0f); glEnd();

// Draw red cube glColor3f(1.0f, 0.0f, 0.0f); glutSolidCube(48.0f);

// Draw green sphere glColor3f(0.0f, 1.0f, 0.0f); glPushMatrix(); glTranslatef(-60.0f, 0.0f, 0.0f); glutSolidSphere(25.0f, 50, 50); glPopMatrix();

// Draw yellow cone glColor3f(1.0f, 1.0f, 0.0f); glPushMatrix(); glRotatef(-90.0f, 1.0f, 0.0f, 0.0f); glTranslatef(60.0f, 0.0f, -24.0f); glutSolidCone(25.0f, 50.0f, 50, 50); glPopMatrix();

// Draw magenta torus glColor3f(1.0f, 0.0f, 1.0f); glPushMatrix(); glTranslatef(0.0f, 0.0f, 60.0f); glutSolidTorus(8.0f, 16.0f, 50, 50); glPopMatrix();

// Draw cyan octahedron glColor3f(0.0f, 1.0f, 1.0f); glPushMatrix(); glTranslatef(0.0f, 0.0f, -60.0f); glScalef(25.0f, 25.0f, 25.0f); glutSolidOctahedron(); glPopMatrix();}

Example (cont’d)#include <gl/glut.h>

int windowWidth = 600;int windowHeight = 600;

void DrawModels(void);void RenderScene(void);void ChangeSize(int w, int h);

int main(int argc, char* argv[]){

glutInit(&argc, argv);

glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);glutInitWindowSize(windowWidth,windowHeight);glutCreateWindow("Example");glutReshapeFunc(ChangeSize);glutDisplayFunc(RenderScene);glutMainLoop();return 0;

}

void ChangeSize(int w, int h){

windowWidth = w;windowHeight = h;

}

Faster Geometry Throughput

Rendering methods in OpenGL

• Immediate mode

• Display List

• Vertex buffer object

Immediate mode

• glBegin() ~ glEnd()– It requires many thousands of very small, potentially

expensive operations to submit a batch of geometry.• Primitive batches are assembled by using individual

glVertex/glNormal/glTexCoord calls.

– That’s a good bit of work for the CPU to perform to draw a single triangle. But, the graphics hardware sitting idle waiting on the CPU to assemble and submit geometry batches in case of drawing a complex 3D scene.

Example#include <math.h>#include <time.h>#include <stdlib.h>#include <gl/glut.h> #define PI 3.141592

typedef struct _Vector3D{

float x;float y;float z;

} Vector3D;

static GLfloat angle, velocity = 5;static Vector3D pos = {0.0, -20.0, 0.0};void DrawCube(CubeData *pData);void ChangeSize(GLsizei width, GLsizei height){

GLfloat fAspect = (GLfloat)width/(GLfloat)height;GLfloat nRange = height/4.0;if(height == 0)height = 1;

glViewport(0, 0, width, height);

glMatrixMode(GL_PROJECTION);glLoadIdentity();

gluPerspective(45.0f, fAspect, 1.0, 4000.0);

glMatrixMode(GL_MODELVIEW);glLoadIdentity();

}

void SpecialKeys(int key, int x, int y){

if(key == GLUT_KEY_UP){

pos.x -= (velocity*sin(angle*PI/180.0));pos.z += (velocity*cos(angle*PI/180.0));

}if(key == GLUT_KEY_DOWN){

pos.x += (velocity*sin(angle*PI/180.0));pos.z -= (velocity*cos(angle*PI/180.0));

}

if(key == GLUT_KEY_LEFT)angle -= 5.0f;if(key == GLUT_KEY_RIGHT)angle += 5.0f;

angle = (GLfloat)((const int)angle % 360);

glutPostRedisplay();}

void SetupRC(){

glClearColor(0.0, 0.0, 0.0, 0.0);glEnable(GL_DEPTH_TEST);

}

void RenderScene(void){

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glLoadIdentity();glRotatef(angle, 0.0f, 1.0f, 0.0f);glTranslatef(pos.x, pos.y, pos.z);

glutSwapBuffers();}

int main(int argc, char *argv[]){

glutInit(&argc, argv);glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);glutInitWindowSize(600, 600);glutCreateWindow("Example");glutReshapeFunc(ChangeSize);glutSpecialFunc(SpecialKeys);glutDisplayFunc(RenderScene);SetupRC();

glutMainLoop();

return 0;

}

Declaration and initialization cube data structure

#define MAX_CUBE 10000typedef struct _CubeData{

Vector3D pos;Vector3D angle;Vector3D color;

} CubeData;CubeData cData[MAX_CUBE];

• Add following codes to SetupRC function

srand((unsigned char)time(NULL));for (int i = 0 ; i < MAX_CUBE ; i++ ){

cData[i].pos.x = rand() % 8000 - 4000;cData[i].pos.z = rand() % 8000 - 4000;cData[i].angle.x = rand() % 360;cData[i].angle.y = rand() % 360;cData[i].angle.z = rand() % 360;cData[i].color.x = (float)(rand() % 101) / 100.0;cData[i].color.y = (float)(rand() % 101) / 100.0;cData[i].color.z = (float)(rand() % 101) / 100.0;

}

Generate cube data randomly

3d position, orientation and color of a cube

Drawing functionvoid DrawCube(CubeData *pData){

glMatrixMode(GL_MODELVIEW);glTranslatef(pData->pos.x, 0.0, pData->pos.z);glRotatef(pData->angle.x, 1.0, 0.0, 0.0);glRotatef(pData->angle.y, 0.0, 1.0, 0.0);glRotatef(pData->angle.z, 0.0, 0.0, 1.0);

glColor3f(pData->color.x, pData->color.y, pData->color.z);glBegin(GL_QUADS);glVertex3f(10.0,10.0,10.0);glVertex3f(10.0,-10.0,10.0);glVertex3f(-10.0,-10.0,10.0);glVertex3f(-10.0,10.0,10.0);

glVertex3f(10.0,10.0,-10.0);glVertex3f(10.0,-10.0,-10.0);glVertex3f(-10.0,-10.0,-10.0);glVertex3f(-10.0,10.0,-10.0);

glVertex3f(10.0,10.0,-10.0);glVertex3f(10.0,10.0,10.0);glVertex3f(-10.0,10.0,10.0);glVertex3f(-10.0,10.0,-10.0);

glVertex3f(10.0,-10.0,-10.0);glVertex3f(10.0,-10.0,10.0);glVertex3f(-10.0,-10.0,10.0);glVertex3f(-10.0,-10.0,-10.0);

glVertex3f(10.0,10.0,10.0);glVertex3f(10.0,10.0,-10.0);glVertex3f(10.0,-10.0,-10.0);glVertex3f(10.0,-10.0,10.0);

glVertex3f(-10.0,10.0,10.0);glVertex3f(-10.0,10.0,-10.0);glVertex3f(-10.0,-10.0,-10.0);glVertex3f(-10.0,-10.0,10.0);glEnd();

}

• insert following codes to RenderScene function (before glutSwapBuffers call).

for ( int i = 0 ; i < MAX_CUBE ; i++ )

{

glPushMatrix();

DrawCube(cData+i);

glPopMatrix();

}

Result

MAX_CUBE = 1000032 fps

MAX_CUBE = 500007 fps

Display List

• A precompiled set of OpenGL commands for rapid execution.– Optimization of the immediate mode.

– Can avoid repetitive rendering tasks.• such as trigonometric calculations for drawing sphere, torus…

– Only for static objects.

Display List

• void glNewList (GLuint list, GLenum mode)– Display lists are created with glNewList.

– All subsequent commands are placed in the display list, in the order issued, until glEndList is called.

– list : Specifies the display-list name.

– mode• GL_COMPILE

• GL_COMPILE_AND_EXECUTE

Display List

• Gluint glGenLists (GLsizei range)– generates a contiguous set of empty display lists.– Range

• The number of contiguous empty display lists to be generated.– It returns an integer n such that range contiguous empty display lists, named n, n +

1, . . ., n + (range - 1), are created.

• void glDeleteLists (GLuint list, GLsizei range)– deletes a contiguous group of display lists.

• void glCallList (GLuint list)– executes a display list.

• void glCallLists (GLsizei n, GLenum type, const GLvoid *lists)

– execute a list of display lists.– n : the number of display lists.– type : the type of value in lists (GL_UNSIGNED_INT, GL_UNSIGNED_BYTE)– lists : the address of an array of name offsets in the display list.

Example - Display list• Declare global variable which is used for

display list name.– GLuint cubeDList;

• Modify SetupRC function and Renderscene function as following.

result

Display list MAX_CUBE = 5000012 fps

Immediate mode MAX_CUBE = 500007 fps

Vertex Buffer Objects, Vertex Array Objects, Pixel Buffer

Objects

20

Vertex Buffer Objects

•Store vertex data (vertex, normal vector, color etc.)

•Stored on graphics hardware for non-immediate rendering.

•Substantial performance gains over immediate mode rendering.

Architecture

Application

Architecture

ApplicationMemory + State

Buffer Object

Client and Server State

Application

Buffer Objects

GL Server

GL Client

size

type

stride

pointer

buffer

ARRAY_BUFFER_ARB

size

type

stride

pointer

buffer

size

type

stride

pointer

buffer

size

type

stride

pointer

buffer

● Buffer objects are server state● Vertex arrays parameters are client state

Memory + State

Per-Array Buffer Specification

VertexPointer(size, type, stride, *pointer);

Size

type

stride

pointer

bufferARRAY_BUFFER_ARB

offset

25

Angel: Interactive Computer Graphics 5E © Addison-Wesley 2009

Creating Vertex Buffer Objects

Creating a VBO requires 3 steps:

1. Generate a new buffer object with glGenBuffersARB().

2. Bind the buffer object with glBindBufferARB().

3. Copy vertex data to the buffer object with glBufferDataARB().

26

C Example

/* Initialise VBO - do only once, at start of program *//* Create a variable to hold the VBO identifier */unsigned int triangleVBO; /* Vertices of a triangle (counter-clockwise winding) */float data[] = {1.0, 0.0, 1.0, 0.0, 0.0, -1.0, -1.0, 0.0, 1.0}; /* Create a new VBO and use the variable id to store the VBO id */glGenBuffers(1, &triangleVBO); /* Make the new VBO active */glBindBuffer(GL_ARRAY_BUFFER, triangleVBO); /* Upload vertex data to the video device */glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);

27

/* Draw Triangle from VBO - do each time window, view point or data changes *//* Establish its 3 coordinates per vertex with zero stride in this array; necessary here */glVertexPointer(3, GL_FLOAT, 0, NULL); /* Make the new VBO active. Repeat here incase changed since initialisation */glBindBuffer(GL_ARRAY_BUFFER, triangleVBO); /* Establish array contains vertices (not normals, colours, texture coords etc) */glEnableClientState(GL_VERTEX_ARRAY); /* Actually draw the triangle, giving the number of vertices provided */glDrawArrays(GL_TRIANGLES, 0, sizeof(data) / sizeof(float) / 3); /* Force display to be drawn now */glFlush();

28

Updating Vertex Buffer Objects

• Use glBufferDataARB() or glBufferSubDataARB() to overwrite data.

• glMapBufferARB() in order to map the buffer object into client's memory. Use glUnmapBufferARB() to unmap.

// bind then map the VBOglBindBufferARB(GL_ARRAY_BUFFER_ARB, vboId);float* ptr = (float*)glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);

// if the pointer is valid(mapped), update VBOif(ptr){ updateMyVBO(ptr, ...); // modify buffer data glUnmapBufferARB(GL_ARRAY_BUFFER_ARB); // unmap it}

29

Vertex Array Object

•Despite the name, they do not store vertices.

•Used to store openGL state attributes.•Contain a reference pointer to a vertex buffer object, but this is not required for all cases (e.g. glDrawArrays).

30

Angel: Interactive Computer Graphics 5E © Addison-Wesley 2009

Pixel Buffer Objects

•Similar concept, allows pixel data to be transferred to gfx card without cpu (through direct memory access).

•Can perform asynchronous DMA transfer between a PBO and a texture object.

•Can modify a portion of the buffer object or the entire buffer by using glMapBufferARB() and glUnmapBufferARB().

31

Angel: Interactive Computer Graphics 5E © Addison-Wesley 2009

// "index" is used to copy pixels from a PBO to a texture object// "nextIndex" is used to update pixels in the other PBOindex = (index + 1) % 2;if(pboMode == 1) nextIndex = index; // with 1 PBOelse if(pboMode == 2) nextIndex = (index + 1) % 2; // with 2 PBOs // bind the texture and PBOglBindTexture(GL_TEXTURE_2D, textureId);glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pboIds[index]);

// copy pixels from PBO to texture object. Use offset instead of pointer.glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, WIDTH, HEIGHT, GL_BGRA, GL_UNSIGNED_BYTE, 0);

// bind PBO to update texture sourceglBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pboIds[nextIndex]);

Manipulating Textures

32

// Note: See BellowglBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, DATA_SIZE, 0, GL_STREAM_DRAW_ARB);

// map the buffer object into client's memoryGLubyte* ptr = (GLubyte*)glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY_ARB);if(ptr){ // update data directly on the mapped buffer updatePixels(ptr, DATA_SIZE); glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB); // release the mapped buffer}

glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);

Manipulating Textures

// Note that glMapBufferARB() causes sync issue.// If GPU is working with this buffer, glMapBufferARB() will wait(stall)// until GPU to finish its job. To avoid waiting (idle), you can call// first glBufferDataARB() with NULL pointer before glMapBufferARB().// If you do that, the previous data in PBO will be discarded and// glMapBufferARB() returns a new allocated pointer immediately// even if GPU is still working with the previous data.

33

// "index" is used to read pixels from framebuffer to a PBO// "nextIndex" is used to update pixels in the other PBOindex = (index + 1) % 2;nextIndex = (index + 1) % 2;

// set the target framebuffer to readglReadBuffer(GL_FRONT);

// read pixels from framebuffer to PBO glReadPixels() returns immediately.glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pboIds[index]);glReadPixels(0, 0, WIDTH, HEIGHT, GL_BGRA, GL_UNSIGNED_BYTE, 0);

// map the PBO to process its data by CPUglBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pboIds[nextIndex]);GLubyte* ptr = (GLubyte*)glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB);if(ptr){ processPixels(ptr, ...); glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);}

// back to conventional pixel operationglBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);

Modifying the Front Buffer

Lighting

Lighting and shading

• A sphere drawn by using glColor (left) does not look like a real sphere (right).

• Light-material interactions cause each point to have a different color or shade.

• Need to consider – Light sources– Material properties– Location of viewer– Surface orientation

Blinn-Phong reflection model

• A simple reflection model which can be computed rapidly.

• The default reflection model used in OpenGL.

• It has three components– Diffuse

– Specular

– Ambient

I =kd Id l · n + ks Is (h · n )+ ka Ia

Light intensity

Surface reflectance

Specular exponent

Normal vector

• Normal vectors which provide direction of the surface are essential for correct lighting calculation.

• Diffuse and specular components depend on the normal vector.

– void glNormal3f (GLfloat nx, GLfloat ny, GLfloat nz);– void glNormal3fv (const GLfloat *v);

– All surface normal vectors must eventually be converted to unit vectors to make lighting calculations correctly be done.

• glEnable(GL_NORMALIZE); • Normal vectors of any length specified with glNormal are normalized automatically after

transformation.• This approach does, however, have performance penalties on some implementations.

Enabling the lighting

• glEnable(GL_LIGHTING);

• Setting global ambient illumination– void glLightModelfv (GLenum pname, const

GLfloat *params);• pname : GL_LIGHT_MODEL_AMBIENT

• params : Specify intensity of global ambient illumination, which has four values.

Setting up light sources– glEnable(GL_LIGHT0);

• At least 8 light sources are supported.(GL_LIGHT0 ~ GL_LIGHT8)

– Setting light source parameters

• void glLightfv (GLenum light, GLenum pname, const GLfloat *params);– light : The identifier of a light. (GL_LIGHT0 ~ GL_LIGHT8)

– pname : A light source parameter for light.» GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR, GL_POSITION

– params : Specifies a pointer to the value or values that parameter pname of light source light will be set to.

» Intensity of the light has four values.

» Position of the light has four values. If the last value in the array is 0.0, it indicates that the light is an infinite distance away along the vector specified by this array.

Example code - lightsource#include <gl/glut.h>

static GLfloat xRot = 0.0f;static GLfloat yRot = 0.0f;static GLfloat xRotLight = 0.0f;static GLfloat yRotLight = 0.0f;static int width, height;GLfloat ambientLight[] = { 0.3f, 0.3f, 0.3f, 1.0f };GLfloat diffuseLight[] = { 0.7f, 0.7f, 0.7f, 1.0f };GLfloat lightPos[] = { -50.f, 50.0f, 100.0f, 1.0f };bool bMoveLightSource = false;

void SetProjection(){

GLfloat fAspect = (GLfloat)width/(GLfloat)height;GLfloat nRange = height/4.0;if(height == 0)height = 1;

glViewport(0, 0, width, height);

glMatrixMode(GL_PROJECTION);glLoadIdentity();

gluPerspective(60.0f, fAspect, 1.0, 400.0);

glMatrixMode(GL_MODELVIEW);glLoadIdentity();

}

void ChangeSize(GLsizei w, GLsizei h){

width = w;height = h;SetProjection();

}

void SpecialKeys(int key, int x, int y){

if (!bMoveLightSource){if(key == GLUT_KEY_UP) xRot-= 5.0f;if(key == GLUT_KEY_DOWN) xRot += 5.0f;if(key == GLUT_KEY_LEFT) yRot -= 5.0f;if(key == GLUT_KEY_RIGHT) yRot += 5.0f;xRot = (GLfloat)((const int)xRot % 360);yRot = (GLfloat)((const int)yRot % 360);}else{if(key == GLUT_KEY_UP) xRotLight-= 5.0f;if(key == GLUT_KEY_DOWN) xRotLight += 5.0f;if(key == GLUT_KEY_LEFT) yRotLight -= 5.0f;if(key == GLUT_KEY_RIGHT) yRotLight += 5.0f;xRotLight = (GLfloat)((const int)xRotLight % 360);yRotLight = (GLfloat)((const int)yRotLight % 360);

}

if (key == GLUT_KEY_F1){bMoveLightSource = !bMoveLightSource;}glutPostRedisplay();

}

Example code - lightsourcevoid RenderScene(void){

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glPushMatrix();glTranslatef(0.0f, 0.0f, -300.0f);glRotatef(xRot, 1.0f, 0.0f, 0.0f);glRotatef(yRot, 0.0f, 1.0f, 0.0f);glPushMatrix();

glRotatef(xRotLight, 1.0f, 0.0f, 0.0f);glRotatef(yRotLight, 0.0f, 1.0f, 0.0f);glLightfv(GL_LIGHT0,GL_POSITION,lightPos);glPopMatrix();

// glColor will be ignored.glColor3f(1.0, 0.0, 0.0);glutSolidTeapot(100.0);glPopMatrix();glutSwapBuffers();

}

void SetupRC(){

glEnable(GL_DEPTH_TEST);glCullFace(GL_BACK);glEnable(GL_LIGHTING);glLightfv(GL_LIGHT0,GL_AMBIENT,ambientLight);glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuseLight);glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight);glEnable(GL_LIGHT0);

}

int main(int argc, char *argv[]){

glutInit(&argc, argv);glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);glutInitWindowSize(600, 600);glutCreateWindow("Light source");glutReshapeFunc(ChangeSize);glutSpecialFunc(SpecialKeys);glutDisplayFunc(RenderScene);

SetupRC();glutMainLoop();

return 0;}

Result - lightsource• Although color of the object was set to red by using glColor3f

function, the object was colored gray.• When light is enabled, the color of an object depends on its

material properties such as reflectance.

Material properties

• void glMaterialfv (GLenum face, GLenum pname, const GLfloat *params);– face :

• GL_FRONT, GL_BACK, GL_FRONT_AND_BACK– pname :

• GL_AMBIENT, GL_DIFFUSE, GL_EMISSION, GL_SPECULAR,GL_AMBIENT_AND_DIFFUSE

– params : Specifies a pointer to the value or values that pname will be set to.• Reflectivity has four values

Example code – material properties

• Source code is based on lightsource example.• Add a global variable for reflectance.

– GLfloat material[] = { 0.75f, 0.0, 0.0, 1.0f };• Modify RenderScene() function as following.

void RenderScene(void){

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glPushMatrix();glTranslatef(0.0f, 0.0f, -300.0f);glRotatef(xRot, 1.0f, 0.0f, 0.0f);glRotatef(yRot, 0.0f, 1.0f, 0.0f);glPushMatrix();

glRotatef(xRotLight, 1.0f, 0.0f, 0.0f);glRotatef(yRotLight, 0.0f, 1.0f, 0.0f);glLightfv(GL_LIGHT0,GL_POSITION,lightPos);glPopMatrix();

glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, material);glutSolidTeapot(100.0);glPopMatrix();glutSwapBuffers();

}

Result - material properties

Color tracking• Current color which specified by glColor function is used 1as material

reflectance.• glEnable(GL_COLOR_MATERIAL);

• void glColorMaterial (GLenum face, GLenum mode);– face

• GL_FRONT, GL_BACK, GL_FRONT_AND_BACK– mode

• GL_EMISSION, GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR, GL_AMBIENT_AND_DIFFUSE

Example code – color tracking• Source code is based on material properties example.• Add following statements to SetupRC() function.

– glEnable(GL_COLOR_MATERIAL);– glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);

• Modify RenderScene() function as following.void RenderScene(void){

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glPushMatrix();glTranslatef(0.0f, 0.0f, -300.0f);glRotatef(xRot, 1.0f, 0.0f, 0.0f);glRotatef(yRot, 0.0f, 1.0f, 0.0f);glPushMatrix();

glRotatef(xRotLight, 1.0f, 0.0f, 0.0f);glRotatef(yRotLight, 0.0f, 1.0f, 0.0f);glLightfv(GL_LIGHT0,GL_POSITION,lightPos);glPopMatrix();

glColor3f(0.0, 1.0, 0.0);glutSolidTeapot(100.0);glPopMatrix();glutSwapBuffers();

}

Result – color tracking

Specular exponent

• The specular exponent of the material specifies how small and focused the specular highlight is.– α in specular term ks Is (h · n )

• void glMaterialf (GLenum face, GLenum pname, const GLfloat param);

• pname :– GL_SHINESS : specular exponent

• parans :– Specify specular exponent value in the range of [0, 128]. If the value is small,

the object will have a large wide specular highlight and appear less shinny.

Example code – specular highlight• Source code is based on color tracking example.• Add following global variable for specluar reflectance.

– GLfloat materialSpecular[] = { 1.0f, 1.0f, 1.0f, 1.0f };• Modify RenderScene() function as following.

void RenderScene(void){

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glPushMatrix();glTranslatef(0.0f, 0.0f, -300.0f);glRotatef(xRot, 1.0f, 0.0f, 0.0f);glRotatef(yRot, 0.0f, 1.0f, 0.0f);glPushMatrix();

glRotatef(xRotLight, 1.0f, 0.0f, 0.0f);glRotatef(yRotLight, 0.0f, 1.0f, 0.0f);glLightfv(GL_LIGHT0,GL_POSITION,lightPos);glPopMatrix();

glMaterialfv(GL_FRONT, GL_SPECULAR,materialSpecular);glMaterialf(GL_FRONT,GL_SHININESS,100);glColor3f(0.0, 1.0, 0.0);glutSolidTeapot(100.0);glPopMatrix();glutSwapBuffers();

}

Result - specular highlight• GL_SHININESS is 100.• Narrow and focused specular

highlight is produced (red circle).

• GL_SHININESS is 1.• Wide and unfocused specular

highlight is produced.

Example code• In case of rendering user-defined model instead

of predefined model in GLUT, normal vectors must be specified explicitly.

• Add following function.

void DrawCube(){

glBegin(GL_QUADS);glNormal3f(0.0, 0.0, 1.0);glVertex3f(50.0,50.0,50.0); glVertex3f(50.0,-50.0,50.0);glVertex3f(-50.0,-50.0,50.0); glVertex3f(-50.0,50.0,50.0);

glNormal3f(0.0, 0.0, -1.0);glVertex3f(50.0,50.0,-50.0); glVertex3f(-50.0,50.0,-50.0);glVertex3f(-50.0,-50.0,-50.0); glVertex3f(50.0,-50.0,-50.0);

glNormal3f(0.0, 1.0, 0.0);glVertex3f(50.0,50.0,-50.0); glVertex3f(50.0,50.0,50.0);glVertex3f(-50.0,50.0,50.0); glVertex3f(-50.0,50.0,-50.0);

glNormal3f(0.0, -1.0, 0.0);glVertex3f(50.0,-50.0,-50.0); glVertex3f(-50.0,-50.0,-50.0);glVertex3f(-50.0,-50.0,50.0); glVertex3f(50.0,-50.0,50.0);

glNormal3f(1.0, 0.0, 0.0);glVertex3f(50.0,50.0,50.0);glVertex3f(50.0,50.0,-50.0); glVertex3f(50.0,-50.0,-50.0); glVertex3f(50.0,-50.0,50.0);

glNormal3f(-1.0, 0.0, 0.0);glVertex3f(-50.0,50.0,50.0); glVertex3f(-50.0,-50.0,50.0);glVertex3f(-50.0,-50.0,-50.0); glVertex3f(-50.0,50.0,-50.0);glEnd();

}

• Call DrawCube() function instead of glutSolidTeapot() call in RenderScene() function.

Spot light

• To apply spotlight, you should specify direction of light source and cut-off angle.– glLightf(GL_LIGHT0,GL_SPOT_CUTOFF,angle);

• Specify cut-off angle in degrees.

– glLightfv(GL_LIGHT0,GL_SPOT_DIRECTION,spotDir);

Example code - spotlight

• Source code is based on color tracking example.• Add following global variable for direction of the spotlight.

– GLfloat spotDir[] = { -lightPos[0],-lightPos[1],-lightPos[2], 1.0 };

• Add following statement to SetupRC() function– glLightf(GL_LIGHT0,GL_SPOT_CUTOFF,60.0f);

• Remove the statement associated with specifying ambient component of light from SetupRC function.

• Add following statement to RenderScene() function (near the statement specifying light direction).– glLightfv(GL_LIGHT0,GL_SPOT_DIRECTION,spotDir);

Result - spotlight

• left : Cut-off angle is 60˚.

• right : Cut-off angle is 10˚.

Shade model

• glShadeModel(GL_SMOOTH);– Gouraud shading is applied.

• glShadeModel(GL_FLAT);