In this assignment, we created a new class called Material and a new MaterialBuilder so that we can use same effect files with different color or alpha values (by using uniforms) without hard coding the values in the shader files. Now we can have two gameObjects in our game using same mesh, same effect files (shaders) but different materials, one BlueTransparentMaterial and another maybe GreenTransparentmaterial.
Just like all other assets, we created a human readable material file and used MaterialBuilder tool to build material binary fie which we can load and use at run time. Here is a example of my Transparent material lua file.
My human-readable material file contains the effect path and the UniformData in table format. UniformData consists of ‘name’ which is the name if the uniform variable, ‘value’ is the uniform variable’s value, ‘shaderType’ specifies the type of shader (vertex or fragment), the uniform variable is associated with. There can be more than one uniform variables, for example in Transparent.mat we have two color and alpha, while only one color in Standard.mat. That’s the reason why we used table to store UniformData. At run time, while loading the material, program will read the uniform name from this material structure and will get the appropriate handle which then we can use to control the associated shader property. As of now, we are just assigning the value taken from material structure (or lua file) to the uniform shader variable.
Our materialBuilder is responsible to generate the binary file from above mentioned material.lua file. Here is how my OpenGL Debug and DirectX Debug binary file looks like.
The first byte in red is the uniform set count. For Transparent.mat it is 2 in both OpenGl and DirectX. Followed by the effect path char array in green. Note the 00 byte at the end terminating the string. After the effect path, I am storing my material struct array (blue and orange). In OpenGL version the GLint is of 4 byte but in DirectX version, the uniform handle is of type const char pointer (D3DXHANDLE) which takes 8 bytes since our DirectX build is for 64-bit architecture. That’s why our material structure in OpenGL is of total 28 bytes, while in DirecctX it is 32 bytes.
Other than uniformHandle, we have an enumerator ShaderType of 4 byte, float array of size 4 so 4X4=16 byte and 1 byte unit8_t for number of values. In OpenGl it takes total of 25 bytes, the rest is padding, making it 28 bytes. In DirectX, its 29 bytes (4 more than opengl) + 3 byte padding making it total of 32 bytes. We can see the padded bits and the uninitialized bits as CD CD CD… in our binary file. In first material striucture (blue), after 3 floats the forth float is CD CD CD, since its uninitialized (color takes only 3 floats). In our second structure (orange), only first index of float array is initialized and the rest three are CD CD… that means uninitialized, since we need only one float for storing alpha value.
Also, I tried to use the 4 byte in OpenGL and 8 byte in DirectX version that we allocated for uniformHandle to store the offset for name char array. We can do that because we don’t need the uniform handle while building the project. At run time, the offset values at uniformHandle will be replaced by the actual handles. As you can see, the first byte of my first material struct (blue) is 40, which is the offset for the uniform name stored after the struct array. In this case its g_color. For second struct (orange) the value is 48, which is pointing to the string g_alpha. By doing this we used some of teh space that we anyway have allocated for uniform handles and also, we dont have to do strlen() while loading the binary file since we already know the offset to them.
There is no difference in Debug and Release version of binary file for any platform, except for the CD CD uninitialized bits are replace with zero.
Controls for my project are: WASD to move the Camera. Arrow keys to move the helix object.
Click here to download DirectX version
Click here to download OpenGL version