diff --git a/KhaoticDemo/water.ps b/KhaoticDemo/water.ps new file mode 100644 index 0000000..290888f --- /dev/null +++ b/KhaoticDemo/water.ps @@ -0,0 +1,72 @@ +///////////// +// GLOBALS // +///////////// +SamplerState SampleType : register(s0); + +Texture2D reflectionTexture : register(t0); +Texture2D refractionTexture : register(t1); +Texture2D normalTexture : register(t2); + +cbuffer WaterBuffer +{ + float waterTranslation; + float reflectRefractScale; + float2 padding; +}; + + +////////////// +// TYPEDEFS // +////////////// +struct PixelInputType +{ + float4 position : SV_POSITION; + float2 tex : TEXCOORD0; + float4 reflectionPosition : TEXCOORD1; + float4 refractionPosition : TEXCOORD2; +}; + + +//////////////////////////////////////////////////////////////////////////////// +// Pixel Shader +//////////////////////////////////////////////////////////////////////////////// +float4 WaterPixelShader(PixelInputType input) : SV_TARGET +{ + float2 reflectTexCoord; + float2 refractTexCoord; + float4 normalMap; + float3 normal; + float4 reflectionColor; + float4 refractionColor; + float4 color; + + // Move the position the water normal is sampled from to simulate moving water. + input.tex.y += waterTranslation; + + // Calculate the projected reflection texture coordinates. + reflectTexCoord.x = input.reflectionPosition.x / input.reflectionPosition.w / 2.0f + 0.5f; + reflectTexCoord.y = -input.reflectionPosition.y / input.reflectionPosition.w / 2.0f + 0.5f; + + // Calculate the projected refraction texture coordinates. + refractTexCoord.x = input.refractionPosition.x / input.refractionPosition.w / 2.0f + 0.5f; + refractTexCoord.y = -input.refractionPosition.y / input.refractionPosition.w / 2.0f + 0.5f; + + // Sample the normal from the normal map texture. + normalMap = normalTexture.Sample(SampleType, input.tex); + + // Expand the range of the normal from (0,1) to (-1,+1). + normal = (normalMap.xyz * 2.0f) - 1.0f; + + // Re-position the texture coordinate sampling position by the normal map value to simulate the rippling wave effect. + reflectTexCoord = reflectTexCoord + (normal.xy * reflectRefractScale); + refractTexCoord = refractTexCoord + (normal.xy * reflectRefractScale); + + // Sample the texture pixels from the textures using the updated texture coordinates. + reflectionColor = reflectionTexture.Sample(SampleType, reflectTexCoord); + refractionColor = refractionTexture.Sample(SampleType, refractTexCoord); + + // Combine the reflection and refraction results for the final color. + color = lerp(reflectionColor, refractionColor, 0.6f); + + return color; +} \ No newline at end of file diff --git a/README.md b/README.md index f482d70..9741747 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ 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). -Ce moteur est basé sur **DirectX11** utilise **ImGui** avec une couche d'abstraction pour permetre son usage avec d'autres API. +Ce moteur est basé sur **DirectX11** utilise **ImGui** et **Boost** avec une couche d'abstraction pour permetre son usage avec d'autres API. --- @@ -10,15 +10,14 @@ Khaotic Engine is a rendering engine made in **C++** by a small team with the ai This **DirectX11** based engine uses **ImGui** with an abstraction layer to enable its use with other APIs. - ## Installation -**Par la solution + Debogueur :** +**Depuis la solution + Debugger** - 1. Télécharger la Release Beta - 2. Dezip le Zip - 3. Ouvrir le fichier en .sln - 4. Lancer le déboguage +1. Télécharge la Beta +2. Dézip le .zip +3. Ouvre le fichier .sln +4. Build en Release ---- @@ -27,7 +26,8 @@ This **DirectX11** based engine uses **ImGui** with an abstraction layer to enab 1. Download the Beta Release 2. Unzip the Zip file 3. Open the .sln file - 4. Launch the debugger + 4. Set the debugger in "Release" + 5. Launch the debugger @@ -45,6 +45,9 @@ This **DirectX11** based engine uses **ImGui** with an abstraction layer to enab - **Clipping Planes** - **Texture Translation** - **Transparency** + - **Water** + - **Refraction** + - *Reflection (cassé / broken)* *Plus de shaders seront disponibles dans le futur* @@ -70,7 +73,7 @@ La librairie ImGui est utilisée afin d'interragir avec les éléments du moteur - Modifier les propriétées des lumières (Position, Couleur RVB) ---- -*This part of the engine is still in developpement, other features will be added in the future* +*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. @@ -89,6 +92,13 @@ ImGui is used to allow interaction between the user and the objects in the scene [![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-) @@ -105,3 +115,4 @@ ImGui is used to allow interaction between the user and the objects in the scene + diff --git a/enginecustom/Lightshaderclass.cpp b/enginecustom/Lightshaderclass.cpp index f195156..6f76143 100644 --- a/enginecustom/Lightshaderclass.cpp +++ b/enginecustom/Lightshaderclass.cpp @@ -75,13 +75,13 @@ void LightShaderClass::Shutdown() } bool LightShaderClass::Render(ID3D11DeviceContext* deviceContext, int indexCount, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix, - ID3D11ShaderResourceView* texture, XMFLOAT4 diffuseColor[], XMFLOAT4 lightPosition[]) + ID3D11ShaderResourceView* texture, XMFLOAT4 diffuseColor[], XMFLOAT4 lightPosition[], XMFLOAT4 ambientClor[]) { bool result; // Set the shader parameters that it will use for rendering. - result = SetShaderParameters(deviceContext, worldMatrix, viewMatrix, projectionMatrix, texture, diffuseColor, lightPosition); + result = SetShaderParameters(deviceContext, worldMatrix, viewMatrix, projectionMatrix, texture, diffuseColor, lightPosition, ambientClor); if(!result) { Logger::Get().Log("Failed to set shader parameters", __FILE__, __LINE__, Logger::LogLevel::Error); @@ -418,7 +418,7 @@ void LightShaderClass::OutputShaderErrorMessage(ID3D10Blob* errorMessage, HWND h bool LightShaderClass::SetShaderParameters(ID3D11DeviceContext* deviceContext, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix, - ID3D11ShaderResourceView* texture, XMFLOAT4 diffuseColor[], XMFLOAT4 lightPosition[]) + ID3D11ShaderResourceView* texture, XMFLOAT4 diffuseColor[], XMFLOAT4 lightPosition[], XMFLOAT4 ambientColor[]) { HRESULT result; D3D11_MAPPED_SUBRESOURCE mappedResource; diff --git a/enginecustom/Lightshaderclass.h b/enginecustom/Lightshaderclass.h index 3cf4974..dd45b3d 100644 --- a/enginecustom/Lightshaderclass.h +++ b/enginecustom/Lightshaderclass.h @@ -67,14 +67,14 @@ public: bool Initialize(ID3D11Device*, HWND); void Shutdown(); - bool Render(ID3D11DeviceContext*, int, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, XMFLOAT4[], XMFLOAT4[]); + bool Render(ID3D11DeviceContext*, int, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, XMFLOAT4[], XMFLOAT4[], XMFLOAT4[]); private: bool InitializeShader(ID3D11Device*, HWND, WCHAR*, WCHAR*); void ShutdownShader(); void OutputShaderErrorMessage(ID3D10Blob*, HWND, WCHAR*); - bool SetShaderParameters(ID3D11DeviceContext*, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, XMFLOAT4[], XMFLOAT4[]); + bool SetShaderParameters(ID3D11DeviceContext*, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, XMFLOAT4[], XMFLOAT4[], XMFLOAT4[]); void RenderShader(ID3D11DeviceContext*, int); private: diff --git a/enginecustom/applicationclass.cpp b/enginecustom/applicationclass.cpp index feda5f3..5c7dc24 100644 --- a/enginecustom/applicationclass.cpp +++ b/enginecustom/applicationclass.cpp @@ -19,7 +19,11 @@ ApplicationClass::ApplicationClass() : m_ShouldQuit(false) m_Position = 0; m_Frustum = 0; m_DisplayPlane = 0; - m_ReflectionShader = 0; + m_BathModel = 0; + m_WaterModel = 0; + m_Light = 0; + m_RefractionTexture = 0; + m_ReflectionTexture = 0; } @@ -192,6 +196,7 @@ bool ApplicationClass::Initialize(int screenWidth, int screenHeight, HWND hwnd) m_Light->SetDiffuseColor(1.0f, 1.0f, 1.0f, 1.0f); m_Light->SetDirection(0.0f, 0.0f, -1.0f); + m_Light->SetAmbientColor(0.15f, 0.15f, 0.15f, 1.0f); m_Light->SetSpecularColor(1.0f, 1.0f, 1.0f, 1.0f); m_Light->SetSpecularPower(16.0f); @@ -203,6 +208,7 @@ bool ApplicationClass::Initialize(int screenWidth, int screenHeight, HWND hwnd) m_Lights[0] = new LightClass; m_Lights[0]->SetDiffuseColor(1.0f, 1.0f, 1.0f, 1.0f); // White m_Lights[0]->SetDirection(0.0f, 0.0f, -1.0f); + m_Lights[0]->SetAmbientColor(0.15f, 0.15f, 0.15f, 1.0f); m_Lights[0]->SetSpecularColor(1.0f, 1.0f, 1.0f, 1.0f); m_Lights[0]->SetSpecularPower(16.0f); m_Lights[0]->SetPosition(10.0f, 7.0f, -5.0f); @@ -210,6 +216,7 @@ bool ApplicationClass::Initialize(int screenWidth, int screenHeight, HWND hwnd) m_Lights[1] = new LightClass; m_Lights[1]->SetDiffuseColor(1.0f, 0.0f, 0.0f, 1.0f); // Red m_Lights[1]->SetDirection(0.0f, 0.0f, -1.0f); + m_Lights[1]->SetAmbientColor(0.15f, 0.15f, 0.15f, 1.0f); m_Lights[1]->SetSpecularColor(1.0f, 0.0f, 0.0f, 1.0f); m_Lights[1]->SetSpecularPower(16.0f); m_Lights[1]->SetPosition(-10.0f, 7.0f, -5.0f); @@ -217,6 +224,7 @@ bool ApplicationClass::Initialize(int screenWidth, int screenHeight, HWND hwnd) m_Lights[2] = new LightClass; m_Lights[2]->SetDiffuseColor(0.0f, 1.0f, 0.0f, 1.0f); // Green m_Lights[2]->SetDirection(0.0f, 0.0f, -1.0f); + m_Lights[2]->SetAmbientColor(0.15f, 0.15f, 0.15f, 1.0f); m_Lights[2]->SetSpecularColor(0.0f, 1.0f, 0.0f, 1.0f); m_Lights[2]->SetSpecularPower(16.0f); m_Lights[2]->SetPosition(10.0f, 7.0f, 5.0f); @@ -224,6 +232,7 @@ bool ApplicationClass::Initialize(int screenWidth, int screenHeight, HWND hwnd) m_Lights[3] = new LightClass; m_Lights[3]->SetDiffuseColor(0.0f, 0.0f, 1.0f, 1.0f); // Blue m_Lights[3]->SetDirection(0.0f, 0.0f, -1.0f); + m_Lights[3]->SetAmbientColor(0.15f, 0.15f, 0.15f, 1.0f); m_Lights[3]->SetSpecularColor(0.0f, 0.0f, 1.0f, 1.0f); m_Lights[3]->SetSpecularPower(16.0f); m_Lights[3]->SetPosition(-10.0f, 7.0f, 5.0f); @@ -255,6 +264,60 @@ bool ApplicationClass::Initialize(int screenWidth, int screenHeight, HWND hwnd) m_ModelList = new ModelListClass; m_ModelList->Initialize(25); + // Set the file names of the bath model. + strcpy_s(modelFilename, "bath.txt"); + Filename.push_back("marble01.tga"); + + // Create and initialize the bath model object. + m_BathModel = new ModelClass; + + result = m_BathModel->Initialize(m_Direct3D->GetDevice(), m_Direct3D->GetDeviceContext(), modelFilename, Filename); + if (!result) + { + MessageBox(hwnd, L"Could not initialize the bath model object.", L"Error", MB_OK); + return false; + } + + // Set the file names of the water model. + strcpy_s(modelFilename, "water.txt"); + Filename.push_back("water01.tga"); + + // Create and initialize the water model object. + m_WaterModel = new ModelClass; + + result = m_WaterModel->Initialize(m_Direct3D->GetDevice(), m_Direct3D->GetDeviceContext(), modelFilename, Filename); + if (!result) + { + MessageBox(hwnd, L"Could not initialize the water model object.", L"Error", MB_OK); + return false; + } + + // Create and initialize the refraction render to texture object. + m_RefractionTexture = new RenderTextureClass; + + result = m_RefractionTexture->Initialize(m_Direct3D->GetDevice(), screenWidth, screenHeight, SCREEN_DEPTH, SCREEN_NEAR, 1); + if (!result) + { + MessageBox(hwnd, L"Could not initialize the refraction render texture object.", L"Error", MB_OK); + return false; + } + + // Create and initialize the reflection render to texture object. + m_ReflectionTexture = new RenderTextureClass; + + result = m_ReflectionTexture->Initialize(m_Direct3D->GetDevice(), screenWidth, screenHeight, SCREEN_DEPTH, SCREEN_NEAR, 1); + if (!result) + { + MessageBox(hwnd, L"Could not initialize the reflection render texture object.", L"Error", MB_OK); + return false; + } + + // Set the height of the water. + m_waterHeight = -9.25f; + + // Initialize the position of the water. + m_waterTranslation = 100.0f; + // Create and initialize the timer object. m_Timer = new TimerClass; @@ -317,6 +380,38 @@ void ApplicationClass::Shutdown() Logger::Get().Log("Shader manager object released", __FILE__, __LINE__, Logger::LogLevel::Shutdown); } + // Release the reflection render texture object. + if (m_ReflectionTexture) + { + m_ReflectionTexture->Shutdown(); + delete m_ReflectionTexture; + m_ReflectionTexture = 0; + } + + // Release the refraction render texture object. + if (m_RefractionTexture) + { + m_RefractionTexture->Shutdown(); + delete m_RefractionTexture; + m_RefractionTexture = 0; + } + + // Release the water model object. + if (m_WaterModel) + { + m_WaterModel->Shutdown(); + delete m_WaterModel; + m_WaterModel = 0; + } + + // Release the bath model object. + if (m_BathModel) + { + m_BathModel->Shutdown(); + delete m_BathModel; + m_BathModel = 0; + } + // Release the frustum class object. if (m_Frustum) { @@ -593,6 +688,28 @@ bool ApplicationClass::Frame(InputClass* Input) rotation += 360.0f; } + // Update the position of the water to simulate motion. + m_waterTranslation += 0.001f; + if (m_waterTranslation > 1.0f) + { + m_waterTranslation -= 1.0f; + } + + // Render the refraction of the scene to a texture. + result = RenderRefractionToTexture(); + if (!result) + { + return false; + } + + // Render the reflection of the scene to a texture. + result = RenderReflectionToTexture(); + if (!result) + { + return false; + } + + //// Update the x position variable each frame. //x -= 0.0174532925f * 0.6f; @@ -641,6 +758,91 @@ bool ApplicationClass::Frame(InputClass* Input) return true; } +bool ApplicationClass::RenderRefractionToTexture() +{ + XMMATRIX worldMatrix, viewMatrix, projectionMatrix; + XMFLOAT4 diffuseColor[4], lightPosition[4], ambientColor[4]; + XMFLOAT4 clipPlane; + int i; + bool result; + + // Setup a clipping plane based on the height of the water to clip everything above it. + clipPlane = XMFLOAT4(0.0f, -1.0f, 0.0f, m_waterHeight + 0.1f); + + // Set the render target to be the refraction render to texture and clear it. + m_RefractionTexture->SetRenderTarget(m_Direct3D->GetDeviceContext()); + m_RefractionTexture->ClearRenderTarget(m_Direct3D->GetDeviceContext(), 0.0f, 0.0f, 0.0f, 1.0f); + + // Generate the view matrix based on the camera's position. + m_Camera->Render(); + + // Get the world, view, and projection matrices from the camera and d3d objects. + m_Direct3D->GetWorldMatrix(worldMatrix); + m_Camera->GetViewMatrix(viewMatrix); + m_Direct3D->GetProjectionMatrix(projectionMatrix); + + // Get the light properties. + for (i = 0; i < m_numLights; i++) + { + // Create the diffuse color array from the four light colors. + diffuseColor[i] = m_Lights[i]->GetDiffuseColor(); + + // Create the light position array from the four light positions. + lightPosition[i] = m_Lights[i]->GetPosition(); + + // Create the light position array from the four light positions. + ambientColor[i] = m_Lights[i]->GetAmbientColor(); + } + + // Translate to where the bath model will be rendered. + worldMatrix = XMMatrixTranslation(0.0f, -10.0f, 0.0f); + + // Render the bath model using the refraction shader. + m_BathModel->Render(m_Direct3D->GetDeviceContext()); + + result = m_ShaderManager->RenderRefractionShader(m_Direct3D->GetDeviceContext(), m_BathModel->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, + m_BathModel->GetTexture(0), m_Lights[0]->GetDirection(), ambientColor, diffuseColor, lightPosition, clipPlane); + if (!result) + { + return false; + } + + // Reset the render target back to the original back buffer and not the render to texture anymore. And reset the viewport back to the original. + m_Direct3D->SetBackBufferRenderTarget(); + m_Direct3D->ResetViewport(); + + return true; +} + +bool ApplicationClass::RenderReflectionToTexture() +{ + XMMATRIX worldMatrix, reflectionViewMatrix, projectionMatrix; + XMFLOAT4 diffuseColor[4], getDirection[4], ambientColor[4]; + bool result; + + + // Set the render target to be the reflection render to texture and clear it. + m_ReflectionTexture->SetRenderTarget(m_Direct3D->GetDeviceContext()); + m_ReflectionTexture->ClearRenderTarget(m_Direct3D->GetDeviceContext(), 0.0f, 0.0f, 0.0f, 1.0f); + + // Use the camera to render the reflection and create a reflection view matrix. + m_Camera->RenderReflection(m_waterHeight); + + // Get the camera reflection view matrix instead of the normal view matrix. + m_Camera->GetReflectionViewMatrix(reflectionViewMatrix); + + // Get the world and projection matrices from the d3d object. + m_Direct3D->GetWorldMatrix(worldMatrix); + m_Direct3D->GetProjectionMatrix(projectionMatrix); + + + // Reset the render target back to the original back buffer and not the render to texture anymore. And reset the viewport back to the original. + m_Direct3D->SetBackBufferRenderTarget(); + m_Direct3D->ResetViewport(); + + return true; +} + bool ApplicationClass::RenderSceneToTexture(float rotation) { XMMATRIX worldMatrix, viewMatrix, projectionMatrix; @@ -680,9 +882,9 @@ bool ApplicationClass::RenderSceneToTexture(float rotation) bool ApplicationClass::Render(float rotation, float x, float y, float z, float textureTranslation) { - XMMATRIX worldMatrix, viewMatrix, orthoMatrix, projectionMatrix, rotateMatrix, translateMatrix, scaleMatrix, srMatrix; + XMMATRIX worldMatrix, viewMatrix, orthoMatrix, projectionMatrix, rotateMatrix, translateMatrix, scaleMatrix, srMatrix, reflectionMatrix; float positionX, positionY, positionZ, radius; - XMFLOAT4 diffuseColor[4], lightPosition[4]; + XMFLOAT4 diffuseColor[4], lightPosition[4], getDirection[4], ambientColor[4]; int modelCount, renderCount, i; bool result, renderModel; float blendAmount; @@ -708,6 +910,9 @@ bool ApplicationClass::Render(float rotation, float x, float y, float z, float t // Create the light position array from the four light positions. lightPosition[i] = m_Lights[i]->GetPosition(); + + // Create the light position array from the four light positions. + ambientColor[i] = m_Lights[i]->GetPosition(); } scaleMatrix = XMMatrixScaling(0.5f, 0.5f, 0.5f); // Build the scaling matrix. @@ -723,7 +928,7 @@ bool ApplicationClass::Render(float rotation, float x, float y, float z, float t // Render the model using the light shader. result = m_ShaderManager->RenderlightShader(m_Direct3D->GetDeviceContext(), m_Model->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, m_Model->GetTexture(0), - diffuseColor, lightPosition); + diffuseColor, lightPosition, ambientColor); for (auto cube : m_cubes) { @@ -753,7 +958,7 @@ 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, cube->GetTexture(0), - diffuseColor, lightPosition); + diffuseColor, lightPosition,ambientColor); if (!result) { Logger::Get().Log("Could not render the cube model using the light shader", __FILE__, __LINE__, Logger::LogLevel::Error); @@ -785,7 +990,7 @@ 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); + diffuseColor, lightPosition, ambientColor); if (!result) { @@ -808,7 +1013,7 @@ bool ApplicationClass::Render(float rotation, float x, float y, float z, float t chunk->Render(m_Direct3D->GetDeviceContext()); result = m_ShaderManager->RenderlightShader(m_Direct3D->GetDeviceContext(), chunk->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, chunk->GetTexture(5), - diffuseColor, lightPosition); + diffuseColor, lightPosition, ambientColor); if (!result) { @@ -890,7 +1095,7 @@ bool ApplicationClass::Render(float rotation, float x, float y, float z, float t m_Model->Render(m_Direct3D->GetDeviceContext()); result = m_ShaderManager->RenderlightShader(m_Direct3D->GetDeviceContext(), m_Model->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, m_Model->GetTexture(0), - diffuseColor, lightPosition); + diffuseColor, lightPosition, ambientColor); if (!result) { Logger::Get().Log("Could not render the model using the light shader", __FILE__, __LINE__, Logger::LogLevel::Error); @@ -998,14 +1203,41 @@ bool ApplicationClass::Render(float rotation, float x, float y, float z, float t lightPosition[i] = m_Lights[i]->GetPosition(); } + // Translate to where the bath model will be rendered. + worldMatrix = XMMatrixTranslation(0.0f, -10.0f, 0.0f); + // Put the bath model vertex and index buffers on the graphics pipeline to prepare them for drawing. + m_BathModel->Render(m_Direct3D->GetDeviceContext()); - // Render the model using the multitexture shader. - //result = m_MultiTextureShader->Render(m_Direct3D->GetDeviceContext(), m_Model->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, - // m_Model->GetTexture(0), m_Model->GetTexture(1)); + // Render the bath model using the light shader. + result = m_ShaderManager->RenderTextureShader(m_Direct3D->GetDeviceContext(), m_BathModel->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, + m_BathModel->GetTexture(0)); + if (!result) + { + return false; + } - //// Render the model using the multitexture shader. - //m_Model->Render(m_Direct3D->GetDeviceContext()); + // Reset the world matrix. + m_Direct3D->GetWorldMatrix(worldMatrix); + + // Get the camera reflection view matrix. + m_Camera->GetReflectionViewMatrix(reflectionMatrix); + + // Translate to where the water model will be rendered. + worldMatrix = XMMatrixTranslation(0.0f, m_waterHeight, 0.0f); + + // Put the water model vertex and index buffers on the graphics pipeline to prepare them for drawing. + m_WaterModel->Render(m_Direct3D->GetDeviceContext()); + + // Render the water model using the water shader. + result = m_ShaderManager->RenderWaterShader(m_Direct3D->GetDeviceContext(), m_WaterModel->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, reflectionMatrix, + m_ReflectionTexture->GetShaderResourceView(), m_RefractionTexture->GetShaderResourceView(), m_WaterModel->GetTexture(0), + m_waterTranslation, 0.01f); + + if (!result) + { + return false; + } // Setup matrices. rotateMatrix = XMMatrixRotationY(rotation); @@ -1129,7 +1361,7 @@ bool ApplicationClass::Render(float rotation, float x, float y, float z, float t // Render the model using the transparent shader. m_Model->Render(m_Direct3D->GetDeviceContext()); - result = m_ShaderManager->RenderlightShader(m_Direct3D->GetDeviceContext(), m_Model->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, m_Model->GetTexture(0), diffuseColor, lightPosition); + result = m_ShaderManager->RenderlightShader(m_Direct3D->GetDeviceContext(), m_Model->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, m_Model->GetTexture(0), diffuseColor, lightPosition, ambientColor); if (!result) { return false; diff --git a/enginecustom/applicationclass.h b/enginecustom/applicationclass.h index 9308ff9..7628949 100644 --- a/enginecustom/applicationclass.h +++ b/enginecustom/applicationclass.h @@ -8,12 +8,10 @@ #include "d3dclass.h" #include "cameraclass.h" #include "object.h" -#include "lightshaderclass.h" #include "lightclass.h" #include #include -#include "lightmapshaderclass.h" #include "bitmapclass.h" #include "spriteclass.h" #include "timerclass.h" @@ -28,8 +26,6 @@ #include "frustumclass.h" #include "rendertextureclass.h" #include "displayplaneclass.h" -#include "reflectionshaderclass.h" -#include "systemclass.h" ///////////// @@ -90,6 +86,8 @@ private: bool UpdateFps(); bool UpdateRenderCountString(int); bool RenderSceneToTexture(float); + bool RenderRefractionToTexture(); + bool RenderReflectionToTexture(); private : @@ -99,7 +97,7 @@ private : D3DClass* m_Direct3D; IDXGISwapChain* m_swapChain; - ModelClass* m_Model; + ModelClass* m_Model,* m_GroundModel, * m_WallModel, * m_BathModel, * m_WaterModel; ModelListClass* m_ModelList; // ------------------------------------- // @@ -107,7 +105,7 @@ private : // ------------------------------------- // XMMATRIX m_baseViewMatrix; - RenderTextureClass* m_RenderTexture; + RenderTextureClass* m_RenderTexture, * m_RefractionTexture, * m_ReflectionTexture; DisplayPlaneClass* m_DisplayPlane; int m_screenWidth, m_screenHeight; CameraClass* m_Camera; @@ -138,11 +136,15 @@ private : ShaderManagerClass* m_ShaderManager; FontShaderClass* m_FontShader; - ReflectionShaderClass* m_ReflectionShader; - BitmapClass* m_Bitmap; SpriteClass* m_Sprite; + // ----------------------------------- // + // ------------ VARIABLES ------------ // + // ----------------------------------- // + + float m_waterHeight, m_waterTranslation; + // ------------------------------------------------- // // ------------- FPS AND INFO ON SCREEN ------------ // // ------------------------------------------------- // diff --git a/enginecustom/bath.txt b/enginecustom/bath.txt new file mode 100644 index 0000000..4f067c7 --- /dev/null +++ b/enginecustom/bath.txt @@ -0,0 +1,82 @@ +Vertex Count: 78 + +Data: + +4 -0.5 -4 0.998008 0.998008 0 1 -0 +-4 -0.5 4 0.001992 0.00199199 0 1 -0 +4 -0.5 4 0.998008 0.00199199 0 1 -0 +4 -0.5 -4 0.998008 0.998008 0 1 -0 +-4 -0.5 -4 0.001992 0.998008 0 1 -0 +-4 -0.5 4 0.001992 0.00199199 0 1 -0 +4 1 4 0.187127 0.998008 0 0 -1 +-4 -0.5 4 0.000374 0.00199199 0 0 -1 +-4 1 4 0.187127 0.00199199 0 0 -1 +4 -0.5 4 0.000374 0.998008 0 0 -1 +-4 -0.5 4 0.000374 0.00199199 0 0 -1 +4 1 4 0.187127 0.998008 0 0 -1 +4 1 -4 0.187126 0.998008 -1 0 -0 +4 -0.5 4 0.000373 0.00199199 -1 0 -0 +4 1 4 0.187126 0.00199199 -1 0 -0 +4 -0.5 -4 0.000373 0.998008 -1 0 -0 +4 -0.5 4 0.000373 0.00199199 -1 0 -0 +4 1 -4 0.187126 0.998008 -1 0 -0 +-4 1 -4 0.000374 0.00199199 0 0 1 +4 -0.5 -4 0.187127 0.998008 0 0 1 +4 1 -4 0.000374 0.998008 0 0 1 +-4 1 -4 0.000374 0.00199199 0 0 1 +-4 -0.5 -4 0.187127 0.00199199 0 0 1 +4 -0.5 -4 0.187127 0.998008 0 0 1 +-4 1 4 0.187127 0.998008 1 0 -0 +-4 -0.5 -4 0.000374 0.00199199 1 0 -0 +-4 1 -4 0.187127 0.00199199 1 0 -0 +-4 -0.5 4 0.000374 0.998008 1 0 -0 +-4 -0.5 -4 0.000374 0.00199199 1 0 -0 +-4 1 4 0.187127 0.998008 1 0 -0 +-5 1 5 0.199602 0.00199199 -1 0 -0 +-5 -1 -5 0.000398 0.998008 -1 0 -0 +-5 -1 5 0.000398 0.00199199 -1 0 -0 +-5 1 -5 0.199602 0.998008 -1 0 -0 +-5 -1 -5 0.000398 0.998008 -1 0 -0 +-5 1 5 0.199602 0.00199199 -1 0 -0 +5 1 -5 0.199602 0.00199199 1 0 -0 +5 -1 5 0.000398 0.998008 1 0 -0 +5 -1 -5 0.000398 0.00199199 1 0 -0 +5 1 5 0.199602 0.998008 1 0 -0 +5 -1 5 0.000398 0.998008 1 0 -0 +5 1 -5 0.199602 0.00199199 1 0 -0 +-5 -1 5 0.199602 0.00199199 0 0 1 +5 1 5 0.000398 0.998008 0 0 1 +-5 1 5 0.000398 0.00199199 0 0 1 +5 -1 5 0.199602 0.998008 0 0 1 +5 1 5 0.000398 0.998008 0 0 1 +-5 -1 5 0.199602 0.00199199 0 0 1 +-5 1 5 0.001992 0.00199199 0 1 -0 +-4 1 -4 0.101594 0.898406 0 1 -0 +-5 1 -5 0.001992 0.998008 0 1 -0 +-5 1 5 0.001992 0.00199199 0 1 -0 +-4 1 4 0.101594 0.101594 0 1 -0 +-4 1 -4 0.101594 0.898406 0 1 -0 +-4 1 -4 0.101594 0.898406 0 1 -0 +5 1 -5 0.998008 0.998008 0 1 -0 +-5 1 -5 0.001992 0.998008 0 1 -0 +4 1 -4 0.898406 0.898406 0 1 -0 +5 1 -5 0.998008 0.998008 0 1 -0 +-4 1 -4 0.101594 0.898406 0 1 -0 +4 1 -4 0.898406 0.898406 0 1 -0 +5 1 5 0.998008 0.00199199 0 1 -0 +5 1 -5 0.998008 0.998008 0 1 -0 +4 1 4 0.898406 0.101594 0 1 -0 +5 1 5 0.998008 0.00199199 0 1 -0 +4 1 -4 0.898406 0.898406 0 1 -0 +4 1 4 0.898406 0.101594 0 1 -0 +-5 1 5 0.001992 0.00199199 0 1 -0 +5 1 5 0.998008 0.00199199 0 1 -0 +-5 1 5 0.001992 0.00199199 0 1 -0 +4 1 4 0.898406 0.101594 0 1 -0 +-4 1 4 0.101594 0.101594 0 1 -0 +-5 1 -5 0.199602 0.00199199 0 0 -1 +5 -1 -5 0.000398 0.998008 0 0 -1 +-5 -1 -5 0.000398 0.00199199 0 0 -1 +5 1 -5 0.199602 0.998008 0 0 -1 +5 -1 -5 0.000398 0.998008 0 0 -1 +-5 1 -5 0.199602 0.00199199 0 0 -1 diff --git a/enginecustom/enginecustom.vcxproj b/enginecustom/enginecustom.vcxproj index 868cc9b..6a6f8fa 100644 --- a/enginecustom/enginecustom.vcxproj +++ b/enginecustom/enginecustom.vcxproj @@ -48,6 +48,7 @@ + @@ -61,6 +62,7 @@ + @@ -93,6 +95,7 @@ + @@ -107,6 +110,7 @@ + @@ -145,6 +149,7 @@ Document + Document @@ -170,6 +175,9 @@ Document + + + @@ -203,6 +211,7 @@ + diff --git a/enginecustom/enginecustom.vcxproj.filters b/enginecustom/enginecustom.vcxproj.filters index a60fa9b..a3c1ca3 100644 --- a/enginecustom/enginecustom.vcxproj.filters +++ b/enginecustom/enginecustom.vcxproj.filters @@ -162,6 +162,12 @@ Fichiers sources + + Fichiers sources + + + Fichiers sources + @@ -299,6 +305,12 @@ Fichiers d%27en-tête + + Fichiers d%27en-tête + + + Fichiers d%27en-tête + @@ -313,9 +325,16 @@ Assets + + Assets + + + + + diff --git a/enginecustom/ground.txt b/enginecustom/ground.txt new file mode 100644 index 0000000..231d065 --- /dev/null +++ b/enginecustom/ground.txt @@ -0,0 +1,10 @@ +Vertex Count: 6 + +Data: + +-20 0 20 0.0 0.0 0 1 0 + 20 0 -20 1.0 1.0 0 1 0 +-20 0 -20 0.0 1.0 0 1 0 + 20 0 20 1.0 0.0 0 1 0 + 20 0 -20 1.0 1.0 0 1 0 +-20 0 20 0.0 0.0 0 1 0 diff --git a/enginecustom/ground01.tga b/enginecustom/ground01.tga new file mode 100644 index 0000000..b216021 Binary files /dev/null and b/enginecustom/ground01.tga differ diff --git a/enginecustom/lightshaderclass.cpp b/enginecustom/lightshaderclass.cpp index f195156..6f76143 100644 --- a/enginecustom/lightshaderclass.cpp +++ b/enginecustom/lightshaderclass.cpp @@ -75,13 +75,13 @@ void LightShaderClass::Shutdown() } bool LightShaderClass::Render(ID3D11DeviceContext* deviceContext, int indexCount, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix, - ID3D11ShaderResourceView* texture, XMFLOAT4 diffuseColor[], XMFLOAT4 lightPosition[]) + ID3D11ShaderResourceView* texture, XMFLOAT4 diffuseColor[], XMFLOAT4 lightPosition[], XMFLOAT4 ambientClor[]) { bool result; // Set the shader parameters that it will use for rendering. - result = SetShaderParameters(deviceContext, worldMatrix, viewMatrix, projectionMatrix, texture, diffuseColor, lightPosition); + result = SetShaderParameters(deviceContext, worldMatrix, viewMatrix, projectionMatrix, texture, diffuseColor, lightPosition, ambientClor); if(!result) { Logger::Get().Log("Failed to set shader parameters", __FILE__, __LINE__, Logger::LogLevel::Error); @@ -418,7 +418,7 @@ void LightShaderClass::OutputShaderErrorMessage(ID3D10Blob* errorMessage, HWND h bool LightShaderClass::SetShaderParameters(ID3D11DeviceContext* deviceContext, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix, - ID3D11ShaderResourceView* texture, XMFLOAT4 diffuseColor[], XMFLOAT4 lightPosition[]) + ID3D11ShaderResourceView* texture, XMFLOAT4 diffuseColor[], XMFLOAT4 lightPosition[], XMFLOAT4 ambientColor[]) { HRESULT result; D3D11_MAPPED_SUBRESOURCE mappedResource; diff --git a/enginecustom/lightshaderclass.h b/enginecustom/lightshaderclass.h index 3cf4974..dd45b3d 100644 --- a/enginecustom/lightshaderclass.h +++ b/enginecustom/lightshaderclass.h @@ -67,14 +67,14 @@ public: bool Initialize(ID3D11Device*, HWND); void Shutdown(); - bool Render(ID3D11DeviceContext*, int, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, XMFLOAT4[], XMFLOAT4[]); + bool Render(ID3D11DeviceContext*, int, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, XMFLOAT4[], XMFLOAT4[], XMFLOAT4[]); private: bool InitializeShader(ID3D11Device*, HWND, WCHAR*, WCHAR*); void ShutdownShader(); void OutputShaderErrorMessage(ID3D10Blob*, HWND, WCHAR*); - bool SetShaderParameters(ID3D11DeviceContext*, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, XMFLOAT4[], XMFLOAT4[]); + bool SetShaderParameters(ID3D11DeviceContext*, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, XMFLOAT4[], XMFLOAT4[], XMFLOAT4[]); void RenderShader(ID3D11DeviceContext*, int); private: diff --git a/enginecustom/lightshaderwaterclass.h b/enginecustom/lightshaderwaterclass.h new file mode 100644 index 0000000..6f70f09 --- /dev/null +++ b/enginecustom/lightshaderwaterclass.h @@ -0,0 +1 @@ +#pragma once diff --git a/enginecustom/marble01.tga b/enginecustom/marble01.tga new file mode 100644 index 0000000..1a6d4ae Binary files /dev/null and b/enginecustom/marble01.tga differ diff --git a/enginecustom/refraction.ps b/enginecustom/refraction.ps new file mode 100644 index 0000000..48190cf --- /dev/null +++ b/enginecustom/refraction.ps @@ -0,0 +1,63 @@ +///////////// +// GLOBALS // +///////////// +SamplerState SampleType : register(s0); +Texture2D shaderTexture : register(t0); + +cbuffer LightBuffer +{ + float4 ambientColor; + float4 diffuseColor; + float3 lightDirection; +}; + + +////////////// +// TYPEDEFS // +////////////// +struct PixelInputType +{ + float4 position : SV_POSITION; + float2 tex : TEXCOORD0; + float3 normal : NORMAL; + float clip : SV_ClipDistance0; +}; + + +//////////////////////////////////////////////////////////////////////////////// +// Pixel Shader +//////////////////////////////////////////////////////////////////////////////// +float4 RefractionPixelShader(PixelInputType input) : SV_TARGET +{ + float4 textureColor; + float3 lightDir; + float lightIntensity; + float4 color; + + + // Sample the texture pixel at this location. + textureColor = shaderTexture.Sample(SampleType, input.tex); + + // Set the default output color to the ambient light value for all pixels. + color = ambientColor; + + // 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 final light color. + color = saturate(color); + + // Multiply the texture pixel and the input color to get the final result. + color = color * textureColor; + + return color; +} \ No newline at end of file diff --git a/enginecustom/refraction.vs b/enginecustom/refraction.vs new file mode 100644 index 0000000..212b462 --- /dev/null +++ b/enginecustom/refraction.vs @@ -0,0 +1,65 @@ +///////////// +// GLOBALS // +///////////// +cbuffer MatrixBuffer +{ + matrix worldMatrix; + matrix viewMatrix; + matrix projectionMatrix; +}; + +cbuffer ClipPlaneBuffer +{ + float4 clipPlane; +}; + + +////////////// +// TYPEDEFS // +////////////// +struct VertexInputType +{ + float4 position : POSITION; + float2 tex : TEXCOORD0; + float3 normal : NORMAL; +}; + +struct PixelInputType +{ + float4 position : SV_POSITION; + float2 tex : TEXCOORD0; + float3 normal : NORMAL; + float clip : SV_ClipDistance0; +}; + + +//////////////////////////////////////////////////////////////////////////////// +// Vertex Shader +//////////////////////////////////////////////////////////////////////////////// +PixelInputType RefractionVertexShader(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; + + // 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); + + // Set the clipping plane. + output.clip = dot(mul(input.position, worldMatrix), clipPlane); + + return output; +} \ No newline at end of file diff --git a/enginecustom/refractionshaderclass.cpp b/enginecustom/refractionshaderclass.cpp new file mode 100644 index 0000000..feeef3a --- /dev/null +++ b/enginecustom/refractionshaderclass.cpp @@ -0,0 +1,473 @@ +#include "refractionshaderclass.h" + + +RefractionShaderClass::RefractionShaderClass() +{ + m_vertexShader = 0; + m_pixelShader = 0; + m_layout = 0; + m_matrixBuffer = 0; + m_sampleState = 0; + m_lightBuffer = 0; + m_clipPlaneBuffer = 0; +} + + +RefractionShaderClass::RefractionShaderClass(const RefractionShaderClass& other) +{ +} + + +RefractionShaderClass::~RefractionShaderClass() +{ +} + + +bool RefractionShaderClass::Initialize(ID3D11Device* device, HWND hwnd) +{ + 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"refraction.vs"); + if (error != 0) + { + return false; + } + + // Set the filename of the pixel shader. + error = wcscpy_s(psFilename, 128, L"refraction.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 RefractionShaderClass::Shutdown() +{ + // Shutdown the vertex and pixel shaders as well as the related objects. + ShutdownShader(); + + return; +} + +bool RefractionShaderClass::Render(ID3D11DeviceContext* deviceContext, int indexCount, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix, + ID3D11ShaderResourceView* texture, XMFLOAT3 lightDirection, XMFLOAT4 ambientColor[], XMFLOAT4 diffuseColor[], XMFLOAT4 lightPosition[], XMFLOAT4 clipPlane) +{ + bool result; + + + // Set the shader parameters that it will use for rendering. + result = SetShaderParameters(deviceContext, worldMatrix, viewMatrix, projectionMatrix, texture, lightDirection, ambientColor, diffuseColor, lightPosition, clipPlane); + if (!result) + { + return false; + } + + // Now render the prepared buffers with the shader. + RenderShader(deviceContext, indexCount); + + return true; +} + + +bool RefractionShaderClass::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_BUFFER_DESC matrixBufferDesc; + D3D11_SAMPLER_DESC samplerDesc; + D3D11_BUFFER_DESC lightBufferDesc; + D3D11_BUFFER_DESC clipPlaneBufferDesc; + + + // 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, "RefractionVertexShader", "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, "RefractionPixelShader", "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. + 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; + + // 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; + } + + // Create a texture sampler state description. + samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; + samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; + samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + 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. + // 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; + } + + // Setup the description of the clip plane dynamic constant buffer that is in the vertex shader. + clipPlaneBufferDesc.Usage = D3D11_USAGE_DYNAMIC; + clipPlaneBufferDesc.ByteWidth = sizeof(ClipPlaneBufferType); + clipPlaneBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + clipPlaneBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + clipPlaneBufferDesc.MiscFlags = 0; + clipPlaneBufferDesc.StructureByteStride = 0; + + // Create the constant buffer pointer so we can access the vertex shader constant buffer from within this class. + result = device->CreateBuffer(&clipPlaneBufferDesc, NULL, &m_clipPlaneBuffer); + if (FAILED(result)) + { + return false; + } + + return true; +} + + +void RefractionShaderClass::ShutdownShader() +{ + // Release the clip plane constant buffer. + if (m_clipPlaneBuffer) + { + m_clipPlaneBuffer->Release(); + m_clipPlaneBuffer = 0; + } + + // Release the light constant buffer. + if (m_lightBuffer) + { + m_lightBuffer->Release(); + m_lightBuffer = 0; + } + + // Release the sampler state. + if (m_sampleState) + { + m_sampleState->Release(); + m_sampleState = 0; + } + + // Release the matrix constant buffer. + if (m_matrixBuffer) + { + m_matrixBuffer->Release(); + m_matrixBuffer = 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 RefractionShaderClass::OutputShaderErrorMessage(ID3D10Blob* errorMessage, HWND hwnd, WCHAR* shaderFilename) +{ + char* compileErrors; + unsigned long long 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 RefractionShaderClass::SetShaderParameters(ID3D11DeviceContext* deviceContext, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix, + ID3D11ShaderResourceView* texture, XMFLOAT3 lightDirection, XMFLOAT4 ambientColor[], XMFLOAT4 diffuseColor[], XMFLOAT4 lightPosition[], XMFLOAT4 clipPlane) +{ + HRESULT result; + D3D11_MAPPED_SUBRESOURCE mappedResource; + MatrixBufferType* dataPtr; + unsigned int bufferNumber; + ClipPlaneBufferType* dataPtr2; + LightBufferType* dataPtr3; + + + // Transpose the matrices to prepare them for the shader. + worldMatrix = XMMatrixTranspose(worldMatrix); + viewMatrix = XMMatrixTranspose(viewMatrix); + projectionMatrix = XMMatrixTranspose(projectionMatrix); + + // Lock the constant buffer so it can be written to. + result = deviceContext->Map(m_matrixBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + 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); + + // Lock the clip plane constant buffer so it can be written to. + result = deviceContext->Map(m_clipPlaneBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if(FAILED(result)) + { + return false; + } + + // Get a pointer to the data in the clip plane constant buffer. + dataPtr2 = (ClipPlaneBufferType*)mappedResource.pData; + + // Copy the clip plane into the clip plane constant buffer. + dataPtr2->clipPlane = clipPlane; + + // Unlock the buffer. + deviceContext->Unmap(m_clipPlaneBuffer, 0); + + // Set the position of the clip plane constant buffer in the vertex shader. + bufferNumber = 1; + + // Now set the clip plane constant buffer in the vertex shader with the updated values. + deviceContext->VSSetConstantBuffers(bufferNumber, 1, &m_clipPlaneBuffer); + + // 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. + dataPtr3 = (LightBufferType*)mappedResource.pData; + + // Copy the lighting variables into the constant buffer. + dataPtr3->ambientColor = ambientColor[0]; + dataPtr3->diffuseColor = diffuseColor[0]; + dataPtr3->lightPosition = lightPosition[0]; + dataPtr3->lightDirection = lightDirection; + + // 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 RefractionShaderClass::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 the geometry. + 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 geometry. + deviceContext->DrawIndexed(indexCount, 0, 0); + + return; +} \ No newline at end of file diff --git a/enginecustom/refractionshaderclass.h b/enginecustom/refractionshaderclass.h new file mode 100644 index 0000000..19e1ded --- /dev/null +++ b/enginecustom/refractionshaderclass.h @@ -0,0 +1,72 @@ +#ifndef _REFRACTIONSHADERCLASS_H_ +#define _REFRACTIONSHADERCLASS_H_ + + +////////////// +// INCLUDES // +////////////// +#include +#include +#include +#include +using namespace DirectX; +using namespace std; + + +//////////////////////////////////////////////////////////////////////////////// +// Class name: RefractionShaderClass +//////////////////////////////////////////////////////////////////////////////// +class RefractionShaderClass +{ +private: + struct MatrixBufferType + { + XMMATRIX world; + XMMATRIX view; + XMMATRIX projection; + }; + + struct LightBufferType + { + XMFLOAT4 ambientColor; + XMFLOAT4 diffuseColor; + XMFLOAT4 lightPosition; + XMFLOAT3 lightDirection; + float padding; + }; + + struct ClipPlaneBufferType + { + XMFLOAT4 clipPlane; + }; + +public: + RefractionShaderClass(); + RefractionShaderClass(const RefractionShaderClass&); + ~RefractionShaderClass(); + + bool Initialize(ID3D11Device*, HWND); + void Shutdown(); + bool Render(ID3D11DeviceContext*, int, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, + XMFLOAT3, XMFLOAT4[], XMFLOAT4[], XMFLOAT4[], XMFLOAT4); + +private: + bool InitializeShader(ID3D11Device*, HWND, WCHAR*, WCHAR*); + void ShutdownShader(); + void OutputShaderErrorMessage(ID3D10Blob*, HWND, WCHAR*); + + bool SetShaderParameters(ID3D11DeviceContext*, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, + XMFLOAT3, XMFLOAT4[], XMFLOAT4[], XMFLOAT4[], XMFLOAT4); + void RenderShader(ID3D11DeviceContext*, int); + +private: + ID3D11VertexShader* m_vertexShader; + ID3D11PixelShader* m_pixelShader; + ID3D11InputLayout* m_layout; + ID3D11SamplerState* m_sampleState; + ID3D11Buffer* m_matrixBuffer; + ID3D11Buffer* m_lightBuffer; + ID3D11Buffer* m_clipPlaneBuffer; +}; + +#endif \ No newline at end of file diff --git a/enginecustom/shadermanagerclass.cpp b/enginecustom/shadermanagerclass.cpp index 063333c..a6d5be3 100644 --- a/enginecustom/shadermanagerclass.cpp +++ b/enginecustom/shadermanagerclass.cpp @@ -11,6 +11,8 @@ ShaderManagerClass::ShaderManagerClass() m_TransparentShader = 0; m_LightShader = 0; m_LightMapShader = 0; + m_RefractionShader = 0; + m_WaterShader = 0; } @@ -120,6 +122,24 @@ bool ShaderManagerClass::Initialize(ID3D11Device* device, HWND hwnd) return false; } + // Create and initialize the refraction shader object. + m_RefractionShader = new RefractionShaderClass; + + result = m_RefractionShader->Initialize(device, hwnd); + if (!result) + { + return false; + } + + // Create and initialize the water shader object. + m_WaterShader = new WaterShaderClass; + + result = m_WaterShader->Initialize(device, hwnd); + if (!result) + { + return false; + } + Logger::Get().Log("ShaderManagerClass initialized", __FILE__, __LINE__, Logger::LogLevel::Initialize); return true; @@ -201,6 +221,22 @@ void ShaderManagerClass::Shutdown() m_LightMapShader = 0; } + // Release the refraction shader object. + if (m_RefractionShader) + { + m_RefractionShader->Shutdown(); + delete m_RefractionShader; + m_RefractionShader = 0; + } + + // Release the water shader object. + if (m_WaterShader) + { + m_WaterShader->Shutdown(); + delete m_WaterShader; + m_WaterShader = 0; + } + Logger::Get().Log("ShaderManagerClass shut down", __FILE__, __LINE__, Logger::LogLevel::Shutdown); return; @@ -322,12 +358,12 @@ bool ShaderManagerClass::RenderTransparentShader(ID3D11DeviceContext* deviceCont } bool ShaderManagerClass::RenderlightShader(ID3D11DeviceContext* deviceContext, int indexCount, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix, - ID3D11ShaderResourceView* texture, XMFLOAT4 diffuseColor[], XMFLOAT4 lightPosition[]) + ID3D11ShaderResourceView* texture, XMFLOAT4 diffuseColor[], XMFLOAT4 lightPosition[], XMFLOAT4 ambientColor[]) { bool result; - result = m_LightShader->Render(deviceContext, indexCount, worldMatrix, viewMatrix, projectionMatrix, texture, diffuseColor, lightPosition); + result = m_LightShader->Render(deviceContext, indexCount, worldMatrix, viewMatrix, projectionMatrix, texture, diffuseColor, lightPosition, ambientColor); if (!result) { return false; @@ -348,5 +384,37 @@ bool ShaderManagerClass::RenderlightMapShader(ID3D11DeviceContext* deviceContext return false; } + return true; +} + +bool ShaderManagerClass::RenderRefractionShader(ID3D11DeviceContext* deviceContext, int indexCount, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix, + ID3D11ShaderResourceView* texture, XMFLOAT3 lightDirection, XMFLOAT4 ambientColor[], XMFLOAT4 diffuseColor[], XMFLOAT4 lightPosition[], XMFLOAT4 clipPlane) +{ + bool result; + + + result = m_RefractionShader->Render(deviceContext, indexCount, worldMatrix, viewMatrix, projectionMatrix, texture, lightDirection, ambientColor, diffuseColor, lightPosition, clipPlane); + if (!result) + { + return false; + } + + return true; +} + +bool ShaderManagerClass::RenderWaterShader(ID3D11DeviceContext* deviceContext, int indexCount, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix, + XMMATRIX reflectionMatrix, ID3D11ShaderResourceView* reflectionTexture, ID3D11ShaderResourceView* refractionTexture, + ID3D11ShaderResourceView* normalTexture, float waterTranslation, float reflectRefractScale) +{ + bool result; + + + result = m_WaterShader->Render(deviceContext, indexCount, worldMatrix, viewMatrix, projectionMatrix, reflectionMatrix, reflectionTexture, + refractionTexture, normalTexture, waterTranslation, reflectRefractScale); + if (!result) + { + return false; + } + return true; } \ No newline at end of file diff --git a/enginecustom/shadermanagerclass.h b/enginecustom/shadermanagerclass.h index 7910b2d..20de267 100644 --- a/enginecustom/shadermanagerclass.h +++ b/enginecustom/shadermanagerclass.h @@ -13,6 +13,10 @@ #include "transparentshaderclass.h" #include "lightshaderclass.h" #include "lightmapshaderclass.h" +#include "refractionshaderclass.h" +#include "watershaderclass.h" + + //////////////////////////////////////////////////////////////////////////////// // Class name: ShaderManagerClass //////////////////////////////////////////////////////////////////////////////// @@ -33,9 +37,12 @@ public: bool RenderSpecMapShader(ID3D11DeviceContext*, int, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, ID3D11ShaderResourceView*, ID3D11ShaderResourceView*, XMFLOAT3, XMFLOAT4, XMFLOAT3, XMFLOAT4, float); bool RenderTransparentShader(ID3D11DeviceContext*, int, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, float); - bool RenderlightShader(ID3D11DeviceContext*, int, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, XMFLOAT4[], XMFLOAT4[]); + bool RenderlightShader(ID3D11DeviceContext*, int, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, XMFLOAT4[], XMFLOAT4[], XMFLOAT4[]); bool RenderlightMapShader(ID3D11DeviceContext*, int, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, ID3D11ShaderResourceView*); - + bool RenderRefractionShader(ID3D11DeviceContext*, int, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, + XMFLOAT3, XMFLOAT4[], XMFLOAT4[], XMFLOAT4[], XMFLOAT4); + bool RenderWaterShader(ID3D11DeviceContext*, int, XMMATRIX, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, + ID3D11ShaderResourceView*, ID3D11ShaderResourceView*, float, float); private: TextureShaderClass* m_TextureShader; NormalMapShaderClass* m_NormalMapShader; @@ -47,6 +54,8 @@ private: LightShaderClass* m_LightShader; LightMapShaderClass* m_LightMapShader; + RefractionShaderClass* m_RefractionShader; + WaterShaderClass* m_WaterShader; }; #endif \ No newline at end of file diff --git a/enginecustom/wall.txt b/enginecustom/wall.txt new file mode 100644 index 0000000..43a9198 --- /dev/null +++ b/enginecustom/wall.txt @@ -0,0 +1,40 @@ +Vertex Count: 36 + +Data: + +-5 5 -0.5 0.001992 0.00199199 0 0 -1 +5 -5 -0.5 0.998008 0.998008 0 0 -1 +-5 -5 -0.5 0.001992 0.998008 0 0 -1 +5 5 -0.5 0.998008 0.00199199 0 0 -1 +5 -5 -0.5 0.998008 0.998008 0 0 -1 +-5 5 -0.5 0.001992 0.00199199 0 0 -1 +-5 5 0.5 0.099801 0.00199199 0 1 -0 +5 5 -0.5 0.000199 0.998008 0 1 -0 +-5 5 -0.5 0.000199 0.00199199 0 1 -0 +5 5 0.5 0.099801 0.998008 0 1 -0 +5 5 -0.5 0.000199 0.998008 0 1 -0 +-5 5 0.5 0.099801 0.00199199 0 1 -0 +-5 -5 0.5 0.001992 0.00199199 0 0 1 +5 5 0.5 0.998008 0.998008 0 0 1 +-5 5 0.5 0.001992 0.998008 0 0 1 +5 -5 0.5 0.998008 0.00199199 0 0 1 +5 5 0.5 0.998008 0.998008 0 0 1 +-5 -5 0.5 0.001992 0.00199199 0 0 1 +-5 -5 -0.5 0.099801 0.00199199 0 -1 -0 +5 -5 0.5 0.000199 0.998008 0 -1 -0 +-5 -5 0.5 0.000199 0.00199199 0 -1 -0 +5 -5 -0.5 0.099801 0.998008 0 -1 -0 +5 -5 0.5 0.000199 0.998008 0 -1 -0 +-5 -5 -0.5 0.099801 0.00199199 0 -1 -0 +5 5 -0.5 0.000199 0.00199199 1 0 -0 +5 -5 0.5 0.099801 0.998008 1 0 -0 +5 -5 -0.5 0.000199 0.998008 1 0 -0 +5 5 0.5 0.099801 0.00199199 1 0 -0 +5 -5 0.5 0.099801 0.998008 1 0 -0 +5 5 -0.5 0.000199 0.00199199 1 0 -0 +-5 5 0.5 0.000199 0.00199199 -1 0 -0 +-5 -5 -0.5 0.099801 0.998008 -1 0 -0 +-5 -5 0.5 0.000199 0.998008 -1 0 -0 +-5 5 -0.5 0.099801 0.00199199 -1 0 -0 +-5 -5 -0.5 0.099801 0.998008 -1 0 -0 +-5 5 0.5 0.000199 0.00199199 -1 0 -0 diff --git a/enginecustom/wall01.tga b/enginecustom/wall01.tga new file mode 100644 index 0000000..b75e7ed Binary files /dev/null and b/enginecustom/wall01.tga differ diff --git a/enginecustom/water.ps b/enginecustom/water.ps new file mode 100644 index 0000000..4dc414e --- /dev/null +++ b/enginecustom/water.ps @@ -0,0 +1,72 @@ +///////////// +// GLOBALS // +///////////// +SamplerState SampleType : register(s0); + +Texture2D reflectionTexture : register(t0); +Texture2D refractionTexture : register(t1); +Texture2D normalTexture : register(t2); + +cbuffer WaterBuffer +{ + float waterTranslation; + float reflectRefractScale; + float2 padding; +}; + + +////////////// +// TYPEDEFS // +////////////// +struct PixelInputType +{ + float4 position : SV_POSITION; + float2 tex : TEXCOORD0; + float4 reflectionPosition : TEXCOORD1; + float4 refractionPosition : TEXCOORD2; +}; + + +//////////////////////////////////////////////////////////////////////////////// +// Pixel Shader +//////////////////////////////////////////////////////////////////////////////// +float4 WaterPixelShader(PixelInputType input) : SV_TARGET +{ + float2 reflectTexCoord; + float2 refractTexCoord; + float4 normalMap; + float3 normal; + float4 reflectionColor; + float4 refractionColor; + float4 color; + + // Move the position the water normal is sampled from to simulate moving water. + input.tex.y += waterTranslation; + + // Calculate the projected reflection texture coordinates. + reflectTexCoord.x = input.reflectionPosition.x / input.reflectionPosition.w / 2.0f + 0.5f; + reflectTexCoord.y = -input.reflectionPosition.y / input.reflectionPosition.w / 2.0f + 0.5f; + + // Calculate the projected refraction texture coordinates. + refractTexCoord.x = input.refractionPosition.x / input.refractionPosition.w / 2.0f + 0.5f; + refractTexCoord.y = -input.refractionPosition.y / input.refractionPosition.w / 2.0f + 0.5f; + + // Sample the normal from the normal map texture. + normalMap = normalTexture.Sample(SampleType, input.tex); + + // Expand the range of the normal from (0,1) to (-1,+1). + normal = (normalMap.xyz * 2.0f) - 1.0f; + + // Re-position the texture coordinate sampling position by the normal map value to simulate the rippling wave effect. + reflectTexCoord = reflectTexCoord + (normal.xy * reflectRefractScale); + refractTexCoord = refractTexCoord + (normal.xy * reflectRefractScale); + + // Sample the texture pixels from the textures using the updated texture coordinates. + reflectionColor = reflectionTexture.Sample(SampleType, reflectTexCoord); + refractionColor = refractionTexture.Sample(SampleType, refractTexCoord); + + // Combine the reflection and refraction results for the final color. + color = lerp(reflectionColor, refractionColor, 0.6f); + + return color; +} \ No newline at end of file diff --git a/enginecustom/water.txt b/enginecustom/water.txt new file mode 100644 index 0000000..1bcedf5 --- /dev/null +++ b/enginecustom/water.txt @@ -0,0 +1,10 @@ +Vertex Count: 6 + +Data: + +-4 0 4 0.0 0.0 0 1 0 + 4 0 -4 1.0 1.0 0 1 0 +-4 0 -4 0.0 1.0 0 1 0 + 4 0 4 1.0 0.0 0 1 0 + 4 0 -4 1.0 1.0 0 1 0 +-4 0 4 0.0 0.0 0 1 0 diff --git a/enginecustom/water.vs b/enginecustom/water.vs new file mode 100644 index 0000000..23e7f60 --- /dev/null +++ b/enginecustom/water.vs @@ -0,0 +1,71 @@ +///////////// +// GLOBALS // +///////////// +cbuffer MatrixBuffer +{ + matrix worldMatrix; + matrix viewMatrix; + matrix projectionMatrix; +}; + +cbuffer ReflectionBuffer +{ + matrix reflectionMatrix; +}; + + +////////////// +// TYPEDEFS // +////////////// +struct VertexInputType +{ + float4 position : POSITION; + float2 tex : TEXCOORD0; +}; + +struct PixelInputType +{ + float4 position : SV_POSITION; + float2 tex : TEXCOORD0; + float4 reflectionPosition : TEXCOORD1; + float4 refractionPosition : TEXCOORD2; +}; + + +//////////////////////////////////////////////////////////////////////////////// +// Vertex Shader +//////////////////////////////////////////////////////////////////////////////// +PixelInputType WaterVertexShader(VertexInputType input) +{ + PixelInputType output; + matrix reflectProjectWorld; + matrix viewProjectWorld; + + + // 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; + + // Create the reflection projection world matrix. + reflectProjectWorld = mul(reflectionMatrix, projectionMatrix); + reflectProjectWorld = mul(worldMatrix, reflectProjectWorld); + + // Calculate the input position against the reflectProjectWorld matrix. + output.reflectionPosition = mul(input.position, reflectProjectWorld); + + // Create the view projection world matrix for refraction. + viewProjectWorld = mul(viewMatrix, projectionMatrix); + viewProjectWorld = mul(worldMatrix, viewProjectWorld); + + // Calculate the input position against the viewProjectWorld matrix. + output.refractionPosition = mul(input.position, viewProjectWorld); + + return output; +} \ No newline at end of file diff --git a/enginecustom/water01.tga b/enginecustom/water01.tga new file mode 100644 index 0000000..b770c8e Binary files /dev/null and b/enginecustom/water01.tga differ diff --git a/enginecustom/watershaderclass.cpp b/enginecustom/watershaderclass.cpp new file mode 100644 index 0000000..32b2a1d --- /dev/null +++ b/enginecustom/watershaderclass.cpp @@ -0,0 +1,470 @@ +#include "watershaderclass.h" + + +WaterShaderClass::WaterShaderClass() +{ + m_vertexShader = 0; + m_pixelShader = 0; + m_layout = 0; + m_sampleState = 0; + m_matrixBuffer = 0; + m_reflectionBuffer = 0; + m_waterBuffer = 0; +} + + +WaterShaderClass::WaterShaderClass(const WaterShaderClass& other) +{ +} + + +WaterShaderClass::~WaterShaderClass() +{ +} + + +bool WaterShaderClass::Initialize(ID3D11Device* device, HWND hwnd) +{ + 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"water.vs"); + if (error != 0) + { + return false; + } + + // Set the filename of the pixel shader. + error = wcscpy_s(psFilename, 128, L"water.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 WaterShaderClass::Shutdown() +{ + // Shutdown the vertex and pixel shaders as well as the related objects. + ShutdownShader(); + + return; +} + +bool WaterShaderClass::Render(ID3D11DeviceContext* deviceContext, int indexCount, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix, + XMMATRIX reflectionMatrix, ID3D11ShaderResourceView* reflectionTexture, ID3D11ShaderResourceView* refractionTexture, + ID3D11ShaderResourceView* normalTexture, float waterTranslation, float reflectRefractScale) +{ + bool result; + + + // Set the shader parameters that it will use for rendering. + result = SetShaderParameters(deviceContext, worldMatrix, viewMatrix, projectionMatrix, reflectionMatrix, reflectionTexture, + refractionTexture, normalTexture, waterTranslation, reflectRefractScale); + if (!result) + { + return false; + } + + // Now render the prepared buffers with the shader. + RenderShader(deviceContext, indexCount); + + return true; +} + + +bool WaterShaderClass::InitializeShader(ID3D11Device* device, HWND hwnd, WCHAR* vsFilename, WCHAR* psFilename) +{ + HRESULT result; + ID3D10Blob* errorMessage; + ID3D10Blob* vertexShaderBuffer; + ID3D10Blob* pixelShaderBuffer; + D3D11_INPUT_ELEMENT_DESC polygonLayout[2]; + unsigned int numElements; + D3D11_BUFFER_DESC matrixBufferDesc; + D3D11_SAMPLER_DESC samplerDesc; + D3D11_BUFFER_DESC reflectionBufferDesc; + D3D11_BUFFER_DESC waterBufferDesc; + + + // 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, "WaterVertexShader", "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, "WaterPixelShader", "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. + 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 = 0; + + pixelShaderBuffer->Release(); + pixelShaderBuffer = 0; + + // 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; + } + + // 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 reflection dynamic constant buffer that is in the vertex shader. + reflectionBufferDesc.Usage = D3D11_USAGE_DYNAMIC; + reflectionBufferDesc.ByteWidth = sizeof(ReflectionBufferType); + reflectionBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + reflectionBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + reflectionBufferDesc.MiscFlags = 0; + reflectionBufferDesc.StructureByteStride = 0; + + // Create the constant buffer pointer so we can access the vertex shader constant buffer from within this class. + result = device->CreateBuffer(&reflectionBufferDesc, NULL, &m_reflectionBuffer); + if (FAILED(result)) + { + return false; + } + + // Setup the description of the water dynamic constant buffer that is in the pixel shader. + waterBufferDesc.Usage = D3D11_USAGE_DYNAMIC; + waterBufferDesc.ByteWidth = sizeof(WaterBufferType); + waterBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + waterBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + waterBufferDesc.MiscFlags = 0; + waterBufferDesc.StructureByteStride = 0; + + // Create the constant buffer pointer so we can access the pixel shader constant buffer from within this class. + result = device->CreateBuffer(&waterBufferDesc, NULL, &m_waterBuffer); + if (FAILED(result)) + { + return false; + } + + return true; +} + + +void WaterShaderClass::ShutdownShader() +{ + // Release the water constant buffer. + if (m_waterBuffer) + { + m_waterBuffer->Release(); + m_waterBuffer = 0; + } + + // Release the reflection constant buffer. + if (m_reflectionBuffer) + { + m_reflectionBuffer->Release(); + m_reflectionBuffer = 0; + } + + // Release the sampler state. + if (m_sampleState) + { + m_sampleState->Release(); + m_sampleState = 0; + } + + // Release the matrix constant buffer. + if (m_matrixBuffer) + { + m_matrixBuffer->Release(); + m_matrixBuffer = 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 WaterShaderClass::OutputShaderErrorMessage(ID3D10Blob* errorMessage, HWND hwnd, WCHAR* shaderFilename) +{ + char* compileErrors; + unsigned long long 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 WaterShaderClass::SetShaderParameters(ID3D11DeviceContext* deviceContext, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix, XMMATRIX reflectionMatrix, + ID3D11ShaderResourceView* reflectionTexture, ID3D11ShaderResourceView* refractionTexture, ID3D11ShaderResourceView* normalTexture, + float waterTranslation, float reflectRefractScale) +{ + HRESULT result; + D3D11_MAPPED_SUBRESOURCE mappedResource; + MatrixBufferType* dataPtr; + unsigned int bufferNumber; + ReflectionBufferType* dataPtr2; + WaterBufferType* dataPtr3; + + // Transpose the matrices to prepare them for the shader. + worldMatrix = XMMatrixTranspose(worldMatrix); + viewMatrix = XMMatrixTranspose(viewMatrix); + projectionMatrix = XMMatrixTranspose(projectionMatrix); + reflectionMatrix = XMMatrixTranspose(reflectionMatrix); + + // 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; + + // Finanly set the constant buffer in the vertex shader with the updated values. + deviceContext->VSSetConstantBuffers(bufferNumber, 1, &m_matrixBuffer); + + // Lock the reflection constant buffer so it can be written to. + result = deviceContext->Map(m_reflectionBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + return false; + } + + // Get a pointer to the data in the constant buffer. + dataPtr2 = (ReflectionBufferType*)mappedResource.pData; + + // Copy the reflection matrix into the constant buffer. + dataPtr2->reflection = reflectionMatrix; + + // Unlock the constant buffer. + deviceContext->Unmap(m_reflectionBuffer, 0); + + // Set the position of the reflection constant buffer in the vertex shader. + bufferNumber = 1; + + // Finally set the reflection constant buffer in the vertex shader with the updated values. + deviceContext->VSSetConstantBuffers(bufferNumber, 1, &m_reflectionBuffer); + + // Set the reflection texture resource in the pixel shader. + deviceContext->PSSetShaderResources(0, 1, &reflectionTexture); + + // Set the refraction texture resource in the pixel shader. + deviceContext->PSSetShaderResources(1, 1, &refractionTexture); + + // Set the normal map texture resource in the pixel shader. + deviceContext->PSSetShaderResources(2, 1, &normalTexture); + + // Lock the water constant buffer so it can be written to. + result = deviceContext->Map(m_waterBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + return false; + } + + // Get a pointer to the data in the constant buffer. + dataPtr3 = (WaterBufferType*)mappedResource.pData; + + // Copy the water data into the constant buffer. + dataPtr3->waterTranslation = waterTranslation; + dataPtr3->reflectRefractScale = reflectRefractScale; + dataPtr3->padding = XMFLOAT2(0.0f, 0.0f); + + // Unlock the constant buffer. + deviceContext->Unmap(m_waterBuffer, 0); + + // Set the position of the water constant buffer in the pixel shader. + bufferNumber = 0; + + // Finally set the water constant buffer in the pixel shader with the updated values. + deviceContext->PSSetConstantBuffers(bufferNumber, 1, &m_waterBuffer); + + return true; +} + +void WaterShaderClass::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 geometry. + deviceContext->DrawIndexed(indexCount, 0, 0); + + return; +} \ No newline at end of file diff --git a/enginecustom/watershaderclass.h b/enginecustom/watershaderclass.h new file mode 100644 index 0000000..78173dd --- /dev/null +++ b/enginecustom/watershaderclass.h @@ -0,0 +1,70 @@ +#ifndef _WATERSHADERCLASS_H_ +#define _WATERSHADERCLASS_H_ + + +////////////// +// INCLUDES // +////////////// +#include +#include +#include +#include +using namespace DirectX; +using namespace std; + + +//////////////////////////////////////////////////////////////////////////////// +// Class name: WaterShaderClass +//////////////////////////////////////////////////////////////////////////////// +class WaterShaderClass +{ +private: + struct MatrixBufferType + { + XMMATRIX world; + XMMATRIX view; + XMMATRIX projection; + }; + + struct ReflectionBufferType + { + XMMATRIX reflection; + }; + + struct WaterBufferType + { + float waterTranslation; + float reflectRefractScale; + XMFLOAT2 padding; + }; + +public: + WaterShaderClass(); + WaterShaderClass(const WaterShaderClass&); + ~WaterShaderClass(); + + bool Initialize(ID3D11Device*, HWND); + void Shutdown(); + bool Render(ID3D11DeviceContext*, int, XMMATRIX, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, + ID3D11ShaderResourceView*, ID3D11ShaderResourceView*, float, float); + +private: + bool InitializeShader(ID3D11Device*, HWND, WCHAR*, WCHAR*); + void ShutdownShader(); + void OutputShaderErrorMessage(ID3D10Blob*, HWND, WCHAR*); + + bool SetShaderParameters(ID3D11DeviceContext*, XMMATRIX, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*, + ID3D11ShaderResourceView*, ID3D11ShaderResourceView*, float, float); + void RenderShader(ID3D11DeviceContext*, int); + +private: + ID3D11VertexShader* m_vertexShader; + ID3D11PixelShader* m_pixelShader; + ID3D11InputLayout* m_layout; + ID3D11Buffer* m_matrixBuffer; + ID3D11SamplerState* m_sampleState; + ID3D11Buffer* m_reflectionBuffer; + ID3D11Buffer* m_waterBuffer; +}; + +#endif \ No newline at end of file