Normally you only hear about various graphical effect problems and issues regarding 3D engines. In this log I want to highlight a few other problem many 3D engine builder face, but you do not hear about as much.
Managing multiple shaders files
In HPL1 there I used a bunch of shader files, one for each specific effect I wanted to do. No specular – new shader, new light type – new shader and so on. Even though HPL1 does not have that many shader combinations I ended up with 10 or so shaders that did about the same thing with various smaller changes. This was not so hard at the start, but when I wanted to optimize it was very frustrating to have to update 10 files all the time and some optimization became a bit hackish or simply left out. There where also times when I wanted to add even more shaders to optimize for specific hardware but I just didn’t have the energy to mange even more shaders, so I skipped it.
In HPL2 I am using a a custom preprocessing system that can parses the shader file before it is sent of to compilation and in that preprocessing step it is determine what different features the current shader should have. For example:
Code: (Select All)
@ifdef UseSpecular
outColor = color + pow(specularComp, shinyness);
@endif
By using this I can have very few shaders and still have plenty of variation. This helps keeping the code optimized and a lot more maintainable! The reson for having a custom system is that I wanted it to be usable on different types of shaders (GLSL, CG and HLSL (if a dx version is made).
Managing combinations of shaders
Now that I have a simple way to loading various shader types I must have some good way of maintaining them. I started out by simply loading the shader “by hand”, writing a line for each shader combo needed, however this turned out to be a bad idea since the number of combinations grows very quickly.
I am now working on a system where I use bit-flags to determine what variables are needed to be set before loading a shader and then loading it correctly. However this becomes even more complicated since I need both a vertex and fragment shader in each shader combination, and the vertex shader is often not changed as much as the fragment one, so I need a system that only creates a new shader when needed. This is problem is actually still work in progress but hopefully solved fully the coming couple of days.
Managing different types of shaders
In HPL1 I used only CG for shaders, but since it is developed by Nvidia it does not function good on ATI cards on some occasions. This made me switch to GLSL, OpenGL’s own language, instead. I still wanted to have Cg though, since I never know if it will come in handy.
The problem with this is that Cg and GLSL function quite differently in many aspects. In CG you set vertex and fragment shaders independantly however in GLSL you need to link vertex and fragment together before you can use that combination – resulting in a program. In GLSL variables for a shader is set in this program, but in Cg they are directly in the shaders. And so on…
All these differences required me to think about the design and since I hade never coded in GLSL before starting the design I looked very carefully in specs and tutorials. However, I was not careful enough. Once all of the code was in and I was happy with how it worked, it turns out I need to explicitly set how textures are connected to a shaders in GLSL, something I had not taken into account when designing and this broke all design. Luckily I came up with the idea of setting up textures inside the actual shader using the preprocessor and this turned out to work great.
There you have a little taste on the types of problems I face on a daily basis Smile I am afraid there is no demo for this, but hopefully I have the renderer in a working condition soon and will then provide a work log with demo. For now I just leave you with a little teaser screen, giving hints on the method of rendering I have chosen Wink