Sign in to follow this  
brekehan

Multiple Passes

Recommended Posts

brekehan    101
Where can I read the details on rendering using multiple passes? Where does the output of 1 pass go? Where does the next pass get its input? Can I change shader variables between passes? Is there some way I can use this to implement more than one light in my shader? Let's say I have a shader which implements one lambert type spot light just fine. Now, I want to render using 4 or 5 lights, but only handle one at a time in my shader variables. How do I use multiple passes to do such? I scanned the SDK ovewr and over. While it says you can render using multiple passes, it doesn't say anything about how, where inputs and outputs go, how one pass effects another etc.

Share this post


Link to post
Share on other sites
VizOne    598
Render the first light normally and use additive alpha blending to render each subsequent light over the previous ones.

First pass:
ALPHABLENDENABLE = false
Render objects with settings of first light

Each consecutive pass:
ALPHABLENDENABLE = true
SRCBLEND = one
DESTBLEND = one
Render objects with settings of respective light

Using this technique adds the effect of each light on top of the current scene. Of course using multiple light passes is not the fastest thing in the world as it requires all the vertex transforms, texture look ups etc. to be done multiple times.

Share this post


Link to post
Share on other sites
brekehan    101

Ok, that is along the lines of what I want to do.

Let's say pass one drew my cube, with 1 spotlight. It executed a vertex shader and a pixel shader, using a float3 lightDir variable.


So, now I want to make another pass and change my lightDir variable.
And I do what in my application's render method?


Now let's look at the shader code.
Pass 2 is getting its VS_INPUT from where?
It's PS_OUTPUT is going where?

Where am I to blend the output from pass 1 with the output of pass 2?
In a shader? In the application? How do I even get seperate output from the passes to blend and what form of data are they taking?

Where does the output of my first pass go? How do I give it to the second. How am I getting the one thing to blend with the other?




All I've done is a single pass.
I know my input comes from my vertex buffer and index buffer
I know I set my effect variables before making my draw call.
I know my output goes....??? to the screen?

Please describe the above 3 lines for the second pass.




Thanks for the help! I can't find anything on google or the SDK that _really_ describes multiple passes.

Share this post


Link to post
Share on other sites
KulSeran    3267
your output goes to the frame buffer.
swap out your shaders / variables.
change the blending mode as described above.
Re-Render your scene (your draw primitive calls).

You input is your vertex/index buffers.
You shared variables are whatever you set them to before your draw call.
Your output is the screen (added ontop of your previous pass)


You could change this a bit by setting a texture as the output of all your PixelShaders, and then render that texture to the screen.
But the base process is the same.

Share this post


Link to post
Share on other sites
brekehan    101
Quote:
Original post by VizOne
First pass:
ALPHABLENDENABLE = false
Render objects with settings of first light

Each consecutive pass:
ALPHABLENDENABLE = true
SRCBLEND = one
DESTBLEND = one
Render objects with settings of respective light


I see no where in the DirectX 10 SDK how to set these states. I follow what you are saying exactly in DX9, but I am using 10. The functions are simply not there anymore.

Nor is inforamtion on alpha blenidng included in the dx10 SDK.
Hell, they omitted everything except the "draw a triangle and spin it".

So umm, how exactly do you set this state in DX10?

Share this post


Link to post
Share on other sites
VizOne    598
Quote:
Original post by brekehan
I see no where in the DirectX 10 SDK how to set these states. I follow what you are saying exactly in DX9, but I am using 10. The functions are simply not there anymore.

Ah, you're using DX10, didn't realize that. Blending is described here:
Configuring Blending Functionality (Direct3D 10)

The good news is that the whole thing is probably easier than you think!

Here's some pseudo code


ID3D10BlendState* firstPassBlend;
ID3D10BlendState* secondPassBlend;

void Init(){
// prepare two blend states:
D3D10_BLEND_DESC firstPassBlendDesc;
ZeroMemory(&firstPassBlend, sizeof(D3D10_BLEND_DESC));
firstPassBlend.BlendEnable[0] = FALSE;
device->CreateBlendState(&firstPassBlendDesc, &firstPassBlend);

D3D10_BLEND_DESC secondPassBlendDesc;
ZeroMemory(&secondPassBlendDesc, sizeof(D3D10_BLEND_DESC));
secondPassBlendDesc.BlendEnable[0] = TRUE;
secondPassBlendDesc.SrcBlend = D3D10_BLEND_ONE;
secondPassBlendDesc.DescBlend = D3D10_BLEND_ONE;
secondPassBlendDesc.BlendOp = D3D10_BLEND_OP_ADD ;
device->CreateBlendState(&secondPassBlendDesc, &secondPassBlend);

}

void Render(){
set vertex shader
set pixel shader

foreach(light in lights){
if(is first light){
device->OMSetBlendState(firstPassBlend);
} else {
device->OMSetBlendState(secondPassBlend);
}

set pixel/vertex shader constant(light.Direction);

draw geometry
}
}





The point is: your shaders don't need to have a clue about whether they are rendering the first, second or sixteenth light. For each light you render the geometry completely the same way, except that you change the blend state to additional blending for any but the first light.

The results are accumulated into the render target.

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