Skip to main content
GameDev.net gamedev.net
🔒 Locked

Only TEXCOORD0 works?

Started by mossmoss Feb 14, 2006 at 4:47 PM 12 replies 6.2k views
Original Post
mossmoss
mossmoss
My current task is to get some basic shaders written for our engine. This is the first time I've been working on shaders; I have a general understanding of how they work, setup, etc... but I've been hitting some specific problems. Basic setup: DX9 engine, using HLSL (but not Effects), compiling primarily for vs_2_0 and ps_2_0, though may use that and 3.0 going ahead. My current problem is that of per-pixel lighting and normal interpolation. (May be changed in the future for normal maps, but need to get the basics done first.) Here is the code:

float4x4 g_Model;
float4x4 g_ModelViewProj;

struct VS_INPUT
{
   float4 localPos  : POSITION;
   float3 localNorm : NORMAL;
   float2 uv        : TEXCOORD0;
   float4 diffuse   : COLOR0;
};

struct VS_OUTPUT
{
   float4 projPos   : POSITION;
   float4 diffuse   : COLOR0;
   float2 uv        : TEXCOORD0;
   float3 worldNorm : TEXCOORD1;
};

VS_OUTPUT vshader(VS_INPUT I)
{
   VS_OUTPUT O;
   O.projPos   = mul(I.localPos,  g_ModelViewProj);
   O.worldNorm = mul(I.localNorm, (float3x3) g_Model);
   O.diffuse   = I.diffuse;
   O.uv        = I.uv;
   return O;
}

float4 pshader(VS_OUTPUT I): COLOR
{
   // just a sample light direction (towards light) for testing
   float3 light = normalize(float3(1.0, -0.2, 0.5));
   return I.diffuse * saturate(dot(light, normalize(I.worldNorm)));
}
This is dead-simple per-pixel lighting. But it doesn't work, unless I change VS_OUTPUT to this:

struct VS_OUTPUT
{
   float4 projPos   : POSITION;
   float4 diffuse   : COLOR0;
   float2 uv        : TEXCOORD1;
   float3 worldNorm : TEXCOORD0;
};
The only difference is that I swapped the texcoord indices for uv and worldNorm. Then my per-pixel lighting and normals look fine. Likewise, I had some basic code working to sample a texture with the uv. That stopped working when I output the uv's to TEXCOORD1 instead of TEXCOORD0. So offhand, this doesn't seem like a shader issue, but more of a render/texture/sampler state issue. But I have no idea at this point what state is preventing TEXCOORD1 (or higher?) from being useful. Please, any hints, suggestions? Thanks...
JoeyBlow2
JoeyBlow2
The code looks fine to me.

I do nearly the exact thing. I have my UV's first as a float2 with TEXCOORD0, and normals as well in TEXCOORD1 as float3. It works fine for me.

What is your vertex declaration going into the Vertex Shader as input?

It should match the struct found in the shader:

struct VS_INPUT
{
float4 localPos : POSITION;
float3 localNorm : NORMAL;
float2 uv : TEXCOORD0;
float4 diffuse : COLOR0;
};

Are you sure you aren't creating the vertex declaration with the uv/localNorm reversed? That could cause some strange results which might explain the funny business you are seeing.
mossmoss
mossmoss
I had the uv/diffuse switched compared to the literal ordering in my C++ vertex declaration, but as far as I knew, that didn't matter for stream verts (as opposed to FVF verts). Similarly, my C++ decl specifies a float3 for position, but DX extends that to a float4 (assigning 1 to w) if I recall correctly.

In any case, I tried making it match the C++ vert declaration exactly with no difference in output.

Looking in the manual, I see D3DDECLUSAGE_TEXCOORD takes a number specifying how many (?) coords it takes, but that's vertex input and AFAIK shouldn't have any bearing on data passed from vertex shader to pixel shader.

Even looking at the asm of both shaders (compiled to asm using fxc /Cc) looks correct.
mossmoss
mossmoss
On a whim, I checked all of the TEXCOORDn. They all work except when n==1. Strange. There must be some state somewhere I've goofed. In any case, at least I can do some shader work and figure out why 1 is broken later.
devronious
devronious
Are you trying to send a float3 into a float2 register? Texcoords or float2 aren't they. Try passing the normal thru a different register. Just an idea tp try.

-Devin
mossmoss
mossmoss
Quote:
Original post by devronious
Are you trying to send a float3 into a float2 register? Texcoords or float2 aren't they. Try passing the normal thru a different register. Just an idea tp try.


TEXCOORDs can handle float4.

As indicated, this works just fine through all texcoord channels except 1.
devronious
devronious
Have you tried it on another video card to see if your register is damaged?
mossmoss
mossmoss
Quote:
Original post by devronious
Have you tried it on another video card to see if your register is damaged?


Damaged registers? Is that something reasonably possible?

I will be trying this stuff on another machine soon... I could see if TEXCOORD1 works there while not on mine, I suppose.
devronious
devronious
Anythings possible as for as damaged hardware. Although, like you, I would not jump to conclusions before testing on another video card.
superpig
superpig
Such a specific kind of damage is unreasonably unlikely. It's the sort of thing that would only happen if someone from the hardware vendor with full access to the chip schematics opened up your machine and attacked it with a microscopic drill...

I'd recommend recording a PIX capture and then examining the device state at the time the shader is used. There might be a particular state set on that texture stage that is causing behaviour such as clamping to the 0..1 range, and PIX would let you explore that.
Richard "Superpig" Fine - saving pigs from untimely fates - Microsoft DirectX MVP 2006/2007/2008/2009
"Shaders are not meant to do everything. Of course you can try to use it for everything, but it's like playing football using cabbage." - MickeyMouse
mossmoss
mossmoss
Rockin' idea, superpig.
I had forgotten about PIX; good idea to fire that up.
devronious
devronious
Superpig,

Perhaps I'm preaching to the choir here. On the micro level of the devices these days, not all micorscopic semiconductor elemts are functional from manufacturing. In fact screening is usually done. Chips with malfunctioning vertex or pixel units are often used in downgraded version of the GPU family. The manufacturer disables the malfunctioning units permanently so they can still get value from the chip.

Beyond that, semiconductor elements that will fail, typcially fail within the first two weeks of operation. It's a well known manufacturing fact that elemts will and do fail.

And, of course, I'm not saying that's what happened here.
Dirk Mittler
Dirk Mittler
You might find that my ideas are rather poorly informed or so. Even though I'm not currently working on any project, I'm curious enough to try to learn how the subject of 3D graphics works - in all its gory detail. And quite by coincidence I stumbled upon this posting, which might have died by now, but which I'd like to post an observation about.

Please tell me whether this idea is at least plausible.

Many moons ago, I had read somewhere that a hardware constraint which had existed with DirectX 9 graphics cards, was that it's assumed that vertex and fragment shaders ran on separate 'pipelines' or 'processors', and that one limitation of the fragment shaders was, that only 'Texture Coordinate Index 0' could be modified arbitrarily, i.e. on a per-fragment basis. I had thought that this was also a reason why in the old Fixed-Function Pipeline, computing a camera-space reflection vector output the coordinates to Index 0 specifically.

But an invention which came along only later, was that of a "unified shader", where the vertex and fragment source-code was compiled to run as one program, and on one core. Please correct me if I'm wrong.

My observation is that the low-level code of a unified shader would be running under the same HW constraints, as those imposed by whatever fragment shader cores exist in fact.

Is it possible that for some reason your shaders, which seem to be hard-coded by the looks of them, have ended up being compiled by a higher OpenGL version, to run as a unified shader anyway, let's say because the drivers see that your shaders only use two coordinate indexes? Could this be a failure on the part of the shader compiling, to recognize that one of your versions can be compiled that way, while the other should not be?

Because to me it looks like just a bit more than a mere coincidence, that "only index zero works", as if your vertex shader was running like a fragment shader...
Dirk Mittler
Dirk Mittler
I'm sorry. It looks as though I've made a mistake in my assumptions. I had not looked up the exact definition of "Unified Shader Model", because I had not realized it could be misunderstood.

From what I just read on the WiKi, only the instruction set is actually unified. Hence, even though the cores are interchangeable, the vertex and fragment shaders would still be running each on at least one separate core.

Also, I just read back at the beginning of this post, that mossmoss had explicitly constrained the shader to Vertex and Pixel Shaders 2. Because Unified Shader Model requires hardware Shader 3 support, this should shut off any attempt by the compiler to use it.

My oversight.

Dirk

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.