|
|
|
||||||||||||||
![]() |
|
|
|||||||||||||
|
|
|||||||||||||||
|
|
|||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
||||||
|
|
|||||||||||||||
Lab 9: OpenGL Shading Language Note: You are ALL now at the point where you may want to seek out additional references for OpenGL. The best reference, by far, is the OpenGL Programming Guide: Fifth Edition, The Official Guide to Learning OpenGL, Version 2, by Shreiner, Woo, Neider, and Davis, 2005. The first edition of this book is available online (and for free). It is very dated and does not contain current information about OpenGL. Nonetheless, it can serve as a good tool for learning OpenGL basics. A good reference book for the OpenGL Shading Language can be found here: www.3dshaders.com. The specification and documentation for GLSL can be found at 3DLabs website: http://developer.3dlabs.com/openGL2/index.htm. Description In this lab, you will use the OpenGL Shading Language to change how a simple GLUT object can be rendered using the shading language. Step 1: Download the Visual Studio Project I have created that contains the GLSLObject class and the PerFragment lighting example we walked through in class: Unzip this file, load it up, and build it. Hopefully it will run for you. It did on my Windows box. You should see a teapot that is lit with per-fragment based lighting. Step 2: Add a second teapot to the scene. Render one of the teapots with the shader activated and render the 2nd teapot without the shader activated. Place the teapots side-by-side. Do you notice any differences? What are these differences? Discuss them with the other students in the lab. There are at least two... Step 3: Now, remove the 2nd teapot you added so that there is only 1 being rendered with per-fragment lighting. Attempt to make the change to fp.glsl that does per fragment cell shading. Here is a snippet of the code I used in class to do cell shading: ... Step 4: If you need to create a uniform variable for the shader you can use a function in the GLSLObject. Recall that the uniform variables allow you to pass variables into your shaders from the CPU program. For instance, to modify the phong exponent in the shader via your CPU code, you would need to create a reference to the uniform variable in the shader within your program: GLint u_phong = shader_object.createUniform("phongexp"); Then change the value of the uniform variable representing the Phong Exponent right before you render the teapot. For instance, with the teapot, shader_object.activate(); Note that you can only call the glUniform calls after activate a particular shader and before the object that needs the uniform variables is rendered. Next, let's add the uniform variable to the fragment shader, "fp.glsl". To do this, add a line at the top of this file for the new variable: uniform float phongexp; Then, in the part of the code where we use the Phong exponent, make the change to use the new variable. See if it worked as planned. Step 5: If you have time, or feel like it later, try to make modifications to your vertex program (vp.glsl) that modify the vertex positions. Recall that one of the jobs of the vertex program is to transform the vertex into the canonical projection space either by gl_Position = ftransform(); or gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; You don't have to multiply the gl_Vertex variable to do this. You could, for instance, create your own vertex based off gl_Vertex and then modify that by gl_ModelViewProjectionMatrix, as in the following pseudo-code: vec4 modified_Vertex = gl_Vertex; See if you can come up with something... perhaps apply a sin function to the vertex positions? There is a "sin" function available in the GLSL. Step 6: For the final step, create a varying variable that you can use to determine whether to draw a pixel in the fragment shader. Specifically, we're going to use the fragment programs "discard" function to throw away a pixel in this case. We will also use a varying variable to communicate between the vertex shader and the fragment shader. Recall that varying variables allow the vertex shader to communicate with the fragment shader. First, create a varying variable to hold the X position of the vertex. At the top of the vp.glsl file, add the following line: varying float x; then, in the main body of the vertex program (ideally the first instruction), set x by storing the x component of the gl_Vertex vertex attribute: x = gl_Vertex.x; Now, in the fragment program, add a line at the top of the file to note the new varying variable: varying float x; Then, at the point where you assign the gl_FragColor, do the following: if (sin(x * 20.0) < 0.0) Did you get what you thought you might get?
|
|||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||