1
\$\begingroup\$

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.

enter image description here

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); } 
\$\endgroup\$
3
  • \$\begingroup\$ Note that most of these Internet Direct3D 11 tutorials are woefully outdated and make extensive use of the legacy DirectX SDK and the deprecated D3DX11 library (see MSDN. You should look at the various replacements and consider using the DirectX Tool Kit tutorials. \$\endgroup\$ Commented Sep 25, 2016 at 3:44
  • \$\begingroup\$ You're not giving us the layout of your Light or cbPerFrame structs on the C++ side - please update your code to include those. \$\endgroup\$ Commented Sep 25, 2016 at 4:45
  • \$\begingroup\$ @LeComteduMerde-fou I just edited my question to add the header file containing the Light & cbPerFrame structs. \$\endgroup\$ Commented Sep 25, 2016 at 6:46

2 Answers 2

1
\$\begingroup\$

You should add lighting info (specular, ambient, diffuse), then multiply with color. Try this:

finalColor = diffuse; finalColor *= saturate(dot(input.normal, -light.dir)) * light.diffuse + light.ambient; 
\$\endgroup\$
2
  • \$\begingroup\$ I tried this but I still get the same results. I asked this exact same question over at gamedev.net, I didn't seem to understand what they were trying to say could you explain some of their answers?: gamedev.net/topic/682496-problem-with-diffuse-lighting/… \$\endgroup\$ Commented Sep 25, 2016 at 6:27
  • 1
    \$\begingroup\$ I am struggling with learning matrix operations myself. But as I understand, world holds translation, rotate and scale. In a normal case, your translation would be zero, rotation also zero and scale will be 1, makes sense. There is code for that in there but world is empty indeed. Why not try world = cube1world; \$\endgroup\$ Commented Sep 25, 2016 at 11:15
0
\$\begingroup\$

So @vtastek spotted that I hadn't set the world matrix for World in my .FX file which meant I had been multiplying my Normals by an Empty matrix.

output.normal = mul(normal, World); 

Basically what solved my problem was setting the World matrix in my main.cpp to

cbPerObj.World = XMMatrixTranspose(cube1World); 

Well spotted vtastek. Man that Diffuse Lighting is looking good ;)

enter image description here

\$\endgroup\$

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.