1#include "ClipmapManager.h"
3#include "ClipmapUpdate.h"
4#include "ClipmapParameterCalculation.h"
5#include "ClipmapDebug.h"
7#include "ExtentCalculation.h"
8#include "Raster/RasterSource.h"
10#include "Rendering/IGraphicsDevice.h"
11#include "Rendering/IContext.h"
12#include "Rendering/CommandGroupAnnotation.h"
14#include "Foundation/Logging/Logger.h"
23 const bool enableMipMapping =
false;
26Cogs::ClipmapManager::ClipmapManager()
28 std::memset(&metrics, 0,
sizeof(TerrainMetrics));
31Cogs::ClipmapManager::~ClipmapManager()
33 detachResponseHandlers();
35 clipmapRenderer.cleanup(device);
38void Cogs::ClipmapManager::setRasterSources(
const RasterSourcePtr & terrain,
const std::vector<RasterSourcePtr> & imagery)
40 LOG_DEBUG(logger,
"Setting raster sources...");
42 detachResponseHandlers();
44 terrainSource.setup(terrain);
46 imagerySources.resize(imagery.size());
47 imageryEnabled.resize(imagerySources.size(),
true);
49 for (
size_t i = 0; i < imagerySources.size(); ++i) {
50 imagerySources[i].setup(imagery[i]);
53 sourcesNeedUpdate =
true;
54 effectsNeedUpdate =
true;
57void Cogs::ClipmapManager::setClipmapParameters(
const ClipmapParameters * parameters)
59 LOG_DEBUG(logger,
"Setting clipmap parameters...");
62 effectsNeedUpdate |= parameters->precomputeNormals != this->parameters.precomputeNormals;
64 this->parameters = *parameters;
66 sourcesNeedUpdate =
true;
67 geometryNeedsUpdate =
true;
70void Cogs::ClipmapManager::setCustomParameters(
const unsigned char * data,
int count)
72 clipmapRenderer.setCustomParameters(data, count);
75void Cogs::ClipmapManager::initialize(IGraphicsDevice * device)
77 this->device = device;
79 Terrain::EffectLoader::setExtension(
".hlsl");
82 clipmapRenderer.raypickDepthData.emplace_back();
83 clipmapRenderer.raypickDepthData.back().initialize(device, 512, 512);
86 clipmapRenderer.initializeTextures(device->getTextures());
87 clipmapRenderer.initializeRasterizerStates(device->getRenderTargets());
88 clipmapRenderer.initializeRenderTargets(device->getRenderTargets());
90 oceanRenderer.initialize(&clipmapRenderer, device);
91 oceanRenderer.initializeTextures(device->getTextures(), device->getRenderTargets());
93 depthQuery.initialize(device, &clipmapRenderer);
95 updater.initialize(device, &normalUpdater);
96 normalUpdater.initialize(device);
101void Cogs::ClipmapManager::initializeGeometry()
103 const size_t clipmapPosts = this->parameters.clipmapPosts;
104 const size_t clipmapSegments = clipmapPosts - 1;
105 const size_t fillPatchPosts = (clipmapPosts + 1) / 4;
106 const size_t fillPatchSegments = fillPatchPosts - 1;
108 if (clipmapGeometry.initialized) {
109 LOG_DEBUG(logger,
"Releasing geometry...");
111 Cogs::releaseGeometry(clipmapGeometry, device->getBuffers());
114 LOG_DEBUG(logger,
"Initializing geometry...");
116 Cogs::initializeGeometry(clipmapGeometry, device->getBuffers(), fillPatchPosts, fillPatchSegments, clipmapSegments, clipmapPosts);
118 clipmapState.fillPatchPosts = fillPatchPosts;
119 clipmapState.fillPatchSegments = fillPatchSegments;
121 clipmapState.clipmapPosts = clipmapPosts;
122 clipmapState.clipmapSegments = clipmapSegments;
124 clipmapState.oneOverBlendedRegionSize = (float)(10.0 / clipmapPosts);
125 clipmapState.unblendedRegionSize = (float)(clipmapSegments / 2 - clipmapPosts / 10.0 - 1);
128void Cogs::ClipmapManager::initializeLevels()
130 CommandGroupAnnotation preGroup(device->getImmediateContext(),
"Terrain::initializeLevels");
132 const size_t numTerrainLevels = terrainSource->getLevels().size();
133 const size_t numLevels = numTerrainLevels;
138 LOG_ERROR(logger,
"No valid terrain levels found in raster source.");
143 this->imagery.resize(imagerySources.size());
145 for (
size_t i = 0; i < imagerySources.size(); ++i) {
147 this->imagery[i].resize(numLevels);
150 this->terrainLevels.resize(numLevels);
152 if (parameters.precomputeNormals) {
153 this->normalLevels.resize(numLevels);
156 const size_t clipmapPosts = this->parameters.clipmapPosts;
158 for (
size_t i = 0; i < numLevels; ++i) {
159 ClipmapLevel & terrainLevel = terrainLevels[i];
161 RasterLevel & terrainRasterLevel = terrainSource->getLevels()[i < numTerrainLevels ? i : numTerrainLevels - 1];
163 terrainLevel.index = i;
165 terrainLevel.rasterLevel = &terrainRasterLevel;
166 terrainLevel.renderTexture = createTexture(clipmapPosts, clipmapPosts, TextureFormat::R32_FLOAT);
167 terrainLevel.coarserLevel = i == 0 ? &terrainLevel : &terrainLevels[i - 1];
168 terrainLevel.finerLevel = i == (numLevels - 1) ?
nullptr : &terrainLevels[i + 1];
170 if (parameters.precomputeNormals) {
171 ClipmapLevel & normalLevel = normalLevels[i];
173 normalLevel.renderTexture = createTexture(clipmapPosts, clipmapPosts, TextureFormat::R16G16B16A16_FLOAT);
174 normalLevel.coarserLevel = i == 0 ? &normalLevel : &normalLevels[i - 1];
175 normalLevel.finerLevel = i == (numLevels - 1) ?
nullptr : &normalLevels[i + 1];
177 terrainLevel.normalLevel = &normalLevel;
180 for (
size_t j = 0; j < imagerySources.size(); ++j) {
181 std::vector<ClipmapLevel> & imageryLevels = imagery[j];
183 ClipmapLevel & imageryLevel = imageryLevels[i];
185 imageryLevel.index = i;
187 imageryLevel.coarserLevel = i == 0 ? &imageryLevel : &imageryLevels[i - 1];
188 imageryLevel.finerLevel = i == (numLevels - 1) ?
nullptr : &imageryLevels[i + 1];
191 double longitudeResRequired = terrainRasterLevel.getPostDeltaLongitude() / parameters.imageryResolutionFactor[j];
192 double latitudeResRequired = terrainRasterLevel.getPostDeltaLatitude() / parameters.imageryResolutionFactor[j];
194 RasterLevel * imageryRasterLevel =
nullptr;
196 auto & levels = imagerySources[j]->getLevels();
198 for (
size_t k = 0; k < levels.size(); ++k) {
199 imageryRasterLevel = &levels[k];
201 if (imageryRasterLevel->getPostDeltaLongitude() <= longitudeResRequired && imageryRasterLevel->getPostDeltaLatitude() <= latitudeResRequired) {
202 if (k < levels.size() - parameters.imageryIndexOffset[j] && i > 0) {
203 imageryRasterLevel = &levels[k + parameters.imageryIndexOffset[j]];
209 const int imageryWidth = (int)std::ceil(clipmapPosts * terrainRasterLevel.getPostDeltaLongitude() / imageryRasterLevel->getPostDeltaLongitude());
210 const int imageryHeight = (int)std::ceil(clipmapPosts * terrainRasterLevel.getPostDeltaLatitude() / imageryRasterLevel->getPostDeltaLatitude());
212 imageryLevel.rasterLevel = imageryRasterLevel;
213 imageryLevel.renderTexture = createTexture(imageryWidth, imageryHeight, imagerySources[j]->format, enableMipMapping);
217 initializeBackgroundLevels();
220void Cogs::ClipmapManager::initializeBackgroundLevels()
222 auto findSize = [](
const int posts) ->
int {
223 if (posts <= 2048)
return posts / 2;
224 if (posts <= 4096)
return posts / 2;
228 RasterLevel & terrainRasterLevel = terrainSource->getLevels()[0];
230 backgroundLevel = ClipmapLevel();
232 backgroundLevel.index = 0;
233 backgroundLevel.background =
true;
234 backgroundLevel.rasterLevel = &terrainRasterLevel;
236 glm::vec4 clearColor{ 0 };
237 const auto noData = terrainRasterLevel.getNoData();
238 if (!std::isnan(noData)) {
239 clearColor = glm::vec4{ noData };
242 backgroundLevel.renderTexture = createTexture(findSize(terrainRasterLevel.getLongitudePosts()), findSize(terrainRasterLevel.getLatitudePosts()), TextureFormat::R32_FLOAT,
false, clearColor);
243 backgroundLevel.coarserLevel = &backgroundLevel;
244 backgroundLevel.finerLevel = &terrainLevels[0];
245 terrainLevels[0].coarserLevel = &backgroundLevel;
247 if (parameters.precomputeNormals) {
248 backgroundNormalLevel = ClipmapLevel();
250 backgroundNormalLevel.index = 0;
251 backgroundNormalLevel.background =
true;
252 backgroundNormalLevel.renderTexture = createTexture(backgroundLevel.renderTexture.width, backgroundLevel.renderTexture.height, TextureFormat::R16G16B16A16_FLOAT);
253 backgroundNormalLevel.coarserLevel = &backgroundNormalLevel;
254 backgroundNormalLevel.finerLevel = &normalLevels[0];
256 backgroundLevel.normalLevel = &backgroundNormalLevel;
259 backgroundImagery.clear();
260 backgroundImagery.resize(imagery.size());
262 for (
size_t i = 0; i < imagerySources.size(); ++i) {
263 std::vector<ClipmapLevel> & imageryLevels = imagery[i];
265 backgroundImagery[i].index = 0;
266 backgroundImagery[i].background =
true;
268 backgroundImagery[i].coarserLevel = &backgroundImagery[i];
269 backgroundImagery[i].finerLevel = &imageryLevels[0];
270 imageryLevels[0].coarserLevel = &backgroundImagery[i];
272 const ClipmapLevel & imageryLevelZero = imagery[i][0];
273 const auto rasterLevel = imageryLevelZero.rasterLevel;
275 const int imageryWidth = findSize(rasterLevel->getLongitudePosts());
276 const int imageryHeight = findSize(rasterLevel->getLatitudePosts());
278 backgroundImagery[i].rasterLevel = imageryLevelZero.rasterLevel;
279 backgroundImagery[i].renderTexture = createTexture(imageryWidth * 2, imageryHeight * 2, imageryLevelZero.rasterLevel->getSource()->format, enableMipMapping);
283void Cogs::ClipmapManager::cleanupLevels()
285 auto clearLevels = [&](std::vector<ClipmapLevel> & levels) {
286 for (
auto & level : levels) {
287 destroyTexture(level.renderTexture);
293 for (
auto & imageryLayer : imagery) {
294 clearLevels(imageryLayer);
297 clearLevels(terrainLevels);
298 clearLevels(normalLevels);
301 backgroundNeedsUpdate =
true;
304 destroyTexture(backgroundLevel.renderTexture);
306 if (
HandleIsValid(backgroundNormalLevel.renderTexture.handle)) {
307 destroyTexture(backgroundNormalLevel.renderTexture);
310 for (
auto & backgroundImageryLayer : backgroundImagery) {
311 destroyTexture(backgroundImageryLayer.renderTexture);
316void Cogs::ClipmapManager::detachResponseHandlers()
318 if (!terrainSource.isReady())
return;
320 terrainSource.teardown();
322 for (
auto & imagerySource : imagerySources) {
323 imagerySource.teardown();
327void Cogs::ClipmapManager::update()
329 CommandGroupAnnotation preGroup(device->getImmediateContext(),
"Terrain::update");
333 if (geometryNeedsUpdate) {
334 initializeGeometry();
336 geometryNeedsUpdate =
false;
339 if (sourcesNeedUpdate && terrainSource.isReady()) {
340 updateSharedDevice(device);
344 preloadLevelZeroTiles();
346 sourcesNeedUpdate =
false;
350 oceanRenderer.update();
354size_t Cogs::ClipmapManager::preRender(RenderContext & renderContext)
356 if (renderContext.oceanEnabled) {
360 CommandGroupAnnotation preGroup(renderContext.context,
"Terrain::preRender");
362 if (!terrainLevels.size()) {
363 LOG_ERROR(logger,
"No terrain levels set. Pre render not possible.");
368 if (!updateOptions.enableUpdate) {
369 renderContext.cullVolume.frustum = previousContext.cullVolume.frustum;
370 renderContext.cullOrigin = previousContext.cullOrigin;
373 updater.setupRenderingState(renderContext);
375 const size_t maxLevel = calculateCenterAndMaxLevel(renderContext);
377 ClipmapLevel & firstLevel = terrainLevels[terrainLevels.size() - 1];
379 calculateNextExtent(clipmapState.clipmapCenter.x, clipmapState.clipmapCenter.y, clipmapState, firstLevel);
381 for (
size_t i = 0; i < imagerySources.size(); ++i) {
382 ClipmapLevel & firstImagery = imagery[i][terrainLevels.size() - 1];
384 if (imageryEnabled[i]) {
385 updateImageryExtent(firstImagery, firstLevel);
389 updateOriginInTextures(firstLevel);
391 for (
size_t i = 0; i < imagerySources.size(); ++i) {
392 if (imageryEnabled[i]) {
393 updateOriginInTextures(imagery[i][terrainLevels.size() - 1]);
397 for (
int i =
static_cast<int>(terrainLevels.size() - 2); i >= 0; --i) {
398 ClipmapLevel & terrainLevel = terrainLevels[i];
400 calculateLevelNextExtent(terrainLevel, *terrainLevel.finerLevel, clipmapState);
401 updateOriginInTextures(terrainLevel);
403 for (
size_t j = 0; j < imagerySources.size(); ++j) {
404 ClipmapLevel & imageryLevel = imagery[j][i];
406 updateImageryExtent(imageryLevel, terrainLevel);
407 updateOriginInTextures(imageryLevel);
411 if (updater.applyNewData(renderContext, worldOptions, terrainSource, terrainLevels, maxLevel) != 0) {
415 for (
size_t i = 0; i < imagerySources.size(); ++i) {
416 if (imageryEnabled[i]) {
417 if (updater.applyNewData(renderContext, worldOptions, imagerySources[i], imagery[i], maxLevel) != 0) {
423 requestTileLoads(renderContext, maxLevel);
425 updateClipmapLevels(renderContext, worldOptions, maxLevel);
427 updateBackgroundLevel(renderContext, worldOptions);
430 renderContext.context->setRenderTarget(renderContext.renderTarget, renderContext.depthStencilTarget);
431 renderContext.context->setViewport(renderContext.viewportX, renderContext.viewportY, renderContext.width, renderContext.height);
435 oceanRenderer.preRender(renderContext);
439 renderContext.context->setRenderTarget(renderContext.renderTarget, renderContext.depthStencilTarget);
440 renderContext.context->setViewport(renderContext.viewportX, renderContext.viewportY, renderContext.width, renderContext.height);
443 updateOptions.invalidateNormals =
false;
445 if(renderContext.reverseDepth != clipmapRenderer.reverseDepth){
446 if (renderContext.reverseDepth) {
447 clipmapRenderer.reverseDepth =
true;
448 clipmapRenderer.initializeRasterizerStates(device->getRenderTargets());
451 clipmapRenderer.reverseDepth =
false;
452 clipmapRenderer.initializeRasterizerStates(device->getRenderTargets());
459void Cogs::ClipmapManager::renderDepth(RenderContext & renderContext,
size_t maxLevel)
461 if (!updateOptions.enableUpdate) {
462 renderContext.cullVolume.frustum = previousContext.cullVolume.frustum;
463 renderContext.cullOrigin = previousContext.cullOrigin;
466 auto & permutationRendererData = clipmapRenderer.getPermutationDependentClipmapRendererData(renderContext.permutation);
467 auto & permutationRenderContextData = renderContext.getPermutationDependentRenderContextData(renderContext.permutation);
468 if (
HandleIsValid(permutationRenderContextData.clipmapEffect) && permutationRenderContextData.clipmapEffect != permutationRendererData.clipmapEffect) {
469 permutationRendererData.clipmapEffect = permutationRenderContextData.clipmapEffect;
470 permutationRendererData.clipmapDepthEffect = permutationRenderContextData.clipmapDepthEffect;
472 clipmapRenderer.initializeEffects(device->getBuffers(), device->getEffects(), imagerySources.size(), renderContext.permutation);
474 effectsNeedUpdate =
false;
477 if (!terrainLevels.size()) {
478 LOG_ERROR(logger,
"No terrain levels set. Render not possible.");
483 if (renderContext.renderPass == TerrainRenderPass::Reflection) maxLevel = maxLevel > 2 ? maxLevel - 2 : maxLevel;
485 if (renderOptions.enableMipMapping) {
486 updateMipmaps(maxLevel, renderContext.device);
489 GlobalParameters globalParameters;
491 calculateGlobalParameters(terrainLevels[0], renderContext, worldOptions, clipmapState, globalParameters);
493 std::vector<LevelParameters> parameters(maxLevel + 1);
494 std::vector<ImageryParameters> imageryParameters(maxLevel + 1);
495 LevelParameters backgroundParameters;
496 ImageryParameters backgroundImageryParameters;
499 auto & worldScale = worldOptions.worldScale;
500 Vector3d scaledCenter = Vector3d(renderContext.center[0] * (1.0 / worldScale[0]), renderContext.center[1] * (1.0 / worldScale[1]), renderContext.center[2]);
502 for (
int i =
static_cast<int>(maxLevel); i >= 0; --i) {
503 ClipmapLevel & terrainLevel = terrainLevels[i];
505 parameters[i].levelIndex = i;
507 std::vector<const ClipmapLevel *> imageryLevels(imagerySources.size());
509 for (
size_t j = 0; j < imagerySources.size(); ++j) {
510 imageryLevels[j] = &imagery[j][i];
513 calculateLevelParameters(
517 imageryParameters[i],
519 worldOptions.enableNoData);
521 parameters[i].useBlendRegions = renderOptions.enableBlending;
522 parameters[i].viewPosInClippedLevel = calculateViewPosInClippedLevel(clipmapState, terrainLevel);
523 parameters[i].useClipping = 0;
526 std::vector<const ClipmapLevel *> imageryLevels(imagerySources.size());
528 for (
size_t j = 0; j < imagerySources.size(); ++j) {
529 imageryLevels[j] = &backgroundImagery[j];
532 calculateLevelParameters(
535 backgroundParameters,
536 backgroundImageryParameters,
538 worldOptions.enableNoData);
540 backgroundParameters.useBlendRegions = 0;
541 backgroundParameters.viewPosInClippedLevel = calculateViewPosInClippedLevel(clipmapState, backgroundLevel);
542 backgroundParameters.useClipping = 1;
543 backgroundParameters.levelIndex = 2;
545 clipmapRenderer.initLevels();
547 bool rendered =
false;
549 for (
int i =
static_cast<int>(maxLevel); i >= 0; --i) {
550 rendered = clipmapRenderer.createRenderLevel(
555 normalLevels.size() ? &normalLevels[i] :
nullptr,
558 imageryParameters[i],
562 std::vector<std::vector<ClipmapLevel>> backgroundImageryReferences;
564 for (
size_t i = 0; i < imagery.size(); ++i) {
565 std::vector<ClipmapLevel> b;
566 b.push_back(backgroundImagery[i]);
567 backgroundImageryReferences.push_back(b);
570 clipmapRenderer.createBackgroundRenderLevel(
574 backgroundImageryReferences,
575 this->parameters.precomputeNormals ? &backgroundNormalLevel :
nullptr,
577 backgroundParameters,
578 backgroundImageryParameters);
580 CommandGroupAnnotation renderGroup(renderContext.context,
"Terrain::renderDepth");
583 auto pickIndex = renderContext.rayPickIndex;
584 if (pickIndex != ClipmapRenderer::NoPickIndex)
587 while(
static_cast<int>(clipmapRenderer.raypickDepthData.size()) <= pickIndex) {
589 auto& depthData = clipmapRenderer.raypickDepthData.emplace_back();
590 depthData.initialize(renderContext.device, renderContext.width, renderContext.height);
594 CommandGroupAnnotation depthGroup(renderContext.context,
"RayPickDepth");
596 clipmapRenderer.setupDepthPass(renderContext, pickIndex);
597 clipmapRenderer.updateGlobalParameters(renderContext, renderOptions, clipmapState, globalParameters);
599 clipmapRenderer.render(renderContext, renderOptions, worldOptions);
601 }
else if (!previousContext.offsetEnabled && renderContext.renderPass == TerrainRenderPass::Main) {
603 CommandGroupAnnotation depthGroup(renderContext.context,
"DepthOnly");
605 clipmapRenderer.setupDepthPass(renderContext, 0);
606 clipmapRenderer.updateGlobalParameters(renderContext, renderOptions, clipmapState, globalParameters);
608 clipmapRenderer.render(renderContext, renderOptions, worldOptions);
612 CommandGroupAnnotation depthQueryGroup(renderContext.context,
"DepthQuery");
613 clipmapRenderer.setupDepthQueryPass(renderContext);
614 clipmapRenderer.updateGlobalParameters(renderContext, renderOptions, clipmapState, globalParameters);
616 clipmapRenderer.render(renderContext, renderOptions, worldOptions);
621 auto context = renderContext.context;
622 context->setRenderTarget(renderContext.renderTarget, renderContext.depthStencilTarget);
623 context->setViewport(renderContext.viewportX, renderContext.viewportY, renderContext.width, renderContext.height);
626void Cogs::ClipmapManager::render(RenderContext & renderContext,
size_t maxLevel)
628 if (!updateOptions.enableUpdate) {
629 renderContext.cullVolume.frustum = previousContext.cullVolume.frustum;
630 renderContext.cullOrigin = previousContext.cullOrigin;
633 if (!terrainLevels.size()) {
634 LOG_ERROR(logger,
"No terrain levels set. Render not possible.");
639 if (renderContext.renderPass == TerrainRenderPass::Reflection) maxLevel = maxLevel > 2 ? maxLevel - 2 : maxLevel;
641 if (renderOptions.enableMipMapping) {
642 updateMipmaps(maxLevel, renderContext.device);
645 GlobalParameters globalParameters;
647 calculateGlobalParameters(terrainLevels[0], renderContext, worldOptions, clipmapState, globalParameters);
649 std::vector<LevelParameters> parameters(maxLevel + 1);
650 std::vector<ImageryParameters> imageryParameters(maxLevel + 1);
651 LevelParameters backgroundParameters;
652 ImageryParameters backgroundImageryParameters;
655 auto & worldScale = worldOptions.worldScale;
656 Vector3d scaledCenter = Vector3d(renderContext.center[0] * (1.0 / worldScale[0]), renderContext.center[1] * (1.0 / worldScale[1]), renderContext.center[2]);
658 for (
int i =
static_cast<int>(maxLevel); i >= 0; --i) {
659 ClipmapLevel & terrainLevel = terrainLevels[i];
661 parameters[i].levelIndex = i;
663 std::vector<const ClipmapLevel *> imageryLevels(imagerySources.size());
665 for (
size_t j = 0; j < imagerySources.size(); ++j) {
666 imageryLevels[j] = &imagery[j][i];
669 calculateLevelParameters(
673 imageryParameters[i],
675 worldOptions.enableNoData);
677 parameters[i].useBlendRegions = renderOptions.enableBlending;
678 parameters[i].viewPosInClippedLevel = calculateViewPosInClippedLevel(clipmapState, terrainLevel);
679 parameters[i].useClipping = 0;
682 std::vector<const ClipmapLevel *> imageryLevels(imagerySources.size());
684 for (
size_t j = 0; j < imagerySources.size(); ++j) {
685 imageryLevels[j] = &backgroundImagery[j];
688 calculateLevelParameters(
691 backgroundParameters,
692 backgroundImageryParameters,
694 worldOptions.enableNoData);
696 backgroundParameters.useBlendRegions = 0;
697 backgroundParameters.viewPosInClippedLevel = calculateViewPosInClippedLevel(clipmapState, backgroundLevel);
698 backgroundParameters.useClipping = 1;
699 backgroundParameters.levelIndex = 2;
701 clipmapRenderer.initLevels();
703 bool rendered =
false;
705 for (
int i =
static_cast<int>(maxLevel); i >= 0; --i) {
706 rendered = clipmapRenderer.createRenderLevel(
711 normalLevels.size() ? &normalLevels[i] :
nullptr,
714 imageryParameters[i],
718 std::vector<std::vector<ClipmapLevel>> backgroundImageryReferences;
720 for (
size_t i = 0; i < imagery.size(); ++i) {
721 std::vector<ClipmapLevel> b;
722 b.push_back(backgroundImagery[i]);
723 backgroundImageryReferences.push_back(b);
726 clipmapRenderer.createBackgroundRenderLevel(
730 backgroundImageryReferences,
731 this->parameters.precomputeNormals ? &backgroundNormalLevel :
nullptr,
733 backgroundParameters,
734 backgroundImageryParameters);
737 CommandGroupAnnotation renderGroup(renderContext.context,
"Terrain::render");
738 clipmapRenderer.setupRegularPass(renderContext);
739 clipmapRenderer.updateGlobalParameters(renderContext, renderOptions, clipmapState, globalParameters);
741 clipmapRenderer.render(renderContext, renderOptions, worldOptions);
745void Cogs::ClipmapManager::renderOcean(RenderContext & renderContext,
size_t maxLevel)
747 CommandGroupAnnotation renderGroup(renderContext.context,
"Terrain::renderOcean");
749 if (!terrainLevels.size()) {
750 LOG_ERROR(logger,
"No terrain levels set. Render not possible.");
755 auto p = renderContext.permutation;
757 auto & permutationRenderContextData = renderContext.getPermutationDependentRenderContextData(renderContext.permutation);
758 auto & permutationOceanData = oceanRenderer.getPermutationDependentOceanRendererData(renderContext.permutation);
759 if (oceanActive &&
HandleIsValid(permutationRenderContextData.oceanEffect) &&
760 permutationRenderContextData.oceanEffect != permutationOceanData.oceanEffect) {
761 permutationOceanData.oceanEffect = permutationRenderContextData.oceanEffect;
763 oceanRenderer.initializeEffects(device->getBuffers(), device->getEffects(), imagerySources.size(), p);
766 if (renderContext.renderPass == TerrainRenderPass::Reflection) maxLevel = maxLevel > 2 ? maxLevel - 2 : maxLevel;
768 GlobalParameters globalParameters;
770 calculateGlobalParameters(terrainLevels[0], renderContext, worldOptions, clipmapState, globalParameters);
772 std::vector<LevelParameters> parameters(maxLevel + 1);
773 std::vector<ImageryParameters> imageryParameters(maxLevel + 1);
774 LevelParameters backgroundParameters;
775 ImageryParameters backgroundImageryParameters;
778 auto & worldScale = worldOptions.worldScale;
779 Vector3d scaledCenter = Vector3d(renderContext.center[0] * (1.0 / worldScale[0]), renderContext.center[1] * (1.0 / worldScale[1]), renderContext.center[2]);
781 for (
int i =
static_cast<int>(maxLevel); i >= 0; --i) {
782 ClipmapLevel & terrainLevel = terrainLevels[i];
784 parameters[i].levelIndex = i;
786 std::vector<const ClipmapLevel *> imageryLevels(imagerySources.size());
788 for (
size_t j = 0; j < imagerySources.size(); ++j) {
789 imageryLevels[j] = &imagery[j][i];
792 calculateLevelParameters(
796 imageryParameters[i],
798 worldOptions.enableNoData);
800 parameters[i].useBlendRegions = renderOptions.enableBlending;
801 parameters[i].viewPosInClippedLevel = calculateViewPosInClippedLevel(clipmapState, terrainLevel);
802 parameters[i].useClipping = 0;
805 std::vector<const ClipmapLevel *> imageryLevels(imagerySources.size());
807 for (
size_t j = 0; j < imagerySources.size(); ++j) {
808 imageryLevels[j] = &backgroundImagery[j];
811 calculateLevelParameters(
814 backgroundParameters,
815 backgroundImageryParameters,
817 worldOptions.enableNoData);
819 backgroundParameters.useBlendRegions = 0;
820 backgroundParameters.viewPosInClippedLevel = calculateViewPosInClippedLevel(clipmapState, backgroundLevel);
821 backgroundParameters.useClipping = 1;
822 backgroundParameters.levelIndex = 2;
824 clipmapRenderer.initLevels();
826 bool rendered =
false;
828 for (
int i =
static_cast<int>(maxLevel); i >= 0; --i) {
829 rendered = clipmapRenderer.createRenderLevel(
834 normalLevels.size() ? &normalLevels[i] :
nullptr,
837 imageryParameters[i],
842 std::vector<std::vector<ClipmapLevel>> backgroundImageryReferences;
844 for (
size_t i = 0; i < imagery.size(); ++i) {
845 std::vector<ClipmapLevel> b;
846 b.push_back(backgroundImagery[i]);
847 backgroundImageryReferences.push_back(b);
850 clipmapRenderer.createBackgroundRenderLevel(
854 backgroundImageryReferences,
855 this->parameters.precomputeNormals ? &backgroundNormalLevel :
nullptr,
857 backgroundParameters,
858 backgroundImageryParameters,
861 if (!oceanActive)
return;
863 if (renderContext.renderPass != TerrainRenderPass::Reflection) {
864 oceanRenderer.setupOceanPass(renderContext);
865 oceanRenderer.updateGlobalParameters(renderContext, renderOptions, clipmapState, globalParameters);
867 oceanRenderer.render(renderContext, renderOptions, worldOptions,
true);
874void Cogs::ClipmapManager::postRender(RenderContext & renderContext)
876 CommandGroupAnnotation postGroup(renderContext.context,
"Terrain::postRender");
878 if (!terrainLevels.size()) {
882 renderDebugOverlays(renderContext);
884 depthQuery.readBack();
887 std::lock_guard<RasterSource> terrainLock(*terrainSource.rasterSource);
889 terrainSource->purgeOldData();
892 for (
auto & imagerySource : imagerySources) {
893 std::lock_guard<RasterSource> imageryLock(*imagerySource.rasterSource);
895 imagerySource->purgeOldData();
899 metrics.sourceTextureBuffers[index++] = terrainSource->textureBufferSize;
901 for (
auto & imagerySource : imagerySources) {
902 metrics.sourceTextureBuffers[index++] = imagerySource->textureBufferSize;
908void Cogs::ClipmapManager::getTerrainMetrics(TerrainMetrics * metrics)
const
910 *metrics = this->metrics;
913void Cogs::ClipmapManager::invalidateRasterSource(RasterSource * rasterSource,
bool clearContents)
917 rasterSource->cancelActiveRequests();
923 while (rasterSource->hasProcessingRequests()) {
924 std::this_thread::sleep_for(std::chrono::milliseconds(0));
927 WriteLock lock(*rasterSource);
929 rasterSource->purgeCache();
931 clearLevels(rasterSource, clearContents);
934void Cogs::ClipmapManager::invalidateTile(RasterSource * rasterSource,
const RasterTileIdentifier &
id)
936 WriteLock lock(*rasterSource);
938 rasterSource->invalidateTile(
id);
943 TextureOrigin updateOrigin(
const Extent & currentExtent,
const Extent & nextExtent,
const int width,
const int height,
const TextureOrigin & origin)
945 int deltaX = nextExtent.west - currentExtent.west;
946 int deltaY = nextExtent.south - currentExtent.south;
948 if (deltaX == 0 && deltaY == 0)
951 if (currentExtent.west > currentExtent.east ||
952 std::abs(deltaX) >= width ||
953 std::abs(deltaY) >= height) {
954 return TextureOrigin(0, 0);
956 int newOriginX = (origin.x + deltaX) % width;
961 int newOriginY = (origin.y + deltaY) % height;
964 newOriginY += height;
966 return TextureOrigin(newOriginX, newOriginY);
971void Cogs::ClipmapManager::updateOriginInTextures(ClipmapLevel & level)
973 level.origin = updateOrigin(level.currentExtent, level.nextExtent, level.renderTexture.width, level.renderTexture.height, level.origin);
976void Cogs::ClipmapManager::updateClipmapLevels(RenderContext & context,
const WorldOptions & worldOptions,
const size_t maxLevel)
978 Extent invalidExtent = { 1, 1, 0, 0 };
980 for (
size_t i = 0; i <= maxLevel; ++i) {
981 updateClipmapLevel(context, worldOptions, terrainLevels[i], *terrainLevels[i].coarserLevel, parameters.precomputeNormals);
983 for (
size_t j = 0; j < imagerySources.size(); ++j) {
984 if (imageryEnabled[j]) {
985 updateClipmapLevel(context, worldOptions, imagery[j][i], *imagery[j][i].coarserLevel,
false);
987 imagery[j][i].currentExtent = invalidExtent;
994 for (
size_t i = maxLevel + 1; i < terrainLevels.size(); ++i) {
995 terrainLevels[i].currentExtent = invalidExtent;
997 for (
size_t j = 0; j < imagerySources.size(); ++j) {
998 imagery[j][i].currentExtent = invalidExtent;
1003void Cogs::ClipmapManager::updateClipmapLevel(RenderContext & context,
const WorldOptions & worldOptions, ClipmapLevel & level, ClipmapLevel & ,
bool normal)
1005 int deltaX = level.nextExtent.west - level.currentExtent.west;
1006 int deltaY = level.nextExtent.south - level.currentExtent.south;
1008 if (deltaX == 0 && deltaY == 0 && !(normal && updateOptions.invalidateNormals)) {
1012 int minLongitude = deltaX > 0 ? level.currentExtent.east + 1 : level.nextExtent.west;
1013 int maxLongitude = deltaX > 0 ? level.nextExtent.east : level.currentExtent.west - 1;
1014 int minLatitude = deltaY > 0 ? level.currentExtent.north + 1 : level.nextExtent.south;
1015 int maxLatitude = deltaY > 0 ? level.nextExtent.north : level.currentExtent.south - 1;
1017 int width = maxLongitude - minLongitude + 1;
1018 int height = maxLatitude - minLatitude + 1;
1020 if (level.currentExtent.west > level.currentExtent.east ||
1021 width >=
static_cast<int>(level.renderTexture.width) ||
1022 height >=
static_cast<int>(level.renderTexture.height))
1025 width = level.renderTexture.width;
1026 height = level.renderTexture.height;
1027 deltaX = level.renderTexture.width;
1028 deltaY = level.renderTexture.height;
1029 minLongitude = level.nextExtent.west;
1030 maxLongitude = level.nextExtent.east;
1031 minLatitude = level.nextExtent.south;
1032 maxLatitude = level.nextExtent.north;
1037 ClipmapUpdate horizontalUpdate(
1039 level.nextExtent.west,
1041 level.nextExtent.east,
1044 updater.updateRasterLevel(context, &horizontalUpdate, 1);
1047 normalUpdater.updateNormalLevel(context, worldOptions, horizontalUpdate, normalLevels[level.index]);
1053 ClipmapUpdate verticalUpdate(
1056 level.nextExtent.south,
1058 level.nextExtent.north);
1060 updater.updateRasterLevel(context, &verticalUpdate, 1);
1063 normalUpdater.updateNormalLevel(context, worldOptions, verticalUpdate, normalLevels[level.index]);
1067 level.currentExtent = level.nextExtent;
1069 if (normal && updateOptions.invalidateNormals) {
1070 ClipmapUpdate update(
1072 level.nextExtent.west,
1073 level.nextExtent.south,
1074 level.nextExtent.east,
1075 level.nextExtent.north);
1077 normalUpdater.updateNormalLevel(context, worldOptions, update, normalLevels[level.index]);
1081void Cogs::ClipmapManager::updateBackgroundLevel(RenderContext & renderContext,
const WorldOptions & worldOptions)
1083 backgroundLevel.nextExtent = backgroundLevel.rasterLevel->getIndexExtent();
1084 backgroundLevel.origin = TextureOrigin();
1086 if (parameters.precomputeNormals) {
1087 backgroundNormalLevel.nextExtent = backgroundLevel.nextExtent;
1088 backgroundNormalLevel.origin = TextureOrigin();
1091 if (missingTileRegions != 0 || backgroundNeedsUpdate) {
1092 ClipmapUpdate update(
1094 backgroundLevel.nextExtent.west,
1095 backgroundLevel.nextExtent.south,
1096 backgroundLevel.nextExtent.east,
1097 backgroundLevel.nextExtent.north);
1099 missingTileRegions =
static_cast<int>(updater.updateRasterLevel(renderContext, &update, 1));
1101 if (parameters.precomputeNormals) {
1102 normalUpdater.updateNormalLevel(renderContext, worldOptions, update, backgroundNormalLevel);
1106 backgroundLevel.currentExtent = backgroundLevel.nextExtent;
1108 if (parameters.precomputeNormals) {
1109 backgroundNormalLevel.currentExtent = backgroundNormalLevel.nextExtent;
1112 for (
size_t i = 0; i < imagerySources.size(); ++i) {
1113 if (missingImageryTileRegions.size() <= i)
1114 missingImageryTileRegions.push_back(1);
1116 if (missingImageryTileRegions[i] || backgroundNeedsUpdate) {
1117 auto & backgroundImageryLevel = backgroundImagery[i];
1119 updater.requestTileResidency(backgroundImageryLevel);
1121 Extent nextImageryExtent = {
1122 static_cast<int>(backgroundImageryLevel.rasterLevel->longitudeToIndex(backgroundLevel.rasterLevel->indexToLongitude(0))),
1123 static_cast<int>(backgroundImageryLevel.rasterLevel->latitudeToIndex(backgroundLevel.rasterLevel->indexToLatitude(0))),
1124 static_cast<int>(backgroundImageryLevel.rasterLevel->longitudeToIndex(backgroundLevel.rasterLevel->indexToLongitude(backgroundLevel.nextExtent.east))),
1125 static_cast<int>(backgroundImageryLevel.rasterLevel->latitudeToIndex(backgroundLevel.rasterLevel->indexToLatitude(backgroundLevel.nextExtent.north)))
1128 backgroundImageryLevel.nextExtent = nextImageryExtent;
1130 backgroundImageryLevel.origin = TextureOrigin();
1132 ClipmapUpdate update(
1133 &backgroundImageryLevel,
1134 backgroundImageryLevel.nextExtent.west,
1135 backgroundImageryLevel.nextExtent.south,
1136 backgroundImageryLevel.nextExtent.east,
1137 backgroundImageryLevel.nextExtent.north);
1139 missingImageryTileRegions[i] = updater.updateRasterLevel(renderContext, &update, 1);
1141 backgroundImageryLevel.currentExtent = backgroundImageryLevel.nextExtent;
1145 backgroundNeedsUpdate =
false;
1148void Cogs::ClipmapManager::updateMipmaps(
size_t maxLevel, IGraphicsDevice * device)
1150 auto textures = device->getTextures();
1152 for (
int i =
static_cast<int>(maxLevel); i >= 0; --i) {
1153 for (
size_t j = 0; j < imagery.size(); ++j) {
1154 textures->generateMipmaps(imagery[j][i].renderTexture.handle);
1158 for (
size_t j = 0; j < imagery.size(); ++j) {
1159 textures->generateMipmaps(backgroundImagery[j].renderTexture.handle);
1163void Cogs::ClipmapManager::requestTileLoads(RenderContext & ,
const size_t maxLevel)
1165 assert(maxLevel < terrainLevels.size());
1167 for (
size_t i = 0; i <= maxLevel; ++i) {
1168 updater.requestTileResidency(terrainLevels[i]);
1170 for (
size_t j = 0; j < imagerySources.size(); ++j) {
1171 if (imageryEnabled[j]) {
1172 updater.requestTileResidency(imagery[j][i]);
1177 updater.requestTileResidency(backgroundLevel);
1179 for (
size_t j = 0; j < imagerySources.size(); ++j) {
1180 if (imageryEnabled[j]) {
1181 updater.requestTileResidency(backgroundImagery[j]);
1186size_t Cogs::ClipmapManager::calculateCenterAndMaxLevel(RenderContext & renderContext)
1188 if (!terrainLevels.size()) {
1189 LOG_ERROR(logger,
"Cannot calculate center and max levels with zero terrain levels.");
1194 if (previousContext.offsetEnabled) {
1195 renderContext.distance = previousContext.distance;
1196 renderContext.center = previousContext.center;
1197 }
else if (updateOptions.enableUpdate) {
1199 renderContext.distance = std::numeric_limits<float>::max();
1200 renderContext.center = Vector3d(0, 0, 0);
1204 const Matrix viewProjection = previousContext.scene.projectionMatrix * previousContext.scene.viewMatrix;
1205 const Matrix inverseViewProjection = glm::inverse(viewProjection);
1207 float xvalues[] = {0.5f, 0.45f, 0.55f, 0.4f, 0.6f, 0.35f, 0.65f, 0.3f, 0.7f, 0.25f, 0.75f, 0.2f, 0.8f, 0.15f, 0.85f, 0.1f, 0.9f, 0.05f, 0.95f};
1208 float yvaluesa[] = {0.5f, 0.45f, 0.4f, 0.35f, 0.3f, 0.25f, 0.2f, 0.15f, 0.1f, 0.05f};
1209 float yvaluesb[] = {0.55f, 0.6f, 0.65f, 0.7f, 0.75f, 0.8f, 0.85f, 0.9f, 0.95f};
1211 std::vector<Vector2> samplePositions;
1212 for(
auto x : xvalues){
1213 for(
auto y : yvaluesa){
1214 samplePositions.push_back(Vector2(x, y));
1217 for(
auto x : xvalues){
1218 for(
auto y : yvaluesb){
1219 samplePositions.push_back(Vector2(x, y));
1223 const size_t numSamples = samplePositions.size();
1224 std::vector<Vector4> center;
1225 std::vector<char> valid;
1226 center.resize(numSamples);
1227 valid.resize(numSamples);
1229 if (depthQuery.getPositions(samplePositions.data(), inverseViewProjection, numSamples, center.data(), (
bool*)valid.data(), ClipmapRenderer::DefaultPickIndex)) {
1230 Vector3 viewCenter(0, 0, 0);
1231 viewCenter = vec3(glm::inverse(previousContext.scene.viewMatrix) * vec4(viewCenter, 1));
1233 renderContext.distance = std::numeric_limits<float>::max();
1235 Vector3 projectedCenter(0, 0, 0);
1237 for (
size_t i = 0; i < numSamples; ++i) {
1239 const Vector3 sampleCenter(center[i]);
1241 const float distance = glm::length(sampleCenter - viewCenter);
1243 if (distance < renderContext.distance) {
1244 renderContext.distance = distance;
1245 renderContext.sampleCenter = sampleCenter;
1246 projectedCenter = sampleCenter;
1252 projectedCenter += Vector3(previousContext.origin);
1255 projectedCenter -= Vector3(renderContext.offset);
1258 clipmapState.clipmapCenter = glm::dvec3(projectedCenter[0] * (1.0f / worldOptions.worldScale[0]), projectedCenter[1] * (1.0f / worldOptions.worldScale[1]), 0);
1261 renderContext.center = Vector3d(projectedCenter[0], projectedCenter[1], 0);
1263 renderContext.sampleOrigin = previousContext.origin;
1265 Vector3d cameraCenter = Vector3d(viewCenter) + previousContext.origin;
1266 renderContext.sampleCameraCenter = cameraCenter;
1268 Vector3 viewCenter = Vector3(glm::inverse(previousContext.scene.viewMatrix) * vec4(0, 0, 0, 1));
1269 Vector3d cameraCenter = Vector3d(viewCenter) + previousContext.origin;
1271 Vector3 cameraDiff = Vector3(cameraCenter-renderContext.sampleCameraCenter);
1273 const float distance = glm::length(renderContext.sampleCenter - viewCenter);
1274 renderContext.distance = distance;
1276 Vector3 projectedCenter = renderContext.sampleCenter;
1279 projectedCenter += Vector3(renderContext.sampleOrigin);
1282 projectedCenter -= Vector3(renderContext.offset);
1284 projectedCenter += cameraDiff;
1287 clipmapState.clipmapCenter = glm::dvec3(projectedCenter[0] * (1.0f / worldOptions.worldScale[0]), projectedCenter[1] * (1.0f / worldOptions.worldScale[1]), 0);
1290 renderContext.center = Vector3d(projectedCenter[0], projectedCenter[1], 0);
1293 Vector3 viewCenter = Vector3(glm::inverse(previousContext.scene.viewMatrix) * vec4(0, 0, 0, 1));
1295 Vector3 cameraCenter = viewCenter + Vector3(previousContext.origin);
1298 cameraCenter -= Vector3(renderContext.offset);
1301 clipmapState.clipmapCenter = glm::dvec3(cameraCenter.x * (1.0f / worldOptions.worldScale.x), cameraCenter.y * (1.0f / worldOptions.worldScale.y), 0);
1304 renderContext.center = Vector3d(cameraCenter.x, cameraCenter.y, 0);
1305 renderContext.distance = std::fabs(cameraCenter.z);
1309 renderContext.center = previousContext.center;
1310 renderContext.distance = previousContext.distance;
1313 const auto & extent = terrainLevels[0].currentExtent;
1315 if (extent.west != 1 || extent.east != 0) {
1316 const float width =
static_cast<float>((extent.east - extent.west) * terrainLevels[0].rasterLevel->getPostDeltaLongitude() * worldOptions.worldScale.x);
1319 if (renderContext.scene.projectionMatrix[3][3] == 1) {
1321 visibleWidth = renderContext.cullVolume.frustum.planes[0].distance + renderContext.cullVolume.frustum.planes[1].distance;
1324 float fieldOfView = std::atan(1 / renderContext.scene.projectionMatrix[1][1]) * 2;
1325 visibleWidth = renderContext.distance * std::sin(fieldOfView) * 2.0f;
1328 const float factor = width / visibleWidth;
1331 float lodBias = renderOptions.lodBias + 0.3465735903f;
1333 size_t maxLevel =
static_cast<size_t>(std::max(lodBias + std::log(factor) / std::log(2.0f), 0.0f));
1334 maxLevel = std::max(
static_cast<size_t>(0), std::min(maxLevel, terrainLevels.size() - 1));
1336 if (maxLevel < lastMaxLevel) {
1341 const float thresholdAboveFactor = std::pow(2.0f,
static_cast<float>(maxLevel - lodBias));
1342 const float thresholdBelowFactor = std::pow(2.0f,
static_cast<float>(maxLevel + 1 - lodBias));
1344 const float fraction = (thresholdBelowFactor - factor) / (thresholdBelowFactor - thresholdAboveFactor);
1346 if (fraction < 0.25f) {
1349 maxLevel = std::min(maxLevel + 1, terrainLevels.size() - 1);
1353 lastMaxLevel = maxLevel;
1359 const auto & mostDetailedLevel = terrainLevels[lastMaxLevel];
1360 const auto & rasterLevel = mostDetailedLevel.rasterLevel;
1361 const auto & rasterGeoExtent = rasterLevel->getGeoExtent();
1363 const double xOffset =
static_cast<double>(parameters.clipmapPosts / 2) * rasterLevel->getPostDeltaLongitude();
1364 const double minX = rasterGeoExtent.getWest() + xOffset;
1365 const double maxX = rasterGeoExtent.getEast() - xOffset;
1367 const double yOffset =
static_cast<double>(parameters.clipmapPosts / 2) * rasterLevel->getPostDeltaLatitude();
1368 const double minY = rasterGeoExtent.getSouth() + yOffset;
1369 const double maxY = rasterGeoExtent.getNorth() - yOffset;
1371 clipmapState.clipmapCenter.x = glm::clamp(clipmapState.clipmapCenter.x, minX, maxX);
1372 clipmapState.clipmapCenter.y = glm::clamp(clipmapState.clipmapCenter.y, minY, maxY);
1375 return lastMaxLevel;
1378void Cogs::ClipmapManager::preloadLevelZeroTiles()
1380 if (!terrainLevels.size())
return;
1382 LOG_DEBUG(logger,
"Preloading tiles...");
1384 auto & terrainLevel = terrainLevels[0];
1386 Extent extent = { 0, 0, terrainLevel.rasterLevel->getLongitudePosts() - 1, terrainLevel.rasterLevel->getLatitudePosts() - 1 };
1387 updater.preloadTiles(terrainLevel, extent);
1389 for (
size_t i = 0; i < imagerySources.size(); ++i) {
1390 if (imageryEnabled[i]) {
1391 auto & imageryLevel = imagery[i][0];
1393 Extent imageryExtent = {
1394 static_cast<int>(imageryLevel.rasterLevel->longitudeToIndex(terrainLevel.rasterLevel->indexToLongitude(0))),
1395 static_cast<int>(imageryLevel.rasterLevel->latitudeToIndex(terrainLevel.rasterLevel->indexToLatitude(0))),
1396 static_cast<int>(imageryLevel.rasterLevel->longitudeToIndex(terrainLevel.rasterLevel->indexToLongitude(extent.east))),
1397 static_cast<int>(imageryLevel.rasterLevel->latitudeToIndex(terrainLevel.rasterLevel->indexToLatitude(extent.north)))
1400 updater.preloadTiles(imageryLevel, imageryExtent);
1405void Cogs::ClipmapManager::clearLevels(RasterSource * rasterSource,
bool clearContents)
1407 auto clearLevel = [&](ClipmapLevel & level) {
1408 if (level.rasterLevel !=
nullptr && level.rasterLevel->getSource() == rasterSource) {
1409 if (clearContents) {
1410 Cogs::clearClipmapTexture(device, level.renderTexture);
1413 if (level.normalLevel) {
1414 if (clearContents) {
1415 Cogs::clearClipmapTexture(device, level.normalLevel->renderTexture);
1420 Extent invalidExtent = { 1, 1, 0, 0 };
1421 level.currentExtent = invalidExtent;
1424 for (
auto & terrainLevel : terrainLevels) {
1425 clearLevel(terrainLevel);
1428 for (
auto & layer : imagery) {
1429 for (
auto & imageryLevel : layer) {
1430 clearLevel(imageryLevel);
1434 clearLevel(backgroundLevel);
1436 for (
auto & level : backgroundImagery) {
1440 backgroundNeedsUpdate =
true;
1443Cogs::RenderTexture Cogs::ClipmapManager::createTexture(
const size_t width,
const size_t height,
const TextureFormat textureFormat,
const bool mipmapping, glm::vec4 clearColor)
1445 auto texture = Cogs::createClipmapTexture(device,
static_cast<int>(width),
static_cast<int>(height), textureFormat, mipmapping && enableMipMapping, clearColor);
1447 metrics.clipmapTextureBuffer += texture.size;
1452void Cogs::ClipmapManager::destroyTexture(RenderTexture & texture)
1454 metrics.clipmapTextureBuffer -= texture.size;
1456 Cogs::releaseClipmapTexture(device, texture);
1459void Cogs::ClipmapManager::updateSharedDevice(IGraphicsDevice * device)
1461 if (terrainSource.isReady()) {
1462 terrainSource->device = device;
1464 for (
size_t i = 0; i < imagerySources.size(); ++i) {
1465 imagerySources[i]->device = device;
1470void Cogs::ClipmapManager::renderDebugOverlays(RenderContext & renderContext)
1472 CommandGroupAnnotation debugGroup(renderContext.context,
"Terrain::renderDebugOverlays");
1474 if (debugOptions.showDepthBuffer || debugOptions.showHeightMaps || debugOptions.showTextures) {
1475 const int sizeX =
static_cast<int>(debugOptions.textureOverlaySize[0]);
1476 const int sizeY =
static_cast<int>(debugOptions.textureOverlaySize[1]);
1478 const int screenHeight = renderContext.height;
1482 const int numX = renderContext.width / sizeX;
1484 if (debugOptions.showDepthBuffer) {
1485 for (
auto & data : clipmapRenderer.raypickDepthData) {
1486 ClipmapDebug::displayClipmapTexture(device, data.depthTextureHandle, xIndex++ * sizeX, screenHeight - yIndex * sizeY, sizeX, sizeY);
1487 if (xIndex > numX) {
1492 ClipmapDebug::displayClipmapTexture(device, clipmapRenderer.depthQueryTextureHandle, xIndex++ * sizeX, screenHeight - yIndex * sizeY, sizeX, sizeY);
1495 if (debugOptions.showHeightMaps) {
1496 for (
size_t i = 0; i < terrainLevels.size(); ++i) {
1497 ClipmapDebug::displayClipmapTexture(device, terrainLevels[i].renderTexture.handle, xIndex++ * sizeX, screenHeight - yIndex * sizeY, sizeX, sizeY, 0.0005f);
1499 if (xIndex > numX) {
1506 if (debugOptions.showTextures) {
1507 for (
size_t i = 0; i < imagery[0].size(); ++i) {
1508 ClipmapDebug::displayClipmapTexture(device, imagery[0][i].renderTexture.handle, xIndex++ * sizeX, screenHeight - yIndex * sizeY, sizeX, sizeY);
1510 if (xIndex > numX) {
1519float Cogs::ClipmapManager::getNearestSample()
1521 if (isInitialized()) {
1522 const Matrix inverseProjection = glm::inverse(previousContext.scene.projectionMatrix);
1524 nearestSample = depthQuery.getNearestTerrainSample(inverseProjection);
1528 return nearestSample;
Log implementation class.
bool HandleIsValid(const ResourceHandle_t< T > &handle)
Check if the given resource is valid, that is not equal to NoHandle or InvalidHandle.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Contains all Cogs related functionality.
@ TerrainProjected
Find the projected center of the screen on the terrain and center the clipmap on these coordinates.
@ Vertical
Project the camera coordinates onto the XY-plane and center the clipmap on these coordinates.
static const Handle_t NoHandle
Represents a handle to nothing.