Minor - Rework skysphere from Object to Entity - V14.2.0

Introduces a skysphere entity to the scene.
Creates the skysphere during application initialization and manages its visibility via Z-buffer enabling/disabling in the render system.
The skysphere is now an ECS entity.
The culling thread skips the skybox entity to avoid unnecessary calculations since it's always visible.
The position of the skybox is updated with the active camera.
This commit is contained in:
2025-09-29 19:08:43 +02:00
parent a3d80256f5
commit 4b47346208
6 changed files with 117 additions and 79 deletions

View File

@@ -450,6 +450,8 @@ public:
* @return A reference to the global model cache as a map of strings to shared pointers of model_class. * @return A reference to the global model cache as a map of strings to shared pointers of model_class.
*/ */
std::map<std::string, std::shared_ptr<model_class>>& get_model_cache() { return g_model_cache; } std::map<std::string, std::shared_ptr<model_class>>& get_model_cache() { return g_model_cache; }
int get_sky_id() const { return sky_id_; }
private: private:
/** /**
@@ -530,6 +532,11 @@ private:
* The thread function for culling objects in the scene. * The thread function for culling objects in the scene.
*/ */
void culling_thread_function(); void culling_thread_function();
/**
* Create the skysphere entity.
*/
bool create_skysphere();
public : public :
std::vector<ID3D11ShaderResourceView*> textures; std::vector<ID3D11ShaderResourceView*> textures;
@@ -587,7 +594,9 @@ private :
float speed_ = 0.1f; // speed for the demo spinning object float speed_ = 0.1f; // speed for the demo spinning object
std::vector<object*> imported_object_; std::vector<object*> imported_object_;
int object_id_ = 0; int object_id_ = 0;
std::vector<object*> skybox_; //std::vector<object*> skybox_;
int sky_id_ = -1;
std::shared_ptr<ecs::Entity> sky_entity_;
// ----------------------------------- // // ----------------------------------- //
// ------------- LIGHTS -------------- // // ------------- LIGHTS -------------- //

View File

@@ -178,6 +178,9 @@ public:
ID3D11Device* GetDevice() const { return device; } ID3D11Device* GetDevice() const { return device; }
ID3D11DeviceContext* GetContext() const { return context; } ID3D11DeviceContext* GetContext() const { return context; }
int GetSkyID() const { return sky_id_; }
void SetSkyID(int id) { sky_id_ = id; }
private: private:
EntityID m_NextEntityID; EntityID m_NextEntityID;
std::unordered_map<EntityID, std::shared_ptr<Entity>> m_Entities; std::unordered_map<EntityID, std::shared_ptr<Entity>> m_Entities;
@@ -186,6 +189,7 @@ private:
FMOD::System* sound_system_ = nullptr; FMOD::System* sound_system_ = nullptr;
ID3D11Device* device; ID3D11Device* device;
ID3D11DeviceContext* context; ID3D11DeviceContext* context;
int sky_id_ = -1;
}; };
} // namespace ecs } // namespace ecs

View File

@@ -238,6 +238,16 @@ public:
// V<>rifier si le mod<6F>le est visible // V<>rifier si le mod<6F>le est visible
if (!render->IsVisible()) continue; if (!render->IsVisible()) continue;
// check if the id the sky id to disabled the z buffer
if (entity->GetID() == entityManager->GetSkyID())
{
// D<>sactiver le Z-buffer pour le skysphere
m_deviceContext->OMSetDepthStencilState(nullptr, 0);
} else {
// Activer le Z-buffer pour les autres entit<69>s
m_deviceContext->OMSetDepthStencilState(nullptr, 1);
}
// Effectuer le rendu // Effectuer le rendu
if (RenderEntity(entity, viewMatrix, projectionMatrix, if (RenderEntity(entity, viewMatrix, projectionMatrix,
diffuseColors, lightPositions, ambientColors,cameraPos, diffuseColors, lightPositions, ambientColors,cameraPos,

View File

@@ -28,7 +28,6 @@ application_class::application_class() : should_quit_(false)
reflection_texture_ = nullptr; reflection_texture_ = nullptr;
scene_texture_ = nullptr; scene_texture_ = nullptr;
physics_ = nullptr; physics_ = nullptr;
skybox_.clear();
lights_.clear(); lights_.clear();
sun_light_ = nullptr; sun_light_ = nullptr;
swap_chain_ = nullptr; swap_chain_ = nullptr;
@@ -498,9 +497,6 @@ bool application_class::initialize(int screenWidth, int screenHeight, HWND hwnd,
physics_thread_ = std::thread(&application_class::physics_thread_function, this); physics_thread_ = std::thread(&application_class::physics_thread_function, this);
//ConstructSkyboxWithPlanes(); //ConstructSkyboxWithPlanes();
Skybox* skybox = new Skybox;
skybox->Initialize(direct_3d_);
skybox_.push_back(skybox->ConstructSkybox(this));
culling_active_ = true; culling_active_ = true;
culling_thread_ = std::thread(&application_class::culling_thread_function, this); culling_thread_ = std::thread(&application_class::culling_thread_function, this);
@@ -523,12 +519,13 @@ bool application_class::initialize(int screenWidth, int screenHeight, HWND hwnd,
entity_manager_->SetSoundSystem(sound_system_); entity_manager_->SetSoundSystem(sound_system_);
entity_manager_->SetDevice(direct_3d_->get_device()); entity_manager_->SetDevice(direct_3d_->get_device());
entity_manager_->SetContext(direct_3d_->get_device_context()); entity_manager_->SetContext(direct_3d_->get_device_context());
create_skysphere();
} }
catch (const std::exception& e) catch (const std::exception& e)
{ {
Logger::Get().Log(std::string("Exception caught during initialization: ") + e.what(), __FILE__, __LINE__, Logger::LogLevel::Error); Logger::Get().Log(std::string("Exception caught during initialization: ") + e.what() , __FILE__, __LINE__, Logger::LogLevel::Error);
return false; return false;
} }
Logger::Get().Log("Application class initialized", __FILE__, __LINE__, Logger::LogLevel::Initialize); Logger::Get().Log("Application class initialized", __FILE__, __LINE__, Logger::LogLevel::Initialize);
@@ -1800,23 +1797,18 @@ void application_class::culling_thread_function()
// Construction du frustum une fois par cycle de culling // Construction du frustum une fois par cycle de culling
construct_frustum(); construct_frustum();
// S'assurer que la skybox est toujours visible
{
std::lock_guard<std::mutex> lock(objects_mutex_);
for (auto* skyboxObject : skybox_)
{
if (skyboxObject)
{
skyboxObject->SetVisible(true);
}
}
}
// Traitement des files d'objets normaux (sans la skybox) // Traitement des files d'objets normaux (sans la skybox)
auto all_entity = entity_manager_->GetAllEntities(); auto all_entity = entity_manager_->GetAllEntities();
for (auto& entity : all_entity) for (auto& entity : all_entity)
{ {
if (entity->GetID() == sky_id_)
{
// skipped the skybox entity to avoid unnecessary calculations since it's always visible
continue;
}
std::lock_guard<std::mutex> lock(objects_mutex_); std::lock_guard<std::mutex> lock(objects_mutex_);
auto renderComponent = entity->GetComponent<ecs::RenderComponent>(); auto renderComponent = entity->GetComponent<ecs::RenderComponent>();
if (renderComponent && renderComponent->GetModel()) if (renderComponent && renderComponent->GetModel())
@@ -1860,58 +1852,6 @@ bool application_class::render_pass(XMFLOAT4* diffuse, XMFLOAT4* position, XMFLO
int renderCount = 0; int renderCount = 0;
int i; int i;
// render skybox
for (auto& skyboxObject : skybox_)
{
if (skyboxObject == nullptr)
{
Logger::Get().Log("skyboxObject is null", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
if (!skyboxObject->IsVisible())
{
continue;
}
direct_3d_->turn_z_buffer_off();
scaleMatrix = skyboxObject->GetScaleMatrix();
rotateMatrix = skyboxObject->GetRotateMatrix();
translateMatrix = skyboxObject->GetTranslateMatrix();
XMMATRIX worldMatrix = XMMatrixMultiply(
XMMatrixMultiply(scaleMatrix, rotateMatrix),
translateMatrix
);
renderCount++;
skyboxObject->get_model()->Render(direct_3d_->get_device_context());
result = shader_manager_->render_skybox_shader(
direct_3d_->get_device_context(),
skyboxObject->get_model()->GetIndexCount(),
worldMatrix,
view,
projection,
skyboxObject->get_model()->GetTexture(TextureType::Diffuse,0),
sun_light_->GetDiffuseColor(),
sun_light_->GetAmbientColor(),
sun_light_->GetDirection(),
sun_light_->GetIntensity()
);
if (!result)
{
Logger::Get().Log("Could not render the object model using the skybox shader", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
direct_3d_->turn_z_buffer_on(); // R<>activer le Z-buffer apr<70>s le rendu de la skybox
break;
}
// Rendu des entit<69>s du syst<73>me ECS s'il est disponible // Rendu des entit<69>s du syst<73>me ECS s'il est disponible
if (entity_manager_) { if (entity_manager_) {
// Cr<43>er le syst<73>me de rendu pour les entit<69>s // Cr<43>er le syst<73>me de rendu pour les entit<69>s
@@ -1972,14 +1912,17 @@ void application_class::construct_frustum()
void application_class::update_skybox_position() void application_class::update_skybox_position()
{ {
if (skybox_.empty()) if (sky_id_ == -1) return;
{
Logger::Get().Log("Skybox is empty", __FILE__, __LINE__, Logger::LogLevel::Error);
return;
}
skybox_[0]->SetTranslateMatrix(XMMatrixTranslation(active_camera_->get_position().x, active_camera_->get_position().y, active_camera_->get_position().z)); if (!sky_entity_) return;
auto transformComponent = sky_entity_->GetComponent<ecs::TransformComponent>();
if (!transformComponent) return;
// convert the camera position to XMVECTOR manually
XMVECTOR cameraPosition = XMVectorSet(camera_->get_position().x, camera_->get_position().y, camera_->get_position().z, 0.0f);
transformComponent->SetPosition(cameraPosition);
transformComponent->UpdateWorldMatrix();
} }
bool application_class::render_physics(float delta_time) { bool application_class::render_physics(float delta_time) {
@@ -2109,3 +2052,75 @@ int application_class::get_terrain_entity_count()
return terrainCount; return terrainCount;
} }
bool application_class::create_skysphere()
{
char modelFilename[128];
TextureContainer textures;
size_t convertedChars = 0;
(void)wcstombs_s(&convertedChars, modelFilename, sizeof(modelFilename), L"assets/Model/OBJ/skysphere.obj", _TRUNCATE);
std::vector<std::wstring> sky_textures = {
L"assets/Skybox/skybox.png"
};
textures.diffusePaths.push_back(sky_textures[0]);
if (sky_textures.size() > 1) textures.normalPaths.push_back(sky_textures[1]);
if (sky_textures.size() > 2) textures.specularPaths.push_back(sky_textures[2]);
std::string modelKey = std::string(modelFilename);
std::shared_ptr<model_class> sharedModel;
auto it = g_model_cache.find(modelKey);
if (it != g_model_cache.end())
{
Logger::Get().Log("Using cached model for sky sphere: " + modelKey, __FILE__, __LINE__);
sharedModel = it->second;
}
else
{
sharedModel = std::make_shared<model_class>();
sharedModel->PreloadTextures(direct_3d_->get_device(), direct_3d_->get_device_context(), textures);
if (!sharedModel->Initialize(direct_3d_->get_device(), direct_3d_->get_device_context(), modelFilename, textures))
{
Logger::Get().Log("Failed to initialize model for sky sphere", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
g_model_cache[modelKey] = sharedModel;
Logger::Get().Log("Added sky sphere model to cache: " + modelKey, __FILE__, __LINE__);
}
sky_entity_ = entity_manager_->CreateEntity();
if (!sky_entity_)
{
Logger::Get().Log("Failed to create sky entity", __FILE__, __LINE__, Logger::LogLevel::Error);
return false;
}
sky_id_ = sky_entity_->GetID();
entity_manager_->SetSkyID(sky_id_);
auto identity = sky_entity_->AddComponent<ecs::IdentityComponent>(object_id_++);
identity->SetName("SkySphere");
identity->SetType(ecs::ObjectType::Unknown);
auto transform = sky_entity_->AddComponent<ecs::TransformComponent>();
transform->SetPosition(XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f));
transform->SetScale(XMVectorSet(2.0f, 2.0f, 2.0f, 0.0f));
transform->UpdateWorldMatrix();
auto render = sky_entity_->AddComponent<ecs::RenderComponent>();
render->InitializeWithModel(sharedModel);
auto modelpath = sky_entity_->AddComponent<ecs::ModelPathComponent>();
modelpath->SetPath(L"assets/Model/OBJ/skysphere.obj");
auto shader = sky_entity_->AddComponent<ecs::ShaderComponent>();
shader->SetActiveShader(ecs::ShaderType::SKYBOX);
return true;
}

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.