CSCI 1230
Project 5: Lights, Camera
1. Introduction
Figure 1: Realtime Pipeline
In the Ray assignments, you implemented a ray tracer that projects a 3- dimensional scene on a 2-dimensional plane. Ray tracing, as you probably have experienced, can be very slow.
Trimeshes, VAOs, and Shaders.
2. Requirements
2.1. Parsing the scene
Similarly to Ray, you will use the same scene parser from Lab 5: Parsing to read in scenefi les. You are expected to call your scene parser to get your metadata and set up the scene as you see fi t when new scenes are loaded in. Note that you will no longer be using .ini fi les and will rather just use .json fi les directly!
Refer to section 3.1 for more information on how to work with the parser and deal with scene changes in the codebase.
2.2. Shape tessellation
In Lab 8: Trimeshes , you should have implemented tessellation for two shapes: cube and sphere. In this project, you are expected to also include tessellation for cone and cylinder. The descriptions of these shapes remain the same as in Project 3: Intersect :
Cube: A unit cube (i.e. sides of length 1) centered at the origin.
Sphere: A sphere centered at the origin with radius 0.5.
Cone: A cone centered at the origin with height 1 whose bottom cap has radius 0.5.
Cylinder: A cylinder centered at the origin with height 1 whose top and bottom caps have radius 0.5.
Figure 3: Tessellated Cone Parameters
Figure 4: Tessellated Cone with Parameters (1, 3). Note the cone tip normals are not perpendicular to the face controls tessellation along the latitude direction while parameter 2 controls tessellation along the longitude direction.
Be especially careful when calculating normals for the tip of the cone: make sure they are always inline with one on the implicit cone, but NOT any face normal, which would result in fl at shading, nor pointing straight up, which can be the edge case for your ray tracer.
Correct Cone Tip Normal Diagram
Hint about cone tip normal calculation
We recommend working on these shapes in your lab 8 stencil prior to porting them into Project 5: Lights, Camera . This will allow you to use the visualizer to debug position and normals.
While the specifi cs of your tessellation code are up to you, you are expected to design your program in an extensible, object-oriented way. This means minimal code duplication and no 400 line branch structures (such as if... else... statements). You will lose points if you do not follow these guidelines.
Your shapes should never disappear when the tessellation parameters are too low! Be sure to set minimum tessellation parameters appropriate to each shape accordingly.
2.3. Camera
Your camera for the raytracer only needed to produce a view matrix. For Project 5: Lights, Camera , you must produce both view and projection matrices given the scene fi le's camera parameters. The projection matrix is needed to convert from camera space to clip space for OpenGL to render the scene correctly.
To implement your projection matrix, you may not use glm::perspective .
Keep in mind you are able to edit the near & far plane distances in real-time. These are seen in the parameters: settings.nearPlane and You will be expanding on your camera's functionality in the next project, so be sure to keep this in mind when implementing your camera.
2.4. Data Handling
Welcome to the meat and potatoes of this project!
You will use everything you have learned from lecture and labs to use the OpenGL pipeline to manipulate and keep track of scene data. You will take your parsed scene metadata and use it to construct all necessary VAO/VBO objects. Then you will use these in the main render loop of paintGL to fi nally render the scene, while integrating materials, global data, and light data as uniforms.
As far as the design goes, some questions you might want to ask are:
How will I represent my shape data in OpenGL?
What do my VAOs and VBOs need to be able to do/How can I generalize what I did in lab 9?
How will I use my parsed RenderData to draw my scene in paintGL ?
How many VBO/VAOs will I need in each scene? Is it dependent on the scene?
Please do not include more VBOs and VAOs than necessary!
For example, two separate VBOs should not store the same data. Points will be deducted for excess memory usage.
In general, fi lling realtime.cpp with all of your gl_____ calls is likely bad code design and will make debugging MUCH MORE DIFFICULT!
2.5. Shaders
For this project, your shader program should have the following features:
Support for directional lights
Ambient, diff use, and specular intensity computation
Final color computation integrating both object and light color
Support for up to 8 simultaneous lights. (See subsection below)
computation. Think about how all of your scene data will integrate with your shaders! Which parts can you do in the Fragment shader, which parts can you do in the Vertex shader?
As such, it is important to have completed Lab 10: Shaders before attempting this part of the project.
2.5.1. Arrays and Structs in GLSL
In Lab 10: Shaders , you learned about various uniforms to use CPU data in a shader. When dealing with multiple identical objects, the common approach is to immediately think about arrays. In GLSL, an array of vec3 s looks like this:
uniform. vec3 myVectors[8];
Notice how this array is of fi xed size 8, specifi ed explicitly in code. This is because GLSL does not support dynamically sized arrays! And it's also why we require you to support an explit number of lights.
You can access element i in this array as follows:
vec3 myithElement = myVectors[i];
The next question you may have is how to actually pass data into a uniform. array. For example, to fi ll in the jth element of the array with the vector (x, y, z) , you would write the following:
GLint loc = glGetUniformLocation(shaderHandle, "myVectors[" + std:: glUniform3f(loc, x, y, z);
If you wish to get fancy, you can try using struct s as well. They have to be fi
rst defi ned in the shader then declared as a uniform. in the following manner:
struct AwesomeStruct
{
int favoriteNumber;
uniform. AwesomeStruct myStruct;
Accessing the member favoriteColor from the uniform. is done as such:
vec3 coolestColor = myStruct.favoriteColor;
To set the color data to a vector (r, g, b) , you would write the following:
GLint loc = glGetUniformLocation(shaderHandle, "myStruct.favoriteCo glUniform3f(loc, r, g, b);
If you wish to read more about uniform. in GLSL, check out this link!
2.5.2. Special tip about GLSL
In GLSL, pow(x, y) is undefi ned for x < 0 or if x = 0 and y ≤ 0, so be careful of these cases as there may be times where shininess = 0 ! Check the offi cial document to learn more.
2.6. Results
Here are some sample images of what your realtime renderer should be capable of by the end of this assignment.
Figure 5: phong_total.json
Figure 6: recursiveCones4.json with far plane distance of 100
Figure 7: recursiveCones4.json with far plane distance of 20
Figure 8: recursiveCones4.json with far plane distance of 15
Figure 9: recursive_sphere_7.json (in real time!) with tessellation parameters of (12, 12)
3. Stencil Code
You may notice the stencil code provided is minimal--that is by design. To complete this assignment, you will need to have a good understanding of the OpenGL pipeline.
We have provided for you the following fi les which you will interact with:
Realtime : A fi le containing the initialization of an OpenGL context as well as functions that are automatically called on certain events. These include: initializeGL , paintGL , and resizeGL .
And you have already written the following:
A scene parser (lab 5)
A basic camera class (Ray projects)
Cube and sphere classes (lab 8)
Working with GLEW and OpenGL in Qt:
If you are working in a fi le and need to use OpenGL functions, make sure to use #include ! Also, Qt creator gives you access to the OpenGL context when calls stem from any of:
Realtime::initializeGL() , Realtime::paintGL() , and Realtime::resizeGL() . If you wish to make OpenGL calls stemming from outside these functions (for example Realtime::sceneChanged() ), you must call makeCurrent() fi rst.
3.1. Loading Scenes
As stated before, you will need to handle the loading of scenes using your scene parser from lab 5. We have provided for you a helper function in realtime.cpp for you to use for this purpose titled sceneChanged() . This function will be called whenever the "Upload Scene File" button is pressed and a .json fi le is selected. To get access to the current scenefi le, you can use the settings object's sceneFilePath parameter.
Important: We will not be working with .ini fi les in this project! Given the real-time nature of this project, settings and parameters will be controlled by interactive UI buttons and sliders instead.
3.2. Realtime::initializeGL() , Realtime::paintGL() , & Realtime::resizeGL()
These functions are the "core" of a rendering system. They are overriden from the parent QOpenGLWidget class if you are interested.
intializeGL() is called once near the start of the program aft er the constructor of Realtime has been called. It also is called before the related information you may need, aft er the GLEW initialization calls as commented. Note that you cannot use any OpenGL-related functions in the constructor of this class as they are only available once GLEW has been initialized.
paintGL() is called whenever the OpenGL context changes, i.e. when you make some state-altering OpenGL call. You won't have to worry about this for this project, but keep in mind this behavior. when you add interactivity in Project 6: Action! .
resizeGL() is called whenever the window is resized. You will need to use the input width and height to correctly update your camera.
3.3. Realtime::finish()
In OpenGL, we oft en use calls of the form. glGen______ . Just as with using the keyword new , we must delete this generated memory as well. This function, finish() , will be called just before the program exits so be sure to use it to your advantage to avoid memory leaks!
3.4. Realtime::settingsChanged()
In general, this function will be called any time a parameter of the settings is changed (via interacting with the left GUI bar) other than settings.sceneFilePath . For this project, the settings you will have to worry about are:
settings.nearPlane : Should control your camera's near clipping plane.
settings.farPlane : Should control your camera's far clipping plane.
settings.shapeParameter1 : Should control the tessellation parameter 1 as described in section 2.2 above.
settings.shapeParameter2 : Should control the tessellation parameter 2 as described in section 2.2 above.
3.5. Realtime::____event() Functions
These functions are all for handling interactivity which you will implement in Project 6: Action! . So do not worry about these for now!
To assist with creating and modifying scene fi les, we have made a web viewer called Scenes. From this site, you are able to upload scenefi les or start from a template, modify properties, then download the scene JSON to render with your raytracer.
We hope that this is a fun and helpful tool as you implement the rest of the projects in the course which all use this scenefi le format!
For more information, here is our published documentation for the JSON scenefi le format and a tutorial for using Scenes.
5. TA Demos
Demos of the TA solution are available in this Google Drive folder titled projects_lightscamera_min .
macOS Warning: "____ cannot be opened because the developer cannot be verifi ed."
6. Submission
Your repo should include a submission template fi le in Markdown format with the fi lename submission-lights-camera.md . We provide the exact scenefi les you should use to generate the outputs. You should also list some basic information about your design choices, the names of students you collaborated with, any known bugs, and the extra credit you've implemented.
For extra credit, please describe what you've done and point out the related part of your code. We have provided for you 4 diff erent booleans in Settings for you to use for extra credit: extraCredit1 , extraCredit2 , extraCredit3 , and extraCredit4 . These are activated by their respective GUI checkboxes. If you implement any extra features using a GUI "Extra Credit #" checkbox to be activated, please also document it accordingly so that te TAs won't miss anything when grading your assignment.