Jump to content
  • Advertisement
Sign in to follow this  
programmermattc

Select Shader Questions

This topic is 3660 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I've been working for shaders for around a year now but I've still got some pretty basic questions. 1) In my demo I've got my shader working (simple point light) and I pass in information such as WorldViewProj matrix, etc.... But to render models theres this Texture input it seems to take that I never specify and yet somehow it works, any idea how this texture is passed in? (I can post code later when I'm not at work!) 2) I've heard rendering more than one shader at a time is impossible or something? I've also heard you can create a shader manager for all shaders in a scene. For example, my shader file takes the world info and light info and places a single point light at that location. What if I wanted 4 lights in a hallway, would I have them all listed in the shader file or have multiple instances of that shader?

Share this post


Link to post
Share on other sites
Advertisement
Quote:

1) In my demo I've got my shader working (simple point light) and I pass in information such as WorldViewProj matrix, etc.... But to render models theres this Texture input it seems to take that I never specify and yet somehow it works, any idea how this texture is passed in? (I can post code later when I'm not at work!)

you may be using the IDirect3DDevice9::setTexture() function, which seemed to work for me when I was messing with HLSL. I seem to remember something like that happened in one of the demos I was making, and I used the wrong set texture(the D3DDevice one, and not the D3DXEffect one), and it still somehow worked. So that may be the cause, but I can't give an explanation why that works, other than possibly pure coincidence and luck, maybe it happened to send your texture data to where the effect shader was looking for it by chance?

Quote:

2) I've heard rendering more than one shader at a time is impossible or something? I've also heard you can create a shader manager for all shaders in a scene. For example, my shader file takes the world info and light info and places a single point light at that location. What if I wanted 4 lights in a hallway, would I have them all listed in the shader file or have multiple instances of that shader?


You do not need to make new effect files or change your effect files directly to add multiple lights or change the lights you have. The method I use is just to change the shader constants in the effect file. In fact, I only have one instance of any one effect file open in my engine at a time, I just change constants. So pseudocode might look like:


get Effect instance for a point light

begin shader

for each shader pass
{
begin shader pass
for each LIGHT
{
set LIGHT constants, light color, light position, light vec, etc

for each MESH
{
set MESH constants: worldviewproj matrix, texture data, material data etc

Make sure to ensure that the data did get to the shader via the
ID3DXEffect::CommitChanges()

draw the mesh
}
}
end shader pass
}
end shader



This is a fairly simple way to keep down changing constants without doing some serious stuff which I have not read up on yet. If you happen to have different kinds of lights(directional lights etc...) I'd just add an extra loop on the outside which loops through each different type of light. Thats basically the way I am doing it for now, I am certain there are faster ways of doing it but this works. I'm fairly new at this as well, but I do know you can just change out constants to reuse the same shader for your purposes. Changing constants is an expensive operation, however I think it is faster to change constants than to keep getting new shaders and call Begin and End all the time, but I am not sure about that. If anyone has any input about how I have this structured, as long as I'm here I'd love to know how better to structure it.

Share this post


Link to post
Share on other sites
Quote:
Original post by Lazerbeard
Quote:

1) In my demo I've got my shader working (simple point light) and I pass in information such as WorldViewProj matrix, etc.... But to render models theres this Texture input it seems to take that I never specify and yet somehow it works, any idea how this texture is passed in? (I can post code later when I'm not at work!)

you may be using the IDirect3DDevice9::setTexture() function, which seemed to work for me when I was messing with HLSL. I seem to remember something like that happened in one of the demos I was making, and I used the wrong set texture(the D3DDevice one, and not the D3DXEffect one), and it still somehow worked. So that may be the cause, but I can't give an explanation why that works, other than possibly pure coincidence and luck, maybe it happened to send your texture data to where the effect shader was looking for it by chance?


The way it works (in D3D9 anyway) is that HLSL samplers are bound to sampler registers, which have a 1:1 correspondence to the texture stages of a device. These registers are s0 through s16, and you can see those registers being used if you look at the disassembly for any pixel shader. If you're not using the effect framework then your HLSL sampler has to be explicitly bound to a sampler, which looks like this:


sampler2D DiffuseSampler : register( s0 );


In the effects framework however, you can use the "texture" type in your HLSL which adds another layer of convenience. These "texture" types are again bound to a sampler register, however the effects framework will take care of which texture is bound to which sampler register. Then when you call ID3DXEffect::SetTexture, the effect looks in its constant table for the register that name is bound to, and then sets the corresponding texture stage using IDirect3DDevice9::SetTexture.

So anyway if you have an effect with a single texture in it, chances are that texture will be bound to s0. So this means if you were to set a texture to sampler 0 using IDirect3DDevice9::SetTexture, the effect would use that texture no problem.

Share this post


Link to post
Share on other sites
I've been working with SceneManagers and ModelManagers lately. Could you have a manager that holds a single effect while having a list of instances of that effect? Then all you have to do is run through each instance (which accesses the effect data) before rendering the model? I think it's similar to your method although you wouldn't have to add another for loop for this one.

Share this post


Link to post
Share on other sites
Quote:
Original post by MJP
Quote:
Original post by Lazerbeard
Quote:

1) In my demo I've got my shader working (simple point light) and I pass in information such as WorldViewProj matrix, etc.... But to render models theres this Texture input it seems to take that I never specify and yet somehow it works, any idea how this texture is passed in? (I can post code later when I'm not at work!)

you may be using the IDirect3DDevice9::setTexture() function, which seemed to work for me when I was messing with HLSL. I seem to remember something like that happened in one of the demos I was making, and I used the wrong set texture(the D3DDevice one, and not the D3DXEffect one), and it still somehow worked. So that may be the cause, but I can't give an explanation why that works, other than possibly pure coincidence and luck, maybe it happened to send your texture data to where the effect shader was looking for it by chance?


The way it works (in D3D9 anyway) is that HLSL samplers are bound to sampler registers, which have a 1:1 correspondence to the texture stages of a device. These registers are s0 through s16, and you can see those registers being used if you look at the disassembly for any pixel shader. If you're not using the effect framework then your HLSL sampler has to be explicitly bound to a sampler, which looks like this:


sampler2D DiffuseSampler : register( s0 );


In the effects framework however, you can use the "texture" type in your HLSL which adds another layer of convenience. These "texture" types are again bound to a sampler register, however the effects framework will take care of which texture is bound to which sampler register. Then when you call ID3DXEffect::SetTexture, the effect looks in its constant table for the register that name is bound to, and then sets the corresponding texture stage using IDirect3DDevice9::SetTexture.

So anyway if you have an effect with a single texture in it, chances are that texture will be bound to s0. So this means if you were to set a texture to sampler 0 using IDirect3DDevice9::SetTexture, the effect would use that texture no problem.


So is it almost like the texture is being passed in indirectly? What it sounds like is the shader assumes theres a texture in that place and instead of the texture being passed in directly, it's being placed in that register and looked at? Am I close here?

Share this post


Link to post
Share on other sites
Quote:
Original post by programmermattc

So is it almost like the texture is being passed in indirectly? What it sounds like is the shader assumes theres a texture in that place and instead of the texture being passed in directly, it's being placed in that register and looked at? Am I close here?


Sorta...if you call IDirect3DDevice9::SetTexture you're actually setting the texture directly, and skipping the middleman (ID3DXEffect). The shader itself has no concept of "setting textures", it just reads from that sampler and expects something to be there. This is why ID3DXEffect has to call IDirect3DDevice9::SetTexture first before it sets up the shaders and you render your primitives.


Share this post


Link to post
Share on other sites
Quote:

Sorta...if you call IDirect3DDevice9::SetTexture you're actually setting the texture directly, and skipping the middleman (ID3DXEffect). The shader itself has no concept of "setting textures", it just reads from that sampler and expects something to be there. This is why ID3DXEffect has to call IDirect3DDevice9::SetTexture first before it sets up the shaders and you render your primitives.

Ah, thanks for the explanation, I thought that was how it worked, but I wasn't positive.


Quote:

I've been working with SceneManagers and ModelManagers lately. Could you have a manager that holds a single effect while having a list of instances of that effect? Then all you have to do is run through each instance (which accesses the effect data) before rendering the model? I think it's similar to your method although you wouldn't have to add another for loop for this one.


I am not entirely sure what you are asking here, are you asking if you could do something like:

LPD3DXEFFECT effect1;
LPD3DXEFFECT effect2;

begin effect1
begin effect2

set shader constants for effect 1
set shader constants for effect 2

draw geometry

end effect 2
end effect 1


I don't think you can do this. If you can I would like to know as this would be really interesting, but I have personally never seen anything which indicates that this is possible. If it is possible, I need to revise my engine :P, if not, you will need that extra loop to go through each one of the effects you are using on the geometry individually.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!