Homework

Development Environment

Homework #1 Due Wednesday, January 11, 2012

The main part of this homework is to get your machine configured, but we can have some fun as well. Write a set of shaders to produce pleasing backdrops. These will (or should) be used through-out the course. Recall that OpenGL Normalized Device Coordinates range from (-1,-1,-1) -> (1,1,1). There is also no requirement that you use the modelview or the projection matrices in your shaders. Probably not the best software engineering, but may make things easier. Suggested shaders include:

Pleasing Colors: Apply some artistic talent to your backgrounds. Here are some general rules on color usage:

  1. Never use pure saturated colors (R=255, etc.). For darker colors use lower values. For desaturated colors never have a component equal to zero.
  2. Contrasting colors are across the color wheel (blue->yellow, etc.).
  3. For backgrounds, less is more, so if the colors are very very close to each other, but provide a subtle pattern or gradient, that is good.

Below are a list of files to get you started. These provide a complete OpenGL 3.1 core (GLSL 1.3) solution to either set the background to a solid color or a mutli-colored (ugly) backdrop. You will need to download and use (locally) GLEW and FreeGLUT. The specific tasks are:

  1. Download GLEW and set-up an include and lib directory for all of your OpenGL development.
  2. Download FreeGLUT (Windows Binaries)
  3. Read through this tutorial on the OpenGL Wiki.
  4. Create a project (Empty project in Visual Studio) and add the following files to it:
    1. main.cpp
    2. backdrop.vert
    3. backdrop.frag
  5. Open the Project Properties:
    1. Under C/C++->General add your include dir (with a GL dir inside it) in the Additional Include Directories
    2. Under Linker->General add your lib directory in the Additional Library Directories.
    3. Add the glew32.lib, freeglut.lib and opengl32.lib as Additional Dependencies in Linker->Input
  6. Build the project and then copy the glew and freeglut dll's to the debug (and/or Release) directories.
  7. Run your project. Seek Immediate Assistance if machine smokes (or you need help :-).
  8. Read through the man pages for all of the OpenGL API calls that are in main.cpp.
  9. Repeat to generate 3 really cool backdrops (if that is possible).
  10. Create either a PDF document or a single HTML page with your results. Include:
    1. Your Name and a header including The Ohio State University, CSE 781and the date.
    2. Some explanation of what you were trying to accomplish.
    3. The Fragment shader or snippet (embedded, not linked to) used to accomplish it.
    4. A window screen shot of the result.
    5. A conclusion describing what machine, graphics card, etc. was used and any issues encountered.
    6. Also, e-mail your best result so I can put them here and share with the class.
  11. The Vertex Shader does not need to be changed for this assignment. If you found something interesting and changed it include that in your report.

Homework #2 Due Friday, February 3, 2012

For this homework, we want to get a basic understanding of geometry shaders and write a fragment shader that will compute a Gaussian texture centered in the image. The next homework will use this as a paint brush for a simple 2D paint package. Here is a sample of what your result should look like:

Gaussian result  

A Gauassian function has a maximum of one at zero and slowly and smoothly decreases to zero at infinity. It has the form:

f(x) = exp(-sigma * x^2) in one dimension and

f(x,y,z,...) = exp(-sigma * r^2) in any higher dimension. The image on the left is obviously two-dimensions.

For this image, we want the value at the edges to be insignificant (aka less than 1/256). You can solve for sigma by letting r=1 at the edge and taking the natural logarithm of 1/256 or some other small number (I think I used 1/512).

 

Step 0

Change the background clear color or use one of your background shaders!

Step 1

Modify your HW #1 (do not use the DemoFramework) to use a fragment shader that computes this value as the intensity. Use a vertex shader that passes an arbitrary color from the vertex shader to the fragment shader (This will be used to understand passing data through the geometry shader later). Also modify your HW #1 to pass a Uniform value to the fragment shader to specify the size of your window / texture. No need to do anything fancy, you can fix it at 256 or whatever. Play with resizing the window and watch the center point move. After playing put the Window size to the value of the uniform to have a consistent view.

Step 2

Change your drawing of the quad to use a triangle strip rather than quads.Note that you will need to change the order of your vertices (swap the last two). That plus changing GL_QUADS to GL_TRIANGLE_STRIP is all that is needed. Now, create a simple pass-thru geometry shader, PassThru.geom, that looks like this:

Simple Geometry Shader
#version 330 core

layout (triangles) in;
layout (triangle_strip) out;
layout (max_vertices = 3) out;
void main(void)
{
       for (int i = 0; i < gl_in.length(); i++) {
              gl_Position = gl_in[i].gl_Position;
              EmitVertex() ;
       }
       EndPrimitive() ;
}

This geometry shader simply walks thru each vertex that is passed in using the data structure gl_in, and emits the vertex without changing its value or position. No other data is passed through. The layout attributes tell OpenGL what is expected of this shader. A good reference for this is Chapter 11 of the 5th Edition of the OpenGL SuperBible. It is available on-line with Safari.

In your main.cpp, let's first change initShaders to createShader that takes as input the filenames for the vertex, fragment and geometry shaders and returns the unsigned int (GUID) of the shader program, like so:

unsigned int createShader(const char* vertexShader, const char* fragmentShader, const char* geometryShader = 0)

I set a default value for the geometryShader so that this routine can be used with only two arguements (no geometry shader) or three. Simply test if geometryShader !=0 and then load, compile and attach the geometry shader. Make these changes, and test that the program runs as in Step 1 without the geometry shader. Now, try to run it with the geometry shader. You will (or should) get black, as the color from the vertex shader is not making it to the fragment shader anymore. Actually, let's add a routine to print out any link errors. Very similar to the printShaderInfo routine, but change shader/Shader everywhere to program/Program. Call this after the link and/or inquiring about the Link status (again change Shader to Program and GL_COMPILE_STATUS to GL_LINK_STATUS. Changing your fragment shader such that it does not use the color (passed in from the vertex shader) should produce a result for you.

Step 3

Now, let's look at how to get data from the vertex shader through the geometry shader to the fragment shader. For this we need the specify the input variable coming from the vertex shader as an array since we will have access to all of the vertices for this primitive. We will output a variable of the same type only not as an array. What happens is that everytime EmitVertex is called, the out data is set for that vertex. This avoids you trying to change vertex one's color while you are working on emitting vertex 2. So, if my variable in the vertex shader is:

out vec4 baseColor;

Then in the geometry shader I would have:

in vec baseColor[];

out vec4 color;

The fragment shader would then have:

in vec4 color;

The geometry shader also needs to set the color variable, assuming it varied every vertex, then we would say:

color = baseColor[i];

just before the EmitVertex call in the for loop.

Summary

Make sure you have:

  1. A Gaussian fragment shader
  2. A geometry shader that passes through the positions and any vertex data.
  3. A printProgramInfo routine that prints out any error messages on linking.
  4. A modified initShader / createShader to allow us to build a few programs in the next homework.
  5. Submit your main program and shaders for the grader.

Homework #3 Due Wednesday, February 8, 2012

For this homework, we want to get Frame-Buffer Objects (FBO's) working, understanding the relationship between FBO's, glClear, the depth buffer, and textures. The usage here of FBO's might be common, but will be different than from lab2. Here, we will write once to the texture and then use it for all other frames. For lab2, we will write the FBO and use it every frame. here, we will also use a Geometry shader that will take a point and produce 2 triangles for a simple paint brush.

Here are the complete specs for this lab: