Jump to content
  • Advertisement
Sign in to follow this  
magicstix

DX11 [DX 11] Scrambled vertex normals

This topic is 2564 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

Hi all,
I've been picking up DX11 and I've started working on a per pixel lighting shader. The shader appears to be working, but for whatever reason, my surface normals are getting scrambled.

In running the shader through pix and stepping through it, it seems my surface normal is being set to the vertex position. I've also noticed that the texture coordinate (which is currently unused and set to zero on the input) is also getting set to the vertex position's X and Y coordinates.

I've tried running the code on two different machines, one with an nvidia card that only supports DX10 (gtx 260) and one with an ati chip that supports DX11 (radeon 5450), and I'm seeing the same behavior, so I'm confident it isn't a driver issue.

Here's the relevant shader code:


cbuffer ConstantBuffer : register( b0 )
{
matrix World;
matrix View;
matrix Projection;
float4 vLightDir[2];
float4 vLightColor[2];
float4 vOutputColor;
}

struct VS_INPUT
{
float4 Pos : POSITION;
float2 Tex : TEXTURE;
float4 Col : COLOR;
float4 Norm : NORMAL;
};

struct PS_INPUT
{
float4 Pos : SV_POSITION;
float4 worldPos : WORLD_POSITION;
float2 Tex : TEXTURE;
float4 Col : COLOR;
float4 Norm : NORMAL;
float4 oldNorm : NORMAL1;

};

//--------------------------------------------------------------------------------------
// Vertex Shader
//--------------------------------------------------------------------------------------
PS_INPUT VS( VS_INPUT Pos )
{
PS_INPUT outPos = (PS_INPUT)0;
outPos.Pos = mul(Pos.Pos, World);
outPos.worldPos = mul(Pos.Pos, World);
outPos.Pos = mul( outPos.Pos, View);
outPos.Pos = mul( outPos.Pos, Projection);
outPos.Col = Pos.Col;
outPos.Tex = Pos.Tex;
outPos.Norm.xyz = normalize(mul(Pos.Norm.xyz, (float3x3)World));
outPos.Norm.w = 1.0;
outPos.oldNorm = normalize(Pos.Norm);
return outPos;

}

float dPLight(float3 lightPos, float3 pos3D, float3 normal)
{
float3 lightDir = normalize(pos3D - lightPos);
return dot(-lightDir, normal);
}

//--------------------------------------------------------------------------------------
// Pixel Shader
//--------------------------------------------------------------------------------------
float4 PS( PS_INPUT Pos ) : SV_Target
{

float4 newColor = float4(saturate(Pos.oldNorm));
//newColor *= saturate(dPLight(vLightDir[0].xyz, Pos.worldPos.xyz, Pos.Norm));
//newColor += 0.3;

return newColor; // Yellow, with Alpha = 1
}




And here's the C++ snippet i'm using to create the layout:


// Define the input layout
D3D11_INPUT_ELEMENT_DESC layout2[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXTURE", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT,0,0,D3D11_INPUT_PER_VERTEX_DATA,0},
{ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT,0,0,D3D11_INPUT_PER_VERTEX_DATA,0},

};
UINT numElements2 = ARRAYSIZE( layout2 );

// Create the input layout
hr = g_pd3dDevice->CreateInputLayout( layout2, numElements2, p3DSVSBlob->GetBufferPointer(),
p3DSVSBlob->GetBufferSize(), &g_p3DSVertexLayout );

//... Draw call later in the code...


stride = sizeof(Vertex_3DS);
g_pImmediateContext->IASetInputLayout( g_p3DSVertexLayout );
g_pImmediateContext->IASetVertexBuffers(0, 1, &g_pGroundVertexBuffer, &stride, &offset);
g_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
g_pImmediateContext->VSSetShader(g_p3DSVShader, NULL, 0);
g_pImmediateContext->PSSetShader(g_p3DSPShader, NULL,0);
g_pImmediateContext->VSSetConstantBuffers( 0, 1, &g_spConstantBuffer );
g_pImmediateContext->PSSetConstantBuffers(0,1, &g_spConstantBuffer);
g_pImmediateContext->Draw(4,0);




I originally noticed the problem in my 3ds file loader and thought I was calculating surface normals wrong, but I also created a 2 triangle ground quad with a single surface normal pointing straight up and found that it too was getting its surface normals set to the vertex position. I've verified in the local buffers before i call D3D11DEVICE::CreateBuffer, but somewhere along the way things are getting buggered up.

What am I doing wrong?

Share this post


Link to post
Share on other sites
Advertisement
You're not setting the element offset in your input layout description, which is the 5th member of the D3D11_INPUT_ELEMENT_DESC structure. This offset tells the input assembler how many bytes there are in each vertex before that particular element. So your TEXTURE element should have an offset of 12, since the POSITION element before it has 3 floats (and each float is 4 bytes). If you don't want to set the offset manually, you can set them all to D3D11_APPEND_ALIGNED_ELEMENT and it will work as long as the order if your input elements matches the order of the data in the actual vertex buffer.

Share this post


Link to post
Share on other sites
Hi,

as an addition to the previous post :

[color=#000000]outPos[color=#666600].[color=#000000]oldNorm [color=#666600]=[color=#000000] normalize[color=#666600]([color=#660066]Pos[color=#666600].[color=#660066]Norm[color=#666600]);

OldNorm and Norm are typed as float4 and you set Pos.Norm.w to 1.0, so normalizing float4 will result incorrect normal vector. You can use float3 for your normal vectors.

Cheers!

Share this post


Link to post
Share on other sites

You're not setting the element offset in your input layout description, which is the 5th member of the D3D11_INPUT_ELEMENT_DESC structure. This offset tells the input assembler how many bytes there are in each vertex before that particular element. So your TEXTURE element should have an offset of 12, since the POSITION element before it has 3 floats (and each float is 4 bytes). If you don't want to set the offset manually, you can set them all to D3D11_APPEND_ALIGNED_ELEMENT and it will work as long as the order if your input elements matches the order of the data in the actual vertex buffer.


Thanks! You win many internets. I should've caught that when I was comparing my layout to the d3d tutorials.... Copypasta syndrome, I guess. :/

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.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!