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]
Pos=0,0
Size=1536,793
Size=1584,845
Collapsed=0
[Window][Debug##Default]
@@ -57,7 +57,7 @@ Collapsed=0
DockId=0x00000002,0
[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=0x00000005 Parent=0x00000001 SizeRef=1265,842 Split=Y
DockNode ID=0x00000003 Parent=0x00000005 SizeRef=1584,609 Split=X

View File

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

View File

@@ -14,13 +14,11 @@ cbuffer MatrixBuffer
struct VertexInputType
{
float4 position : POSITION;
float2 tex : TEXCOORD0;
};
struct PixelInputType
{
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, projectionMatrix);
// Store the texture coordinates for the pixel shader.
output.tex = input.tex;
return output;
}

View File

@@ -35,14 +35,14 @@ public:
bool initialize(ID3D11Device*, HWND);
void shutdown();
bool render(ID3D11DeviceContext*, int, XMMATRIX, XMMATRIX, XMMATRIX, ID3D11ShaderResourceView*);
bool render(ID3D11DeviceContext*, int, XMMATRIX, XMMATRIX, XMMATRIX);
private:
bool initialize_shader(ID3D11Device*, HWND, WCHAR*, WCHAR*);
void shutdown_shader();
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);
private:
@@ -50,7 +50,6 @@ private:
ID3D11PixelShader* pixel_shader_;
ID3D11InputLayout* layout_;
ID3D11Buffer* matrix_buffer_;
ID3D11SamplerState* sample_state_;
};

View File

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

View File

@@ -544,6 +544,13 @@ private:
* @return True if the refraction was rendered to the texture successfully, false otherwise.
*/
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.
* This function will render the reflection effects, such as water or mirrors, to a texture.
@@ -616,7 +623,7 @@ private :
// ------------------------------------- //
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_;
display_plane_class* display_plane_;
int screen_width_, screen_height_;

View File

@@ -72,6 +72,10 @@ public:
*/
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.
*

View File

@@ -224,6 +224,7 @@ public:
std::stringstream ss;
ss << "RenderComponent:HasModel:"
<< is_shadow_caster_ << ":"
<< diffuse_count << ":" << diffuse_paths_ << ":"
<< normal_count << ":" << normal_paths_ << ":"
<< specular_count << ":" << specular_paths_ << ":"
@@ -252,6 +253,9 @@ public:
if (!std::getline(ss, token, ':') || token != "HasModel")
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;
std::vector<std::wstring> paths_diffuse, paths_normal, paths_specular, paths_alpha;
@@ -328,6 +332,7 @@ public:
*/
void OnImGuiRender() override {
ImGui::Checkbox("Visible", &m_isVisible);
C_BOX("Is shadow caster" , &is_shadow_caster_);
ImGui::Text("Model File Path: %s", m_modelFilePath.c_str());
if (m_model) {
ImGui::Text("Index Count: %d", m_model->GetIndexCount());
@@ -453,6 +458,17 @@ public:
void SetTextureContainer(const TextureContainer& texContainer) { texture_container_buffer = texContainer; }
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:
std::shared_ptr<model_class> m_model;
std::string m_modelFilePath;
@@ -460,6 +476,7 @@ private:
ID3D11Device* device;
ID3D11DeviceContext* context;
TextureContainer texture_container_buffer;
bool is_shadow_caster_ = true;
};
} // 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_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) --- //
// ---------------------------------------------------- //

View File

@@ -7,7 +7,6 @@ depth_shader_class::depth_shader_class()
pixel_shader_ = 0;
layout_ = 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,
XMMATRIX projectionMatrix, ID3D11ShaderResourceView* texture)
XMMATRIX projectionMatrix)
{
bool result;
// 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)
{
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];
unsigned int numElements;
D3D11_BUFFER_DESC matrixBufferDesc;
D3D11_SAMPLER_DESC samplerDesc;
// 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");
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");
@@ -240,13 +216,6 @@ void depth_shader_class::shutdown_shader()
{
LOG_SHUTDOWN("Shutting down shader");
// Release the sampler state.
if (sample_state_)
{
sample_state_->Release();
sample_state_ = 0;
}
// Release the matrix constant 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,
XMMATRIX projectionMatrix, ID3D11ShaderResourceView* texture)
XMMATRIX projectionMatrix)
{
HRESULT result;
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.
deviceContext->VSSetConstantBuffers(bufferNumber, 1, &matrix_buffer_);
// Set shader texture resource in the pixel shader.
deviceContext->PSSetShaderResources(0, 1, &texture);
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.
deviceContext->VSSetShader(vertex_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.
deviceContext->DrawIndexed(indexCount, 0, 0);

View File

@@ -511,13 +511,12 @@ bool shader_manager_class::render_depth_shader(
int indexCount,
XMMATRIX worldMatrix,
XMMATRIX viewMatrix,
XMMATRIX projectionMatrix,
ID3D11ShaderResourceView* texture
XMMATRIX projectionMatrix
)
{
bool result;
result = depth_shader_->render(context, indexCount, worldMatrix, viewMatrix, projectionMatrix, texture);
result = depth_shader_->render(context, indexCount, worldMatrix, viewMatrix, projectionMatrix);
if (!result)
{
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 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)
{
@@ -788,6 +797,12 @@ void application_class::shutdown()
LOG_SHUTDOWN("Stats object released");
}
if (shadow_texture_) {
shadow_texture_->Shutdown();
delete shadow_texture_;
shadow_texture_ = nullptr;
}
LOG_SHUTDOWN("Application class shut down");
}
@@ -929,6 +944,9 @@ bool application_class::frame(input_class* Input)
R_FALSE
}
result = render_shadow_map();
R_LOG_ERROR(result, "Could not render the shadow map")
// Update the mouse strings each frame.
result = update_mouse_strings(mouseX, mouseY, leftMouseDown);
if (!result)
@@ -1025,6 +1043,65 @@ bool application_class::render_reflection_to_texture()
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)
{
XMMATRIX worldMatrix, viewMatrix, projectionMatrix;

View File

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