Compare commits

4 Commits

Author SHA1 Message Date
1457450fef Small cleanup 2025-01-16 17:07:59 +01:00
071caf51b6 Shadows go brrr 2025-01-16 14:03:28 +01:00
8a3bf57d7e Well it's something ig 2025-01-15 03:40:39 +01:00
9805c7a2c1 Temp 2025-01-14 02:26:26 +01:00
35 changed files with 6060 additions and 27 deletions

View File

@@ -5,6 +5,7 @@ set(SOURCES
"src/Renderer.cpp"
"src/Timer.cpp"
"src/Mesh.cpp"
"src/ShadowMesh.cpp"
"src/InstancedMesh.cpp"
"src/Camera.cpp"
"src/Texture.cpp"
@@ -12,21 +13,30 @@ set(SOURCES
"src/Utils.cpp"
"src/HitTest.cpp"
"src/Material.cpp"
"src/Light.cpp"
"src/Math/Vector2.cpp"
"src/Math/Vector3.cpp"
"src/Math/Vector4.cpp"
"src/Math/Matrix.cpp"
"src/Effects/Effect.cpp"
"src/Effects/BaseEffect.cpp"
"src/Effects/FireEffect.cpp"
"src/Effects/ShadowEffect.cpp"
"src/PerlinNoise.hpp"
"src/Buffers/DepthBuffer.cpp"
"src/Buffers/SamplerState.cpp"
"src/Buffers/ShadowMapBuffer.cpp"
"src/Scenes/BaseScene.cpp"
"src/Scenes/MainScene.cpp"
"src/Scenes/DioramaScene.cpp"
"src/Scenes/InstancedScene.cpp"
"src/Scenes/PlanetScene.cpp"
"src/Scenes/ShadowTestScene.cpp"
)
SET(INCLUDE_DIRS
@@ -34,6 +44,7 @@ SET(INCLUDE_DIRS
"src/Math"
"src/Effects"
"src/Scenes"
"src/Buffers"
)
# Create the executable

View File

@@ -0,0 +1,2 @@
# Blender 4.3.2 MTL File: 'None'
# www.blender.org

File diff suppressed because it is too large Load Diff

View File

@@ -116,6 +116,10 @@ float3 Shade(VS_OUTPUT input)
}
float4 PS(VS_OUTPUT input) : SV_TARGET{
//Check if gDiffuseMap sample has a valid value, otherwise render red
if (gDiffuseMap.Sample(gSampleState, input.TexCoord).a == 0.f)
return float4(1.f, 0.f, 0.f, 1.f);
return gDiffuseMap.Sample(gSampleState, input.TexCoord);
}

View File

@@ -0,0 +1,141 @@
// Global parameters
SamplerState gShadowSampler : ShadowSampler;
SamplerState gShadowSampler2 : ShadowSampler {
Filter = MIN_MAG_MIP_POINT;
AddressU = CLAMP;
AddressV = CLAMP;
ComparisonFunc = LESS_EQUAL;
};
texture2D gShadowMap : ShadowMap;
float4x4 gLightViewProj : LightViewProjection;
DepthStencilState ShadowDepthStencilState
{
DepthEnable = true;
DepthWriteMask = ALL; // Write depth to the shadow map
DepthFunc = LESS_EQUAL; // Compare depth in the shadow map
StencilEnable = false; // We don't need stencil operations here
};
SamplerState gSampleState : SampleState;
RasterizerState gRasterizerState : RastState;
float4x4 gWorldViewProj : WorldViewProjection;
float4x4 gWorldMatrix : WorldMatrix;
texture2D gDiffuseMap : DiffuseMap;
texture2D gNormalMap : Normal;
texture2D gSpecularMap : Specular;
texture2D gGlossMap : Gloss;
float3 gLightDirection : LightDirection;
float3 gLightColor : LightColor;
float3 gCameraPosition : CameraPosition;
bool gUseNormal : UseNormal;
static const float3 gAmbient = float3(.03f, .03f, .03f);
// Input output structures
struct VS_INPUT {
float3 Position : POSITION;
float2 TexCoord : TEXCOORD;
float3 Normal : NORMAL;
float3 Tangent : TANGENT;
};
struct VS_OUTPUT {
float4 Position : SV_POSITION;
float4 WorldPosition : WORLDPOSITION;
float2 TexCoord : TEXCOORD;
float3 Normal : NORMAL;
float3 Tangent : TANGENT;
float4 ShadowCoord : SHADOWCOORD; // Add this to store shadow map coordinates
};
// Vertex shader
VS_OUTPUT VS(VS_INPUT input) {
VS_OUTPUT output = (VS_OUTPUT)0;
output.WorldPosition = mul(float4(input.Position, 1.f), gWorldMatrix);
output.Position = mul(float4(input.Position, 1.f), gWorldViewProj);
output.TexCoord = input.TexCoord;
output.Normal = mul(input.Normal, (float3x3) gWorldMatrix);
output.Tangent = mul(input.Tangent, (float3x3) gWorldMatrix);
// Calculate shadow map coordinates
// lightSpaceMatrix * vec4(vs_out.FragPos, 1.0);
output.ShadowCoord = mul(float4(input.Position, 1.f) , gLightViewProj);
return output;
}
// Shadow sampling function
float ShadowCalculation(float4 shadowCoord) {
// Normalize the depth by dividing by the w component
float3 projCoord = shadowCoord.xyz / shadowCoord.w;
// Convert from [-1, 1] to [0, 1]
float2 UVCoords;
UVCoords.x = 0.5f * projCoord.x + 0.5f;
UVCoords.y = -0.5f * projCoord.y + 0.5f;
// float z = 0.5 * projCoord.z + 0.5;
float z = projCoord.z;
// Sample the shadow map
float shadowDepth = gShadowMap.Sample(gShadowSampler2, UVCoords.xy).r;
float bias = 0.0025f;
// float bias = max(0.05 * (1.0 - dot(normal, lightDir)), 0.005);
// return gShadowMap.Sample(gShadowSampler2, UVCoords.xy).r;
// Check if the current fragment is in shadow
if (shadowDepth + bias < z)
return 0.5f;
else
return 1.0f;
}
// Pixel shader
float4 PS(VS_OUTPUT input) : SV_TARGET {
// Check if gDiffuseMap sample has a valid value, otherwise render red
// if (gDiffuseMap.Sample(gSampleState, input.TexCoord).a == 0.f)
// return float4(1.f, 0.f, 0.f, 1.f);
// return float4(Shade(input), 1.0f); // Use the shading function with shadow
// return gShadowMap.Sample(gShadowSampler, input.ShadowCoord.xy / input.ShadowCoord.w); // Sample shadow map
float shadowFactor = ShadowCalculation(input.ShadowCoord);
float3 diffuseColor = gDiffuseMap.Sample(gSampleState, input.TexCoord).rgb;
float3 finalColor = float3(1.f, 1.f, 1.f) * shadowFactor;
finalColor += gAmbient;
// return float4(shadowDepth,shadowDepth,shadowDepth, 1.0f);
return float4(finalColor, 1.0f);
// return gShadowMap.Sample(gShadowSampler, input.TexCoord); // Sample shadow map
}
// DepthStencilState
DepthStencilState gDepthStencilState
{
DepthEnable = true;
DepthWriteMask = ALL;
DepthFunc = LESS;
StencilEnable = true;
};
// Technique
technique11 DefaultTechnique {
pass P0 {
SetDepthStencilState(ShadowDepthStencilState, 0);
SetRasterizerState(gRasterizerState);
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(NULL);
SetPixelShader(CompileShader(ps_5_0, PS()));
}
}

View File

@@ -0,0 +1,47 @@
float4x4 gLightWorldViewProj : WorldViewProjection;
float4x4 gWorldViewProj: WorldViewProjection; //For compatibility sake
struct VS_Input {
float3 Position : POSITION;
float2 TexCoord : TEXCOORD;
float3 Normal : NORMAL;
float3 Tangent : TANGENT;
};
struct VS_Output
{
float4 Position : SV_POSITION;
};
VS_Output VS_Shadow(VS_Input input)
{
VS_Output output;
// Transform vertex position to light's clip space
output.Position = mul(float4(input.Position, 1.0f), gLightWorldViewProj);
return output;
}
float4 PS_Shadow(VS_Output input) : SV_TARGET
{
// Output depth information (Z/W in clip space)
// // gl_FragDepth = gl_FragCoord.z;
return float4(input.Position.z / input.Position.w, 0.0f, 0.0f, input.Position.z / input.Position.w);
}
// Rasterizer state for front face culling
RasterizerState FrontFaceCull
{
FrontCounterClockwise = FALSE;
CullMode = FRONT;
};
// Technique for rendering shadow map
technique11 DefaultTechnique
{
pass P0
{
//Set FrontFaceCulling
SetRasterizerState(FrontFaceCull);
SetVertexShader(CompileShader(vs_5_0, VS_Shadow()));
SetPixelShader(CompileShader(ps_5_0, PS_Shadow()));
}
}

View File

@@ -0,0 +1,5 @@
//
// Created by Bram on 16/01/2025.
//
#include "DX11Viewport.h"

View File

@@ -0,0 +1,51 @@
#ifndef GP1_DIRECTX_DX11VIEWPORT_H
#define GP1_DIRECTX_DX11VIEWPORT_H
#include <d3d11.h>
class DX11Viewport
{
public:
DX11Viewport(float width, float height, float topLeftX = 0.0f, float topLeftY = 0.0f, float minDepth = 0.0f, float maxDepth = 1.0f)
{
viewport.Width = width;
viewport.Height = height;
viewport.TopLeftX = topLeftX;
viewport.TopLeftY = topLeftY;
viewport.MinDepth = minDepth;
viewport.MaxDepth = maxDepth;
}
void Apply(ID3D11DeviceContext* context)
{
if (context)
{
context->RSSetViewports(1, &viewport);
}
}
void SetDimensions(float width, float height)
{
viewport.Width = width;
viewport.Height = height;
}
void SetPosition(float topLeftX, float topLeftY)
{
viewport.TopLeftX = topLeftX;
viewport.TopLeftY = topLeftY;
}
void SetDepthRange(float minDepth, float maxDepth)
{
viewport.MinDepth = minDepth;
viewport.MaxDepth = maxDepth;
}
const D3D11_VIEWPORT& GetViewport() const { return viewport; }
private:
D3D11_VIEWPORT viewport;
};
#endif //GP1_DIRECTX_DX11VIEWPORT_H

View File

@@ -0,0 +1,57 @@
#include "DepthBuffer.h"
DepthBuffer::DepthBuffer(ID3D11Device* device, UINT width, UINT height)
: m_device(device), m_width(width), m_height(height), m_depthBuffer(nullptr), m_depthStencilView(nullptr)
{
}
DepthBuffer::~DepthBuffer()
{
if (m_depthStencilView) m_depthStencilView->Release();
if (m_depthBuffer) m_depthBuffer->Release();
}
bool DepthBuffer::Initialize()
{
// Create a depth buffer with a typeless format
D3D11_TEXTURE2D_DESC desc = {};
desc.Width = m_width;
desc.Height = m_height;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R32_TYPELESS; // Typeless format
desc.SampleDesc.Count = 1;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE; // Add shader resource binding
desc.CPUAccessFlags = 0;
desc.MiscFlags = 0;
HRESULT hr = m_device->CreateTexture2D(&desc, nullptr, &m_depthBuffer);
if (FAILED(hr))
{
return false;
}
// Create DepthStencilView
D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
dsvDesc.Format = DXGI_FORMAT_D32_FLOAT; // Depth format
dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
dsvDesc.Texture2D.MipSlice = 0;
hr = m_device->CreateDepthStencilView(m_depthBuffer, &dsvDesc, &m_depthStencilView);
if (FAILED(hr))
{
return false;
}
return true;
}
ID3D11Texture2D* DepthBuffer::GetDepthBuffer()
{
return m_depthBuffer;
}
ID3D11DepthStencilView* DepthBuffer::GetDepthStencilView()
{
return m_depthStencilView;
}

View File

@@ -0,0 +1,31 @@
#ifndef GP1_DIRECTX_DEPTHBUFFER_H
#define GP1_DIRECTX_DEPTHBUFFER_H
#include <d3d11.h>
class DepthBuffer
{
public:
DepthBuffer(ID3D11Device* device, UINT width, UINT height);
~DepthBuffer();
bool Initialize();
ID3D11Texture2D* GetDepthBuffer() const { return m_depthBuffer; }
ID3D11DepthStencilView* GetDepthStencilView() const { return m_depthStencilView; }
ID3D11DepthStencilView *GetDepthStencilView();
ID3D11Texture2D *GetDepthBuffer();
private:
ID3D11Device* m_device;
UINT m_width;
UINT m_height;
ID3D11Texture2D* m_depthBuffer;
ID3D11DepthStencilView* m_depthStencilView;
};
#endif //GP1_DIRECTX_DEPTHBUFFER_H

View File

@@ -0,0 +1,29 @@
#include "SamplerState.h"
SamplerState::SamplerState(ID3D11Device *device)
: m_device(device), m_samplerState(nullptr) {
}
SamplerState::~SamplerState() {
if (m_samplerState) m_samplerState->Release();
}
bool SamplerState::Initialize() {
D3D11_SAMPLER_DESC samplerDesc = {};
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.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
samplerDesc.ComparisonFunc = D3D11_COMPARISON_LESS_EQUAL;
samplerDesc.MinLOD = 0;
samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
HRESULT hr = m_device->CreateSamplerState(&samplerDesc, &m_samplerState);
if (FAILED(hr)) {
return false;
}
return true;
}

View File

@@ -0,0 +1,19 @@
#ifndef GP1_DIRECTX_SAMPLERSTATE_H
#define GP1_DIRECTX_SAMPLERSTATE_H
#include <d3d11.h>
class SamplerState
{
public:
SamplerState(ID3D11Device* device);
~SamplerState();
bool Initialize();
ID3D11SamplerState* GetSamplerState() const { return m_samplerState; }
private:
ID3D11Device* m_device;
ID3D11SamplerState* m_samplerState;
};
#endif //GP1_DIRECTX_SAMPLERSTATE_H

View File

@@ -0,0 +1,51 @@
#include "ShadowMapBuffer.h"
ShadowMapBuffer::ShadowMapBuffer(ID3D11Device *device, UINT width, UINT height)
: m_device(device), m_width(width), m_height(height), m_shaderResourceView(nullptr),
m_depthBuffer(device, width, height), m_samplerState(device) {
}
ShadowMapBuffer::~ShadowMapBuffer() {
if (m_shaderResourceView) m_shaderResourceView->Release();
}
bool ShadowMapBuffer::Initialize() {
if (!m_depthBuffer.Initialize()) {
return false;
}
if (!m_samplerState.Initialize()) {
return false;
}
// Create ShaderResourceView for the depth buffer
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
srvDesc.Format = DXGI_FORMAT_R32_FLOAT; // Shader-readable format
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MipLevels = 1;
srvDesc.Texture2D.MostDetailedMip = 0;
HRESULT hr = m_device->CreateShaderResourceView(m_depthBuffer.GetDepthBuffer(), &srvDesc, &m_shaderResourceView);
if (FAILED(hr))
{
OutputDebugStringA("Failed to create ShaderResourceView for ShadowMapBuffer.\n");
return false;
}
return true;
}
void ShadowMapBuffer::SetRenderTarget(ID3D11DeviceContext *deviceContext) {
deviceContext->OMSetRenderTargets(0, nullptr, m_depthBuffer.GetDepthStencilView());
}
void ShadowMapBuffer::ResetRenderTarget(ID3D11DeviceContext *deviceContext) {
ID3D11RenderTargetView *nullRTV = nullptr;
deviceContext->OMSetRenderTargets(1, &nullRTV, nullptr);
}
ID3D11DepthStencilView *ShadowMapBuffer::GetDepthStencilView() {
return m_depthBuffer.GetDepthStencilView();
}

View File

@@ -0,0 +1,42 @@
//
// Created by Bram on 13/01/2025.
//
#ifndef GP1_DIRECTX_SHADOWMAPBUFFER_H
#define GP1_DIRECTX_SHADOWMAPBUFFER_H
#include <d3d11.h>
#include <DirectXMath.h>
#include "DepthBuffer.h"
#include "SamplerState.h"
class ShadowMapBuffer {
public:
ShadowMapBuffer(ID3D11Device *device, UINT width, UINT height);
~ShadowMapBuffer();
bool Initialize();
void SetRenderTarget(ID3D11DeviceContext *deviceContext);
void ResetRenderTarget(ID3D11DeviceContext *deviceContext);
// Get the depth stencil view and the sampler state
ID3D11ShaderResourceView *GetShaderResourceView() const { return m_shaderResourceView; }
ID3D11SamplerState *GetSamplerState() const { return m_samplerState.GetSamplerState(); }
ID3D11DepthStencilView *GetDepthStencilView();
private:
ID3D11Device *m_device;
UINT m_width;
UINT m_height;
DepthBuffer m_depthBuffer;
SamplerState m_samplerState;
ID3D11ShaderResourceView *m_shaderResourceView;
};
#endif //GP1_DIRECTX_SHADOWMAPBUFFER_H

View File

@@ -60,11 +60,9 @@ void dae::Camera::Update(const dae::Timer *pTimer) {
if (pKeyboardState[SDL_SCANCODE_LSHIFT]) {
MovementSpeed *= 2;
}
if (pKeyboardState[SDL_SCANCODE_W]) {
origin += forward * deltaTime * MovementSpeed;
}
if (pKeyboardState[SDL_SCANCODE_A]) {
origin -= right * deltaTime * MovementSpeed;
}

View File

@@ -9,13 +9,10 @@ BaseEffect::BaseEffect(ID3D11Device *devicePtr, const std::wstring &filePath) {
const std::ifstream file(filePath);
if (!file)
std::wcout << L"File doesn't exist" << std::endl;
m_EffectPtr = LoadEffect(devicePtr, filePath);
m_TechniquePtr = m_EffectPtr->GetTechniqueByName("DefaultTechnique");
if (!m_TechniquePtr->IsValid())
std::wcout << L"Technique is not valid" << std::endl;
m_MatWorldViewProjVariablePtr = m_EffectPtr->GetVariableByName("gWorldViewProj")->AsMatrix();
if (!m_MatWorldViewProjVariablePtr->IsValid())
std::wcout << L"gWorldViewProj Matrix is not valid" << std::endl;
@@ -54,11 +51,11 @@ ID3DX11Effect *BaseEffect::LoadEffect(ID3D11Device *devicePtr, const std::wstrin
ss << errorsPtr[i];
OutputDebugStringW(ss.str().c_str());
errorBlobPtr->Release();
errorBlobPtr = nullptr;
return nullptr;
} else {
std::wstringstream ss;
ss << "EffectLoader: Failed to CreateEffectFromFile!\nPath: " << filePath;
std::wcout << ss.str() << std::endl;
@@ -81,7 +78,6 @@ void BaseEffect::SetCameraPos(const dae::Vector3 &vector3) const {
}
void BaseEffect::SetMaterial(Material *material) {
}
void BaseEffect::SetWorldMatrix(const dae::Matrix& matrix) const {

View File

@@ -28,6 +28,8 @@ public:
ID3DX11EffectTechnique* GetTechniquePtr() const { return m_TechniquePtr; }
void SetWorldViewProjMatrix(const dae::Matrix& matrix);
virtual void NextSamplingState();

View File

@@ -40,6 +40,7 @@ Effect::Effect(ID3D11Device *devicePtr, const std::wstring &filePath)
if(!m_CameraPosVariablePtr->IsValid())
std::wcout << L"gCameraPos Vector is not valid" << std::endl;
m_LightColorVariablePtr = m_EffectPtr->GetVariableByName("gLightColor")->AsVector();
if(!m_LightColorVariablePtr->IsValid())
std::wcout << L"gLightColor Vector is not valid" << std::endl;
@@ -52,6 +53,18 @@ Effect::Effect(ID3D11Device *devicePtr, const std::wstring &filePath)
if(!m_RasterizerVariablePtr->IsValid())
std::wcout << L"gRasterizerState Rasterizer is not valid" << std::endl;
m_ShadowMapVariablePtr = m_EffectPtr->GetVariableByName("gShadowMap")->AsShaderResource();
if(!m_ShadowMapVariablePtr->IsValid())
std::wcout << L"gShadowMap ShaderResource is not valid" << std::endl;
m_ShadowMapSamplerVariablePtr = m_EffectPtr->GetVariableByName("gShadowSampler")->AsSampler();
if(!m_ShadowMapSamplerVariablePtr->IsValid())
std::wcout << L"gShadowSampler Sampler is not valid" << std::endl;
m_LightWorldViewProjVariablePtr = m_EffectPtr->GetVariableByName("gLightViewProj")->AsMatrix();
if(!m_LightWorldViewProjVariablePtr->IsValid())
std::wcout << L"gLightWorldViewProj Matrix is not valid" << std::endl;
m_UseNormalMapVariablePtr->SetBool(m_UseNormalMap);
@@ -65,6 +78,7 @@ Effect::Effect(ID3D11Device *devicePtr, const std::wstring &filePath)
this->InitSamplers(devicePtr);
this->InitRasterizer(devicePtr);
m_SamplerVariablePtr->SetSampler(0,m_SamplerStates[static_cast<int>(m_TechniqueType)]);
m_RasterizerVariablePtr->SetRasterizerState(0,m_RasterizerStates[static_cast<int>(m_CullMode)]);
}
@@ -202,3 +216,17 @@ void Effect::InitRasterizer(ID3D11Device *devicePtr) {
devicePtr->CreateRasterizerState(&rasterDesc, &m_RasterizerStates[static_cast<int>(CullMode::None)]);
}
void Effect::SetShadowMapSampler(ID3D11SamplerState *pState) {
m_ShadowMapSamplerVariablePtr->SetSampler(0,pState);
}
void Effect::SetShadowMap(ID3D11ShaderResourceView *pView) {
m_ShadowMapVariablePtr->SetResource(pView);
}
void Effect::SetLightViewProjMatrix(Matrix matrix) {
m_LightWorldViewProjVariablePtr->SetMatrix(reinterpret_cast<const float*>(&matrix));
}

View File

@@ -30,6 +30,12 @@ public:
void NextCullMode() override;
void SetShadowMap(ID3D11ShaderResourceView *pView);
void SetShadowMapSampler(ID3D11SamplerState *pState);
void SetLightViewProjMatrix(Matrix matrix);
private:
void InitSamplers(ID3D11Device* devicePtr);
@@ -52,6 +58,13 @@ private:
ID3DX11EffectRasterizerVariable* m_RasterizerVariablePtr{};
ID3DX11EffectShaderResourceVariable* m_ShadowMapVariablePtr{};
//m_LightWorldViewProjVariablePtr
ID3DX11EffectMatrixVariable* m_LightWorldViewProjVariablePtr{};
ID3DX11EffectSamplerVariable* m_ShadowMapSamplerVariablePtr{};
TechniqueType m_TechniqueType{TechniqueType::Linear};
std::array<ID3D11SamplerState*, 3> m_SamplerStates{};

View File

@@ -0,0 +1,44 @@
//
// Created by Bram on 13/01/2025.
//
#include "ShadowEffect.h"
ShadowEffect::ShadowEffect(ID3D11Device *devicePtr, const std::wstring &filePath)
: BaseEffect(devicePtr, filePath) {
// Retrieve shadow-specific variables
m_LightWorldViewProjVariable = m_EffectPtr->GetVariableByName("gLightWorldViewProj")->AsMatrix();
if (!m_LightWorldViewProjVariable->IsValid()) {
throw std::runtime_error("Failed to retrieve gLightWorldViewProj variable in ShadowEffect.");
}
// m_ShadowMapVariable = m_EffectPtr->GetVariableByName("gShadowMap")->AsShaderResource();
// if (!m_ShadowMapVariable->IsValid()) {
// throw std::runtime_error("Failed to retrieve gShadowMap variable in ShadowEffect.");
// }
//
// m_ShadowMapSamplerVariable = m_EffectPtr->GetVariableByName("gShadowMapSampler")->AsSampler();
// if (!m_ShadowMapSamplerVariable->IsValid()) {
// throw std::runtime_error("Failed to retrieve gShadowMapSampler variable in ShadowEffect.");
// }
}
void ShadowEffect::SetLightWorldViewProjMatrix(const Matrix &matrix) {
if (m_LightWorldViewProjVariable) {
m_LightWorldViewProjVariable->SetMatrix(reinterpret_cast<const float*>(&matrix));
}
}
void ShadowEffect::SetShadowMap(ID3D11ShaderResourceView *shadowMapSRV) {
if (m_ShadowMapVariable) {
m_ShadowMapVariable->SetResource(shadowMapSRV);
}
}
void ShadowEffect::SetShadowMapSampler(ID3D11SamplerState *samplerState) {
if (m_ShadowMapSamplerVariable) {
m_ShadowMapSamplerVariable->SetSampler(0, samplerState);
}
}

View File

@@ -0,0 +1,25 @@
#ifndef GP1_DIRECTX_SHADOWEFFECT_H
#define GP1_DIRECTX_SHADOWEFFECT_H
#include "BaseEffect.h"
class ShadowEffect : public BaseEffect {
public:
ShadowEffect(ID3D11Device* devicePtr, const std::wstring& filePath);
~ShadowEffect() override = default;
void SetLightWorldViewProjMatrix(const dae::Matrix& matrix);
void SetShadowMap(ID3D11ShaderResourceView* shadowMapSRV);
void SetShadowMapSampler(ID3D11SamplerState* samplerState);
private:
ID3DX11EffectMatrixVariable* m_LightWorldViewProjVariable{nullptr};
ID3DX11EffectShaderResourceVariable* m_ShadowMapVariable{nullptr};
ID3DX11EffectSamplerVariable* m_ShadowMapSamplerVariable{nullptr};
};
#endif //GP1_DIRECTX_SHADOWEFFECT_H

45
project/src/Light.cpp Normal file
View File

@@ -0,0 +1,45 @@
#include "Light.h"
#include <cmath>
Light::Light()
: m_Position(0.0f, 10.0f, 0.0f),
m_Target(0.0f, 0.0f, 0.0f),
m_Up(0.0f, 1.0f, 0.0f),
m_ViewMatrix(dae::Matrix()),
m_ProjectionMatrix(dae::Matrix()) {}
void Light::SetPosition(const dae::Vector3 &position) {
m_Position = position;
}
void Light::SetTarget(const dae::Vector3 &target) {
m_Target = target;
}
void Light::SetUp(const dae::Vector3 &up) {
m_Up = up;
}
dae::Matrix Light::GetViewMatrix() const {
return dae::Matrix::CreateLookAtLH(m_Position, m_Target, m_Up);
}
dae::Matrix Light::GetProjectionMatrix(float nearPlane, float farPlane, float size) const {
return dae::Matrix::CreateOrthographic(size, size, nearPlane, farPlane);
}
dae::Matrix Light::GetViewProjectionMatrix(float nearPlane, float farPlane, float size) const {
return GetViewMatrix() * GetProjectionMatrix(nearPlane, farPlane, size);
}
void Light::Update() {
// If the light position or target changes dynamically, this is where updates would be managed.
// m_ViewMatrix = dae::Matrix::CreateLookAtLH(m_Position, m_Target, m_Up);
// m_ProjectionMatrix = dae::Matrix::CreateOrthographic(size, size, nearPlane, farPlane);
}
dae::Vector3 Light::GetTarget() {
return m_Target;
}
dae::Vector3 Light::GetPosition() {
return m_Position;
}

34
project/src/Light.h Normal file
View File

@@ -0,0 +1,34 @@
#ifndef GP1_DIRECTX_LIGHT_H
#define GP1_DIRECTX_LIGHT_H
#include "Math/Vector3.h"
#include "Math/Matrix.h"
class Light {
public:
Light();
~Light() = default;
void SetPosition(const dae::Vector3 &position);
void SetTarget(const dae::Vector3 &target);
void SetUp(const dae::Vector3 &up);
dae::Matrix GetViewMatrix() const;
dae::Matrix GetProjectionMatrix(float nearPlane = 0.1f, float farPlane = 100.0f, float size = 50.0f) const;
dae::Matrix GetViewProjectionMatrix(float nearPlane = 0.1f, float farPlane = 100.0f, float size = 50.0f) const;
void Update();
dae::Vector3 GetTarget();
dae::Vector3 GetPosition();
private:
dae::Vector3 m_Position;
dae::Vector3 m_Target;
dae::Vector3 m_Up;
dae::Matrix m_ViewMatrix;
dae::Matrix m_ProjectionMatrix;
};
#endif //GP1_DIRECTX_LIGHT_H

View File

@@ -144,8 +144,8 @@ namespace dae {
return out;
}
Matrix Matrix::CreateLookAtLH(const Vector3& origin, const Vector3& forward, const Vector3& up)
{
Matrix Matrix::CreateLookAtLH(const Vector3& origin, const Vector3& forward, const Vector3& up)
{
Vector3 zAxis = (forward - origin).Normalized();
Vector3 xAxis = Vector3::Cross(up, zAxis).Normalized();
Vector3 yAxis = Vector3::Cross(zAxis, xAxis).Normalized();
@@ -161,9 +161,9 @@ namespace dae {
{xAxis.z, yAxis.z, zAxis.z},
{trans.x, trans.y, trans.z}
};
}
}
Matrix Matrix::CreatePerspectiveFovLH(float fovy, float aspect, float zn, float zf)
Matrix Matrix::CreatePerspectiveFovLH(float fovy, float aspect, float zn, float zf)
{
return Matrix(
{ 1.f / (aspect * fovy), 0, 0, 0 },
@@ -282,6 +282,7 @@ namespace dae {
return result;
}
const Matrix& Matrix::operator*=(const Matrix& m)
{
Matrix copy{ *this };
@@ -302,5 +303,14 @@ namespace dae {
data[3] = {vector3, 1};
}
Matrix Matrix::CreateOrthographic(float size, float size1, float nearPlane, float farPlane) {
return Matrix(
{2.f / size, 0, 0, 0},
{0, 2.f / size1, 0, 0},
{0, 0, 1.f / (farPlane - nearPlane), 0},
{0, 0, -nearPlane / (farPlane - nearPlane), 1}
);
}
#pragma endregion
}

View File

@@ -51,6 +51,8 @@ namespace dae {
static Matrix CreateLookAtLH(const Vector3& origin, const Vector3& forward, const Vector3& up);
static Matrix CreatePerspectiveFovLH(float fovy, float aspect, float zn, float zf);
Vector4& operator[](int index);
Vector4 operator[](int index) const;
Matrix operator*(const Matrix& m) const;
@@ -58,6 +60,8 @@ namespace dae {
void SetTranslation(Vector3 vector3);
static dae::Matrix CreateOrthographic(float size, float size1, float plane, float plane1);
private:
//Row-Major Matrix

View File

@@ -140,4 +140,8 @@ void Mesh::SetMaterial(Material *pMaterial) {
void Mesh::CycleCullMode() {
m_EffectPtr->NextCullMode();
}
}
BaseEffect *Mesh::GetEffect() {
return m_EffectPtr;
}

View File

@@ -21,7 +21,7 @@ enum class PrimitiveTopology {
class Mesh final {
class Mesh {
public:
Mesh(ID3D11Device *devicePtr, const std::vector<VertexIn> &verticesIn, const std::vector<Uint32> &indices,
std::shared_ptr<Material> material, BaseEffect* effectPtr);
@@ -53,6 +53,8 @@ public:
void SetShouldRender(bool shouldRender) { m_ShouldRender = shouldRender; }
bool GetShouldRender() const { return m_ShouldRender; }
BaseEffect *GetEffect();
private:
BaseEffect *m_EffectPtr;

View File

@@ -10,6 +10,7 @@
#include "Scenes/DioramaScene.h"
#include "Scenes/InstancedScene.h"
#include "Scenes/PlanetScene.h"
#include "Scenes/ShadowTestScene.h"
namespace dae {
@@ -36,7 +37,7 @@ namespace dae {
InitializeSDLRasterizer();
m_pScene = new MainScene();
m_pScene = new ShadowTestScene();
m_pScene->Initialize(m_DevicePtr, m_DeviceContextPtr, nullptr);
if (!m_pScene->GetMeshes().empty()) {
@@ -112,30 +113,52 @@ namespace dae {
}
void Renderer::RenderDirectX() const {
//Clear back buffer
ColorRGB ChosenClearColor = m_UseUniformClearColor ? m_UniformClearColor : DirectXClearColor;
const float clearColor[] = {static_cast<float>(ChosenClearColor.r) / 255.f, static_cast<float>(ChosenClearColor.g) / 255.f,
static_cast<float>(ChosenClearColor.b) / 255.f, 1.f};
// Clear back buffer
ColorRGB chosenClearColor = m_UseUniformClearColor ? m_UniformClearColor : DirectXClearColor;
const float clearColor[] = {
static_cast<float>(chosenClearColor.r) / 255.f,
static_cast<float>(chosenClearColor.g) / 255.f,
static_cast<float>(chosenClearColor.b) / 255.f,
1.0f
};
m_DeviceContextPtr->ClearRenderTargetView(m_RenderTargetViewPtr, clearColor);
// Clear depth and stencil buffer
m_DeviceContextPtr->ClearDepthStencilView(m_DepthStencilViewPtr, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
// Set viewport
D3D11_VIEWPORT viewport = {};
viewport.TopLeftX = 0.0f;
viewport.TopLeftY = 0.0f;
viewport.Width = static_cast<float>(m_Width);
viewport.Height = static_cast<float>(m_Height);
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
m_DeviceContextPtr->RSSetViewports(1, &viewport);
// Set camera matrix
Matrix viewProjMatrix = m_Camera.GetViewProjectionMatrix();
for (auto mesh: m_pScene->GetMeshes()) {
if (mesh->GetShouldRender()) {
Matrix modelMatrix = mesh->GetWorldMatrix();
Matrix worldViewProjMatrix = modelMatrix * viewProjMatrix;
mesh->Render(m_DeviceContextPtr, worldViewProjMatrix);
}
}
// Render all meshes in the scene
// for (auto mesh : m_pScene->GetMeshes()) {
// if (mesh->GetShouldRender()) {
// Matrix modelMatrix = mesh->GetWorldMatrix();
// Matrix worldViewProjMatrix = modelMatrix * viewProjMatrix;
//
// mesh->Render(m_DeviceContextPtr, worldViewProjMatrix);
// }
// }
// Call additional scene render logic (e.g., shadow rendering or post-processing)
m_pScene->Render(m_DeviceContextPtr, m_RenderTargetViewPtr, m_DepthStencilViewPtr, m_Camera);
//Present
m_SwapChainPtr->Present(0, 0);
// Present the rendered frame
HRESULT result = m_SwapChainPtr->Present(0, 0);
assert(SUCCEEDED(result) && "SwapChain Present failed");
}
void Renderer::RenderSDL() {
ColorRGB ChosenClearColor = m_UseUniformClearColor ? m_UniformClearColor : m_ClearColorSoftware;
SDL_FillRect(m_pBackBuffer, nullptr, SDL_MapRGB(m_pBackBuffer->format, ChosenClearColor.r, ChosenClearColor.g, ChosenClearColor.b));

View File

@@ -5,6 +5,7 @@
#include "HitTest.h"
#include "Scenes/BaseScene.h"
#include "Effects/Effect.h"
#include "Buffers/ShadowMapBuffer.h"
#include <unordered_map>
@@ -92,6 +93,9 @@ namespace dae
ColorRGB m_UniformClearColor{ ColorRGB{0.1f * 255.f, 0.1f * 255.f, 0.1 * 255.f} };
ShadowMapBuffer* m_pShadowMapBuffer{};
dae::Matrix m_LightViewProjectionMatrix{};
//DirectX vars

View File

@@ -27,6 +27,7 @@ public:
virtual std::vector<Mesh*>& GetMeshes() = 0;
virtual std::vector<std::shared_ptr<Material>>& GetMaterials() = 0;
};

View File

@@ -0,0 +1,167 @@
//
// Created by Bram on 14/01/2025.
//
#include "ShadowTestScene.h"
#include "../Utils.h"
#include "../Effects/ShadowEffect.h"
#include "../Effects/Effect.h"
#include "../Buffers/DX11Viewport.h"
void ShadowTestScene::Initialize(ID3D11Device *DevicePtr, ID3D11DeviceContext *DeviceContextPtr, Camera *camera) {
// Initialize shadow map buffer
m_ShadowMapBuffer = new ShadowMapBuffer(DevicePtr, 1024 * 4, 1024 * 4); // Example resolution: 1024x1024
if(!m_ShadowMapBuffer->Initialize()){
assert(true && "Shadow map buffer failed to initialize");
}
// Initialize light source
m_Light.SetPosition({-20.0f, 30.0f, 0.0f});
m_Light.SetTarget({0, -5, 40});
m_Light.SetUp({0.0f, 1.0f, 0.0f});
std::vector<VertexIn> vertices{};
std::vector<uint32_t> indices{};
if(!Utils::ParseOBJNew("resources/ShadingDemo.obj", vertices, indices, true)){
assert(true && "Model failed to load");
}
auto material = std::make_shared<Material>();
// material->diffuseTexturePtr = Texture::LoadFromFile("resources/vehicle_diffuse.png", DevicePtr);
auto shadowEffect = new ShadowEffect(DevicePtr, L"resources/shadowEffect.fx");
auto otherEffect = new Effect(DevicePtr, L"resources/SuperSimpleDiffuse.fx");
auto shadowMesh = new ShadowMesh(DevicePtr, vertices, indices, material, shadowEffect, otherEffect);
// std::vector<std::unique_ptr<Utils::MaterialMesh>> materialMeshes;
// Utils::LoadObjWithMaterials("resources/scene.obj", materialMeshes, true, DevicePtr);
// for (const auto &mesh: materialMeshes) {
// if (mesh->vertices.size() > 0) {
// std::shared_ptr<Material> material = std::make_shared<Material>();
// BaseEffect *effect = new Effect(DevicePtr, L"resources/SuperSimpleDiffuse.fx");
// ShadowEffect* shadowEffect = new ShadowEffect(DevicePtr, L"resources/shadowEffect.fx");
// material->diffuseTexturePtr = Texture::LoadFromFile("./resources/diorama/" + mesh->diffuse_texture, DevicePtr);
//
// if (mesh->opacity_map != "") {
//// continue;
//// effect = new FireEffect(DevicePtr, L"resources/Fire.fx");
//// material->diffuseTexturePtr = Texture::LoadFromFile("./resources/diorama/" + mesh->diffuse_texture, DevicePtr);
// } else {
// }
//
// m_shadowMeshes.push_back(new ShadowMesh(DevicePtr, mesh->vertices, mesh->indices, material, shadowEffect, effect));
//
// Matrix worldMatrix = m_shadowMeshes.back()->GetWorldMatrix();
// worldMatrix *= Matrix::CreateScale(2.f, 2.f, 2.f);
// worldMatrix *= Matrix::CreateScale(-1.f, 1.f, 1.f); // Mirror the model (Possible loading fault)
// m_shadowMeshes.back()->SetWorldMatrix(worldMatrix);
// }
// }
//Move forward 100
shadowMesh->SetWorldMatrix(Matrix::CreateTranslation(Vector3(0, -5, 40)));
//
m_shadowMeshes.push_back(shadowMesh);
// m_shadowMaterials.push_back(material);
}
void ShadowTestScene::Update() {
// m_Light.SetTarget(lightTarget);
Vector3 pos = m_Light.GetPosition();
pos.y = sin(SDL_GetTicks() / 1000.f) * 10.f + 10.f;
m_Light.SetPosition(pos);
m_Light.Update();
}
void ShadowTestScene::Render(ID3D11DeviceContext *devicePtr, ID3D11RenderTargetView *renderTargetViewPtr,
ID3D11DepthStencilView *depthStencilViewPtr, const Camera &camera) {
// Shadow map pass
// Set the viewport to match the shadow map size
DX11Viewport ShadowViewport(1024 * 4, 1024 * 4);
ShadowViewport.Apply(devicePtr);
devicePtr->OMSetRenderTargets(0, nullptr, m_ShadowMapBuffer->GetDepthStencilView()); // Set the shadow map as the render target
devicePtr->ClearDepthStencilView(m_ShadowMapBuffer->GetDepthStencilView(), D3D11_CLEAR_DEPTH, 1.0f, 0); // Clear the shadow map
ID3D11ShaderResourceView* shadowMap = m_ShadowMapBuffer->GetShaderResourceView(); // Get the shadow map shader resource view
devicePtr->PSSetShaderResources(0, 1, &shadowMap); // Set the shadow map as a shader resource
devicePtr->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
ID3D11SamplerState* shadowSampler = m_ShadowMapBuffer->GetSamplerState();
devicePtr->PSSetSamplers(0, 1, &shadowSampler);
auto lightViewProjection = m_Light.GetViewProjectionMatrix();
for (auto* mesh : m_shadowMeshes) {
Matrix lightWorldViewProj = mesh->GetWorldMatrix() * lightViewProjection;
dynamic_cast<ShadowMesh*>(mesh)->RenderShadow(devicePtr, lightWorldViewProj);
}
ID3D11DepthStencilView* nullDepthStencilView = nullptr;
devicePtr->OMSetRenderTargets(1, &renderTargetViewPtr, nullDepthStencilView);
// Set the depthmap correctly
DX11Viewport ColorViewport(640, 480);
ColorViewport.Apply(devicePtr);
devicePtr->OMSetRenderTargets(1, &renderTargetViewPtr, depthStencilViewPtr);
ColorRGB DirectXClearColor{ .39f * 255.f, .59f * 255.f, .93f * 255.f };
const float clearColor[] = {
static_cast<float>(DirectXClearColor.r) / 255.f,
static_cast<float>(DirectXClearColor.g) / 255.f,
static_cast<float>(DirectXClearColor.b) / 255.f,
1.0f
};
devicePtr->ClearRenderTargetView(renderTargetViewPtr, clearColor);
devicePtr->ClearDepthStencilView(depthStencilViewPtr, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
for (auto* mesh : m_shadowMeshes) {
Matrix worldViewProj = mesh->GetWorldMatrix() * camera.GetViewProjectionMatrix();
Matrix lightWorldViewProj = mesh->GetWorldMatrix() * lightViewProjection;
auto* effect = dynamic_cast<ShadowMesh*>(mesh)->GetColorEffectPtr() ;
dynamic_cast<Effect*>(effect)->SetWorldViewProjMatrix(worldViewProj);
dynamic_cast<Effect*>(effect)->SetWorldMatrix(mesh->GetWorldMatrix());
dynamic_cast<Effect*>(effect)->SetShadowMapSampler(shadowSampler);
dynamic_cast<Effect*>(effect)->SetShadowMap(shadowMap);
dynamic_cast<Effect*>(effect)->SetLightViewProjMatrix(lightWorldViewProj);
dynamic_cast<ShadowMesh*>(mesh)->RenderFinal(devicePtr, worldViewProj);
}
}
void ShadowTestScene::Cleanup() {
for (auto *mesh : m_Meshes) {
delete mesh;
}
m_Meshes.clear();
for (auto *mesh : m_shadowMeshes) {
delete mesh;
}
m_shadowMeshes.clear();
delete m_ShadowMapBuffer;
}
std::vector<Mesh *> &ShadowTestScene::GetMeshes() {
return m_Meshes;
}
std::vector<std::shared_ptr<Material>> &ShadowTestScene::GetMaterials() {
return m_Materials;
}

View File

@@ -0,0 +1,42 @@
#ifndef GP1_DIRECTX_SHADOWTESTSCENE_H
#define GP1_DIRECTX_SHADOWTESTSCENE_H
#include "BaseScene.h"
#include "../Buffers/ShadowMapBuffer.h"
#include "../Light.h"
#include "../ShadowMesh.h"
class ShadowTestScene: public BaseScene {
public:
void Initialize(ID3D11Device *DevicePtr, ID3D11DeviceContext *DeviceContextPtr, Camera *camera) override;
void Update() override;
void Render(ID3D11DeviceContext *devicePtr, ID3D11RenderTargetView *renderTargetViewPtr, ID3D11DepthStencilView *depthStencilViewPtr,
const Camera &camera) override;
void Cleanup() override;
std::vector<Mesh *> &GetMeshes() override;
std::vector<std::shared_ptr<Material>> &GetMaterials() override;
private:
std::vector<Mesh *> m_Meshes;
std::vector<std::shared_ptr<Material>> m_Materials;
std::vector<ShadowMesh *> m_shadowMeshes;
std::vector<std::shared_ptr<Material>> m_shadowMaterials;
ShadowMapBuffer *m_ShadowMapBuffer{nullptr};
Light m_Light;
float angle = 0.0f;
void RenderShadowMapToScreen(ID3D11DeviceContext *devicePtr, ID3D11RenderTargetView *renderTargetViewPtr);
};
#endif //GP1_DIRECTX_SHADOWTESTSCENE_H

118
project/src/ShadowMesh.cpp Normal file
View File

@@ -0,0 +1,118 @@
#include "ShadowMesh.h"
#include <d3d11.h>
#include <d3dx11effect.h>
#include <cassert>
ShadowMesh::ShadowMesh(ID3D11Device* devicePtr,
const std::vector<VertexIn>& verticesIn,
const std::vector<Uint32>& indices,
std::shared_ptr<Material> material,
ShadowEffect* shadowEffectPtr,
BaseEffect* colorEffectPtr)
: m_ShadowEffectPtr(shadowEffectPtr),
m_ColorEffectPtr(colorEffectPtr),
m_VerticesIn(verticesIn),
m_Indices(indices),
m_IndicesCount(static_cast<UINT>(indices.size())) {
HRESULT result;
m_Material = material;
m_ColorEffectPtr->SetMaterial(material.get());
// Create input layout
D3D11_INPUT_ELEMENT_DESC vertexDesc[] = {
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
{"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, static_cast<UINT>(offsetof(VertexIn, uv)), D3D11_INPUT_PER_VERTEX_DATA, 0},
{"NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, static_cast<UINT>(offsetof(VertexIn, normal)), D3D11_INPUT_PER_VERTEX_DATA, 0},
{"TANGENT", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, static_cast<UINT>(offsetof(VertexIn, tangent)), D3D11_INPUT_PER_VERTEX_DATA, 0},
};
D3DX11_PASS_DESC passDesc;
ID3DX11EffectTechnique* techniquePtr = m_ColorEffectPtr->GetTechniquePtr();
techniquePtr->GetPassByIndex(0)->GetDesc(&passDesc);
result = devicePtr->CreateInputLayout(vertexDesc, ARRAYSIZE(vertexDesc),
passDesc.pIAInputSignature, passDesc.IAInputSignatureSize,
&m_InputLayoutPtr);
assert(result == S_OK && "Creating input layout failed");
// Create vertex buffer
D3D11_BUFFER_DESC bufferDesc = {};
bufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
bufferDesc.ByteWidth = sizeof(VertexIn) * static_cast<UINT>(verticesIn.size());
bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bufferDesc.CPUAccessFlags = 0;
D3D11_SUBRESOURCE_DATA subresourceData = {};
subresourceData.pSysMem = verticesIn.data();
result = devicePtr->CreateBuffer(&bufferDesc, &subresourceData, &m_VertexBufferPtr);
assert(result == S_OK && "Creating vertex buffer failed");
// Create index buffer
bufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
bufferDesc.ByteWidth = sizeof(Uint32) * m_IndicesCount;
bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
subresourceData.pSysMem = m_Indices.data();
result = devicePtr->CreateBuffer(&bufferDesc, &subresourceData, &m_IndexBufferPtr);
assert(result == S_OK && "Creating index buffer failed");
}
ShadowMesh::~ShadowMesh() {
if (m_InputLayoutPtr) m_InputLayoutPtr->Release();
if (m_VertexBufferPtr) m_VertexBufferPtr->Release();
if (m_IndexBufferPtr) m_IndexBufferPtr->Release();
delete m_ShadowEffectPtr;
delete m_ColorEffectPtr;
}
void ShadowMesh::RenderShadow(ID3D11DeviceContext* deviceContextPtr, const Matrix& lightWorldViewProj) {
m_ShadowEffectPtr->SetLightWorldViewProjMatrix(lightWorldViewProj);
deviceContextPtr->IASetInputLayout(m_InputLayoutPtr);
const UINT stride = sizeof(VertexIn);
const UINT offset = 0;
deviceContextPtr->IASetVertexBuffers(0, 1, &m_VertexBufferPtr, &stride, &offset);
deviceContextPtr->IASetIndexBuffer(m_IndexBufferPtr, DXGI_FORMAT_R32_UINT, 0);
D3DX11_TECHNIQUE_DESC techniqueDesc;
m_ShadowEffectPtr->GetTechniquePtr()->GetDesc(&techniqueDesc);
for (UINT p = 0; p < techniqueDesc.Passes; ++p) {
m_ShadowEffectPtr->GetTechniquePtr()->GetPassByIndex(p)->Apply(0, deviceContextPtr);
deviceContextPtr->DrawIndexed(m_IndicesCount, 0, 0);
}
}
void ShadowMesh::RenderFinal(ID3D11DeviceContext* deviceContextPtr, const Matrix& worldViewProj) {
m_ColorEffectPtr->SetWorldViewProjMatrix(worldViewProj);
deviceContextPtr->IASetInputLayout(m_InputLayoutPtr);
const UINT stride = sizeof(VertexIn);
const UINT offset = 0;
deviceContextPtr->IASetVertexBuffers(0, 1, &m_VertexBufferPtr, &stride, &offset);
deviceContextPtr->IASetIndexBuffer(m_IndexBufferPtr, DXGI_FORMAT_R32_UINT, 0);
D3DX11_TECHNIQUE_DESC techniqueDesc;
m_ColorEffectPtr->GetTechniquePtr()->GetDesc(&techniqueDesc);
for (UINT p = 0; p < techniqueDesc.Passes; ++p) {
m_ColorEffectPtr->GetTechniquePtr()->GetPassByIndex(p)->Apply(0, deviceContextPtr);
deviceContextPtr->DrawIndexed(m_IndicesCount, 0, 0);
}
}
void ShadowMesh::SetWorldMatrix(const Matrix& matrix) {
m_WorldMatrix = matrix;
}
Matrix ShadowMesh::GetWorldMatrix() const {
return m_WorldMatrix;
}

63
project/src/ShadowMesh.h Normal file
View File

@@ -0,0 +1,63 @@
#ifndef SHADOW_MESH_H
#define SHADOW_MESH_H
#include <cassert>
#include <vector>
#include <d3d11.h>
#include "Effects/ShadowEffect.h"
#include "Material.h"
#include "Mesh.h"
class ShadowMesh {
public:
ShadowMesh(ID3D11Device* devicePtr,
const std::vector<VertexIn>& verticesIn,
const std::vector<Uint32>& indices,
std::shared_ptr<Material> material,
ShadowEffect* shadowEffectPtr,
BaseEffect* colorEffectPtr);
~ShadowMesh();
void RenderShadow(ID3D11DeviceContext* deviceContextPtr, const Matrix& lightWorldViewProj);
void RenderFinal(ID3D11DeviceContext* deviceContextPtr, const Matrix& worldViewProj);
void SetWorldMatrix(const Matrix& matrix);
Matrix GetWorldMatrix() const;
ShadowEffect* GetShadowEffectPtr(){ return m_ShadowEffectPtr; }
BaseEffect* GetColorEffectPtr(){ return m_ColorEffectPtr; }
private:
// Shadow effect
ShadowEffect* m_ShadowEffectPtr;
// Color effect for final render
BaseEffect* m_ColorEffectPtr;
// Buffers
ID3D11InputLayout* m_InputLayoutPtr;
ID3D11Buffer* m_VertexBufferPtr;
ID3D11Buffer* m_IndexBufferPtr;
//Shadow buffers
ID3D11InputLayout* m_ShadowInputLayoutPtr;
ID3D11Buffer* m_ShadowVertexBufferPtr;
ID3D11Buffer* m_ShadowIndexBufferPtr;
// Material and mesh data
std::shared_ptr<Material> m_Material;
std::vector<VertexIn> m_VerticesIn;
std::vector<Uint32> m_Indices;
// Matrix transformations
Matrix m_WorldMatrix;
// Indices count
UINT m_IndicesCount;
};
#endif // SHADOW_MESH_H

View File

@@ -133,6 +133,7 @@ int main(int argc, char *args[]) {
const uint32_t height = 480;
SDL_Window *pWindow = SDL_CreateWindow(
"DirectX - Bram Verhulst - 2GD11E",
SDL_WINDOWPOS_UNDEFINED,