diff --git a/data/scene/debugglobe/debugglobe.mod b/data/scene/debugglobe/debugglobe.mod index dd494b168f..7332347b93 100644 --- a/data/scene/debugglobe/debugglobe.mod +++ b/data/scene/debugglobe/debugglobe.mod @@ -10,31 +10,25 @@ return { Textures = { ColorTextures = { { - Name = "ESRI Imagery World 2D", - FilePath = "map_service_configs/ESRI_Imagery_World_2D.wms", + Name = "VIIRS_SNPP_CorrectedReflectance_TrueColor", + FilePath = "map_service_configs/VIIRS_SNPP_CorrectedReflectance_TrueColor.xml" + }, + { + Name = "MODIS_Terra_CorrectedReflectance_TrueColor", + FilePath = "map_service_configs/MODIS_Terra_CorrectedReflectance_TrueColor.xml" + }, + { + Name = "MODIS_Water_Mask", + FilePath = "map_service_configs/MODIS_Water_Mask.xml" }, - - - --[[ { Name = "Coastlines", FilePath = "map_service_configs/Coastlines.xml", }, - { - Name = "VIIRS_SNPP_CorrectedReflectance_TrueColor", - FilePath = "map_service_configs/VIIRS_SNPP_CorrectedReflectance_TrueColor.xml" - }, { Name = "ESRI Imagery World 2D", FilePath = "map_service_configs/ESRI_Imagery_World_2D.wms", }, - - { - Name = "MODIS_Terra_CorrectedReflectance_TrueColor", - FilePath = "map_service_configs/MODIS_Terra_CorrectedReflectance_TrueColor.xml", - }, - - --]] }, HeightMaps = { { diff --git a/ext/ghoul b/ext/ghoul index 5c9f358af8..f3420c0b5c 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit 5c9f358af8056944d09b48c23cb9633aa5e533ff +Subproject commit f3420c0b5c40cb0819e9b67a85c3ab51fce6be8f diff --git a/modules/globebrowsing/globes/chunk.cpp b/modules/globebrowsing/globes/chunk.cpp index dea8a7fd4a..a33bf03377 100644 --- a/modules/globebrowsing/globes/chunk.cpp +++ b/modules/globebrowsing/globes/chunk.cpp @@ -121,7 +121,7 @@ namespace openspace { Scalar scaleFactor = _owner->lodScaleFactor * ellipsoid.minimumRadius();; Scalar projectedScaleFactor = scaleFactor / distance; - int desiredLevel = floor(log2(projectedScaleFactor)); + int desiredLevel = ceil(log2(projectedScaleFactor)); // clamp level desiredLevel = glm::clamp(desiredLevel, _owner->minSplitDepth, _owner->maxSplitDepth); diff --git a/modules/globebrowsing/globes/renderableglobe.cpp b/modules/globebrowsing/globes/renderableglobe.cpp index 3cc4768bfc..ca29c86ece 100644 --- a/modules/globebrowsing/globes/renderableglobe.cpp +++ b/modules/globebrowsing/globes/renderableglobe.cpp @@ -59,7 +59,7 @@ namespace openspace { , doFrustumCulling(properties::BoolProperty("doFrustumCulling", "doFrustumCulling")) , doHorizonCulling(properties::BoolProperty("doHorizonCulling", "doHorizonCulling")) , mergeInvisible(properties::BoolProperty("mergeInvisible", "mergeInvisible", true)) - , lodScaleFactor(properties::FloatProperty("lodScaleFactor", "lodScaleFactor", 10.0f, 0.0f, 100.0f)) + , lodScaleFactor(properties::FloatProperty("lodScaleFactor", "lodScaleFactor", 5.0f, 0.0f, 20.0f)) , initChunkVisible(properties::BoolProperty("initChunkVisible", "initChunkVisible", true)) , renderSmallChunksFirst(properties::BoolProperty("renderSmallChunksFirst", "renderSmallChunksFirst", true)) { @@ -129,7 +129,10 @@ namespace openspace { std::shared_ptr colorTextureProvider = std::shared_ptr( new TileProvider(tileReader, cacheSize, frameUntilFlushRequestQueue)); - _tileProviderManager->addColorTexture(name, colorTextureProvider); + _tileProviderManager->addColorTexture(name, colorTextureProvider, true); + + // Create property for this tile provider + _activeColorLayers.push_back(properties::BoolProperty(name, name, true)); } ghoul::Dictionary heightMapsDictionary; @@ -157,8 +160,20 @@ namespace openspace { new TileProvider(tileReader, cacheSize, frameUntilFlushRequestQueue)); - _tileProviderManager->addHeightMap(name, heightMapProvider); + _tileProviderManager->addHeightMap(name, heightMapProvider, true); + + // Create property for this tile provider + _activeHeightMapLayers.push_back(properties::BoolProperty(name, name, true)); } + + // Add properties for the tile providers + for (auto it = _activeColorLayers.begin(); it != _activeColorLayers.end(); it++) { + addProperty(*it); + } + for (auto it = _activeHeightMapLayers.begin(); it != _activeHeightMapLayers.end(); it++) { + addProperty(*it); + } + _chunkedLodGlobe = std::shared_ptr( new ChunkedLodGlobe(_ellipsoid, patchSegments, _tileProviderManager)); @@ -197,17 +212,31 @@ namespace openspace { _chunkedLodGlobe->setSaveCamera(nullptr); } } - _chunkedLodGlobe->doFrustumCulling = doFrustumCulling.value(); - _chunkedLodGlobe->doHorizonCulling = doHorizonCulling.value(); - _chunkedLodGlobe->mergeInvisible = mergeInvisible.value(); - _chunkedLodGlobe->lodScaleFactor= lodScaleFactor.value(); - _chunkedLodGlobe->initChunkVisible = initChunkVisible.value(); + _distanceSwitch.render(data); } void RenderableGlobe::update(const UpdateData& data) { _time = data.time; _distanceSwitch.update(data); + + _chunkedLodGlobe->doFrustumCulling = doFrustumCulling.value(); + _chunkedLodGlobe->doHorizonCulling = doHorizonCulling.value(); + _chunkedLodGlobe->mergeInvisible = mergeInvisible.value(); + _chunkedLodGlobe->lodScaleFactor = lodScaleFactor.value(); + _chunkedLodGlobe->initChunkVisible = initChunkVisible.value(); + + std::vector& colorTextureProviders = + _tileProviderManager->colorTextureProviders(); + std::vector& heightMapProviders = + _tileProviderManager->heightMapProviders(); + + for (size_t i = 0; i < colorTextureProviders.size(); i++) { + colorTextureProviders[i].isActive = _activeColorLayers[i].value(); + } + for (size_t i = 0; i < heightMapProviders.size(); i++) { + heightMapProviders[i].isActive = _activeHeightMapLayers[i].value(); + } } glm::dvec3 RenderableGlobe::geodeticSurfaceProjection(glm::dvec3 position) { diff --git a/modules/globebrowsing/globes/renderableglobe.h b/modules/globebrowsing/globes/renderableglobe.h index 6b4163158d..0cbeaf200d 100644 --- a/modules/globebrowsing/globes/renderableglobe.h +++ b/modules/globebrowsing/globes/renderableglobe.h @@ -88,6 +88,9 @@ private: properties::BoolProperty _saveOrThrowCamera; + std::vector _activeColorLayers; + std::vector _activeHeightMapLayers; + DistanceSwitch _distanceSwitch; }; diff --git a/modules/globebrowsing/other/TileProviderManager.cpp b/modules/globebrowsing/other/TileProviderManager.cpp index 09115b4728..b4afd69e77 100644 --- a/modules/globebrowsing/other/TileProviderManager.cpp +++ b/modules/globebrowsing/other/TileProviderManager.cpp @@ -44,29 +44,57 @@ namespace openspace { void TileProviderManager::addHeightMap( std::string name, - std::shared_ptr tileProvider) + std::shared_ptr tileProvider, + bool isActive) { - _heightMapProviders.push_back(tileProvider); + _heightMapProviders.push_back({ name , tileProvider, isActive}); } void TileProviderManager::addColorTexture( std::string name, - std::shared_ptr tileProvider) + std::shared_ptr tileProvider, + bool isActive) { - _colorTextureProviders.push_back(tileProvider); - + _colorTextureProviders.push_back({ name , tileProvider, isActive }); } - const std::vector >& + std::vector& TileProviderManager::heightMapProviders() { return _heightMapProviders; } - const std::vector >& + std::vector& TileProviderManager::colorTextureProviders() { return _colorTextureProviders; } + const std::vector > + TileProviderManager::getActiveHeightMapProviders() + { + std::vector > tileProviders; + for (auto it = _heightMapProviders.begin(); it != _heightMapProviders.end(); it++) + { + if (it->isActive) { + tileProviders.push_back(it->tileProvider); + } + } + return tileProviders; + } + + const std::vector > + TileProviderManager::getActiveColorTextureProviders() + { + std::vector > tileProviders; + for (auto it = _colorTextureProviders.begin(); it != _colorTextureProviders.end(); it++) + { + if (it->isActive) { + tileProviders.push_back(it->tileProvider); + } + } + return tileProviders; + } + + } // namespace openspace diff --git a/modules/globebrowsing/other/TileProviderManager.h b/modules/globebrowsing/other/TileProviderManager.h index 1142c1e26d..40aa8bef57 100644 --- a/modules/globebrowsing/other/TileProviderManager.h +++ b/modules/globebrowsing/other/TileProviderManager.h @@ -37,23 +37,38 @@ namespace openspace { class TileProviderManager { public: + struct TileProviderWithName { + std::string name; + std::shared_ptr tileProvider; + bool isActive; + }; + TileProviderManager(); ~TileProviderManager(); static ThreadPool tileRequestThreadPool; - void addHeightMap(std::string name, std::shared_ptr tileProvider); - void addColorTexture(std::string name, std::shared_ptr tileProvider); + void addHeightMap( + std::string name, + std::shared_ptr tileProvider, + bool isActive); + void addColorTexture( + std::string name, + std::shared_ptr tileProvider, + bool isActive); /* std::shared_ptr getHeightMap(std::string name); std::shared_ptr getColorTexture(std::string name); */ - const std::vector >& heightMapProviders(); - const std::vector >& colorTextureProviders(); + const std::vector > getActiveHeightMapProviders(); + const std::vector > getActiveColorTextureProviders(); + + std::vector& heightMapProviders(); + std::vector& colorTextureProviders(); private: - std::vector > _heightMapProviders; - std::vector > _colorTextureProviders; + std::vector _heightMapProviders; + std::vector _colorTextureProviders; }; } // namespace openspace diff --git a/modules/globebrowsing/other/layeredtextureshaderprovider.cpp b/modules/globebrowsing/other/layeredtextureshaderprovider.cpp index 843f2fb1dc..dbd984511d 100644 --- a/modules/globebrowsing/other/layeredtextureshaderprovider.cpp +++ b/modules/globebrowsing/other/layeredtextureshaderprovider.cpp @@ -107,6 +107,9 @@ namespace openspace { textureTypes[i].keyNumLayers, textureTypes[i].numLayers); } + // Remove old program + _programObject.release(); + _programObject = OsEng.renderEngine().buildRenderProgram( _shaderName, _vsPath, diff --git a/modules/globebrowsing/other/tileprovider.cpp b/modules/globebrowsing/other/tileprovider.cpp index bbfe8d3133..74abfe41d8 100644 --- a/modules/globebrowsing/other/tileprovider.cpp +++ b/modules/globebrowsing/other/tileprovider.cpp @@ -98,10 +98,9 @@ namespace openspace { } - Tile TileProvider::getHighestResolutionTile(ChunkIndex chunkIndex) { - TileUvTransform uvTransform; - uvTransform.uvOffset = glm::vec2(0, 0); - uvTransform.uvScale = glm::vec2(1, 1); + Tile TileProvider::getHighestResolutionTile( + ChunkIndex chunkIndex, + TileUvTransform uvTransform) { int maximumLevel = _asyncTextureDataProvider->getTextureDataProvider()->getMaximumLevel(); @@ -113,6 +112,20 @@ namespace openspace { return getOrEnqueueHighestResolutionTile(chunkIndex, uvTransform); } + Tile TileProvider::getHighestResolutionParentTile(ChunkIndex chunkIndex, int levelOffset) { + TileUvTransform uvTransform; + uvTransform.uvOffset = glm::vec2(0, 0); + uvTransform.uvScale = glm::vec2(1, 1); + + for (int i = 0; i < levelOffset && chunkIndex.level > 2; i++) { + transformFromParent(chunkIndex, uvTransform); + chunkIndex = chunkIndex.parent(); + } + + Tile toReturn = getHighestResolutionTile(chunkIndex, uvTransform); + return toReturn; + } + Tile TileProvider::getOrEnqueueHighestResolutionTile(const ChunkIndex& chunkIndex, TileUvTransform& uvTransform) { diff --git a/modules/globebrowsing/other/tileprovider.h b/modules/globebrowsing/other/tileprovider.h index 7474ba6411..95e2a6df73 100644 --- a/modules/globebrowsing/other/tileprovider.h +++ b/modules/globebrowsing/other/tileprovider.h @@ -81,7 +81,15 @@ namespace openspace { ~TileProvider(); - Tile getHighestResolutionTile(ChunkIndex chunkIndex); + Tile getHighestResolutionTile( + ChunkIndex chunkIndex, + TileUvTransform uvTransform = {glm::vec2(0.0f,0.0f), glm::vec2(1.0f,1.0f)}); + /** + \param levelOffset gives a tile from a parent chunk with that particular + offset. For example levelOffset = 1 gives the first parent and levelOffset = 2 + gives the grand parent. + */ + Tile getHighestResolutionParentTile(ChunkIndex chunkIndex, int levelOffset = 1); std::shared_ptr getOrStartFetchingTile(ChunkIndex chunkIndex); std::shared_ptr getDefaultTexture(); diff --git a/modules/globebrowsing/rendering/patchrenderer.cpp b/modules/globebrowsing/rendering/patchrenderer.cpp index f30fde92ed..79f2cd93ee 100644 --- a/modules/globebrowsing/rendering/patchrenderer.cpp +++ b/modules/globebrowsing/rendering/patchrenderer.cpp @@ -68,12 +68,12 @@ namespace openspace { } void PatchRenderer::update() { - auto heightMapProviders = _tileProviderManager->heightMapProviders(); + auto heightMapProviders = _tileProviderManager->getActiveHeightMapProviders(); for (auto iter = heightMapProviders.begin(); iter != heightMapProviders.end(); iter++) { iter->get()->prerender(); } - auto colorTextureProviders = _tileProviderManager->colorTextureProviders(); + auto colorTextureProviders = _tileProviderManager->getActiveColorTextureProviders(); for (auto iter = colorTextureProviders.begin(); iter != colorTextureProviders.end(); iter++) { iter->get()->prerender(); @@ -100,24 +100,6 @@ namespace openspace { "LocalChunkedLodPatch", "${MODULE_GLOBEBROWSING}/shaders/localchunkedlodpatch_vs.glsl", "${MODULE_GLOBEBROWSING}/shaders/localchunkedlodpatch_fs.glsl")); - - /* - _programObjectGlobalRendering = OsEng.renderEngine().buildRenderProgram( - "GlobalChunkedLodPatch", - "${MODULE_GLOBEBROWSING}/shaders/globalchunkedlodpatch_vs.glsl", - "${MODULE_GLOBEBROWSING}/shaders/globalchunkedlodpatch_fs.glsl"); - ghoul_assert(_programObjectGlobalRendering != nullptr, "Failed to initialize programObject!"); - - _programObjectLocalRendering = OsEng.renderEngine().buildRenderProgram( - "LocalChunkedLodPatch", - "${MODULE_GLOBEBROWSING}/shaders/localchunkedlodpatch_vs.glsl", - "${MODULE_GLOBEBROWSING}/shaders/localchunkedlodpatch_fs.glsl"); - ghoul_assert(_programObjectLocalRendering != nullptr, "Failed to initialize programObject!"); - using IgnoreError = ghoul::opengl::ProgramObject::IgnoreError; - _programObjectGlobalRendering->setIgnoreSubroutineUniformLocationError(IgnoreError::Yes); - _programObjectLocalRendering->setIgnoreSubroutineUniformLocationError(IgnoreError::Yes); - */ - } void ChunkRenderer::renderChunk(const Chunk& chunk, const RenderData& data) { @@ -133,8 +115,8 @@ namespace openspace { using namespace glm; // All providers of tiles - auto heightMapProviders = _tileProviderManager->heightMapProviders(); - auto colorTextureProviders = _tileProviderManager->colorTextureProviders(); + auto heightMapProviders = _tileProviderManager->getActiveHeightMapProviders(); + auto colorTextureProviders = _tileProviderManager->getActiveColorTextureProviders(); int numHeightMapProviders = heightMapProviders.size(); int numColorTextureProviders = colorTextureProviders.size(); @@ -162,10 +144,18 @@ namespace openspace { programObject->activate(); std::vector texUnitHeight; + std::vector texUnitHeightParent1; + std::vector texUnitHeightParent2; std::vector texUnitColor; + std::vector texUnitColorParent1; + std::vector texUnitColorParent2; texUnitHeight.resize(numHeightMapProviders); + texUnitHeightParent1.resize(numHeightMapProviders); + texUnitHeightParent2.resize(numHeightMapProviders); texUnitColor.resize(numColorTextureProviders); + texUnitColorParent1.resize(numColorTextureProviders); + texUnitColorParent2.resize(numColorTextureProviders); // Go through all the height map providers @@ -176,6 +166,8 @@ namespace openspace { auto tileProvider = it->get(); // Get the texture that should be used for rendering Tile tile = tileProvider->getHighestResolutionTile(chunk.index()); + Tile tileParent1 = tileProvider->getHighestResolutionParentTile(chunk.index(), 1); + Tile tileParent2 = tileProvider->getHighestResolutionParentTile(chunk.index(), 2); TileDepthTransform depthTransform = tileProvider->depthTransform(); // The texture needs a unit to sample from @@ -193,6 +185,41 @@ namespace openspace { indexedTileKey + ".uvTransform.uvOffset", tile.uvTransform.uvOffset); + // Blend tile with two parents + // The texture needs a unit to sample from + texUnitHeightParent1[i].activate(); + tileParent1.texture->bind(); + + std::string indexedTileKeyParent1 = "heightTilesParent1[" + std::to_string(i) + "]"; + // Send uniforms for the tile to the shader + programObject->setUniform(indexedTileKeyParent1 + ".textureSampler", texUnitHeightParent1[i]); + + programObject->setUniform( + indexedTileKeyParent1 + ".uvTransform.uvScale", + tileParent1.uvTransform.uvScale); + programObject->setUniform( + indexedTileKeyParent1 + ".uvTransform.uvOffset", + tileParent1.uvTransform.uvOffset); + + + + // The texture needs a unit to sample from + texUnitHeightParent2[i].activate(); + tileParent2.texture->bind(); + + std::string indexedTileKeyParent2 = "heightTilesParent2[" + std::to_string(i) + "]"; + // Send uniforms for the tile to the shader + programObject->setUniform(indexedTileKeyParent2 + ".textureSampler", texUnitHeightParent2[i]); + + programObject->setUniform( + indexedTileKeyParent2 + ".uvTransform.uvScale", + tileParent2.uvTransform.uvScale); + programObject->setUniform( + indexedTileKeyParent2 + ".uvTransform.uvOffset", + tileParent2.uvTransform.uvOffset); + + + programObject->setUniform( indexedTileKey + ".depthTransform.depthScale", depthTransform.depthScale); @@ -210,6 +237,8 @@ namespace openspace { auto tileProvider = it->get(); // Get the texture that should be used for rendering Tile tile = tileProvider->getHighestResolutionTile(chunk.index()); + Tile tileParent1 = tileProvider->getHighestResolutionParentTile(chunk.index(), 1); + Tile tileParent2 = tileProvider->getHighestResolutionParentTile(chunk.index(), 2); // The texture needs a unit to sample from texUnitColor[i].activate(); @@ -225,6 +254,38 @@ namespace openspace { programObject->setUniform( indexedTileKey + ".uvTransform.uvOffset", tile.uvTransform.uvOffset); + + // Blend tile with two parents + // The texture needs a unit to sample from + texUnitColorParent1[i].activate(); + tileParent1.texture->bind(); + + std::string indexedTileKeyParent1 = "colorTilesParent1[" + std::to_string(i) + "]"; + // Send uniforms for the tile to the shader + programObject->setUniform(indexedTileKeyParent1 + ".textureSampler", texUnitColorParent1[i]); + + programObject->setUniform( + indexedTileKeyParent1 + ".uvTransform.uvScale", + tileParent1.uvTransform.uvScale); + programObject->setUniform( + indexedTileKeyParent1 + ".uvTransform.uvOffset", + tileParent1.uvTransform.uvOffset); + + + // The texture needs a unit to sample from + texUnitColorParent2[i].activate(); + tileParent2.texture->bind(); + + std::string indexedTileKeyParent2 = "colorTilesParent2[" + std::to_string(i) + "]"; + // Send uniforms for the tile to the shader + programObject->setUniform(indexedTileKeyParent2 + ".textureSampler", texUnitColorParent2[i]); + + programObject->setUniform( + indexedTileKeyParent2 + ".uvTransform.uvScale", + tileParent2.uvTransform.uvScale); + programObject->setUniform( + indexedTileKeyParent2 + ".uvTransform.uvOffset", + tileParent2.uvTransform.uvOffset); i++; } @@ -240,6 +301,12 @@ namespace openspace { * viewTransform * modelTransform; const Ellipsoid& ellipsoid = chunk.owner()->ellipsoid(); + vec3 pointClosestToCamera = chunk.owner()->ellipsoid().cartesianSurfacePosition(chunk.surfacePatch().closestPoint(chunk.owner()->ellipsoid().cartesianToGeodetic2(data.camera.positionVec3()))); + + + + float distanceScaleFactor = chunk.owner()->lodScaleFactor * chunk.owner()->ellipsoid().minimumRadius(); + // Upload the uniform variables programObject->setUniform("modelViewProjectionTransform", modelViewProjectionTransform); programObject->setUniform("minLatLon", vec2(swCorner.toLonLatVec2())); @@ -247,6 +314,14 @@ namespace openspace { programObject->setUniform("radiiSquared", vec3(ellipsoid.radiiSquared())); programObject->setUniform("xSegments", _grid->xSegments()); + // The length of the skirts is proportional to its size + programObject->setUniform("skirtLength", static_cast(chunk.surfacePatch().halfSize().lat * 1000000)); + + programObject->setUniform("cameraPosition", vec3(data.camera.positionVec3())); + programObject->setUniform("distanceScaleFactor", distanceScaleFactor); + programObject->setUniform("chunkLevel", chunk.index().level); + + // OpenGL rendering settings glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); @@ -257,7 +332,6 @@ namespace openspace { // disable shader programObject->deactivate(); - } void ChunkRenderer::renderChunkLocally(const Chunk& chunk, const RenderData& data) @@ -265,8 +339,8 @@ namespace openspace { using namespace glm; // All providers of tiles - auto heightMapProviders = _tileProviderManager->heightMapProviders(); - auto colorTextureProviders = _tileProviderManager->colorTextureProviders(); + auto heightMapProviders = _tileProviderManager->getActiveHeightMapProviders(); + auto colorTextureProviders = _tileProviderManager->getActiveColorTextureProviders(); int numHeightMapProviders = heightMapProviders.size(); int numColorTextureProviders = colorTextureProviders.size(); @@ -293,22 +367,31 @@ namespace openspace { // Activate the shader program programObject->activate(); - std::vector texUnitHeight; + std::vector texUnitHeightParent1; + std::vector texUnitHeightParent2; std::vector texUnitColor; + std::vector texUnitColorParent1; + std::vector texUnitColorParent2; texUnitHeight.resize(numHeightMapProviders); + texUnitHeightParent1.resize(numHeightMapProviders); + texUnitHeightParent2.resize(numHeightMapProviders); texUnitColor.resize(numColorTextureProviders); + texUnitColorParent1.resize(numColorTextureProviders); + texUnitColorParent2.resize(numColorTextureProviders); // Go through all the height map providers int i = 0; for (auto it = heightMapProviders.begin(); it != heightMapProviders.end(); it++) { + texUnitHeight.push_back(ghoul::opengl::TextureUnit()); auto tileProvider = it->get(); - // Get the texture that should be used for rendering Tile tile = tileProvider->getHighestResolutionTile(chunk.index()); + Tile tileParent1 = tileProvider->getHighestResolutionParentTile(chunk.index(), 1); + Tile tileParent2 = tileProvider->getHighestResolutionParentTile(chunk.index(), 2); TileDepthTransform depthTransform = tileProvider->depthTransform(); // The texture needs a unit to sample from @@ -326,6 +409,40 @@ namespace openspace { indexedTileKey + ".uvTransform.uvOffset", tile.uvTransform.uvOffset); + // Blend tile with two parents + // The texture needs a unit to sample from + texUnitHeightParent1[i].activate(); + tileParent1.texture->bind(); + + std::string indexedTileKeyParent1 = "heightTilesParent1[" + std::to_string(i) + "]"; + // Send uniforms for the tile to the shader + programObject->setUniform(indexedTileKeyParent1 + ".textureSampler", texUnitHeightParent1[i]); + + programObject->setUniform( + indexedTileKeyParent1 + ".uvTransform.uvScale", + tileParent1.uvTransform.uvScale); + programObject->setUniform( + indexedTileKeyParent1 + ".uvTransform.uvOffset", + tileParent1.uvTransform.uvOffset); + + + // The texture needs a unit to sample from + texUnitHeightParent2[i].activate(); + tileParent2.texture->bind(); + + std::string indexedTileKeyParent2 = "heightTilesParent2[" + std::to_string(i) + "]"; + // Send uniforms for the tile to the shader + programObject->setUniform(indexedTileKeyParent2 + ".textureSampler", texUnitHeightParent2[i]); + + programObject->setUniform( + indexedTileKeyParent2 + ".uvTransform.uvScale", + tileParent2.uvTransform.uvScale); + programObject->setUniform( + indexedTileKeyParent2 + ".uvTransform.uvOffset", + tileParent2.uvTransform.uvOffset); + + + programObject->setUniform( indexedTileKey + ".depthTransform.depthScale", depthTransform.depthScale); @@ -341,9 +458,10 @@ namespace openspace { for (auto it = colorTextureProviders.begin(); it != colorTextureProviders.end(); it++) { auto tileProvider = it->get(); - // Get the texture that should be used for rendering Tile tile = tileProvider->getHighestResolutionTile(chunk.index()); + Tile tileParent1 = tileProvider->getHighestResolutionParentTile(chunk.index(), 1); + Tile tileParent2 = tileProvider->getHighestResolutionParentTile(chunk.index(), 2); // The texture needs a unit to sample from texUnitColor[i].activate(); @@ -360,10 +478,41 @@ namespace openspace { indexedTileKey + ".uvTransform.uvOffset", tile.uvTransform.uvOffset); + // Blend tile with two parents + // The texture needs a unit to sample from + texUnitColorParent1[i].activate(); + tileParent1.texture->bind(); + + std::string indexedTileKeyParent1 = "colorTilesParent1[" + std::to_string(i) + "]"; + // Send uniforms for the tile to the shader + programObject->setUniform(indexedTileKeyParent1 + ".textureSampler", texUnitColorParent1[i]); + + programObject->setUniform( + indexedTileKeyParent1 + ".uvTransform.uvScale", + tileParent1.uvTransform.uvScale); + programObject->setUniform( + indexedTileKeyParent1 + ".uvTransform.uvOffset", + tileParent1.uvTransform.uvOffset); + + + // The texture needs a unit to sample from + texUnitColorParent2[i].activate(); + tileParent2.texture->bind(); + + std::string indexedTileKeyParent2 = "colorTilesParent2[" + std::to_string(i) + "]"; + // Send uniforms for the tile to the shader + programObject->setUniform(indexedTileKeyParent2 + ".textureSampler", texUnitColorParent2[i]); + + programObject->setUniform( + indexedTileKeyParent2 + ".uvTransform.uvScale", + tileParent2.uvTransform.uvScale); + programObject->setUniform( + indexedTileKeyParent2 + ".uvTransform.uvOffset", + tileParent2.uvTransform.uvOffset); + i++; } - // Calculate other uniform variables needed for rendering // TODO : Model transform should be fetched as a matrix directly. @@ -409,6 +558,12 @@ namespace openspace { data.camera.projectionMatrix()); programObject->setUniform("xSegments", _grid->xSegments()); + // The length of the skirts is proportional to its size + programObject->setUniform("skirtLength", static_cast(chunk.surfacePatch().halfSize().lat * 1000000)); + + float distanceScaleFactor = chunk.owner()->lodScaleFactor * chunk.owner()->ellipsoid().minimumRadius(); + programObject->setUniform("distanceScaleFactor", distanceScaleFactor); + programObject->setUniform("chunkLevel", chunk.index().level); // OpenGL rendering settings glEnable(GL_DEPTH_TEST); @@ -421,6 +576,4 @@ namespace openspace { // disable shader programObject->deactivate(); } - - } // namespace openspace diff --git a/modules/globebrowsing/shaders/globalchunkedlodpatch_fs.glsl b/modules/globebrowsing/shaders/globalchunkedlodpatch_fs.glsl index 1665862311..69183277db 100644 --- a/modules/globebrowsing/shaders/globalchunkedlodpatch_fs.glsl +++ b/modules/globebrowsing/shaders/globalchunkedlodpatch_fs.glsl @@ -31,19 +31,49 @@ #define NUMLAYERS_HEIGHTMAP #{numLayersHeight} uniform TextureTile colorTiles[NUMLAYERS_COLORTEXTURE]; +uniform TextureTile colorTilesParent1[NUMLAYERS_COLORTEXTURE]; +uniform TextureTile colorTilesParent2[NUMLAYERS_COLORTEXTURE]; in vec4 fs_position; in vec2 fs_uv; +in vec3 positionWorldSpace; + +uniform vec3 cameraPosition; +uniform float distanceScaleFactor; +uniform int chunkLevel; + Fragment getFragment() { Fragment frag; - #for i in 0..#{numLayersColor} + // Calculate desired level based on distance + float distToFrag = length(positionWorldSpace - cameraPosition); + float projectedScaleFactor = distanceScaleFactor / distToFrag; + float desiredLevel = log2(projectedScaleFactor); + + // x increases with distance + float x = chunkLevel - desiredLevel; + float w1 = clamp(1 - x, 0 , 1); + float w2 = (clamp(x, 0 , 1) - clamp(x - 1, 0 , 1)); + float w3 = clamp(x - 1, 0 , 1); + + #for j in 1..#{numLayersColor} { + int i = #{j} - 1; vec2 samplePos = - colorTiles[#{i}].uvTransform.uvScale * fs_uv + - colorTiles[#{i}].uvTransform.uvOffset; - vec4 colorSample = texture(colorTiles[#{i}].textureSampler, samplePos); + colorTiles[i].uvTransform.uvScale * fs_uv + + colorTiles[i].uvTransform.uvOffset; + vec2 samplePosParent1 = + colorTilesParent1[i].uvTransform.uvScale * fs_uv + + colorTilesParent1[i].uvTransform.uvOffset; + vec2 samplePosParent2 = + colorTilesParent2[i].uvTransform.uvScale * fs_uv + + colorTilesParent2[i].uvTransform.uvOffset; + + vec4 colorSample = + w1 * texture(colorTiles[i].textureSampler, samplePos) + + w2 * texture(colorTilesParent1[i].textureSampler, samplePosParent1) + + w3 * texture(colorTilesParent2[i].textureSampler, samplePosParent2); frag.color = blendOver(frag.color, colorSample); } #endfor diff --git a/modules/globebrowsing/shaders/globalchunkedlodpatch_vs.glsl b/modules/globebrowsing/shaders/globalchunkedlodpatch_vs.glsl index da7f692152..7e54669ad1 100644 --- a/modules/globebrowsing/shaders/globalchunkedlodpatch_vs.glsl +++ b/modules/globebrowsing/shaders/globalchunkedlodpatch_vs.glsl @@ -39,13 +39,21 @@ uniform vec2 lonLatScalingFactor; uniform int xSegments; uniform int ySegments; +uniform float skirtLength; uniform TextureTile heightTiles[NUMLAYERS_HEIGHTMAP]; +uniform TextureTile heightTilesParent1[NUMLAYERS_HEIGHTMAP]; +uniform TextureTile heightTilesParent2[NUMLAYERS_HEIGHTMAP]; + +uniform vec3 cameraPosition; +uniform float distanceScaleFactor; +uniform int chunkLevel; layout(location = 1) in vec2 in_uv; out vec2 fs_uv; out vec4 fs_position; +out vec3 positionWorldSpace; PositionNormalPair globalInterpolation() { vec2 lonLatInput; @@ -58,21 +66,43 @@ PositionNormalPair globalInterpolation() { void main() { PositionNormalPair pair = globalInterpolation(); + positionWorldSpace = pair.position; float height = 0; - #for i in 0..#{numLayersHeight} - { - vec2 samplePos = - heightTiles[#{i}].uvTransform.uvScale * in_uv + - heightTiles[#{i}].uvTransform.uvOffset; + // Calculate desired level based on distance + float distToVertex = length(positionWorldSpace - cameraPosition); + float projectedScaleFactor = distanceScaleFactor / distToVertex; + float desiredLevel = log2(projectedScaleFactor); - float sampledValue = texture(heightTiles[#{i}].textureSampler, samplePos).r; + // x increases with distance + float x = chunkLevel - desiredLevel; + float w1 = clamp(1 - x, 0 , 1); + float w2 = (clamp(x, 0 , 1) - clamp(x - 1, 0 , 1)); + float w3 = clamp(x - 1, 0 , 1); + + #for j in 1..#{numLayersHeight} + { + int i = #{j} - 1; + vec2 samplePos = + heightTiles[i].uvTransform.uvScale * in_uv + + heightTiles[i].uvTransform.uvOffset; + vec2 samplePosParent1 = + heightTilesParent1[i].uvTransform.uvScale * in_uv + + heightTilesParent1[i].uvTransform.uvOffset; + vec2 samplePosParent2 = + heightTilesParent2[i].uvTransform.uvScale * in_uv + + heightTilesParent2[i].uvTransform.uvOffset; + + float sampledValue = + w1 * texture(heightTiles[i].textureSampler, samplePos).r + + w2 * texture(heightTilesParent1[i].textureSampler, samplePosParent1).r + + w3 * texture(heightTilesParent2[i].textureSampler, samplePosParent2).r; // TODO : Some kind of blending here. Now it just writes over height = (sampledValue * - heightTiles[#{i}].depthTransform.depthScale + - heightTiles[#{i}].depthTransform.depthOffset); + heightTiles[i].depthTransform.depthScale + + heightTiles[i].depthTransform.depthOffset); // Skirts int vertexIDx = gl_VertexID % (xSegments + 3); @@ -81,7 +111,7 @@ void main() vertexIDy == 0 || vertexIDx == (xSegments + 2) || vertexIDy == (xSegments + 2) ) { - height = 0; + height -= skirtLength; } } #endfor diff --git a/modules/globebrowsing/shaders/localchunkedlodpatch_fs.glsl b/modules/globebrowsing/shaders/localchunkedlodpatch_fs.glsl index f0cb8f2ed0..1066b3c267 100644 --- a/modules/globebrowsing/shaders/localchunkedlodpatch_fs.glsl +++ b/modules/globebrowsing/shaders/localchunkedlodpatch_fs.glsl @@ -31,19 +31,48 @@ #define NUMLAYERS_HEIGHTMAP #{numLayersHeight} uniform TextureTile colorTiles[NUMLAYERS_COLORTEXTURE]; +uniform TextureTile colorTilesParent1[NUMLAYERS_COLORTEXTURE]; +uniform TextureTile colorTilesParent2[NUMLAYERS_COLORTEXTURE]; in vec4 fs_position; in vec2 fs_uv; +in vec3 positionCameraSpace; + +uniform float distanceScaleFactor; +uniform int chunkLevel; Fragment getFragment() { Fragment frag; - #for i in 0..#{numLayersColor} + // Calculate desired level based on distance + float distToFrag = length(positionCameraSpace); + float projectedScaleFactor = distanceScaleFactor / distToFrag; + float desiredLevel = log2(projectedScaleFactor); + + // x increases with distance + float x = chunkLevel - desiredLevel; + float w1 = clamp(1 - x, 0 , 1); + float w2 = (clamp(x, 0 , 1) - clamp(x - 1, 0 , 1)); + float w3 = clamp(x - 1, 0 , 1); + + #for j in 1..#{numLayersColor} { + int i = #{j} - 1; + vec2 samplePos = - colorTiles[#{i}].uvTransform.uvScale * fs_uv + - colorTiles[#{i}].uvTransform.uvOffset; - vec4 colorSample = texture(colorTiles[#{i}].textureSampler, samplePos); + colorTiles[i].uvTransform.uvScale * fs_uv + + colorTiles[i].uvTransform.uvOffset; + vec2 samplePosParent1 = + colorTilesParent1[i].uvTransform.uvScale * fs_uv + + colorTilesParent1[i].uvTransform.uvOffset; + vec2 samplePosParent2 = + colorTilesParent2[i].uvTransform.uvScale * fs_uv + + colorTilesParent2[i].uvTransform.uvOffset; + + vec4 colorSample = + w1 * texture(colorTiles[i].textureSampler, samplePos) + + w2 * texture(colorTilesParent1[i].textureSampler, samplePosParent1) + + w3 * texture(colorTilesParent2[i].textureSampler, samplePosParent2); frag.color = blendOver(frag.color, colorSample); } #endfor diff --git a/modules/globebrowsing/shaders/localchunkedlodpatch_vs.glsl b/modules/globebrowsing/shaders/localchunkedlodpatch_vs.glsl index 51128d0a7e..fefd829b79 100644 --- a/modules/globebrowsing/shaders/localchunkedlodpatch_vs.glsl +++ b/modules/globebrowsing/shaders/localchunkedlodpatch_vs.glsl @@ -41,14 +41,21 @@ uniform vec3 p11; uniform vec3 patchNormalCameraSpace; uniform TextureTile heightTiles[NUMLAYERS_HEIGHTMAP]; +uniform TextureTile heightTilesParent1[NUMLAYERS_HEIGHTMAP]; +uniform TextureTile heightTilesParent2[NUMLAYERS_HEIGHTMAP]; uniform int xSegments; uniform int ySegments; +uniform float skirtLength; + +uniform float distanceScaleFactor; +uniform int chunkLevel; layout(location = 1) in vec2 in_uv; out vec2 fs_uv; out vec4 fs_position; +out vec3 positionCameraSpace; vec3 bilinearInterpolation(vec2 uv) { // Bilinear interpolation @@ -65,18 +72,41 @@ void main() float height = 0; - #for i in 0..#{numLayersHeight} - { - vec2 samplePos = - heightTiles[#{i}].uvTransform.uvScale * in_uv + - heightTiles[#{i}].uvTransform.uvOffset; + positionCameraSpace = p; - float sampledValue = texture(heightTiles[#{i}].textureSampler, samplePos).r; + // Calculate desired level based on distance + float distToVertex = length(positionCameraSpace); + float projectedScaleFactor = distanceScaleFactor / distToVertex; + float desiredLevel = log2(projectedScaleFactor); + + // x increases with distance + float x = chunkLevel - desiredLevel; + float w1 = clamp(1 - x, 0 , 1); + float w2 = (clamp(x, 0 , 1) - clamp(x - 1, 0 , 1)); + float w3 = clamp(x - 1, 0 , 1); + + #for j in 1..#{numLayersHeight} + { + int i = #{j} - 1; + vec2 samplePos = + heightTiles[i].uvTransform.uvScale * in_uv + + heightTiles[i].uvTransform.uvOffset; + vec2 samplePosParent1 = + heightTilesParent1[i].uvTransform.uvScale * in_uv + + heightTilesParent1[i].uvTransform.uvOffset; + vec2 samplePosParent2 = + heightTilesParent2[i].uvTransform.uvScale * in_uv + + heightTilesParent2[i].uvTransform.uvOffset; + + float sampledValue = + w1 * texture(heightTiles[i].textureSampler, samplePos).r + + w2 * texture(heightTilesParent1[i].textureSampler, samplePosParent1).r + + w3 * texture(heightTilesParent2[i].textureSampler, samplePosParent2).r; // TODO : Some kind of blending here. Now it just writes over height = (sampledValue * - heightTiles[#{i}].depthTransform.depthScale + - heightTiles[#{i}].depthTransform.depthOffset); + heightTiles[i].depthTransform.depthScale + + heightTiles[i].depthTransform.depthOffset); // Skirts int vertexIDx = gl_VertexID % (xSegments + 3); @@ -85,7 +115,7 @@ void main() vertexIDy == 0 || vertexIDx == (xSegments + 2) || vertexIDy == (xSegments + 2) ) { - height = 0; + height -= skirtLength; } } #endfor