Well it's something ig

This commit is contained in:
2025-01-15 03:40:39 +01:00
parent 9805c7a2c1
commit 8a3bf57d7e
15 changed files with 295 additions and 46 deletions

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,111 @@
SamplerState gSampleState : SampleState;
RasterizerState gRasterizerState : RastState;
// Transformations
float4x4 gWorldViewProj : WorldViewProjection;
float4x4 gWorldMatrix : WorldMatrix;
float4x4 gLightViewProj : LightViewProjection;
// Textures
texture2D gDiffuseMap : DiffuseMap;
texture2D gNormalMap : Normal;
texture2D gSpecularMap : Specular;
texture2D gGlossMap : Gloss;
texture2D gShadowMap : ShadowMap;
// Light properties
float3 gLightDirection : LightDirection;
float3 gLightColor : LightColor;
float3 gCameraPosition : CameraPosition;
bool gUseNormal : UseNormal;
// Constants
static const float3 gAmbient = float3(.03f, .03f, .03f);
static const float gLightIntensity = 7.f;
static const float PI = 3.14159f;
static const float gSpecularReflectance = 1.f;
static const float gShininess = 25.f;
// Shadow bias to reduce artifacts
static const float gShadowBias = 0.005f;
// 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 LightPosition : TEXCOORD1;
};
VS_OUTPUT VS(VS_INPUT input) {
VS_OUTPUT output = (VS_OUTPUT)0;
output.Position = mul(float4(input.Position, 1.f), gWorldViewProj);
output.WorldPosition = mul(float4(input.Position, 1.f), gWorldMatrix);
output.TexCoord = input.TexCoord;
output.Normal = mul(input.Normal, (float3x3)gWorldMatrix);
output.Tangent = mul(input.Tangent, (float3x3)gWorldMatrix);
output.LightPosition = mul(float4(input.Position, 1.f), gLightViewProj);
return output;
}
float ShadowCalculation(float4 lightPos) {
// Transform light position to shadow map space
float2 shadowCoord = lightPos.xy / lightPos.w;
shadowCoord = shadowCoord * 0.5f + 0.5f;
// Sample the shadow map
float shadowDepth = gShadowMap.Sample(gSampleState, shadowCoord).r;
// Compare depth and apply bias
if (shadowDepth + gShadowBias < lightPos.z / lightPos.w) {
return 0.0f; // In shadow
}
return 1.0f; // Not in shadow
}
float4 PS(VS_OUTPUT input) : SV_TARGET {
// Normalize inputs
float3 normal = normalize(input.Normal);
float3 lightDir = normalize(gLightDirection);
// Diffuse lighting
float NdotL = max(dot(normal, -lightDir), 0.0f);
float3 diffuse = gLightColor * NdotL;
// Shadows
float shadowFactor = ShadowCalculation(input.LightPosition);
// Ambient + Diffuse * Shadow
float3 finalColor = gAmbient + (diffuse * shadowFactor);
// float3 finalColor = float3(shadowFactor,shadowFactor,shadowFactor);
return float4(finalColor, 1.0f);
}
DepthStencilState gDepthStencilState {
DepthEnable = true;
DepthWriteMask = ALL;
DepthFunc = LESS;
StencilEnable = true;
};
technique11 DefaultTechnique {
pass P0 {
SetDepthStencilState(gDepthStencilState, 0);
SetRasterizerState(gRasterizerState);
SetVertexShader(CompileShader(vs_5_0, VS()));
SetGeometryShader(NULL);
SetPixelShader(CompileShader(ps_5_0, PS()));
}
}

View File

@@ -2,14 +2,15 @@ float4x4 gLightWorldViewProj : WorldViewProjection;
float4x4 gWorldViewProj: WorldViewProjection; //For compatibility sake
Texture2D gShadowMap : register(t0); // Shadow map texture
SamplerState gShadowMapSampler : register(s0); // Shadow map sampler
Texture2D gShadowMap : ShadowMap;
SamplerState gShadowMapSampler : ShadowMapSampler;
struct VS_Input
{
struct VS_Input {
float3 Position : POSITION;
float2 TexCoord : TEXCOORD;
float3 Normal : NORMAL;
float3 Tangent : TANGENT;
};
struct VS_Output
{
float4 Position : SV_POSITION;

View File

@@ -13,17 +13,18 @@ DepthBuffer::~DepthBuffer()
bool DepthBuffer::Initialize()
{
// Create a depth buffer
// 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_D32_FLOAT;
desc.Format = DXGI_FORMAT_R32_TYPELESS; // Typeless format
desc.SampleDesc.Count = 1;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
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))
@@ -33,8 +34,9 @@ bool DepthBuffer::Initialize()
// Create DepthStencilView
D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
dsvDesc.Format = DXGI_FORMAT_D32_FLOAT;
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))
{
@@ -42,4 +44,14 @@ bool DepthBuffer::Initialize()
}
return true;
}
}
ID3D11Texture2D* DepthBuffer::GetDepthBuffer()
{
return m_depthBuffer;
}
ID3D11DepthStencilView* DepthBuffer::GetDepthStencilView()
{
return m_depthStencilView;
}

View File

@@ -13,6 +13,10 @@ public:
ID3D11Texture2D* GetDepthBuffer() const { return m_depthBuffer; }
ID3D11DepthStencilView* GetDepthStencilView() const { return m_depthStencilView; }
ID3D11DepthStencilView *GetDepthStencilView();
ID3D11Texture2D *GetDepthBuffer();
private:
ID3D11Device* m_device;
UINT m_width;
@@ -20,6 +24,7 @@ private:
ID3D11Texture2D* m_depthBuffer;
ID3D11DepthStencilView* m_depthStencilView;
};

View File

@@ -20,16 +20,22 @@ bool ShadowMapBuffer::Initialize() {
// Create ShaderResourceView for the depth buffer
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
srvDesc.Format = DXGI_FORMAT_R32_FLOAT;
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)) {
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());
}

View File

@@ -54,6 +54,7 @@ ID3DX11Effect *BaseEffect::LoadEffect(ID3D11Device *devicePtr, const std::wstrin
ss << errorsPtr[i];
OutputDebugStringW(ss.str().c_str());
errorBlobPtr->Release();
errorBlobPtr = nullptr;
return nullptr;

View File

@@ -52,6 +52,14 @@ 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_UseNormalMapVariablePtr->SetBool(m_UseNormalMap);
@@ -202,3 +210,13 @@ 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);
}

View File

@@ -30,6 +30,10 @@ public:
void NextCullMode() override;
void SetShadowMap(ID3D11ShaderResourceView *pView);
void SetShadowMapSampler(ID3D11SamplerState *pState);
private:
void InitSamplers(ID3D11Device* devicePtr);
@@ -52,6 +56,10 @@ private:
ID3DX11EffectRasterizerVariable* m_RasterizerVariablePtr{};
ID3DX11EffectShaderResourceVariable* m_ShadowMapVariablePtr{};
ID3DX11EffectSamplerVariable* m_ShadowMapSamplerVariablePtr{};
TechniqueType m_TechniqueType{TechniqueType::Linear};
std::array<ID3D11SamplerState*, 3> m_SamplerStates{};

View File

@@ -21,6 +21,7 @@ void Light::SetUp(const dae::Vector3 &up) {
}
dae::Matrix Light::GetViewMatrix() const {
auto test = dae::Matrix::CreateLookAtLH(m_Position, m_Target, m_Up);
return dae::Matrix::CreateLookAtLH(m_Position, m_Target, m_Up);
}

View File

@@ -144,24 +144,42 @@ namespace dae {
return out;
}
Matrix Matrix::CreateLookAtLH(const Vector3& origin, const Vector3& forward, const Vector3& up)
{
Vector3 zAxis = (forward - origin).Normalized();
Vector3 xAxis = Vector3::Cross(up, zAxis).Normalized();
Matrix Matrix::CreateLookAtLH(const Vector3& origin, const Vector3& forward, const Vector3& up) {
// Calculate the z-axis (view direction)
Vector3 zAxis = forward - origin;
if (zAxis.SqrMagnitude() < 1e-6f) {
// Avoid NaN by ensuring the forward and origin are not the same
zAxis = Vector3(0, 0, 1); // Default to a valid direction
}
zAxis = zAxis.Normalized();
// Calculate the x-axis (right direction)
Vector3 xAxis = Vector3::Cross(up, zAxis);
if (xAxis.SqrMagnitude() < 1e-6f) {
// Handle the case where up is parallel to zAxis
Vector3 alternateUp = (std::abs(up.x) > 0.9f) ? Vector3(0, 1, 0) : Vector3(1, 0, 0);
xAxis = Vector3::Cross(alternateUp, zAxis);
}
xAxis = xAxis.Normalized();
// Calculate the y-axis (up direction)
Vector3 yAxis = Vector3::Cross(zAxis, xAxis).Normalized();
Vector3 trans =
{
-Vector3::Dot(xAxis, origin),
-Vector3::Dot(yAxis, origin),
-Vector3::Dot(zAxis, origin)
};
return {
{xAxis.x, yAxis.x, zAxis.x},
{xAxis.y, yAxis.y, zAxis.y},
{xAxis.z, yAxis.z, zAxis.z},
{trans.x, trans.y, trans.z}
// Calculate the translation
Vector3 trans = {
-Vector3::Dot(xAxis, origin),
-Vector3::Dot(yAxis, origin),
-Vector3::Dot(zAxis, origin)
};
}
// Return the look-at matrix in row-major order
return {
{xAxis.x, yAxis.x, zAxis.x, 0.0f},
{xAxis.y, yAxis.y, zAxis.y, 0.0f},
{xAxis.z, yAxis.z, zAxis.z, 0.0f},
{trans.x, trans.y, trans.z, 1.0f}
};
}
Matrix Matrix::CreatePerspectiveFovLH(float fovy, float aspect, float zn, float zf)
{

View File

@@ -113,28 +113,49 @@ 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");
}

View File

@@ -10,26 +10,31 @@
void ShadowTestScene::Initialize(ID3D11Device *DevicePtr, ID3D11DeviceContext *DeviceContextPtr, Camera *camera) {
// Initialize shadow map buffer
m_ShadowMapBuffer = new ShadowMapBuffer(DevicePtr, 1024, 1024); // Example resolution: 1024x1024
m_ShadowMapBuffer->Initialize();
if(!m_ShadowMapBuffer->Initialize()){
assert(true && "Shadow map buffer failed to initialize");
}
// Initialize light source
m_Light.SetPosition({0.0f, 10.0f, 0.0f});
m_Light.SetTarget({0.0f, 0.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)){
if(!Utils::ParseOBJNew("resources/scene.obj", vertices, indices, true)){
assert(true && "Model failed to load");
}
auto shadowEffect = new ShadowEffect(DevicePtr, L"resources/shadowEffect.fx");
auto otherEffect = new Effect(DevicePtr, L"resources/SimpleDiffuse.fx");
auto otherEffect = new Effect(DevicePtr, L"resources/SuperSimpleDiffuse.fx");
auto shadowMesh = new ShadowMesh(DevicePtr, vertices, indices, std::make_shared<Material>(), shadowEffect, otherEffect);
//Move forward 100
shadowMesh->SetWorldMatrix(Matrix::CreateTranslation(Vector3(0, -5, 40)));
m_shadowMeshes.push_back(shadowMesh);
// m_shadowMaterials.push_back(material);
}
@@ -41,17 +46,43 @@ void ShadowTestScene::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
// D3D11_VIEWPORT shadowViewport = {};
// shadowViewport.Width = static_cast<float>(1024);
// shadowViewport.Height = static_cast<float>(1024);
// shadowViewport.MinDepth = 0.0f;
// shadowViewport.MaxDepth = 1.0f;
// devicePtr->RSSetViewports(1, &shadowViewport);
devicePtr->OMSetRenderTargets(0, nullptr, m_ShadowMapBuffer->GetDepthStencilView());
devicePtr->ClearDepthStencilView(m_ShadowMapBuffer->GetDepthStencilView(), D3D11_CLEAR_DEPTH, 1.0f, 0);
ID3D11ShaderResourceView* shadowMap = m_ShadowMapBuffer->GetShaderResourceView();
devicePtr->PSSetShaderResources(0, 1, &shadowMap);
ID3D11SamplerState* shadowSampler = m_ShadowMapBuffer->GetSamplerState();
devicePtr->PSSetSamplers(0, 1, &shadowSampler);
for (auto* mesh : m_shadowMeshes) {
Matrix lightWorldViewProj = mesh->GetWorldMatrix() * m_Light.GetViewProjectionMatrix();
dynamic_cast<ShadowMesh*>(mesh)->RenderShadow(devicePtr, lightWorldViewProj);
}
ID3D11DepthStencilView* nullDepthStencilView = nullptr;
devicePtr->OMSetRenderTargets(1, &renderTargetViewPtr, nullDepthStencilView);
devicePtr->OMSetRenderTargets(1, &renderTargetViewPtr, depthStencilViewPtr);
for (auto* mesh : m_shadowMeshes) {
Matrix worldViewProj = mesh->GetWorldMatrix() * camera.GetViewProjectionMatrix();
auto* effect = dynamic_cast<ShadowMesh*>(mesh)->GetColorEffectPtr() ;
// effect->SetLightWorldViewProjMatrix(m_Light.GetViewProjectionMatrix());
dynamic_cast<Effect*>(effect)->SetWorldMatrix(worldViewProj);
dynamic_cast<Effect*>(effect)->SetShadowMapSampler(shadowSampler);
dynamic_cast<Effect*>(effect)->SetShadowMap(shadowMap);
dynamic_cast<ShadowMesh*>(mesh)->RenderFinal(devicePtr, worldViewProj);
}
}

View File

@@ -17,6 +17,7 @@ ShadowMesh::ShadowMesh(ID3D11Device* devicePtr,
HRESULT result;
// Create input layout
D3D11_INPUT_ELEMENT_DESC vertexDesc[] = {
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
@@ -26,7 +27,7 @@ ShadowMesh::ShadowMesh(ID3D11Device* devicePtr,
};
D3DX11_PASS_DESC passDesc;
ID3DX11EffectTechnique* techniquePtr = m_ShadowEffectPtr->GetTechniquePtr();
ID3DX11EffectTechnique* techniquePtr = m_ColorEffectPtr->GetTechniquePtr();
techniquePtr->GetPassByIndex(0)->GetDesc(&passDesc);
result = devicePtr->CreateInputLayout(vertexDesc, ARRAYSIZE(vertexDesc),
@@ -34,6 +35,7 @@ ShadowMesh::ShadowMesh(ID3D11Device* devicePtr,
&m_InputLayoutPtr);
assert(result == S_OK && "Creating input layout failed");
// Create vertex buffer
D3D11_BUFFER_DESC bufferDesc = {};
bufferDesc.Usage = D3D11_USAGE_IMMUTABLE;

View File

@@ -25,6 +25,10 @@ public:
void SetWorldMatrix(const Matrix& matrix);
Matrix GetWorldMatrix() const;
ShadowEffect* GetShadowEffectPtr(){ return m_ShadowEffectPtr; }
BaseEffect* GetColorEffectPtr(){ return m_ColorEffectPtr; }
private:
// Shadow effect
ShadowEffect* m_ShadowEffectPtr;
@@ -37,6 +41,12 @@ private:
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;