Всем привет! Введение в ситуацию: Не так давно приступил к написанию своей игры. Т.к я до боли любопытный изобретатель велосипедов, мне хочется изучить вопрос максимально, то я решил делать игру с нуля. Сейчас занимаюсь созданием окружения - графики, в качестве API использую Vulkan.
Последней моей задачей было создание каскадных теней (CSM). Собственно сделать то я их сделал, четыре уровня и даже все вроде работает, однако при обновлении матрицы камеры происходит невнятное "мерцание" ландшафта (на видео) - и микрофризы. То есть тени как бы на миг прекращают отображаться, что то пересчитывается и в этот момент и происходит лаг.
Может кто то сталкивался с такой проблемой и сможет подсказать, где может крыться ошибка или хотя бы куда можно попробовать логи воткнуть, чтобы попытаться отловить причину?
Слои валидации включены - ошибок нет.

Код:
void GameState::UpdateCascades() { static uint64_t lastUpdateTime = 0; static glm::vec3 lastCameraPos; static glm::vec3 lastSunDir; uint64_t currentTime = SDL_GetTicks64( ); glm::vec3 currentCameraPos = m_cameraController.GetPosition( ); glm::vec3 currentSunDir = m_timeSystem->GetSunDirection( ); // движении камеры > 2м, изменении солнца > 5, или каждые 200мс float cameraMoveDist = glm::distance( currentCameraPos, lastCameraPos); float sunAngleChange = glm::degrees( acos( glm::dot( currentSunDir, lastSunDir))); if ( cameraMoveDist < 2.0f && sunAngleChange < 5.0f && ( currentTime - lastUpdateTime < 200)) { return; } lastUpdateTime = currentTime; lastCameraPos = currentCameraPos; lastSunDir = currentSunDir; auto cam = m_cameraController; float nearClip = 0.1f; float farClip = 500.0f; VkExtent2D extent = m_app->GetRenderSystem( )->GetSwapchainExtent( ); float aspect = static_cast<float>( extent.width) / static_cast<float>( extent.height); glm::mat4 view = cam.GetViewMatrix( ); glm::mat4 proj = glm::perspective( glm::radians( 90.0f), aspect, nearClip, farClip); glm::mat4 invView = glm::inverse( view); glm::mat4 invProj = glm::inverse( proj); //сплиты каскадов float cascadeSplits[CASCADE_COUNT + 1]; float splitLambda = 0.95f; for ( int i = 0; i <= CASCADE_COUNT; ++i) { float fraction = static_cast<float>( i) / static_cast<float>( CASCADE_COUNT); float logSplit = nearClip * std::pow( farClip / nearClip, fraction); float uniformSplit = nearClip + ( farClip - nearClip) * fraction; cascadeSplits[i] = splitLambda * logSplit + ( 1.0f - splitLambda) * uniformSplit; m_cascadesSplitsLinear[i] = cascadeSplits[i]; } glm::vec3 sunDir = m_timeSystem->GetSunDirection( ); const float SHADOW_MAP_RESOLUTION = 2048.0f; for ( int cascadeIndex = 0; cascadeIndex < CASCADE_COUNT; ++cascadeIndex) { float nearZ = cascadeSplits[cascadeIndex]; float farZ = cascadeSplits[cascadeIndex + 1]; // Углы фрустума glm::vec4 frustumCornersLS[8] = { glm::vec4( -1.0f, -1.0f, -1.0f, 1.0f), glm::vec4( 1.0f, -1.0f, -1.0f, 1.0f), glm::vec4( 1.0f, 1.0f, -1.0f, 1.0f), glm::vec4( -1.0f, 1.0f, -1.0f, 1.0f), glm::vec4( -1.0f, -1.0f, 1.0f, 1.0f), glm::vec4( 1.0f, -1.0f, 1.0f, 1.0f), glm::vec4( 1.0f, 1.0f, 1.0f, 1.0f), glm::vec4( -1.0f, 1.0f, 1.0f, 1.0f) }; glm::vec3 frustumCornersWS[8]; for ( int i = 0; i < 8; ++i) { glm::vec4 viewPos = invProj * frustumCornersLS[i]; if ( viewPos.w != 0.0f) viewPos /= viewPos.w; viewPos.z = ( i < 4) ? -nearZ : -farZ; glm::vec4 worldPos = invView * viewPos; frustumCornersWS[i] = glm::vec3( worldPos); } // Центр фрустума glm::vec3 centerWS( 0.0f); for ( const auto& corner : frustumCornersWS) { centerWS += corner; } centerWS /= 8.0f; // Матрица вида света glm::vec3 lightPos = centerWS - sunDir * 1000.0f; glm::mat4 lightView = glm::lookAt( lightPos, centerWS, glm::vec3( 0.0f, 1.0f, 0.0f)); // AABB в light space float minX = std::numeric_limits<float>::max( ); float maxX = std::numeric_limits<float>::lowest( ); float minY = std::numeric_limits<float>::max( ); float maxY = std::numeric_limits<float>::lowest( ); float minZ = std::numeric_limits<float>::max( ); float maxZ = std::numeric_limits<float>::lowest( ); for ( const auto& corner : frustumCornersWS) { glm::vec4 lightSpaceCorner = lightView * glm::vec4( corner, 1.0f); minX = std::min( minX, lightSpaceCorner.x); maxX = std::max( maxX, lightSpaceCorner.x); minY = std::min( minY, lightSpaceCorner.y); maxY = std::max( maxY, lightSpaceCorner.y); minZ = std::min( minZ, lightSpaceCorner.z); maxZ = std::max( maxZ, lightSpaceCorner.z); } // СТАБИЛИЗАЦИЯ glm::mat4 shadowMatrix = glm::ortho( minX, maxX, minY, maxY, minZ, maxZ) * lightView; glm::vec4 shadowOrigin = glm::vec4( 0.0f, 0.0f, 0.0f, 1.0f); shadowOrigin = shadowMatrix * shadowOrigin; shadowOrigin = shadowOrigin * ( SHADOW_MAP_RESOLUTION / 2.0f); glm::vec4 roundedOrigin = glm::round( shadowOrigin); glm::vec4 roundOffset = roundedOrigin - shadowOrigin; roundOffset = roundOffset * ( 2.0f / SHADOW_MAP_RESOLUTION); roundOffset.z = 0.0f; roundOffset.w = 0.0f; // Применяем стабилизацию glm::mat4 shadowMatrixTemp = shadowMatrix; shadowMatrixTemp[3][0] += roundOffset.x; shadowMatrixTemp[3][1] += roundOffset.y; shadowMatrixTemp[3][2] += roundOffset.z; // стаб матрица для финального AABB minX = maxX = minY = maxY = minZ = maxZ = 0.0f; bool first = true; for ( const auto& corner : frustumCornersWS) { glm::vec4 lightSpaceCorner = shadowMatrixTemp * glm::vec4( corner, 1.0f); if ( first) { minX = maxX = lightSpaceCorner.x; minY = maxY = lightSpaceCorner.y; minZ = maxZ = lightSpaceCorner.z; first = false; } else { minX = std::min( minX, lightSpaceCorner.x); maxX = std::max( maxX, lightSpaceCorner.x); minY = std::min( minY, lightSpaceCorner.y); maxY = std::max( maxY, lightSpaceCorner.y); minZ = std::min( minZ, lightSpaceCorner.z); maxZ = std::max( maxZ, lightSpaceCorner.z); } } // Финальная проекция const float zMargin = 10.0f; glm::mat4 finalLightProj = glm::ortho( minX, maxX, minY, maxY, minZ - zMargin, maxZ + zMargin); m_cascades[cascadeIndex].viewProj = finalLightProj * lightView; m_cascades[cascadeIndex].splitDepth = farZ; } }
Tesmio
> происходит невнятное "мерцание" ландшафта (на видео) - и микрофризы
По видео не особо понятна проблема, особенно с такой текстурой, где там вообще тени?
Tesmio
> где может крыться ошибка
Я бы действовал методом исключения: просто коментишь кусок и смотришь пропала проблема или нет, потом сужаешь кусок в котором обнаружена проблема.
По видео не особо понятна проблема, особенно с такой текстурой, где там вообще тени?
Битрейт ютуба наверное съедает этот эффект. Но я бы описал это точнее так: на миллисекунду затенение "выключается", что воспринимается как вспышка ландшафта. Ровно на это же самое время "подвисает" экран (фриз).
Благослови бог нейросети, нашел причину.
Проблема заключалась в том, что перед рендером не копировал тени в юниформ-буффер.
Tesmio
как спрашивал ?
Как спрашивал?
Ты на свете всех умнее, красивее и стройнее.
И ответик подскажи.
Странные новички, сразу в Вулкан лезут.
И наверное чужие примеры с гитхаба натырил.
ronniko
По крайней мере, чел пытается разбираться, что-то пробовать, а не тупо нанимать команду, как этот тут происходит по 100 раз на дню 😂
Странные новички, сразу в Вулкан лезут.
ronniko, Ну конечно, надо с основ начинать. Надо же сначала ассемблер изучить для каждого существующего процессора, а то как можно вообще сразу лезть в высокоуровневые языки программирования. А еще лучше изучить как работает компьютер, ведь это так важно знать для того чтобы писать программы. Ну и наверное, еще и заодно надо знать весь курс электротехники до корки, и еще желательно по профильному направлению протереть штаны 6 лет в вузе, изучая мертвые и древние как г... мамонта подходы и алгоритмы.
И только после этого, потратив на все это нафиг на ненужное г.. лет 10, можно приступать к написанию программы Hello World. Иначе никак.
Мир изменился с появлением нейросетей, нужно это просто принять. Уже не нужно знать все что я перечислил выше (хотя я - знаю в основе, и я далеко не новичок, просто на этом форуме не был зарегистрирован ранее).
За меня это уже знает нейросеть, и знает гораздо лучше и больше. И с ее помощью я могу писать сразу то, что мне нужно, не тратя огромное количество времени на обучение этому всему. По сути нейросети заменяют мне ту самую команду разработчиков, о которой написал AMM1AK
ksacvet777, сначала локализовал метод где это происходило, потом попросил построчно прокомментировать как что работает, спросил как должно работать и после этого поставил задачу выкатить список вероятных фиксов, уже конкретно и точечно описав проблему. Один из фиксов подошел.
Мир изменился с появлением нейросетей, нужно это просто принять.
Вот поэтому Вулкан не нужон, нужно это просто принять.
Чей-то виртуал.
Tesmio
Куда ты не копировал?