diff --git a/data/scene/debugglobe/debugglobe.mod b/data/scene/debugglobe/debugglobe.mod index b6c0348725..7332347b93 100644 --- a/data/scene/debugglobe/debugglobe.mod +++ b/data/scene/debugglobe/debugglobe.mod @@ -13,6 +13,14 @@ return { 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", @@ -21,9 +29,7 @@ return { Name = "ESRI Imagery World 2D", FilePath = "map_service_configs/ESRI_Imagery_World_2D.wms", }, - }, - HeightMaps = { { Name = "Terrain tileset", 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 467408db42..7d4d30058e 100644 --- a/modules/globebrowsing/globes/renderableglobe.cpp +++ b/modules/globebrowsing/globes/renderableglobe.cpp @@ -60,7 +60,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)) { 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 8e5b469b34..f5c9eca9de 100644 --- a/modules/globebrowsing/rendering/patchrenderer.cpp +++ b/modules/globebrowsing/rendering/patchrenderer.cpp @@ -145,10 +145,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 @@ -159,11 +167,12 @@ 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 texUnitHeight[i].activate(); - int hej = 0; tile.texture->bind(); std::string indexedTileKey = "heightTiles[" + std::to_string(i) + "]"; @@ -177,6 +186,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); @@ -194,6 +238,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(); @@ -209,6 +255,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++; } @@ -224,6 +302,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())); @@ -232,6 +316,11 @@ namespace openspace { 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); @@ -278,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 @@ -311,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); @@ -326,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(); @@ -345,6 +478,38 @@ 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++; } @@ -397,6 +562,9 @@ namespace openspace { // 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); diff --git a/modules/globebrowsing/shaders/globalchunkedlodpatch_fs.glsl b/modules/globebrowsing/shaders/globalchunkedlodpatch_fs.glsl index 0c5c83bdaf..69183277db 100644 --- a/modules/globebrowsing/shaders/globalchunkedlodpatch_fs.glsl +++ b/modules/globebrowsing/shaders/globalchunkedlodpatch_fs.glsl @@ -31,20 +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; + // 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); + 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 f7a3f2cefc..7e54669ad1 100644 --- a/modules/globebrowsing/shaders/globalchunkedlodpatch_vs.glsl +++ b/modules/globebrowsing/shaders/globalchunkedlodpatch_vs.glsl @@ -42,11 +42,18 @@ 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; @@ -59,17 +66,38 @@ PositionNormalPair globalInterpolation() { void main() { PositionNormalPair pair = globalInterpolation(); + positionWorldSpace = pair.position; float height = 0; + // Calculate desired level based on distance + float distToVertex = length(positionWorldSpace - cameraPosition); + 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 = texture(heightTiles[i].textureSampler, samplePos).r; + 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 * diff --git a/modules/globebrowsing/shaders/localchunkedlodpatch_fs.glsl b/modules/globebrowsing/shaders/localchunkedlodpatch_fs.glsl index 487bc44f90..1066b3c267 100644 --- a/modules/globebrowsing/shaders/localchunkedlodpatch_fs.glsl +++ b/modules/globebrowsing/shaders/localchunkedlodpatch_fs.glsl @@ -31,20 +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; + // 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); + 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 38b87213f0..fefd829b79 100644 --- a/modules/globebrowsing/shaders/localchunkedlodpatch_vs.glsl +++ b/modules/globebrowsing/shaders/localchunkedlodpatch_vs.glsl @@ -41,15 +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 @@ -66,14 +72,36 @@ void main() float height = 0; + positionCameraSpace = p; + + // 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 = texture(heightTiles[i].textureSampler, samplePos).r; + 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 *