06.05.09

Module : Introduction to 3D Graphics – Part 1

Posted in Development Report - 3D Graphics Renderer at 22:31 by markcampbellprogrammer

This module was introduced in the first semester of the second year during my university course. The purpose of it was to learn about the fundamentals of 3D graphics at a foundational level and gain confidence using 3D APIs. The main focus of study was aimed at the practical and theoretical understanding of real time rendering and the role of the graphics pipeline.

Although I had been introduced to C++ in the first semester, this was the first time I was expected to use full object orientation using inheritance and understand how important its power is in complex programming. As well as the programming element, this module gave me an understanding of how to represent 3D rendering using mathematical techniques and equations. A lot of this module focused on understanding the maths first, then implementing what was learned week by week into the final project. 

The Project  

Each weekly task required me to learn the mathematical theory then implement that into a small program. As the semester progressed, I was then required to combine each weeks work into one big project being a 3D graphics renderer. The focus was on implementing a range of techniques and presenting them as a demo showing technical ability and personal style similar to that of the demo scene for rendering in the early 1990’s i.e. the pre –  hardware accelerated graphics era.

This was without a doubt going to be the most difficult project of my semester due to the volume of work and understanding of the theory behind it. I was excited and nervous at the same time about how the renderer would turn out as I felt that my understanding of programming at the time was not of a good enough standard and would require a lot of additional private study gain a better understanding. Although the programming and mathematical side of this module was important, understanding and getting a full grasp of how the rendering pipeline works and considering what order function calls and transformations are done in was the main objective. The rendering pipeline is ultimately the factory part of the program. It is feed all this data and then is forced to deal with it in constructive and logical way to produce the desired results. There are various considerations which I will discuss later that can affect the pipeline and make rendering slow and inefficient.

During the first few weeks the main focus was on getting a vector and matrix class written to express mathematical calculations used to describe transformations. Vectors and matrices have a wide range of uses in 3D rendering and although in graphics based programs such as OpenGL and DirectXyou can simply create a variable using the functionality within the libraries, we instead had to write our own including simpler mathematical methods such as addition, subtraction, multiplication and divide. However to make full use of our own written classes I also wrote methods such as dot and cross product for the Vector class, and Matrix based transforms such as transpose, transform and axis based rotations.

At this point everything seemed a little murky as the only way of testing what I had wrote was to write a console out method to test what I had done. From calling this method in main I was able to check manual if my methods was working correctly. For the time being I simply hard-coded 2 vectors and 2 matrices and worked out on paper if the answers i had matched that of my program. To be honest I didn’t do enough testing at this point as I should have as there was a problem with my matrix multiplication function which delayed progress later on which I should really have spotted at this point. Below are a code snippets from the Vector and Matrix classes -

Cross product from my Vector class

Vector Vector::CrossProduct(Vector v)

{

         float crossP_x = ((_y * v._z) – (_z * v._y));

         float crossP_y = ((_z * v._x) – (_x * v._z));

         float crossP_z = ((_x * v._y) – (_y * v._x));

         float crossP_w = ((_w * v._w) – (_w * v._w));

        // Returns new vector

        return Vector(crossP_x, crossP_y, crossP_z, crossP_y);

}

 Rotate X method from my matrix class

void Martrix :: RotateX(Matrix &resultMat, const float rotation)

{

          resultMat.m[1] [1] = cos(rotation);

          resultMat.m[2] [1] = -sin(rotation);

          resultMat.m[1] [2] = sin(rotation);

          resultMat.m[2] [2] = cos(rotation);

}

Constructors, Destructors, Static and Const

Using classes and header files in C++ was new to me and I had to quickly understand the difference between using them in C++ compared to C# which I had used in the first year. Using constructors and destructors was something I understood to a degree but didn’t understand the full usability of. Making use of a constructor is useful because multiple versions for the same class can be defined with different parameters to distinguish them. This was something I found useful by using assignment and copy constructors when creating instances of objects. Using parameterised constructors means that I can pass specific parameters to an objects base constructor when creating specific objects. Getting used to how these differ and each work individually  gave me more power and freedom when creating objects and gave me a nice introduction to object orientation.

Destructors are simply the matching partner to the constructor and just de-allocated memory when a class object passes out of scope or is explicitly deleted. It is always important to include these whenever a constructor is used and usually is where pointer variables are freed. Using the key word static simply means when declaring varaibles as being static, that varaible’s value is shared between each instance of each class i.e. it is passed down through different blocks of code. This was useful mainly due to the fact that it reduced the chance of values being changed without me wanting them to be. Const simply means that a variable is constant and therefore can’t be modified however it was a key word which I had had not encountered before and was unsure of how to use.

At this point my programming skills had been tested but I didn’t really understand the full picture of what it was I was doing. It wasn’t until I could see the effects of what I had written that I could really see what was going on and be able to look at ways to improve or comprehend what was actually being done by my code and why it was so important to make sure these calculations were correct.