diff --git a/enginecustom/Lightshaderclass.h b/enginecustom/Lightshaderclass.h index dd45b3d..bd072db 100644 --- a/enginecustom/Lightshaderclass.h +++ b/enginecustom/Lightshaderclass.h @@ -3,7 +3,7 @@ //////////////////////////////////////////////////////////////////////////////// #ifndef _LIGHTSHADERCLASS_H_ #define _LIGHTSHADERCLASS_H_ - +#pragma once ///////////// // GLOBALS // diff --git a/enginecustom/applicationclass.cpp b/enginecustom/applicationclass.cpp index a5a9355..3e105c1 100644 --- a/enginecustom/applicationclass.cpp +++ b/enginecustom/applicationclass.cpp @@ -29,6 +29,9 @@ ApplicationClass::ApplicationClass() : m_ShouldQuit(false) m_terrainChunk.clear(); m_object.clear(); m_RenderQueues.clear(); + m_Skybox.clear(); + m_Lights.clear(); + m_SunLight = 0; } ApplicationClass::~ApplicationClass() @@ -274,6 +277,15 @@ bool ApplicationClass::Initialize(int screenWidth, int screenHeight, HWND hwnd) m_Lights[3]->SetSpecularPower(16.0f); m_Lights[3]->SetPosition(-10.0f, 7.0f, 5.0f); + // Create || THE SUN || + m_SunLight = new LightClass; + m_SunLight->SetDiffuseColor(1.0f, 1.0f, 1.0f, 1.0f); // White + m_SunLight->SetDirection(0.0f, -1.0f, 0.0f); + m_SunLight->SetAmbientColor(0.15f, 0.15f, 0.15f, 1.0f); + m_SunLight->SetSpecularColor(1.0f, 1.0f, 1.0f, 1.0f); + m_SunLight->SetSpecularPower(16.0f); + m_SunLight->SetPosition(0.0f, 100.0f, 0.0f); + // Create and initialize the normal map shader object. m_ShaderManager = new ShaderManagerClass; @@ -1442,15 +1454,11 @@ void ApplicationClass::GenerateTerrain() { Object* newTerrain = new Object(); newTerrain->Initialize(m_Direct3D->GetDevice(), m_Direct3D->GetDeviceContext(), modelFilename, textures); - newTerrain->SetScaleMatrix(scaleMatrix); - newTerrain->SetTranslateMatrix(XMMatrixTranslation(i / 2 * scaleX , -12.0f, j * scaleZ)); - newTerrain->SetName(filenameWithoutExtension); - newTerrain->SetType(ObjectType::Cube); - + newTerrain->SetActiveShader(Object::SUNLIGHT); m_terrainChunk.push_back(newTerrain); } @@ -1922,6 +1930,8 @@ bool ApplicationClass::RenderPass(const std::vectorRenderlightShader(m_Direct3D->GetDeviceContext(), object->GetIndexCount(), worldMatrix, view, projection, object->GetTexture(0), diffuse, position, ambient); @@ -1931,6 +1941,16 @@ bool ApplicationClass::RenderPass(const std::vectorRenderSunlightShader(m_Direct3D->GetDeviceContext(), object->GetIndexCount(), worldMatrix, view, projection, + object->GetTexture(0), m_SunLight->GetDiffuseColor(), m_SunLight->GetPosition(), m_SunLight->GetAmbientColor()); + if (!result) + { + Logger::Get().Log("Could not render the object model using the sunlight shader", __FILE__, __LINE__, Logger::LogLevel::Error); + return false; + } + break; default: result = m_ShaderManager->RenderlightShader(m_Direct3D->GetDeviceContext(), object->GetIndexCount(), worldMatrix, view, projection, object->GetTexture(0), diffuse, position, ambient); diff --git a/enginecustom/applicationclass.h b/enginecustom/applicationclass.h index 61d78d9..b4d4200 100644 --- a/enginecustom/applicationclass.h +++ b/enginecustom/applicationclass.h @@ -201,6 +201,7 @@ private : LightClass* m_Light; std::vector m_Lights; int m_numLights; + LightClass* m_SunLight; XMFLOAT3 TrueLightPosition; ModelClass* m_LightModel; diff --git a/enginecustom/enginecustom.vcxproj b/enginecustom/enginecustom.vcxproj index 530c5d6..c805cfc 100644 --- a/enginecustom/enginecustom.vcxproj +++ b/enginecustom/enginecustom.vcxproj @@ -62,6 +62,7 @@ + @@ -118,6 +119,7 @@ + @@ -207,6 +209,12 @@ Document + + Document + + + Document + diff --git a/enginecustom/enginecustom.vcxproj.filters b/enginecustom/enginecustom.vcxproj.filters index fc655b2..b2cde4c 100644 --- a/enginecustom/enginecustom.vcxproj.filters +++ b/enginecustom/enginecustom.vcxproj.filters @@ -222,6 +222,9 @@ Fichiers sources\System + + Fichiers sources\Shader + @@ -389,6 +392,9 @@ Fichiers d%27en-tĂȘte\System + + Fichiers d%27en-tĂȘte\Shader + @@ -644,5 +650,11 @@ Assets\Skybox + + shader + + + shader + \ No newline at end of file diff --git a/enginecustom/imgui.ini b/enginecustom/imgui.ini index e009bf2..c490a08 100644 --- a/enginecustom/imgui.ini +++ b/enginecustom/imgui.ini @@ -25,13 +25,12 @@ DockId=0x00000009,0 Pos=8,27 Size=330,487 Collapsed=0 -DockId=0x00000004,1 [Window][Shader Manager] Pos=8,27 Size=330,487 Collapsed=0 -DockId=0x00000004,2 +DockId=0x00000001,2 [Window][Engine Settings] Pos=1180,27 @@ -73,9 +72,7 @@ DockId=0x0000000E,0 [Docking][Data] DockSpace ID=0xC0DFADC4 Pos=8,27 Size=1568,826 Split=X - DockNode ID=0x00000001 Parent=0xC0DFADC4 SizeRef=330,1094 Split=Y Selected=0x393905AB - DockNode ID=0x00000004 Parent=0x00000001 SizeRef=330,487 Selected=0x393905AB - DockNode ID=0x00000006 Parent=0x00000001 SizeRef=330,485 Selected=0x031DC75C + DockNode ID=0x00000001 Parent=0xC0DFADC4 SizeRef=330,1094 Selected=0x393905AB DockNode ID=0x00000003 Parent=0xC0DFADC4 SizeRef=1700,1094 CentralNode=1 DockSpace ID=0xCCBD8CF7 Window=0x3DA2F1DE Pos=8,27 Size=1568,826 Split=Y DockNode ID=0x0000000D Parent=0xCCBD8CF7 SizeRef=1568,598 Split=Y diff --git a/enginecustom/lightshaderclass.h b/enginecustom/lightshaderclass.h index dd45b3d..bd072db 100644 --- a/enginecustom/lightshaderclass.h +++ b/enginecustom/lightshaderclass.h @@ -3,7 +3,7 @@ //////////////////////////////////////////////////////////////////////////////// #ifndef _LIGHTSHADERCLASS_H_ #define _LIGHTSHADERCLASS_H_ - +#pragma once ///////////// // GLOBALS // diff --git a/enginecustom/object.h b/enginecustom/object.h index cb9048d..a734e39 100644 --- a/enginecustom/object.h +++ b/enginecustom/object.h @@ -76,7 +76,8 @@ public: REFLECTION, REFRACTION, TEXTURE, - SKYBOX + SKYBOX, + SUNLIGHT }; ShaderType GetActiveShader() const { return m_activeShader; }; diff --git a/enginecustom/shadermanagerclass.cpp b/enginecustom/shadermanagerclass.cpp index d1bd191..eb85b21 100644 --- a/enginecustom/shadermanagerclass.cpp +++ b/enginecustom/shadermanagerclass.cpp @@ -134,6 +134,13 @@ bool ShaderManagerClass::Initialize(ID3D11Device* device, HWND hwnd) return false; } + m_SunlightShader = new SunlightShaderClass; + result = m_SunlightShader->Initialize(device, hwnd); + if (!result) + { + return false; + } + Logger::Get().Log("ShaderManagerClass initialized", __FILE__, __LINE__, Logger::LogLevel::Initialize); return true; @@ -239,6 +246,13 @@ void ShaderManagerClass::Shutdown() m_CelShadingShader = 0; } + if (m_SunlightShader) + { + m_SunlightShader->Shutdown(); + delete m_SunlightShader; + m_SunlightShader = 0; + } + Logger::Get().Log("ShaderManagerClass shut down", __FILE__, __LINE__, Logger::LogLevel::Shutdown); } @@ -419,4 +433,18 @@ bool ShaderManagerClass::RenderCelShadingShader(ID3D11DeviceContext* deviceConte } return true; +} + +bool ShaderManagerClass::RenderSunlightShader(ID3D11DeviceContext* deviceContext, int indexCount, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix, + ID3D11ShaderResourceView* texture, XMFLOAT4 ambientColor, XMFLOAT4 diffuseColor, XMFLOAT4 sunColor) +{ + bool result; + + result = m_SunlightShader->Render(deviceContext, indexCount, worldMatrix, viewMatrix, projectionMatrix, texture, ambientColor, diffuseColor, sunColor); + if (!result) + { + return false; + } + + return true; } \ No newline at end of file diff --git a/enginecustom/shadermanagerclass.h b/enginecustom/shadermanagerclass.h index d79c8ae..b341f51 100644 --- a/enginecustom/shadermanagerclass.h +++ b/enginecustom/shadermanagerclass.h @@ -17,6 +17,7 @@ #include "refractionshaderclass.h" #include "watershaderclass.h" #include "celshadingshader.h" +#include "sunlightshaderclass.h" using namespace DirectX; @@ -42,8 +43,7 @@ public: bool RenderRefractionShader(ID3D11DeviceContext*, int, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, XMFLOAT3, XMFLOAT4[], XMFLOAT4[], XMFLOAT4[], XMFLOAT4); bool RenderWaterShader(ID3D11DeviceContext*, int, XMMATRIX, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, ID3D11ShaderResourceView*, ID3D11ShaderResourceView*, float, float); bool RenderCelShadingShader(ID3D11DeviceContext*, int, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, XMFLOAT3, XMFLOAT4, XMFLOAT3); - bool RenderSkyboxShader(ID3D11DeviceContext*, int, XMMATRIX, XMMATRIX, XMMATRIX, const std::vector&); - + bool RenderSunlightShader(ID3D11DeviceContext*, int, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, XMFLOAT4, XMFLOAT4, XMFLOAT4); private: TextureShaderClass* m_TextureShader; NormalMapShaderClass* m_NormalMapShader; @@ -57,7 +57,7 @@ private: RefractionShaderClass* m_RefractionShader; WaterShaderClass* m_WaterShader; CelShadingShader* m_CelShadingShader; + SunlightShaderClass* m_SunlightShader; }; -#endif - +#endif \ No newline at end of file diff --git a/enginecustom/sunlight.ps b/enginecustom/sunlight.ps new file mode 100644 index 0000000..6079dae --- /dev/null +++ b/enginecustom/sunlight.ps @@ -0,0 +1,69 @@ +///////////// +// GLOBALS // +///////////// +Texture2D shaderTexture : register(t0); +SamplerState SampleType : register(s0); +cbuffer SunLightBuffer +{ + float4 ambientColor; + float3 lightDirection; + float padding; + float specularPower; + float4 specularColor; +}; + +cbuffer SunLightColorBuffer +{ + float4 sunColor; +}; + + +////////////// +// TYPEDEFS // +////////////// +struct PixelInputType +{ + float4 position : SV_POSITION; + float2 tex : TEXCOORD0; + float3 normal : NORMAL; + float3 sunPos : TEXCOORD1; +}; + + +//////////////////////////////////////////////////////////////////////////////// +// Pixel Shader +//////////////////////////////////////////////////////////////////////////////// +float4 SunLightPixelShader(PixelInputType input) : SV_TARGET +{ + float4 textureColor; + float3 lightDir; + float4 color; + float3 reflection; + float4 specular; + float lightIntensity; + float4 colorArray; + float4 colorSum; + int i; + + // Sample the pixel color from the texture using the sampler at this texture coordinate location. + textureColor = shaderTexture.Sample(SampleType, input.tex); + + // Calculate the different amounts of light on this pixel based on the positions of the lights. + lightIntensity = saturate(dot(input.normal, input.sunPos)); + + // Determine the diffuse color amount of each of the four lights. + colorArray = sunColor * lightIntensity; + + // Initialize the sum of colors. + colorSum = float4(0.0f, 0.0f, 0.0f, 1.0f); + + // Add all of the light colors up. + colorSum.r += colorArray.r; + colorSum.g += colorArray.g; + colorSum.b += colorArray.b; + + // Multiply the texture pixel by the combination of all four light colors to get the final result. + color = saturate(colorSum) * textureColor; + + return color; +} \ No newline at end of file diff --git a/enginecustom/sunlight.vs b/enginecustom/sunlight.vs new file mode 100644 index 0000000..d368d88 --- /dev/null +++ b/enginecustom/sunlight.vs @@ -0,0 +1,78 @@ +///////////// +// GLOBALS // +///////////// +cbuffer MatrixBuffer +{ + matrix worldMatrix; + matrix viewMatrix; + matrix projectionMatrix; +}; + +cbuffer CameraBuffer +{ + float3 cameraPosition; + float padding; +}; + +cbuffer SunLightPositionBuffer +{ + float4 sunPosition; +}; + +////////////// +// TYPEDEFS // +////////////// +struct VertexInputType +{ + float4 position : POSITION; + float2 tex : TEXCOORD0; + float3 normal : NORMAL; +}; + +struct PixelInputType +{ + float4 position : SV_POSITION; + float2 tex : TEXCOORD0; + float3 normal : NORMAL; + float3 lightPos : TEXCOORD1; +}; + + +//////////////////////////////////////////////////////////////////////////////// +// Vertex Shader +//////////////////////////////////////////////////////////////////////////////// +PixelInputType SunLightVertexShader(VertexInputType input) +{ + PixelInputType output; + float4 worldPosition; + int i; + + // Change the position vector to be 4 units for proper matrix calculations. + input.position.w = 1.0f; + + // Calculate the position of the vertex against the world, view, and projection matrices. + output.position = mul(input.position, worldMatrix); + output.position = mul(output.position, viewMatrix); + output.position = mul(output.position, projectionMatrix); + + // Store the texture coordinates for the pixel shader. + output.tex = input.tex; + + // Calculate the normal vector against the world matrix only. + output.normal = mul(input.normal, (float3x3) worldMatrix); + + // Normalize the normal vector. + output.normal = normalize(output.normal); + + // Calculate the position of the vertex in the world. + worldPosition = mul(input.position, worldMatrix); + + // Determine the light positions based on the position of the lights and the position of the vertex in the world. + output.lightPos = sunPosition.xyz - worldPosition.xyz; + + // Normalize the light position vectors. + output.lightPos = normalize(output.lightPos); + + + return output; +} \ No newline at end of file diff --git a/enginecustom/sunlightshaderclass.cpp b/enginecustom/sunlightshaderclass.cpp new file mode 100644 index 0000000..1da78ac --- /dev/null +++ b/enginecustom/sunlightshaderclass.cpp @@ -0,0 +1,538 @@ +//////////////////////////////////////////////////////////////////////////////// +// Filename: lightshaderclass.cpp +//////////////////////////////////////////////////////////////////////////////// +#include "sunlightshaderclass.h" + + +SunlightShaderClass::SunlightShaderClass() +{ + m_vertexShader = 0; + m_pixelShader = 0; + m_layout = 0; + m_sampleState = 0; + m_matrixBuffer = 0; + m_cameraBuffer = 0; + m_sunlightBuffer = 0; + m_sunlightColorBuffer = 0; + m_sunlightPositionBuffer = 0; +} + + +SunlightShaderClass::SunlightShaderClass(const SunlightShaderClass& other) +{ +} + + +SunlightShaderClass::~SunlightShaderClass() +{ +} + + +bool SunlightShaderClass::Initialize(ID3D11Device* device, HWND hwnd) +{ + Logger::Get().Log("Initializing LightShaderClass", __FILE__, __LINE__, Logger::LogLevel::Initialize); + + wchar_t vsFilename[128]; + wchar_t psFilename[128]; + int error; + bool result; + + // Set the filename of the vertex shader. + error = wcscpy_s(vsFilename, 128, L"sunlight.vs"); + if (error != 0) + { + Logger::Get().Log("Failed to copy string", __FILE__, __LINE__, Logger::LogLevel::Error); + return false; + } + + // Set the filename of the pixel shader. + error = wcscpy_s(psFilename, 128, L"sunlight.ps"); + if (error != 0) + { + Logger::Get().Log("Failed to copy string", __FILE__, __LINE__, Logger::LogLevel::Error); + return false; + } + // Initialize the vertex and pixel shaders. + result = InitializeShader(device, hwnd, vsFilename, psFilename); + if (!result) + { + Logger::Get().Log("Failed to initialize shader", __FILE__, __LINE__, Logger::LogLevel::Error); + return false; + } + + Logger::Get().Log("SunLightShaderClass initialized", __FILE__, __LINE__, Logger::LogLevel::Initialize); + + return true; +} + + +void SunlightShaderClass::Shutdown() +{ + // Shutdown the vertex and pixel shaders as well as the related objects. + ShutdownShader(); + + return; +} + +bool SunlightShaderClass::Render(ID3D11DeviceContext* deviceContext, int indexCount, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix, + ID3D11ShaderResourceView* texture, XMFLOAT4 diffuseColor, XMFLOAT4 lightPosition, XMFLOAT4 ambientClor) +{ + bool result; + + + // Set the shader parameters that it will use for rendering. + result = SetShaderParameters(deviceContext, worldMatrix, viewMatrix, projectionMatrix, texture, diffuseColor, lightPosition, ambientClor); + if (!result) + { + Logger::Get().Log("Failed to set shader parameters", __FILE__, __LINE__, Logger::LogLevel::Error); + return false; + } + + // Now render the prepared buffers with the shader. + RenderShader(deviceContext, indexCount); + + return true; +} + + +bool SunlightShaderClass::InitializeShader(ID3D11Device* device, HWND hwnd, WCHAR* vsFilename, WCHAR* psFilename) +{ + Logger::Get().Log("Initializing shader", __FILE__, __LINE__, Logger::LogLevel::Initialize); + + HRESULT result; + ID3D10Blob* errorMessage; + ID3D10Blob* vertexShaderBuffer; + ID3D10Blob* pixelShaderBuffer; + D3D11_INPUT_ELEMENT_DESC polygonLayout[3]; + unsigned int numElements; + D3D11_SAMPLER_DESC samplerDesc; + D3D11_BUFFER_DESC matrixBufferDesc; + D3D11_BUFFER_DESC cameraBufferDesc; + D3D11_BUFFER_DESC lightColorBufferDesc; + D3D11_BUFFER_DESC lightPositionBufferDesc; + + + // Initialize the pointers this function will use to null. + errorMessage = 0; + vertexShaderBuffer = 0; + pixelShaderBuffer = 0; + + // Compile the vertex shader code. + result = D3DCompileFromFile(vsFilename, NULL, NULL, "SunLightVertexShader", "vs_5_0", D3D10_SHADER_ENABLE_STRICTNESS, 0, &vertexShaderBuffer, &errorMessage); + if (FAILED(result)) + { + // If the shader failed to compile it should have writen something to the error message. + if (errorMessage) + { + OutputShaderErrorMessage(errorMessage, hwnd, vsFilename); + } + // If there was nothing in the error message then it simply could not find the shader file itself. + else + { + Logger::Get().Log("Failed to compile shader", __FILE__, __LINE__, Logger::LogLevel::Error); + } + + return false; + } + + // Compile the pixel shader code. + result = D3DCompileFromFile(psFilename, NULL, NULL, "SunLightPixelShader", "ps_5_0", D3D10_SHADER_ENABLE_STRICTNESS, 0, &pixelShaderBuffer, &errorMessage); + if (FAILED(result)) + { + // If the shader failed to compile it should have writen something to the error message. + if (errorMessage) + { + OutputShaderErrorMessage(errorMessage, hwnd, psFilename); + } + // If there was nothing in the error message then it simply could not find the file itself. + else + { + Logger::Get().Log("Failed to compile shader", __FILE__, __LINE__, Logger::LogLevel::Error); + } + + return false; + } + + // Create the vertex shader from the buffer. + result = device->CreateVertexShader(vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), NULL, &m_vertexShader); + if (FAILED(result)) + { + Logger::Get().Log("Failed to create vertex shader", __FILE__, __LINE__, Logger::LogLevel::Error); + return false; + } + + // Create the pixel shader from the buffer. + result = device->CreatePixelShader(pixelShaderBuffer->GetBufferPointer(), pixelShaderBuffer->GetBufferSize(), NULL, &m_pixelShader); + if (FAILED(result)) + { + Logger::Get().Log("Failed to create pixel shader", __FILE__, __LINE__, Logger::LogLevel::Error); + return false; + } + + // Create the vertex input layout description. + // This setup needs to match the VertexType stucture in the ModelClass and in the shader. + polygonLayout[0].SemanticName = "POSITION"; + polygonLayout[0].SemanticIndex = 0; + polygonLayout[0].Format = DXGI_FORMAT_R32G32B32_FLOAT; + polygonLayout[0].InputSlot = 0; + polygonLayout[0].AlignedByteOffset = 0; + polygonLayout[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + polygonLayout[0].InstanceDataStepRate = 0; + + polygonLayout[1].SemanticName = "TEXCOORD"; + polygonLayout[1].SemanticIndex = 0; + polygonLayout[1].Format = DXGI_FORMAT_R32G32_FLOAT; + polygonLayout[1].InputSlot = 0; + polygonLayout[1].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT; + polygonLayout[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + polygonLayout[1].InstanceDataStepRate = 0; + + polygonLayout[2].SemanticName = "NORMAL"; + polygonLayout[2].SemanticIndex = 0; + polygonLayout[2].Format = DXGI_FORMAT_R32G32B32_FLOAT; + polygonLayout[2].InputSlot = 0; + polygonLayout[2].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT; + polygonLayout[2].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + polygonLayout[2].InstanceDataStepRate = 0; + + // Get a count of the elements in the layout. + numElements = sizeof(polygonLayout) / sizeof(polygonLayout[0]); + + // Create the vertex input layout. + result = device->CreateInputLayout(polygonLayout, numElements, vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), + &m_layout); + if (FAILED(result)) + { + Logger::Get().Log("Failed to create input layout", __FILE__, __LINE__, Logger::LogLevel::Error); + return false; + } + + // Release the vertex shader buffer and pixel shader buffer since they are no longer needed. + vertexShaderBuffer->Release(); + vertexShaderBuffer = 0; + + pixelShaderBuffer->Release(); + pixelShaderBuffer = 0; + + // Create a texture sampler state description. + samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + samplerDesc.MipLODBias = 0.0f; + samplerDesc.MaxAnisotropy = 1; + samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + samplerDesc.BorderColor[0] = 0; + samplerDesc.BorderColor[1] = 0; + samplerDesc.BorderColor[2] = 0; + samplerDesc.BorderColor[3] = 0; + samplerDesc.MinLOD = 0; + samplerDesc.MaxLOD = D3D11_FLOAT32_MAX; + + // Create the texture sampler state. + result = device->CreateSamplerState(&samplerDesc, &m_sampleState); + if (FAILED(result)) + { + Logger::Get().Log("Failed to create sampler state", __FILE__, __LINE__, Logger::LogLevel::Error); + return false; + } + + // Setup the description of the dynamic matrix constant buffer that is in the vertex shader. + matrixBufferDesc.Usage = D3D11_USAGE_DYNAMIC; + matrixBufferDesc.ByteWidth = sizeof(MatrixBufferType); + matrixBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + matrixBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + matrixBufferDesc.MiscFlags = 0; + matrixBufferDesc.StructureByteStride = 0; + + // Create the constant buffer pointer so we can access the vertex shader constant buffer from within this class. + result = device->CreateBuffer(&matrixBufferDesc, NULL, &m_matrixBuffer); + if (FAILED(result)) + { + Logger::Get().Log("Failed to create matrix buffer", __FILE__, __LINE__, Logger::LogLevel::Error); + return false; + } + + + + // Setup the description of the camera dynamic constant buffer that is in the vertex shader. + cameraBufferDesc.Usage = D3D11_USAGE_DYNAMIC; + cameraBufferDesc.ByteWidth = sizeof(CameraBufferType); + cameraBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + cameraBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + cameraBufferDesc.MiscFlags = 0; + cameraBufferDesc.StructureByteStride = 0; + + // Create the camera constant buffer pointer so we can access the vertex shader constant buffer from within this class. + result = device->CreateBuffer(&cameraBufferDesc, NULL, &m_cameraBuffer); + if (FAILED(result)) + { + Logger::Get().Log("Failed to create camera buffer", __FILE__, __LINE__, Logger::LogLevel::Error); + return false; + } + + // Setup the description of the dynamic constant buffer that is in the pixel shader. + lightColorBufferDesc.Usage = D3D11_USAGE_DYNAMIC; + lightColorBufferDesc.ByteWidth = sizeof(SunLightColorBufferType); + lightColorBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + lightColorBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + lightColorBufferDesc.MiscFlags = 0; + lightColorBufferDesc.StructureByteStride = 0; + + // Create the constant buffer pointer so we can access the pixel shader constant buffer from within this class. + result = device->CreateBuffer(&lightColorBufferDesc, NULL, &m_sunlightColorBuffer); + if (FAILED(result)) + { + Logger::Get().Log("Failed to create sunlight color buffer", __FILE__, __LINE__, Logger::LogLevel::Error); + return false; + } + + // Setup the description of the dynamic constant buffer that is in the vertex shader. + lightPositionBufferDesc.Usage = D3D11_USAGE_DYNAMIC; + lightPositionBufferDesc.ByteWidth = sizeof(SunLightPositionBufferType); + lightPositionBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + lightPositionBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + lightPositionBufferDesc.MiscFlags = 0; + lightPositionBufferDesc.StructureByteStride = 0; + + // Create the constant buffer pointer so we can access the vertex shader constant buffer from within this class. + result = device->CreateBuffer(&lightPositionBufferDesc, NULL, &m_sunlightPositionBuffer); + if (FAILED(result)) + { + Logger::Get().Log("Failed to create sunlight position buffer", __FILE__, __LINE__, Logger::LogLevel::Error); + return false; + } + + Logger::Get().Log("Shader initialized", __FILE__, __LINE__, Logger::LogLevel::Initialize); + + return true; +} + + +void SunlightShaderClass::ShutdownShader() +{ + Logger::Get().Log("Shutting down SunLightShaderClass", __FILE__, __LINE__, Logger::LogLevel::Shutdown); + + // Release the light constant buffers. + if (m_sunlightColorBuffer) + { + m_sunlightColorBuffer->Release(); + m_sunlightColorBuffer = 0; + } + + if (m_sunlightPositionBuffer) + { + m_sunlightPositionBuffer->Release(); + m_sunlightPositionBuffer = 0; + } + + // Release the light constant buffer. + if (m_sunlightBuffer) + { + m_sunlightBuffer->Release(); + m_sunlightBuffer = 0; + } + + // Release the camera constant buffer. + if (m_cameraBuffer) + { + m_cameraBuffer->Release(); + m_cameraBuffer = 0; + } + + // Release the matrix constant buffer. + if (m_matrixBuffer) + { + m_matrixBuffer->Release(); + m_matrixBuffer = 0; + } + + // Release the sampler state. + if (m_sampleState) + { + m_sampleState->Release(); + m_sampleState = 0; + } + + // Release the layout. + if (m_layout) + { + m_layout->Release(); + m_layout = 0; + } + + // Release the pixel shader. + if (m_pixelShader) + { + m_pixelShader->Release(); + m_pixelShader = 0; + } + + // Release the vertex shader. + if (m_vertexShader) + { + m_vertexShader->Release(); + m_vertexShader = 0; + } + + Logger::Get().Log("SunLightShaderClass shut down", __FILE__, __LINE__, Logger::LogLevel::Shutdown); + + return; +} + + +void SunlightShaderClass::OutputShaderErrorMessage(ID3D10Blob* errorMessage, HWND hwnd, WCHAR* shaderFilename) +{ + char* compileErrors; + unsigned __int64 bufferSize, i; + ofstream fout; + + + // Get a pointer to the error message text buffer. + compileErrors = (char*)(errorMessage->GetBufferPointer()); + + // Get the length of the message. + bufferSize = errorMessage->GetBufferSize(); + + // Open a file to write the error message to. + fout.open("shader-error.txt"); + + // Write out the error message. + for (i = 0; i < bufferSize; i++) + { + fout << compileErrors[i]; + } + + // Close the file. + fout.close(); + + // Release the error message. + errorMessage->Release(); + errorMessage = 0; + + // Pop a message up on the screen to notify the user to check the text file for compile errors. + MessageBox(hwnd, L"Error compiling shader. Check shader-error.txt for message.", shaderFilename, MB_OK); + + return; +} + + +bool SunlightShaderClass::SetShaderParameters(ID3D11DeviceContext* deviceContext, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix, + ID3D11ShaderResourceView* texture, XMFLOAT4 diffuseColor, XMFLOAT4 lightPosition, XMFLOAT4 ambientColor) +{ + HRESULT result; + D3D11_MAPPED_SUBRESOURCE mappedResource; + unsigned int bufferNumber; + MatrixBufferType* dataPtr; + SunLightPositionBufferType* dataPtr2; + SunLightColorBufferType* dataPtr3; + + // Transpose the matrices to prepare them for the shader. + worldMatrix = XMMatrixTranspose(worldMatrix); + viewMatrix = XMMatrixTranspose(viewMatrix); + projectionMatrix = XMMatrixTranspose(projectionMatrix); + + // Lock the constant buffer so it can be written to. + result = deviceContext->Map(m_matrixBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + Logger::Get().Log("Failed to map matrix buffer", __FILE__, __LINE__, Logger::LogLevel::Error); + return false; + } + + // Get a pointer to the data in the constant buffer. + dataPtr = (MatrixBufferType*)mappedResource.pData; + + // Copy the matrices into the constant buffer. + dataPtr->world = worldMatrix; + dataPtr->view = viewMatrix; + dataPtr->projection = projectionMatrix; + + // Unlock the constant buffer. + deviceContext->Unmap(m_matrixBuffer, 0); + + // Set the position of the constant buffer in the vertex shader. + bufferNumber = 0; + + // Now set the constant buffer in the vertex shader with the updated values. + deviceContext->VSSetConstantBuffers(bufferNumber, 1, &m_matrixBuffer); + + // Lock the camera constant buffer so it can be written to. + result = deviceContext->Map(m_cameraBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + Logger::Get().Log("Failed to map camera buffer", __FILE__, __LINE__, Logger::LogLevel::Error); + return false; + } + + // Lock the light position constant buffer so it can be written to. + result = deviceContext->Map(m_sunlightPositionBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + Logger::Get().Log("Failed to map sunlight position buffer", __FILE__, __LINE__, Logger::LogLevel::Error); + return false; + } + + // Get a pointer to the data in the constant buffer. + dataPtr2 = (SunLightPositionBufferType*)mappedResource.pData; + + // Copy the light position variables into the constant buffer. + dataPtr2->sunPosition = lightPosition; + + // Unlock the constant buffer. + deviceContext->Unmap(m_sunlightPositionBuffer, 0); + + // Set the position of the constant buffer in the vertex shader. + bufferNumber = 1; + + // Finally set the constant buffer in the vertex shader with the updated values. + deviceContext->VSSetConstantBuffers(bufferNumber, 1, &m_sunlightPositionBuffer); + + // Set shader texture resource in the pixel shader. + deviceContext->PSSetShaderResources(0, 1, &texture); + + // Lock the light color constant buffer so it can be written to. + result = deviceContext->Map(m_sunlightColorBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + Logger::Get().Log("Failed to map sunlight color buffer", __FILE__, __LINE__, Logger::LogLevel::Error); + return false; + } + + // Get a pointer to the data in the constant buffer. + dataPtr3 = (SunLightColorBufferType*)mappedResource.pData; + + // Copy the light color variables into the constant buffer. + dataPtr3->sunColor = diffuseColor; + + // Unlock the constant buffer. + deviceContext->Unmap(m_sunlightColorBuffer, 0); + + // Set the position of the constant buffer in the pixel shader. + bufferNumber = 0; + + // Finally set the constant buffer in the pixel shader with the updated values. + deviceContext->PSSetConstantBuffers(bufferNumber, 1, &m_sunlightColorBuffer); + + + return true; +} + + +void SunlightShaderClass::RenderShader(ID3D11DeviceContext* deviceContext, int indexCount) +{ + // Set the vertex input layout. + deviceContext->IASetInputLayout(m_layout); + + // Set the vertex and pixel shaders that will be used to render this triangle. + deviceContext->VSSetShader(m_vertexShader, NULL, 0); + deviceContext->PSSetShader(m_pixelShader, NULL, 0); + + // Set the sampler state in the pixel shader. + deviceContext->PSSetSamplers(0, 1, &m_sampleState); + + // Render the triangle. + deviceContext->DrawIndexed(indexCount, 0, 0); + + return; +} diff --git a/enginecustom/sunlightshaderclass.h b/enginecustom/sunlightshaderclass.h new file mode 100644 index 0000000..ac8d35c --- /dev/null +++ b/enginecustom/sunlightshaderclass.h @@ -0,0 +1,75 @@ +#pragma once + +#include "Logger.h" +#include +#include +#include +#include +using namespace DirectX; +using namespace std; + +class SunlightShaderClass +{ + +private : + struct MatrixBufferType + { + XMMATRIX world; + XMMATRIX view; + XMMATRIX projection; + }; + + struct CameraBufferType + { + XMFLOAT3 cameraPosition; + float padding; + }; + + struct SunLightBufferType + { + XMFLOAT4 ambientColor; + XMFLOAT4 diffuseColor; + XMFLOAT3 lightDirection; + float padding; // Added extra padding so structure is a multiple of 16 for CreateBuffer function requirements. + float specularPower; + XMFLOAT4 specularColor; + }; + + struct SunLightColorBufferType + { + XMFLOAT4 sunColor; + }; + + struct SunLightPositionBufferType + { + XMFLOAT4 sunPosition; + }; + +public : + SunlightShaderClass(); + SunlightShaderClass(const SunlightShaderClass&); + ~SunlightShaderClass(); + + bool Initialize(ID3D11Device*, HWND); + void Shutdown(); + bool Render(ID3D11DeviceContext*, int, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, XMFLOAT4, XMFLOAT4, XMFLOAT4); + +private: + bool InitializeShader(ID3D11Device*, HWND, WCHAR*, WCHAR*); + void ShutdownShader(); + void OutputShaderErrorMessage(ID3D10Blob*, HWND, WCHAR*); + + bool SetShaderParameters(ID3D11DeviceContext*, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, XMFLOAT4, XMFLOAT4, XMFLOAT4); + void RenderShader(ID3D11DeviceContext*, int); + +private: + ID3D11VertexShader* m_vertexShader; + ID3D11PixelShader* m_pixelShader; + ID3D11InputLayout* m_layout; + ID3D11SamplerState* m_sampleState; + ID3D11Buffer* m_matrixBuffer; + ID3D11Buffer* m_cameraBuffer; + ID3D11Buffer* m_sunlightBuffer; + ID3D11Buffer* m_sunlightColorBuffer; + ID3D11Buffer* m_sunlightPositionBuffer; +}; \ No newline at end of file