mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-01-06 03:29:44 -06:00
Remove tile-padding to reduce stair-stepping issues (#2842)
* account for availability of next level in desired level solves #2834 * remove tile-padding option & functionality * remove (no longer needed) recursive read function since we no longer padd tiles we cannot sample outside of a read region anymore. * change default tilesize for heightlayers to avoid discontinuities * make frustum culling control a debug property * Small style guide fix * clarify if-statement with comment * add variable for default height-tile resolution, update comment --------- Co-authored-by: Alexander Bock <mail@alexanderbock.eu>
This commit is contained in:
@@ -108,30 +108,23 @@ vec4 performLayerSettings(vec4 value, LayerSettings settings) {
|
||||
return vec4(v, value.a * settings.opacity);
|
||||
}
|
||||
|
||||
vec2 tileUVToTextureSamplePosition(ChunkTile chunkTile, vec2 tileUV, PixelPadding padding)
|
||||
vec2 tileUVToTextureSamplePosition(ChunkTile chunkTile, vec2 tileUV)
|
||||
{
|
||||
vec2 uv = chunkTile.uvTransform.uvOffset + chunkTile.uvTransform.uvScale * tileUV;
|
||||
|
||||
// compensateSourceTextureSampling
|
||||
ivec2 resolution = textureSize(chunkTile.textureSampler, 0);
|
||||
vec2 sourceSize = vec2(resolution) + padding.sizeDifference;
|
||||
vec2 currentSize = vec2(resolution);
|
||||
vec2 sourceToCurrentSize = currentSize / sourceSize;
|
||||
return sourceToCurrentSize * (uv - padding.startOffset / sourceSize);
|
||||
return chunkTile.uvTransform.uvOffset + chunkTile.uvTransform.uvScale * tileUV;
|
||||
}
|
||||
|
||||
vec4 getTexVal(ChunkTilePile chunkTilePile, vec3 w, vec2 uv, PixelPadding padding) {
|
||||
vec4 getTexVal(ChunkTilePile chunkTilePile, vec3 w, vec2 uv) {
|
||||
vec4 v1 = texture(
|
||||
chunkTilePile.chunkTile0.textureSampler,
|
||||
tileUVToTextureSamplePosition(chunkTilePile.chunkTile0, uv, padding)
|
||||
tileUVToTextureSamplePosition(chunkTilePile.chunkTile0, uv)
|
||||
);
|
||||
vec4 v2 = texture(
|
||||
chunkTilePile.chunkTile1.textureSampler,
|
||||
tileUVToTextureSamplePosition(chunkTilePile.chunkTile1, uv, padding)
|
||||
tileUVToTextureSamplePosition(chunkTilePile.chunkTile1, uv)
|
||||
);
|
||||
vec4 v3 = texture(
|
||||
chunkTilePile.chunkTile2.textureSampler,
|
||||
tileUVToTextureSamplePosition(chunkTilePile.chunkTile2, uv, padding)
|
||||
tileUVToTextureSamplePosition(chunkTilePile.chunkTile2, uv)
|
||||
);
|
||||
|
||||
return w.x * v1 + w.y * v2 + w.z * v3;
|
||||
@@ -147,27 +140,27 @@ vec4 getSample#{layerGroup}#{i}(vec2 uv, vec3 levelWeights,
|
||||
|
||||
// All tile layers are the same. Sample from texture
|
||||
#if (#{#{layerGroup}#{i}LayerType} == 0) // DefaultTileProvider
|
||||
c = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv, #{layerGroup}[#{i}].padding);
|
||||
c = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv);
|
||||
#elif (#{#{layerGroup}#{i}LayerType} == 1) // SingleImageProvider
|
||||
c = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv, #{layerGroup}[#{i}].padding);
|
||||
c = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv);
|
||||
#elif (#{#{layerGroup}#{i}LayerType} == 2) // ImageSequenceTileProvider
|
||||
c = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv, #{layerGroup}[#{i}].padding);
|
||||
c = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv);
|
||||
#elif (#{#{layerGroup}#{i}LayerType} == 3) // SizeReferenceTileProvider
|
||||
c = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv, #{layerGroup}[#{i}].padding);
|
||||
c = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv);
|
||||
#elif (#{#{layerGroup}#{i}LayerType} == 4) // TemporalTileProvider
|
||||
c = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv, #{layerGroup}[#{i}].padding);
|
||||
c = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv);
|
||||
#elif (#{#{layerGroup}#{i}LayerType} == 5) // TileIndexTileProvider
|
||||
c = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv, #{layerGroup}[#{i}].padding);
|
||||
c = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv);
|
||||
#elif (#{#{layerGroup}#{i}LayerType} == 6) // TileProviderByIndex
|
||||
c = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv, #{layerGroup}[#{i}].padding);
|
||||
c = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv);
|
||||
#elif (#{#{layerGroup}#{i}LayerType} == 7) // TileProviderByLevel
|
||||
c = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv, #{layerGroup}[#{i}].padding);
|
||||
c = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv);
|
||||
#elif (#{#{layerGroup}#{i}LayerType} == 8) // SolidColor
|
||||
c.rgb = #{layerGroup}[#{i}].color;
|
||||
#elif (#{#{layerGroup}#{i}LayerType} == 9) // SpoutImageProvider
|
||||
c = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv, #{layerGroup}[#{i}].padding);
|
||||
c = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv);
|
||||
#elif (#{#{layerGroup}#{i}LayerType} == 10) // VideoTileProvider
|
||||
c = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv, #{layerGroup}[#{i}].padding);
|
||||
c = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv);
|
||||
#endif
|
||||
|
||||
return c;
|
||||
@@ -332,12 +325,8 @@ vec4 calculateDebugColor(vec2 uv, vec4 fragPos, vec2 vertexResolution) {
|
||||
}
|
||||
|
||||
float tileResolution(vec2 tileUV, ChunkTile chunkTile) {
|
||||
PixelPadding padding;
|
||||
padding.startOffset = ivec2(0);
|
||||
padding.sizeDifference = ivec2(0);
|
||||
|
||||
vec2 heightResolution = textureSize(chunkTile.textureSampler, 0);
|
||||
vec2 uv = tileUVToTextureSamplePosition(chunkTile, tileUV, padding);
|
||||
vec2 uv = tileUVToTextureSamplePosition(chunkTile, tileUV);
|
||||
return gridDots(uv, heightResolution);
|
||||
}
|
||||
|
||||
|
||||
@@ -40,11 +40,6 @@ struct ChunkTile {
|
||||
TileUvTransform uvTransform;
|
||||
};
|
||||
|
||||
struct PixelPadding {
|
||||
ivec2 startOffset;
|
||||
ivec2 sizeDifference;
|
||||
};
|
||||
|
||||
struct ChunkTilePile {
|
||||
ChunkTile chunkTile0;
|
||||
ChunkTile chunkTile1;
|
||||
@@ -69,7 +64,6 @@ struct Layer {
|
||||
TileDepthTransform depthTransform;
|
||||
LayerSettings settings;
|
||||
LayerAdjustment adjustment;
|
||||
PixelPadding padding;
|
||||
|
||||
// Other layer type properties stuff
|
||||
vec3 color;
|
||||
|
||||
@@ -94,12 +94,6 @@ void GPULayerGroup::setValue(ghoul::opengl::ProgramObject& program,
|
||||
program.setUniform(t.uniformCache.uvOffset, ct.uvTransform.uvOffset);
|
||||
program.setUniform(t.uniformCache.uvScale, ct.uvTransform.uvScale);
|
||||
}
|
||||
|
||||
program.setUniform(galuc.paddingStartOffset, al.tilePixelStartOffset());
|
||||
program.setUniform(
|
||||
galuc.paddingSizeDifference,
|
||||
al.tilePixelSizeDifference()
|
||||
);
|
||||
break;
|
||||
}
|
||||
case layers::Layer::ID::SolidColor:
|
||||
@@ -166,14 +160,6 @@ void GPULayerGroup::bind(ghoul::opengl::ProgramObject& p, const LayerGroup& laye
|
||||
tuc.uvOffset = p.uniformLocation(n + "uvTransform.uvOffset");
|
||||
tuc.uvScale = p.uniformLocation(n + "uvTransform.uvScale");
|
||||
}
|
||||
|
||||
galuc.paddingStartOffset = p.uniformLocation(
|
||||
name + "padding.startOffset"
|
||||
);
|
||||
galuc.paddingSizeDifference = p.uniformLocation(
|
||||
name + "padding.sizeDifference"
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
case layers::Layer::ID::SolidColor:
|
||||
|
||||
@@ -78,8 +78,7 @@ private:
|
||||
std::vector<GPUChunkTile> gpuChunkTiles;
|
||||
|
||||
UniformCache(opacity, gamma, multiplier, offset, valueBlending, chromaKeyColor,
|
||||
chromaKeyTolerance, paddingStartOffset, paddingSizeDifference, color,
|
||||
depthOffset, depthScale) uniformCache;
|
||||
chromaKeyTolerance, color, depthOffset, depthScale) uniformCache;
|
||||
|
||||
bool isHeightLayer = false;
|
||||
};
|
||||
|
||||
@@ -132,10 +132,6 @@ namespace {
|
||||
// the layer is disabled
|
||||
std::optional<bool> enabled;
|
||||
|
||||
// Determines whether the downloaded tiles should have a padding added to the
|
||||
// borders
|
||||
std::optional<bool> padTiles;
|
||||
|
||||
// The opacity value of the layer
|
||||
std::optional<float> opacity [[codegen::inrange(0.0, 1.0)]];
|
||||
|
||||
@@ -233,11 +229,7 @@ Layer::Layer(layers::Group::ID id, const ghoul::Dictionary& layerDict, LayerGrou
|
||||
addProperty(_guiDescription);
|
||||
}
|
||||
|
||||
const bool padTiles = p.padTiles.value_or(true);
|
||||
|
||||
TileTextureInitData initData = tileTextureInitData(_layerGroupId, padTiles);
|
||||
_padTilePixelStartOffset = initData.tilePixelStartOffset;
|
||||
_padTilePixelSizeDifference = initData.tilePixelSizeDifference;
|
||||
TileTextureInitData initData = tileTextureInitData(_layerGroupId);
|
||||
|
||||
_opacity = p.opacity.value_or(_opacity);
|
||||
addProperty(Fadeable::_opacity);
|
||||
@@ -472,25 +464,12 @@ void Layer::update() {
|
||||
}
|
||||
}
|
||||
|
||||
glm::ivec2 Layer::tilePixelStartOffset() const {
|
||||
return _padTilePixelStartOffset;
|
||||
}
|
||||
|
||||
glm::ivec2 Layer::tilePixelSizeDifference() const {
|
||||
return _padTilePixelSizeDifference;
|
||||
}
|
||||
|
||||
glm::vec2 Layer::tileUvToTextureSamplePosition(const TileUvTransform& uvTransform,
|
||||
const glm::vec2& tileUV,
|
||||
const glm::uvec2& resolution)
|
||||
{
|
||||
glm::vec2 uv = uvTransform.uvOffset + uvTransform.uvScale * tileUV;
|
||||
|
||||
const glm::vec2 sourceSize = glm::vec2(resolution) +
|
||||
glm::vec2(_padTilePixelSizeDifference);
|
||||
const glm::vec2 currentSize = glm::vec2(resolution);
|
||||
const glm::vec2 sourceToCurrentSize = currentSize / sourceSize;
|
||||
return sourceToCurrentSize * (uv - glm::vec2(_padTilePixelStartOffset) / sourceSize);
|
||||
return uv;
|
||||
}
|
||||
|
||||
void Layer::initializeBasedOnType(layers::Layer::ID id, ghoul::Dictionary initDict) {
|
||||
|
||||
@@ -68,8 +68,6 @@ public:
|
||||
|
||||
void update();
|
||||
|
||||
glm::ivec2 tilePixelStartOffset() const;
|
||||
glm::ivec2 tilePixelSizeDifference() const;
|
||||
glm::vec2 tileUvToTextureSamplePosition(const TileUvTransform& uvTransform,
|
||||
const glm::vec2& tileUV, const glm::uvec2& resolution);
|
||||
|
||||
@@ -94,9 +92,6 @@ private:
|
||||
LayerRenderSettings _renderSettings;
|
||||
LayerAdjustment _layerAdjustment;
|
||||
|
||||
glm::ivec2 _padTilePixelStartOffset = glm::ivec2(0);
|
||||
glm::ivec2 _padTilePixelSizeDifference = glm::ivec2(0);
|
||||
|
||||
const layers::Group::ID _layerGroupId;
|
||||
|
||||
std::function<void(Layer*)> _onChangeCallback;
|
||||
|
||||
@@ -321,7 +321,7 @@ void MemoryAwareTileCache::createDefaultTextureContainers() {
|
||||
ZoneScoped;
|
||||
|
||||
for (const layers::Group& gi : layers::Groups) {
|
||||
TileTextureInitData initData = tileTextureInitData(gi.id, true);
|
||||
TileTextureInitData initData = tileTextureInitData(gi.id);
|
||||
assureTextureContainerExists(initData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -674,7 +674,7 @@ void RawTileDataReader::readImageData(IODescription& io, RawTile::ReadError& wor
|
||||
switch (_initData.ghoulTextureFormat) {
|
||||
case ghoul::opengl::Texture::Format::Red: {
|
||||
char* dest = imageDataDest;
|
||||
const RawTile::ReadError err = repeatedRasterRead(1, io, dest);
|
||||
const RawTile::ReadError err = rasterRead(1, io, dest);
|
||||
worstError = std::max(worstError, err);
|
||||
break;
|
||||
}
|
||||
@@ -686,7 +686,7 @@ void RawTileDataReader::readImageData(IODescription& io, RawTile::ReadError& wor
|
||||
// The final destination pointer is offsetted by one datum byte size
|
||||
// for every raster (or data channel, i.e. R in RGB)
|
||||
char* dest = imageDataDest + (i * _initData.bytesPerDatum);
|
||||
const RawTile::ReadError err = repeatedRasterRead(1, io, dest);
|
||||
const RawTile::ReadError err = rasterRead(1, io, dest);
|
||||
worstError = std::max(worstError, err);
|
||||
}
|
||||
}
|
||||
@@ -695,12 +695,12 @@ void RawTileDataReader::readImageData(IODescription& io, RawTile::ReadError& wor
|
||||
// The final destination pointer is offsetted by one datum byte size
|
||||
// for every raster (or data channel, i.e. R in RGB)
|
||||
char* dest = imageDataDest + (i * _initData.bytesPerDatum);
|
||||
const RawTile::ReadError err = repeatedRasterRead(1, io, dest);
|
||||
const RawTile::ReadError err = rasterRead(1, io, dest);
|
||||
worstError = std::max(worstError, err);
|
||||
}
|
||||
// Last read is the alpha channel
|
||||
char* dest = imageDataDest + (3 * _initData.bytesPerDatum);
|
||||
const RawTile::ReadError err = repeatedRasterRead(2, io, dest);
|
||||
const RawTile::ReadError err = rasterRead(2, io, dest);
|
||||
worstError = std::max(worstError, err);
|
||||
}
|
||||
else { // Three or more rasters
|
||||
@@ -708,7 +708,7 @@ void RawTileDataReader::readImageData(IODescription& io, RawTile::ReadError& wor
|
||||
// The final destination pointer is offsetted by one datum byte size
|
||||
// for every raster (or data channel, i.e. R in RGB)
|
||||
char* dest = imageDataDest + (i * _initData.bytesPerDatum);
|
||||
const RawTile::ReadError err = repeatedRasterRead(i + 1, io, dest);
|
||||
const RawTile::ReadError err = rasterRead(i + 1, io, dest);
|
||||
worstError = std::max(worstError, err);
|
||||
}
|
||||
}
|
||||
@@ -721,7 +721,7 @@ void RawTileDataReader::readImageData(IODescription& io, RawTile::ReadError& wor
|
||||
// The final destination pointer is offsetted by one datum byte size
|
||||
// for every raster (or data channel, i.e. R in RGB)
|
||||
char* dest = imageDataDest + (i * _initData.bytesPerDatum);
|
||||
const RawTile::ReadError err = repeatedRasterRead(1, io, dest);
|
||||
const RawTile::ReadError err = rasterRead(1, io, dest);
|
||||
worstError = std::max(worstError, err);
|
||||
}
|
||||
}
|
||||
@@ -730,12 +730,12 @@ void RawTileDataReader::readImageData(IODescription& io, RawTile::ReadError& wor
|
||||
// The final destination pointer is offsetted by one datum byte size
|
||||
// for every raster (or data channel, i.e. R in RGB)
|
||||
char* dest = imageDataDest + (i * _initData.bytesPerDatum);
|
||||
const RawTile::ReadError err = repeatedRasterRead(1, io, dest);
|
||||
const RawTile::ReadError err = rasterRead(1, io, dest);
|
||||
worstError = std::max(worstError, err);
|
||||
}
|
||||
// Last read is the alpha channel
|
||||
char* dest = imageDataDest + (3 * _initData.bytesPerDatum);
|
||||
const RawTile::ReadError err = repeatedRasterRead(2, io, dest);
|
||||
const RawTile::ReadError err = rasterRead(2, io, dest);
|
||||
worstError = std::max(worstError, err);
|
||||
}
|
||||
else { // Three or more rasters
|
||||
@@ -743,14 +743,14 @@ void RawTileDataReader::readImageData(IODescription& io, RawTile::ReadError& wor
|
||||
// The final destination pointer is offsetted by one datum byte size
|
||||
// for every raster (or data channel, i.e. R in RGB)
|
||||
char* dest = imageDataDest + (i * _initData.bytesPerDatum);
|
||||
const RawTile::ReadError err = repeatedRasterRead(3 - i, io, dest);
|
||||
const RawTile::ReadError err = rasterRead(3 - i, io, dest);
|
||||
worstError = std::max(worstError, err);
|
||||
}
|
||||
}
|
||||
if (nRastersToRead > 3) { // Alpha channel exists
|
||||
// Last read is the alpha channel
|
||||
char* dest = imageDataDest + (3 * _initData.bytesPerDatum);
|
||||
const RawTile::ReadError err = repeatedRasterRead(4, io, dest);
|
||||
const RawTile::ReadError err = rasterRead(4, io, dest);
|
||||
worstError = std::max(worstError, err);
|
||||
}
|
||||
break;
|
||||
@@ -773,20 +773,6 @@ IODescription RawTileDataReader::ioDescription(const TileIndex& tileIndex) const
|
||||
io.read.overview = 0;
|
||||
io.read.fullRegion.start = glm::ivec2(0, 0);
|
||||
io.read.fullRegion.numPixels = glm::ivec2(_rasterXSize, _rasterYSize);
|
||||
// For correct sampling in dataset, we need to pad the texture tile
|
||||
|
||||
PixelRegion scaledPadding = {
|
||||
.start = _initData.tilePixelStartOffset,
|
||||
.numPixels = _initData.tilePixelSizeDifference
|
||||
};
|
||||
|
||||
const double scale = static_cast<double>(io.read.region.numPixels.x) /
|
||||
static_cast<double>(io.write.region.numPixels.x);
|
||||
scaledPadding.numPixels *= scale;
|
||||
scaledPadding.start *= scale;
|
||||
|
||||
io.read.region.start += scaledPadding.start;
|
||||
io.read.region.numPixels += scaledPadding.numPixels;
|
||||
|
||||
io.write.bytesPerLine = _initData.bytesPerLine;
|
||||
io.write.totalNumBytes = _initData.totalNumBytes;
|
||||
@@ -811,121 +797,6 @@ glm::ivec2 RawTileDataReader::fullPixelSize() const {
|
||||
return geodeticToPixel(Geodetic2{ 90.0, 180.0 }, _padfTransform);
|
||||
}
|
||||
|
||||
RawTile::ReadError RawTileDataReader::repeatedRasterRead(int rasterBand,
|
||||
const IODescription& fullIO,
|
||||
char* dataDestination,
|
||||
int depth) const
|
||||
{
|
||||
|
||||
// NOTE:
|
||||
// Ascii graphics illustrates the implementation details of this method, for one
|
||||
// specific case. Even though the illustrated case is specific, readers can
|
||||
// hopefully find it useful to get the general idea.
|
||||
|
||||
// Make a copy of the full IO desription as we will have to modify it
|
||||
IODescription io = fullIO;
|
||||
|
||||
// Example:
|
||||
// We have an io description that defines a WRITE and a READ region.
|
||||
// In this case the READ region extends outside of the defined io.read.fullRegion,
|
||||
// meaning we will have to perform wrapping
|
||||
|
||||
// io.write.region io.read.region
|
||||
// | |
|
||||
// V V
|
||||
// +-------+ +-------+
|
||||
// | | | |--------+
|
||||
// | | | | |
|
||||
// | | | | |
|
||||
// +-------+ +-------+ |
|
||||
// | | <-- io.read.fullRegion
|
||||
// | |
|
||||
// +--------------+
|
||||
|
||||
RawTile::ReadError worstError = RawTile::ReadError::None;
|
||||
if (!isInside(io.read.region, io.read.fullRegion)) {
|
||||
// Loop through each side: left, top, right, bottom
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
// Example:
|
||||
// We are currently considering the left side of the pixel region
|
||||
const Side side = static_cast<Side>(i);
|
||||
IODescription cutoff = cutIODescription(
|
||||
io,
|
||||
side,
|
||||
edge(io.read.fullRegion, side)
|
||||
);
|
||||
|
||||
// Example:
|
||||
// We cut off the left part that was outside the io.read.fullRegion, and we
|
||||
// now have an additional io description for the cut off region.
|
||||
// Note that the cut-method used above takes care of the corresponding
|
||||
// WRITE region for us.
|
||||
|
||||
// cutoff.write.region cutoff.read.region
|
||||
// | io.write.region | io.read.region
|
||||
// | | | |
|
||||
// V V V V
|
||||
// +-+-----+ +-+-----+
|
||||
// | | | | | |--------+
|
||||
// | | | | | | |
|
||||
// | | | | | | |
|
||||
// +-+-----+ +-+-----+ |
|
||||
// | | <-- io.read.fullRegion
|
||||
// | |
|
||||
// +--------------+
|
||||
|
||||
const int area = cutoff.read.region.numPixels.x *
|
||||
cutoff.read.region.numPixels.y;
|
||||
if (area > 0) {
|
||||
// Wrap by repeating
|
||||
Side oppositeSide = static_cast<Side>((i + 2) % 4);
|
||||
|
||||
alignPixelRegion(
|
||||
cutoff.read.region,
|
||||
oppositeSide,
|
||||
edge(io.read.fullRegion, oppositeSide)
|
||||
);
|
||||
|
||||
// Example:
|
||||
// The cut off region is wrapped to the opposite side of the region,
|
||||
// i.e. "repeated". Note that we don't want WRITE region to change,
|
||||
// we're only wrapping the READ region.
|
||||
|
||||
// cutoff.write.region io.read.region cutoff.read.region
|
||||
// | io.write.region | |
|
||||
// | | V V
|
||||
// V V +-----+ +-+
|
||||
// +-+-----+ | |------| |
|
||||
// | | | | | | |
|
||||
// | | | | | | |
|
||||
// | | | +-----+ +-+
|
||||
// +-+-----+ | | <-- io.read.fullRegion
|
||||
// | |
|
||||
// +--------------+
|
||||
|
||||
// Example:
|
||||
// The cutoff region has been repeated along one of its sides, but
|
||||
// as we can see in this example, it still has a top part outside the
|
||||
// defined gdal region. This is handled through recursion.
|
||||
const RawTile::ReadError err = repeatedRasterRead(
|
||||
rasterBand,
|
||||
cutoff,
|
||||
dataDestination,
|
||||
depth + 1
|
||||
);
|
||||
|
||||
worstError = std::max(worstError, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const RawTile::ReadError err = rasterRead(rasterBand, io, dataDestination);
|
||||
|
||||
// The return error from a repeated rasterRead is ONLY based on the main region,
|
||||
// which in the usual case will cover the main area of the patch anyway
|
||||
return err;
|
||||
}
|
||||
|
||||
TileMetaData RawTileDataReader::tileMetaData(RawTile& rawTile,
|
||||
const PixelRegion& region) const
|
||||
{
|
||||
|
||||
@@ -79,13 +79,6 @@ private:
|
||||
|
||||
IODescription ioDescription(const TileIndex& tileIndex) const;
|
||||
|
||||
/**
|
||||
* A recursive function that is able to perform wrapping in case the read region of
|
||||
* the given IODescription is outside of the given write region.
|
||||
*/
|
||||
RawTile::ReadError repeatedRasterRead(int rasterBand, const IODescription& fullIO,
|
||||
char* dataDestination, int depth = 0) const;
|
||||
|
||||
TileMetaData tileMetaData(RawTile& rawTile, const PixelRegion& region) const;
|
||||
|
||||
const std::string _datasetFilePath;
|
||||
|
||||
@@ -69,7 +69,6 @@ namespace {
|
||||
|
||||
// Global flags to modify the RenderableGlobe
|
||||
constexpr bool LimitLevelByAvailableData = true;
|
||||
constexpr bool PerformFrustumCulling = true;
|
||||
constexpr bool PreformHorizonCulling = true;
|
||||
|
||||
// Shadow structure
|
||||
@@ -98,6 +97,7 @@ namespace {
|
||||
// time being. --abock 2018-10-30
|
||||
constexpr int DefaultSkirtedGridSegments = 64;
|
||||
constexpr int UnknownDesiredLevel = -1;
|
||||
constexpr int DefaultHeightTileResolution = 512;
|
||||
|
||||
const openspace::globebrowsing::GeodeticPatch Coverage =
|
||||
openspace::globebrowsing::GeodeticPatch(0, 0, 90, 180);
|
||||
@@ -126,6 +126,13 @@ namespace {
|
||||
openspace::properties::Property::Visibility::Developer
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo PerformFrustumCullingInfo = {
|
||||
"PerformFrustumCulling",
|
||||
"Perform frusum culling",
|
||||
"If this value is set to 'true', frustum culling will be performed.",
|
||||
openspace::properties::Property::Visibility::AdvancedUser
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo ResetTileProviderInfo = {
|
||||
"ResetTileProviders",
|
||||
"Reset tile providers",
|
||||
@@ -543,6 +550,7 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
|
||||
BoolProperty(ShowChunkEdgeInfo, false),
|
||||
BoolProperty(LevelProjectedAreaInfo, true),
|
||||
BoolProperty(ResetTileProviderInfo, false),
|
||||
BoolProperty(PerformFrustumCullingInfo, true),
|
||||
IntProperty(ModelSpaceRenderingInfo, 14, 1, 22),
|
||||
IntProperty(DynamicLodIterationCountInfo, 16, 4, 128)
|
||||
})
|
||||
@@ -649,6 +657,7 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
|
||||
_debugPropertyOwner.addProperty(_debugProperties.showChunkEdges);
|
||||
_debugPropertyOwner.addProperty(_debugProperties.levelByProjectedAreaElseDistance);
|
||||
_debugPropertyOwner.addProperty(_debugProperties.resetTileProviders);
|
||||
_debugPropertyOwner.addProperty(_debugProperties.performFrustumCulling);
|
||||
_debugPropertyOwner.addProperty(_debugProperties.modelSpaceRenderingCutoffLevel);
|
||||
_debugPropertyOwner.addProperty(_debugProperties.dynamicLodIterationCount);
|
||||
|
||||
@@ -1602,11 +1611,11 @@ void RenderableGlobe::setCommonUniforms(ghoul::opengl::ProgramObject& programObj
|
||||
|
||||
const glm::mat3& modelViewTransformMat3 = glm::mat3(modelViewTransform);
|
||||
|
||||
// This is an assumption that the height tile has a resolution of 64 * 64
|
||||
// This is an assumption that the height tile has a resolution of 512 * 512
|
||||
// If it does not it will still produce "correct" normals. If the resolution is
|
||||
// higher the shadows will be softer, if it is lower, pixels will be visible.
|
||||
// Since default is 64 this will most likely work fine.
|
||||
constexpr float TileDelta = 1.f / DefaultSkirtedGridSegments;
|
||||
// Since default is 512 this will most likely work fine.
|
||||
constexpr float TileDelta = 1.f / DefaultHeightTileResolution;
|
||||
const glm::vec3 deltaTheta0 = modelViewTransformMat3 *
|
||||
(glm::vec3(corner10 - corner00) * TileDelta);
|
||||
const glm::vec3 deltaTheta1 = modelViewTransformMat3 *
|
||||
@@ -1890,7 +1899,7 @@ bool RenderableGlobe::testIfCullable(const Chunk& chunk,
|
||||
ZoneScoped;
|
||||
|
||||
return (PreformHorizonCulling && isCullableByHorizon(chunk, renderData, heights)) ||
|
||||
(PerformFrustumCulling && isCullableByFrustum(chunk, renderData, mvp));
|
||||
(_debugProperties.performFrustumCulling && isCullableByFrustum(chunk, renderData, mvp));
|
||||
}
|
||||
|
||||
int RenderableGlobe::desiredLevel(const Chunk& chunk, const RenderData& renderData,
|
||||
@@ -2357,7 +2366,9 @@ int RenderableGlobe::desiredLevelByAvailableTileData(const Chunk& chunk) const {
|
||||
const std::vector<Layer*>& lyrs = _layerManager.layerGroup(gi.id).activeLayers();
|
||||
for (Layer* layer : lyrs) {
|
||||
Tile::Status status = layer->tileStatus(chunk.tileIndex);
|
||||
if (status == Tile::Status::OK) {
|
||||
// Ensure that the current tile is OK and that the tileprovider for the current
|
||||
// layer has enough data to support an additional level.
|
||||
if (status == Tile::Status::OK && layer->tileProvider()->maxLevel() > currLevel + 1) {
|
||||
return UnknownDesiredLevel;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,6 +130,7 @@ private:
|
||||
properties::BoolProperty showChunkEdges;
|
||||
properties::BoolProperty levelByProjectedAreaElseDistance;
|
||||
properties::BoolProperty resetTileProviders;
|
||||
properties::BoolProperty performFrustumCulling;
|
||||
properties::IntProperty modelSpaceRenderingCutoffLevel;
|
||||
properties::IntProperty dynamicLodIterationCount;
|
||||
} _debugProperties;
|
||||
|
||||
@@ -82,10 +82,6 @@ namespace {
|
||||
// [[codegen::verbatim(TilePixelSizeInfo.description)]]
|
||||
std::optional<int> tilePixelSize;
|
||||
|
||||
// Determines whether the tiles should have a padding zone around it, making the
|
||||
// interpolation between tiles more pleasant
|
||||
std::optional<bool> padTiles;
|
||||
|
||||
// Determines if the tiles should be preprocessed before uploading to the GPU
|
||||
std::optional<bool> performPreProcessing;
|
||||
|
||||
@@ -144,7 +140,6 @@ DefaultTileProvider::DefaultTileProvider(const ghoul::Dictionary& dictionary)
|
||||
// 2. Initialize default values for any optional Keys
|
||||
// getValue does not work for integers
|
||||
int pixelSize = p.tilePixelSize.value_or(0);
|
||||
_padTiles = p.padTiles.value_or(_padTiles);
|
||||
|
||||
// Only preprocess height layers by default
|
||||
_performPreProcessing = _layerGroupID == layers::Group::ID::HeightLayers;
|
||||
@@ -193,7 +188,7 @@ DefaultTileProvider::DefaultTileProvider(const ghoul::Dictionary& dictionary)
|
||||
_cacheProperties.compression = codegen::toString(compression);
|
||||
|
||||
TileTextureInitData initData(
|
||||
tileTextureInitData(_layerGroupID, _padTiles, pixelSize)
|
||||
tileTextureInitData(_layerGroupID, pixelSize)
|
||||
);
|
||||
_tilePixelSize = initData.dimensions.x;
|
||||
initAsyncTileDataReader(initData, _cacheProperties);
|
||||
@@ -279,7 +274,7 @@ void DefaultTileProvider::update() {
|
||||
|
||||
if (_asyncTextureDataProvider->shouldBeDeleted()) {
|
||||
initAsyncTileDataReader(
|
||||
tileTextureInitData(_layerGroupID, _padTiles, _tilePixelSize),
|
||||
tileTextureInitData(_layerGroupID, _tilePixelSize),
|
||||
_cacheProperties
|
||||
);
|
||||
}
|
||||
|
||||
@@ -57,7 +57,6 @@ private:
|
||||
std::unique_ptr<AsyncTileDataProvider> _asyncTextureDataProvider;
|
||||
layers::Group::ID _layerGroupID = layers::Group::ID::Unknown;
|
||||
bool _performPreProcessing = false;
|
||||
bool _padTiles = true;
|
||||
TileCacheProperties _cacheProperties;
|
||||
};
|
||||
|
||||
|
||||
@@ -737,7 +737,6 @@ Tile TemporalTileProvider::InterpolateTileProvider::tile(const TileIndex& tileIn
|
||||
prev.texture->dimensions().y,
|
||||
prev.texture->dataType(),
|
||||
prev.texture->format(),
|
||||
TileTextureInitData::PadTiles::No,
|
||||
TileTextureInitData::ShouldAllocateDataOnCPU::No
|
||||
);
|
||||
|
||||
|
||||
@@ -97,7 +97,6 @@ void TileProvider::initializeDefaultTile() {
|
||||
8,
|
||||
GL_UNSIGNED_BYTE,
|
||||
Texture::Format::RGBA,
|
||||
TileTextureInitData::PadTiles::No,
|
||||
TileTextureInitData::ShouldAllocateDataOnCPU::Yes
|
||||
);
|
||||
char* pixels = new char[initData.totalNumBytes];
|
||||
|
||||
@@ -26,9 +26,6 @@
|
||||
|
||||
namespace {
|
||||
|
||||
const glm::ivec2 TilePixelStartOffset = glm::ivec2(-2);
|
||||
const glm::ivec2 TilePixelSizeDifference = glm::ivec2(4);
|
||||
|
||||
size_t numberOfRasters(ghoul::opengl::Texture::Format format) {
|
||||
switch (format) {
|
||||
case ghoul::opengl::Texture::Format::Red:
|
||||
@@ -104,18 +101,17 @@ openspace::globebrowsing::TileTextureInitData::HashKey calculateHashKey(
|
||||
|
||||
namespace openspace::globebrowsing {
|
||||
|
||||
TileTextureInitData tileTextureInitData(layers::Group::ID id, bool shouldPadTiles,
|
||||
TileTextureInitData tileTextureInitData(layers::Group::ID id,
|
||||
size_t preferredTileSize)
|
||||
{
|
||||
switch (id) {
|
||||
case layers::Group::ID::HeightLayers: {
|
||||
const size_t tileSize = preferredTileSize ? preferredTileSize : 64;
|
||||
const size_t tileSize = preferredTileSize ? preferredTileSize : 512;
|
||||
return TileTextureInitData(
|
||||
tileSize,
|
||||
tileSize,
|
||||
GL_FLOAT,
|
||||
ghoul::opengl::Texture::Format::Red,
|
||||
TileTextureInitData::PadTiles(shouldPadTiles),
|
||||
TileTextureInitData::ShouldAllocateDataOnCPU::Yes
|
||||
);
|
||||
}
|
||||
@@ -125,8 +121,7 @@ TileTextureInitData tileTextureInitData(layers::Group::ID id, bool shouldPadTile
|
||||
tileSize,
|
||||
tileSize,
|
||||
GL_UNSIGNED_BYTE,
|
||||
ghoul::opengl::Texture::Format::BGRA,
|
||||
TileTextureInitData::PadTiles(shouldPadTiles)
|
||||
ghoul::opengl::Texture::Format::BGRA
|
||||
);
|
||||
}
|
||||
case layers::Group::ID::Overlays: {
|
||||
@@ -135,8 +130,7 @@ TileTextureInitData tileTextureInitData(layers::Group::ID id, bool shouldPadTile
|
||||
tileSize,
|
||||
tileSize,
|
||||
GL_UNSIGNED_BYTE,
|
||||
ghoul::opengl::Texture::Format::BGRA,
|
||||
TileTextureInitData::PadTiles(shouldPadTiles)
|
||||
ghoul::opengl::Texture::Format::BGRA
|
||||
);
|
||||
}
|
||||
case layers::Group::ID::NightLayers: {
|
||||
@@ -145,8 +139,7 @@ TileTextureInitData tileTextureInitData(layers::Group::ID id, bool shouldPadTile
|
||||
tileSize,
|
||||
tileSize,
|
||||
GL_UNSIGNED_BYTE,
|
||||
ghoul::opengl::Texture::Format::BGRA,
|
||||
TileTextureInitData::PadTiles(shouldPadTiles)
|
||||
ghoul::opengl::Texture::Format::BGRA
|
||||
);
|
||||
}
|
||||
case layers::Group::ID::WaterMasks: {
|
||||
@@ -155,8 +148,7 @@ TileTextureInitData tileTextureInitData(layers::Group::ID id, bool shouldPadTile
|
||||
tileSize,
|
||||
tileSize,
|
||||
GL_UNSIGNED_BYTE,
|
||||
ghoul::opengl::Texture::Format::BGRA,
|
||||
TileTextureInitData::PadTiles(shouldPadTiles)
|
||||
ghoul::opengl::Texture::Format::BGRA
|
||||
);
|
||||
}
|
||||
default: {
|
||||
@@ -167,10 +159,8 @@ TileTextureInitData tileTextureInitData(layers::Group::ID id, bool shouldPadTile
|
||||
|
||||
TileTextureInitData::TileTextureInitData(size_t width, size_t height, GLenum type,
|
||||
ghoul::opengl::Texture::Format textureFormat,
|
||||
PadTiles pad, ShouldAllocateDataOnCPU allocCpu)
|
||||
ShouldAllocateDataOnCPU allocCpu)
|
||||
: dimensions(width, height, 1)
|
||||
, tilePixelStartOffset(pad ? TilePixelStartOffset : glm::ivec2(0))
|
||||
, tilePixelSizeDifference(pad ? TilePixelSizeDifference : glm::ivec2(0))
|
||||
, glType(type)
|
||||
, ghoulTextureFormat(textureFormat)
|
||||
, nRasters(numberOfRasters(ghoulTextureFormat))
|
||||
@@ -179,7 +169,6 @@ TileTextureInitData::TileTextureInitData(size_t width, size_t height, GLenum typ
|
||||
, bytesPerLine(bytesPerPixel * width)
|
||||
, totalNumBytes(bytesPerLine * height)
|
||||
, shouldAllocateDataOnCPU(allocCpu)
|
||||
, padTiles(pad)
|
||||
, hashKey(calculateHashKey(dimensions, ghoulTextureFormat, glType))
|
||||
{}
|
||||
|
||||
|
||||
@@ -39,10 +39,9 @@ class TileTextureInitData {
|
||||
public:
|
||||
using HashKey = uint64_t;
|
||||
BooleanType(ShouldAllocateDataOnCPU);
|
||||
BooleanType(PadTiles);
|
||||
|
||||
TileTextureInitData(size_t width, size_t height, GLenum type,
|
||||
ghoul::opengl::Texture::Format textureFormat, PadTiles pad,
|
||||
ghoul::opengl::Texture::Format textureFormat,
|
||||
ShouldAllocateDataOnCPU allocCpu = ShouldAllocateDataOnCPU::No);
|
||||
|
||||
TileTextureInitData(const TileTextureInitData& original) = default;
|
||||
@@ -54,8 +53,6 @@ public:
|
||||
~TileTextureInitData() = default;
|
||||
|
||||
const glm::ivec3 dimensions;
|
||||
const glm::ivec2 tilePixelStartOffset;
|
||||
const glm::ivec2 tilePixelSizeDifference;
|
||||
const GLenum glType;
|
||||
const ghoul::opengl::Texture::Format ghoulTextureFormat;
|
||||
const size_t nRasters;
|
||||
@@ -64,11 +61,10 @@ public:
|
||||
const size_t bytesPerLine;
|
||||
const size_t totalNumBytes;
|
||||
const bool shouldAllocateDataOnCPU;
|
||||
const bool padTiles;
|
||||
const HashKey hashKey;
|
||||
};
|
||||
|
||||
TileTextureInitData tileTextureInitData(layers::Group::ID id, bool shouldPadTiles,
|
||||
TileTextureInitData tileTextureInitData(layers::Group::ID id,
|
||||
size_t preferredTileSize = 0);
|
||||
|
||||
} // namespace openspace::globebrowsing
|
||||
|
||||
Reference in New Issue
Block a user