Building shaders 'on the fly' - how?

Scali said:
1. How does the engine know a particular polygon or fragment belongs to a tree?

The engine will render the scene one object at a time (or actually one mesh at a time). Something like Draw( tree );
The tree object will contain all the polygons and some kind of description of the surface (texture, material properties etc).

2. Once it does know, and it needs to build some leaf shaders 'from scratch', how does it know the visual characteristics of foliage? Where does it get the info on ambient, diffusse and specular for example?

Those are stored in some way with each object, as stated before.
So there is some kind of 'recipe' from which the engine can dynamically create a shader.
For example, the object could contain a set of properties like this:
ambient: 0, 1, 1
diffuse: 1, 1, 1
specular: 0.5, 0.5, 1
shininess: 16
reflection: no
cast shadow: yes
texture: tree.jpg
bump: treebump.jpg

Then the engine has a list of active lights, and if you combine the two, you should know everything you want to know for your lighting model.

Thanks Scali, that makes sense now.
How much effects can a set of default ingredience generate? With just ambient, diffuse, specular, textures etc. one can get most surfaces, but what about water, gas or exotic materials? How would it' handle something like a Fresnel shader or subsurface scatter?
 
Well, I could think of a couple of ways.

One would be to build a completely custom shader. Another would be to simply write the shader code that performs the particular effect that isn't included in the shader library, and use the shader library to do the rest.

But the reality of the situation is that there just aren't that many shader effects you can apply, so it should be pretty easy for the programmers to have the most common effects pre-programmed for the artists. If this is coupled with an extension mechanism to easily add new options to the "recipe," then you'd have an excellent system for building any arbitrary shader.
 
There is at least one commericial real-time shader editor. Not cheap but for companies its probably better than writing your own.

http://www.rtzen.com/home/index,1.html

You make nodes and wire them up and it spits out a HLSL/GLSL/ASM shader. We've had a quick play seemed fairly good (but generated some invalid code in a complicated case).
 
Chalnoth said:
But the reality of the situation is that there just aren't that many shader effects you can apply, so it should be pretty easy for the programmers to have the most common effects pre-programmed for the artists.

I've read that HL2 has over a thousand shaders. I don't know what they could all be, since I can't even write down a thousand unique materials. But you're right, most things we encounter are the same few catagories;wood, metal, water, fire, smoke etc. And most are related to opaque materials like plastic, terrain, concrete, metal. I guess the reason why it's simple to generate shaders from limited paramters is that most things can be differentiated by just diffuse and specular.
 
Over a thousand shaders doesn't mean they all have unique code: they're probably just different combinations of a limited number of parts, as described above.

And by the way, you don't necessarily need a different shader for most of those things, as you can simply use textures to set different values for various variables (reflectance and such).
 
JF_Aidan_Pryde said:
I don't know what they could all be, since I can't even write down a thousand unique materials.

Let's think about a single lighting & material model.

It has the following properties:
- D: Diffuse color
- S: Specular color
- G: Glossiness (specular power)
- N: Surface normal (it is a little strange way of thinking about this, but it fits)
- O: Opacity

The following stuff is dynamically computed:
- L: light direction
- H: (light/view) halfway vector
- I: light intensity

The lighting model is:
output_color = D*I*(L dot N) + S*I*(H dot N)^G
output_alpha = O

Now how many shader is that?
First D, S, G, N, O can each come from a texture or can be constant - independently.
Then the light computation differs based on the light type - let's say we have directional, point and spot lights, the latter two can have no attenuation, 1/dist or 1/dist^2 attenuation.

That is 2^5 * (1+3+3) = 224 pixel shader combination

Oh, I forgot - you might have a shadow-buffer (or not).
You might have fog (various types).
You can have a self-illumination texture (or not).
You can have more fancy lights and/or textured light sources.

And if there's more room in the shader you can try to do multiple lights in the same pass. (= same shader)

So, if you think about it we are already talking about thousands of shaders.
 
We currently have 6427 shaders (dumped them today) created via a lua based meta shader system. Fragments are composed into full HLSL files via a lua powered meta-system.

We are currently changing our shader creation policy, as shader permutations are killing us.

Definately lots of work to be done...
 
One has to wonder if moving into the future branching won't just be a method to make developers' lives easier, but by drastically reducing the number of shaders in the game, it should become dramatically easier to optimize, too.
 
Chalnoth said:
One has to wonder if moving into the future branching won't just be a method to make developers' lives easier, but by drastically reducing the number of shaders in the game, it should become dramatically easier to optimize, too.

Of course it will.
That's the purpose of static branching, it helps reducing the shader combinations.

I wonder when we can say on the box; minumum hardware: PS3.0 capable card...
Until that time comes, our lives will remain as complicated as it is now.
 
Except static branches are simply unrolled at compile time, so I'm not sure that really helps the situation all that much. I was referring to dynamic branching.

Given the performance drop that I'm seeing from slightly modifying the interaction.vfp Doom 3 shader that is apparently highly optimized-for in nVidia's drivers, it seems to me that if performance can be improved that much by specifically modifying a shader like this, dynamic branching's performance hit may well be covered by the amount of optimization that becomes possible if just one shader is used for most surfaces.
 
Back
Top