normals getting displayed wrong

Started by
5 comments, last by jollyjeffers 17 years, 12 months ago
i didn't want to revive my old funky normals thread but i've got some new infos that may help to solve my problem. For those who haven't read my old thread: (I thought that!!)The problem is that my function for calculating the normals of my mesh doesn't work right. I first tested it with 2 cubes(both cubes in 1 Vertexbuffer) and the normals of the first cube were alright while the ones from the second cube weren't. For testing purpose i simply exported 2 seperated triangles lying on the x/z plane and all normals(for both triangles) were wrong. I tested if my code calculates the right normals and noticed that even in the vertex buffer the normals are correct(see screenshot below). But when i show the normals as colors with my pixelshader i get this: clicky but when i lock my buffer just before rendering and look at the memory inside the buffer everything looks fine:(the floats surrounded by the blue boxes are the normals) clicky and the vertex decl used is: clicky (also checked right before rendering with

	D3DVERTEXELEMENT9 decl[256];
	UINT numElements;
	HRESULT hr = vertexdecl->GetDeclaration( decl, &numElements);

) my rendering function looks like this:

void Draw(ngVertexBuffer *pvbuffer,ngIndexBuffer *pibuffer)
{
	ngEngine &engine=ngEngine::getInstance();
	
	int vertexsize=pvbuffer->getVertexsize();
	int triangleCount=pibuffer->getLength()/3;
	LPDIRECT3DVERTEXBUFFER9 vbuffer=pvbuffer->getD3DVBuffer();
	LPDIRECT3DINDEXBUFFER9 ibuffer=pibuffer->getD3DIBuffer();
	DWORD fvf=pvbuffer->getFVF(); //just switched 2 vertexdecls recently...
	DWORD vlength=pvbuffer->getLength();
	LPDIRECT3DVERTEXDECLARATION9 vertexdecl=pvbuffer->getVertexDecl();

	D3DVERTEXELEMENT9 decl[256];
	UINT numElements;
	HRESULT hr = vertexdecl->GetDeclaration( decl, &numElements);
	void *pOut;
	//vbuffer->Lock(0,0,&pOut,0);

	//engine.g_pD3DDevice->SetRenderState(D3DRS_FILLMODE,D3DFILL_SOLID);
	engine.g_pD3DDevice->SetVertexDeclaration(vertexdecl);
	//engine.g_pD3DDevice->SetFVF(fvf);
	engine.g_pD3DDevice->SetStreamSource(0,vbuffer,0,vertexsize);
	engine.g_pD3DDevice->SetIndices(ibuffer);
	engine.g_pD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,pvbuffer->getLength(),0,triangleCount);
}




All that looks quite correct to me. So maybe the error is in the shader:

float3 lightVector;
float4x4 matView : View;
float4x4 matProjection : Projection;
float4x4 matWorld : World;
float4x4 matWorldViewProjection : WorldViewProjection;

struct VS_INPUT 
{
   float3 Position : POSITION0;
   float2 uv : TEXCOORD0;
   float3 Normal : NORMAL0;
};

struct VS_OUTPUT 
{
   float3 normal : TEXCOORD1;
   float2 uv : TEXCOORD0;
   float4 Position : POSITION0;
   
};

struct PS_INPUT 
{
   float3 normal : TEXCOORD1;
   float2 uv : TEXCOORD0;
   float4 Position : POSITION0;
   
};


VS_OUTPUT Position_Pass_0_Vertex_Shader_vs_main( VS_INPUT Input )
{
   VS_OUTPUT Output;
   float4 n=mul(float4(Input.Normal,1.0f), matWorld);
   //Output.normal = float3(n.x, n.y, n.z);
   Output.uv=Input.uv;
   Output.normal = Input.Normal;
   Output.Position = mul(float4(Input.Position,1.0f), matWorldViewProjection);
   return( Output );
   
}

float4 Position_Pass_0_Pixel_Shader_ps_main(PS_INPUT Input) : COLOR0
{   	
   //float3 light=normalize(float3(1.0f,1.0f,1.0f));
   //return float4(1.0f,0.0f,0.0f,1.0f)*dot(normalize(normal),lightVector);
   return float4(Input.normal,1.0f);
}

//--------------------------------------------------------------//
// Technique Section for Position
//--------------------------------------------------------------//
technique Position
{
   pass Pass_0
   {
      PixelShader = compile ps_2_0 Position_Pass_0_Pixel_Shader_ps_main();
      VertexShader = compile vs_2_0 Position_Pass_0_Vertex_Shader_vs_main();
   }

}





hopefully somebody spots the problem. I really have no clue how that is possible. regards, m4gnus [Edited by - m4gnus on April 23, 2006 3:57:20 AM]
"There are 10 types of people in the world... those who understand binary and those who don't."
Advertisement
Normals are defined between [-1,+1], but the colour your emitting is [0,1] - so you're effectively chopping off half of your normal [smile]

Values in normal-maps have similar problems. It's usual to encode them using:

float3 Encoded = (Normal + 1.0f) / 2.0f;

and decode using:

float3 Decoded = (Normal * 2.0f) - 1.0f;

Therefore a (0,0,1) normal becomes RGB(128,128,255) and the opposite (0,0,-1) normal becomes RGB(128,128,0)...

hth
Jack

EDIT: changed "/" to "*"..

[Edited by - jollyjeffers on April 23, 2006 10:22:13 AM]

<hr align="left" width="25%" />
Jack Hoxley <small>[</small><small> Forum FAQ | Revised FAQ | MVP Profile | Developer Journal ]</small>

ok fixed that. Now it looks like this:
clicky
Sadly still wrong. The triangles should be all green.(theoretically, in fact the normal of the one triangle is (0,-1,0))

thx for reply

regards,
m4gnus
"There are 10 types of people in the world... those who understand binary and those who don't."
Your vertex declaration puts all components at offset 0, which is obviously wrong. When using FVF it was probably wrong because in an FVF the normal always comes before the UV coords in the structure.

What ends up happening is that the data you're reading as normals is some other data stored in the vertex.

are these offsets the offsets from the vertex start to a specific element? i thought they had somehting to do with the streams.
i think i fixed that now. i changed Offset=0; to Offset=(unsigned char*)pointerToVertexElement-(unsigned char*)vertexStart;
everything is right one tri is green and the other one purple(because it's normal points downwards)

Thank you very much guys.

regards,
m4gnus
"There are 10 types of people in the world... those who understand binary and those who don't."
Quote:Original post by jollyjeffers
Values in normal-maps have similar problems. It's usual to encode them using:

float3 Encoded = (Normal + 1.0f) / 2.0f;

and decode using:

float3 Decoded = (Normal / 2.0f) - 1.0f;


Don´t want to be nit-picky or anything, but I think it should be

float3 Decoded = (Normal * 2.0f) - 1.0f;

just wanted to mention that.
Quote:are these offsets the offsets from the vertex start to a specific element?
Yeah, a '0' offset is the start of each vertex..

Quote:Original post by matches81
Quote:Original post by jollyjeffers
Values in normal-maps have similar problems. It's usual to encode them using:

float3 Encoded = (Normal + 1.0f) / 2.0f;

and decode using:

float3 Decoded = (Normal / 2.0f) - 1.0f;


Don´t want to be nit-picky or anything, but I think it should be

float3 Decoded = (Normal * 2.0f) - 1.0f;

just wanted to mention that.
[embarrass] Looks like you got me there!

Thanks for pointing that out.

Jack

<hr align="left" width="25%" />
Jack Hoxley <small>[</small><small> Forum FAQ | Revised FAQ | MVP Profile | Developer Journal ]</small>

This topic is closed to new replies.

Advertisement