Working on multi-threading, including web

This commit is contained in:
Vladislav Khorev committed 2026-01-09 15:24:01 +03:00
1 parent b055faf882
commit 648acf8938
12 files changed
+230 -45

No files matched your search

+88 -16
View File
@@ -4,7 +4,7 @@
#include "render/OpenGlExtensions.h"
#include "Environment.h"
#include "StoneObject.h"
#include "utils/TaskManager.h"
namespace ZL {
@@ -77,20 +77,18 @@ namespace ZL {
sandTexture = std::make_unique<Texture>(CreateTextureDataFromPng("./resources/sand2.png", CONST_ZIP_FILE));
stoneTexture = std::make_unique<Texture>(CreateTextureDataFromPng("./resources/rock.png", CONST_ZIP_FILE));
//#ifndef SIMPLIFIED
// Атмосфера
planetAtmosphereRenderStruct.data = planetData.getAtmosphereLod().vertexData;
if (planetAtmosphereRenderStruct.data.PositionData.size() > 0)
{
planetAtmosphereRenderStruct.RefreshVBO();
}
//#endif
planetStones = CreateStoneGroupData(778, planetData.getLodLevel(lodIndex));
stonesToRender = planetStones.inflate(planetStones.allInstances.size());
//stonesToRender = planetStones.inflate(planetStones.allInstances.size());
stonesToRender.resize(planetStones.allInstances.size());
planetStones.initStatuses();
stoneToBake = planetStones.inflateOne(0, 0.75);
}
@@ -98,6 +96,75 @@ namespace ZL {
void PlanetObject::update(float deltaTimeMs) {
// 1. Проверка порога движения (оптимизация из текущего кода)
float movementThreshold = 1.0f;
if ((Environment::shipPosition - lastUpdatePos).squaredNorm() < movementThreshold * movementThreshold
&& !triangleIndicesToDraw.empty()) {
processMainThreadTasks(); // Все равно обрабатываем очередь OpenGL задач
return;
}
lastUpdatePos = Environment::shipPosition;
// 2. Получаем список видимых треугольников
auto newIndices = planetData.getTrianglesUnderCameraNew2(Environment::shipPosition);
std::sort(newIndices.begin(), newIndices.end());
// 3. Анализируем, что нужно загрузить
for (int triIdx : newIndices) {
if (planetStones.statuses[triIdx] == ChunkStatus::Empty) {
// Помечаем, чтобы не спамить задачами
planetStones.statuses[triIdx] = ChunkStatus::Generating;
// Отправляем тяжелую математику в TaskManager
taskManager->EnqueueBackgroundTask([this, triIdx]() {
// Выполняется в фоновом потоке: только генерация геометрии в RAM
float scaleModifier = 1.0f;
VertexDataStruct generatedData = planetStones.inflateOneDataOnly(triIdx, scaleModifier);
// Передаем задачу на загрузку в GPU в очередь главного потока
this->EnqueueMainThreadTask([this, triIdx, data = std::move(generatedData)]() mutable {
// Проверяем актуальность: если треугольник всё еще в списке видимых
auto it = std::find(triangleIndicesToDraw.begin(), triangleIndicesToDraw.end(), triIdx);
if (it != triangleIndicesToDraw.end()) {
stonesToRender[triIdx].data = std::move(data);
stonesToRender[triIdx].RefreshVBO(); // OpenGL вызов
planetStones.statuses[triIdx] = ChunkStatus::Live;
}
else {
// Если уже не нужен — просто сбрасываем статус
planetStones.statuses[triIdx] = ChunkStatus::Empty;
}
});
});
}
}
// 4. Очистка (Unload)
// Если статус Live, но треугольника нет в новых индексах — освобождаем GPU память
for (size_t i = 0; i < planetStones.statuses.size(); ++i) {
if (planetStones.statuses[i] == ChunkStatus::Live) {
bool isVisible = std::binary_search(newIndices.begin(), newIndices.end(), (int)i);
if (!isVisible) {
// Очищаем данные и VBO (деструкторы shared_ptr в VertexRenderStruct сделают glDeleteBuffers)
stonesToRender[i].data.PositionData.clear();
stonesToRender[i].vao.reset();
stonesToRender[i].positionVBO.reset();
stonesToRender[i].normalVBO.reset();
stonesToRender[i].tangentVBO.reset();
stonesToRender[i].binormalVBO.reset();
stonesToRender[i].colorVBO.reset();
stonesToRender[i].texCoordVBO.reset();
planetStones.statuses[i] = ChunkStatus::Empty;
}
}
}
triangleIndicesToDraw = std::move(newIndices);
// 5. Выполняем одну задачу из очереди OpenGL (RefreshVBO и т.д.)
processMainThreadTasks();
/*
float movementThreshold = 1.0f;
if ((Environment::shipPosition - lastUpdatePos).squaredNorm() < movementThreshold * movementThreshold && !triangleIndicesToDraw.empty()) {
return;
@@ -111,7 +178,7 @@ namespace ZL {
if (newIndices != triangleIndicesToDraw) {
triangleIndicesToDraw = std::move(newIndices);
}
}*/
}
@@ -205,7 +272,6 @@ namespace ZL {
void PlanetObject::draw(Renderer& renderer) {
//#ifndef SIMPLIFIED
{
if (stoneMapFB == nullptr)
{
@@ -221,10 +287,6 @@ namespace ZL {
stoneMapFB->GenerateMipmaps();
}
//#endif
//bakeStoneTexture(renderer);
glViewport(0, 0, Environment::width, Environment::height);
//--------------------------
@@ -232,10 +294,7 @@ namespace ZL {
drawPlanet(renderer);
drawStones(renderer);
//#ifndef SIMPLIFIED
drawAtmosphere(renderer);
//#endif
}
void PlanetObject::drawPlanet(Renderer& renderer)
@@ -382,7 +441,7 @@ namespace ZL {
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBindTexture(GL_TEXTURE_2D, stoneTexture->getTexID());
/*
for (int i : triangleIndicesToDraw)
//for (int i = 0; i < stonesToRender.size(); i++)
{
@@ -390,7 +449,20 @@ namespace ZL {
{
renderer.DrawVertexRenderStruct(stonesToRender[i]);
}
}*/
for (int i : triangleIndicesToDraw) {
// КРИТИЧЕСКОЕ ИЗМЕНЕНИЕ:
// Проверяем, что данные не просто существуют, а загружены в GPU
if (planetStones.statuses[i] == ChunkStatus::Live) {
// Дополнительная проверка на наличие данных (на всякий случай)
if (stonesToRender[i].data.PositionData.size() > 0) {
renderer.DrawVertexRenderStruct(stonesToRender[i]);
}
}
// Если статус Generating или Empty — мы просто пропускаем этот индекс.
// Камни появятся на экране плавно, как только отработает TaskManager и RefreshVBO.
}
CheckGlError();
glDisable(GL_BLEND);
glDisable(GL_CULL_FACE);