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.
*/
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:
/**
@@ -530,6 +532,11 @@ private:
* The thread function for culling objects in the scene.
*/
void culling_thread_function();
/**
* Create the skysphere entity.
*/
bool create_skysphere();
public :
std::vector<ID3D11ShaderResourceView*> textures;
@@ -587,7 +594,9 @@ private :
float speed_ = 0.1f; // speed for the demo spinning object
std::vector<object*> imported_object_;
int object_id_ = 0;
std::vector<object*> skybox_;
//std::vector<object*> skybox_;
int sky_id_ = -1;
std::shared_ptr<ecs::Entity> sky_entity_;
// ----------------------------------- //
// ------------- LIGHTS -------------- //

View File

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

View File

@@ -238,6 +238,16 @@ public:
// V<>rifier si le mod<6F>le est visible
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
if (RenderEntity(entity, viewMatrix, projectionMatrix,
diffuseColors, lightPositions, ambientColors,cameraPos,

View File

@@ -28,7 +28,6 @@ application_class::application_class() : should_quit_(false)
reflection_texture_ = nullptr;
scene_texture_ = nullptr;
physics_ = nullptr;
skybox_.clear();
lights_.clear();
sun_light_ = 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);
//ConstructSkyboxWithPlanes();
Skybox* skybox = new Skybox;
skybox->Initialize(direct_3d_);
skybox_.push_back(skybox->ConstructSkybox(this));
culling_active_ = true;
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_->SetDevice(direct_3d_->get_device());
entity_manager_->SetContext(direct_3d_->get_device_context());
create_skysphere();
}
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;
}
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
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)
auto all_entity = entity_manager_->GetAllEntities();
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_);
auto renderComponent = entity->GetComponent<ecs::RenderComponent>();
if (renderComponent && renderComponent->GetModel())
@@ -1860,58 +1852,6 @@ bool application_class::render_pass(XMFLOAT4* diffuse, XMFLOAT4* position, XMFLO
int renderCount = 0;
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
if (entity_manager_) {
// 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()
{
if (skybox_.empty())
{
Logger::Get().Log("Skybox is empty", __FILE__, __LINE__, Logger::LogLevel::Error);
return;
}
if (sky_id_ == -1) 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) {
@@ -2109,3 +2052,75 @@ int application_class::get_terrain_entity_count()
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.