Sign in to follow this  
Daave

Mixing Shader and Fixed Functionality (.fx)

Recommended Posts

I'm currently trying to multitexture using a pixel shader (.fx) and it works fine, until I render anything in addition to the multitextured plane using SetTexture on the device. The way it works now I have 3 textures (which get applied to the plane based on the plane's vertex colors), those textures were getting passed to the shader using... effect->SetTexture(handle, tex); Then, in the shader I would have... texture g_MultiTex1; sampler MultiTex1Sampler - sampler_state { Texture = <MultiTex1>; }; for each texture. I also can get it working by having just... sampler MultiTex1Sampler; sampler MultiTex2Sampler; sampler MultiTex3Sampler; In the shader, and calling... device->SetTexture(0-1-2, tex); Either way, when another object being rendered calls device->SetTexture(0, tex) it completely screws up my shader, even though I'm setting my own texture every frame right before the rendering through the shader. What happens is all 3 textures show up as (0,0,0,0) when rendered alone, but when added together they show 2 out of the 3 correctly added together. Is there something I should know about the interaction of having some fixed function rendering and some stuff rendered through a shader? And, what are the ways to pass textures to a shader, just the 2 I've tried above?

Share this post


Link to post
Share on other sites
Shaders and fixed function use the same texture bindings for sampling textures. When you declare a sampler in HLSL, it's bound to a special sampler register. These registers, named s0-s15 (in ps_2_0 and ps_3_0, at least) directly correspond to texture stage states. So calling IDirect3DDevice9::SetTexture and specifying a texture stage of 0 will bind the texture to s0, and so on.

Typically samplers will get bound to sampler registers in the order they're declared in the HLSL. This is why your "MultiTex1Sampler" and so on are getting bound to s0, s1, and s2 respectively. You can explicitly bind a sampler to a register like this:

sampler2D texSampler : register(s0);


Now when you're using the effects framework, things get a little different. Typically with effects the whole sampler register thing will be hidden behind a layer of abstraction, by declaring the "texture" type. What happens is a "texture" is bound to a sampler register, and when you call ID3DXBaseEffect::SetTexture the Effect looks up what register that texture corresponds to in a table and then calls IDirect3DDevice9::SetTexture with the corresponding texture stage. What this means is that in the end everything boils down to a call to IDirect3DDevice9::SetTexture, which means setting textures using that will affect the textures set by calling the methods of ID3DXEffect.

Share this post


Link to post
Share on other sites
Thanks, using register(s2), register(s3), and register(s4) fixed my problem. I only wonder now what the point of being able to define...

texture something;

...in a shader is. I mean, wouldn't you only ever do samplers? (and then device->SetTexture(register, texture))

Share this post


Link to post
Share on other sites
The point of defining a texture is so that samplers are bound to a name, and not a number. This isn't such a big deal with simple shaders, where you know ahead of time what textures are needed and what register they should be bound to. However for more complex material systems things can get significantly more complicated. It's not always feasible or practical to know the exact order your samplers are declared in without being able to discover that information at runtime.

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