Add shadows, fi other stuff
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -25,4 +25,5 @@ bld/
|
||||
.vs
|
||||
cmake-build-debug
|
||||
cmake-build-release
|
||||
cmake-build-debug-visual-studio
|
||||
cmake-build-debug-visual-studio
|
||||
cmake-**
|
||||
|
||||
@@ -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,13 +13,23 @@ set(SOURCES
|
||||
"src/Utils.cpp"
|
||||
"src/HitTest.cpp"
|
||||
"src/Material.cpp"
|
||||
"src/Math/Vector2.cpp"
|
||||
"src/DirectionalLight.cpp"
|
||||
|
||||
"src/Math/Vector2.cpp"
|
||||
"src/Math/Vector3.cpp"
|
||||
"src/Math/Vector4.cpp"
|
||||
"src/Math/Matrix.cpp"
|
||||
|
||||
"src/BRDF.h"
|
||||
|
||||
"src/Effects/Effect.cpp"
|
||||
"src/Effects/BaseEffect.cpp"
|
||||
"src/Effects/FireEffect.cpp"
|
||||
"src/Effects/ShadowEffect.cpp"
|
||||
"src/Effects/ShadowDiffuse.cpp"
|
||||
|
||||
"src/Singleton.h"
|
||||
"src/RenderSettings.h"
|
||||
|
||||
"src/PerlinNoise.hpp"
|
||||
|
||||
@@ -27,6 +38,12 @@ set(SOURCES
|
||||
"src/Scenes/DioramaScene.cpp"
|
||||
"src/Scenes/InstancedScene.cpp"
|
||||
"src/Scenes/PlanetScene.cpp"
|
||||
"src/Scenes/ShadowTestScene.cpp"
|
||||
|
||||
"src/Buffers/ShadowMapBuffer.cpp"
|
||||
"src/Buffers/SamplerState.cpp"
|
||||
"src/Buffers/DepthBuffer.cpp"
|
||||
"src/Buffers/DX11Viewport.cpp"
|
||||
)
|
||||
|
||||
SET(INCLUDE_DIRS
|
||||
@@ -34,6 +51,7 @@ SET(INCLUDE_DIRS
|
||||
"src/Math"
|
||||
"src/Effects"
|
||||
"src/Scenes"
|
||||
"src/Buffers"
|
||||
)
|
||||
|
||||
# Create the executable
|
||||
|
||||
2
project/resources/ShadingDemo.mtl
Normal file
2
project/resources/ShadingDemo.mtl
Normal file
@@ -0,0 +1,2 @@
|
||||
# Blender 4.3.2 MTL File: 'None'
|
||||
# www.blender.org
|
||||
4919
project/resources/ShadingDemo.obj
Normal file
4919
project/resources/ShadingDemo.obj
Normal file
File diff suppressed because it is too large
Load Diff
131
project/resources/SuperSimpleDiffuse.fx
Normal file
131
project/resources/SuperSimpleDiffuse.fx
Normal file
@@ -0,0 +1,131 @@
|
||||
|
||||
texture2D gShadowMap : ShadowMap;
|
||||
float4x4 gLightWorldViewProj : 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 gShadowSampler2 : ShadowSampler {
|
||||
Filter = MIN_MAG_MIP_POINT;
|
||||
AddressU = CLAMP;
|
||||
AddressV = CLAMP;
|
||||
ComparisonFunc = LESS_EQUAL;
|
||||
};
|
||||
|
||||
|
||||
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) , gLightWorldViewProj);
|
||||
return output;
|
||||
}
|
||||
|
||||
// Shadow sampling function
|
||||
float ShadowCalculation(float4 shadowCoord, float3 normal) {
|
||||
// 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, gLightDirection)), 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 {
|
||||
float shadowFactor = ShadowCalculation(input.ShadowCoord, input.Normal);
|
||||
|
||||
float3 diffuseColor = gDiffuseMap.Sample(gSampleState, input.TexCoord).rgb;
|
||||
|
||||
float3 finalColor = float3(1.f, 1.f, 1.f) * shadowFactor;
|
||||
finalColor += gAmbient;
|
||||
|
||||
return float4(finalColor, 1.0f);
|
||||
}
|
||||
|
||||
// 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()));
|
||||
}
|
||||
}
|
||||
47
project/resources/shadowEffect.fx
Normal file
47
project/resources/shadowEffect.fx
Normal 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()));
|
||||
}
|
||||
}
|
||||
25
project/src/BRDF.h
Normal file
25
project/src/BRDF.h
Normal file
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// Created by Bram on 17/01/2025.
|
||||
//
|
||||
|
||||
#ifndef GP1_DIRECTX_BRDF_H
|
||||
#define GP1_DIRECTX_BRDF_H
|
||||
|
||||
#include "ColorRGB.h"
|
||||
#include "./math/Vector3.h"
|
||||
|
||||
namespace dae{
|
||||
static ColorRGB Phong(const ColorRGB& specularReflectance, float exp, const Vector3& lightDir, const Vector3& viewDir, const Vector3& normal)
|
||||
{
|
||||
const Vector3 reflect{ Vector3::Reflect(lightDir, normal) };
|
||||
const float dot{ Saturate(Vector3::Dot(reflect, -viewDir)) };
|
||||
return specularReflectance * powf(dot, exp);
|
||||
}
|
||||
|
||||
static ColorRGB Lambert(float kd, const ColorRGB& diffuse)
|
||||
{
|
||||
return kd * diffuse;
|
||||
}
|
||||
}
|
||||
|
||||
#endif //GP1_DIRECTX_BRDF_H
|
||||
35
project/src/Buffers/DX11Viewport.cpp
Normal file
35
project/src/Buffers/DX11Viewport.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
//
|
||||
// Created by Bram on 16/01/2025.
|
||||
//
|
||||
|
||||
#include "DX11Viewport.h"
|
||||
|
||||
DX11Viewport::DX11Viewport(float width, float height, float topLeftX, float topLeftY, float minDepth, float maxDepth) {
|
||||
viewport.Width = width;
|
||||
viewport.Height = height;
|
||||
viewport.TopLeftX = topLeftX;
|
||||
viewport.TopLeftY = topLeftY;
|
||||
viewport.MinDepth = minDepth;
|
||||
viewport.MaxDepth = maxDepth;
|
||||
}
|
||||
|
||||
void DX11Viewport::Apply(ID3D11DeviceContext *context) {
|
||||
if (context) {
|
||||
context->RSSetViewports(1, &viewport);
|
||||
}
|
||||
}
|
||||
|
||||
void DX11Viewport::SetDimensions(float width, float height) {
|
||||
viewport.Width = width;
|
||||
viewport.Height = height;
|
||||
}
|
||||
|
||||
void DX11Viewport::SetPosition(float topLeftX, float topLeftY) {
|
||||
viewport.TopLeftX = topLeftX;
|
||||
viewport.TopLeftY = topLeftY;
|
||||
}
|
||||
|
||||
void DX11Viewport::SetDepthRange(float minDepth, float maxDepth) {
|
||||
viewport.MinDepth = minDepth;
|
||||
viewport.MaxDepth = maxDepth;
|
||||
}
|
||||
24
project/src/Buffers/DX11Viewport.h
Normal file
24
project/src/Buffers/DX11Viewport.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#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);
|
||||
|
||||
void Apply(ID3D11DeviceContext *context);
|
||||
|
||||
void SetDimensions(float width, float height);
|
||||
|
||||
void SetPosition(float topLeftX, float topLeftY);
|
||||
|
||||
void SetDepthRange(float minDepth, float maxDepth);
|
||||
|
||||
const D3D11_VIEWPORT &GetViewport() const { return viewport; }
|
||||
|
||||
private:
|
||||
D3D11_VIEWPORT viewport;
|
||||
};
|
||||
|
||||
#endif //GP1_DIRECTX_DX11VIEWPORT_H
|
||||
50
project/src/Buffers/DepthBuffer.cpp
Normal file
50
project/src/Buffers/DepthBuffer.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
#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;
|
||||
}
|
||||
31
project/src/Buffers/DepthBuffer.h
Normal file
31
project/src/Buffers/DepthBuffer.h
Normal 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
|
||||
29
project/src/Buffers/SamplerState.cpp
Normal file
29
project/src/Buffers/SamplerState.cpp
Normal 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;
|
||||
}
|
||||
19
project/src/Buffers/SamplerState.h
Normal file
19
project/src/Buffers/SamplerState.h
Normal 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
|
||||
50
project/src/Buffers/ShadowMapBuffer.cpp
Normal file
50
project/src/Buffers/ShadowMapBuffer.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
#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();
|
||||
}
|
||||
37
project/src/Buffers/ShadowMapBuffer.h
Normal file
37
project/src/Buffers/ShadowMapBuffer.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#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);
|
||||
|
||||
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
|
||||
45
project/src/DirectionalLight.cpp
Normal file
45
project/src/DirectionalLight.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
#include "DirectionalLight.h"
|
||||
#include <cmath>
|
||||
|
||||
DirectionalLight::DirectionalLight()
|
||||
: 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 DirectionalLight::SetPosition(const dae::Vector3 &position) {
|
||||
m_Position = position;
|
||||
}
|
||||
|
||||
void DirectionalLight::SetTarget(const dae::Vector3 &target) {
|
||||
m_Target = target;
|
||||
}
|
||||
|
||||
void DirectionalLight::SetUp(const dae::Vector3 &up) {
|
||||
m_Up = up;
|
||||
}
|
||||
|
||||
dae::Matrix DirectionalLight::GetViewMatrix() const {
|
||||
return dae::Matrix::CreateLookAtLH(m_Position, m_Target, m_Up);
|
||||
}
|
||||
|
||||
dae::Matrix DirectionalLight::GetProjectionMatrix(float nearPlane, float farPlane, float size) const {
|
||||
return dae::Matrix::CreateOrthographic(size, size, nearPlane, farPlane);
|
||||
}
|
||||
dae::Matrix DirectionalLight::GetViewProjectionMatrix(float nearPlane, float farPlane, float size) const {
|
||||
return GetViewMatrix() * GetProjectionMatrix(nearPlane, farPlane, size);
|
||||
}
|
||||
void DirectionalLight::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 DirectionalLight::GetTarget() {
|
||||
return m_Target;
|
||||
}
|
||||
|
||||
dae::Vector3 DirectionalLight::GetPosition() {
|
||||
return m_Position;
|
||||
}
|
||||
34
project/src/DirectionalLight.h
Normal file
34
project/src/DirectionalLight.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#ifndef GP1_DIRECTX_DIRECTIONALLIGHT_H
|
||||
#define GP1_DIRECTX_DIRECTIONALLIGHT_H
|
||||
|
||||
|
||||
#include "Math/Vector3.h"
|
||||
#include "Math/Matrix.h"
|
||||
|
||||
class DirectionalLight {
|
||||
public:
|
||||
DirectionalLight();
|
||||
~DirectionalLight() = 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_DIRECTIONALLIGHT_H
|
||||
@@ -52,6 +52,7 @@ Effect::Effect(ID3D11Device *devicePtr, const std::wstring &filePath)
|
||||
if(!m_RasterizerVariablePtr->IsValid())
|
||||
std::wcout << L"gRasterizerState Rasterizer is not valid" << std::endl;
|
||||
|
||||
|
||||
m_UseNormalMapVariablePtr->SetBool(m_UseNormalMap);
|
||||
|
||||
|
||||
@@ -201,4 +202,4 @@ void Effect::InitRasterizer(ID3D11Device *devicePtr) {
|
||||
rasterDesc.CullMode = D3D11_CULL_NONE;
|
||||
|
||||
devicePtr->CreateRasterizerState(&rasterDesc, &m_RasterizerStates[static_cast<int>(CullMode::None)]);
|
||||
}
|
||||
}
|
||||
@@ -3,15 +3,12 @@
|
||||
#include "BaseEffect.h"
|
||||
#include <array>
|
||||
|
||||
|
||||
|
||||
enum class CullMode {
|
||||
None = 0,
|
||||
Front = 1,
|
||||
Back = 2
|
||||
};
|
||||
|
||||
|
||||
class Effect final: public BaseEffect {
|
||||
public:
|
||||
Effect(ID3D11Device *devicePtr, const std::wstring &filePath);
|
||||
@@ -60,4 +57,4 @@ private:
|
||||
CullMode m_CullMode{ CullMode::Back };
|
||||
|
||||
bool m_UseNormalMap{true};
|
||||
};
|
||||
};
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <array>
|
||||
#include "BaseEffect.h"
|
||||
|
||||
class FireEffect final: public BaseEffect {
|
||||
class FireEffect final : public BaseEffect {
|
||||
public:
|
||||
FireEffect(ID3D11Device *devicePtr, const std::wstring &filePath);
|
||||
|
||||
@@ -20,14 +20,13 @@ public:
|
||||
void NextSamplingState() override;
|
||||
|
||||
private:
|
||||
void InitSamplers(ID3D11Device* devicePtr);
|
||||
|
||||
void InitSamplers(ID3D11Device *devicePtr);
|
||||
|
||||
ID3DX11EffectShaderResourceVariable *m_DiffuseMapVariablePtr{};
|
||||
|
||||
ID3DX11EffectSamplerVariable *m_SamplerVariablePtr{};
|
||||
|
||||
std::array<ID3D11SamplerState*, 3> m_SamplerStates{};
|
||||
std::array<ID3D11SamplerState *, 3> m_SamplerStates{};
|
||||
|
||||
TechniqueType m_TechniqueType{TechniqueType::Linear};
|
||||
|
||||
|
||||
235
project/src/Effects/ShadowDiffuse.cpp
Normal file
235
project/src/Effects/ShadowDiffuse.cpp
Normal file
@@ -0,0 +1,235 @@
|
||||
#include "../pch.h"
|
||||
#include "ShadowDiffuse.h"
|
||||
#include "../Utils.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
ShadowDiffuse::ShadowDiffuse(ID3D11Device *devicePtr, const std::wstring &filePath)
|
||||
: BaseEffect(devicePtr, filePath) {
|
||||
|
||||
m_LightPosVariablePtr = m_EffectPtr->GetVariableByName("gLightDirection")->AsVector();
|
||||
if(!m_LightPosVariablePtr->IsValid())
|
||||
std::wcout << L"gLightDirection Vector is not valid" << std::endl;
|
||||
|
||||
|
||||
m_SamplerVariablePtr = m_EffectPtr->GetVariableByName("gSampleState")->AsSampler();
|
||||
if(!m_SamplerVariablePtr->IsValid())
|
||||
std::wcout << L"gSampleState Sampler is not valid" << std::endl;
|
||||
|
||||
m_MatWorldVariablePtr = m_EffectPtr->GetVariableByName("gWorldMatrix")->AsMatrix();
|
||||
if(!m_MatWorldVariablePtr->IsValid())
|
||||
std::wcout << L"gWorld Matrix is not valid" << std::endl;
|
||||
|
||||
m_DiffuseMapVariablePtr = m_EffectPtr->GetVariableByName("gDiffuseMap")->AsShaderResource();
|
||||
if(!m_DiffuseMapVariablePtr->IsValid())
|
||||
std::wcout << L"gDiffuseMap ShaderResource is not valid" << std::endl;
|
||||
|
||||
m_NormalMapVariablePtr = m_EffectPtr->GetVariableByName("gNormalMap")->AsShaderResource();
|
||||
if(!m_NormalMapVariablePtr->IsValid())
|
||||
std::wcout << L"gNormalMap ShaderResource is not valid" << std::endl;
|
||||
|
||||
m_SpecularMapVariablePtr = m_EffectPtr->GetVariableByName("gSpecularMap")->AsShaderResource();
|
||||
if(!m_SpecularMapVariablePtr->IsValid())
|
||||
std::wcout << L"gSpecularMap ShaderResource is not valid" << std::endl;
|
||||
|
||||
m_GlossMapVariablePtr = m_EffectPtr->GetVariableByName("gGlossMap")->AsShaderResource();
|
||||
if(!m_GlossMapVariablePtr->IsValid())
|
||||
std::wcout << L"gGlossMap ShaderResource is not valid" << std::endl;
|
||||
|
||||
m_CameraPosVariablePtr = m_EffectPtr->GetVariableByName("gCameraPosition")->AsVector();
|
||||
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;
|
||||
|
||||
m_UseNormalMapVariablePtr = m_EffectPtr->GetVariableByName("gUseNormal")->AsScalar();
|
||||
if(!m_UseNormalMapVariablePtr->IsValid())
|
||||
std::wcout << L"gUseNormalMap Scalar is not valid" << std::endl;
|
||||
|
||||
m_RasterizerVariablePtr = m_EffectPtr->GetVariableByName("gRasterizerState")->AsRasterizer();
|
||||
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"gShadowMapSampler Sampler is not valid" << std::endl;
|
||||
|
||||
m_LightWorldViewProjVariablePtr = m_EffectPtr->GetVariableByName("gLightWorldViewProj")->AsMatrix();
|
||||
if(!m_LightWorldViewProjVariablePtr->IsValid())
|
||||
std::wcout << L"gLightWorldViewProj Matrix is not valid" << std::endl;
|
||||
|
||||
|
||||
m_UseNormalMapVariablePtr->SetBool(m_UseNormalMap);
|
||||
|
||||
|
||||
constexpr int vectorSize{ 4 };
|
||||
constexpr float lightDirection[vectorSize]{ .577f, -.577f, .577f, 0.f };
|
||||
m_LightPosVariablePtr->SetFloatVector(lightDirection);
|
||||
|
||||
constexpr float lightColor[vectorSize]{ 1.f, 1.f, 1.f, 1.f };
|
||||
m_LightColorVariablePtr->SetFloatVector(lightColor);
|
||||
|
||||
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)]);
|
||||
}
|
||||
|
||||
ShadowDiffuse::~ShadowDiffuse() {
|
||||
m_MatWorldVariablePtr->Release();
|
||||
m_MatWorldVariablePtr = nullptr;
|
||||
|
||||
m_DiffuseMapVariablePtr->Release();
|
||||
m_DiffuseMapVariablePtr = nullptr;
|
||||
|
||||
m_NormalMapVariablePtr->Release();
|
||||
m_NormalMapVariablePtr = nullptr;
|
||||
|
||||
m_SpecularMapVariablePtr->Release();
|
||||
m_SpecularMapVariablePtr = nullptr;
|
||||
|
||||
m_GlossMapVariablePtr->Release();
|
||||
m_GlossMapVariablePtr = nullptr;
|
||||
|
||||
m_CameraPosVariablePtr->Release();
|
||||
m_CameraPosVariablePtr = nullptr;
|
||||
|
||||
m_LightPosVariablePtr->Release();
|
||||
m_LightPosVariablePtr = nullptr;
|
||||
|
||||
m_LightColorVariablePtr->Release();
|
||||
m_LightColorVariablePtr = nullptr;
|
||||
|
||||
m_UseNormalMapVariablePtr->Release();
|
||||
m_UseNormalMapVariablePtr = nullptr;
|
||||
|
||||
m_SamplerVariablePtr->Release();
|
||||
m_SamplerVariablePtr = nullptr;
|
||||
|
||||
m_RasterizerVariablePtr->Release();
|
||||
m_RasterizerVariablePtr = nullptr;
|
||||
|
||||
if(m_ShadowMapVariablePtr){
|
||||
m_ShadowMapVariablePtr->Release();
|
||||
m_ShadowMapVariablePtr = nullptr;
|
||||
}
|
||||
|
||||
if(m_LightWorldViewProjVariablePtr){
|
||||
m_LightWorldViewProjVariablePtr->Release();
|
||||
m_LightWorldViewProjVariablePtr = nullptr;
|
||||
}
|
||||
|
||||
for(auto sampler : m_SamplerStates){
|
||||
sampler->Release();
|
||||
}
|
||||
|
||||
for(auto rasterizer : m_RasterizerStates){
|
||||
rasterizer->Release();
|
||||
}
|
||||
|
||||
m_EffectPtr->Release();
|
||||
m_EffectPtr = nullptr;
|
||||
}
|
||||
|
||||
void ShadowDiffuse::SetWorldMatrix(const dae::Matrix &world) const {
|
||||
m_MatWorldVariablePtr->SetMatrix(reinterpret_cast<const float*>(&world));
|
||||
}
|
||||
|
||||
void ShadowDiffuse::SetMaterial(Material* material) {
|
||||
if(material->diffuseTexturePtr)
|
||||
m_DiffuseMapVariablePtr->SetResource(material->diffuseTexturePtr->GetSrv());
|
||||
if(material->normalTexturePtr)
|
||||
m_NormalMapVariablePtr->SetResource(material->normalTexturePtr->GetSrv());
|
||||
if(material->specularTexturePtr)
|
||||
m_SpecularMapVariablePtr->SetResource(material->specularTexturePtr->GetSrv());
|
||||
if(material->glossTexturePtr)
|
||||
m_GlossMapVariablePtr->SetResource(material->glossTexturePtr->GetSrv());
|
||||
}
|
||||
|
||||
|
||||
void ShadowDiffuse::SetCameraPos(const dae::Vector3 &pos) const {
|
||||
m_CameraPosVariablePtr->SetFloatVector(reinterpret_cast<const float*>(&pos));
|
||||
}
|
||||
|
||||
void ShadowDiffuse::NextSamplingState() {
|
||||
switch(m_TechniqueType){
|
||||
case TechniqueType::Point:
|
||||
m_TechniqueType = TechniqueType::Linear;
|
||||
break;
|
||||
case TechniqueType::Linear:
|
||||
m_TechniqueType = TechniqueType::Anisotropic;
|
||||
break;
|
||||
case TechniqueType::Anisotropic:
|
||||
m_TechniqueType = TechniqueType::Point;
|
||||
break;
|
||||
}
|
||||
m_SamplerVariablePtr->SetSampler(0,m_SamplerStates[static_cast<int>(m_TechniqueType)]);
|
||||
}
|
||||
|
||||
void ShadowDiffuse::ToggleNormals() {
|
||||
m_UseNormalMap = !m_UseNormalMap;
|
||||
m_UseNormalMapVariablePtr->SetBool(m_UseNormalMap);
|
||||
}
|
||||
|
||||
void ShadowDiffuse::InitSamplers(ID3D11Device *devicePtr) {
|
||||
D3D11_SAMPLER_DESC samplerDesc{};
|
||||
samplerDesc.Filter = D3D11_FILTER_ANISOTROPIC;
|
||||
samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
|
||||
samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
|
||||
samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
|
||||
samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
|
||||
|
||||
devicePtr->CreateSamplerState(&samplerDesc, &m_SamplerStates[static_cast<int>(TechniqueType::Anisotropic)]);
|
||||
|
||||
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
|
||||
devicePtr->CreateSamplerState(&samplerDesc, &m_SamplerStates[static_cast<int>(TechniqueType::Linear)]);
|
||||
|
||||
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
|
||||
devicePtr->CreateSamplerState(&samplerDesc, &m_SamplerStates[static_cast<int>(TechniqueType::Point)]);
|
||||
|
||||
m_SamplerVariablePtr->SetSampler(0,m_SamplerStates[static_cast<int>(m_TechniqueType)]);
|
||||
}
|
||||
|
||||
void ShadowDiffuse::NextCullMode() {
|
||||
m_CullMode = static_cast<CullMode>((static_cast<int>(m_CullMode) + 1) % 3);
|
||||
m_RasterizerVariablePtr->SetRasterizerState(0,m_RasterizerStates[static_cast<int>(m_CullMode)]);
|
||||
}
|
||||
|
||||
void ShadowDiffuse::InitRasterizer(ID3D11Device *devicePtr) {
|
||||
D3D11_RASTERIZER_DESC rasterDesc = {};
|
||||
rasterDesc.FillMode = D3D11_FILL_SOLID; // Solid fill
|
||||
rasterDesc.FrontCounterClockwise = FALSE;
|
||||
rasterDesc.DepthBias = D3D11_DEFAULT_DEPTH_BIAS;
|
||||
rasterDesc.SlopeScaledDepthBias = D3D11_DEFAULT_SLOPE_SCALED_DEPTH_BIAS;
|
||||
rasterDesc.DepthClipEnable = TRUE;
|
||||
rasterDesc.ScissorEnable = FALSE;
|
||||
rasterDesc.MultisampleEnable = FALSE;
|
||||
rasterDesc.AntialiasedLineEnable = FALSE;
|
||||
|
||||
rasterDesc.CullMode = D3D11_CULL_BACK; // Cull back faces
|
||||
|
||||
devicePtr->CreateRasterizerState(&rasterDesc, &m_RasterizerStates[static_cast<int>(CullMode::Back)]);
|
||||
|
||||
rasterDesc.CullMode = D3D11_CULL_FRONT;
|
||||
|
||||
devicePtr->CreateRasterizerState(&rasterDesc, &m_RasterizerStates[static_cast<int>(CullMode::Front)]);
|
||||
|
||||
rasterDesc.CullMode = D3D11_CULL_NONE;
|
||||
|
||||
devicePtr->CreateRasterizerState(&rasterDesc, &m_RasterizerStates[static_cast<int>(CullMode::None)]);
|
||||
}
|
||||
|
||||
void ShadowDiffuse::SetShadowMap(ID3D11ShaderResourceView *shadowMapSRV) {
|
||||
m_ShadowMapVariablePtr->SetResource(shadowMapSRV);
|
||||
}
|
||||
|
||||
void ShadowDiffuse::SetLightViewProjMatrix(Matrix matrix) {
|
||||
m_LightWorldViewProjVariablePtr->SetMatrix(reinterpret_cast<const float*>(&matrix));
|
||||
}
|
||||
|
||||
void ShadowDiffuse::SetLightDirection(Vector3 direction) {
|
||||
|
||||
}
|
||||
70
project/src/Effects/ShadowDiffuse.h
Normal file
70
project/src/Effects/ShadowDiffuse.h
Normal file
@@ -0,0 +1,70 @@
|
||||
#pragma once
|
||||
|
||||
#include "BaseEffect.h"
|
||||
#include <array>
|
||||
|
||||
enum class CullMode {
|
||||
None = 0,
|
||||
Front = 1,
|
||||
Back = 2
|
||||
};
|
||||
|
||||
class ShadowDiffuse final: public BaseEffect {
|
||||
public:
|
||||
ShadowDiffuse(ID3D11Device *devicePtr, const std::wstring &filePath);
|
||||
|
||||
virtual ~ShadowDiffuse() override;
|
||||
|
||||
void SetWorldMatrix(const dae::Matrix &world) const override;
|
||||
|
||||
void SetCameraPos(const dae::Vector3 &pos) const override;
|
||||
|
||||
void SetMaterial(Material *material) override;
|
||||
|
||||
void ToggleNormals() override;
|
||||
|
||||
void NextSamplingState() override;
|
||||
|
||||
void NextCullMode() override;
|
||||
|
||||
void SetShadowMap(ID3D11ShaderResourceView* shadowMapSRV);
|
||||
|
||||
void SetLightViewProjMatrix(Matrix matrix);
|
||||
|
||||
void SetLightDirection(Vector3 direction);
|
||||
|
||||
private:
|
||||
|
||||
void InitSamplers(ID3D11Device* devicePtr);
|
||||
void InitRasterizer(ID3D11Device* devicePtr);
|
||||
|
||||
ID3DX11EffectMatrixVariable *m_MatWorldVariablePtr{};
|
||||
|
||||
ID3DX11EffectShaderResourceVariable *m_DiffuseMapVariablePtr{};
|
||||
ID3DX11EffectShaderResourceVariable *m_NormalMapVariablePtr{};
|
||||
ID3DX11EffectShaderResourceVariable *m_SpecularMapVariablePtr{};
|
||||
ID3DX11EffectShaderResourceVariable *m_GlossMapVariablePtr{};
|
||||
|
||||
ID3DX11EffectVectorVariable *m_CameraPosVariablePtr{};
|
||||
ID3DX11EffectVectorVariable *m_LightPosVariablePtr{};
|
||||
ID3DX11EffectVectorVariable *m_LightColorVariablePtr{};
|
||||
|
||||
ID3DX11EffectScalarVariable *m_UseNormalMapVariablePtr{};
|
||||
|
||||
ID3DX11EffectSamplerVariable *m_SamplerVariablePtr{};
|
||||
|
||||
ID3DX11EffectRasterizerVariable* m_RasterizerVariablePtr{};
|
||||
|
||||
ID3DX11EffectMatrixVariable* m_LightWorldViewProjVariablePtr{};
|
||||
|
||||
ID3DX11EffectShaderResourceVariable* m_ShadowMapVariablePtr{};
|
||||
|
||||
TechniqueType m_TechniqueType{TechniqueType::Linear};
|
||||
|
||||
std::array<ID3D11SamplerState*, 3> m_SamplerStates{};
|
||||
std::array<ID3D11RasterizerState*, 3> m_RasterizerStates{};
|
||||
|
||||
CullMode m_CullMode{ CullMode::Back };
|
||||
|
||||
bool m_UseNormalMap{true};
|
||||
};
|
||||
64
project/src/Effects/ShadowEffect.cpp
Normal file
64
project/src/Effects/ShadowEffect.cpp
Normal file
@@ -0,0 +1,64 @@
|
||||
//
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
ShadowEffect::~ShadowEffect() {
|
||||
if (m_LightWorldViewProjVariable) {
|
||||
m_LightWorldViewProjVariable->Release();
|
||||
m_LightWorldViewProjVariable = nullptr;
|
||||
}
|
||||
|
||||
if (m_ShadowMapVariable) {
|
||||
m_ShadowMapVariable->Release();
|
||||
m_ShadowMapVariable = nullptr;
|
||||
}
|
||||
|
||||
if (m_ShadowMapSamplerVariable) {
|
||||
m_ShadowMapSamplerVariable->Release();
|
||||
m_ShadowMapSamplerVariable = nullptr;
|
||||
}
|
||||
|
||||
m_EffectPtr->Release();
|
||||
m_EffectPtr = nullptr;
|
||||
}
|
||||
|
||||
23
project/src/Effects/ShadowEffect.h
Normal file
23
project/src/Effects/ShadowEffect.h
Normal file
@@ -0,0 +1,23 @@
|
||||
|
||||
#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;
|
||||
|
||||
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
|
||||
@@ -21,7 +21,7 @@ void GamePadController::Init() {
|
||||
SDL_GameController *pController = SDL_GameControllerOpen(i);
|
||||
if (pController) {
|
||||
m_pGameControllers.push_back(pController);
|
||||
m_GamePads.emplace_back();
|
||||
m_GamePads.push_back(GamePad());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,7 +46,7 @@ void GamePadController::Update() {
|
||||
SDL_GameController *pController = SDL_GameControllerOpen(i);
|
||||
if (pController) {
|
||||
m_pGameControllers.push_back(pController);
|
||||
m_GamePads.emplace_back();
|
||||
m_GamePads.push_back(GamePad());
|
||||
|
||||
std::cout << GREEN << "New Controller Connected" << RESET << std::endl;
|
||||
}
|
||||
@@ -64,6 +64,7 @@ void GamePadController::Update() {
|
||||
std::cout << RED << "Controller Disconnected" << RESET << std::endl;
|
||||
--i; // Adjust index after removing the controller
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#include "HitTest.h"
|
||||
|
||||
|
||||
|
||||
float CrossZ(const Vector3& p0, const Vector3& p1, const Vector3& point)
|
||||
{
|
||||
return (p1.x - p0.x) * (point.y - p0.y)
|
||||
@@ -70,4 +68,3 @@ std::optional<Sample> TriangleHitTest(const Vector3& fragPos, const VertexOut& v
|
||||
.mesh = v0.mesh
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "Math/Vector3.h"
|
||||
#include "Math/Vector2.h"
|
||||
#include "Mesh.h"
|
||||
#include "Effects/Effect.h"
|
||||
|
||||
using namespace dae;
|
||||
|
||||
@@ -23,6 +24,6 @@ struct Sample final
|
||||
};
|
||||
|
||||
|
||||
std::optional<Sample> TriangleHitTest(const Vector3& fragPos, const VertexOut& v0, const VertexOut& v1, const VertexOut& v2);
|
||||
std::optional<Sample> TriangleHitTest(const Vector3 &fragPos, const VertexOut &v0, const VertexOut &v1, const VertexOut &v2);
|
||||
|
||||
#endif //GP1_DIRECTX_HITTEST_H
|
||||
|
||||
@@ -302,5 +302,14 @@ namespace dae {
|
||||
data[3] = {vector3, 1};
|
||||
}
|
||||
|
||||
Matrix Matrix::CreateOrthographic(float width, float height, float zn, float zf) {
|
||||
return Matrix(
|
||||
{2.f / width, 0, 0, 0},
|
||||
{0, 2.f / height, 0, 0},
|
||||
{0, 0, 1.f / (zf - zn), 0},
|
||||
{0, 0, -zn / (zf - zn), 1}
|
||||
);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
}
|
||||
@@ -50,7 +50,7 @@ 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);
|
||||
|
||||
static Matrix CreateOrthographic(float width, float height, float zn, float zf);
|
||||
Vector4& operator[](int index);
|
||||
Vector4 operator[](int index) const;
|
||||
Matrix operator*(const Matrix& m) const;
|
||||
|
||||
26
project/src/RenderSettings.h
Normal file
26
project/src/RenderSettings.h
Normal file
@@ -0,0 +1,26 @@
|
||||
//
|
||||
// Created by Bram on 16/01/2025.
|
||||
//
|
||||
|
||||
#ifndef GP1_DIRECTX_RENDERSETTINGS_H
|
||||
#define GP1_DIRECTX_RENDERSETTINGS_H
|
||||
|
||||
#include "Singleton.h"
|
||||
|
||||
class RenderSettings : public Singleton<RenderSettings> {
|
||||
public:
|
||||
void setWidth(int w) { width = w; }
|
||||
void setHeight(int h) { height = h; }
|
||||
int getWidth() const { return width; }
|
||||
int getHeight() const { return height; }
|
||||
|
||||
private:
|
||||
friend class Singleton<RenderSettings>;
|
||||
RenderSettings() : width(1920), height(1080) {} // Default values
|
||||
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
|
||||
|
||||
#endif //GP1_DIRECTX_RENDERSETTINGS_H
|
||||
@@ -10,6 +10,8 @@
|
||||
#include "Scenes/DioramaScene.h"
|
||||
#include "Scenes/InstancedScene.h"
|
||||
#include "Scenes/PlanetScene.h"
|
||||
#include "Scenes/ShadowTestScene.h"
|
||||
#include "BRDF.h"
|
||||
|
||||
|
||||
namespace dae {
|
||||
@@ -36,7 +38,7 @@ namespace dae {
|
||||
|
||||
InitializeSDLRasterizer();
|
||||
|
||||
m_pScene = std::make_unique<MainScene>();
|
||||
m_pScene = std::make_unique<ShadowTestScene>();
|
||||
m_pScene->Initialize(m_DevicePtr, m_DeviceContextPtr, nullptr);
|
||||
|
||||
if (!m_pScene->GetMeshes().empty()) {
|
||||
@@ -148,14 +150,14 @@ namespace dae {
|
||||
m_VerticiesScreenSpace.clear();
|
||||
|
||||
|
||||
for (auto& currentMesh: m_pScene->GetMeshes()) {
|
||||
|
||||
for (auto& currentMeshUP: m_pScene->GetMeshes()) {
|
||||
Mesh* currentMesh = currentMeshUP.get();
|
||||
if (!currentMesh->GetShouldRender()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const Matrix worldViewProjectionMatrix{currentMesh->GetWorldMatrix() * m_Camera.GetViewProjectionMatrix()};
|
||||
VertexTransformationFunction(worldViewProjectionMatrix, currentMesh.get(), currentMesh->GetVertices(), m_VerticiesScreenSpace);
|
||||
VertexTransformationFunction(worldViewProjectionMatrix, currentMesh, currentMesh->GetVertices(), m_VerticiesScreenSpace);
|
||||
|
||||
int numTriangles{};
|
||||
|
||||
@@ -199,14 +201,12 @@ namespace dae {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
const float minX{std::min(vertex0.position.x, std::min(vertex1.position.x, vertex2.position.x))};
|
||||
const float minY{std::min(vertex0.position.y, std::min(vertex1.position.y, vertex2.position.y))};
|
||||
|
||||
const float maxX{std::max(vertex0.position.x, std::max(vertex1.position.x, vertex2.position.x))};
|
||||
const float maxY{std::max(vertex0.position.y, std::max(vertex1.position.y, vertex2.position.y))};
|
||||
|
||||
|
||||
const Vector3 side1{vertex1.position - vertex0.position};
|
||||
const Vector3 side2{vertex2.position - vertex0.position};
|
||||
|
||||
@@ -282,6 +282,7 @@ namespace dae {
|
||||
SDL_UpdateWindowSurface(m_pWindow);
|
||||
}
|
||||
|
||||
|
||||
HRESULT Renderer::InitializeDirectX() {
|
||||
//1. Create device & deviceContext
|
||||
//=====
|
||||
@@ -434,13 +435,14 @@ namespace dae {
|
||||
vertex_out.mesh = mesh;
|
||||
vertex_out.valid = isValid;
|
||||
vertex_out.viewDir = (mesh->GetWorldMatrix().TransformPoint(vertex_out.position)
|
||||
- m_Camera.GetPosition().ToPoint4()).Normalized().GetXYZ();
|
||||
- m_Camera.GetPosition().ToPoint4()).Normalized().GetXYZ();
|
||||
|
||||
vertices_out.push_back(vertex_out);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Renderer::ToggleDepthBuffer() {
|
||||
m_isDepthBuffer = !m_isDepthBuffer;
|
||||
|
||||
@@ -469,10 +471,10 @@ namespace dae {
|
||||
const Vector3 biNormal{Vector3::Cross(normal, sample.tangent)};
|
||||
|
||||
const Matrix tangentToWorld{
|
||||
sample.tangent,
|
||||
biNormal,
|
||||
normal,
|
||||
{0.f, 0.f, 0.f}
|
||||
sample.tangent,
|
||||
biNormal,
|
||||
normal,
|
||||
{0.f, 0.f, 0.f}
|
||||
};
|
||||
|
||||
const ColorRGB normalSample{sample.mesh->GetMaterial()->normalTexturePtr->Sample(sample.uv)};
|
||||
@@ -533,6 +535,8 @@ namespace dae {
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Renderer::CycleCullMode() {
|
||||
for (auto& mesh: m_pScene->GetMeshes()) {
|
||||
mesh->CycleCullMode();
|
||||
@@ -691,6 +695,12 @@ namespace dae {
|
||||
std::cout << MAGENTA << "This could take a second" << RESET << std::endl;
|
||||
break;
|
||||
|
||||
case SceneNames::ShadowTest:
|
||||
m_pScene = std::make_unique<ShadowTestScene>();
|
||||
|
||||
std::cout << MAGENTA << "[SHARED]" << BLUE << " Scene = ShadowTest" << RESET << std::endl;
|
||||
std::cout << MAGENTA << "This could take a second" << RESET << std::endl;
|
||||
|
||||
case SceneNames::Count:
|
||||
break;
|
||||
}
|
||||
|
||||
162
project/src/Scenes/ShadowTestScene.cpp
Normal file
162
project/src/Scenes/ShadowTestScene.cpp
Normal file
@@ -0,0 +1,162 @@
|
||||
//
|
||||
// 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"
|
||||
#include "../RenderSettings.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(RenderSettings::GetInstance().getWidth(), RenderSettings::GetInstance().getHeight());
|
||||
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)->SetShadowMap(shadowMap);
|
||||
dynamic_cast<Effect*>(effect)->SetLightViewProjMatrix(lightWorldViewProj);
|
||||
|
||||
|
||||
dynamic_cast<ShadowMesh*>(mesh)->RenderFinal(devicePtr, worldViewProj);
|
||||
}
|
||||
}
|
||||
|
||||
void ShadowTestScene::Cleanup() {
|
||||
|
||||
|
||||
for (auto *mesh : m_shadowMeshes) {
|
||||
delete mesh;
|
||||
}
|
||||
|
||||
m_shadowMeshes.clear();
|
||||
|
||||
delete m_ShadowMapBuffer;
|
||||
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<Mesh>> & ShadowTestScene::GetMeshes() {
|
||||
return m_Meshes;
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<Material>> &ShadowTestScene::GetMaterials() {
|
||||
return m_Materials;
|
||||
}
|
||||
41
project/src/Scenes/ShadowTestScene.h
Normal file
41
project/src/Scenes/ShadowTestScene.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#ifndef GP1_DIRECTX_SHADOWTESTSCENE_H
|
||||
#define GP1_DIRECTX_SHADOWTESTSCENE_H
|
||||
|
||||
#include "BaseScene.h"
|
||||
#include "../Buffers/ShadowMapBuffer.h"
|
||||
#include "../DirectionalLight.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<std::unique_ptr<Mesh>>& GetMeshes() override;
|
||||
|
||||
std::vector<std::shared_ptr<Material>> &GetMaterials() override;
|
||||
|
||||
private:
|
||||
|
||||
std::vector<std::unique_ptr<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};
|
||||
DirectionalLight m_Light;
|
||||
|
||||
float angle = 0.0f;
|
||||
|
||||
void RenderShadowMapToScreen(ID3D11DeviceContext *devicePtr, ID3D11RenderTargetView *renderTargetViewPtr);
|
||||
};
|
||||
|
||||
|
||||
#endif //GP1_DIRECTX_SHADOWTESTSCENE_H
|
||||
118
project/src/ShadowMesh.cpp
Normal file
118
project/src/ShadowMesh.cpp
Normal 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
63
project/src/ShadowMesh.h
Normal 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
|
||||
30
project/src/Singleton.h
Normal file
30
project/src/Singleton.h
Normal file
@@ -0,0 +1,30 @@
|
||||
//
|
||||
// Created by Bram on 16/01/2025.
|
||||
//
|
||||
|
||||
#ifndef GP1_DIRECTX_SINGLETON_H
|
||||
#define GP1_DIRECTX_SINGLETON_H
|
||||
|
||||
template<typename T>
|
||||
class Singleton {
|
||||
public:
|
||||
static T &GetInstance() {
|
||||
static T instance{};
|
||||
return instance;
|
||||
}
|
||||
|
||||
virtual ~Singleton() = default;
|
||||
|
||||
Singleton(Singleton &&other) = delete;
|
||||
|
||||
Singleton(const Singleton &other) = delete;
|
||||
|
||||
Singleton &operator=(Singleton &&other) = delete;
|
||||
|
||||
Singleton &operator=(const Singleton &other) = delete;
|
||||
|
||||
protected:
|
||||
Singleton() = default;
|
||||
};
|
||||
|
||||
#endif //GP1_DIRECTX_SINGLETON_H
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "Renderer.h"
|
||||
#include "GamePadController.h"
|
||||
#include "Utils.h"
|
||||
#include "RenderSettings.h"
|
||||
|
||||
using namespace dae;
|
||||
|
||||
@@ -129,8 +130,11 @@ int main(int argc, char *args[]) {
|
||||
//Create window + surfaces
|
||||
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK);
|
||||
|
||||
const uint32_t width = 1600;
|
||||
const uint32_t height = 900;
|
||||
const uint32_t width = 640;
|
||||
const uint32_t height = 480;
|
||||
|
||||
RenderSettings::GetInstance().setHeight(height);
|
||||
RenderSettings::GetInstance().setWidth(width);
|
||||
|
||||
//// const uint32_t width = 640;
|
||||
//// const uint32_t height = 480;
|
||||
|
||||
Reference in New Issue
Block a user