From eea4518a0a674abd0cbbeb34242e5b09fefdcd80 Mon Sep 17 00:00:00 2001 From: CatChow0 Date: Tue, 24 Sep 2024 12:16:22 +0200 Subject: [PATCH 1/6] Cel Shading [WIP] + Cel shading shader + Shader Manager window --- enginecustom/CelShadingShader.cpp | 397 ++++++++++++++++++++++ enginecustom/CelShadingShader.h | 61 ++++ enginecustom/applicationclass.cpp | 12 + enginecustom/applicationclass.h | 4 + enginecustom/celshading.ps | 44 +++ enginecustom/celshading.vs | 37 ++ enginecustom/enginecustom.vcxproj | 8 + enginecustom/enginecustom.vcxproj.filters | 12 + enginecustom/imgui.ini | 4 + enginecustom/imguiManager.cpp | 21 ++ enginecustom/imguiManager.h | 6 + enginecustom/shadermanagerclass.cpp | 23 ++ enginecustom/shadermanagerclass.h | 3 + 13 files changed, 632 insertions(+) create mode 100644 enginecustom/CelShadingShader.cpp create mode 100644 enginecustom/CelShadingShader.h create mode 100644 enginecustom/celshading.ps create mode 100644 enginecustom/celshading.vs diff --git a/enginecustom/CelShadingShader.cpp b/enginecustom/CelShadingShader.cpp new file mode 100644 index 0000000..3745b30 --- /dev/null +++ b/enginecustom/CelShadingShader.cpp @@ -0,0 +1,397 @@ +#include "CelShadingShader.h" + +CelShadingShader::CelShadingShader() +{ + m_vertexShader = 0; + m_pixelShader = 0; + m_layout = 0; + m_matrixBuffer = 0; + m_sampleState = 0; + m_lightBuffer = 0; +} + +CelShadingShader::CelShadingShader(const CelShadingShader& other) +{ +} + +CelShadingShader::~CelShadingShader() +{ +} + +bool CelShadingShader::Initialize(ID3D11Device* device, HWND hwnd) +{ + Logger::Get().Log("Initializing CelShadingShader", __FILE__, __LINE__, Logger::LogLevel::Initialize); + + bool result; + wchar_t vsFilename[128]; + wchar_t psFilename[128]; + int error; + + // Set the filename of the vertex shader. + error = wcscpy_s(vsFilename, 128, L"celshading.vs"); + if (error != 0) + { + Logger::Get().Log("Failed to set the filename of the vertex shader", __FILE__, __LINE__); + return false; + } + + // Set the filename of the pixel shader. + error = wcscpy_s(psFilename, 128, L"celshading.ps"); + if (error != 0) + { + Logger::Get().Log("Failed to set the filename of the pixel shader", __FILE__, __LINE__); + return false; + } + + // Initialize the vertex and pixel shaders. + result = InitializeShader(device, hwnd, vsFilename, psFilename); + if (!result) + { + Logger::Get().Log("Failed to initialize the vertex and pixel shaders", __FILE__, __LINE__); + return false; + } + + Logger::Get().Log("Successfully initialized CelShadingShader", __FILE__, __LINE__, Logger::LogLevel::Initialize); + + return true; +} + +void CelShadingShader::Shutdown() +{ + // Shutdown the vertex and pixel shaders as well as the related objects. + ShutdownShader(); +} + +bool CelShadingShader::Render(ID3D11DeviceContext* deviceContext, int indexCount, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix, + ID3D11ShaderResourceView* texture, XMFLOAT3 lightDirection, XMFLOAT4 diffuseColor[]) +{ + bool result; + + // Set the shader parameters that it will use for rendering. + result = SetShaderParameters(deviceContext, worldMatrix, viewMatrix, projectionMatrix, texture, lightDirection, diffuseColor); + if (!result) + { + return false; + } + + // Now render the prepared buffers with the shader. + RenderShader(deviceContext, indexCount); + + return true; +} + +bool CelShadingShader::InitializeShader(ID3D11Device* device, HWND hwnd, WCHAR* vsFilename, WCHAR* psFilename) +{ + HRESULT result; + ID3D10Blob* errorMessage = nullptr; + ID3D10Blob* vertexShaderBuffer = nullptr; + ID3D10Blob* pixelShaderBuffer = nullptr; + D3D11_INPUT_ELEMENT_DESC polygonLayout[2]; + unsigned int numElements; + D3D11_BUFFER_DESC matrixBufferDesc; + D3D11_SAMPLER_DESC samplerDesc; + D3D11_BUFFER_DESC lightBufferDesc; + + // Compile the vertex shader code. + result = D3DCompileFromFile(vsFilename, nullptr, nullptr, "CelShadingVertexShader", "vs_5_0", D3D10_SHADER_ENABLE_STRICTNESS, 0, &vertexShaderBuffer, &errorMessage); + if (FAILED(result)) + { + // If the shader failed to compile it should have written 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 + { + MessageBox(hwnd, vsFilename, L"Missing Shader File", MB_OK); + } + + return false; + } + + // Compile the pixel shader code. + result = D3DCompileFromFile(psFilename, nullptr, nullptr, "CelShadingPixelShader", "ps_5_0", D3D10_SHADER_ENABLE_STRICTNESS, 0, &pixelShaderBuffer, &errorMessage); + if (FAILED(result)) + { + // If the shader failed to compile it should have written 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 + { + MessageBox(hwnd, psFilename, L"Missing Shader File", MB_OK); + } + + return false; + } + + // Create the vertex shader from the buffer. + result = device->CreateVertexShader(vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), nullptr, &m_vertexShader); + if (FAILED(result)) + { + return false; + } + + // Create the pixel shader from the buffer. + result = device->CreatePixelShader(pixelShaderBuffer->GetBufferPointer(), pixelShaderBuffer->GetBufferSize(), nullptr, &m_pixelShader); + if (FAILED(result)) + { + return false; + } + + // Create the vertex input layout description. + // This setup needs to match the VertexType structure 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; + + // 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)) + { + return false; + } + + // Release the vertex shader buffer and pixel shader buffer since they are no longer needed. + vertexShaderBuffer->Release(); + vertexShaderBuffer = nullptr; + + pixelShaderBuffer->Release(); + pixelShaderBuffer = nullptr; + + // 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, nullptr, &m_matrixBuffer); + if (FAILED(result)) + { + return false; + } + + // 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)) + { + return false; + } + + // Setup the description of the light dynamic constant buffer that is in the pixel shader. + lightBufferDesc.Usage = D3D11_USAGE_DYNAMIC; + lightBufferDesc.ByteWidth = sizeof(LightBufferType); + lightBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + lightBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + lightBufferDesc.MiscFlags = 0; + lightBufferDesc.StructureByteStride = 0; + + // Create the constant buffer pointer so we can access the pixel shader constant buffer from within this class. + result = device->CreateBuffer(&lightBufferDesc, nullptr, &m_lightBuffer); + if (FAILED(result)) + { + return false; + } + + return true; +} + + +void CelShadingShader::ShutdownShader() +{ + // Release the light constant buffer. + if (m_lightBuffer) + { + m_lightBuffer->Release(); + m_lightBuffer = nullptr; + } + + // Release the sampler state. + if (m_sampleState) + { + m_sampleState->Release(); + m_sampleState = nullptr; + } + + // Release the matrix constant buffer. + if (m_matrixBuffer) + { + m_matrixBuffer->Release(); + m_matrixBuffer = nullptr; + } + + // Release the layout. + if (m_layout) + { + m_layout->Release(); + m_layout = nullptr; + } + + // Release the pixel shader. + if (m_pixelShader) + { + m_pixelShader->Release(); + m_pixelShader = nullptr; + } + + // Release the vertex shader. + if (m_vertexShader) + { + m_vertexShader->Release(); + m_vertexShader = nullptr; + } +} + +void CelShadingShader::OutputShaderErrorMessage(ID3D10Blob* errorMessage, HWND hwnd, WCHAR* shaderFilename) +{ + char* compileErrors; + unsigned long bufferSize, i; + std::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 = nullptr; + + // 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); +} + + +bool CelShadingShader::SetShaderParameters(ID3D11DeviceContext* deviceContext, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix, + ID3D11ShaderResourceView* texture, XMFLOAT3 lightDirection, XMFLOAT4 diffuseColor[]) +{ + HRESULT result; + D3D11_MAPPED_SUBRESOURCE mappedResource; + MatrixBufferType* dataPtr; + LightBufferType* dataPtr2; + unsigned int bufferNumber; + + // 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)) + { + 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; + + // Finally set the constant buffer in the vertex shader with the updated values. + deviceContext->VSSetConstantBuffers(bufferNumber, 1, &m_matrixBuffer); + + // Set shader texture resource in the pixel shader. + deviceContext->PSSetShaderResources(0, 1, &texture); + + // Lock the light constant buffer so it can be written to. + result = deviceContext->Map(m_lightBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + return false; + } + + // Get a pointer to the data in the constant buffer. + dataPtr2 = (LightBufferType*)mappedResource.pData; + + // Copy the lighting variables into the constant buffer. + dataPtr2->diffuseColor = diffuseColor[0]; + dataPtr2->lightDirection = lightDirection; + dataPtr2->padding = 0.0f; + + // Unlock the constant buffer. + deviceContext->Unmap(m_lightBuffer, 0); + + // Set the position of the light constant buffer in the pixel shader. + bufferNumber = 0; + + // Finally set the light constant buffer in the pixel shader with the updated values. + deviceContext->PSSetConstantBuffers(bufferNumber, 1, &m_lightBuffer); + + return true; +} + + +void CelShadingShader::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, nullptr, 0); + deviceContext->PSSetShader(m_pixelShader, nullptr, 0); + + // Set the sampler state in the pixel shader. + deviceContext->PSSetSamplers(0, 1, &m_sampleState); + + // Render the triangle. + deviceContext->DrawIndexed(indexCount, 0, 0); +} diff --git a/enginecustom/CelShadingShader.h b/enginecustom/CelShadingShader.h new file mode 100644 index 0000000..a675f34 --- /dev/null +++ b/enginecustom/CelShadingShader.h @@ -0,0 +1,61 @@ +#ifndef _CELSHADINGSHADER_H_ +#define _CELSHADINGSHADER_H_ + +////////////// +// INCLUDES // +////////////// +#include "Logger.h" +#include +#include +#include +#include +using namespace DirectX; +using namespace std; + +//////////////////////////////////////////////////////////////////////////////// +// Class name: CelShadingShader +//////////////////////////////////////////////////////////////////////////////// +class CelShadingShader +{ +private: + struct MatrixBufferType + { + XMMATRIX world; + XMMATRIX view; + XMMATRIX projection; + }; + + struct LightBufferType + { + XMFLOAT4 diffuseColor; + XMFLOAT3 lightDirection; + float padding; + }; + +public: + CelShadingShader(); + CelShadingShader(const CelShadingShader&); + ~CelShadingShader(); + + bool Initialize(ID3D11Device*, HWND); + void Shutdown(); + bool Render(ID3D11DeviceContext*, int, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, XMFLOAT3, XMFLOAT4[]); + +private: + bool InitializeShader(ID3D11Device*, HWND, WCHAR*, WCHAR*); + void ShutdownShader(); + void OutputShaderErrorMessage(ID3D10Blob*, HWND, WCHAR*); + + bool SetShaderParameters(ID3D11DeviceContext*, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, XMFLOAT3, XMFLOAT4[]); + void RenderShader(ID3D11DeviceContext*, int); + +private: + ID3D11VertexShader* m_vertexShader; + ID3D11PixelShader* m_pixelShader; + ID3D11InputLayout* m_layout; + ID3D11Buffer* m_matrixBuffer; + ID3D11SamplerState* m_sampleState; + ID3D11Buffer* m_lightBuffer; +}; + +#endif diff --git a/enginecustom/applicationclass.cpp b/enginecustom/applicationclass.cpp index 3e6553b..b32234f 100644 --- a/enginecustom/applicationclass.cpp +++ b/enginecustom/applicationclass.cpp @@ -1021,6 +1021,17 @@ bool ApplicationClass::Render(float rotation, float x, float y, float z, float t result = m_ShaderManager->RenderlightShader(m_Direct3D->GetDeviceContext(), m_Model->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, m_Model->GetTexture(0), diffuseColor, lightPosition, ambientColor); + // Render cel shading globally to the scene using the cel shader if the checkbox is checked. + if (m_enableCelShading) { + result = m_ShaderManager->RenderCelShadingShader(m_Direct3D->GetDeviceContext(), m_Model->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, m_Model->GetTexture(0), + m_Lights[0]->GetDirection(), ambientColor); + if (!result) + { + Logger::Get().Log("Could not render the model using the cel shader", __FILE__, __LINE__, Logger::LogLevel::Error); + return false; + } + } + for (auto cube : m_cubes) { @@ -1055,6 +1066,7 @@ bool ApplicationClass::Render(float rotation, float x, float y, float z, float t Logger::Get().Log("Could not render the cube model using the light shader", __FILE__, __LINE__, Logger::LogLevel::Error); return false; } + } for (auto& object : m_object) diff --git a/enginecustom/applicationclass.h b/enginecustom/applicationclass.h index 377e8a5..c4357e9 100644 --- a/enginecustom/applicationclass.h +++ b/enginecustom/applicationclass.h @@ -83,6 +83,8 @@ public: bool GetShouldQuit() const { return m_ShouldQuit; }; void SetShouldQuit(bool shouldQuit) { m_ShouldQuit = shouldQuit; }; + void SetCelShading(bool enable) { m_enableCelShading = enable; }; + private: bool Render(float, float, float, float, float); bool UpdateMouseStrings(int, int, bool); @@ -142,6 +144,8 @@ private : FontShaderClass* m_FontShader; BitmapClass* m_Bitmap; SpriteClass* m_Sprite; + + bool m_enableCelShading; // ----------------------------------- // // ------------ VARIABLES ------------ // diff --git a/enginecustom/celshading.ps b/enginecustom/celshading.ps new file mode 100644 index 0000000..08b0a87 --- /dev/null +++ b/enginecustom/celshading.ps @@ -0,0 +1,44 @@ +// celshading.ps +cbuffer LightBuffer +{ + float4 diffuseColor; + float3 lightDirection; + float padding; // Padding to ensure the structure is a multiple of 16 bytes. +}; + +Texture2D shaderTexture; +SamplerState SampleType; + +struct PixelInputType +{ + float4 position : SV_POSITION; + float2 tex : TEXCOORD0; +}; + +float4 CelShadingPixelShader(PixelInputType input) : SV_TARGET +{ + float4 textureColor; + float lightIntensity; + float4 finalColor; + + // Sample the pixel color from the texture. + textureColor = shaderTexture.Sample(SampleType, input.tex); + + // Calculate the light intensity based on the light direction. + lightIntensity = saturate(dot(normalize(lightDirection), float3(0.0f, 0.0f, -1.0f))); + + // Apply a step function to create the cel shading effect. + if (lightIntensity > 0.5f) + { + lightIntensity = 1.0f; + } + else + { + lightIntensity = 0.3f; + } + + // Calculate the final color by combining the texture color with the light intensity and diffuse color. + finalColor = textureColor * diffuseColor * lightIntensity; + + return finalColor; +} diff --git a/enginecustom/celshading.vs b/enginecustom/celshading.vs new file mode 100644 index 0000000..4b4e8b8 --- /dev/null +++ b/enginecustom/celshading.vs @@ -0,0 +1,37 @@ +// celshading.vs +cbuffer MatrixBuffer +{ + matrix worldMatrix; + matrix viewMatrix; + matrix projectionMatrix; +}; + +struct VertexInputType +{ + float4 position : POSITION; + float2 tex : TEXCOORD0; +}; + +struct PixelInputType +{ + float4 position : SV_POSITION; + float2 tex : TEXCOORD0; +}; + +PixelInputType CelShadingVertexShader(VertexInputType input) +{ + PixelInputType output; + + // 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; + + return output; +} diff --git a/enginecustom/enginecustom.vcxproj b/enginecustom/enginecustom.vcxproj index 8e7cd31..95b3754 100644 --- a/enginecustom/enginecustom.vcxproj +++ b/enginecustom/enginecustom.vcxproj @@ -23,6 +23,7 @@ + @@ -70,6 +71,7 @@ + @@ -154,6 +156,12 @@ Document + + Document + + + Document + Document diff --git a/enginecustom/enginecustom.vcxproj.filters b/enginecustom/enginecustom.vcxproj.filters index c4b2c4c..b273a41 100644 --- a/enginecustom/enginecustom.vcxproj.filters +++ b/enginecustom/enginecustom.vcxproj.filters @@ -171,6 +171,9 @@ Fichiers sources + + Fichiers sources + @@ -317,6 +320,9 @@ Fichiers d%27en-tête + + Fichiers d%27en-tête + @@ -508,5 +514,11 @@ Assets + + shader + + + shader + \ No newline at end of file diff --git a/enginecustom/imgui.ini b/enginecustom/imgui.ini index fc8a95f..d7b8118 100644 --- a/enginecustom/imgui.ini +++ b/enginecustom/imgui.ini @@ -18,3 +18,7 @@ Size=342,82 Pos=95,296 Size=345,230 +[Window][Shader Manager] +Pos=60,60 +Size=172,284 + diff --git a/enginecustom/imguiManager.cpp b/enginecustom/imguiManager.cpp index 5cc5ea0..e781373 100644 --- a/enginecustom/imguiManager.cpp +++ b/enginecustom/imguiManager.cpp @@ -111,6 +111,17 @@ void imguiManager::WidgetAddObject(ApplicationClass* app) } } +void imguiManager::WidgetShaderWindow(ApplicationClass* app) +{ + ImGui::Begin("Shader Manager"); + + // Checkbox for toggling cel shading globally in the application class by calling the SetCelShading function in the application class when the checkbox state changes + ImGui::Checkbox("Enable Cel Shading", &m_EnableCelShading); + app->SetCelShading(m_EnableCelShading); + + ImGui::End(); +} + void imguiManager::WidgetObjectWindow(ApplicationClass* app) { ImGui::Begin("Objects", &showObjectWindow); @@ -300,6 +311,11 @@ bool imguiManager::ImGuiWidgetRenderer(ApplicationClass* app) showLightWindow = true; } + if (ImGui::Button("Open Shader Window")) + { + showShaderWindow = true; + } + ImGui::End(); // Show windows if their corresponding variables are true @@ -318,6 +334,11 @@ bool imguiManager::ImGuiWidgetRenderer(ApplicationClass* app) WidgetLightWindow(app); } + if (showShaderWindow) + { + WidgetShaderWindow(app); + } + //render imgui Render(); diff --git a/enginecustom/imguiManager.h b/enginecustom/imguiManager.h index c814210..a6977cb 100644 --- a/enginecustom/imguiManager.h +++ b/enginecustom/imguiManager.h @@ -31,13 +31,19 @@ public: void WidgetObjectWindow(ApplicationClass* app); void WidgetTerrainWindow(ApplicationClass* app); void WidgetLightWindow(ApplicationClass* app); + void WidgetShaderWindow(ApplicationClass* app); bool ImGuiWidgetRenderer(ApplicationClass* app); + // Shader toggles + + bool m_EnableCelShading; + private : bool showObjectWindow = false; bool showTerrainWindow = false; bool showLightWindow = false; + bool showShaderWindow = false; private: ImGuiIO* io; diff --git a/enginecustom/shadermanagerclass.cpp b/enginecustom/shadermanagerclass.cpp index a6d5be3..a66e8b1 100644 --- a/enginecustom/shadermanagerclass.cpp +++ b/enginecustom/shadermanagerclass.cpp @@ -13,6 +13,7 @@ ShaderManagerClass::ShaderManagerClass() m_LightMapShader = 0; m_RefractionShader = 0; m_WaterShader = 0; + m_CelShadingShader = 0; } @@ -140,6 +141,14 @@ bool ShaderManagerClass::Initialize(ID3D11Device* device, HWND hwnd) return false; } + m_CelShadingShader = new CelShadingShader; + + result = m_CelShadingShader->Initialize(device, hwnd); + if (!result) + { + return false; + } + Logger::Get().Log("ShaderManagerClass initialized", __FILE__, __LINE__, Logger::LogLevel::Initialize); return true; @@ -417,4 +426,18 @@ bool ShaderManagerClass::RenderWaterShader(ID3D11DeviceContext* deviceContext, i } return true; +} + +bool ShaderManagerClass::RenderCelShadingShader(ID3D11DeviceContext* deviceContext, int indexCount, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix, + ID3D11ShaderResourceView* texture, XMFLOAT3 lightDirection, XMFLOAT4 diffuseColor[]) +{ + bool result; + + result = m_CelShadingShader->Render(deviceContext, indexCount, worldMatrix, viewMatrix, projectionMatrix, texture, lightDirection, diffuseColor); + if (!result) + { + return false; + } + + return true; } \ No newline at end of file diff --git a/enginecustom/shadermanagerclass.h b/enginecustom/shadermanagerclass.h index 20de267..e2362e2 100644 --- a/enginecustom/shadermanagerclass.h +++ b/enginecustom/shadermanagerclass.h @@ -15,6 +15,7 @@ #include "lightmapshaderclass.h" #include "refractionshaderclass.h" #include "watershaderclass.h" +#include "CelShadingShader.h" //////////////////////////////////////////////////////////////////////////////// @@ -43,6 +44,7 @@ public: 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[]); private: TextureShaderClass* m_TextureShader; NormalMapShaderClass* m_NormalMapShader; @@ -56,6 +58,7 @@ private: LightMapShaderClass* m_LightMapShader; RefractionShaderClass* m_RefractionShader; WaterShaderClass* m_WaterShader; + CelShadingShader* m_CelShadingShader; }; #endif \ No newline at end of file From 1b8b25ce2ac3297c46b7c1690fecc7c3a1c175df Mon Sep 17 00:00:00 2001 From: CatChow0 <115560405+CatChow0@users.noreply.github.com> Date: Tue, 24 Sep 2024 12:24:57 +0200 Subject: [PATCH 2/6] Update README.md --- README.md | 76 ++++++++----------------------------------------------- 1 file changed, 11 insertions(+), 65 deletions(-) diff --git a/README.md b/README.md index 06c6517..f38ba45 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ -# Khaotic Engine - C++ Custom Engine +# Khaotic Engine Reborn - C++ Custom Engine -Khaotic Engine est un moteur de rendu fait en **C++** réalisé par une petite équipe dans le but d'apprendre à utiliser les API de rendu (OpenGL,DirectX 11/12 et Vulkan). +Khaotic Engine Reborn reprend comme base le moteur Khaotic Engine pour lui ajouter plus de fonctionalité. -Ce moteur est basé sur **DirectX11** utilise **ImGui** et **Boost** avec une couche d'abstraction pour permetre son usage avec d'autres API. +Ce moteur est basé sur **DirectX11** utilise **ImGui** avec une couche d'abstraction pour permetre son usage avec d'autres API. --- @@ -31,77 +31,23 @@ This **DirectX11** based engine uses **ImGui** with an abstraction layer to enab -## Shaders list: +## Nouvauté Aporté par Khaotic Engine Reborn +**SHADER** : - - **Diffuse Lighting** - - **Ambiant Lighting** - - **Specular Lighting** - - **Light Shader** - - **Light Map Shader** - - **Alpha Mapping** - - **Normal Mapping** - - **Specular Mapping** - - **Clipping Planes** - - **Texture Translation** - - **Transparency** - - **Water** - - **Refraction** - - *Reflection (cassé / broken)* - - -*Plus de shaders seront disponibles dans le futur* - ---- - -*More shaders will be added in the future* - - - -## ImGui: - -*Cette partie du moteur est encore en développement, d'autres fonctionnalitées seront ajoutées dans le futur* - -La librairie ImGui est utilisée afin d'intéragir avec les éléments du moteur comme les objets. - -### Fonctionnalitées: -- Importer des objets 3D sous format **.obj** -- Ajout d'un cube à la scène -- Modifier les propriétées d'un objet (Position, Rotation, Taille) -- Modifier les objets présents dans la scène -- Création d'un terrain -- Modifier les propriétées des lumières (Position, Couleur RVB) - ----- -*This part of the engine is still in development, other features will be added in the future* - -ImGui is used to allow interaction between the user and the objects in the scene. - -### Features: -- Import 3D objects with the **.obj** format -- Can add a cube to the scene -- Edit an object properties (Position, Rotation, Scale) -- Edit objects in the current scene -- Terrain generation -- Edit lights properties (Position, RGB Color) +- Cel Shading +**Interface Graphique** : +- Shader Manager ## Demo : [![Demo Video](https://img.youtube.com/vi/qCOCTyB_97c/0.jpg)](https://www.youtube.com/watch?v=qCOCTyB_97c) - -## Bug Report : - -Vous pouvez signalez les problèmes en ouvrant un ticket dans [Issues](https://github.com/GamingCampus-AdrienBourgois/khaotic-engine/issues) - ----- -You can report bugs with the program by creating a ticket in [Issues](https://github.com/GamingCampus-AdrienBourgois/khaotic-engine/issues) - ## Engine Build by : -[](https://github.com/GamingCampus-AdrienBourgois/khaotic-engine?tab=readme-ov-file#engine-build-by-) +**Moteur D'origine** : - [@CatChow0](https://github.com/CatChow0) - [@miragefr0st](https://github.com/miragefr0st) @@ -113,6 +59,6 @@ You can report bugs with the program by creating a ticket in [Issues](https://gi - [@sutabasuto](https://github.com/sutabasuto) +**Moteur Reborn** : - - +- [@CatChow0](https://github.com/CatChow0) From 71403c614dc62ef8cada91dd42e954add49c237a Mon Sep 17 00:00:00 2001 From: CatChow0 Date: Wed, 25 Sep 2024 12:40:02 +0200 Subject: [PATCH 3/6] Cel shading Update --- enginecustom/CelShadingShader.cpp | 35 +++++++--- enginecustom/CelShadingShader.h | 8 ++- enginecustom/applicationclass.cpp | 104 ++++++++++++++++------------ enginecustom/applicationclass.h | 2 + enginecustom/celshading.ps | 17 ++++- enginecustom/celshading.vs | 12 +++- enginecustom/imgui.ini | 12 ++-- enginecustom/imguiManager.cpp | 3 +- enginecustom/shadermanagerclass.cpp | 4 +- enginecustom/shadermanagerclass.h | 2 +- 10 files changed, 128 insertions(+), 71 deletions(-) diff --git a/enginecustom/CelShadingShader.cpp b/enginecustom/CelShadingShader.cpp index 3745b30..29bbc17 100644 --- a/enginecustom/CelShadingShader.cpp +++ b/enginecustom/CelShadingShader.cpp @@ -1,4 +1,5 @@ #include "CelShadingShader.h" +#include CelShadingShader::CelShadingShader() { @@ -63,14 +64,14 @@ void CelShadingShader::Shutdown() } bool CelShadingShader::Render(ID3D11DeviceContext* deviceContext, int indexCount, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix, - ID3D11ShaderResourceView* texture, XMFLOAT3 lightDirection, XMFLOAT4 diffuseColor[]) + ID3D11ShaderResourceView* texture, XMFLOAT3 lightDirection, XMFLOAT4 diffuseColor, XMFLOAT3 lightPosition) { bool result; - // Set the shader parameters that it will use for rendering. - result = SetShaderParameters(deviceContext, worldMatrix, viewMatrix, projectionMatrix, texture, lightDirection, diffuseColor); + result = SetShaderParameters(deviceContext, worldMatrix, viewMatrix, projectionMatrix, texture, lightDirection, diffuseColor, lightPosition); if (!result) { + Logger::Get().Log("CelShading Error", __FILE__, __LINE__, Logger::LogLevel::Error); return false; } @@ -86,7 +87,7 @@ bool CelShadingShader::InitializeShader(ID3D11Device* device, HWND hwnd, WCHAR* ID3D10Blob* errorMessage = nullptr; ID3D10Blob* vertexShaderBuffer = nullptr; ID3D10Blob* pixelShaderBuffer = nullptr; - D3D11_INPUT_ELEMENT_DESC polygonLayout[2]; + D3D11_INPUT_ELEMENT_DESC polygonLayout[3]; unsigned int numElements; D3D11_BUFFER_DESC matrixBufferDesc; D3D11_SAMPLER_DESC samplerDesc; @@ -146,20 +147,28 @@ bool CelShadingShader::InitializeShader(ID3D11Device* device, HWND hwnd, WCHAR* // This setup needs to match the VertexType structure in the ModelClass and in the shader. polygonLayout[0].SemanticName = "POSITION"; polygonLayout[0].SemanticIndex = 0; - polygonLayout[0].Format = DXGI_FORMAT_R32G32B32_FLOAT; + polygonLayout[0].Format = DXGI_FORMAT_R32G32B32A32_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].SemanticName = "NORMAL"; polygonLayout[1].SemanticIndex = 0; - polygonLayout[1].Format = DXGI_FORMAT_R32G32_FLOAT; + polygonLayout[1].Format = DXGI_FORMAT_R32G32B32_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 = "TEXCOORD"; + polygonLayout[2].SemanticIndex = 0; + polygonLayout[2].Format = DXGI_FORMAT_R32G32_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]); @@ -312,7 +321,7 @@ void CelShadingShader::OutputShaderErrorMessage(ID3D10Blob* errorMessage, HWND h bool CelShadingShader::SetShaderParameters(ID3D11DeviceContext* deviceContext, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix, - ID3D11ShaderResourceView* texture, XMFLOAT3 lightDirection, XMFLOAT4 diffuseColor[]) + ID3D11ShaderResourceView* texture, XMFLOAT3 lightDirection, XMFLOAT4 diffuseColor, XMFLOAT3 lightPosition) { HRESULT result; D3D11_MAPPED_SUBRESOURCE mappedResource; @@ -320,6 +329,7 @@ bool CelShadingShader::SetShaderParameters(ID3D11DeviceContext* deviceContext, X LightBufferType* dataPtr2; unsigned int bufferNumber; + // Transpose the matrices to prepare them for the shader. worldMatrix = XMMatrixTranspose(worldMatrix); viewMatrix = XMMatrixTranspose(viewMatrix); @@ -363,9 +373,16 @@ bool CelShadingShader::SetShaderParameters(ID3D11DeviceContext* deviceContext, X dataPtr2 = (LightBufferType*)mappedResource.pData; // Copy the lighting variables into the constant buffer. - dataPtr2->diffuseColor = diffuseColor[0]; + dataPtr2->diffuseColor = diffuseColor; dataPtr2->lightDirection = lightDirection; + dataPtr2->lightPosition = lightPosition; dataPtr2->padding = 0.0f; + dataPtr2->padding2 = 0.0f; + + // store the light direction in a string + std::string lightDirectionString = std::to_string(lightDirection.x) + ", " + std::to_string(lightDirection.y) + ", " + std::to_string(lightDirection.z); + Logger::Get().Log(lightDirectionString, __FILE__, __LINE__, Logger::LogLevel::Debug); + // Unlock the constant buffer. deviceContext->Unmap(m_lightBuffer, 0); diff --git a/enginecustom/CelShadingShader.h b/enginecustom/CelShadingShader.h index a675f34..6e0c4f3 100644 --- a/enginecustom/CelShadingShader.h +++ b/enginecustom/CelShadingShader.h @@ -29,7 +29,9 @@ private: { XMFLOAT4 diffuseColor; XMFLOAT3 lightDirection; - float padding; + float padding; // Padding to ensure the structure is a multiple of 16 bytes. + XMFLOAT3 lightPosition; // Add light position + float padding2; // Padding to ensure the structure is a multiple of 16 bytes. }; public: @@ -39,14 +41,14 @@ public: bool Initialize(ID3D11Device*, HWND); void Shutdown(); - bool Render(ID3D11DeviceContext*, int, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, XMFLOAT3, XMFLOAT4[]); + bool Render(ID3D11DeviceContext*, int, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, XMFLOAT3, XMFLOAT4, XMFLOAT3); private: bool InitializeShader(ID3D11Device*, HWND, WCHAR*, WCHAR*); void ShutdownShader(); void OutputShaderErrorMessage(ID3D10Blob*, HWND, WCHAR*); - bool SetShaderParameters(ID3D11DeviceContext*, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, XMFLOAT3, XMFLOAT4[]); + bool SetShaderParameters(ID3D11DeviceContext*, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, XMFLOAT3, XMFLOAT4, XMFLOAT3); void RenderShader(ID3D11DeviceContext*, int); private: diff --git a/enginecustom/applicationclass.cpp b/enginecustom/applicationclass.cpp index b32234f..9b45de2 100644 --- a/enginecustom/applicationclass.cpp +++ b/enginecustom/applicationclass.cpp @@ -1006,6 +1006,11 @@ bool ApplicationClass::Render(float rotation, float x, float y, float z, float t ambientColor[i] = m_Lights[i]->GetPosition(); } + //Add the 3 first value of the light position to the TrueLightPosition XMFLOAT3 + TrueLightPosition.x = lightPosition[0].x; + TrueLightPosition.y = lightPosition[0].y; + TrueLightPosition.z = lightPosition[0].z; + scaleMatrix = XMMatrixScaling(0.5f, 0.5f, 0.5f); // Build the scaling matrix. rotateMatrix = XMMatrixRotationY(rotation); // Build the rotation matrix. translateMatrix = XMMatrixTranslation(x, y, z); // Build the translation matrix. @@ -1021,17 +1026,6 @@ bool ApplicationClass::Render(float rotation, float x, float y, float z, float t result = m_ShaderManager->RenderlightShader(m_Direct3D->GetDeviceContext(), m_Model->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, m_Model->GetTexture(0), diffuseColor, lightPosition, ambientColor); - // Render cel shading globally to the scene using the cel shader if the checkbox is checked. - if (m_enableCelShading) { - result = m_ShaderManager->RenderCelShadingShader(m_Direct3D->GetDeviceContext(), m_Model->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, m_Model->GetTexture(0), - m_Lights[0]->GetDirection(), ambientColor); - if (!result) - { - Logger::Get().Log("Could not render the model using the cel shader", __FILE__, __LINE__, Logger::LogLevel::Error); - return false; - } - } - for (auto cube : m_cubes) { @@ -1051,20 +1045,26 @@ bool ApplicationClass::Render(float rotation, float x, float y, float z, float t cube->Render(m_Direct3D->GetDeviceContext()); - // render the texture using the texture shader. - result = m_ShaderManager->RenderTextureShader(m_Direct3D->GetDeviceContext(), cube->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, cube->GetTexture(0)); - if (!result) - { - Logger::Get().Log("Could not render the cube model using the texture shader", __FILE__, __LINE__, Logger::LogLevel::Error); - return false; + + if (!m_enableCelShading) { + result = m_ShaderManager->RenderlightShader(m_Direct3D->GetDeviceContext(), cube->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, cube->GetTexture(0), + diffuseColor, lightPosition, ambientColor); + if (!result) + { + Logger::Get().Log("Could not render the cube model using the light shader", __FILE__, __LINE__, Logger::LogLevel::Error); + return false; + } } - result = m_ShaderManager->RenderlightShader(m_Direct3D->GetDeviceContext(), m_Model->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, cube->GetTexture(0), - diffuseColor, lightPosition,ambientColor); - if (!result) - { - Logger::Get().Log("Could not render the cube model using the light shader", __FILE__, __LINE__, Logger::LogLevel::Error); - return false; + // Render cel shading globally to the scene using the cel shader if the checkbox is checked. + if (m_enableCelShading) { + result = m_ShaderManager->RenderCelShadingShader(m_Direct3D->GetDeviceContext(), cube->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, cube->GetTexture(0), + m_Lights[0]->GetDirection(), m_Lights[0]->GetDiffuseColor(), TrueLightPosition); + if (!result) + { + Logger::Get().Log("Could not render the model using the cel shader", __FILE__, __LINE__, Logger::LogLevel::Error); + return false; + } } } @@ -1084,21 +1084,26 @@ bool ApplicationClass::Render(float rotation, float x, float y, float z, float t object->Render(m_Direct3D->GetDeviceContext()); - // render the texture using the texture shader. - result = m_ShaderManager->RenderTextureShader(m_Direct3D->GetDeviceContext(), object->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, object->GetTexture(0)); - if (!result) - { - Logger::Get().Log("Could not render the cube model using the texture shader", __FILE__, __LINE__, Logger::LogLevel::Error); - return false; + if (!m_enableCelShading) { + result = m_ShaderManager->RenderlightShader(m_Direct3D->GetDeviceContext(), m_Model->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, object->GetTexture(0), + diffuseColor, lightPosition, ambientColor); + + if (!result) + { + Logger::Get().Log("Could not render the object model using the light shader", __FILE__, __LINE__, Logger::LogLevel::Error); + return false; + } } - result = m_ShaderManager->RenderlightShader(m_Direct3D->GetDeviceContext(), m_Model->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, m_Model->GetTexture(0), - diffuseColor, lightPosition, ambientColor); - - if (!result) - { - Logger::Get().Log("Could not render the object model using the light shader", __FILE__, __LINE__, Logger::LogLevel::Error); - return false; + // Render cel shading globally to the scene using the cel shader if the checkbox is checked. + if (m_enableCelShading) { + result = m_ShaderManager->RenderCelShadingShader(m_Direct3D->GetDeviceContext(), m_Model->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, object->GetTexture(0), + m_Lights[0]->GetDirection(), m_Lights[0]->GetDiffuseColor(), TrueLightPosition); + if (!result) + { + Logger::Get().Log("Could not render the model using the cel shader", __FILE__, __LINE__, Logger::LogLevel::Error); + return false; + } } } @@ -1114,14 +1119,27 @@ bool ApplicationClass::Render(float rotation, float x, float y, float z, float t worldMatrix = XMMatrixMultiply(srMatrix, translateMatrix); chunk->Render(m_Direct3D->GetDeviceContext()); + if (!m_enableCelShading) { + result = m_ShaderManager->RenderlightShader(m_Direct3D->GetDeviceContext(), chunk->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, chunk->GetTexture(5), + diffuseColor, lightPosition, ambientColor); - result = m_ShaderManager->RenderlightShader(m_Direct3D->GetDeviceContext(), chunk->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, chunk->GetTexture(5), - diffuseColor, lightPosition, ambientColor); - - if (!result) - { - Logger::Get().Log("Could not render the terrain model using the light shader", __FILE__, __LINE__, Logger::LogLevel::Error); - return false; + if (!result) + { + Logger::Get().Log("Could not render the terrain model using the light shader", __FILE__, __LINE__, Logger::LogLevel::Error); + return false; + } + } + + + // Render cel shading globally to the scene using the cel shader if the checkbox is checked. + if (m_enableCelShading) { + result = m_ShaderManager->RenderCelShadingShader(m_Direct3D->GetDeviceContext(), chunk->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, chunk->GetTexture(5), + m_Lights[0]->GetDirection(), m_Lights[0]->GetDiffuseColor(), TrueLightPosition); + if (!result) + { + Logger::Get().Log("Could not render the model using the cel shader", __FILE__, __LINE__, Logger::LogLevel::Error); + return false; + } } } diff --git a/enginecustom/applicationclass.h b/enginecustom/applicationclass.h index c4357e9..ff9bcee 100644 --- a/enginecustom/applicationclass.h +++ b/enginecustom/applicationclass.h @@ -136,6 +136,8 @@ private : std::vector m_Lights; int m_numLights; + XMFLOAT3 TrueLightPosition; + // ----------------------------------- // // ------------- SHADERS ------------- // // ----------------------------------- // diff --git a/enginecustom/celshading.ps b/enginecustom/celshading.ps index 08b0a87..520ed49 100644 --- a/enginecustom/celshading.ps +++ b/enginecustom/celshading.ps @@ -1,9 +1,10 @@ -// celshading.ps cbuffer LightBuffer { float4 diffuseColor; float3 lightDirection; float padding; // Padding to ensure the structure is a multiple of 16 bytes. + float3 lightPosition; // Add light position + float padding2; // Padding to ensure the structure is a multiple of 16 bytes. }; Texture2D shaderTexture; @@ -12,7 +13,9 @@ SamplerState SampleType; struct PixelInputType { float4 position : SV_POSITION; + float3 normal : NORMAL; float2 tex : TEXCOORD0; + float3 worldPos : TEXCOORD1; // Add world position }; float4 CelShadingPixelShader(PixelInputType input) : SV_TARGET @@ -24,8 +27,16 @@ float4 CelShadingPixelShader(PixelInputType input) : SV_TARGET // Sample the pixel color from the texture. textureColor = shaderTexture.Sample(SampleType, input.tex); + // Normalize the normal + float3 normal = normalize(input.normal); + + // Calculate the vector from the pixel to the light source + float3 lightVector = lightPosition - input.worldPos; + float distance = length(lightVector); + lightVector = normalize(lightVector); + // Calculate the light intensity based on the light direction. - lightIntensity = saturate(dot(normalize(lightDirection), float3(0.0f, 0.0f, -1.0f))); + lightIntensity = saturate(dot(normal, lightVector)); // Apply a step function to create the cel shading effect. if (lightIntensity > 0.5f) @@ -41,4 +52,4 @@ float4 CelShadingPixelShader(PixelInputType input) : SV_TARGET finalColor = textureColor * diffuseColor * lightIntensity; return finalColor; -} +} \ No newline at end of file diff --git a/enginecustom/celshading.vs b/enginecustom/celshading.vs index 4b4e8b8..fe58dbc 100644 --- a/enginecustom/celshading.vs +++ b/enginecustom/celshading.vs @@ -1,4 +1,3 @@ -// celshading.vs cbuffer MatrixBuffer { matrix worldMatrix; @@ -9,13 +8,16 @@ cbuffer MatrixBuffer struct VertexInputType { float4 position : POSITION; + float3 normal : NORMAL; float2 tex : TEXCOORD0; }; struct PixelInputType { float4 position : SV_POSITION; + float3 normal : NORMAL; float2 tex : TEXCOORD0; + float3 worldPos : TEXCOORD1; // Add world position }; PixelInputType CelShadingVertexShader(VertexInputType input) @@ -30,8 +32,14 @@ PixelInputType CelShadingVertexShader(VertexInputType input) output.position = mul(output.position, viewMatrix); output.position = mul(output.position, projectionMatrix); + // Pass the normal to the pixel shader + output.normal = mul(input.normal, (float3x3)worldMatrix); + + // Pass the world position to the pixel shader + output.worldPos = mul(input.position, worldMatrix).xyz; + // Store the texture coordinates for the pixel shader. output.tex = input.tex; return output; -} +} \ No newline at end of file diff --git a/enginecustom/imgui.ini b/enginecustom/imgui.ini index d7b8118..3b43e0d 100644 --- a/enginecustom/imgui.ini +++ b/enginecustom/imgui.ini @@ -3,22 +3,22 @@ Pos=60,60 Size=400,400 [Window][Khaotic Engine] -Pos=429,57 +Pos=430,-13 Size=392,218 [Window][Objects] -Pos=39,222 -Size=589,294 +Pos=998,87 +Size=457,294 [Window][Terrain] Pos=60,60 Size=342,82 [Window][Light] -Pos=95,296 -Size=345,230 +Pos=1197,66 +Size=345,519 [Window][Shader Manager] -Pos=60,60 +Pos=33,253 Size=172,284 diff --git a/enginecustom/imguiManager.cpp b/enginecustom/imguiManager.cpp index e781373..002e579 100644 --- a/enginecustom/imguiManager.cpp +++ b/enginecustom/imguiManager.cpp @@ -118,7 +118,7 @@ void imguiManager::WidgetShaderWindow(ApplicationClass* app) // Checkbox for toggling cel shading globally in the application class by calling the SetCelShading function in the application class when the checkbox state changes ImGui::Checkbox("Enable Cel Shading", &m_EnableCelShading); app->SetCelShading(m_EnableCelShading); - + ImGui::End(); } @@ -373,7 +373,6 @@ void imguiManager::WidgetLightWindow(ApplicationClass* app) app->SetLightColor(index, XMVectorSet(col[0], col[1], col[2], 0.0f)); } - ImGui::Separator(); } index++; }; diff --git a/enginecustom/shadermanagerclass.cpp b/enginecustom/shadermanagerclass.cpp index a66e8b1..4ad7658 100644 --- a/enginecustom/shadermanagerclass.cpp +++ b/enginecustom/shadermanagerclass.cpp @@ -429,11 +429,11 @@ bool ShaderManagerClass::RenderWaterShader(ID3D11DeviceContext* deviceContext, i } bool ShaderManagerClass::RenderCelShadingShader(ID3D11DeviceContext* deviceContext, int indexCount, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix, - ID3D11ShaderResourceView* texture, XMFLOAT3 lightDirection, XMFLOAT4 diffuseColor[]) + ID3D11ShaderResourceView* texture, XMFLOAT3 lightDirection, XMFLOAT4 diffuseColor, XMFLOAT3 lightPosition) { bool result; - result = m_CelShadingShader->Render(deviceContext, indexCount, worldMatrix, viewMatrix, projectionMatrix, texture, lightDirection, diffuseColor); + result = m_CelShadingShader->Render(deviceContext, indexCount, worldMatrix, viewMatrix, projectionMatrix, texture, lightDirection, diffuseColor, lightPosition); if (!result) { return false; diff --git a/enginecustom/shadermanagerclass.h b/enginecustom/shadermanagerclass.h index e2362e2..c0aa0ba 100644 --- a/enginecustom/shadermanagerclass.h +++ b/enginecustom/shadermanagerclass.h @@ -44,7 +44,7 @@ public: 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[]); + bool RenderCelShadingShader(ID3D11DeviceContext*, int, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, XMFLOAT3, XMFLOAT4, XMFLOAT3); private: TextureShaderClass* m_TextureShader; NormalMapShaderClass* m_NormalMapShader; From 30b41922d928498fd7da1b1e15cf3a66198b5fd9 Mon Sep 17 00:00:00 2001 From: CatChow0 Date: Thu, 26 Sep 2024 11:30:26 +0200 Subject: [PATCH 4/6] Cel shade c'est mieux mais ALED --- enginecustom/CelShadingShader.cpp | 14 +++--------- enginecustom/CelShadingShader.h | 2 +- enginecustom/applicationclass.cpp | 16 ++++++++----- enginecustom/applicationclass.h | 1 + enginecustom/celshading.ps | 37 +++++++++++++++++++++++-------- enginecustom/celshading.vs | 8 +++---- enginecustom/imgui.ini | 8 +++---- 7 files changed, 51 insertions(+), 35 deletions(-) diff --git a/enginecustom/CelShadingShader.cpp b/enginecustom/CelShadingShader.cpp index 29bbc17..478551d 100644 --- a/enginecustom/CelShadingShader.cpp +++ b/enginecustom/CelShadingShader.cpp @@ -329,7 +329,6 @@ bool CelShadingShader::SetShaderParameters(ID3D11DeviceContext* deviceContext, X LightBufferType* dataPtr2; unsigned int bufferNumber; - // Transpose the matrices to prepare them for the shader. worldMatrix = XMMatrixTranspose(worldMatrix); viewMatrix = XMMatrixTranspose(viewMatrix); @@ -359,9 +358,6 @@ bool CelShadingShader::SetShaderParameters(ID3D11DeviceContext* deviceContext, X // Finally set the constant buffer in the vertex shader with the updated values. deviceContext->VSSetConstantBuffers(bufferNumber, 1, &m_matrixBuffer); - // Set shader texture resource in the pixel shader. - deviceContext->PSSetShaderResources(0, 1, &texture); - // Lock the light constant buffer so it can be written to. result = deviceContext->Map(m_lightBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); if (FAILED(result)) @@ -376,13 +372,6 @@ bool CelShadingShader::SetShaderParameters(ID3D11DeviceContext* deviceContext, X dataPtr2->diffuseColor = diffuseColor; dataPtr2->lightDirection = lightDirection; dataPtr2->lightPosition = lightPosition; - dataPtr2->padding = 0.0f; - dataPtr2->padding2 = 0.0f; - - // store the light direction in a string - std::string lightDirectionString = std::to_string(lightDirection.x) + ", " + std::to_string(lightDirection.y) + ", " + std::to_string(lightDirection.z); - Logger::Get().Log(lightDirectionString, __FILE__, __LINE__, Logger::LogLevel::Debug); - // Unlock the constant buffer. deviceContext->Unmap(m_lightBuffer, 0); @@ -393,6 +382,9 @@ bool CelShadingShader::SetShaderParameters(ID3D11DeviceContext* deviceContext, X // Finally set the light constant buffer in the pixel shader with the updated values. deviceContext->PSSetConstantBuffers(bufferNumber, 1, &m_lightBuffer); + // Set shader texture resource in the pixel shader. + deviceContext->PSSetShaderResources(0, 1, &texture); + return true; } diff --git a/enginecustom/CelShadingShader.h b/enginecustom/CelShadingShader.h index 6e0c4f3..d152943 100644 --- a/enginecustom/CelShadingShader.h +++ b/enginecustom/CelShadingShader.h @@ -60,4 +60,4 @@ private: ID3D11Buffer* m_lightBuffer; }; -#endif +#endif \ No newline at end of file diff --git a/enginecustom/applicationclass.cpp b/enginecustom/applicationclass.cpp index 9b45de2..9cbe31c 100644 --- a/enginecustom/applicationclass.cpp +++ b/enginecustom/applicationclass.cpp @@ -355,6 +355,7 @@ bool ApplicationClass::Initialize(int screenWidth, int screenHeight, HWND hwnd) Logger::Get().Log("Could not initialize the fps string", __FILE__, __LINE__, Logger::LogLevel::Error); return false; } + } catch (const std::exception& e) { @@ -1006,10 +1007,13 @@ bool ApplicationClass::Render(float rotation, float x, float y, float z, float t ambientColor[i] = m_Lights[i]->GetPosition(); } - //Add the 3 first value of the light position to the TrueLightPosition XMFLOAT3 - TrueLightPosition.x = lightPosition[0].x; - TrueLightPosition.y = lightPosition[0].y; - TrueLightPosition.z = lightPosition[0].z; + //Add the 3 first value of the first light position to the TrueLightPosition XMFLOAT3 + positionX = lightPosition[0].x; + positionY = lightPosition[0].y; + positionZ = lightPosition[0].z; + XMFLOAT3 TrueLightPosition = XMFLOAT3(positionX, positionY, positionZ); + + Logger::Get().Log("PositionX: " + std::to_string(positionX) + ", PositionY: " + std::to_string(positionY) + ", PositionZ: " + std::to_string(positionZ), __FILE__, __LINE__, Logger::LogLevel::Debug); scaleMatrix = XMMatrixScaling(0.5f, 0.5f, 0.5f); // Build the scaling matrix. rotateMatrix = XMMatrixRotationY(rotation); // Build the rotation matrix. @@ -1085,7 +1089,7 @@ bool ApplicationClass::Render(float rotation, float x, float y, float z, float t object->Render(m_Direct3D->GetDeviceContext()); if (!m_enableCelShading) { - result = m_ShaderManager->RenderlightShader(m_Direct3D->GetDeviceContext(), m_Model->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, object->GetTexture(0), + result = m_ShaderManager->RenderlightShader(m_Direct3D->GetDeviceContext(), object->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, object->GetTexture(0), diffuseColor, lightPosition, ambientColor); if (!result) @@ -1097,7 +1101,7 @@ bool ApplicationClass::Render(float rotation, float x, float y, float z, float t // Render cel shading globally to the scene using the cel shader if the checkbox is checked. if (m_enableCelShading) { - result = m_ShaderManager->RenderCelShadingShader(m_Direct3D->GetDeviceContext(), m_Model->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, object->GetTexture(0), + result = m_ShaderManager->RenderCelShadingShader(m_Direct3D->GetDeviceContext(), object->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, object->GetTexture(0), m_Lights[0]->GetDirection(), m_Lights[0]->GetDiffuseColor(), TrueLightPosition); if (!result) { diff --git a/enginecustom/applicationclass.h b/enginecustom/applicationclass.h index ff9bcee..fccdea5 100644 --- a/enginecustom/applicationclass.h +++ b/enginecustom/applicationclass.h @@ -137,6 +137,7 @@ private : int m_numLights; XMFLOAT3 TrueLightPosition; + ModelClass* m_LightModel; // ----------------------------------- // // ------------- SHADERS ------------- // diff --git a/enginecustom/celshading.ps b/enginecustom/celshading.ps index 520ed49..c613dcf 100644 --- a/enginecustom/celshading.ps +++ b/enginecustom/celshading.ps @@ -27,25 +27,44 @@ float4 CelShadingPixelShader(PixelInputType input) : SV_TARGET // Sample the pixel color from the texture. textureColor = shaderTexture.Sample(SampleType, input.tex); - // Normalize the normal float3 normal = normalize(input.normal); - // Calculate the vector from the pixel to the light source - float3 lightVector = lightPosition - input.worldPos; - float distance = length(lightVector); - lightVector = normalize(lightVector); + // Calculate the light vector from the light position to the world position + float3 lightVector = normalize(lightPosition - input.worldPos); // Calculate the light intensity based on the light direction. - lightIntensity = saturate(dot(normal, lightVector)); + float directionalLightIntensity = saturate(dot(normal, normalize(lightDirection))); + + // Calculate the light intensity based on the light position. + float positionalLightIntensity = saturate(dot(normal, lightVector)); + + // Combine the directional and positional light intensities. + lightIntensity = max(directionalLightIntensity, positionalLightIntensity); // Apply a step function to create the cel shading effect. - if (lightIntensity > 0.5f) + if (lightIntensity > 0.75f) { - lightIntensity = 1.0f; + lightIntensity = 1.0f; // Brightest level + } + else if (lightIntensity > 0.5f) + { + lightIntensity = 0.7f; // Mid-bright level + } + else if (lightIntensity > 0.25f) + { + lightIntensity = 0.4f; // Mid-dark level } else { - lightIntensity = 0.3f; + lightIntensity = 0.1f; // Darkest level + } + + // Simple shadow calculation: if the fragment is behind the light source, it is in shadow. + float3 toLight = normalize(lightPosition - input.worldPos); + float shadow = saturate(dot(normal, toLight)); + if (shadow < 0.1f) + { + lightIntensity *= 0.5f; // Darken the fragment if it is in shadow } // Calculate the final color by combining the texture color with the light intensity and diffuse color. diff --git a/enginecustom/celshading.vs b/enginecustom/celshading.vs index fe58dbc..842d724 100644 --- a/enginecustom/celshading.vs +++ b/enginecustom/celshading.vs @@ -28,15 +28,15 @@ PixelInputType CelShadingVertexShader(VertexInputType input) 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); + float4 worldPosition = mul(input.position, worldMatrix); + output.position = mul(worldPosition, viewMatrix); output.position = mul(output.position, projectionMatrix); // Pass the normal to the pixel shader - output.normal = mul(input.normal, (float3x3)worldMatrix); + output.normal = mul((float3x3)worldMatrix, input.normal); // Pass the world position to the pixel shader - output.worldPos = mul(input.position, worldMatrix).xyz; + output.worldPos = worldPosition.xyz; // Store the texture coordinates for the pixel shader. output.tex = input.tex; diff --git a/enginecustom/imgui.ini b/enginecustom/imgui.ini index 3b43e0d..6bf74f5 100644 --- a/enginecustom/imgui.ini +++ b/enginecustom/imgui.ini @@ -3,11 +3,11 @@ Pos=60,60 Size=400,400 [Window][Khaotic Engine] -Pos=430,-13 -Size=392,218 +Pos=510,25 +Size=392,273 [Window][Objects] -Pos=998,87 +Pos=934,36 Size=457,294 [Window][Terrain] @@ -15,7 +15,7 @@ Pos=60,60 Size=342,82 [Window][Light] -Pos=1197,66 +Pos=1223,64 Size=345,519 [Window][Shader Manager] From 002edb6651439168a176ae74f5fb5a42090e2cde Mon Sep 17 00:00:00 2001 From: CatChow0 Date: Thu, 26 Sep 2024 20:51:39 +0200 Subject: [PATCH 5/6] FIX DEBUG VS --- enginecustom/Spriteclass.cpp | 2 +- enginecustom/imgui.ini | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/enginecustom/Spriteclass.cpp b/enginecustom/Spriteclass.cpp index dcb7c42..40aa1e6 100644 --- a/enginecustom/Spriteclass.cpp +++ b/enginecustom/Spriteclass.cpp @@ -329,7 +329,7 @@ void SpriteClass::RenderBuffers(ID3D11DeviceContext* deviceContext) bool SpriteClass::LoadTextures(ID3D11Device* device, ID3D11DeviceContext* deviceContext, char* filename) { - std::string textureFilename; + std::string textureFilename(256, '0'); std::ifstream fin; int i, j; char input; diff --git a/enginecustom/imgui.ini b/enginecustom/imgui.ini index 6bf74f5..7130f2b 100644 --- a/enginecustom/imgui.ini +++ b/enginecustom/imgui.ini @@ -3,7 +3,7 @@ Pos=60,60 Size=400,400 [Window][Khaotic Engine] -Pos=510,25 +Pos=509,25 Size=392,273 [Window][Objects] From 1e6ea97fd067921db935f7381dbd1375cb859909 Mon Sep 17 00:00:00 2001 From: CatChow0 Date: Thu, 26 Sep 2024 21:55:33 +0200 Subject: [PATCH 6/6] MONKEYYYY --- enginecustom/CelShadingShader.cpp | 4 ++++ enginecustom/CelShadingShader.h | 5 +++++ enginecustom/celshading.ps | 15 ++++++++++++++- enginecustom/imgui.ini | 4 ++-- 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/enginecustom/CelShadingShader.cpp b/enginecustom/CelShadingShader.cpp index 478551d..ddc15e0 100644 --- a/enginecustom/CelShadingShader.cpp +++ b/enginecustom/CelShadingShader.cpp @@ -372,6 +372,9 @@ bool CelShadingShader::SetShaderParameters(ID3D11DeviceContext* deviceContext, X dataPtr2->diffuseColor = diffuseColor; dataPtr2->lightDirection = lightDirection; dataPtr2->lightPosition = lightPosition; + dataPtr2->constantAttenuation = 0.5f; // Set your attenuation values here + dataPtr2->linearAttenuation = 0.1f; + dataPtr2->quadraticAttenuation = 0.01f; // Unlock the constant buffer. deviceContext->Unmap(m_lightBuffer, 0); @@ -389,6 +392,7 @@ bool CelShadingShader::SetShaderParameters(ID3D11DeviceContext* deviceContext, X } + void CelShadingShader::RenderShader(ID3D11DeviceContext* deviceContext, int indexCount) { // Set the vertex input layout. diff --git a/enginecustom/CelShadingShader.h b/enginecustom/CelShadingShader.h index d152943..141c6a3 100644 --- a/enginecustom/CelShadingShader.h +++ b/enginecustom/CelShadingShader.h @@ -32,8 +32,13 @@ private: float padding; // Padding to ensure the structure is a multiple of 16 bytes. XMFLOAT3 lightPosition; // Add light position float padding2; // Padding to ensure the structure is a multiple of 16 bytes. + float constantAttenuation; + float linearAttenuation; + float quadraticAttenuation; + float padding3; // Padding to ensure the structure is a multiple of 16 bytes. }; + public: CelShadingShader(); CelShadingShader(const CelShadingShader&); diff --git a/enginecustom/celshading.ps b/enginecustom/celshading.ps index c613dcf..32fd479 100644 --- a/enginecustom/celshading.ps +++ b/enginecustom/celshading.ps @@ -5,6 +5,10 @@ cbuffer LightBuffer float padding; // Padding to ensure the structure is a multiple of 16 bytes. float3 lightPosition; // Add light position float padding2; // Padding to ensure the structure is a multiple of 16 bytes. + float constantAttenuation; + float linearAttenuation; + float quadraticAttenuation; + float padding3; // Padding to ensure the structure is a multiple of 16 bytes. }; Texture2D shaderTexture; @@ -41,6 +45,15 @@ float4 CelShadingPixelShader(PixelInputType input) : SV_TARGET // Combine the directional and positional light intensities. lightIntensity = max(directionalLightIntensity, positionalLightIntensity); + // Calculate the distance from the light to the fragment. + float distance = length(lightPosition - input.worldPos); + + // Apply an attenuation factor based on the distance. + float attenuation = 1.0f / (constantAttenuation + linearAttenuation * distance + quadraticAttenuation * distance * distance); + + // Combine the light intensity with the attenuation factor. + lightIntensity *= attenuation; + // Apply a step function to create the cel shading effect. if (lightIntensity > 0.75f) { @@ -71,4 +84,4 @@ float4 CelShadingPixelShader(PixelInputType input) : SV_TARGET finalColor = textureColor * diffuseColor * lightIntensity; return finalColor; -} \ No newline at end of file +} diff --git a/enginecustom/imgui.ini b/enginecustom/imgui.ini index 7130f2b..45d976f 100644 --- a/enginecustom/imgui.ini +++ b/enginecustom/imgui.ini @@ -15,10 +15,10 @@ Pos=60,60 Size=342,82 [Window][Light] -Pos=1223,64 +Pos=1564,17 Size=345,519 [Window][Shader Manager] -Pos=33,253 +Pos=32,253 Size=172,284