lighting problem...

Started by
1 comment, last by Cytorrak 19 years, 7 months ago
Hi, I'm trying to get a model lit, but it isn't working. The following pic shows the model in two phases of its rotation, one appears black, the other affected by the light... i guess: this is what I'm doing:

void SetupLights()
{
    D3DMATERIAL9 mtrl;
    ZeroMemory( &mtrl, sizeof(D3DMATERIAL9) );
    mtrl.Diffuse.r = 1.0f;
    mtrl.Diffuse.g = 0.5f;
    mtrl.Diffuse.b = 0.0f;
    mtrl.Diffuse.a = 1.0f;
    g_pd3dDevice->SetMaterial( &mtrl );

    D3DLIGHT9 light;
    ZeroMemory( &light, sizeof(D3DLIGHT9) );
    light.Type       = D3DLIGHT_DIRECTIONAL;
    light.Diffuse.r  = 1.0f;
    light.Diffuse.g  = 1.0f;
    light.Diffuse.b  = 1.0f;
	light.Direction.x = 2.0f;
	light.Direction.y = 30.0f;
	light.Direction.z = -30.0f;
    light.Range       = 1000.0f;
    g_pd3dDevice->SetLight( 0, &light );
    g_pd3dDevice->LightEnable( 0, TRUE );
}

void Render()
{
	if(g_pd3dDevice == NULL)
		return;

	g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(234, 234, 234), 1.0f, 0);

	g_pd3dDevice->BeginScene();

	SetupLights();
	SetupMatrices();

	mdx->BuildNormals();

	g_pd3dDevice->SetStreamSource(0, g_pVB, 0, sizeof(Vertex));
	g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX);
	g_pd3dDevice->SetIndices(g_pIB);
	g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, mdx->m_pMeshes[0].m_iNumVerts, 0, mdx->m_pMeshes[0].m_iNumFaces);

	g_pd3dDevice->EndScene();
	g_pd3dDevice->Present(NULL, NULL, NULL, NULL);
}



and here is the BuildNormals method:

void CMdx::BuildNormals()
{
   for (int i = 0; i < m_iNumMeshes; i++)
   {
      Mesh &mesh = m_pMeshes;

	  for (int j = 0; j < mesh.m_iNumVerts; j++)
      {
		 mesh.m_pVert[j].normal.x = 0;
		 mesh.m_pVert[j].normal.y = 0;
		 mesh.m_pVert[j].normal.z = 0;
      }

	  for (int j = 0; j < mesh.m_iNumFaces; j++)
      {
		 Face &tri = mesh.m_pFace[j];

		 Vertex &v0 = mesh.m_pVert[tri.vertIndex[0]];
         Vertex &v1 = mesh.m_pVert[tri.vertIndex[1]];
         Vertex &v2 = mesh.m_pVert[tri.vertIndex[2]];

		 float Ax = v1.position.x - v0.position.x;
         float Ay = v1.position.y - v0.position.y;
         float Az = v1.position.z - v0.position.z;

         float Bx = v2.position.x - v0.position.x;
         float By = v2.position.y - v0.position.y;
         float Bz = v2.position.z - v0.position.z;

         float nx = Ay * Bz - By * Az;
         float ny = -(Ax * Bz - Bx * Az);
         float nz = Ax * By - Bx * Ay;

		 v0.normal.x += nx;
         v0.normal.y += ny;
         v0.normal.z += nz;

         v1.normal.x += nx;
         v1.normal.y += ny;
         v1.normal.z += nz;

         v2.normal.x += nx;
         v2.normal.y += ny;
         v2.normal.z += nz;
      }

	  for (int j = 0; j < mesh.m_iNumVerts; j++)
      {
         Vertex &v = mesh.m_pVert[j];

		 float len = float(sqrt(v.normal.x * v.normal.x + v.normal.y * v.normal.y + v.normal.z * v.normal.z));

         if (len)
         {
            v.normal.x /= len;
            v.normal.y /= len;
            v.normal.z /= len;
         }
      }
   }   
}



Any help?
Advertisement
Is the object rotating or are you rotating the view matrix? If you are rotating the view matrix, then the light is staying constant, so on one side you're staring into the light and can't see anything (black figure) and on the other side the light is illuminating, rather crazy-like, the figure.

A couple of comments: Range is not used for directional lights, so you can remove that. I didn't see a SetRenderState to enable D3D Lighting, though I believe you are setting that. Also, add some ambient lighting, by setting the ambient render state. You should only have to calculate the normals once, instead of every frame. Other than these, which aren't really indicative of what you're seeing, I don't see what's wrong...although the normals defined incorrectly will cause this. Are you applying a texture?

Chris
Chris ByersMicrosoft DirectX MVP - 2005
I'm not very familiar with DirectX but from looking at your code, it seems that your vertex normal calculation is off. You should be calculating a vertex normal based on the face normals of all faces adjacent to a vertex. Your code seems to iterate through all the faces, calculates a face normal (un-normalized) and adds this to a running sum for each of the adjacent verticies.

The problem here is that the normal you calculate has a length that depends on the size of the triangle face. The vertex normal should be the average of all the face normals adjacent to that vertex. You method skews the average by weighing the larger faces more. To fix this, you should normalize each face normal before adding to the running sum for each vertex.

I don't know if this will fix your lighting problem but it is a place to start.

Zeljko Pavic
Zeljko

This topic is closed to new replies.

Advertisement