Sign in to follow this  
_DarkWIng_

variable multipass shaders

Recommended Posts

Hi. I have material/shader implementation working in for most things, but there is one thing I just can't find elegant solution to. How do you create a shader that has variable number of passes. I have no trouble with shaders that use bouncing to other shaders but this is something different. Lets take PPL shader for example. And for simplicity let's say I can do 1 light in one pass and I want up to 4 lights per chunk. So I need to loop this shader 1-4 times or a no-light shader once, based on number of lights in area. I really can't find elegant solution to this. I've tried number of things but all end up breaking the whole shader system or end-up being major performance problem. I would really like to know how you guys handle this type of problems.

Share this post


Link to post
Share on other sites
One soulution could be to send to the shader the actual state,where it can find, for example, the first 4 light near.
With this approach,the shader take the decision if to render all in one pass or render with multiple pass or take only one light and skip the other three light.

Davide

Share this post


Link to post
Share on other sites
Took me a while to solve this too, however I think my shader system is quite different ( I went the script route rather than the plugin DLL route ). Anyway, this is what I do:

As an input to my shader script ( similar to an fx file, but not ), I have a variable array of light positions or vectors. I then define different paths to take ( to different cg programs - shaders in the classical sense ) depending on the hardware available and the number of lights. So, for instance, say you had 3 lights coming in. If the graphics card could cope with 2 lights per pass, the shader would have coded a path for 2 lights, and a path for one light. At runtime, the engine would split the render operation up into two parts, one renders two lights, one renders one, and adds them both to the render queue. So essentially I have a number of shaders that can each do a number of lights per pass, and I bounce around them to render however many I require.

I don't know how you'd do it in a plugin system, but with a script it's easy.

Share this post


Link to post
Share on other sites
davidino79: I don't have a problem how to select ligts and so on. I have a problem how to handle then in elegant maner.

Hi python_regious. I had similar system as one of possibilitys. So you create one shader chain (list of shaders) for each number of lights and select the right one each frame of what? Or do you select shader with max possible lights and somehow ignore the rest. In your example. You create shader for 3 lights: what happens if 2 of lights move out of range?

Could anyone else please explain how they handle this.

Share this post


Link to post
Share on other sites
What about having a part at the end of your shader that tells the engine what shader it should run next. This can be a reference to the shader for the next pass in the overall shader (could be the same shader again), or that the shader is finished. Also this ending part indicates what parameters to pass to the next shader, which could include the pass number. The pass number can be used to figure out when to finish the shader.

Share this post


Link to post
Share on other sites
Quote:
Original post by DudeMiester
What about having a part at the end of your shader that tells the engine what shader it should run next. This can be a reference to the shader for the next pass in the overall shader (could be the same shader again), or that the shader is finished. Also this ending part indicates what parameters to pass to the next shader, which could include the pass number. The pass number can be used to figure out when to finish the shader.


This wont work, shaders should be sorted to minimize state changes so going to a different shader like that is a bad idea. I use the same principals in my system as the thread but it is quite different in the implementation then what was proposed.

I have run into the problem you speak of and right now haven't implementated a solution, beside proxy shaders that do nothing and just act to chain others together. This is just for debugging.

What about just adding another function to the shader, GetCallBack() that would either return a bool for a call to be placed back to the shader or an integer that would tell you how many calls you need (just loop it then).

Anyway, very interested in hearing what you come up with to solve this problem

Share this post


Link to post
Share on other sites
Quote:
Original post by nts
What about just adding another function to the shader, GetCallBack() that would either return a bool for a call to be placed back to the shader or an integer that would tell you how many calls you need (just loop it then).

This is simmilar to the method that I have as my best option so far. Shader has a function that returns info how many times it needs to be looped. But the problem is that you have to disable blending for 1st pass and enable it for all the rest. And blending state switch is not very cheap as far as I can remember. I might just implement this and test it... probably tomorrow.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
I know of engines that simply use different shaders for different light counts (I think Source does this). Which is basically what was described above. Either pre-build shaders that do 1 light, 2 lights, ... up to some maximum. Or have a system to dynamically build the shaders based on the number of lights requested (with some caching, etc...). That last approach is becoming fairly common, I think - especially as it's not that hard to paste together HLSL or something similar at run-time and run it through the shader compiler/assembler.

Share this post


Link to post
Share on other sites
Quote:
Original post by _DarkWIng_
Quote:
Original post by nts
What about just adding another function to the shader, GetCallBack() that would either return a bool for a call to be placed back to the shader or an integer that would tell you how many calls you need (just loop it then).

This is simmilar to the method that I have as my best option so far. Shader has a function that returns info how many times it needs to be looped. But the problem is that you have to disable blending for 1st pass and enable it for all the rest. And blending state switch is not very cheap as far as I can remember. I might just implement this and test it... probably tomorrow.


I'm thinking of going this route aswell. My engine isn't as advanced yet and i'm not familiar with the cost associated with each state change (except that its best to minimize them :p) but what about implementing the shader as multipass then, with the first base shader and the rest of the blend passes in another i'm sure you though about this already too :)

Lemme know how it works for you, dunno when i'll have the time to implement it

Share this post


Link to post
Share on other sites
Quote:
Original post by _DarkWIng_
Hi python_regious. I had similar system as one of possibilitys. So you create one shader chain (list of shaders) for each number of lights and select the right one each frame of what? Or do you select shader with max possible lights and somehow ignore the rest. In your example. You create shader for 3 lights: what happens if 2 of lights move out of range?


If two lights moved out of range, then only the one-light-per-pass shader would be added to the render queue. If 5 lights were in range, then the 2 lights per pass shader would be added twice, and the 1 light per pass shader would be added once.

Share this post


Link to post
Share on other sites
Quote:
Original post by nts
Quote:
Original post by DudeMiester
What about having a part at the end of your shader that tells the engine what shader it should run next. This can be a reference to the shader for the next pass in the overall shader (could be the same shader again), or that the shader is finished. Also this ending part indicates what parameters to pass to the next shader, which could include the pass number. The pass number can be used to figure out when to finish the shader.


This wont work, shaders should be sorted to minimize state changes so going to a different shader like that is a bad idea. I use the same principals in my system as the thread but it is quite different in the implementation then what was proposed.


I don't see how that's a problem. Couldn't you simply, at the beginning of the frame, evaluate how many passes that shader will require, and then use that information to properly sort everything. You could also include a flag to indicate if the passes need to be executed consecutively or if they can be run in any order.

Share this post


Link to post
Share on other sites
I've implemented something that looks a bit like combination of both sides. I made shader that can handle 1 or 2 lights then I loop it for all lights on chunk. Performance is so-so. I know there are couple of places where I could improve performace a bit, but not as much as I would like. And the whole blend on, blend off still bothers me big time.

python_regious: I might try something like yours in future, but it needs a lot of work to get it running in my system.

Did anyone else implemented Yanns shader system?

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