2017 March 6,

CS 311: Second Half

Day 15 (Wed Feb 8)

500glfw.c

500openGL14.c

500openGL15.c

500openGL20.c

Homework

This is a benchmark for the course. You will hand in 160mainDiffuse.c, 170mainSpecular, 180mainAmbient.c, 190mainFog.c, and all of the files on which they depend. Make sure your files are functional, clean, and commented. Make sure that all contributors are credited. Make sure that all contributors have copies of the files. One student then uploads the files to COURSES.

510vector.c: In a copy of 100vector.c, replace all doubles with GLdoubles.

510mesh.c: This is a clean copy of 100mesh.c, with a few changes. All doubles have been replaced with GLdoubles. All ints have been replaced with GLuints, except in the return values for meshInitialize... functions. In meshSetTriangle and the three functions after it, the <= tests have been removed, because they are now vacuous and raise warnings. Finally, the Rendering section has been replaced with an OpenGL section, with some incomplete functions. Your job is to finish implementing those functions. Specifically, there are two spots, marked with !!, where you need to write code. If you are unsure what should happen, then examine 500openGL20.c and 510mainMesh.c.

510mainMesh.c: Study. Do not alter. Use this file to understand how 510mesh.c should work, and to verify that it works. Here's a screenshot of mine:

mesh screenshot

Day 16

500shader.c

500openGL20b.c

camera

scene graph

Homework

500time.c: Study. If you're working on Windows, and you want your animations to be good, then figure out the analogous code there (and please tell us).

520matrix.c: In a copy of 130matrix.c, paste the mat44OpenGL function from 500openGL20b.c. Insert a comment before it, to document/specify what it does. Then, throughout the file, replace all doubles with GLdoubles. While we're here, add the following functions to build identity matrices, if you don't already have them.

void mat33Identity(GLdouble m[3][3])
void mat44Identity(GLdouble m[4][4])

520camera.c: This file implements a camera data type, with both low- and high-level interfaces. Your job is to implement camRender, consulting 500openGL20b.c and 520mainCamera.c as needed.

520mainCamera.c: Study. Do not alter. Use this file to understand how 520camera.c should work, and to verify that it works.

530scene.c: This file implements a scene graph data type (with no texturing yet). Your job is to implement sceneRender. You may find 500openGL20b.c helpful. You will also need the following functions for setting uniform variables. Pass 1 for the count parameter.

glUniform4fv(GLint location, GLsizei count, GLfloat values[4]);
glUniform3fv(GLint location, GLsizei count, GLfloat values[3]);
glUniform2fv(GLint location, GLsizei count, GLfloat values[2]);
glUniform1fv(GLint location, GLsizei count, GLfloat values[1]);

530mainScene.c: Study. Do not alter. Use this file to understand how 530scene.c should work, and to verify that it works. Here's a screenshot of mine:

scene graph screenshot

Day 17 (Mon Feb 13)

500texturing.c

perspective vs. linear texture mapping

lighting

Homework

530vector.c: Move the vecOpenGL function from 530scene.c to 530vector.c. (We're correcting an oversight of mine in the last homework assignment.)

530mainScene.c: Include 530vector.c and check that everything is still working correctly.

540texture.c: Study.

540scene.c: Add a texTexture **tex member to the scene node. Alter sceneInitialize so that it begins like the code below. Add new accessor functions sceneSetTexture and sceneSetOneTexture, mimicking sceneSetUniform and sceneSetOneUniform. Add a new parameter, GLint textureLocs[], to the end of sceneRender's parameters. Update that function to correctly activate and deactivate textures, using the first node->texNum texture units. You may assume, if you like, that node->texNum ≤ 8.

int sceneInitialize(sceneNode *node, GLuint unifDim, GLuint texNum, 
        meshGLMesh *mesh, sceneNode *firstChild, sceneNode *nextSibling) {
    node->unif = (GLdouble *)malloc(unifDim * sizeof(GLdouble) + 
        texNum * sizeof(texTexture *));
    if (node->unif == NULL)
        return 1;
    node->tex = (texTexture **)&(node->unif[unifDim]);
    mat33Identity(node->rotation);
    ...

540mainTexturing.c: Make a demonstration program. Use at least two scene graph nodes and at least three textures. You are not allowed to use every texture at every node (because we're trying to verify that your sceneRender correctly activates and deactivates textures).

550light.c: Study.

550mainLighting.c: Make a demonstration program, that works with the following shader code. (Whenever I give you GLSL, study it. It's easiest to learn GLSL from examples like this.) In my program, specular comes from the scene node uniforms, so that different nodes can have differing specular reflectivity. All other uniforms are set in my render function, in various ways.

GLchar vertexCode[] = "\
    uniform mat4 viewing;\
    uniform mat4 modeling;\
    attribute vec3 position;\
    attribute vec2 texCoords;\
    attribute vec3 normal;\
    varying vec3 fragPos;\
    varying vec3 normalDir;\
    varying vec2 st;\
    void main() {\
        vec4 worldPos = modeling * vec4(position, 1.0);\
        gl_Position = viewing * worldPos;\
        fragPos = vec3(worldPos);\
        normalDir = vec3(modeling * vec4(normal, 0.0));\
        st = texCoords;\
    }";
GLchar fragmentCode[] = "\
    uniform sampler2D texture0;\
    uniform vec3 specular;\
    uniform vec3 camPos;\
    uniform vec3 lightPos;\
    uniform vec3 lightCol;\
    uniform vec3 lightAtt;\
    varying vec3 fragPos;\
    varying vec3 normalDir;\
    varying vec2 st;\
    void main() {\
        vec3 surfCol = vec3(texture2D(texture0, st));\
        vec3 norDir = normalize(normalDir);\
        vec3 litDir = normalize(lightPos - fragPos);\
        vec3 camDir = normalize(camPos - fragPos);\
        vec3 refDir = 2.0 * dot(litDir, norDir) * norDir - litDir;\
        float d = distance(lightPos, fragPos);\
        float a = lightAtt[0] + lightAtt[1] * d + lightAtt[2] * d * d;\
        float diffInt = dot(norDir, litDir) / a;\
        float specInt = dot(refDir, camDir);\
        if (diffInt <= 0.0 || specInt <= 0.0)\
            specInt = 0.0;\
        float ambInt = 0.1;\
        if (diffInt <= ambInt)\
            diffInt = ambInt;\
        vec3 diffLight = diffInt * lightCol * surfCol;\
        float shininess = 64.0;\
        vec3 specLight = pow(specInt / a, shininess) * lightCol * specular;\
        gl_FragColor = vec4(diffLight + specLight, 1.0);\
    }";

Day 18

interlude: debugging, clarifying

lighting

Homework

560light.c: Study.

560mainSpot.c: First get the omnidirectional light from 550mainLighting.c working with the new light code in 560light.c. Then change the light to a spot light. Most of that work is in GLSL. Here is a screenshot of mine:

spot light screenshot

This is a benchmark for the course. You will hand in 550mainLighting.c, 560mainSpot.c, and all of the files on which they depend. Make sure your files are functional, clean, and commented. Make sure that all contributors are credited. Make sure that all contributors have copies of the files. One student then uploads the files to COURSES.

Day 19

500openGL32.c

miscellany

Homework

570mainDirectional.c: This exercise is optional and not difficult. Demonstrate a directional light. (Whether or not you do this exercise, you are expected to know how directional lights work.)

580mesh.c: We have to make four major changes to the OpenGL section. First, the meshGL data type now stores the number of attributes, the dimensions of those attributes, and an array of VAOs. The initializer is as follows. Update the meshGLMesh struct accordingly.

/* Initializes an OpenGL mesh from a non-OpenGL mesh. vaoNum is the number of 
vertex array objects attached to this mesh storage. Typically vaoNum equals the 
number of distinct shader programs that will need to draw the mesh. Returns 0 
on success, non-zero on failure. */
int meshGLInitialize(meshGLMesh *meshGL, meshMesh *mesh, GLuint attrNum, 
        GLuint attrDims[], GLuint vaoNum) {
    meshGL->attrDims = (GLuint *)malloc((attrNum + vaoNum) * sizeof(GLuint));
    if (meshGL->attrDims == NULL)
        return 1;
    for (int i = 0; i < attrNum; i += 1)
        meshGL->attrDims[i] = attrDims[i];
    meshGL->vaos = &meshGL->attrDims[attrNum];
    glGenVertexArrays(vaoNum, meshGL->vaos);
    meshGL->vaoNum = vaoNum;
    meshGL->attrNum = attrNum;
    meshGL->triNum = mesh->triNum;
    meshGL->vertNum = mesh->vertNum;
    meshGL->attrDim = mesh->attrDim;
    glGenBuffers(2, meshGL->buffers);
    glBindBuffer(GL_ARRAY_BUFFER, meshGL->buffers[0]);
    glBufferData(GL_ARRAY_BUFFER, 
        meshGL->vertNum * meshGL->attrDim * sizeof(GLdouble), 
        (GLvoid *)(mesh->vert), GL_STATIC_DRAW);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, meshGL->buffers[1]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, meshGL->triNum * 3 * sizeof(GLuint),
        (GLvoid *)(mesh->tri), GL_STATIC_DRAW);
    return 0;
}

Second, the initializer above allocates space to hold the VAOs, and even requests those VAOs from OpenGL, but does not really initialize those VAOs with any useful information. The following function does the initialization of a single VAO. Write it, using 500openGL32.c as a guide.

/* attrLocs is meshGL->attrNum locations in the active shader program. index is 
an integer between 0 and meshGL->voaNum - 1, inclusive. This function 
initializes the VAO at that index in the meshGL's array of VAOs, so that the 
VAO can render using those locations. */
void meshGLVAOInitialize(meshGLMesh *meshGL, GLuint index, GLint attrLocs[])

Third, meshGLRender now takes just two parameters: the mesh, and a VAO array index like the one above.

Fourth, meshGLDestroy has more resources to clean up. It already deallocates the VBOs. It should also deallocate the VAOs. It should also free the one pointer that was malloced in meshGLInitialize. We haven't talked much about malloc and free in this course, but they're not hard. Mimic the malloc/free pair that you see in meshInitialize and meshDestroy.

580scene.c: Change sceneRender to account for the changes to meshGLRender. That is, where it used to take three parameters for passing on to meshGLRender (between unifLocs and textureLocs), it now takes a single VAO array index.

580mainSpot.c: In a copy of 560mainSpot.c, make the changes needed to incorporate OpenGL 3.2, GL3W, 580mesh.c, and 580scene.c. Because you have just one shader program (don't try to be a hero), pass 1 as the value for voaNum, and initialize just one VOA per mesh. Your program should use a scene graph of at least two nodes and two meshes, to demonstrate that everything is working correctly. If your 560mainSpot.c already satisfied that requirement, then the new program should be visually identical to it.

Day 20 (Mon Feb 20)

shadow mapping

project work

Homework

Read the project details and ideas in the Materials section of the course web page. Do some preliminary exploring online. Come up with your own project ideas if you like. Find a partner, or ask me to find you a partner.

Day 21

shadow mapping

project work

Homework

590matrix.c: To get shadow mapping to work, I eventually resigned myself to OpenGL's left-handed depth convention. So, edit the two functions that construct projection matrices. In each one, negate the third row (that is, row 2).

590shadow.c: Study.

590mainShadowing.c: Study. Find your own image files to supply the five textures to this program. Then run the program. It should draw a scene with a single shadow-mapped spot light. There is no attenuation, diffuse reflection, or specular reflection. Merge this code with your own, to supply those features. Test.

590mainShadowing.c: Add a second shadow-casting spot light. This addition requires changes throughout your code. Here is a screen shot of mine, with a white light and a pink light:

shadow-casting screenshot

Day 22

cel shading

project work

cel-shading screenshot

Homework

Work on your project. By Saturday at 11:59 PM, each project sends me a single e-mail with the following information about what the project is and how it is feasible.

  1. names of project members
  2. if solo, then the reason for being solo
  3. topic
  4. what software the project will use, usually including an OpenGL version number and why that version is adequate/necessary
  5. whether the software works on our lab machines; if not, then a plan for how the project can happen
  6. if other people's software is being used, then an explanation of how the students will demonstrate that they understand the project, rather than treating the software as a "black box" that does the project for them

Day 23 (Mon Feb 27)

Exam: There is no class today. Instead we have individual oral exams today and tomorrow. No computers, notes, or other aids are allowed. This exam is cumulative, covering all material up to and including shadowing. However, it will focus disproportionately on topics that did not appear on the first exam. Here are some study questions.

Homework

This is a benchmark for the course. You will hand in 590mainShadowing.c and all of the files on which it depends. Make sure your files are functional, clean, and commented. Make sure that all contributors are credited. Make sure that all contributors have copies of the files. One student then uploads the files to COURSES.

Then work on your project.

Day 24

picking and other mouse interaction

project work

Homework

Work on your project. Remember that in about a week you will give a progress report to the class.

Day 25

scientific visualization example (orientational data from structural geology)

design choices for OpenGL bridged from R, Python, etc.

project work

visualizing orientations screenshot

Homework

Work on your project. Don't forget to sign up for a report/demo slot, using the sheet posted on my office door.

Day 26 (Mon Mar 6)

deferred shading

antialiasing and depth of field, briefly

dissecting a frame of a modern video game, such as here or here (content warning: guns and gore)

project work

Homework

Work on your project.

Day 27

reports and demonstrations

Homework

Work on your project.

Day 28

reports and demonstrations

Homework

Work on your project.

End (Wed Mar 15)

Your final project is due at 5:00 PM on this day.

Other small topics, that we will never cover

abstracting the program? textured light? mesh file formats? CGI movie examples? 000mallocFree.c? OpenGL 4.x?