Lab hints and tips
1) Do selective unit testing. Don't implement a lot of code and then expect it all to work. If it doesn't (likelihood: it won't ...;-) how will you locate the error? Divide and conquer.
2) Use a pen and paper to solve problem subsets first. Try to work a math problem out on paper first, or manually simulate how an algorithm works for a simple situation. If you sit down and try to code straight away, you are trying to solve multiple difficult issues at once. First solve and understand the model/math using pen and paper. Then solve the programming issues. Especially, if you solve the programming issues in the sense that your program compiles, you will still need to think deeply about the algorithm if your rendering has errors in it.
3) Be critical of instructions and attempt to understand equations. Trying to directly implement equations without understanding what they do or their relationship to the overall algorithm will guarantee many hours of wasted time in the labs and the real world.
For some, the most difficult initial aspect of the labs is getting the programming environment up and running with the skeleton code. The large number of various operating systems, development environments and versions make it difficult to provide a single solution. The following details may therefore be helpful for setting the labs up on your particular configuration:
A quick tutorial on Ubuntu system can be found here.
Windows and Microsoft Visual Studio
A useful guide can be found here by previous DH2323 student Victor Dahlin on conducting a setup in Microsoft Visual Studio 2013. Fangkai has a newer version that runs on Visual Studio 2013 (VS2013) and which can be found here. Note that in order to easily enable cout output to the console, you may need to set the project to be a console application in the properties menu.
VS2015 (or higher)
For the students using VS2015, you may encounter the problems as posted in the News feed. The reason is in Visual Studio 2015, stdin, stderr, stdout are defined differently. The lib files downloaded from SDL homepage were compiled in VS version lower than VS2015. We recompiled the SDL lib files for VS2015 (download here), which you should use instead of those in the original download. Henrik Dahlberg made a template for VS2015 for those who want to use SDL2.0. SDL2 GLM VS15 Template and SDL2-2.0.4. Place the folder in the second link directly under C:\ and it should work.
For students using cmake to generate project, new lab1 source code should be used (for the following labs, you could modify CMakeLists file). The only change is the CMakeLists file where 'find_package' is not used considering the installation of SDL in Windows is a bit rusty. Fangkai tested it on VS2017 using the new compiled SDL libs.
Installing SDL on Mac OSX:
In order to get some of the lab code working with Mac OS, you will need to use SDL 2.0 rather than SDL 1.2. Here's example code for how to do this (also includes instructions for Linux): https://github.com/lemonad/DH2323-Skeleton
MacOS (with XCode)
Update (2020 March 24): The old setup seems to be deprecated in the latest XCode and Mac OSX. Jonas Nockert have uploaded a template using SDL 2.0, it was tested to be working on the new Mac OSX 10.14+.
MacOS (without XCode)
Tutorial on setting up SDL2 on your Mac without XCode:
Previous DH2323 student Mikael Hedin recommends the following:
Install fink (http://www.finkproject.org/)
fink install sdl
Include in your Makefile: CXXFLAGS=$(shell sdl-config --libs) $(shell sdl-config --cflags)
General hints and tips
Lab 3 Rasterisation (lab track 1)
There are some misprints in the Lab 3 documentation (not difficult to spot, hopefully...):
1. Eqn. (3) and (4) on page 2 should refer to W/2 instead of W2 and H/2 instead of H2, respectively.
2. In section 5 on page 11, it repeatedly mentions the inverse "1=z" - it should be "1/z"
3. On page 14, the reflectance element of the Vertex struct should be represented a vec3 and not vec2 as printed.
Issues with triangle borders (or gaps) being drawn may relate to missing out the drawing of pixels in one of the loops related to triangle filling operations. Check the starting and finishing conditions of those loops.
On page 14, the Light power of 1.1f * vec3(1,1,1) is not enough to give clear illumination. Try the value from the previous lab of 14.1f * vec3(1,1,1), especially if you are not getting good results for the illumination questions at the end of the lab.
Per vertex illumination is implemented in the vertex shader using eq. 10 and 11. The normal vectors of vertices are identical to those of triangles in this scene.
Perspective correct interpolation (last section of lab 3)
Per pixel illumination involves 3D position stored in the pixel structure. Do not interpolate the original 3D positions linearly, interpolate the transformed position (which is multiplied by inverse z value).
More detailed explanation:
Since a 2D point (x, y) in the screen space image is derived by x = fX/Z+W2; y = fY/Z+H2; (the perspective view), the interpolated points in the 2D screen space image change linearly with 1/z. For example, consider a triangle edge AB in world-space, with A(Xa, Ya, Za), B(Xb,Yb,Zb) and the equivalent perspective projected edge in screen space ab, with a(xa, ya), b(xb, yb). If we create linearly interpolated points between A and B in 3D world-space and then project them into the 2D screen space, the results will not be linear. This creates distortion in terms of lighting and so on.
Therefore, we should do a linear interpolation on the 2D screen space between a and b first. We then use these 2D interpolated points to reconstruct 3D interpolated points in 3D space.
The solution to this involves finding a variable in 2D screen space which changes linearly. Given x = fX/Z+W2 and y = fY/Z+H2, the variable 1/Z changes linearly. This is because x and y change linearly and (x, y) is the linear combination of 1/Z in 2D screen space. 1/Z should then be inverted to obtain Z in the 3D position.
In code, that translates to:
1) The illumination and position vectors of the Pixel struct should be multiplied by 1/Z in VertexShader to be interpolated correctly.
2) The values are then restored in the DrawPolygonRows function (by being divided by the zinverse)
before being sent to PixelShader.
More detailed descriptions of the problem and derivation of the solution is available here:
You should try to understand the problem, although deriving the solution is a lot more involved. You do not need to fully understand the derivation of the solution in order to implement, although it is good to understand.
Be careful of the following:
Accidentally converting floats to integers: Make sure your floats are being evaluated as such, and not being converted to integers. E.g. be careful of using "zinv = 1/vtx.z" instead of the correct "zinv = 1.0f/vtx.z"
If you are having segmentation fauls, you need to implement some form of bounds checking i.e. if it is possible for a vertex of a triangle be placed outside of the view, it would access the depth buffer out of bounds resulting in a segmentation fault.