From af2231210c2e8ecc29a7414cf7364f1d94b383cf Mon Sep 17 00:00:00 2001 From: Harpie94 Date: Fri, 22 Mar 2024 18:00:55 +0100 Subject: [PATCH 1/3] =?UTF-8?q?D=C3=A9but=20Tuto=2010?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- enginecustom/Light.ps | 79 +++++++++++++++++++++++ enginecustom/Light.vs | 73 +++++++++++++++++++++ enginecustom/enginecustom.vcxproj | 1 + enginecustom/enginecustom.vcxproj.filters | 3 + 4 files changed, 156 insertions(+) create mode 100644 enginecustom/Light.ps create mode 100644 enginecustom/Light.vs diff --git a/enginecustom/Light.ps b/enginecustom/Light.ps new file mode 100644 index 0000000..b8add43 --- /dev/null +++ b/enginecustom/Light.ps @@ -0,0 +1,79 @@ +//////////////////////////////////////////////////////////////////////////////// +// Filename: light.ps +//////////////////////////////////////////////////////////////////////////////// + + +///////////// +// GLOBALS // +///////////// +Texture2D shaderTexture : register(t0); +SamplerState SampleType : register(s0); +cbuffer LightBuffer +{ + float4 ambientColor; + float4 diffuseColor; + float3 lightDirection; + float specularPower; + float4 specularColor; +}; +////////////// +// TYPEDEFS // +////////////// +struct PixelInputType +{ + float4 position : SV_POSITION; + float2 tex : TEXCOORD0; + float3 normal : NORMAL; + float3 viewDirection : TEXCOORD1; +}; + +//////////////////////////////////////////////////////////////////////////////// +// Pixel Shader +//////////////////////////////////////////////////////////////////////////////// +float4 LightPixelShader(PixelInputType input) : SV_TARGET +{ + float4 textureColor; + float3 lightDir; + float lightIntensity; + float4 color; + float3 reflection; + float4 specular; + + + // Sample the pixel color from the texture using the sampler at this texture coordinate location. + textureColor = shaderTexture.Sample(SampleType, input.tex); + + // Set the default output color to the ambient light value for all pixels. + color = ambientColor; + + // Initialize the specular color. + specular = float4(0.0f, 0.0f, 0.0f, 0.0f); + + // Invert the light direction for calculations. + lightDir = -lightDirection; + + // Calculate the amount of light on this pixel. + lightIntensity = saturate(dot(input.normal, lightDir)); + + if(lightIntensity > 0.0f) + { + // Determine the final diffuse color based on the diffuse color and the amount of light intensity. + color += (diffuseColor * lightIntensity); + + // Saturate the ambient and diffuse color. + color = saturate(color); + + // Calculate the reflection vector based on the light intensity, normal vector, and light direction. + reflection = normalize(2.0f * lightIntensity * input.normal - lightDir); + + // Determine the amount of specular light based on the reflection vector, viewing direction, and specular power. + specular = pow(saturate(dot(reflection, input.viewDirection)), specularPower); + } + + // Multiply the texture pixel and the final diffuse color to get the final pixel color result. + color = color * textureColor; + // Add the specular component last to the output color. + color = saturate(color + specular); + + return color; +} diff --git a/enginecustom/Light.vs b/enginecustom/Light.vs new file mode 100644 index 0000000..15843cb --- /dev/null +++ b/enginecustom/Light.vs @@ -0,0 +1,73 @@ +//////////////////////////////////////////////////////////////////////////////// +// Filename: light.vs +//////////////////////////////////////////////////////////////////////////////// + + +///////////// +// GLOBALS // +///////////// +cbuffer MatrixBuffer +{ + matrix worldMatrix; + matrix viewMatrix; + matrix projectionMatrix; +}; +cbuffer CameraBuffer +{ + float3 cameraPosition; + float padding; +}; +////////////// +// 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 viewDirection : TEXCOORD1; +}; + +//////////////////////////////////////////////////////////////////////////////// +// Vertex Shader +//////////////////////////////////////////////////////////////////////////////// +PixelInputType LightVertexShader(VertexInputType input) +{ + PixelInputType output; + float4 worldPosition; + + + // 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 viewing direction based on the position of the camera and the position of the vertex in the world. + output.viewDirection = cameraPosition.xyz - worldPosition.xyz; + + // Normalize the viewing direction vector. + output.viewDirection = normalize(output.viewDirection); + + return output; +} \ No newline at end of file diff --git a/enginecustom/enginecustom.vcxproj b/enginecustom/enginecustom.vcxproj index ba1ba40..a1722bf 100644 --- a/enginecustom/enginecustom.vcxproj +++ b/enginecustom/enginecustom.vcxproj @@ -43,6 +43,7 @@ + diff --git a/enginecustom/enginecustom.vcxproj.filters b/enginecustom/enginecustom.vcxproj.filters index cc96857..cf581b5 100644 --- a/enginecustom/enginecustom.vcxproj.filters +++ b/enginecustom/enginecustom.vcxproj.filters @@ -98,6 +98,9 @@ texture + + shader + From da18ae654747a824ac4d751aa7c3ab04e475ab7b Mon Sep 17 00:00:00 2001 From: Harpie94 Date: Mon, 25 Mar 2024 18:03:06 +0100 Subject: [PATCH 2/3] =?UTF-8?q?Avancement=20Limi=C3=A8re?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- enginecustom/Light.ps | 36 +- enginecustom/Light.vs | 23 +- enginecustom/Lightclass.cpp | 45 +++ enginecustom/Lightclass.h | 37 ++ enginecustom/Lightshaderclass.cpp | 428 ++++++++++++++++++++++ enginecustom/Lightshaderclass.h | 65 ++++ enginecustom/applicationclass.cpp | 61 ++- enginecustom/applicationclass.h | 6 +- enginecustom/enginecustom.vcxproj | 5 + enginecustom/enginecustom.vcxproj.filters | 15 + enginecustom/modelclass.cpp | 6 + enginecustom/modelclass.h | 1 + 12 files changed, 678 insertions(+), 50 deletions(-) create mode 100644 enginecustom/Lightclass.cpp create mode 100644 enginecustom/Lightclass.h create mode 100644 enginecustom/Lightshaderclass.cpp create mode 100644 enginecustom/Lightshaderclass.h diff --git a/enginecustom/Light.ps b/enginecustom/Light.ps index b8add43..66babd6 100644 --- a/enginecustom/Light.ps +++ b/enginecustom/Light.ps @@ -10,12 +10,12 @@ Texture2D shaderTexture : register(t0); SamplerState SampleType : register(s0); cbuffer LightBuffer { - float4 ambientColor; float4 diffuseColor; float3 lightDirection; - float specularPower; - float4 specularColor; + float padding; }; + + ////////////// // TYPEDEFS // ////////////// @@ -24,9 +24,9 @@ struct PixelInputType float4 position : SV_POSITION; float2 tex : TEXCOORD0; float3 normal : NORMAL; - float3 viewDirection : TEXCOORD1; }; + //////////////////////////////////////////////////////////////////////////////// // Pixel Shader //////////////////////////////////////////////////////////////////////////////// @@ -36,44 +36,22 @@ float4 LightPixelShader(PixelInputType input) : SV_TARGET float3 lightDir; float lightIntensity; float4 color; - float3 reflection; - float4 specular; // Sample the pixel color from the texture using the sampler at this texture coordinate location. textureColor = shaderTexture.Sample(SampleType, input.tex); - // Set the default output color to the ambient light value for all pixels. - color = ambientColor; - - // Initialize the specular color. - specular = float4(0.0f, 0.0f, 0.0f, 0.0f); - // Invert the light direction for calculations. lightDir = -lightDirection; // Calculate the amount of light on this pixel. lightIntensity = saturate(dot(input.normal, lightDir)); - if(lightIntensity > 0.0f) - { - // Determine the final diffuse color based on the diffuse color and the amount of light intensity. - color += (diffuseColor * lightIntensity); - - // Saturate the ambient and diffuse color. - color = saturate(color); - - // Calculate the reflection vector based on the light intensity, normal vector, and light direction. - reflection = normalize(2.0f * lightIntensity * input.normal - lightDir); - - // Determine the amount of specular light based on the reflection vector, viewing direction, and specular power. - specular = pow(saturate(dot(reflection, input.viewDirection)), specularPower); - } + // Determine the final amount of diffuse color based on the diffuse color combined with the light intensity. + color = saturate(diffuseColor * lightIntensity); // Multiply the texture pixel and the final diffuse color to get the final pixel color result. color = color * textureColor; - // Add the specular component last to the output color. - color = saturate(color + specular); return color; -} +} \ No newline at end of file diff --git a/enginecustom/Light.vs b/enginecustom/Light.vs index 15843cb..87f1edd 100644 --- a/enginecustom/Light.vs +++ b/enginecustom/Light.vs @@ -12,11 +12,7 @@ cbuffer MatrixBuffer matrix viewMatrix; matrix projectionMatrix; }; -cbuffer CameraBuffer -{ - float3 cameraPosition; - float padding; -}; + ////////////// // TYPEDEFS // ////////////// @@ -26,22 +22,22 @@ struct VertexInputType float2 tex : TEXCOORD0; float3 normal : NORMAL; }; + struct PixelInputType { float4 position : SV_POSITION; float2 tex : TEXCOORD0; float3 normal : NORMAL; - float3 viewDirection : TEXCOORD1; }; + //////////////////////////////////////////////////////////////////////////////// // Vertex Shader //////////////////////////////////////////////////////////////////////////////// PixelInputType LightVertexShader(VertexInputType input) { PixelInputType output; - float4 worldPosition; - + // Change the position vector to be 4 units for proper matrix calculations. input.position.w = 1.0f; @@ -53,21 +49,12 @@ PixelInputType LightVertexShader(VertexInputType input) // 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 viewing direction based on the position of the camera and the position of the vertex in the world. - output.viewDirection = cameraPosition.xyz - worldPosition.xyz; - - // Normalize the viewing direction vector. - output.viewDirection = normalize(output.viewDirection); - return output; } \ No newline at end of file diff --git a/enginecustom/Lightclass.cpp b/enginecustom/Lightclass.cpp new file mode 100644 index 0000000..e6f0f9b --- /dev/null +++ b/enginecustom/Lightclass.cpp @@ -0,0 +1,45 @@ +//////////////////////////////////////////////////////////////////////////////// +// Filename: lightclass.cpp +//////////////////////////////////////////////////////////////////////////////// +#include "lightclass.h" + + +LightClass::LightClass() +{ +} + + +LightClass::LightClass(const LightClass& other) +{ +} + + +LightClass::~LightClass() +{ +} + + +void LightClass::SetDiffuseColor(float red, float green, float blue, float alpha) +{ + m_diffuseColor = XMFLOAT4(red, green, blue, alpha); + return; +} + + +void LightClass::SetDirection(float x, float y, float z) +{ + m_direction = XMFLOAT3(x, y, z); + return; +} + + +XMFLOAT4 LightClass::GetDiffuseColor() +{ + return m_diffuseColor; +} + + +XMFLOAT3 LightClass::GetDirection() +{ + return m_direction; +} \ No newline at end of file diff --git a/enginecustom/Lightclass.h b/enginecustom/Lightclass.h new file mode 100644 index 0000000..0159c95 --- /dev/null +++ b/enginecustom/Lightclass.h @@ -0,0 +1,37 @@ +#pragma once +//////////////////////////////////////////////////////////////////////////////// +// Filename: lightclass.h +//////////////////////////////////////////////////////////////////////////////// +#ifndef _LIGHTCLASS_H_ +#define _LIGHTCLASS_H_ + + +////////////// +// INCLUDES // +////////////// +#include +using namespace DirectX; + + +//////////////////////////////////////////////////////////////////////////////// +// Class name: LightClass +//////////////////////////////////////////////////////////////////////////////// +class LightClass +{ +public: + LightClass(); + LightClass(const LightClass&); + ~LightClass(); + + void SetDirection(float, float, float); + void SetDiffuseColor(float, float, float, float); + + XMFLOAT3 GetDirection(); + XMFLOAT4 GetDiffuseColor(); + +private: + XMFLOAT4 m_diffuseColor; + XMFLOAT3 m_direction; +}; + +#endif \ No newline at end of file diff --git a/enginecustom/Lightshaderclass.cpp b/enginecustom/Lightshaderclass.cpp new file mode 100644 index 0000000..d615a75 --- /dev/null +++ b/enginecustom/Lightshaderclass.cpp @@ -0,0 +1,428 @@ +//////////////////////////////////////////////////////////////////////////////// +// Filename: lightshaderclass.cpp +//////////////////////////////////////////////////////////////////////////////// +#include "lightshaderclass.h" + + +LightShaderClass::LightShaderClass() +{ + m_vertexShader = 0; + m_pixelShader = 0; + m_layout = 0; + m_sampleState = 0; + m_matrixBuffer = 0; + m_lightBuffer = 0; +} + + +LightShaderClass::LightShaderClass(const LightShaderClass& other) +{ +} + + +LightShaderClass::~LightShaderClass() +{ +} + + +bool LightShaderClass::Initialize(ID3D11Device* device, HWND hwnd) +{ + 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"../Engine/light.vs"); + if (error != 0) + { + return false; + } + + // Set the filename of the pixel shader. + error = wcscpy_s(psFilename, 128, L"../Engine/light.ps"); + if (error != 0) + { + return false; + } + + // Initialize the vertex and pixel shaders. + result = InitializeShader(device, hwnd, vsFilename, psFilename); + if (!result) + { + return false; + } + + return true; +} + + +void LightShaderClass::Shutdown() +{ + // Shutdown the vertex and pixel shaders as well as the related objects. + ShutdownShader(); + + return; +} + +bool LightShaderClass::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 LightShaderClass::InitializeShader(ID3D11Device* device, HWND hwnd, WCHAR* vsFilename, WCHAR* psFilename) +{ + 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 lightBufferDesc; + + + // 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, "LightVertexShader", "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 + { + MessageBox(hwnd, vsFilename, L"Missing Shader File", MB_OK); + } + + return false; + } + + // Compile the pixel shader code. + result = D3DCompileFromFile(psFilename, NULL, NULL, "LightPixelShader", "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 + { + 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(), NULL, &m_vertexShader); + if (FAILED(result)) + { + return false; + } + + // Create the pixel shader from the buffer. + result = device->CreatePixelShader(pixelShaderBuffer->GetBufferPointer(), pixelShaderBuffer->GetBufferSize(), NULL, &m_pixelShader); + if (FAILED(result)) + { + 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)) + { + 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)) + { + 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)) + { + return false; + } + + // Setup the description of the light dynamic constant buffer that is in the pixel shader. + // Note that ByteWidth always needs to be a multiple of 16 if using D3D11_BIND_CONSTANT_BUFFER or CreateBuffer will fail. + 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 vertex shader constant buffer from within this class. + result = device->CreateBuffer(&lightBufferDesc, NULL, &m_lightBuffer); + if (FAILED(result)) + { + return false; + } + + return true; +} + + +void LightShaderClass::ShutdownShader() +{ + // Release the light constant buffer. + if (m_lightBuffer) + { + m_lightBuffer->Release(); + m_lightBuffer = 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; + } + + return; +} + + +void LightShaderClass::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 LightShaderClass::SetShaderParameters(ID3D11DeviceContext* deviceContext, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix, + ID3D11ShaderResourceView* texture, XMFLOAT3 lightDirection, XMFLOAT4 diffuseColor) +{ + HRESULT result; + D3D11_MAPPED_SUBRESOURCE mappedResource; + unsigned int bufferNumber; + MatrixBufferType* dataPtr; + LightBufferType* dataPtr2; + + + // 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; + + // Now 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; + 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 LightShaderClass::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/Lightshaderclass.h b/enginecustom/Lightshaderclass.h new file mode 100644 index 0000000..247d3b8 --- /dev/null +++ b/enginecustom/Lightshaderclass.h @@ -0,0 +1,65 @@ +//////////////////////////////////////////////////////////////////////////////// +// Filename: lightshaderclass.h +//////////////////////////////////////////////////////////////////////////////// +#ifndef _LIGHTSHADERCLASS_H_ +#define _LIGHTSHADERCLASS_H_ + + +////////////// +// INCLUDES // +////////////// +#include +#include +#include +#include +using namespace DirectX; +using namespace std; + + +//////////////////////////////////////////////////////////////////////////////// +// Class name: LightShaderClass +//////////////////////////////////////////////////////////////////////////////// +class LightShaderClass +{ +private: + struct MatrixBufferType + { + XMMATRIX world; + XMMATRIX view; + XMMATRIX projection; + }; + + struct LightBufferType + { + XMFLOAT4 diffuseColor; + XMFLOAT3 lightDirection; + float padding; // Added extra padding so structure is a multiple of 16 for CreateBuffer function requirements. + }; + +public: + LightShaderClass(); + LightShaderClass(const LightShaderClass&); + ~LightShaderClass(); + + 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; + ID3D11SamplerState* m_sampleState; + ID3D11Buffer* m_matrixBuffer; + ID3D11Buffer* m_lightBuffer; +}; + +#endif \ No newline at end of file diff --git a/enginecustom/applicationclass.cpp b/enginecustom/applicationclass.cpp index f953417..af6f3dd 100644 --- a/enginecustom/applicationclass.cpp +++ b/enginecustom/applicationclass.cpp @@ -6,6 +6,8 @@ ApplicationClass::ApplicationClass() m_Camera = 0; m_Model = 0; m_TextureShader = 0; + m_LightShader = 0; + m_Light = 0; } @@ -72,12 +74,43 @@ bool ApplicationClass::Initialize(int screenWidth, int screenHeight, HWND hwnd) return false; } + + // Create and initialize the light shader object. + m_LightShader = new LightShaderClass; + + result = m_LightShader->Initialize(m_Direct3D->GetDevice(), hwnd); + if (!result) + { + MessageBox(hwnd, L"Could not initialize the light shader object.", L"Error", MB_OK); + return false; + } + + // Create and initialize the light object. + m_Light = new LightClass; + + m_Light->SetDiffuseColor(1.0f, 1.0f, 1.0f, 1.0f); + m_Light->SetDirection(0.0f, 0.0f, 1.0f); + return true; } void ApplicationClass::Shutdown() { + // Release the light object. + if (m_Light) + { + delete m_Light; + m_Light = 0; + } + + // Release the light shader object. + if (m_LightShader) + { + m_LightShader->Shutdown(); + delete m_LightShader; + m_LightShader = 0; + } // Release the texture shader object. if (m_TextureShader) { @@ -115,11 +148,19 @@ void ApplicationClass::Shutdown() bool ApplicationClass::Frame() { + static float rotation = 0.0f; bool result; + // Update the rotation variable each frame. + rotation -= 0.0174532925f * 0.1f; + if (rotation < 0.0f) + { + rotation += 360.0f; + } // Render the graphics scene. - result = Render(); + + result = Render(rotation); if (!result) { return false; @@ -129,7 +170,8 @@ bool ApplicationClass::Frame() } -bool ApplicationClass::Render() + +bool ApplicationClass::Render(float rotation) { XMMATRIX worldMatrix, viewMatrix, projectionMatrix; bool result; @@ -146,8 +188,15 @@ bool ApplicationClass::Render() m_Camera->GetViewMatrix(viewMatrix); m_Direct3D->GetProjectionMatrix(projectionMatrix); + // Rotate the world matrix by the rotation value so that the triangle will spin. + worldMatrix = XMMatrixRotationY(rotation); + + // Put the model vertex and index buffers on the graphics pipeline to prepare them for drawing. m_Model->Render(m_Direct3D->GetDeviceContext()); + + + // Render the model using the texture shader. result = m_TextureShader->Render(m_Direct3D->GetDeviceContext(), m_Model->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, m_Model->GetTexture()); if (!result) @@ -155,6 +204,14 @@ bool ApplicationClass::Render() return false; } + // Render the model using the light shader. + result = m_LightShader->Render(m_Direct3D->GetDeviceContext(), m_Model->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, m_Model->GetTexture(), + m_Light->GetDirection(), m_Light->GetDiffuseColor()); + if (!result) + { + return false; + } + // Present the rendered scene to the screen. m_Direct3D->EndScene(); diff --git a/enginecustom/applicationclass.h b/enginecustom/applicationclass.h index b0bf8f3..03618fd 100644 --- a/enginecustom/applicationclass.h +++ b/enginecustom/applicationclass.h @@ -11,6 +11,8 @@ #include "textureshaderclass.h" +#include "lightshaderclass.h" +#include "lightclass.h" ///////////// // GLOBALS // @@ -36,13 +38,15 @@ public: bool Frame(); private: - bool Render(); + bool Render(float); private: D3DClass* m_Direct3D; CameraClass* m_Camera; ModelClass* m_Model; TextureShaderClass* m_TextureShader; + LightShaderClass* m_LightShader; + LightClass* m_Light; }; #endif diff --git a/enginecustom/enginecustom.vcxproj b/enginecustom/enginecustom.vcxproj index a1722bf..badba0b 100644 --- a/enginecustom/enginecustom.vcxproj +++ b/enginecustom/enginecustom.vcxproj @@ -25,6 +25,8 @@ + + @@ -37,12 +39,15 @@ + + + diff --git a/enginecustom/enginecustom.vcxproj.filters b/enginecustom/enginecustom.vcxproj.filters index cf581b5..5a7e5d1 100644 --- a/enginecustom/enginecustom.vcxproj.filters +++ b/enginecustom/enginecustom.vcxproj.filters @@ -54,6 +54,12 @@ Fichiers sources + + Fichiers sources + + + Fichiers sources + @@ -83,6 +89,12 @@ Fichiers d%27en-tête + + Fichiers d%27en-tête + + + Fichiers d%27en-tête + @@ -101,6 +113,9 @@ shader + + shader + diff --git a/enginecustom/modelclass.cpp b/enginecustom/modelclass.cpp index d74d099..3fe78b1 100644 --- a/enginecustom/modelclass.cpp +++ b/enginecustom/modelclass.cpp @@ -97,22 +97,28 @@ bool ModelClass::InitializeBuffers(ID3D11Device* device) // Triangle 1 vertices[0].position = XMFLOAT3(-1.0f, -1.0f, 0.0f); // Bottom Left. vertices[0].texture = XMFLOAT2(0.0f, 1.0f); + vertices[0].normal = XMFLOAT3(0.0f, 0.0f, -1.0f); vertices[1].position = XMFLOAT3(1.0f, 1.0f, 0.0f); // Top Right. vertices[1].texture = XMFLOAT2(1.0f, 0.0f); + vertices[1].normal = XMFLOAT3(0.0f, 0.0f, -1.0f); vertices[2].position = XMFLOAT3(1.0f, -1.0f, 0.0f); // Bottom Right. vertices[2].texture = XMFLOAT2(1.0f, 1.0f); + vertices[2].normal = XMFLOAT3(0.0f, 0.0f, -1.0f); // Triangle 2 vertices[3].position = XMFLOAT3(-1.0f, 1.0f, 0.0f); // Top Left. vertices[3].texture = XMFLOAT2(0.0f, 0.0f); + vertices[3].normal = XMFLOAT3(0.0f, 0.0f, -1.0f); vertices[4].position = XMFLOAT3(1.0f, 1.0f, 0.0f); // Top Right. vertices[4].texture = XMFLOAT2(1.0f, 0.0f); + vertices[4].normal = XMFLOAT3(0.0f, 0.0f, -1.0f); vertices[5].position = XMFLOAT3(-1.0f, -1.0f, 0.0f); // Bottom Left. vertices[5].texture = XMFLOAT2(0.0f, 1.0f); + vertices[5].normal = XMFLOAT3(0.0f, 0.0f, -1.0f); // Load the index array with data. indices[0] = 0; // Bottom left. diff --git a/enginecustom/modelclass.h b/enginecustom/modelclass.h index aee6989..d570397 100644 --- a/enginecustom/modelclass.h +++ b/enginecustom/modelclass.h @@ -26,6 +26,7 @@ private: { XMFLOAT3 position; XMFLOAT2 texture; + XMFLOAT3 normal; }; public: From a160af0f6462fb99d20df2999e5b185e80554653 Mon Sep 17 00:00:00 2001 From: Harpie94 Date: Tue, 26 Mar 2024 11:23:18 +0100 Subject: [PATCH 3/3] Diffuse Lighting --- enginecustom/Lightshaderclass.cpp | 4 ++-- enginecustom/applicationclass.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/enginecustom/Lightshaderclass.cpp b/enginecustom/Lightshaderclass.cpp index d615a75..c759fd3 100644 --- a/enginecustom/Lightshaderclass.cpp +++ b/enginecustom/Lightshaderclass.cpp @@ -33,14 +33,14 @@ bool LightShaderClass::Initialize(ID3D11Device* device, HWND hwnd) bool result; // Set the filename of the vertex shader. - error = wcscpy_s(vsFilename, 128, L"../Engine/light.vs"); + error = wcscpy_s(vsFilename, 128, L"./Light.vs"); if (error != 0) { return false; } // Set the filename of the pixel shader. - error = wcscpy_s(psFilename, 128, L"../Engine/light.ps"); + error = wcscpy_s(psFilename, 128, L"./Light.ps"); if (error != 0) { return false; diff --git a/enginecustom/applicationclass.cpp b/enginecustom/applicationclass.cpp index af6f3dd..1d92d99 100644 --- a/enginecustom/applicationclass.cpp +++ b/enginecustom/applicationclass.cpp @@ -88,8 +88,8 @@ bool ApplicationClass::Initialize(int screenWidth, int screenHeight, HWND hwnd) // Create and initialize the light object. m_Light = new LightClass; - m_Light->SetDiffuseColor(1.0f, 1.0f, 1.0f, 1.0f); - m_Light->SetDirection(0.0f, 0.0f, 1.0f); + m_Light->SetDiffuseColor(1.0f, 0.0f, 0.0f, 1.0f); + m_Light->SetDirection(0.0f, 1.0f, 0.0f); return true; }