DirectX 10 lightning example

This topic is 3848 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

Hi everyone. I have been modifying the lightning example that comes with DirectX 10. The example puts a cube and a red light rotating around it lightning the cube's sides. The example declares the the cube's vertices like this:
struct SimpleVertex
{
D3DXVECTOR3 Pos;
D3DXVECTOR3 Normal;
};

SimpleVertex vertices[] =
{
{ D3DXVECTOR3( -1.0f,  1.0f, -1.0f ), D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) },
{ D3DXVECTOR3(  1.0f,  1.0f, -1.0f ), D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) },
{ D3DXVECTOR3(  1.0f,  1.0f,  1.0f ), D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) },
{ D3DXVECTOR3( -1.0f,  1.0f,  1.0f ), D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) },

{ D3DXVECTOR3( -1.0f, -1.0f, -1.0f ), D3DXVECTOR3( 0.0f, -1.0f, 0.0f ) },
{ D3DXVECTOR3(  1.0f, -1.0f, -1.0f ), D3DXVECTOR3( 0.0f, -1.0f, 0.0f ) },
{ D3DXVECTOR3(  1.0f, -1.0f,  1.0f ), D3DXVECTOR3( 0.0f, -1.0f, 0.0f ) },
{ D3DXVECTOR3( -1.0f, -1.0f,  1.0f ), D3DXVECTOR3( 0.0f, -1.0f, 0.0f ) },

{ D3DXVECTOR3( -1.0f, -1.0f,  1.0f ), D3DXVECTOR3( -1.0f, 0.0f, 0.0f ) },
{ D3DXVECTOR3( -1.0f, -1.0f, -1.0f ), D3DXVECTOR3( -1.0f, 0.0f, 0.0f ) },
{ D3DXVECTOR3( -1.0f,  1.0f, -1.0f ), D3DXVECTOR3( -1.0f, 0.0f, 0.0f ) },
{ D3DXVECTOR3( -1.0f,  1.0f,  1.0f ), D3DXVECTOR3( -1.0f, 0.0f, 0.0f ) },

{ D3DXVECTOR3( 1.0f, -1.0f,  1.0f ), D3DXVECTOR3( 1.0f, 0.0f, 0.0f ) },
{ D3DXVECTOR3( 1.0f, -1.0f, -1.0f ), D3DXVECTOR3( 1.0f, 0.0f, 0.0f ) },
{ D3DXVECTOR3( 1.0f,  1.0f, -1.0f ), D3DXVECTOR3( 1.0f, 0.0f, 0.0f ) },
{ D3DXVECTOR3( 1.0f,  1.0f,  1.0f ), D3DXVECTOR3( 1.0f, 0.0f, 0.0f ) },

{ D3DXVECTOR3( -1.0f, -1.0f, -1.0f ), D3DXVECTOR3( 0.0f, 0.0f, -1.0f ) },
{ D3DXVECTOR3(  1.0f, -1.0f, -1.0f ), D3DXVECTOR3( 0.0f, 0.0f, -1.0f ) },
{ D3DXVECTOR3(  1.0f,  1.0f, -1.0f ), D3DXVECTOR3( 0.0f, 0.0f, -1.0f ) },
{ D3DXVECTOR3( -1.0f,  1.0f, -1.0f ), D3DXVECTOR3( 0.0f, 0.0f, -1.0f ) },

{ D3DXVECTOR3( -1.0f, -1.0f, 1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 1.0f ) },
{ D3DXVECTOR3(  1.0f, -1.0f, 1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 1.0f ) },
{ D3DXVECTOR3(  1.0f,  1.0f, 1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 1.0f ) },
{ D3DXVECTOR3( -1.0f,  1.0f, 1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 1.0f ) },
};


As you can see the code declares already the normals of each face, still, I used an algorithm I took from a book for computing the cube's normals:
DWORD indices[] =
{
3,1,0,
2,1,3,

6,4,5,
7,4,6,

11,9,8,
10,9,11,

14,12,13,
15,12,14,

19,17,16,
18,17,19,

22,20,21,
23,20,22
};

UINT numIndices = sizeof(indices) / sizeof(DWORD);

for(UINT i = 0; i < numIndices; i+=3)
{
D3DXVECTOR3 v0 = vertices[indices].Pos;
D3DXVECTOR3 v1 = vertices[indices[i + 1]].Pos;
D3DXVECTOR3 v2 = vertices[indices[i + 2]].Pos;

D3DXVECTOR3 normal;
D3DXVECTOR3 cross;
D3DXVec3Cross(&cross, &D3DXVECTOR3(v2 - v0), &D3DXVECTOR3(v1 - v0));
D3DXVec3Normalize(&normal, &cross);

vertices[indices].Normal = -normal;
vertices[indices[i + 1]].Normal = -normal;
vertices[indices[i + 2]].Normal = -normal;
}

But this produces a black cube that does not reflect any light at all, declaring the normals as before renders the desired effect. Debugging I found out that the computed normals for the first face are {-0.0, 0.99999997, -0.0} pretty much close to {0.0, 1.0, 0.0} The full code of my app is:
//Include Windows file
#include <windows.h>
#include <tchar.h>

#include <d3d10.h>
#include <d3dx10.h>

HINSTANCE hInst;	//global handle for the app
HWND wndHandle;		//global variable for window handle

//Direct3D global vars
ID3D10Device* pD3DDevice = NULL;
IDXGISwapChain* pSwapChain = NULL;
ID3D10RenderTargetView* pRenderTargetView = NULL;
ID3D10Texture2D*            g_pDepthStencil = NULL;
ID3D10DepthStencilView*     g_pDepthStencilView = NULL;
ID3D10Effect*               g_pEffect = NULL;
ID3D10EffectTechnique*      g_pTechniqueRender = NULL;
ID3D10EffectTechnique*      g_pTechniqueRenderLight = NULL;
ID3D10EffectMatrixVariable* g_pWorldVariable = NULL;
ID3D10EffectMatrixVariable* g_pViewVariable = NULL;
ID3D10EffectMatrixVariable* g_pProjectionVariable = NULL;
ID3D10EffectVectorVariable* g_pLightDirVariable = NULL;
ID3D10EffectVectorVariable* g_pLightColorVariable = NULL;
ID3D10EffectVectorVariable* g_pOutputColorVariable = NULL;
ID3D10InputLayout*          g_pVertexLayout = NULL;
ID3D10Buffer*               g_pVertexBuffer = NULL;
ID3D10Buffer*               g_pIndexBuffer = NULL;
D3DXMATRIX                  g_World;
D3DXMATRIX                  g_View;
D3DXMATRIX                  g_Projection;

int width = 640;
int height = 480;

//foward declarations
bool InitWindow(HINSTANCE hInstance, int width, int height);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

bool DoInit();
void DoShutdown();
bool DoPreFrame();
bool DoFrame();
bool DoPostFrame();

bool InitModelObject();

struct SimpleVertex
{
D3DXVECTOR3 Pos;
D3DXVECTOR3 Normal;
};

//Winmain point of entry
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
//initialize the window
if(!InitWindow(hInstance, width, height))
{
return false;
}

//main message loop
MSG msg = {0};
if(DoInit())
{
while(WM_QUIT != msg.message)
{
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) == TRUE)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

if(!DoPreFrame())
break;

if(!DoFrame())
break;

if(!DoPostFrame())
break;
}
}

DoShutdown();

UnregisterClass(TEXT("DirectXExample"), hInst);

return (int)msg.wParam;
}

/*********************************************************************************
* InitWindow
* Inits and creates a main app window
* Inputs - aplication instance - HINSTANCE
Window width - int
Window height - int
* Outputs - true if successful, false if failed - true
*********************************************************************************/
bool InitWindow(HINSTANCE hInstance, int width, int height)
{
WNDCLASSEX wcex;

//Fill in the WNDCLASSEX structure, This describes how the window will look to the system
wcex.cbSize = sizeof(WNDCLASSEX);	//size of the structure
wcex.style = CS_HREDRAW | CS_VREDRAW;	//the class style
wcex.lpfnWndProc = (WNDPROC)WndProc;	//the window procedure callback
wcex.cbClsExtra = 0;					//extra bytes to allocate for this class
wcex.cbWndExtra = 0;					//extra bytes to alloate for this instance
wcex.hInstance = hInstance;				//handle to the application instance
wcex.hIcon = 0;							//icon to associate with the application
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);	//the default cursor to use
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);	//the background color
wcex.lpszClassName = TEXT("DirectXExample");	//class name being created
wcex.hIconSm = 0;	//handle to small icon
RegisterClassEx(&wcex);

//resize the window
RECT rect = {0, 0, width, height};

//create the window from the class above
wndHandle = CreateWindow(TEXT("DirectXExample"),
TEXT("DirectXExample"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
rect.right - rect.left,
rect.bottom - rect.top,
NULL,
NULL,
hInstance,
NULL);

if(!wndHandle)
{
return false;
}

//display the window on the screen
ShowWindow(wndHandle, SW_SHOW);
UpdateWindow(wndHandle);

return true;
}
/*********************************************************************************
* WndProc
* The main window procedure for the application
* Inputs - aplication window handle - HWND
message sent to the window - UINT
wParam of the message being sent - WPARAM
lParam of the message being sent - LPARAM
* Outputs - LRESULT
*********************************************************************************/
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
//check any available messages from the queue
switch(message)
{
//allow the user to press the Escape key to end the application
case WM_KEYDOWN:
switch(wParam)
{
//check if the use hit the escape key
case VK_ESCAPE:
PostQuitMessage(0);
break;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}

//always return the message to the default widow procedure for further processing
return DefWindowProc(hWnd, message, wParam, lParam);
}

bool DoInit()
{
//create the clear DXGI_SWAP_CHAIN_DESC structure
DXGI_SWAP_CHAIN_DESC swapChainDesc;
ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));

//fill the values
swapChainDesc.BufferCount = 1;
swapChainDesc.BufferDesc.Width = width;
swapChainDesc.BufferDesc.Height = height;
swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapChainDesc.BufferDesc.RefreshRate.Numerator = 60;
swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.OutputWindow = wndHandle;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.Windowed = TRUE;

//create the D3D device and swap chain
HRESULT hr = D3D10CreateDeviceAndSwapChain(NULL,
D3D10_DRIVER_TYPE_HARDWARE,
NULL,
0,
D3D10_SDK_VERSION,
&swapChainDesc,
&pSwapChain,
&pD3DDevice);

//Error checking. Make sure device was created
if (hr != S_OK)
{
return false;
}

//get the backbuffer from the swap chain
ID3D10Texture2D *pBackBuffer;
hr = pSwapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), (LPVOID*)&pBackBuffer);
if (hr != S_OK)
{
return false;
}

//create the render target view
hr = pD3DDevice->CreateRenderTargetView(pBackBuffer, NULL, &pRenderTargetView);

//release the backbuffer
pBackBuffer->Release();

//make sure render target was created
if (hr != S_OK)
{
return false;
}

//set the render target
//pD3DDevice->OMSetRenderTargets(1, &pRenderTargetView, NULL);

// Create depth stencil texture
D3D10_TEXTURE2D_DESC descDepth;
descDepth.Width = width;
descDepth.Height = height;
descDepth.MipLevels = 1;
descDepth.ArraySize = 1;
descDepth.Format = DXGI_FORMAT_D32_FLOAT;
descDepth.SampleDesc.Count = 1;
descDepth.SampleDesc.Quality = 0;
descDepth.Usage = D3D10_USAGE_DEFAULT;
descDepth.BindFlags = D3D10_BIND_DEPTH_STENCIL;
descDepth.CPUAccessFlags = 0;
descDepth.MiscFlags = 0;
hr = pD3DDevice->CreateTexture2D( &descDepth, NULL, &g_pDepthStencil );
if( FAILED(hr) )
return false;

// Create the depth stencil view
D3D10_DEPTH_STENCIL_VIEW_DESC descDSV;
descDSV.Format = descDepth.Format;
descDSV.ViewDimension = D3D10_DSV_DIMENSION_TEXTURE2D;
descDSV.Texture2D.MipSlice = 0;
hr = pD3DDevice->CreateDepthStencilView( g_pDepthStencil, &descDSV, &g_pDepthStencilView );
if( FAILED(hr) )
return false;

pD3DDevice->OMSetRenderTargets( 1, &pRenderTargetView, g_pDepthStencilView );

//create and set the viewport
D3D10_VIEWPORT viewPort;
viewPort.Width = width;
viewPort.Height = height;
viewPort.MinDepth = 0.0f;
viewPort.MaxDepth = 1.0f;
viewPort.TopLeftX = 0;
viewPort.TopLeftY = 0;

if(!InitModelObject())
{
return false;
}

return true;
}

void DoShutdown()
{
if(pD3DDevice)
{
pD3DDevice->ClearState();
}

if(g_pEffect)
{
g_pEffect->Release();
}

if(g_pVertexLayout)
{
g_pVertexLayout->Release();
}

if(g_pVertexBuffer)
{
g_pVertexBuffer->Release();
}

if(g_pIndexBuffer)
{
g_pIndexBuffer->Release();
}

//release render target
if(pRenderTargetView)
{
pRenderTargetView->Release();
}

if(g_pDepthStencil)
{
g_pDepthStencil->Release();
}

if(g_pDepthStencilView)
{
g_pDepthStencilView->Release();
}

//release the swapchain
if(pSwapChain)
{
pSwapChain->Release();
}

//release the D3D Device
if(pD3DDevice)
{
pD3DDevice->Release();
}
}

bool DoPreFrame()
{
// Update our time
static float t = 0.0f;

static DWORD dwTimeStart = 0;
DWORD dwTimeCur = GetTickCount();
if( dwTimeStart == 0 )
dwTimeStart = dwTimeCur;
t = ( dwTimeCur - dwTimeStart) / 1000.0f;

// Rotate cube around the origin
D3DXMatrixRotationY( &g_World, t );

// Setup our lighting parameters
D3DXVECTOR4 vLightDirs[2] =
{
D3DXVECTOR4( -0.577f, 0.577f, -0.577f, 1.0f ),
D3DXVECTOR4( 0.0f, 0.0f, -1.0f, 1.0f ),
};
D3DXVECTOR4 vLightColors[2] =
{
D3DXVECTOR4( 0.5f, 0.5f, 0.5f, 1.0f ),
D3DXVECTOR4( 0.5f, 0.0f, 0.0f, 1.0f )
};

//rotate the second light around the origin
D3DXMATRIX mRotate;
D3DXVECTOR4 vOutDir;
D3DXMatrixRotationY( &mRotate, -2.0f*t );
D3DXVec3Transform( &vLightDirs[1], (D3DXVECTOR3*)&vLightDirs[1], &mRotate );

//
// Clear the back buffer
//
float ClearColor[4] = { 0.0f, 0.125f, 0.3f, 1.0f }; // red, green, blue, alpha
pD3DDevice->ClearRenderTargetView( pRenderTargetView, ClearColor );

//
// Clear the depth buffer to 1.0 (max depth)
//
pD3DDevice->ClearDepthStencilView( g_pDepthStencilView, D3D10_CLEAR_DEPTH, 1.0f, 0 );

//
// Update matrix variables
//
g_pWorldVariable->SetMatrix( (float*)&g_World );
g_pViewVariable->SetMatrix( (float*)&g_View );
g_pProjectionVariable->SetMatrix( (float*)&g_Projection );

//
// Update lighting variables
//
g_pLightDirVariable->SetFloatVectorArray( (float*)vLightDirs, 0,    2 );
g_pLightColorVariable->SetFloatVectorArray( (float*)vLightColors, 0,    2 );

//
// Render the cube
//
D3D10_TECHNIQUE_DESC techDesc;
g_pTechniqueRender->GetDesc( &techDesc );
for( UINT p = 0; p < techDesc.Passes; ++p )
{
g_pTechniqueRender->GetPassByIndex( p )->Apply(0);
pD3DDevice->DrawIndexed( 36, 0, 0 );
}

//
// Render each light
//
for( int m = 0; m < 2; m++ )
{
D3DXMATRIX mLight;
D3DXMATRIX mLightScale;
D3DXVECTOR3 vLightPos = vLightDirs[m]*5.0f;
D3DXMatrixTranslation( &mLight, vLightPos.x, vLightPos.y, vLightPos.z );
D3DXMatrixScaling( &mLightScale, 0.2f, 0.2f, 0.2f );
mLight = mLightScale*mLight;

// Update the world variable to reflect the current light
g_pWorldVariable->SetMatrix( (float*)&mLight );
g_pOutputColorVariable->SetFloatVector( (float*)&vLightColors[m]    );

g_pTechniqueRenderLight->GetDesc( &techDesc );
for( UINT p = 0; p < techDesc.Passes; ++p )
{
g_pTechniqueRenderLight->GetPassByIndex( p )->Apply(0);
pD3DDevice->DrawIndexed( 36, 0, 0 );
}

}

//
// Present our back buffer to our front buffer
//
pSwapChain->Present( 0, 0 );

return true;
}

bool DoFrame()
{
//all drawing here
//
// Render the cube
//

//pSwapChain->Present(0, 0);

return true;
}

bool DoPostFrame()
{

return true;
}

bool InitModelObject()
{

HRESULT hr = D3DX10CreateEffectFromFile( L"simple.fx", NULL, NULL, "fx_4_0", dwShaderFlags, 0, pD3DDevice, NULL, NULL, &g_pEffect, NULL, NULL );
if( FAILED( hr ) )
{
MessageBox( NULL, L"The FX file cannot be located.  Please run this executable from the directory that contains the FX file.", L"Error", MB_OK );
return false;
}

// Obtain the techniques
g_pTechniqueRender = g_pEffect->GetTechniqueByName( "Render" );
g_pTechniqueRenderLight = g_pEffect->GetTechniqueByName( "RenderLight" );

// Obtain the variables
g_pWorldVariable = g_pEffect->GetVariableByName( "World" )->AsMatrix();
g_pViewVariable = g_pEffect->GetVariableByName( "View" )->AsMatrix();
g_pProjectionVariable = g_pEffect->GetVariableByName( "Projection" )->AsMatrix();
g_pLightDirVariable = g_pEffect->GetVariableByName( "vLightDir" )->AsVector();
g_pLightColorVariable = g_pEffect->GetVariableByName( "vLightColor" )->AsVector();
g_pOutputColorVariable = g_pEffect->GetVariableByName( "vOutputColor" )->AsVector();

// Define the input layout
D3D10_INPUT_ELEMENT_DESC layout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
{ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0 },
};
UINT numElements = sizeof(layout)/sizeof(layout[0]);

// Create the input layout
D3D10_PASS_DESC PassDesc;
g_pTechniqueRender->GetPassByIndex(0)->GetDesc(&PassDesc);
hr = pD3DDevice->CreateInputLayout( layout, numElements, PassDesc.pIAInputSignature, PassDesc.IAInputSignatureSize, &g_pVertexLayout );
if( FAILED(hr) )
return false;

pD3DDevice->IASetInputLayout( g_pVertexLayout );

/*SimpleVertex vertices[] =
{
{ D3DXVECTOR3( -1.0f,  1.0f, -1.0f ), D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) },
{ D3DXVECTOR3(  1.0f,  1.0f, -1.0f ), D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) },
{ D3DXVECTOR3(  1.0f,  1.0f,  1.0f ), D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) },
{ D3DXVECTOR3( -1.0f,  1.0f,  1.0f ), D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) },

{ D3DXVECTOR3( -1.0f, -1.0f, -1.0f ), D3DXVECTOR3( 0.0f, -1.0f, 0.0f ) },
{ D3DXVECTOR3(  1.0f, -1.0f, -1.0f ), D3DXVECTOR3( 0.0f, -1.0f, 0.0f ) },
{ D3DXVECTOR3(  1.0f, -1.0f,  1.0f ), D3DXVECTOR3( 0.0f, -1.0f, 0.0f ) },
{ D3DXVECTOR3( -1.0f, -1.0f,  1.0f ), D3DXVECTOR3( 0.0f, -1.0f, 0.0f ) },

{ D3DXVECTOR3( -1.0f, -1.0f,  1.0f ), D3DXVECTOR3( -1.0f, 0.0f, 0.0f ) },
{ D3DXVECTOR3( -1.0f, -1.0f, -1.0f ), D3DXVECTOR3( -1.0f, 0.0f, 0.0f ) },
{ D3DXVECTOR3( -1.0f,  1.0f, -1.0f ), D3DXVECTOR3( -1.0f, 0.0f, 0.0f ) },
{ D3DXVECTOR3( -1.0f,  1.0f,  1.0f ), D3DXVECTOR3( -1.0f, 0.0f, 0.0f ) },

{ D3DXVECTOR3( 1.0f, -1.0f,  1.0f ), D3DXVECTOR3( 1.0f, 0.0f, 0.0f ) },
{ D3DXVECTOR3( 1.0f, -1.0f, -1.0f ), D3DXVECTOR3( 1.0f, 0.0f, 0.0f ) },
{ D3DXVECTOR3( 1.0f,  1.0f, -1.0f ), D3DXVECTOR3( 1.0f, 0.0f, 0.0f ) },
{ D3DXVECTOR3( 1.0f,  1.0f,  1.0f ), D3DXVECTOR3( 1.0f, 0.0f, 0.0f ) },

{ D3DXVECTOR3( -1.0f, -1.0f, -1.0f ), D3DXVECTOR3( 0.0f, 0.0f, -1.0f ) },
{ D3DXVECTOR3(  1.0f, -1.0f, -1.0f ), D3DXVECTOR3( 0.0f, 0.0f, -1.0f ) },
{ D3DXVECTOR3(  1.0f,  1.0f, -1.0f ), D3DXVECTOR3( 0.0f, 0.0f, -1.0f ) },
{ D3DXVECTOR3( -1.0f,  1.0f, -1.0f ), D3DXVECTOR3( 0.0f, 0.0f, -1.0f ) },

{ D3DXVECTOR3( -1.0f, -1.0f, 1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 1.0f ) },
{ D3DXVECTOR3(  1.0f, -1.0f, 1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 1.0f ) },
{ D3DXVECTOR3(  1.0f,  1.0f, 1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 1.0f ) },
{ D3DXVECTOR3( -1.0f,  1.0f, 1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 1.0f ) },
};*/

SimpleVertex vertices[] =
{
{ D3DXVECTOR3( -1.0f,  1.0f, -1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 0.0f ) },
{ D3DXVECTOR3(  1.0f,  1.0f, -1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 0.0f ) },
{ D3DXVECTOR3(  1.0f,  1.0f,  1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 0.0f ) },
{ D3DXVECTOR3( -1.0f,  1.0f,  1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 0.0f ) },

{ D3DXVECTOR3( -1.0f, -1.0f, -1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 0.0f ) },
{ D3DXVECTOR3(  1.0f, -1.0f, -1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 0.0f ) },
{ D3DXVECTOR3(  1.0f, -1.0f,  1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 0.0f ) },
{ D3DXVECTOR3( -1.0f, -1.0f,  1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 0.0f ) },

{ D3DXVECTOR3( -1.0f, -1.0f,  1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 0.0f ) },
{ D3DXVECTOR3( -1.0f, -1.0f, -1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 0.0f ) },
{ D3DXVECTOR3( -1.0f,  1.0f, -1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 0.0f ) },
{ D3DXVECTOR3( -1.0f,  1.0f,  1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 0.0f ) },

{ D3DXVECTOR3( 1.0f, -1.0f,  1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 0.0f ) },
{ D3DXVECTOR3( 1.0f, -1.0f, -1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 0.0f ) },
{ D3DXVECTOR3( 1.0f,  1.0f, -1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 0.0f ) },
{ D3DXVECTOR3( 1.0f,  1.0f,  1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 0.0f ) },

{ D3DXVECTOR3( -1.0f, -1.0f, -1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 0.0f ) },
{ D3DXVECTOR3(  1.0f, -1.0f, -1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 0.0f ) },
{ D3DXVECTOR3(  1.0f,  1.0f, -1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 0.0f ) },
{ D3DXVECTOR3( -1.0f,  1.0f, -1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 0.0f ) },

{ D3DXVECTOR3( -1.0f, -1.0f, 1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 0.0f ) },
{ D3DXVECTOR3(  1.0f, -1.0f, 1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 0.0f ) },
{ D3DXVECTOR3(  1.0f,  1.0f, 1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 0.0f ) },
{ D3DXVECTOR3( -1.0f,  1.0f, 1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 0.0f ) },
};

int numVertices = sizeof(vertices) / sizeof(SimpleVertex);

D3D10_BUFFER_DESC bd;
bd.Usage = D3D10_USAGE_DEFAULT;
bd.ByteWidth = sizeof(SimpleVertex) * numVertices;
bd.BindFlags = D3D10_BIND_VERTEX_BUFFER;
bd.CPUAccessFlags = 0;
bd.MiscFlags = 0;
D3D10_SUBRESOURCE_DATA InitData;
InitData.pSysMem = vertices;
hr = pD3DDevice->CreateBuffer( &bd, &InitData, &g_pVertexBuffer );
if( FAILED(hr) )
return false;

UINT stride = sizeof( SimpleVertex );
UINT offset = 0;
pD3DDevice->IASetVertexBuffers( 0, 1, &g_pVertexBuffer, &stride, &offset );

DWORD indices[] =
{
3,1,0,
2,1,3,

6,4,5,
7,4,6,

11,9,8,
10,9,11,

14,12,13,
15,12,14,

19,17,16,
18,17,19,

22,20,21,
23,20,22
};

UINT numIndices = sizeof(indices) / sizeof(DWORD);

for(UINT i = 0; i < numIndices; i+=3)
{
D3DXVECTOR3 v0 = vertices[indices].Pos;
D3DXVECTOR3 v1 = vertices[indices[i + 1]].Pos;
D3DXVECTOR3 v2 = vertices[indices[i + 2]].Pos;

D3DXVECTOR3 normal;
D3DXVECTOR3 cross;
D3DXVec3Cross(&cross, &D3DXVECTOR3(v2 - v0), &D3DXVECTOR3(v1 - v0));
D3DXVec3Normalize(&normal, &cross);

vertices[indices].Normal = -normal;
vertices[indices[i + 1]].Normal = -normal;
vertices[indices[i + 2]].Normal = -normal;
}

bd.Usage = D3D10_USAGE_DEFAULT;
bd.ByteWidth = sizeof(DWORD) * numIndices;
bd.BindFlags = D3D10_BIND_INDEX_BUFFER;
bd.CPUAccessFlags = 0;
bd.MiscFlags = 0;
InitData.pSysMem = indices;
hr = pD3DDevice->CreateBuffer( &bd, &InitData, &g_pIndexBuffer );
if( FAILED(hr) )
return true;

pD3DDevice->IASetIndexBuffer( g_pIndexBuffer, DXGI_FORMAT_R32_UINT, 0 );

// Set primitive topology
pD3DDevice->IASetPrimitiveTopology( D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST );

// Initialize the world matrices
D3DXMatrixIdentity( &g_World );

// Initialize the view matrix
D3DXVECTOR3 Eye( 0.0f, 4.0f, -10.0f );
D3DXVECTOR3 At( 0.0f, 1.0f, 0.0f );
D3DXVECTOR3 Up( 0.0f, 1.0f, 0.0f );
D3DXMatrixLookAtLH( &g_View, &Eye, &At, &Up );

// Initialize the projection matrix
D3DXMatrixPerspectiveFovLH( &g_Projection, (float)D3DX_PI * 0.25f, width/(FLOAT)height, 0.1f, 100.0f );

return true;
}

matrix World;
matrix View;
matrix Projection;
float4 vLightDir[2];
float4 vLightColor[2];
float4 vOutputColor;

//--------------------------------------------------------------------------------------
struct VS_INPUT
{
float4 Pos : POSITION;
float3 Normal : NORMAL;
};

// PS_INPUT - input variables to the pixel shader
// This struct is created and fill in by the
struct PS_INPUT
{
float4 Pos : SV_POSITION;
float3 Normal : TEXCOORD0;
};

////////////////////////////////////////////////
// Vertex Shader - Main Function
///////////////////////////////////////////////
PS_INPUT VS(VS_INPUT input)
{
PS_INPUT output;

output.Pos = mul(input.Pos, World);
output.Pos = mul(output.Pos, View);
output.Pos = mul(output.Pos, Projection);
output.Normal = mul(input.Normal, World);

return output;
}

///////////////////////////////////////////////
///////////////////////////////////////////////
float4 PS(PS_INPUT input) : SV_Target
{
float4 finalColor = 0;

//do NdotL lighting for 2 lights
for(int i=0; i<2; i++)
{
finalColor += saturate( dot( (float3)vLightDir,input.Normal) * vLightColor );
}
finalColor.a = 1;
return finalColor;
}

//--------------------------------------------------------------------------------------
// PSSolid - render a solid color
//--------------------------------------------------------------------------------------
float4 PSSolid( PS_INPUT input) : SV_Target
{
return vOutputColor;
}

// Define the technique
technique10 Render
{
pass P0
{
}
}

technique10 RenderLight
{
pass P0
{
}
}

Can somebody tell me how can I fix this while still using the algorithm for computing the normals?

Share on other sites
It looks like you set the normals for the vertices array after you create the vertex buffer. So the mesh will have normals all = (0,0,0).

Modify the vertices array and then create the vertex buffer.

EDIT: A quick trouble-shooting technique for meshes (if it loads but doesn't display correctly) is to dump the mesh to an x-file in text format once it's created. (D3DXSaveMeshToX) Then you can examine all the values (vertex positions, normals, tex coords, indices, etc.). If you were to do that, you'll see that all your normals are (0,0,0) and that might quickly lead you to the solution for your problem.

Share on other sites
Thank you, that was it.

I have modified the code and it works now. :D

Share on other sites
Alternatively, you can use PIX to examine what values are being fed to the VS.

Share on other sites
Quote:
 Alternatively, you can use PIX to examine what values are being fed to the VS.

What's that? How do I use it?

BTW: thanks for the tip on dumping the data into a file.

Share on other sites
PIX is an utilities gived with SDK.
PIXWin.exe is in the folder Utilities\Bin\x86 (or x64) of your SDK's folder. You just have to do file->New Experiment and follow instructions.

[Edited by - Squallc on July 7, 2008 6:52:24 PM]

• What is your GameDev Story?

In 2019 we are celebrating 20 years of GameDev.net! Share your GameDev Story with us.

• 9
• 13
• 9
• 9
• 15
• Forum Statistics

• Total Topics
634075
• Total Posts
3015349
×