Using more than 1 pixel shader when drawing a texture

Started by
4 comments, last by MJP 13 years, 6 months ago
Hey guys I'm new here and pretty much a noob at directX and pixel shaders in general.
I was able to make 2 pixel shaders that do some effects I want to a texture.

Now my question is if there is a way to run both these shaders, one after another, so that the second pixel shader performs its modifications on the output of the first pixel shader.

My draw routine looks like:
d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, 0xff000000, 0.0f, 0);d3ddev->BeginScene();d3ddev->SetPixelShader(ps);d3ddev->SetTexture(0, texture);d3ddev->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);d3ddev->EndScene();d3ddev->Present(NULL, NULL, NULL, NULL);


As you can see, I am able to set my pixel shader before drawing the texture; but how can i use 2 pixel shaders? Is this possible?

Thanks in advance.

p.s. Using directX9 and c++...
Advertisement
I don't now how to do it pure, but if you use the ID3DXEffect interface, there's a set of methods for doing multiple passes. Basically, you draw your geometry once using the first pass, then you draw your geometry again using the second pass, with the result of the first pass as the new input. When you're defining your pixel shader, you create another pass and define the next shader function to use as you did with the primary pass.

See:
http://msdn.microsoft.com/en-us/library/bb205788(VS.85).aspx

Let me know if you're still confused. I'm pretty tired and probably didn't explain that too well.
Your other option is to combine the two existing shaders into a 3rd shader that does both effects. That will probably be quicker than doing it in two passes, and more flexible too.
You can't have 2 pixel shaders active at once, and there's no automatic way to combine them. So this basically leaves you with 3 options. I'll rank them from most ideal, to least ideal:

1. Manually combine both pixel shaders into a single shader

2. If the results of the two shaders are combined using a simple arithmetic operation (such as adding), then you can use blend states to combine the results of two passes

3. Render the first pass to a render target texture, then sample that texture with your second pass
Thanks for your comments guys.

I can't just combine the 2 shaders into 1 shader because my app has multiple shaders for filters and effects that will be selectable through its configuration screen.
So it could be the user chooses to use just 1 shader, or 2 shaders, or 0 shaders.

Well I suppose this might be possible with a giant shader and using some global boolean values. I haven't experimented with using variables between c++ and shader code yet. Although i think having all the different code in 1 big shader will be messy.


I think the most ideal solution is MJP's 3rd choice, "3. Render the first pass to a render target texture, then sample that texture with your second pass".
A friend of mine also said this is what I need to do if i want to support multiple shaders.

p.s. In case you're curious on what I'm doing, I'm writing some shaders for my NES emulator project. I have pixel shaders that do pixel-scaling algorithms like Scale3x and Eagle2x. But i also have shaders like a scanline shader which mimics scanline effects from an old TV.
So the reason for my post is that the user might want to select the Scale3x shader but also use the Scanline shader. Thus I was hoping directX had some simple way to do this.
Anyways thanks for the help, I'll post again if I have anymore problems/questions.
Well the problem with writing out to a render target is that you waste bandwidth writing out the data, and then sucking it back into the shader. If you do the combination all in the shader, that doesn't happen. So it's a trade off between performance and shader management complexity.

The core D3D9 API doesn't include any sort of shader management, it just has methods for loading and running precompiled shader data. However the effects framework in D3DX does include a lot of shader management functionality. If you wanted to start using that, it has some features to make the task of compiling shader permutations easier. Or a lot of big engines have their own systems for handling shader permutations, but that's certainly overkill in your case. For you the performance probably isn't a big deal...I really doubt an emulator is going to stress even a weak GPU. So you're probably fine going with #3 and keeping your code clean.

This topic is closed to new replies.

Advertisement