D3DXCompileShader cannot compile shader with NORMAL in it - directx

I noticed that the D3DXCompileShader function from the Ogre library fails in case of DirectX9 because of the following reason:
error X4502: invalid vs_2_0 output semantic 'NORMAL'
Seems pretty strange to me because MSDN states that it should be supported starting from the DirectX 9:
The following types of semantics are supported in both Direct3D 9 and Direct3D 10 and later
Here's my hlsl file:
float4x4 worldViewProj;
float4 lightPosition;
float3 eyePosition;
struct VS_OUTPUT
{
float4 pos: POSITION;
float4 normal: NORMAL;
float4 color: COLOR;
float4 lightPosition: TEXCOORD0;
float3 eyePosition: TEXCOORD1;
float3 pos3d: TEXCOORD2;
};
VS_OUTPUT main(
float4 pos: POSITION,
float4 normal: NORMAL,
float4 color: COLOR
)
{
VS_OUTPUT Out;
Out.pos = mul(worldViewProj, pos);
Out.pos3d = pos.xyz;
Out.normal = normal;
Out.color = color;
Out.lightPosition = lightPosition;
Out.eyePosition = eyePosition;
return Out;
}

The link you provided clearly states that NORMAL semantics is only supported as VS input.
You may try to pass the normal(s) to the pixel shader using TEXCOORD (TEXCOORD3 for instance) instead.

Related

metal shader: pass color encoded as 4 bytes INTEGER instead of 8 Bytes FLOAT

I need to send color encoded as in 4 bytes RGBA channel in INTEGER (not float) to my metal shader, but I don't know if metal shader can handle color stored in INTEGER. Actually I translate it in the shader to float4 (don't even know if it's not better to use half4 instead) color but I don't know if it's a good way:
struct VertexIn {
packed_float3 pos;
packed_uchar4 color;
};
struct VertexOut {
float4 pos [[position]];
float4 color;
};
vertex VertexOut vertexShader(const device VertexIn *vertexArray [[buffer(0)]],
const unsigned int vid [[vertex_id]]){
VertexIn in = vertexArray[vid];
VertexOut out;
out.color = float4(float(in.color[2])/255,float(in.color[1])/255,float(in.color[0])/255,float(in.color[3])/255);
out.pos = float4(in.pos.x, in.pos.y, in.pos.z, 1);
return out;
}
fragment float4 fragmentShader(VertexOut interpolated [[stage_in]]){
return interpolated.color;
}

Pass an array to HLSL vertex shader as an argument?

I need to pass an array to my vertex shader as an argument in Direct3D. The signature of the shader function looks like the following:
ReturnDataType main(float3 QuadPos : POSITION0, float4 OffsetArray[4] : COLOR0)
Is the signature OK? How do I define input layout description?
Thanks in Advance.
From HLSL references page, The function arguments only support intrinsic type, and user-defined type, the user-defined type also rely on intrinsic type, which does not support native array type, vector type or struct type might be your choice.
here is an example to use struct, you can simply build up a struct and pass in it as below like VS_INPUT.
//--------------------------------------------------------------------------------------
// Input / Output structures
//--------------------------------------------------------------------------------------
struct VS_INPUT
{
float4 vPosition : POSITION;
float3 vNormal : NORMAL;
float2 vTexcoord : TEXCOORD0;
};
struct VS_OUTPUT
{
float3 vNormal : NORMAL;
float2 vTexcoord : TEXCOORD0;
float4 vPosition : SV_POSITION;
};
//--------------------------------------------------------------------------------------
// Vertex Shader
//--------------------------------------------------------------------------------------
VS_OUTPUT VSMain( VS_INPUT Input )
{
VS_OUTPUT Output;
Output.vPosition = mul( Input.vPosition, g_mWorldViewProjection );
Output.vNormal = mul( Input.vNormal, (float3x3)g_mWorld );
Output.vTexcoord = Input.vTexcoord;
return Output;
}

How to pass textures to DirectX 9 pixel shader?

I have pixel shader
// fxc.exe tiles.fs /T ps_3_0 /Fotiles.fsc /Fctiles.fsl
struct PSInput
{
float4 Pos : TEXCOORD0;
float3 Normal : TEXCOORD1;
float2 TexcoordUV : TEXCOORD2;
float2 TexcoordST : TEXCOORD3;
};
sampler2D sampler0; //uniform
sampler2D sampler1; //uniform
sampler2D sampler2; //uniform
sampler2D sampler3; //uniform
sampler2D alphamap1;//uniform
sampler2D alphamap2;//uniform
sampler2D alphamap3;//uniform
uniform int tex_count = 0;
uniform float4 color_ambient = float4(0.75, 0.75, 0.75, 1.0);
uniform float4 color_diffuse = float4(0.25, 0.25, 0.25, 1.0);
uniform float4 color_specular = float4(1.0, 1.0, 1.0, 1.0);
uniform float shininess = 77.0f;
uniform float3 light_position = float3(12.0f, 32.0f, 560.0f);
float4 main(PSInput In) : COLOR
{
float3 light_direction = normalize(light_position - (float3)In.Pos);
float3 normal = normalize(In.Normal);
float3 half_vector = normalize(light_direction + normalize((float3)In.Pos));
float diffuse = max(0.0, dot(normal, light_direction));
float specular = pow(max(0.0, dot(In.Normal, half_vector)), shininess);
float4 color = tex2D(sampler0, In.TexcoordUV);
if (tex_count > 0){
float4 temp = tex2D(sampler1, In.TexcoordUV);
float4 amap = tex2D(alphamap1, In.TexcoordST);
color = lerp(color, temp, amap.a);
}
if (tex_count > 1){
float4 temp = tex2D(sampler2, In.TexcoordUV);
float4 amap = tex2D(alphamap2, In.TexcoordST);
color = lerp(color, temp, amap.a);
}
if (tex_count > 2){
float4 temp = tex2D(sampler3, In.TexcoordUV);
float4 amap = tex2D(alphamap3, In.TexcoordST);
color = lerp(color, temp, amap.a);
}
color = color * color_ambient + diffuse * color_diffuse + specular * color_specular;
return color;
}
vertex shader
// fxc.exe tiles.vs /T vs_3_0 /Fotiles.vsc /Fctiles.vsl
struct VSInput
{
float3 Pos : POSITION;
float3 Normal : NORMAL;
float2 TexcoordUV : TEXCOORD0;
float2 TexcoordST : TEXCOORD1;
};
struct PSInput
{
float4 Pos : POSITION;
float3 Normal : TEXCOORD0;
float2 TexcoordUV : TEXCOORD1;
float2 TexcoordST : TEXCOORD2;
};
uniform matrix modelMatrix;
uniform matrix projectionMatrix;
uniform matrix lookAtMatrix;
PSInput main(VSInput In)
{
PSInput Out = (PSInput) 0;
//projectionMatrix * lookAtMatrix * modelMatrix;
matrix MVP = mul(modelMatrix, lookAtMatrix);
MVP = mul(MVP, projectionMatrix);
Out.Normal = mul(In.Normal, (float3x3)modelMatrix);
Out.Pos = mul(float4(In.Pos, 1.0), MVP);
Out.TexcoordUV = In.TexcoordUV;
Out.TexcoordST = In.TexcoordST;
return Out;
}
same works under OpenGL + GLSL except mix replaced by lerp (I hope its correct).
By example from http://www.two-kings.de/tutorials/dxgraphics/dxgraphics18.html I passing textures with:
ps_pConstantTable.SetInt(m_pD3DDevice, texCountHandle, 0);
for i := 0 to texCount - 1 do begin
tBlp := texture_buf[cx, cy][i];
if tBlp = nil then
break;
m_pD3DDevice.SetTexture(i, tBlp.itex);
ps_pConstantTable.SetInt(m_pD3DDevice, texCountHandle, i);
if i > 0 then begin
// this time, use blending:
m_pD3DDevice.SetTexture(i + 3, AlphaMaps[cx, cy][i]);
end;
end;
so ordinal textures have indices 0-3 and alpha 4-6 (max texCount 4).
The problem is: I can see mesh (terrain) but it is solid black. Am I need something else to set (without shaders it also was black until I assigned materials and light)? Can I pass textures like that? Can I do this with sampler2D as uniform (how)?
Edit: example with sources, shaders, several used textures and alphamaps, vertex data with normals at filebeam http://fbe.am/nm4 added. As small as possible. Also contains DXErr9ab.dll to log errors.
To use texture in pixel shader, you may following below steps
Create texture in your C/C++ file by D3DXCreateTextureFromFile or other functions.
if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice, "FaceTexture.jpg",
&g_pTexture ) ) )
return E_FAIL;
Declare a D3DXHANDLE and associate it with the texture in your shader file.(you should compile your effect file before this step, effects_ here is a pointer to ID3DXEffect)
texture_handle = effects->GetParameterByName(0, "FaceTexture");
Set the texture in render function
effects_->SetTexture(texture_handle, g_pTexture);
Declare a texture in your shader file
texture FaceTexture;
Declare a sampler in your shader file
// Face texture sampler
sampler FaceTextureSampler = sampler_state
{
Texture = <FaceTexture>;
MipFilter = LINEAR;
MinFilter = LINEAR;
MagFilter = LINEAR;
};
Do sampling in your pixel shader function
float4 BasicPS(OutputVS outputVS) : COLOR
{
float4 Output;
Output = FaceTexture.Sample(FaceTextureSampler, outputVS.texUV);
return Output;
}
If you have DirectX SDK installed, I recommend you to take a look at the sample "BasicHLSL" which has a very basic introduction of Vertex shader and Pixel shader(including texture).

HLSL invalid ps_2_0 input semantic POSITION0

I'm attempting to write a phong shader effect for Dx9 in RenderMonkey.
I'm getting a compile error in the pixel shader
*"invalid ps_2_0 input semantic 'POSITION0'"*
and I'm not sure how to fix it, although I know it's got to be something to do with the POSITION0 semantic in VS_OUTPUT.
I tried changing VS_OUTPUT's Pos semantic to TEXCOORD0, but then the system reports that
vertex shader must minimally write all four components of POSITION
Shaders are supplied below. Any suggestions?
Here's my vertex shader:
struct VS_INPUT
{
float4 Pos : POSITION0;
float3 Normal : NORMAL0;
};
struct VS_OUTPUT
{
float4 Pos : POSITION0;
float3 Normal : TEXCOORD0;
};
VS_OUTPUT vs_main( VS_INPUT Input )
{
VS_OUTPUT Output;
Output.Pos = Input.Pos;
Output.Normal = Input.Normal;
return Output;
}
and my pixel shader:
float4x4 matViewProjection;
// light source
float4 lightPos;
float4 Ambient;
float4 Diffuse;
float4 Specular;
// material reflection properties
float4 Ke;
float4 Ka;
float4 Kd;
float4 Ks;
float nSpecular;
// eye
float4 eyePosition;
struct VS_OUTPUT
{
float4 Pos : POSITION0;
float3 Normal : TEXCOORD0;
};
float4 ps_main( VS_OUTPUT vsOutput ) : COLOR0
{
vsOutput.Pos = mul( vsOutput.Pos, matViewProjection );
float3 ViewDirection = normalize( eyePosition.xyz - vsOutput.Pos.xyz );
float3 LightDirection = normalize( lightPos.xyz - vsOutput.Pos.xyz );
float3 N = normalize( vsOutput.Normal );
float3 R = reflect( -LightDirection, N );
float LdotN = max( 0.0, dot( LightDirection, N ) );
float VdotR = max( 0.0, dot( ViewDirection, R ) );
// find colour components
float4 a = Ka * Ambient;
float4 d = Kd * Diffuse * LdotN;
float4 s = Ks * Specular * pow( VdotR, nSpecular );
float4 FragColour = Ke + a + d + s;
return FragColour;
}
Okay, I found a solution for those interested.
The Vertex Shader should have the following structs defined:
struct VS_INPUT
{
float4 Pos : POSITION0;
float3 Normal : NORMAL0;
};
struct VS_OUTPUT
{
float4 Pos : POSITION0;
float4 PosOut : TEXCOORD0;
float3 Normal : TEXCOORD1;
};
The VS_OUTPUT struct should be different in the pixel shader:
struct VS_OUTPUT
{
float4 PosOut : TEXCOORD0;
float3 Normal : TEXCOORD1;
};
My problem stemmed from the fact that you can't have a POSITION semantic as input to the pixel shader. At least for ps_2_0.
As user, one is not allowed to use the value of POSITION0 of the VertexShaderOutput in the PixelShaderFunction. This attribute seems to be cut off at some point between Vertex and Pixel Shader.
Instead you need to declare another attribute in the VertexshaderOutput, e.g.,
float4 newPosition : TEXCOORD1;
which you assign the same value as POSITION0. This new attribute, you may use ist in the PixelShaderfunction.

HLSL point sprite texture coordinates work on ATI not NVIDIA

I am really stuck on this one. My HLSL for rendering point sprites with texture coordinates for a sprite sheet works fine on all ATI cards but not on any NVIDIA cards. On NVIDIA cards the passed texture coordinates map to the whole sprite sheet rather than a portion of it. Strange but it works fine on ATI cards. Am I missing something unique to ATI cards?
Here is my shader
struct VS_INPUT
{
float4 Position : POSITION;
float4 Color : COLOR;
float4 Texture : TEXCOORD0;
//float1 Psize : PSIZE0;
};
struct VS_OUTPUT
{
float4 Position : POSITION;
float4 Color : COLOR;
float2 Texture : TEXCOORD0;
float2 Texture_zw : TEXCOORD1;
float1 Psize : PSIZE;
};
float4x4 WorldViewProj;
texture Tex <string name = "sprite_coin_test.dds";>;
sampler2D s_2D;
float offset_x=0.0;
float offset_y=0.0;
sampler S0 = sampler_state
{
Texture = (Tex);
MinFilter = ANISOTROPIC; //LINEAR;
MagFilter = ANISOTROPIC; //LINEAR;
MipFilter = LINEAR;
};
VS_OUTPUT vs_main( in VS_INPUT In )
{
VS_OUTPUT Out=(VS_OUTPUT)0; //create an output vertex
Out.Position = mul(In.Position, WorldViewProj); //apply vertex transformation
Out.Texture = In.Texture;
Out.Texture_zw = float2(In.Texture.z, In.Texture.w);
Out.Color = In.Color;
//Out.Psize = In.Psize;
Out.Psize=(Out.Position.z)*10.0;
return Out; //return output vertex
}
float4 PS_Particle_main(float2 vPos: TEXCOORD0, float2 text_zw: TEXCOORD1) : COLOR
{
vPos.x*=offset_x;
vPos.y*=offset_y;
vPos += float2(text_zw[0], text_zw[1]);
return tex2D(s_2D, vPos);
}
technique RenderVS
{
pass p0
{
AlphaBlendEnable = true;
AlphaTestEnable = false;
SrcBlend = SRCALPHA;
DestBlend = INVSRCALPHA;
POINTSPRITEENABLE = true;
POINTSCALEENABLE = true;
POINTSIZE_MIN = 1.0f;
POINTSIZE_MAX = 400.0f;
POINTSCALE_A = 1.0f;
POINTSCALE_B = 1.0f;
POINTSCALE_C = 1.0f;
ZWRITEENABLE = false;
Sampler[0] = (S0);
VertexShader = compile vs_1_1 vs_main();
PixelShader = compile ps_2_0 PS_Particle_main();
}
}
I had the same problem for a while and it costed me a lot of time. I have not found any documentation about this problematic, but with testing on ATI and NVIDIA devices I found the difference. With pointsprites ATI works all fine, it interpolates the texturecoordinates properly into TEXCOORD0. In contrast NVIDIA does nearly the same, but they write the texturecoordinates in all fields with a TEXCOORD-interpolator. So all information which you pass by texturecoordinates to the pixelshader will be overwritten. I solved this by using a COLOR-interpolator instead of a TEXCOORD-interpolator. Very strange, but it works fine for me :) In your case it would be:
struct VS_OUTPUT
{
float4 Position : POSITION;
float4 Color : COLOR0;
float2 Texture : TEXCOORD0;
float2 Texture_zw : COLOR1;
float1 Psize : PSIZE;
};

Resources