Sign in to follow this  
Matruz

DirectX 10 lightning example

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[i]].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[i]].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);
			}
			//additional game logic...
			
			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.lpszMenuName = NULL;	//the resource name for the menu
	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};
	AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);

	//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;
	pD3DDevice->RSSetViewports(1, &viewPort);

	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()
{
	DWORD dwShaderFlags = D3D10_SHADER_ENABLE_STRICTNESS;

	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[i]].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[i]].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;
}
And the shader file:
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 
// vertex shader
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;
}

///////////////////////////////////////////////
// Pixel Shader
///////////////////////////////////////////////
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[i],input.Normal) * vLightColor[i] );
    }
    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
    {
        SetVertexShader( CompileShader( vs_4_0, VS() ) );
        SetGeometryShader( NULL );
        SetPixelShader( CompileShader( ps_4_0, PS() ) );
    }
}

technique10 RenderLight
{
    pass P0
    {
        SetVertexShader( CompileShader( vs_4_0, VS() ) );
        SetGeometryShader( NULL );
        SetPixelShader( CompileShader( ps_4_0, PSSolid() ) );
    }
}
Can somebody tell me how can I fix this while still using the algorithm for computing the normals?

Share this post


Link to post
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 this post


Link to post
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 this post


Link to post
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]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this