Minor - Implémente le rendu des ombres - V14.6.0

Ajoute la possibilité de rendre une shadow map pour les objets de la scène.
Supprime la dépendance de la texture du depth shader et ajoute une option pour caster les ombres sur les RenderComponents.
Modifie la taille de la fenêtre dans l'imgui.ini
This commit is contained in:
2025-10-14 13:33:30 +02:00
parent 13fc189ee8
commit ba7d0ca27e
15 changed files with 126 additions and 59 deletions

View File

@@ -1,6 +1,6 @@
[Window][DockSpace] [Window][DockSpace]
Pos=0,0 Pos=0,0
Size=1536,793 Size=1584,845
Collapsed=0 Collapsed=0
[Window][Debug##Default] [Window][Debug##Default]
@@ -57,7 +57,7 @@ Collapsed=0
DockId=0x00000002,0 DockId=0x00000002,0
[Docking][Data] [Docking][Data]
DockSpace ID=0xCCBD8CF7 Window=0x3DA2F1DE Pos=0,19 Size=1536,774 Split=X DockSpace ID=0xCCBD8CF7 Window=0x3DA2F1DE Pos=0,19 Size=1584,826 Split=X
DockNode ID=0x00000001 Parent=0xCCBD8CF7 SizeRef=1350,842 Split=X DockNode ID=0x00000001 Parent=0xCCBD8CF7 SizeRef=1350,842 Split=X
DockNode ID=0x00000005 Parent=0x00000001 SizeRef=1265,842 Split=Y DockNode ID=0x00000005 Parent=0x00000001 SizeRef=1265,842 Split=Y
DockNode ID=0x00000003 Parent=0x00000005 SizeRef=1584,609 Split=X DockNode ID=0x00000003 Parent=0x00000005 SizeRef=1584,609 Split=X

View File

@@ -1,8 +1,6 @@
///////////// /////////////
// GLOBALS // // GLOBALS //
///////////// /////////////
Texture2D shaderTexture : register(t0);
SamplerState SampleType : register(s0);
////////////// //////////////
// TYPEDEFS // // TYPEDEFS //
@@ -10,7 +8,6 @@ SamplerState SampleType : register(s0);
struct PixelInputType struct PixelInputType
{ {
float4 position : SV_POSITION; float4 position : SV_POSITION;
float2 tex : TEXCOORD0;
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@@ -14,13 +14,11 @@ cbuffer MatrixBuffer
struct VertexInputType struct VertexInputType
{ {
float4 position : POSITION; float4 position : POSITION;
float2 tex : TEXCOORD0;
}; };
struct PixelInputType struct PixelInputType
{ {
float4 position : SV_POSITION; float4 position : SV_POSITION;
float2 tex : TEXCOORD0;
}; };
@@ -40,8 +38,5 @@ PixelInputType DepthVertexShader(VertexInputType input)
output.position = mul(output.position, viewMatrix); output.position = mul(output.position, viewMatrix);
output.position = mul(output.position, projectionMatrix); output.position = mul(output.position, projectionMatrix);
// Store the texture coordinates for the pixel shader.
output.tex = input.tex;
return output; return output;
} }

View File

@@ -35,14 +35,14 @@ public:
bool initialize(ID3D11Device*, HWND); bool initialize(ID3D11Device*, HWND);
void shutdown(); void shutdown();
bool render(ID3D11DeviceContext*, int, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*); bool render(ID3D11DeviceContext*, int, XMMATRIX, XMMATRIX, XMMATRIX);
private: private:
bool initialize_shader(ID3D11Device*, HWND, WCHAR*, WCHAR*); bool initialize_shader(ID3D11Device*, HWND, WCHAR*, WCHAR*);
void shutdown_shader(); void shutdown_shader();
void output_shader_error_message(ID3D10Blob*, HWND, WCHAR*); void output_shader_error_message(ID3D10Blob*, HWND, WCHAR*);
bool set_shader_parameters(ID3D11DeviceContext*, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*); bool set_shader_parameters(ID3D11DeviceContext*, XMMATRIX, XMMATRIX, XMMATRIX);
void render_shader(ID3D11DeviceContext*, int); void render_shader(ID3D11DeviceContext*, int);
private: private:
@@ -50,7 +50,6 @@ private:
ID3D11PixelShader* pixel_shader_; ID3D11PixelShader* pixel_shader_;
ID3D11InputLayout* layout_; ID3D11InputLayout* layout_;
ID3D11Buffer* matrix_buffer_; ID3D11Buffer* matrix_buffer_;
ID3D11SamplerState* sample_state_;
}; };

View File

@@ -54,8 +54,7 @@ public:
int indexCount, int indexCount,
XMMATRIX worldMatrix, XMMATRIX worldMatrix,
XMMATRIX viewMatrix, XMMATRIX viewMatrix,
XMMATRIX projectionMatrix, XMMATRIX projectionMatrix
ID3D11ShaderResourceView* texture
); );
private: private:

View File

@@ -544,6 +544,13 @@ private:
* @return True if the refraction was rendered to the texture successfully, false otherwise. * @return True if the refraction was rendered to the texture successfully, false otherwise.
*/ */
bool render_refraction_to_texture(); bool render_refraction_to_texture();
/**
* Render the shadow map texture for the scene.
* @return True if the shadow map was rendered successfully, false otherwise.
*/
bool render_shadow_map();
/** /**
* Render the reflection of the scene to a texture. * Render the reflection of the scene to a texture.
* This function will render the reflection effects, such as water or mirrors, to a texture. * This function will render the reflection effects, such as water or mirrors, to a texture.
@@ -616,7 +623,7 @@ private :
// ------------------------------------- // // ------------------------------------- //
XMMATRIX base_view_matrix_; XMMATRIX base_view_matrix_;
render_texture_class* render_texture_, * refraction_texture_, * reflection_texture_; render_texture_class* render_texture_, * refraction_texture_, * reflection_texture_,* shadow_texture_ ;
render_texture_class* scene_texture_; render_texture_class* scene_texture_;
display_plane_class* display_plane_; display_plane_class* display_plane_;
int screen_width_, screen_height_; int screen_width_, screen_height_;

View File

@@ -72,6 +72,10 @@ public:
*/ */
XMMATRIX get_view_matrix(XMMATRIX& view_matrix) const; XMMATRIX get_view_matrix(XMMATRIX& view_matrix) const;
/**
* Update the camera's view matrix without
*/
/** /**
* @brief Renders the reflection of the scene from the camera's perspective. * @brief Renders the reflection of the scene from the camera's perspective.
* *

View File

@@ -224,6 +224,7 @@ public:
std::stringstream ss; std::stringstream ss;
ss << "RenderComponent:HasModel:" ss << "RenderComponent:HasModel:"
<< is_shadow_caster_ << ":"
<< diffuse_count << ":" << diffuse_paths_ << ":" << diffuse_count << ":" << diffuse_paths_ << ":"
<< normal_count << ":" << normal_paths_ << ":" << normal_count << ":" << normal_paths_ << ":"
<< specular_count << ":" << specular_paths_ << ":" << specular_count << ":" << specular_paths_ << ":"
@@ -252,6 +253,9 @@ public:
if (!std::getline(ss, token, ':') || token != "HasModel") if (!std::getline(ss, token, ':') || token != "HasModel")
R_FALSE R_FALSE
std::getline(ss,token, ':');
is_shadow_caster_ = std::stoi(token);
int diffuse_count = 0, normal_count = 0, specular_count = 0, alpha_count = 0; int diffuse_count = 0, normal_count = 0, specular_count = 0, alpha_count = 0;
std::vector<std::wstring> paths_diffuse, paths_normal, paths_specular, paths_alpha; std::vector<std::wstring> paths_diffuse, paths_normal, paths_specular, paths_alpha;
@@ -328,6 +332,7 @@ public:
*/ */
void OnImGuiRender() override { void OnImGuiRender() override {
ImGui::Checkbox("Visible", &m_isVisible); ImGui::Checkbox("Visible", &m_isVisible);
C_BOX("Is shadow caster" , &is_shadow_caster_);
ImGui::Text("Model File Path: %s", m_modelFilePath.c_str()); ImGui::Text("Model File Path: %s", m_modelFilePath.c_str());
if (m_model) { if (m_model) {
ImGui::Text("Index Count: %d", m_model->GetIndexCount()); ImGui::Text("Index Count: %d", m_model->GetIndexCount());
@@ -453,6 +458,17 @@ public:
void SetTextureContainer(const TextureContainer& texContainer) { texture_container_buffer = texContainer; } void SetTextureContainer(const TextureContainer& texContainer) { texture_container_buffer = texContainer; }
const TextureContainer& GetTextureContainerBuffer() const { return texture_container_buffer; } const TextureContainer& GetTextureContainerBuffer() const { return texture_container_buffer; }
/**
* Get whether the model casts shadows.
* @return True if the model casts shadows, false otherwise.
*/
bool IsShadowCaster() const { return is_shadow_caster_; }
/**
* Set whether the model casts shadows.
* @param isCaster True to make the model cast shadows, false otherwise.
*/
void SetShadowCaster(bool isCaster) { is_shadow_caster_ = isCaster; }
private: private:
std::shared_ptr<model_class> m_model; std::shared_ptr<model_class> m_model;
std::string m_modelFilePath; std::string m_modelFilePath;
@@ -460,6 +476,7 @@ private:
ID3D11Device* device; ID3D11Device* device;
ID3D11DeviceContext* context; ID3D11DeviceContext* context;
TextureContainer texture_container_buffer; TextureContainer texture_container_buffer;
bool is_shadow_caster_ = true;
}; };
} // namespace ecs } // namespace ecs

View File

@@ -52,6 +52,12 @@ inline int size_t_to_int(size_t x)
#define LOG_SHUTDOWN(msg) Logger::Get().Log(msg, __FILE__, __LINE__, Logger::LogLevel::Shutdown) #define LOG_SHUTDOWN(msg) Logger::Get().Log(msg, __FILE__, __LINE__, Logger::LogLevel::Shutdown)
#define LOG_INIT(msg) Logger::Get().Log(msg, __FILE__, __LINE__, Logger::LogLevel::Initialize) #define LOG_INIT(msg) Logger::Get().Log(msg, __FILE__, __LINE__, Logger::LogLevel::Initialize)
#define R_LOG_ERROR(result,msg) \
if(!(result)) { \
LOG_ERROR(msg); \
return false; \
}
// ---------------------------------------------------- // // ---------------------------------------------------- //
// --- Macros for the Entity Component System (ECS) --- // // --- Macros for the Entity Component System (ECS) --- //
// ---------------------------------------------------- // // ---------------------------------------------------- //

View File

@@ -7,7 +7,6 @@ depth_shader_class::depth_shader_class()
pixel_shader_ = 0; pixel_shader_ = 0;
layout_ = 0; layout_ = 0;
matrix_buffer_ = 0; matrix_buffer_ = 0;
sample_state_ = 0;
} }
@@ -67,12 +66,12 @@ void depth_shader_class::shutdown()
} }
bool depth_shader_class::render(ID3D11DeviceContext* deviceContext, int indexCount, XMMATRIX worldMatrix, XMMATRIX viewMatrix, bool depth_shader_class::render(ID3D11DeviceContext* deviceContext, int indexCount, XMMATRIX worldMatrix, XMMATRIX viewMatrix,
XMMATRIX projectionMatrix, ID3D11ShaderResourceView* texture) XMMATRIX projectionMatrix)
{ {
bool result; bool result;
// Set the shader parameters that it will use for rendering. // Set the shader parameters that it will use for rendering.
result = set_shader_parameters(deviceContext, worldMatrix, viewMatrix, projectionMatrix, texture); result = set_shader_parameters(deviceContext, worldMatrix, viewMatrix, projectionMatrix);
if (!result) if (!result)
{ {
LOG_ERROR("Error setting shader parameters"); LOG_ERROR("Error setting shader parameters");
@@ -96,7 +95,6 @@ bool depth_shader_class::initialize_shader(ID3D11Device* device, HWND hwnd, WCHA
D3D11_INPUT_ELEMENT_DESC polygonLayout[2]; D3D11_INPUT_ELEMENT_DESC polygonLayout[2];
unsigned int numElements; unsigned int numElements;
D3D11_BUFFER_DESC matrixBufferDesc; D3D11_BUFFER_DESC matrixBufferDesc;
D3D11_SAMPLER_DESC samplerDesc;
// initialize the pointers this function will use to null. // initialize the pointers this function will use to null.
@@ -208,28 +206,6 @@ bool depth_shader_class::initialize_shader(ID3D11Device* device, HWND hwnd, WCHA
LOG_ERROR("Error creating constant buffer"); LOG_ERROR("Error creating constant buffer");
R_FALSE R_FALSE
} }
// Create a texture sampler state description.
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
samplerDesc.MipLODBias = 0.0f;
samplerDesc.MaxAnisotropy = 1;
samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
samplerDesc.BorderColor[0] = 0;
samplerDesc.BorderColor[1] = 0;
samplerDesc.BorderColor[2] = 0;
samplerDesc.BorderColor[3] = 0;
samplerDesc.MinLOD = 0;
samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
// Create the texture sampler state.
result = device->CreateSamplerState(&samplerDesc, &sample_state_);
if (FAILED(result))
{
LOG_ERROR("Error creating sampler state");
R_FALSE
}
LOG_INIT("Shader initialized"); LOG_INIT("Shader initialized");
@@ -240,13 +216,6 @@ void depth_shader_class::shutdown_shader()
{ {
LOG_SHUTDOWN("Shutting down shader"); LOG_SHUTDOWN("Shutting down shader");
// Release the sampler state.
if (sample_state_)
{
sample_state_->Release();
sample_state_ = 0;
}
// Release the matrix constant buffer. // Release the matrix constant buffer.
if (matrix_buffer_) if (matrix_buffer_)
{ {
@@ -316,7 +285,7 @@ void depth_shader_class::output_shader_error_message(ID3D10Blob* errorMessage, H
} }
bool depth_shader_class::set_shader_parameters(ID3D11DeviceContext* deviceContext, XMMATRIX worldMatrix, XMMATRIX viewMatrix, bool depth_shader_class::set_shader_parameters(ID3D11DeviceContext* deviceContext, XMMATRIX worldMatrix, XMMATRIX viewMatrix,
XMMATRIX projectionMatrix, ID3D11ShaderResourceView* texture) XMMATRIX projectionMatrix)
{ {
HRESULT result; HRESULT result;
D3D11_MAPPED_SUBRESOURCE mappedResource; D3D11_MAPPED_SUBRESOURCE mappedResource;
@@ -353,8 +322,6 @@ bool depth_shader_class::set_shader_parameters(ID3D11DeviceContext* deviceContex
// Finanly set the constant buffer in the vertex shader with the updated values. // Finanly set the constant buffer in the vertex shader with the updated values.
deviceContext->VSSetConstantBuffers(bufferNumber, 1, &matrix_buffer_); deviceContext->VSSetConstantBuffers(bufferNumber, 1, &matrix_buffer_);
// Set shader texture resource in the pixel shader.
deviceContext->PSSetShaderResources(0, 1, &texture);
R_TRUE R_TRUE
} }
@@ -367,8 +334,6 @@ void depth_shader_class::render_shader(ID3D11DeviceContext* deviceContext, int i
// Set the vertex and pixel shaders that will be used to render this triangle. // Set the vertex and pixel shaders that will be used to render this triangle.
deviceContext->VSSetShader(vertex_shader_, NULL, 0); deviceContext->VSSetShader(vertex_shader_, NULL, 0);
deviceContext->PSSetShader(pixel_shader_, NULL, 0); deviceContext->PSSetShader(pixel_shader_, NULL, 0);
// Set the sampler state in the pixel shader.
deviceContext->PSSetSamplers(0, 1, &sample_state_);
// render the triangle. // render the triangle.
deviceContext->DrawIndexed(indexCount, 0, 0); deviceContext->DrawIndexed(indexCount, 0, 0);

View File

@@ -511,13 +511,12 @@ bool shader_manager_class::render_depth_shader(
int indexCount, int indexCount,
XMMATRIX worldMatrix, XMMATRIX worldMatrix,
XMMATRIX viewMatrix, XMMATRIX viewMatrix,
XMMATRIX projectionMatrix, XMMATRIX projectionMatrix
ID3D11ShaderResourceView* texture
) )
{ {
bool result; bool result;
result = depth_shader_->render(context, indexCount, worldMatrix, viewMatrix, projectionMatrix, texture); result = depth_shader_->render(context, indexCount, worldMatrix, viewMatrix, projectionMatrix);
if (!result) if (!result)
{ {
LOG_ERROR("Error rendering depth_shader_class"); LOG_ERROR("Error rendering depth_shader_class");

View File

@@ -529,6 +529,15 @@ bool application_class::initialize(int screenWidth, int screenHeight, HWND hwnd,
create_skysphere(); create_skysphere();
// create the render textures for the shadow map
shadow_texture_ = new render_texture_class();
result = shadow_texture_->Initialize(direct_3d_->get_device(), 2048, 2048, screen_depth, screen_near, 1);
if (!result)
{
LOG_ERROR("Could not initialize the shadow map render texture object");
R_FALSE
}
} }
catch (const std::exception& e) catch (const std::exception& e)
{ {
@@ -788,6 +797,12 @@ void application_class::shutdown()
LOG_SHUTDOWN("Stats object released"); LOG_SHUTDOWN("Stats object released");
} }
if (shadow_texture_) {
shadow_texture_->Shutdown();
delete shadow_texture_;
shadow_texture_ = nullptr;
}
LOG_SHUTDOWN("Application class shut down"); LOG_SHUTDOWN("Application class shut down");
} }
@@ -929,6 +944,9 @@ bool application_class::frame(input_class* Input)
R_FALSE R_FALSE
} }
result = render_shadow_map();
R_LOG_ERROR(result, "Could not render the shadow map")
// Update the mouse strings each frame. // Update the mouse strings each frame.
result = update_mouse_strings(mouseX, mouseY, leftMouseDown); result = update_mouse_strings(mouseX, mouseY, leftMouseDown);
if (!result) if (!result)
@@ -1025,6 +1043,65 @@ bool application_class::render_reflection_to_texture()
R_TRUE R_TRUE
} }
bool application_class::render_shadow_map()
{
XMMATRIX light_viewMatrix, light_projectionMatrix;
bool result;
shadow_texture_->SetRenderTarget(direct_3d_->get_device_context());
shadow_texture_->ClearRenderTarget(direct_3d_->get_device_context(), 1.0f, 1.0f, 1.0f, 1.0f);
sun_camera_->render(); // Generate the view matrix based on the camera's position.
sun_camera_->get_view_matrix(light_viewMatrix);
shadow_texture_->GetProjectionMatrix(light_projectionMatrix);
for (auto& entity : entity_manager_->GetAllEntities()) {
auto render_cpnt = entity->GetComponent<ecs::RenderComponent>();
if (!render_cpnt) continue;
auto transform_cpnt = entity->GetComponent<ecs::TransformComponent>();
if (!transform_cpnt) continue;
if (render_cpnt->IsShadowCaster())
{
// Prepare the world matrix.
XMMATRIX tra, rot, scl;
tra = transform_cpnt->GetTranslateMatrix();
rot = transform_cpnt->GetRotateMatrix();
scl = transform_cpnt->GetScaleMatrix();
XMMATRIX worldMat = XMMatrixMultiply(
XMMatrixMultiply(scl, rot),
tra
);
// Render the geometry of the model
render_cpnt->Render(direct_3d_->get_device_context());
// render using the depth shader to create the shadow map
result = shader_manager_->render_depth_shader(
direct_3d_->get_device_context(),
render_cpnt->GetIndexCount(),
worldMat,
light_viewMatrix,
light_projectionMatrix
);
R_LOG_ERROR(result, "Could not render the model using the depth shader")
}
}
direct_3d_->set_back_buffer_render_target();
direct_3d_->reset_viewport();
R_TRUE;
}
bool application_class::render_scene_to_texture(float rotation) bool application_class::render_scene_to_texture(float rotation)
{ {
XMMATRIX worldMatrix, viewMatrix, projectionMatrix; XMMATRIX worldMatrix, viewMatrix, projectionMatrix;

View File

@@ -114,6 +114,8 @@ void camera_class::render()
return; return;
} }
XMMATRIX camera_class::get_view_matrix(XMMATRIX& view_matrix) const XMMATRIX camera_class::get_view_matrix(XMMATRIX& view_matrix) const
{ {
view_matrix = view_matrix_; view_matrix = view_matrix_;

BIN
x64/Debug/config.txt (Stored with Git LFS)

Binary file not shown.

BIN
x64/Release/config.txt (Stored with Git LFS)

Binary file not shown.