void RenderRasterLayer::render(PaintParameters& parameters) { if (parameters.pass != RenderPass::Translucent) return; const auto& evaluated = static_cast<const RasterLayerProperties&>(*evaluatedProperties).evaluated; RasterProgram::Binders paintAttributeData{ evaluated, 0 }; auto draw = [&] (const mat4& matrix, const auto& vertexBuffer, const auto& indexBuffer, const auto& segments, const auto& textureBindings, const std::string& drawScopeID) { auto& programInstance = parameters.programs.getRasterLayerPrograms().raster; const auto allUniformValues = programInstance.computeAllUniformValues( RasterProgram::LayoutUniformValues { uniforms::matrix::Value( matrix ), uniforms::opacity::Value( evaluated.get<RasterOpacity>() ), uniforms::fade_t::Value( 1 ), uniforms::brightness_low::Value( evaluated.get<RasterBrightnessMin>() ), uniforms::brightness_high::Value( evaluated.get<RasterBrightnessMax>() ), uniforms::saturation_factor::Value( saturationFactor(evaluated.get<RasterSaturation>()) ), uniforms::contrast_factor::Value( contrastFactor(evaluated.get<RasterContrast>()) ), uniforms::spin_weights::Value( spinWeights(evaluated.get<RasterHueRotate>()) ), uniforms::buffer_scale::Value( 1.0f ), uniforms::scale_parent::Value( 1.0f ), uniforms::tl_parent::Value( std::array<float, 2> {{ 0.0f, 0.0f }} ), }, paintAttributeData, evaluated, parameters.state.getZoom() ); const auto allAttributeBindings = programInstance.computeAllAttributeBindings( vertexBuffer, paintAttributeData, evaluated ); checkRenderability(parameters, programInstance.activeBindingCount(allAttributeBindings)); programInstance.draw( parameters.context, *parameters.renderPass, gfx::Triangles(), parameters.depthModeForSublayer(0, gfx::DepthMaskType::ReadOnly), gfx::StencilMode::disabled(), parameters.colorModeForRenderPass(), gfx::CullFaceMode::disabled(), indexBuffer, segments, allUniformValues, allAttributeBindings, textureBindings, getID() + "/" + drawScopeID ); }; const gfx::TextureFilterType filter = evaluated.get<RasterResampling>() == RasterResamplingType::Nearest ? gfx::TextureFilterType::Nearest : gfx::TextureFilterType::Linear; if (imageData && !imageData->bucket->needsUpload()) { RasterBucket& bucket = *imageData->bucket; assert(bucket.texture); size_t i = 0; for (const auto& matrix_ : *imageData->matrices) { draw(matrix_, *bucket.vertexBuffer, *bucket.indexBuffer, bucket.segments, RasterProgram::TextureBindings{ textures::image0::Value{ bucket.texture->getResource(), filter }, textures::image1::Value{ bucket.texture->getResource(), filter }, }, bucket.drawScopeID + std::to_string(i++)); } } else { for (const RenderTile& tile : renderTiles) { auto* bucket_ = tile.getBucket(*baseImpl); if (!bucket_) { continue; } auto& bucket = static_cast<RasterBucket&>(*bucket_); if (!bucket.hasData()) continue; assert(bucket.texture); if (bucket.vertexBuffer && bucket.indexBuffer && !bucket.segments.empty()) { // Draw only the parts of the tile that aren't drawn by another tile in the layer. draw(parameters.matrixForTile(tile.id, true), *bucket.vertexBuffer, *bucket.indexBuffer, bucket.segments, RasterProgram::TextureBindings{ textures::image0::Value{ bucket.texture->getResource(), filter }, textures::image1::Value{ bucket.texture->getResource(), filter }, }, bucket.drawScopeID); } else { // Draw the full tile. draw(parameters.matrixForTile(tile.id, true), *parameters.staticData.rasterVertexBuffer, *parameters.staticData.quadTriangleIndexBuffer, parameters.staticData.rasterSegments, RasterProgram::TextureBindings{ textures::image0::Value{ bucket.texture->getResource(), filter }, textures::image1::Value{ bucket.texture->getResource(), filter }, }, bucket.drawScopeID); } } } }
void RenderHillshadeLayer::render(PaintParameters& parameters) { if (parameters.pass != RenderPass::Translucent && parameters.pass != RenderPass::Pass3D) return; const auto& evaluated = static_cast<const HillshadeLayerProperties&>(*evaluatedProperties).evaluated; auto draw = [&] (const mat4& matrix, const auto& vertexBuffer, const auto& indexBuffer, const auto& segments, const UnwrappedTileID& id, const auto& textureBindings) { auto& programInstance = parameters.programs.getHillshadeLayerPrograms().hillshade; const HillshadeProgram::Binders paintAttributeData{ evaluated, 0 }; const auto allUniformValues = programInstance.computeAllUniformValues( HillshadeProgram::LayoutUniformValues { uniforms::matrix::Value( matrix ), uniforms::highlight::Value( evaluated.get<HillshadeHighlightColor>() ), uniforms::shadow::Value( evaluated.get<HillshadeShadowColor>() ), uniforms::accent::Value( evaluated.get<HillshadeAccentColor>() ), uniforms::light::Value( getLight(parameters) ), uniforms::latrange::Value( getLatRange(id) ), }, paintAttributeData, evaluated, parameters.state.getZoom() ); const auto allAttributeBindings = programInstance.computeAllAttributeBindings( vertexBuffer, paintAttributeData, evaluated ); checkRenderability(parameters, programInstance.activeBindingCount(allAttributeBindings)); programInstance.draw( parameters.context, *parameters.renderPass, gfx::Triangles(), parameters.depthModeForSublayer(0, gfx::DepthMaskType::ReadOnly), gfx::StencilMode::disabled(), parameters.colorModeForRenderPass(), gfx::CullFaceMode::disabled(), indexBuffer, segments, allUniformValues, allAttributeBindings, textureBindings, getID() ); }; mat4 mat; matrix::ortho(mat, 0, util::EXTENT, -util::EXTENT, 0, 0, 1); matrix::translate(mat, mat, 0, -util::EXTENT, 0); for (const RenderTile& tile : renderTiles) { auto* bucket_ = tile.getBucket(*baseImpl); if (!bucket_) { continue; } auto& bucket = static_cast<HillshadeBucket&>(*bucket_); if (!bucket.hasData()){ continue; } if (!bucket.isPrepared() && parameters.pass == RenderPass::Pass3D) { assert(bucket.dem); const uint16_t stride = bucket.getDEMData().stride; const uint16_t tilesize = bucket.getDEMData().dim; auto view = parameters.context.createOffscreenTexture({ tilesize, tilesize }); auto renderPass = parameters.encoder->createRenderPass( "hillshade prepare", { *view, Color{ 0.0f, 0.0f, 0.0f, 0.0f }, {}, {} }); const Properties<>::PossiblyEvaluated properties; const HillshadePrepareProgram::Binders paintAttributeData{ properties, 0 }; auto& programInstance = parameters.programs.getHillshadeLayerPrograms().hillshadePrepare; const auto allUniformValues = programInstance.computeAllUniformValues( HillshadePrepareProgram::LayoutUniformValues { uniforms::matrix::Value( mat ), uniforms::dimension::Value( {{stride, stride}} ), uniforms::zoom::Value( float(tile.id.canonical.z) ), uniforms::maxzoom::Value( float(maxzoom) ), }, paintAttributeData, properties, parameters.state.getZoom() ); const auto allAttributeBindings = programInstance.computeAllAttributeBindings( *parameters.staticData.rasterVertexBuffer, paintAttributeData, properties ); checkRenderability(parameters, programInstance.activeBindingCount(allAttributeBindings)); programInstance.draw( parameters.context, *renderPass, gfx::Triangles(), parameters.depthModeForSublayer(0, gfx::DepthMaskType::ReadOnly), gfx::StencilMode::disabled(), parameters.colorModeForRenderPass(), gfx::CullFaceMode::disabled(), *parameters.staticData.quadTriangleIndexBuffer, parameters.staticData.rasterSegments, allUniformValues, allAttributeBindings, HillshadePrepareProgram::TextureBindings{ textures::image::Value{ bucket.dem->getResource() }, }, getID() ); bucket.texture = std::move(view->getTexture()); bucket.setPrepared(true); } else if (parameters.pass == RenderPass::Translucent) { assert(bucket.texture); if (bucket.vertexBuffer && bucket.indexBuffer && !bucket.segments.empty()) { // Draw only the parts of the tile that aren't drawn by another tile in the layer. draw(parameters.matrixForTile(tile.id, true), *bucket.vertexBuffer, *bucket.indexBuffer, bucket.segments, tile.id, HillshadeProgram::TextureBindings{ textures::image::Value{ bucket.texture->getResource(), gfx::TextureFilterType::Linear }, }); } else { // Draw the full tile. draw(parameters.matrixForTile(tile.id, true), *parameters.staticData.rasterVertexBuffer, *parameters.staticData.quadTriangleIndexBuffer, parameters.staticData.rasterSegments, tile.id, HillshadeProgram::TextureBindings{ textures::image::Value{ bucket.texture->getResource(), gfx::TextureFilterType::Linear }, }); } } } }