Shader Builder

Assignment 08

This assignment was one of two assignments which were due this week. We had two weeks to complete the assignments and they were just serving as build ups for the biggest one yet (Assignment 10). This time we were cleaning up the Effect code, and building shaders during building rather than runtime. Visually the output looked the same as the last assignment. This was one of the easier assignments as we just had to replicate what we had done previously in MeshBuilder. Also, we had to integrate John-Paul’s code into tools, to build the shaders.

Effect Files

The human readable is designed to be simple and precise. It just contains two paths with the corresponding keys. I had the option to skip the keys, but it would mean that the order of the paths should be known. To avoid this ambiguity, I specified which path represents which shader. As for the prebuilt binary file, I decided to keep the null terminated strings, with storing the null terminator too. This is the simplest method, yet it does not make any compromises, and does not require any unnecessary extra data in the binary file.
To extract the paths, from the buffer of the file, I use the fact that the function strlen() finds the length till the null terminator. Hence it finds the length of the first string and then with that I can calculate the start of the second path.

return
{
	vertex = "data/vertex.shader",
	fragment = "data/fragment.shader",
}
							



Shader Builder

The second part of the assignment involved in creating a ShaderBuilder tool. We wanted to precompile the shaders to reduce the load while building. However, this is not completely true right now. This assignment, we just use a preprocessor to reduce the size of the shader file in OpenGL, and we convert the shader code into byte code for Direct3D. This was done by incorporating John-Paul’s code into ours, with a few changes.

Single or Multiple?

I decided to keep a single ShaderBuilder, instead of two slightly different builders. This choice was made to avoid any future work by doing some extra work in the present. Hence I created an enum, in Graphics, to specify whether it was a vertex shader or a fragment shader. However this posed a problem while passing arguments to the Builder exe. This was remedied by adding optional arguments to AssetsToBuild.lua file and accounting for them in BuildAssets.lua file as seen below.



Debug and Release

The interesting part of this builder is that it can build both debug and release shaders. The release shaders are relatively light weight than the debug counter parts. This change is toggled by using a preprocessor define. We could have done this by checking for the default debug macro _DEBUG. However by doing the previous method, allows us to have detached shader building from the debug or release build. We can now have release shaders in a debug build if we do not want to debug the shaders.

HLSL Shaders (Direct3D)

You can see the difference between the debug and release HLSL shaders. The debug file has definitely more data than the release one. It is because the debug file also stores all the comments and extra data related to at what location the file was built. This data is removed from the release version of the shader.

Debug

Release

GLSL Shaders (OpenGL)

The difference is more noticeable in the GLSL shaders, as they are in text files and not in binary form. All the comments in the debug file are removed and just the data required for the successful use of the shader remains in the code.

Debug

Release

This differentiation is done so that the (relatively) huge files are not used if we do not want to debug the shaders, even if we want to debug the application. This was the main aim for building the shaders beforehand.

Controls

Use the (Arrow keys) to move the rectangle mesh and press ESC to exit the game.

Time Estimate

Reading: 1 hour
Coding: 2 hours
Debugging: 0 hours
Writeup: 1 hour