Need help with Pixel shader

Started by
4 comments, last by MJP 15 years ago
As far as my understanding goes theres a couple ways to upload data to the shader. 1: The constant table, 2: fx files. I've tried to use the constant table before with little success :( I want to upload a float2 for an extra set of UVs, And I dont want to declare another UV in the FVF (if thats even possible). What is the best way to upload a float2 to the shader decoupled from the actual vertex? [Edited by - VprMatrix89 on March 27, 2009 9:24:28 PM]
Advertisement
let me get this straight. You want to upload an extra pair of UV coordinates per vertex, but dont want to change the FVF or vertex declaration? That is of course not possible. You need to declare a second UV in there and make sure this is uploaded to the graphics card along with the rest of the model data.
I suppose you could have them in a texture, a buffer or whatever, but what's wrong with having it with the vertex data?
The only way, is to upload to a texture, and access the texture, with the vertex id-s. But that's slower than adding it to the vertex declaration, and requires shader model 3.0 compatible hardware (vertex textures).

shaken, not stirred

The only solution I thought of is to use a texture or something and use the original uv coords to detect which vertex is being drawn since apparently, you can't use an iteration variable in the shader. The only reason I think its possible is because I'm assuming that the verts are shaded in order from the VB. (left to right). I suppose it would be easier to just to add another UV to the vertex as has been mentioned.
Thank you
Here let me explain how shader constants work. Depending on the vertex shader or pixel shader profile you're using (vs_2_0, ps_3_0, etc.) you have a fixed amount of constant registers you can use. These registers each can hold a 4-component vector, just like every other register type in shader assembly.

If you're using assembly, you just access these registers directly. However in HLSL you don't deal directly with registers. Instead, what happens when you declare a shader constant it gets mapped to a constant register. Typically they'll just get mapped in order, so let's say you have this at the top of your HLSL:
float4 someVector;float4 someOtherVector;

Typically someVector will get mapped to c0, and someOtherVector will get mapped to c1. If you want, you can even explictly specify which register you want the constant bound to:
float4 someVector : register (c4);float4 someOtherVector : register (c9);

If your constant is a type that reguires more than one vector, like a float4x4, it will get mapped to consecutive registers. So in the case of a float4x4 matrix, it will get mapped to 4 adjacent registers.

These register numbers come into play when your app needs to set the value of these constant registers. The functions for doing this are IDirect3DDevice9::SetVertexShaderConstantF, and IDirect3DDevice9::SetPixelShaderConstantF. With these functions you specify the index of the constant register you want to set, the values, and how many registers you're setting.

Now, let's move on to constant tables. A constant table is very simple: all it is is a map of named handles to constant registers. This lets your app specify the string name of a shader constant (like "someVector"), and the table figures out which constant register it needs to set and then sets it with SetVertexShaderConstant or SetPixelShaderConstant. Pretty simple.

Effect's work similarly. They also maintain a table mapping named handles to effect parameters. An effect parameter is usually a shader constant, but it might not be. It could also be a texture that gets bound to a sampler, or even a variable that control how many anisotropic samples to take in a sampler declaration. Effect's also don't set shader constants as soon as you specify a value for them. They will cache the set value internally, and set them either when you call ID3DXEffect::Begin, or when you call ID3DXEffect::BeginPass. This is because an Effect can have multiple sets of shaders, and doesn't know which shader to set the constant for until you've specified a technique and pass.

Now the important thing about shader constants is that they're constant! When you call DrawPrimitives, the values set for your vertex shader is the same for all vertices. Same goes for your pixel shader. This means it cannot change in the middle of drawing something. This generally makes it insuitable for per-vertex and per-pixel data.

However it is possible to use them for per-vertex data. Vertex shaders have the ability to look up a shader constant by index. So this means you could set an array of shader constants, put an index in your vertex buffer for each vertex, and then use that index to look up the value of a shader constant. This is often used for skinning, or for instancing. However it will require you to modify your vertex declaration, and your vertex buffer.

This topic is closed to new replies.

Advertisement