Sign in to follow this  
Subotron

Materials & passes: material system design

Recommended Posts

I'm currently setting up a material system for my renderer to sort meshes by. After a lot of thought I have decided on a basic 'material design', but I have a few questions left. First, let me present my 'design':
material "name"
{
    pass 1 
    {
        state descriptions go here
    }
    pass 2
    {
        ....
    }
    etc
}

Now, when meshes are passed to the render queue, I want to divide the render queue based on material. So ultimately each material has its own render queue. This means I can do a minimal amount of state changes. I probably also need a comparison function to decide which materials are most similar and thus require the least state changes when switching materials. One thing I'm not sure about: should I divide the render queue even further, by pass instead of just by material (which may contain several passes)? I was thinking the "by pass"-method is better because different materials might share common passes. Inside each render queue, I sort the meshes by textures used, since texture changes are expensive, right? After all the sorting, the queues will be rendered, but again I'm not sure how to handle passes (kind of depends on if I seperate the render queue by pass or by material). Should I, for a given material queue, do all the passes at once before moving on to the next queue, or does it make more sense to first do one pass in each queue, then a second one where needed, etc? Also, is there a logical maximum number of needed passes? I don't think I ever saw more than 3 passes in one effect, but I'm not sure if I can assume this will always be the case. I hear a lot of people talk about pre- and post processing, I'm not entirely sure what those mean. My last issue: where (and how) is information stored that is both pass and mesh specific? For example, while vertex positions will not differ across passes for a single mesh, the texture coordinates might (consider a heightmap which uses repeating tile textures but also a stretched lightmap in a second pass). Should I store a texcoord buffer for each seperate pass in the mesh? At the moment it's all foggy in my head. I have no previous experience dealing with a material-based approach. I'm not even 100% sure what a material is, and if I'm using the idea correctly. I tried searching the forums for more information on material systems, but I didn't find much useful info. Most topics are all about shaders, and to be honest I'm not even at that step yet. I figured I first need a working material system, then I can start working on a system that assigns shaders to material passes automatically based on the material's properties.

Share this post


Link to post
Share on other sites
Quote:
Original post by Subotron
Inside each render queue, I sort the meshes by textures used, since texture changes are expensive, right?

From the threads here at GDnet, it seems me that nowadays shader switching is most expensive, below that comes texture switching.

I've not implemented such a material system yet, but what comes to my mind is that separating passes is possible if and only if no temporary results are overwritten due to the switching. E.g. if stencil or depth values are computed in a previous pass but used by a following pass, inserting a foreign pass may destroy things. That would need to introduce a hard criteria for pass sorting, wouldn't it?

Share this post


Link to post
Share on other sites
My situation is exactly the same; I'm just reimplementing my material system since my old solution didn't support multi-pass rendering or shaders.

In addition to materials and passes, I have techniques. They are different ways of implementing the same material, like different LOD levels, shader models or fixed function fallback. So each material consists of one or more techniques, which in turn have one or more passes.

Like you, I have two options for rendering, in pseudocode:

for each material:
switch to material
for each pass in material:
render all objects with the material

OR

for each material:
switch to material
for each object with material:
render all passes of the material

I guess the first option would be faster, since there are less state changes, but is it valid for all effects? Is there a situation where I want to render all the passes for each object, and only then move on to the next object?

Share this post


Link to post
Share on other sites
i havent tried implementing this yet, but after doing some searching, it seems like it will be the fastest way to render. take a look at your different shaders. how many of them are similar? my bet is you can make a generic diffuse shader, generic normal/parallax shader, etc. all you need to do is change out the textures which are attached. sort your scene by:


render by shader
render by diffuse texture
render each object


my guess is this will be the fastest way.

Share this post


Link to post
Share on other sites
I too think this is the fastest way to go, but as Selkrank mentioned, I'm not sure if you can work on a pass-first basis. Probably some effects require rendering all the passes directly after eachother, to prevent erasing stored data and invalidating results from earlier passes. However, if you work on an effect-first sorting method, you might end up with a whole lot of state changes because each mess will require several for each pass...

Share this post


Link to post
Share on other sites
one of the design considerations might be to only support one-pass effects. That means that the old DX8 hardware will have much less impressive effects, but makes the whole material system easier to handle. On ps_3_0 or ps_4_0 hardware one pass is enough anyway in most cases.
If more passes are required you can implement them with different techniques as well.

I described a material / meta-material system that was used in a couple of games in a ShaderX4 article. You can find a short version on my blog ...

Share this post


Link to post
Share on other sites
i read your blog about how mass effect renders its models. its essentially what i was talking about. i did forget about blending, and blurring. that could be the second run, render everything black, except for the textures that need to be blended or blurred. render that to a texture, and then blend that texture over the scene.

rendering everything black would help occlude particles and other transparent objects. am i missing anything?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this