I'm designing Material/Shader System (target API DX10+ and may be OpenGL3+, now only DX10). I know, there was a lot of topics about this, but i can't find what i need.

I don't want to do some kind of compilation/parsing scripts in real-time.

So there some artist-created material, written at some analog of CG. After it compiled to hlsl code and after to final shader. Also there are some hard-coded ConstantBuffers, like

cbuffer EveryFrameChanging
    float4x4 matView;
    float time;
    float delta;

And shader use shared constant buffers to get parameters. For each mesh in the scene, getting needs and what it can give (normals, binormals etc.) and finding corresponding permutation of shader or calculating missing parts.

Also, during build calculating render states and the permutations or hash for this shader which later will be used for sorting or even giving the ID from 0 to ShaderCount w/o gaps to it for sorting.

FinalShader have only 1 technique and one pass. After it for each Mesh setting some shader and it's good to render.

some pseudo code

foreach (shader in FinalShaders)
    SetConstantBuffer(ConstantBuffer::PerShader, shader);
    foreach (mesh in shader.GetAllMeshes)
        SetConstantBuffer(ConstantBuffer::PerMesh, mesh); 

class FinalShader
    UUID m_ID;
    RenderState m_RenderState;
    CBufferBindings m_BufferBindings;

But i have no idea how to create this CG language and do i really need it? May be WYSIWYG editor?


I found interesting articles: Shader Designer and here DICE Frostbyte. I think it's good cause it's more easy to build then parsing custom language and more flexible cuz all graph elements are inherited from IBaseNode which have inputs, outputs, so cbuffer EveryFrameChanging is also IBaseNode with 0 inputs and 3 outputs. Maybe possible apply graph optimization theory to shaders. Any usefull links or advises?


1 Answer 1


This is a common thing where there is tons of different implementations.
I Will give you my approach, how i would implement this. ( according to your psudo code )

SetConstantBuffer( GlobalData ); <- this would be bound to the first register, so i always know that this one will be there.

For( unsigned int i = 0; i < m_Materials; ++i ) <- where this is a variable containing the amount of material we got in our "database"
SetConstantBuffer( MaterialSpecificData ) <- R1
SetRenderState( MaterialSpecificStates )
for( unsigned int u = 0; u < meshQueue[i].size(); ++i )

This point is all the same. But the main thing i would do is to have a loadtime collector, where you collect each mesh, find itś assigned material and from there store them correctly in the meshQueue, where meshqueue would be a vector vector, so you could store an array for each corresponding material.

For the shaders, I would have one main Include named something like, System.H or Materials.H which would hold the Registery0 where all the "per frame" stuff would be held. Also some neat helpers you might need.

From that point on, you could have a define or a integer saying what part of a shader to run. You could compile different part of the program with ifdef/ifndef. So if you would have a "Main" shader entry point, you could esily branch that one out to different branches by just having defines beeing defined before running. since the .h files wont get compiled you can change them on the fly with simple c++ code.

I hope this answers your question as you hoped.


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .