Shader Passes

Started by
7 comments, last by Ashkan 16 years, 1 month ago
Guys: I'm reworking my shader logic. Does this make sense: If you have a tree like this:

- Object A
   - Object B
   - Object C

Each object has the same shader "Shader A" lets say. That shader has two passes, would there ever be a reason you would do:

- Object A (pass 0)
   - Object B (pass 0)
   - Object C (pass 0)
THEN:
- Object A (pass 1)
   - Object B (pass 1)
   - Object C (pass 1)
??


Or is this the more traditional way:
- Object A (pass 0 & 1)
   - Object B (pass 0 & 1)
   - Object C (pass 0 & 1)

Thanks Jeff!
Advertisement
What are the most expensive state changes?


The order from most to least expensive is basically;


* Binding a Shader

* Binding a Texture

* Updating a GLSL texture sampler uniform

* VBO data pointers

* Everything else

taken from some gamedev.net faq
http://www.8ung.at/basiror/theironcross.html
Are you saying, it doesn't matter on the pass order? Just as long as its the same shader binded?

So if pass 0 was ShaderA & pass 1 was ShaderB... I should go

ObjectA (pass 0)
ObjectB (pass 0)
ObjectC (pass 0)
ObjectA (pass 1)
ObjectB (pass 1)
ObjectC (pass 1)

Does order matter in passes though?
What if pass 0 & pass 1 just had state changes, but the same shader, should I then go with

ObjectA (pass 0)
ObjectA (pass 1)
ObjectB (pass 0)
ObjectB (pass 1)
ObjectC (pass 0)
ObjectC (pass 1)

Thanks,
Jeff.
You should probably go with your first option, where you render all objects with pass 0, then render all objects with pass 1, etc. If one of your objects ends up being highly occluded, you don't want to spend time doing extra passes on those hidden pixels.
Just to add to Zipster's comment, there's also the possibility that pass 1 might require alpha blending, implying you should render that pass after all the opaque stuff (and sorted with all the alpha-blended stuff). I prefer to think of individual object/material passes as a completely separate object render, even if it's going to re-render the same geometry as from a previous/different pass.
Depending on how you designed your renderer you might have a geometry database or the equivalent. So in case you draw the same geometry twice it is actually cached in-between for multi-pass algorithms. This is how it was done 8 - 9 years ago when multi-pass approaches were on vogue on the available hardware.

So drawing and render states were cached and did not need to be updated for each pass.

Overall a shader sub-system is a rather trivial thing if you setup simple conventions like naming conventions and how you want artists to use it. In essence you want to have as less shader code as possible and shadow all constant data that is sent to the shaders. This way you can setup character drawing for example by first drawing the eyes of the 120 characters on screen, then the hair etc. without changing shaders.
Thanks for your responses.

I'm coming from a DX Effect framworks background, I want to get rid of that dependency and focus more on Vertex/Pixel shaders. So, lets say I have an effect with a simple two-pass blur (vertical pass/horizontal pass)... in the Effects system you would do this:
Render Scene  - Setup Effect (bind)     - Render BOX1 pass 0     - Render BOX1 pass 1     - Render BOX2 pass 0     - Render BOX2 pass 1//because code would be similar to this: (psuedo code)for( each pass in effect.passCount)  {  pass.Begin();  Draw( geomtry );  pass.End();  }


However, because now I have two seperate Vertex/Pixel Shaders for each pass my logic turns into this:

Render Scene  - Setup ShaderPass0 (bind)  - Render BOX1 pass 0  - Setup ShaderPass1 (bind)  - Render BOX1 pass 1  - Setup ShaderPass0 (bind)  - Render BOX2 pass 0  - Setup ShaderPass1 (bind)  - Render BOX2 pass 1


As you can see, more shader binds (which I don't want)... however, looking into sample engines online and browsing tutorials, everyone seems to do it like this:

Render Scene  - Draw Child     - Setup Shader        - loop through passes             - Draw Geometry


Which this way will incur more shader binds if each pass is it's own seperate shader. So my thinking is why do people do it that way... lazy?... Then I thought, well, are there multi-pass effects that require you to render pass 0, then pass 1 before moving to another peiece of geometry???

Can passes mean two different things? One being apart of an effect per object (2 passes for each object), and one being independent of eachother (2 passes, but can do 1 pass for all objects and pass 2 for all objects again)?

Thanks in advance,
Jeff.
probably cause they implement it with OO in mind

some render preprocess that optimizes your render passes would be a solution
but don t ask me about its speed

also think about rendering environment maps, this makes it even more tricky
http://www.8ung.at/basiror/theironcross.html
IMHO this, just like any other performance-related question is really hard to answer without some real world data to back it up with. At the end of the day, the best approach is to implement both methods and profile the results. That's not the fastest approach to get an answer to a performance-related question, neither is it the answer you expected to hear from us, but that definitely is your safest bet. You can't go very far with predictions. You see, the problem with such predictions is that varying parameters are just TOO many. The rendering pipeline is just too complex to be predictable to such extents. Sad but true.

This topic is closed to new replies.

Advertisement