Archived

This topic is now archived and is closed to further replies.

El Duderino

D3D lighting woes (amongst other problems perhaps)

Recommended Posts

Hello, In trying to learn d3d I am doing my usual thing, which is taking a sample piece of code (in this case one of NeXe''s tutes) and then modifying it. This tute originally had a diffuse colour component to the vertex buffers, which provided the light. As a modification I decided to remove this component and turn on d3d lighting. I threw in everything I thought would be needed, and no doubt a few things that aren''t needed either ... just sort of playing by ear using the SDK documentation. But it hasn''t worked despite hours of tinkering something is eluding me. Here''s the relevant code :
  
// Includes for Windows and DirectX

#include <windows.h>
#include <d3d8.h>
#include <d3dx8.h>
#include <stdlib.h>
#include <time.h>

// Our vertex class

class CVertex
{
public:
	// Its coordinates

	float fX, fY, fZ;

	// Its texture coordinates

	float fU, fV;

	// A function to simplify initialization

	void Create(float fp_fX,float fp_fY,float fp_fZ, float fp_fU, float fp_fV)
	{
		fX=fp_fX;
		fY=fp_fY;
		fZ=fp_fZ;

		fU=fp_fU;
		fV=fp_fV;
	}
};
// The CVertex FVF

const DWORD D3DFVF_CVertex=D3DFVF_XYZ | D3DFVF_TEX1; 

// Our processed vertex class

class CProcessedVertex
{
public:
	// Processed position

	float fX, fY, fZ;

	float fNX, fNY, fNZ;

	// Texture coordinates

	float fU, fV;
};
// The CProcessedVertex FVF

const DWORD D3DFVF_CProcessedVertex=D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1; 

// Constants to make changing stuff in initialization easier

const int WINDOW_WIDTH = 800; 
const int WINDOW_HEIGHT = 600; 
const int WINDOW_X = 0; 
const int WINDOW_Y = 0; 
const char *WINDOW_TITLE="NeXe Tutorial 5";
const char *WINDOW_CLASS_NAME="NeXe Tutorial"; 

// Important Windows variables

HINSTANCE g_hInst;
HWND g_hWnd;	

// Whether or not it''s fullscreen

bool g_bFullscreen;

// Important Direct3D variables

IDirect3D8 *g_pDirect3D;
IDirect3DDevice8 *g_pDevice;
IDirect3DTexture8 *g_pTexture;
IDirect3DTexture8 *g_pTexture1;

D3DLIGHT8		d3dLight;
D3DMATERIAL8	d3dMaterial;
D3DCOLORVALUE	d3dColour;

// Results from Direct3D function calls are stored here

HRESULT g_hr;

// Instead of an array of vertices, we have a pointer to a vertex buffer

IDirect3DVertexBuffer8 *g_pVertexBuffer;
// Also, when using vertex buffers, you have two copies of the data, the unprocessed data, and the processed data.

IDirect3DVertexBuffer8 *g_pProcessedVertexBuffer;

bool Direct3DInit()
{
	// Create the IDirect3D object

	g_pDirect3D=Direct3DCreate8(D3D_SDK_VERSION);
	if (g_pDirect3D==NULL)
		return 0;
	
	// Set up a structure with either the current display mode for windowed mode or the desired display mode for fullscreen

	D3DDISPLAYMODE displayMode;
	if (g_bFullscreen==false)
	{
		g_hr=g_pDirect3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &displayMode);
		if (FAILED(g_hr))
			return 0;
	}
	else
	{
		displayMode.Width=WINDOW_WIDTH;
		displayMode.Height=WINDOW_HEIGHT;
		displayMode.RefreshRate=0;
		displayMode.Format=D3DFMT_A8R8G8B8;
	}

	// Setup the present parameters

	D3DPRESENT_PARAMETERS presentParameters;
	memset(&presentParameters, 0, sizeof(D3DPRESENT_PARAMETERS));
	if (g_bFullscreen==false)
	{
		presentParameters.Windowed   = TRUE;
	}
	else
	{
		presentParameters.Windowed   = FALSE;
	}

	presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
	presentParameters.BackBufferFormat = displayMode.Format;
	presentParameters.BackBufferWidth = displayMode.Width;
	presentParameters.BackBufferHeight = displayMode.Height;

	// Create the device

	g_hr=g_pDirect3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd,
                                  D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                  &presentParameters, &g_pDevice ); 

	if (FAILED(g_hr))
		return false;

	// Matrix code

	D3DXMATRIX mat;
	
	D3DXMatrixPerspectiveFovLH(&mat, D3DX_PI/6, WINDOW_WIDTH/WINDOW_HEIGHT, 1.0, 180.0);
	g_pDevice->SetTransform(D3DTS_PROJECTION, &(D3DMATRIX)mat);

	D3DXMatrixIdentity(&mat);
	g_pDevice->SetTransform(D3DTS_WORLD, &(D3DMATRIX)mat);

	D3DXMatrixTranslation(&mat, 0, 0, 10.0);
	g_pDevice->SetTransform(D3DTS_VIEW, &(D3DMATRIX)mat);

    int x = 90, y = 195, z = 90;
	D3DXMatrixRotationYawPitchRoll(&mat, D3DXToRadian(x), D3DXToRadian(y), D3DXToRadian(z));	
	g_pDevice->MultiplyTransform(D3DTS_VIEW, &(D3DMATRIX)mat);
	// Set that matrix to the world transformation


	// Setup the vertex buffer

	g_pDevice->CreateVertexBuffer(sizeof(CVertex)*1600, NULL, D3DFVF_CVertex, D3DPOOL_MANAGED, &g_pVertexBuffer);
	
	CVertex *vtxQuad;
	g_pVertexBuffer->Lock(0, 0, (BYTE **)&vtxQuad, NULL);

	float Mapx=-10.0f, Mapy=-10.0f;
	int   Counter=0;

	for (Mapy=-10; Mapy < 10; Mapy++)
	{
		for (Mapx=-10; Mapx < 10; Mapx++)
		{
			vtxQuad[Counter].Create(Mapx    , 1, Mapy    , 0, 1);
			Counter++;
			vtxQuad[Counter].Create(Mapx    , 1, Mapy + 1, 0, 0);
			Counter++;
			vtxQuad[Counter].Create(Mapx + 1, 1, Mapy    , 1, 1);
			Counter++;
			vtxQuad[Counter].Create(Mapx + 1, 1, Mapy + 1, 0, 1);
			Counter++;
		}
	}
	
	g_pVertexBuffer->Unlock();

	// Create the processed vertex buffer

	g_hr = g_pDevice->CreateVertexBuffer(sizeof(CProcessedVertex)*1600, NULL, D3DFVF_CProcessedVertex, D3DPOOL_MANAGED, &g_pProcessedVertexBuffer);
	if (FAILED(g_hr))
	{
		MessageBox(g_hWnd, "Create processed buffer no good", "Error Box", MB_OK);
	    return false;// Code to handle the error goes here.

	}

	// Make it so that it''ll draw triangles facing either towards or away from the camera

    g_pDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
	
	g_pDevice->SetRenderState( D3DRS_LIGHTING, TRUE); 
	g_pDevice->SetRenderState( D3DRS_NORMALIZENORMALS, TRUE);

	ZeroMemory(&d3dLight, sizeof(D3DLIGHT8));
	d3dLight.Type = D3DLIGHT_POINT;
	d3dLight.Diffuse.r  = 0.0f;
	d3dLight.Diffuse.g  = 0.0f;
	d3dLight.Diffuse.b  = 0.0f;
	d3dLight.Ambient.r  = 1.0f;
	d3dLight.Ambient.g  = 1.0f;
	d3dLight.Ambient.b  = 1.0f;
	d3dLight.Specular.r = 0.0f;
	d3dLight.Specular.g = 0.0f;
	d3dLight.Specular.b = 0.0f;

// Position it high in the scene and behind the user.

// Remember, these coordinates are in world space, so

// the user could be anywhere in world space, too. 

// For the purposes of this example, assume the user

// is at the origin of world space.

	d3dLight.Position.x = 10.0f;
	d3dLight.Position.y = 10.0f;
	d3dLight.Position.z = -100.0f;

// Don''t attenuate.

	d3dLight.Attenuation0 = 1.0f; 
	d3dLight.Range      = 1000.0f;

// Set the property information for the first light.

g_hr = g_pDevice->SetLight(0, &d3dLight);
if (FAILED(g_hr))
{
	MessageBox(g_hWnd, "SetLight no good", "Error Box", MB_OK);
    return false;// Code to handle the error goes here.

}

g_hr = g_pDevice->LightEnable(0, TRUE);
if (FAILED(g_hr))
{
	MessageBox(g_hWnd, "LightEnable no good", "Error Box", MB_OK);
    return false; // Code to handle the error goes here.

}

	ZeroMemory(&d3dColour, sizeof(D3DCOLORVALUE));
	ZeroMemory(&d3dMaterial, sizeof(D3DMATERIAL8));

    d3dColour.r = 1.0f;
	d3dColour.g = 1.0f;
	d3dColour.b = 1.0f;
	d3dColour.a = 0.0f;

	d3dMaterial.Ambient  = d3dColour;
	d3dMaterial.Emissive = d3dColour;

	d3dColour.r = 0.0f;
	d3dColour.g = 0.0f;
	d3dColour.b = 0.0f;
	d3dColour.a = 0.0f;

	d3dMaterial.Specular = d3dColour;
	d3dMaterial.Diffuse  = d3dColour;
	d3dMaterial.Power    = 1.0f;

g_hr = g_pDevice->SetMaterial(&d3dMaterial);
if (FAILED(g_hr))
{
	MessageBox(g_hWnd, "SetMaterial no good", "Error Box", MB_OK);
    return false; // Code to handle the error goes here.

}

	g_pDevice->SetRenderState( D3DRS_AMBIENT, 0x00ffffff);
	g_pDevice->SetRenderState( D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL);

	g_pDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
	g_pDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
	g_pDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE);

	// Turn off the alpha channel since the texture doesn''t have one

	g_pDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);

	// Create the texture

	D3DXCreateTextureFromFile(g_pDevice, "TileLas.bmp", &g_pTexture);
	D3DXCreateTextureFromFile(g_pDevice, "TileLbs.bmp", &g_pTexture1);

	srand((unsigned)time(NULL));

	return true;
}

void UpdateScene()
{
	// We have a static integer for how many degrees to generate the rotation matrix for

	static float i=0;
	static int   si=0;
	static int   toggle=0;

	// Setup a matrix 


	D3DXMATRIX mat;

	D3DXMatrixTranslation(&mat, 0, 0, i + 20.0f);
	g_pDevice->SetTransform(D3DTS_VIEW, &(D3DMATRIX)mat);

	int x = 90, y = 195, z = 90;
	D3DXMatrixRotationYawPitchRoll(&mat, D3DXToRadian(x), D3DXToRadian(y), D3DXToRadian(z));	
	g_pDevice->MultiplyTransform(D3DTS_VIEW, &(D3DMATRIX)mat);
		
	// Change the zoom/pan.

	if (toggle==0)
	{
		i++;
		if (i==1800)
			toggle^=1;
	}
	else
	{
		i--;
		if (i==0)
			toggle^=1;
	}

}

void DrawScene()
{
	// Clear the screen

	g_pDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(10, 10, 10), 1.0f, 0 );
	// Make it so we can draw stuff

	g_pDevice->BeginScene();

	int  PCount=0;
	byte PToggle=0;

	for (PCount=0; PCount < 400; PCount++)
	{
		// Tell it the source vertex buffer is g_pVertexBuffer

		g_pDevice->SetStreamSource(0, g_pVertexBuffer, sizeof(CVertex));

		// Tell it to process the source vertex buffer using the CVertex FVF

		g_pDevice->SetVertexShader(D3DFVF_CVertex);
	
		// Tell it to process the vertices


		g_pDevice->ProcessVertices(PCount * 4, 0, 4, g_pProcessedVertexBuffer, NULL);


		// Tell it to use our texture

		if (PToggle == 0)
		{
			g_pDevice->SetTexture(0, g_pTexture);
		}
		else
		{
			g_pDevice->SetTexture(0, g_pTexture1);
		}

		PToggle^=1;

		// Set the source vertex buffer to our processed vertices

		g_pDevice->SetStreamSource(0, g_pProcessedVertexBuffer, sizeof(CProcessedVertex));

		// Tell it to process the source vertex buffer using the CProcessedVertex FVF

		g_pDevice->SetVertexShader(D3DFVF_CProcessedVertex);

		// Draw the source vertex buffer

		g_pDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);

	}

	// Make it so we can''t draw stuff

	g_pDevice->EndScene();
	// Put the back buffer onto the screen

	g_pDevice->Present(NULL, NULL, NULL, NULL);
}
  
I tried some stuff that maybe has no place in there - I know it''s a big chunk of source but there''s probably so many questionable bits of code there ... Thanks for looking El Duderino

Share this post


Link to post
Share on other sites
I think I picked up one problem - I put the normals in the wrong vertex buffer ?

El Duderino

Edit - well, I finally found out what the hell a normal is and worked out *most* of the other problems too ... one thing I can't get a grip on is whether I need the diffuse component for lighting properly in the vertex buffer - what about defining such things in materials ? Isn't this what it's for ?

Edited by - El Duderino on June 26, 2001 1:28:10 PM

Share this post


Link to post
Share on other sites