You will need to install the following software:
You may work on a platform of your choice, but test your submission for correctness on a Windows machine, as that is how it will be graded.
Add a README.md to describe any bells, whistles, and anything out of the ordinary you did for the project. This will help us grade your project and make sure you receive all the credit you deserve.
When you have made sure you committed and pushed everything to your Gitlab repository, tag your commit with SUBMIT (for submitting it on the project-specific branch) or SUBMIT-projectname (for submitting on the main branch), and push the tag. We will run a script to clone all repositories shortly after the due date and we will be grading your project based on which commit you tag. You will be able to see on Gitlab whether you have done so successfully. To tag a commit, simply do the following:
git tag SUBMIT
git push --tags
In this screenshot, under Repository->Tags, the commit “test commit” is the one tagged for submission.
After each assignment, you are required to submit an ‘artifact’ that is created with your project and shows off the features of your program.
You will lose points if you do not submit something. We will not grade on artistic merit. However, after everyone submits their artifacts, we will create a gallery on the course website where you will vote on your favorite artifacts. The winner and runners-up will receive a small amount of extra credit. So be sure to try your best!
The link to submit the artifact will be available on the project pages after the code submission deadline. We will also be sending out reminders.
OpenGL sits between the graphics hardware and the application, providing a standard, cross-platform API for hardware accelerated rendering. There are a few other popular rendering technologies, such as Microsoft’s DirectX, Apple’s Metal, and the more recent Vulkan. But we will be using OpenGL because it is supported on Windows, Mac, and Linux.
In the first project, you will be writing OpenGL code that draws primitives like triangles and lines to emulate brush strokes. In the second project, you will be writing OpenGL shaders that affect describe how the GPU colors your 3d scene and models. At any time, you are free to explore OpenGL on your own and go above and beyond to extend the program to suit your own needs.
Graphics hardware used to be very specific and non-flexible, a fixed function pipeline that output pixels to the screen. But these days, many stages of this pipeline are programmable (shaders) and we can even perform arbitrary massively parallel computations on the GPU.
OpenGL operates like a state machine with global variables. When something is changed, it stays changed until something else changes it again. All the state associated with an instance of OpenGL is stored in an OpenGL Context. However, while the OpenGL API is defined as a standard, the creation of an OpenGL Context is not. Every operating system does it differently, so we want to use a windowing toolkit like Qt or FLTK that handles cross-platform context creation automatically, as well as provide a GUI framework.
Since there is no single implementation of OpenGL, graphics hardware vendors need to supply their own implementation of OpenGL with the graphics drivers, necessitating the step of loading OpenGL functions dynamically. It would be an enormous pain to do this by hand, so instead loading libraries are used such as GLEW.
Graphics hardware does not understand higher level primitives such as circles and rectangles. It only understands how to draw things like points, lines, and triangles. A 3d sphere drawn on the GPU is actually a whole bunch of triangles that approximate a sphere. Each primitive has one (point), two (line), or three (triangle) vertices that you can attach any data you would like, such as a 3d position, or intrinsic color.
The set of all data and data types belonging to a vertex is defined as the Vertex Format. The vertices of these basic primitives are stored in something called a Vertex Buffer, which is really just a GPU allocated piece of memory. You can store all the data for each vertex in separate vertex buffers, for example: one vertex buffer for 3d positions, another for intrinsic colors. Or you can store it interleaved in one giant vertex buffer. Everything required to render a specific set of primitives is saved in a Vertex Array Object.
A lot of OpenGL functions operate on the notion of a global “current” something that is “bound.” For instance, there is a global GL_ARRAY_BUFFER variable which must have a Vertex Buffer bound to it before you can do anything with the GL_ARRAY_BUFFER like upload data to it.
OpenGL manages its own memory. OpenGL objects are represented by unique integers. There are a whole slew of glGenX functions that basically request for a GPU resource to be allocated and you are given its ID in return. However you must also remember to ask OpenGL to delete those resources when they are not used anymore.
If you would like to know more about OpenGL and how it works, you can read a lot more about it on the Khronos OpenGL Wiki.
We provide most of the boilerplate OpenGL code required to run the program because we believe that would take too long and would not be a very good use of time. We would rather that time be spent towards learning higher level graphics concepts and trying out cool bells and whistles. If you would like to learn more about OpenGL, this website goes through how to start drawing things from scratch.
C++ Language Tutorial - useful for quick reference
Thinking in C++ and Thinking in C by Bruce Eckel
Full documentation can be found here, but below is a brief overview of the most common Unity structures.
A GameObject
is something that can be placed in the world. You can create a
GameObject
by right-clicking in the Hierarchy on the left, and choosing
any of the options. Selecting the object will open the Inspector on the right. You
can edit the GameObject
's properties here. A GameObject
can have
attachments called a Component
. A Component
can add behavior
to the GameObject
, such as being a 3D model or a light source. You can also create
your own Component
through the using of Unity's Scripting API.
To add a Component
, click on the object either in the Scene view or in the
Hierarchy tab on the left. Then, under the Insepector view on the right, click
Add Component at the bottom of the inspector (you may have to scroll down). A list
will pop up and you can search for what you want to add. If you create scripts, they will
show up here so you can add them to the GameObject
.
You may make a script by going to the Project view in the bottom and navigating to Assets.
Then right click and do Create -> C# Script. If you have installed Visual Studio, double clicking
on the script will open it there. By default, the script is populated with two methods, Start()
and Update()
. Start()
is called once to initialize the script and
Update()
is called on each frame. Inside your scripts, you can use the Debug.Log()
function to output data to Unity's console. By default, this is found as a tab titled Console near
the Project area. You can also set breakpoints in your scripts in Visual Studio. These breakpoints
will only be triggered if you use Attach to Unity or Attach to Unity and Play inside Visual
Studio.
Your script extends the MonoBehaviour
class, for which the documentation can be found
here. It has various
methods that you may override, each of which have slightly different behavior. You will mostly
likely only need to use Start()
, Update()
, and FixedUpdate()
.
Declaring public
qualified fields in your script allows you to control the behavior
of the script from within the Unity editor itself. This is important when you want to reference
another GameObject
within your scene. For instance, the below script will result
in the view in the Inspector for the GameObject
which has the script attached:
You can drag a GameObject
from the Hierarchy into the field in the Unity editor
to set the field in the C# script. You can retrieve a specific component within a GameObject
by calling the method GetComponent<ComponentType>()
on a GameObject
.
C# is a language most similar to Java, supporting garbage collection. Unity uses it as its scripting language. You will not need to have an extensive knowledge of it as you will be using Unity's own library functions.
Having a good knowledge of Java or C++ will suffice to be able to write C# code, but if you are struggling, there are resources below that may be of help.