So I am currently implementing Diffuse & Ambient Lighting based off this tutorial: https://www.braynzarsoft.net/viewtutorial/q16390-simple-lighting
I think I have implemented everything correctly, so the Ambient & Diffuse Light should work correctly but I just get Ambient Light. Can someone help me fix this? Here is my code.
HEADER.H
#pragma once #define SCREEN_WIDTH 800 #define SCREEN_HEIGHT 600 // include the basic windows header files and the Direct3D header files #include <windows.h> #include <windowsx.h> #include <d3d11.h> #include <d3dx11.h> #include <d3dx10.h> #include <DirectXMath.h> using namespace DirectX; // include the Direct3D Library file #pragma comment (lib, "d3d11.lib") #pragma comment (lib, "d3dx11.lib") #pragma comment (lib, "d3dx10.lib") // global declarations IDXGISwapChain *swapchain; // the pointer to the swap chain interface ID3D11Device *dev; // the pointer to our Direct3D device interface ID3D11DeviceContext *devcon; // the pointer to our Direct3D device context ID3D11RenderTargetView *backbuffer; // the pointer to our back buffer ID3D11Buffer* squareIndexBuffer; ID3D11Buffer* squareVertBuffer; ID3D11VertexShader* VS; ID3D11PixelShader* PS; ID3D10Blob* VS_Buffer; ID3D10Blob* PS_Buffer; ID3D11InputLayout* vertLayout; ID3D11Texture2D* pDepthStencil; ID3D11DepthStencilView* pDSV; ID3D11Buffer* cbPerObjectBuffer; ID3D11Buffer* cbPerFrameBuffer; ID3D11ShaderResourceView* CubesTexture; ID3D11SamplerState* CubesTexSamplerState; XMMATRIX WVP; XMMATRIX World; XMMATRIX camView; XMMATRIX camProjection; XMVECTOR camPosition; XMVECTOR camTarget; XMVECTOR camUp; XMMATRIX cube1World; XMMATRIX cube2World; XMMATRIX Rotation; XMMATRIX Scale; XMMATRIX Translation; float rot = 0.01f; // function prototypes void InitD3D(HWND hWnd); // sets up and initializes Direct3D void RenderFrame(void); // renders a single frame void CleanD3D(void); // closes Direct3D and releases memory void InitScene(void); void UpdateScene(void); D3D11_INPUT_ELEMENT_DESC layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 20, D3D11_INPUT_PER_VERTEX_DATA, 0 } }; UINT numElements = ARRAYSIZE(layout); struct cbPerObject { XMMATRIX WVP; XMMATRIX World; }; struct Vertex { Vertex() {} Vertex(float x, float y, float z, float u, float v, float nx, float ny, float nz) : pos(x, y, z), texCoord(u, v), normal(nx, ny, nz){} XMFLOAT3 pos; XMFLOAT2 texCoord; XMFLOAT3 normal; }; struct Light { Light() { ZeroMemory(this, sizeof(Light)); } XMFLOAT3 dir; float pad; XMFLOAT4 ambient; XMFLOAT4 diffuse; }; Light light; struct cbPerFrame { Light light; }; cbPerFrame constbuffPerFrame; MAIN.CPP
#include "Header.h" // the WindowProc function prototype LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); // the entry point for any Windows program int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { HWND hWnd; WNDCLASSEX wc; ZeroMemory(&wc, sizeof(WNDCLASSEX)); wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WindowProc; wc.hInstance = hInstance; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)COLOR_WINDOW; wc.lpszClassName = L"WindowClass"; RegisterClassEx(&wc); RECT wr = { 0, 0, 800, 600 }; AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE); hWnd = CreateWindowEx(NULL, L"WindowClass", L"Eagle Engine (Alpha)", WS_OVERLAPPEDWINDOW, SCREEN_WIDTH, SCREEN_HEIGHT, wr.right - wr.left, wr.bottom - wr.top, NULL, NULL, hInstance, NULL); ShowWindow(hWnd, nCmdShow); // set up and initialize Direct3D InitD3D(hWnd); // enter the main loop: MSG msg; while (TRUE) { if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); if (msg.message == WM_QUIT) break; } RenderFrame(); } // clean up DirectX and COM CleanD3D(); return msg.wParam; } // this is the main message handler for the program LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_DESTROY: { PostQuitMessage(0); return 0; } break; } return DefWindowProc(hWnd, message, wParam, lParam); } cbPerObject cbPerObj; // this function initializes and prepares Direct3D for use void InitD3D(HWND hWnd) { // create a struct to hold information about the swap chain DXGI_SWAP_CHAIN_DESC scd; // clear out the struct for use ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC)); HRESULT hr = S_OK; // fill the swap chain description struct scd.BufferCount = 2; // one back buffer scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; // use 32-bit color scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // how swap chain is to be used scd.OutputWindow = hWnd; // the window to be used scd.SampleDesc.Count = 8; // how many multisamples scd.SampleDesc.Quality = 1; scd.Windowed = TRUE; scd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; // allow full-screen switching// windowed/full-screen mode // create a device, device context and swap chain using the information in the scd struct hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, NULL, NULL, NULL, D3D11_SDK_VERSION, &scd, &swapchain, &dev, NULL, &devcon); // get the address of the back buffer ID3D11Texture2D *pBackBuffer; swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer); // use the back buffer address to create the render target dev->CreateRenderTargetView(pBackBuffer, NULL, &backbuffer); pBackBuffer->Release(); // set the render target as the back buffer devcon->OMSetRenderTargets(1, &backbuffer, NULL); ID3D11Texture2D* pDepthStencil = NULL; D3D11_TEXTURE2D_DESC descDepth; descDepth.Width = SCREEN_WIDTH; descDepth.Height = SCREEN_HEIGHT; descDepth.MipLevels = 1; descDepth.ArraySize = 1; descDepth.Format = DXGI_FORMAT_R32_TYPELESS; descDepth.SampleDesc.Count = scd.SampleDesc.Count; descDepth.SampleDesc.Quality = scd.SampleDesc.Quality; descDepth.Usage = D3D11_USAGE_DEFAULT; descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE; descDepth.CPUAccessFlags = 0; descDepth.MiscFlags = 0; hr = dev->CreateTexture2D(&descDepth, NULL, &pDepthStencil); D3D11_DEPTH_STENCIL_VIEW_DESC descDSV; descDSV.Format = DXGI_FORMAT_D32_FLOAT_S8X24_UINT; descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS; descDSV.Texture2D.MipSlice = 0; dev->CreateTexture2D(&descDepth, NULL, &pDepthStencil); // Create the depth stencil view ID3D11DepthStencilView* pDSV; hr = dev->CreateDepthStencilView(pDepthStencil, // Depth stencil texture &descDSV, // Depth stencil desc &pDSV); // [out] Depth stencil view devcon->OMSetRenderTargets(1, &backbuffer, pDSV); // Set the viewport D3D11_VIEWPORT viewport; ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT)); viewport.TopLeftX = 0; viewport.TopLeftY = 0; viewport.Width = SCREEN_WIDTH; viewport.Height = SCREEN_HEIGHT; viewport.MinDepth = 0.0f; viewport.MaxDepth = 1.0f; devcon->RSSetViewports(1, &viewport); //Create the buffer to send to the cbuffer in effect file D3D11_BUFFER_DESC cbbd; ZeroMemory(&cbbd, sizeof(D3D11_BUFFER_DESC)); cbbd.Usage = D3D11_USAGE_DEFAULT; cbbd.ByteWidth = sizeof(cbPerObject); cbbd.BindFlags = D3D11_BIND_CONSTANT_BUFFER; cbbd.CPUAccessFlags = 0; cbbd.MiscFlags = 0; dev->CreateBuffer(&cbbd, NULL, &cbPerObjectBuffer); ZeroMemory(&cbbd, sizeof(D3D11_BUFFER_DESC)); cbbd.Usage = D3D11_USAGE_DEFAULT; cbbd.ByteWidth = sizeof(cbPerFrame); cbbd.BindFlags = D3D11_BIND_CONSTANT_BUFFER; cbbd.CPUAccessFlags = 0; cbbd.MiscFlags = 0; dev->CreateBuffer(&cbbd, NULL, &cbPerFrameBuffer); //Camera information camPosition = XMVectorSet(-5.0f, 3.0f, -5.0f, 0.0f); //Position X,Y,Z camTarget = XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f); //Rotation X,Y,Z camUp = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f); //Set the View matrix camView = XMMatrixLookAtLH(camPosition, camTarget, camUp); //Set the Projection matrix camProjection = XMMatrixPerspectiveFovLH(0.4f*3.14f, (float)SCREEN_WIDTH/SCREEN_HEIGHT , 1.0f, 1000.0f); D3DX11CreateShaderResourceViewFromFile(dev, L"braynzar.jpg", NULL, NULL, &CubesTexture, NULL); D3D11_SAMPLER_DESC sampDesc; ZeroMemory(&sampDesc, sizeof(sampDesc)); sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; sampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; sampDesc.MinLOD = 0; sampDesc.MaxLOD = D3D11_FLOAT32_MAX; dev->CreateSamplerState(&sampDesc, &CubesTexSamplerState); InitScene(); UpdateScene(); } // this is the function used to render a single frame void RenderFrame(void) { //Clear our backbuffer float bgColor[4] = { (0.0f, 0.0f, 0.0f, 0.0f) }; devcon->ClearRenderTargetView(backbuffer, bgColor); //Refresh the Depth/Stencil view devcon->ClearDepthStencilView(pDSV, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); constbuffPerFrame.light = light; devcon->UpdateSubresource(cbPerFrameBuffer, 0, NULL, &constbuffPerFrame, 0, 0); devcon->PSSetConstantBuffers(0, 1, &cbPerFrameBuffer); ///////////////**************new**************//////////////////// //Set the WVP matrix and send it to the constant buffer in effect file WVP = cube1World * camView * camProjection; cbPerObj.WVP = XMMatrixTranspose(WVP); devcon->UpdateSubresource(cbPerObjectBuffer, 0, NULL, &cbPerObj, 0, 0); devcon->VSSetConstantBuffers(0, 1, &cbPerObjectBuffer); devcon->PSSetShaderResources(0, 1, &CubesTexture); devcon->PSSetSamplers(0, 1, &CubesTexSamplerState); //Draw the first cube devcon->DrawIndexed(36, 0, 0); WVP = cube2World * camView * camProjection; cbPerObj.WVP = XMMatrixTranspose(WVP); devcon->UpdateSubresource(cbPerObjectBuffer, 0, NULL, &cbPerObj, 0, 0); devcon->VSSetConstantBuffers(0, 1, &cbPerObjectBuffer); devcon->PSSetShaderResources(0, 1, &CubesTexture); devcon->PSSetSamplers(0, 1, &CubesTexSamplerState); //Draw the second cube devcon->DrawIndexed(36, 0, 0); ///////////////**************new**************//////////////////// //Present the backbuffer to the screen swapchain->Present(0, 0); }; // this is the function that cleans up Direct3D and COM void CleanD3D(void) { swapchain->SetFullscreenState(FALSE, NULL); // switch to windowed mode // close and release all existing COM objects swapchain->Release(); dev->Release(); backbuffer->Release(); devcon->Release(); squareIndexBuffer->Release(); squareVertBuffer->Release(); VS->Release(); PS->Release(); VS_Buffer->Release(); PS_Buffer->Release(); vertLayout->Release(); cbPerObjectBuffer->Release(); cbPerFrameBuffer->Release(); } void InitScene() { //Compile Shaders from shader file D3DX11CompileFromFile(L"Effects.fx", 0, 0, "VS", "vs_4_0", 0, 0, 0, &VS_Buffer, 0, 0); D3DX11CompileFromFile(L"Effects.fx", 0, 0, "PS", "ps_4_0", 0, 0, 0, &PS_Buffer, 0, 0); //Create the Shader Objects dev->CreateVertexShader(VS_Buffer->GetBufferPointer(), VS_Buffer->GetBufferSize(), NULL, &VS); dev->CreatePixelShader(PS_Buffer->GetBufferPointer(), PS_Buffer->GetBufferSize(), NULL, &PS); //Set Vertex and Pixel Shaders devcon->VSSetShader(VS, 0, 0); devcon->PSSetShader(PS, 0, 0); light.dir = XMFLOAT3(0.25f, 1.0f, 1.0f); light.ambient = XMFLOAT4(0.2f, 0.2f, 0.2f, 1.0f); light.diffuse = XMFLOAT4(1.0f, 1.0f, 2.0f, 5.0f); //Create the vertex buffer Vertex v[] = { // Front Face Vertex(-1.0f, -1.0f, -1.0f, 0.0f, 1.0f,-1.0f, -1.0f, -1.0f), Vertex(-1.0f, 1.0f, -1.0f, 0.0f, 0.0f,-1.0f, 1.0f, -1.0f), Vertex(1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, -1.0f), Vertex(1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f), // Back Face Vertex(-1.0f, -1.0f, 1.0f, 1.0f, 1.0f,-1.0f, -1.0f, 1.0f), Vertex(1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f), Vertex(1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f), Vertex(-1.0f, 1.0f, 1.0f, 1.0f, 0.0f,-1.0f, 1.0f, 1.0f), // Top Face Vertex(-1.0f, 1.0f, -1.0f, 0.0f, 1.0f,-1.0f, 1.0f, -1.0f), Vertex(-1.0f, 1.0f, 1.0f, 0.0f, 0.0f,-1.0f, 1.0f, 1.0f), Vertex(1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f), Vertex(1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f), // Bottom Face Vertex(-1.0f, -1.0f, -1.0f, 1.0f, 1.0f,-1.0f, -1.0f, -1.0f), Vertex(1.0f, -1.0f, -1.0f, 0.0f, 1.0f, 1.0f, -1.0f, -1.0f), Vertex(1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f), Vertex(-1.0f, -1.0f, 1.0f, 1.0f, 0.0f,-1.0f, -1.0f, 1.0f), // Left Face Vertex(-1.0f, -1.0f, 1.0f, 0.0f, 1.0f,-1.0f, -1.0f, 1.0f), Vertex(-1.0f, 1.0f, 1.0f, 0.0f, 0.0f,-1.0f, 1.0f, 1.0f), Vertex(-1.0f, 1.0f, -1.0f, 1.0f, 0.0f,-1.0f, 1.0f, -1.0f), Vertex(-1.0f, -1.0f, -1.0f, 1.0f, 1.0f,-1.0f, -1.0f, -1.0f), // Right Face Vertex(1.0f, -1.0f, -1.0f, 0.0f, 1.0f, 1.0f, -1.0f, -1.0f), Vertex(1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, -1.0f), Vertex(1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f), Vertex(1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f), }; DWORD indices[] = { // Front Face 0, 1, 2, 0, 2, 3, // Back Face 4, 5, 6, 4, 6, 7, // Top Face 8, 9, 10, 8, 10, 11, // Bottom Face 12, 13, 14, 12, 14, 15, // Left Face 16, 17, 18, 16, 18, 19, // Right Face 20, 21, 22, 20, 22, 23 }; D3D11_BUFFER_DESC indexBufferDesc; ZeroMemory(&indexBufferDesc, sizeof(indexBufferDesc)); indexBufferDesc.Usage = D3D11_USAGE_DEFAULT; indexBufferDesc.ByteWidth = sizeof(DWORD) * 12 * 3; indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; indexBufferDesc.CPUAccessFlags = 0; indexBufferDesc.MiscFlags = 0; D3D11_SUBRESOURCE_DATA iinitData; iinitData.pSysMem = indices; dev->CreateBuffer(&indexBufferDesc, &iinitData, &squareIndexBuffer); devcon->IASetIndexBuffer(squareIndexBuffer, DXGI_FORMAT_R32_UINT, 0); D3D11_BUFFER_DESC vertexBufferDesc; ZeroMemory(&vertexBufferDesc, sizeof(vertexBufferDesc)); vertexBufferDesc.Usage = D3D11_USAGE_DYNAMIC; vertexBufferDesc.ByteWidth = sizeof(Vertex) * 24; vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; vertexBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; vertexBufferDesc.MiscFlags = 0; D3D11_SUBRESOURCE_DATA vertexBufferData; ZeroMemory(&vertexBufferData, sizeof(vertexBufferData)); vertexBufferData.pSysMem = v; dev->CreateBuffer(&vertexBufferDesc, &vertexBufferData, &squareVertBuffer); //Set the vertex buffer UINT stride = sizeof(Vertex); UINT offset = 0; devcon->IASetVertexBuffers(0, 1, &squareVertBuffer, &stride, &offset); //Create the Input Layout dev->CreateInputLayout(layout, numElements, VS_Buffer->GetBufferPointer(), VS_Buffer->GetBufferSize(), &vertLayout); //Set the Input Layout devcon->IASetInputLayout(vertLayout); //Set Primitive Topology devcon->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); } void UpdateScene() { //Reset cube1World cube1World = XMMatrixIdentity(); Translation = XMMatrixTranslation(0.0f, 0.0f, 4.0f); //Define cube2's world space matrix Scale = XMMatrixScaling(1.3f, 1.3f, 1.3f); //Set cube1's world space using the transformations cube1World = Translation; //Reset cube2World cube2World = XMMatrixIdentity(); //Set cube2's world space matrix cube2World = Scale; } EFFECTS.FX
struct Light { float3 dir; float4 ambient; float4 diffuse; }; cbuffer cbPerFrame { Light light; }; cbuffer cbPerObject { float4x4 WVP; float4x4 World; }; Texture2D ObjTexture; SamplerState ObjSamplerState; struct VS_OUTPUT { float4 Pos : SV_POSITION; float2 TexCoord : TEXCOORD; float3 normal : NORMAL; }; VS_OUTPUT VS(float4 inPos : POSITION, float2 inTexCoord : TEXCOORD, float3 normal : NORMAL) { VS_OUTPUT output; output.Pos = mul(inPos, WVP); output.normal = mul(normal, World); output.TexCoord = inTexCoord; return output; } float4 PS(VS_OUTPUT input) : SV_TARGET { input.normal = normalize(input.normal); float4 diffuse = ObjTexture.Sample(ObjSamplerState, input.TexCoord); float3 finalColor; finalColor = diffuse * light.ambient; finalColor += saturate(dot(light.dir, input.normal) * light.diffuse * diffuse); return float4(finalColor, diffuse.a); } 
