Sign in to follow this  
all_names_taken

Problem with my shader when I add color indata

Recommended Posts

I'm making an HLSL shader to blend 4 textures with blend factors passed to the shader. It works fine as long as I don't mix in the blend factors. But when I add a DWORD color value entry for each vertex in the vertex buffer, no matter what I try I can't get the shaders to work properly. Is it not allowed to pass DWORD colors from application/vertex buffer to a shader? Do I have to pass the color from the application as 4 floats instead? The odd thing is, the example tutorial application I used as starting point seems to be using an FVF definition for the vertex buffer, which AFAIK doesn't allow storing colors as floats but only as DWORDs. Also are FVFs really supposed to be used in combination with shaders at all?! My question is how to pass a color quad from application and vertex buffer to the vertex shader. That color value should then be passed to the pixel shader where it would be used to determine the blend factors for the different textures. The code is something like this:
	// ... effectShader constants and technique set here ...

	// ... view and world matrices set up here ...

	UINT totalPasses;
	effectShader->Begin(&totalPasses, 0);
	for(UINT pass = 0; pass < totalPasses; pass++)
	{
		effectShader->BeginPass(pass);
		D3D_Device->SetStreamSource(0, Vertex_Buffer, 0, sizeof(Vertex));
		D3D_Device->SetFVF(D3DFVF_D3DVertex);
		D3D_Device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
		effectShader->EndPass();
	}



The FVF thing worked as long as there was only position and texture coordinate that was passed from the app to the shader via the vertex buffer... Here's the shader:
float4x4 worldViewProj : WorldViewProjection;

texture t1;
texture t2;
texture t3;
texture t4;

sampler Sampler1 = sampler_state
{
	Texture   = (t1);
	MipFilter = LINEAR;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
};
sampler Sampler2 = sampler_state
{
	Texture   = (t2);
	MipFilter = LINEAR;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
};
sampler Sampler3 = sampler_state
{
	Texture   = (t3);
	MipFilter = LINEAR;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
};
sampler Sampler4 = sampler_state
{
	Texture   = (t4);
	MipFilter = LINEAR;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
};

struct App_Input
{
	float3 vertexPos  : POSITION;
	float2 texture0   : TEXCOORD0;
};


struct Vs_Output
{
	float4 vertexPos  : POSITION;
	float2 texture0   : TEXCOORD0;
	float4 color      : COLOR0;
};

struct Ps_Output
{
	float4 color      : COLOR;
};

Vs_Output VertexShaderEffect(App_Input IN)
{
	Vs_Output vs_out;
	vs_out.vertexPos = mul(worldViewProj, float4(IN.vertexPos, 1));
	vs_out.color = float4(1.0, 1.0, 1.0, 1.0);
	vs_out.texture0 = IN.texture0;

	return vs_out;
}

Ps_Output PixelShaderEffect(float2 Tex : TEXCOORD0)
{
	Ps_Output ps_out;
	//temporary test where all textures are blended with the same factor
	ps_out.color = (tex2D(Sampler1, Tex.xy) + tex2D(Sampler2, Tex.xy) + tex2D(Sampler3, Tex.xy) + tex2D(Sampler4, Tex.xy)) / 4;

	return ps_out;
}

technique BlendFour
{
	pass Pass0
	{
		Lighting = FALSE;
		VertexShader = compile vs_2_0 VertexShaderEffect();
		PixelShader  = compile ps_2_0 PixelShaderEffect();
	}
}



Share this post


Link to post
Share on other sites

What kind of error/problem do you get ? Perhaps a screenshot or an error message. Could you show us your vertex structure and the FVF declaration ?

Yes, you are able to pass a dword to a shader.

Here is a simple vertex structure with dword color.

struct MYVERTEX
{
D3DXVECTOR3 p
DWORD colour;
}

#define MYVERTEX_FVF (D3DFVF_XYZ | D3DFVF_DIFFUSE)

Remarks:

- The order of the components inside the vertex structure is important. The DX SDK explain the correct ordering of elements inside a vertex structure.

- A dword color value is mapped to a range of [0..1] when it arrives to the vertex shader.

Share this post


Link to post
Share on other sites
The problem I get is that the texture coordinates seem to be misunderstood by the shader, so I get the quad I'm drawing drawn as if it's texture coordinates were (0.0, 0.0), (1.0, 0.0), (0.0, 0.0), (1.0, 0.0) or something like that... My guess is that when I add the color entry I get some kind of incorrect alignment when data is fetched for the last vertices, or something like that, because of an error either on the application side or in the receiving vertex buffer (the struct App_Input)... Anyway here's the vertex structure and FVF used in the application:

struct MYVERTEX {
D3DXVECTOR3 position;
D3DXVECTOR2 textureCoordinates;
DWORD color;
};

The FVF:
#define MYVERTEX_FVF (D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_DIFFUSE)

and order is correct according to MSDN...

Quote:

- A dword color value is mapped to a range of [0..1] when it arrives to the vertex shader.

Ok, so does it becomes a float4? Should modify my vertex shader input struct to:

struct App_Input
{
float3 vertexPos : POSITION;
float2 texture0 : TEXCOORD0;
float4 color : COLOR0;
};

The problem is that when I try this I still get the same strange rendering behavior... Is it incorrect to use a float4 for the color?

Also, for the other key part - moving this color info from vertex shader to pixel shader. Once I get the first part to work I know I need to edit the line in the vertex shader:
vs_out.color = float4(1.0, 1.0, 1.0, 1.0);

to
vs_out.color = IN.color;

But after that I don't know how to transfer it correctly to the pixel shader? Can I just add another input argument to the pixel shader, or do I somehow need to use semantics to match it to the earlier returned color value?

[Edited by - all_names_taken on June 7, 2006 6:24:17 AM]

Share this post


Link to post
Share on other sites
Yes,a dword converts nicely and automatically to a float4 (the byte order is a bit tricky if I remember correctly). Of course I also meant that the dword is considered to carry 4 byte values (which are converted to the 0..1 range).

So, practically you can just forward to color values to your pixel shader. There is no trouble with it. float4 is correct for transferring color values.

Your input structure looks ok too (you could use float4 for the position).


Humm ...

Quote:

vs_out.color = IN.color;


You'll use the same structure as vs_out as input to your pixel shader so after that line you have the color in your pixel shader already. Yes, it requires an input semantic, but it seems that you got that part already.

Oups, I missed the pixel shader input line. It should look something like this to get the whole structure in:

Ps_Output PixelShaderEffect(Vs_Output In)
{
...
}

Share this post


Link to post
Share on other sites
Edit: problem solved as soon as I switched to vertex declaration instead of FVF! Thanks for the help though, with so many errors at the same time as I did, I wouldn't have been able to solve the problem without the confirmation that the parts I did right but I was unsure about were right.

[Edited by - all_names_taken on June 7, 2006 9:49:54 AM]

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