core: Update Hillshade Algorithms and add Color-Relief Layer support (#3965)
17
.github/workflows/node-ci.yml
vendored
@@ -106,11 +106,11 @@ jobs:
|
|||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
- name: Get OS Architecture
|
- name: Get OS Architecture
|
||||||
if: runner.os == 'MacOS' || runner.os == 'Linux'
|
if: runner.os == 'macOS' || runner.os == 'Linux'
|
||||||
run: uname -m
|
run: uname -m
|
||||||
|
|
||||||
- name: Install dependencies (MacOS)
|
- name: Install dependencies (MacOS)
|
||||||
if: runner.os == 'MacOS'
|
if: runner.os == 'macOS'
|
||||||
env:
|
env:
|
||||||
HOMEBREW_NO_AUTO_UPDATE: 1
|
HOMEBREW_NO_AUTO_UPDATE: 1
|
||||||
HOMEBREW_NO_INSTALL_CLEANUP: 1
|
HOMEBREW_NO_INSTALL_CLEANUP: 1
|
||||||
@@ -200,7 +200,7 @@ jobs:
|
|||||||
key: ${{ runner.os }}-${{ runner.arch }}-cmake-node-module-deps
|
key: ${{ runner.os }}-${{ runner.arch }}-cmake-node-module-deps
|
||||||
|
|
||||||
- name: Configure maplibre-native (MacOS)
|
- name: Configure maplibre-native (MacOS)
|
||||||
if: runner.os == 'MacOS'
|
if: runner.os == 'macOS'
|
||||||
run: |
|
run: |
|
||||||
cmake --preset macos-metal-node -DCMAKE_BUILD_TYPE=${{ env.BUILDTYPE }}
|
cmake --preset macos-metal-node -DCMAKE_BUILD_TYPE=${{ env.BUILDTYPE }}
|
||||||
|
|
||||||
@@ -242,7 +242,7 @@ jobs:
|
|||||||
cmake --preset windows-arm64-opengl-node -DCMAKE_BUILD_TYPE=${{ env.BUILDTYPE }}
|
cmake --preset windows-arm64-opengl-node -DCMAKE_BUILD_TYPE=${{ env.BUILDTYPE }}
|
||||||
|
|
||||||
- name: Build maplibre-native (MacOS/Linux)
|
- name: Build maplibre-native (MacOS/Linux)
|
||||||
if: runner.os == 'MacOS' || runner.os == 'Linux'
|
if: runner.os == 'macOS' || runner.os == 'Linux'
|
||||||
run: |
|
run: |
|
||||||
cmake --build build -j "$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null)"
|
cmake --build build -j "$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null)"
|
||||||
|
|
||||||
@@ -254,7 +254,7 @@ jobs:
|
|||||||
- name: Run render tests on macOS
|
- name: Run render tests on macOS
|
||||||
id: render_tests
|
id: render_tests
|
||||||
if: runner.os == 'macOS'
|
if: runner.os == 'macOS'
|
||||||
continue-on-error: ${{ runner.arch == 'X64' }}
|
continue-on-error: true
|
||||||
run: ./build/mbgl-render-test-runner --manifestPath metrics/macos-xcode11-release-style.json
|
run: ./build/mbgl-render-test-runner --manifestPath metrics/macos-xcode11-release-style.json
|
||||||
|
|
||||||
- name: Upload render test artifacts (MacOS)
|
- name: Upload render test artifacts (MacOS)
|
||||||
@@ -263,6 +263,11 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: render-query-test-results_${{ runner.os }}_${{ matrix.arch }}
|
name: render-query-test-results_${{ runner.os }}_${{ matrix.arch }}
|
||||||
path: metrics/macos-xcode11-release-style.html
|
path: metrics/macos-xcode11-release-style.html
|
||||||
|
if-no-files-found: ignore
|
||||||
|
|
||||||
|
- name: Fail macOS render tests when required
|
||||||
|
if: runner.os == 'macOS' && steps.render_tests.outcome == 'failure' && runner.arch != 'X64'
|
||||||
|
run: exit 1
|
||||||
|
|
||||||
- name: Test (Linux)
|
- name: Test (Linux)
|
||||||
working-directory: platform/node
|
working-directory: platform/node
|
||||||
@@ -270,7 +275,7 @@ jobs:
|
|||||||
run: xvfb-run --auto-servernum npm test
|
run: xvfb-run --auto-servernum npm test
|
||||||
|
|
||||||
- name: Test (MacOS)
|
- name: Test (MacOS)
|
||||||
if: runner.os == 'MacOS'
|
if: runner.os == 'macOS'
|
||||||
continue-on-error: true # flaky on CI
|
continue-on-error: true # flaky on CI
|
||||||
working-directory: platform/node
|
working-directory: platform/node
|
||||||
run: npm test
|
run: npm test
|
||||||
|
|||||||
@@ -172,6 +172,7 @@ list(APPEND SRC_FILES
|
|||||||
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/dynamic_texture_atlas.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/dynamic_texture_atlas.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/gpu_expression.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/gpu_expression.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/hillshade_prepare_drawable_data.hpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/hillshade_prepare_drawable_data.hpp
|
||||||
|
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/color_relief_drawable_data.hpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/image_drawable_data.hpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/image_drawable_data.hpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/line_drawable_data.hpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/line_drawable_data.hpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/symbol_drawable_data.hpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/symbol_drawable_data.hpp
|
||||||
@@ -251,6 +252,7 @@ list(APPEND INCLUDE_FILES
|
|||||||
${PROJECT_SOURCE_DIR}/include/mbgl/layermanager/fill_layer_factory.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/layermanager/fill_layer_factory.hpp
|
||||||
${PROJECT_SOURCE_DIR}/include/mbgl/layermanager/heatmap_layer_factory.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/layermanager/heatmap_layer_factory.hpp
|
||||||
${PROJECT_SOURCE_DIR}/include/mbgl/layermanager/hillshade_layer_factory.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/layermanager/hillshade_layer_factory.hpp
|
||||||
|
${PROJECT_SOURCE_DIR}/include/mbgl/layermanager/color_relief_layer_factory.hpp
|
||||||
${PROJECT_SOURCE_DIR}/include/mbgl/layermanager/layer_factory.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/layermanager/layer_factory.hpp
|
||||||
${PROJECT_SOURCE_DIR}/include/mbgl/layermanager/layer_manager.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/layermanager/layer_manager.hpp
|
||||||
${PROJECT_SOURCE_DIR}/include/mbgl/layermanager/line_layer_factory.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/layermanager/line_layer_factory.hpp
|
||||||
@@ -362,6 +364,7 @@ list(APPEND INCLUDE_FILES
|
|||||||
${PROJECT_SOURCE_DIR}/include/mbgl/style/layers/fill_layer.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/style/layers/fill_layer.hpp
|
||||||
${PROJECT_SOURCE_DIR}/include/mbgl/style/layers/heatmap_layer.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/style/layers/heatmap_layer.hpp
|
||||||
${PROJECT_SOURCE_DIR}/include/mbgl/style/layers/hillshade_layer.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/style/layers/hillshade_layer.hpp
|
||||||
|
${PROJECT_SOURCE_DIR}/include/mbgl/style/layers/color_relief_layer.hpp
|
||||||
${PROJECT_SOURCE_DIR}/include/mbgl/style/layers/line_layer.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/style/layers/line_layer.hpp
|
||||||
${PROJECT_SOURCE_DIR}/include/mbgl/style/layers/location_indicator_layer.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/style/layers/location_indicator_layer.hpp
|
||||||
${PROJECT_SOURCE_DIR}/include/mbgl/style/layers/raster_layer.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/style/layers/raster_layer.hpp
|
||||||
@@ -501,6 +504,7 @@ list(APPEND SRC_FILES
|
|||||||
${PROJECT_SOURCE_DIR}/src/mbgl/layermanager/fill_layer_factory.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/layermanager/fill_layer_factory.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/layermanager/heatmap_layer_factory.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/layermanager/heatmap_layer_factory.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/layermanager/hillshade_layer_factory.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/layermanager/hillshade_layer_factory.cpp
|
||||||
|
${PROJECT_SOURCE_DIR}/src/mbgl/layermanager/color_relief_layer_factory.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/layermanager/layer_factory.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/layermanager/layer_factory.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/layermanager/layer_manager.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/layermanager/layer_manager.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/layermanager/line_layer_factory.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/layermanager/line_layer_factory.cpp
|
||||||
@@ -582,6 +586,10 @@ list(APPEND SRC_FILES
|
|||||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/render_heatmap_layer.hpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/render_heatmap_layer.hpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/render_hillshade_layer.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/render_hillshade_layer.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/render_hillshade_layer.hpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/render_hillshade_layer.hpp
|
||||||
|
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/render_color_relief_layer.cpp
|
||||||
|
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/render_color_relief_layer.hpp
|
||||||
|
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/color_relief_layer_tweaker.cpp
|
||||||
|
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/color_relief_layer_tweaker.hpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/render_line_layer.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/render_line_layer.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/render_line_layer.hpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/render_line_layer.hpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/render_raster_layer.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/render_raster_layer.cpp
|
||||||
@@ -680,6 +688,7 @@ list(APPEND SRC_FILES
|
|||||||
${PROJECT_SOURCE_DIR}/src/mbgl/style/conversion/light.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/style/conversion/light.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/style/conversion/position.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/style/conversion/position.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/style/conversion/property_value.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/style/conversion/property_value.cpp
|
||||||
|
${PROJECT_SOURCE_DIR}/src/mbgl/style/conversion/hillshade_conversions.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/style/conversion/rotation.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/style/conversion/rotation.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/style/conversion/source.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/style/conversion/source.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/style/conversion/source_options.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/style/conversion/source_options.cpp
|
||||||
@@ -765,6 +774,11 @@ list(APPEND SRC_FILES
|
|||||||
${PROJECT_SOURCE_DIR}/src/mbgl/style/layers/hillshade_layer_impl.hpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/style/layers/hillshade_layer_impl.hpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/style/layers/hillshade_layer_properties.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/style/layers/hillshade_layer_properties.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/style/layers/hillshade_layer_properties.hpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/style/layers/hillshade_layer_properties.hpp
|
||||||
|
${PROJECT_SOURCE_DIR}/src/mbgl/style/layers/color_relief_layer.cpp
|
||||||
|
${PROJECT_SOURCE_DIR}/src/mbgl/style/layers/color_relief_layer_impl.cpp
|
||||||
|
${PROJECT_SOURCE_DIR}/src/mbgl/style/layers/color_relief_layer_impl.hpp
|
||||||
|
${PROJECT_SOURCE_DIR}/src/mbgl/style/layers/color_relief_layer_properties.cpp
|
||||||
|
${PROJECT_SOURCE_DIR}/src/mbgl/style/layers/color_relief_layer_properties.hpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/style/layers/line_layer.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/style/layers/line_layer.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/style/layers/line_layer_impl.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/style/layers/line_layer_impl.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/style/layers/line_layer_impl.hpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/style/layers/line_layer_impl.hpp
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ MLN_PUBLIC_GENERATED_STYLE_HEADERS = [
|
|||||||
"include/mbgl/style/layers/fill_extrusion_layer.hpp",
|
"include/mbgl/style/layers/fill_extrusion_layer.hpp",
|
||||||
"include/mbgl/style/layers/raster_layer.hpp",
|
"include/mbgl/style/layers/raster_layer.hpp",
|
||||||
"include/mbgl/style/layers/hillshade_layer.hpp",
|
"include/mbgl/style/layers/hillshade_layer.hpp",
|
||||||
|
"include/mbgl/style/layers/color_relief_layer.hpp",
|
||||||
"include/mbgl/style/layers/background_layer.hpp",
|
"include/mbgl/style/layers/background_layer.hpp",
|
||||||
"include/mbgl/style/layers/location_indicator_layer.hpp",
|
"include/mbgl/style/layers/location_indicator_layer.hpp",
|
||||||
"include/mbgl/style/light.hpp",
|
"include/mbgl/style/light.hpp",
|
||||||
@@ -37,6 +38,7 @@ MLN_PRIVATE_GENERATED_STYLE_HEADERS = [
|
|||||||
"src/mbgl/style/layers/fill_extrusion_layer_properties.hpp",
|
"src/mbgl/style/layers/fill_extrusion_layer_properties.hpp",
|
||||||
"src/mbgl/style/layers/raster_layer_properties.hpp",
|
"src/mbgl/style/layers/raster_layer_properties.hpp",
|
||||||
"src/mbgl/style/layers/hillshade_layer_properties.hpp",
|
"src/mbgl/style/layers/hillshade_layer_properties.hpp",
|
||||||
|
"src/mbgl/style/layers/color_relief_layer_properties.hpp",
|
||||||
"src/mbgl/style/layers/background_layer_properties.hpp",
|
"src/mbgl/style/layers/background_layer_properties.hpp",
|
||||||
"src/mbgl/style/layers/location_indicator_layer_properties.hpp",
|
"src/mbgl/style/layers/location_indicator_layer_properties.hpp",
|
||||||
]
|
]
|
||||||
@@ -58,6 +60,8 @@ MLN_GENERATED_STYLE_SOURCE = [
|
|||||||
"src/mbgl/style/layers/raster_layer.cpp",
|
"src/mbgl/style/layers/raster_layer.cpp",
|
||||||
"src/mbgl/style/layers/hillshade_layer_properties.cpp",
|
"src/mbgl/style/layers/hillshade_layer_properties.cpp",
|
||||||
"src/mbgl/style/layers/hillshade_layer.cpp",
|
"src/mbgl/style/layers/hillshade_layer.cpp",
|
||||||
|
"src/mbgl/style/layers/color_relief_layer_properties.cpp",
|
||||||
|
"src/mbgl/style/layers/color_relief_layer.cpp",
|
||||||
"src/mbgl/style/layers/background_layer_properties.cpp",
|
"src/mbgl/style/layers/background_layer_properties.cpp",
|
||||||
"src/mbgl/style/layers/background_layer.cpp",
|
"src/mbgl/style/layers/background_layer.cpp",
|
||||||
"src/mbgl/style/layers/location_indicator_layer_properties.cpp",
|
"src/mbgl/style/layers/location_indicator_layer_properties.cpp",
|
||||||
@@ -95,6 +99,7 @@ MLN_GENERATED_OPENGL_SHADER_HEADERS = [
|
|||||||
"include/mbgl/shaders/gl/heatmap_texture.hpp",
|
"include/mbgl/shaders/gl/heatmap_texture.hpp",
|
||||||
"include/mbgl/shaders/gl/hillshade_prepare.hpp",
|
"include/mbgl/shaders/gl/hillshade_prepare.hpp",
|
||||||
"include/mbgl/shaders/gl/hillshade.hpp",
|
"include/mbgl/shaders/gl/hillshade.hpp",
|
||||||
|
"include/mbgl/shaders/gl/color_relief.hpp",
|
||||||
"include/mbgl/shaders/gl/line_gradient.hpp",
|
"include/mbgl/shaders/gl/line_gradient.hpp",
|
||||||
"include/mbgl/shaders/gl/line_pattern.hpp",
|
"include/mbgl/shaders/gl/line_pattern.hpp",
|
||||||
"include/mbgl/shaders/gl/line_sdf.hpp",
|
"include/mbgl/shaders/gl/line_sdf.hpp",
|
||||||
@@ -161,6 +166,7 @@ MLN_CORE_SOURCE = [
|
|||||||
"src/mbgl/layermanager/fill_layer_factory.cpp",
|
"src/mbgl/layermanager/fill_layer_factory.cpp",
|
||||||
"src/mbgl/layermanager/heatmap_layer_factory.cpp",
|
"src/mbgl/layermanager/heatmap_layer_factory.cpp",
|
||||||
"src/mbgl/layermanager/hillshade_layer_factory.cpp",
|
"src/mbgl/layermanager/hillshade_layer_factory.cpp",
|
||||||
|
"src/mbgl/layermanager/color_relief_layer_factory.cpp",
|
||||||
"src/mbgl/layermanager/layer_factory.cpp",
|
"src/mbgl/layermanager/layer_factory.cpp",
|
||||||
"src/mbgl/layermanager/layer_manager.cpp",
|
"src/mbgl/layermanager/layer_manager.cpp",
|
||||||
"src/mbgl/layermanager/line_layer_factory.cpp",
|
"src/mbgl/layermanager/line_layer_factory.cpp",
|
||||||
@@ -237,6 +243,8 @@ MLN_CORE_SOURCE = [
|
|||||||
"src/mbgl/renderer/layers/render_heatmap_layer.hpp",
|
"src/mbgl/renderer/layers/render_heatmap_layer.hpp",
|
||||||
"src/mbgl/renderer/layers/render_hillshade_layer.cpp",
|
"src/mbgl/renderer/layers/render_hillshade_layer.cpp",
|
||||||
"src/mbgl/renderer/layers/render_hillshade_layer.hpp",
|
"src/mbgl/renderer/layers/render_hillshade_layer.hpp",
|
||||||
|
"src/mbgl/renderer/layers/render_color_relief_layer.cpp",
|
||||||
|
"src/mbgl/renderer/layers/render_color_relief_layer.hpp",
|
||||||
"src/mbgl/renderer/layers/render_line_layer.cpp",
|
"src/mbgl/renderer/layers/render_line_layer.cpp",
|
||||||
"src/mbgl/renderer/layers/render_line_layer.hpp",
|
"src/mbgl/renderer/layers/render_line_layer.hpp",
|
||||||
"src/mbgl/renderer/layers/render_location_indicator_layer.cpp",
|
"src/mbgl/renderer/layers/render_location_indicator_layer.cpp",
|
||||||
@@ -336,6 +344,7 @@ MLN_CORE_SOURCE = [
|
|||||||
"src/mbgl/style/conversion/light.cpp",
|
"src/mbgl/style/conversion/light.cpp",
|
||||||
"src/mbgl/style/conversion/position.cpp",
|
"src/mbgl/style/conversion/position.cpp",
|
||||||
"src/mbgl/style/conversion/property_value.cpp",
|
"src/mbgl/style/conversion/property_value.cpp",
|
||||||
|
"src/mbgl/style/conversion/hillshade_conversions.cpp",
|
||||||
"src/mbgl/style/conversion/rotation.cpp",
|
"src/mbgl/style/conversion/rotation.cpp",
|
||||||
"src/mbgl/style/conversion/source.cpp",
|
"src/mbgl/style/conversion/source.cpp",
|
||||||
"src/mbgl/style/conversion/source_options.cpp",
|
"src/mbgl/style/conversion/source_options.cpp",
|
||||||
@@ -409,6 +418,8 @@ MLN_CORE_SOURCE = [
|
|||||||
"src/mbgl/style/layers/heatmap_layer_impl.hpp",
|
"src/mbgl/style/layers/heatmap_layer_impl.hpp",
|
||||||
"src/mbgl/style/layers/hillshade_layer_impl.cpp",
|
"src/mbgl/style/layers/hillshade_layer_impl.cpp",
|
||||||
"src/mbgl/style/layers/hillshade_layer_impl.hpp",
|
"src/mbgl/style/layers/hillshade_layer_impl.hpp",
|
||||||
|
"src/mbgl/style/layers/color_relief_layer_impl.cpp",
|
||||||
|
"src/mbgl/style/layers/color_relief_layer_impl.hpp",
|
||||||
"src/mbgl/style/layers/line_layer_impl.cpp",
|
"src/mbgl/style/layers/line_layer_impl.cpp",
|
||||||
"src/mbgl/style/layers/line_layer_impl.hpp",
|
"src/mbgl/style/layers/line_layer_impl.hpp",
|
||||||
"src/mbgl/style/layers/location_indicator_layer_impl.cpp",
|
"src/mbgl/style/layers/location_indicator_layer_impl.cpp",
|
||||||
@@ -652,6 +663,7 @@ MLN_CORE_HEADERS = [
|
|||||||
"include/mbgl/layermanager/fill_layer_factory.hpp",
|
"include/mbgl/layermanager/fill_layer_factory.hpp",
|
||||||
"include/mbgl/layermanager/heatmap_layer_factory.hpp",
|
"include/mbgl/layermanager/heatmap_layer_factory.hpp",
|
||||||
"include/mbgl/layermanager/hillshade_layer_factory.hpp",
|
"include/mbgl/layermanager/hillshade_layer_factory.hpp",
|
||||||
|
"include/mbgl/layermanager/color_relief_layer_factory.hpp",
|
||||||
"include/mbgl/layermanager/layer_factory.hpp",
|
"include/mbgl/layermanager/layer_factory.hpp",
|
||||||
"include/mbgl/layermanager/layer_manager.hpp",
|
"include/mbgl/layermanager/layer_manager.hpp",
|
||||||
"include/mbgl/layermanager/line_layer_factory.hpp",
|
"include/mbgl/layermanager/line_layer_factory.hpp",
|
||||||
@@ -912,6 +924,7 @@ MLN_DRAWABLES_SOURCE = [
|
|||||||
"src/mbgl/gfx/dynamic_texture_atlas.cpp",
|
"src/mbgl/gfx/dynamic_texture_atlas.cpp",
|
||||||
"src/mbgl/gfx/gpu_expression.cpp",
|
"src/mbgl/gfx/gpu_expression.cpp",
|
||||||
"src/mbgl/gfx/hillshade_prepare_drawable_data.hpp",
|
"src/mbgl/gfx/hillshade_prepare_drawable_data.hpp",
|
||||||
|
"src/mbgl/gfx/color_relief_drawable_data.hpp",
|
||||||
"src/mbgl/gfx/image_drawable_data.hpp",
|
"src/mbgl/gfx/image_drawable_data.hpp",
|
||||||
"src/mbgl/gfx/line_drawable_data.hpp",
|
"src/mbgl/gfx/line_drawable_data.hpp",
|
||||||
"src/mbgl/gfx/symbol_drawable_data.hpp",
|
"src/mbgl/gfx/symbol_drawable_data.hpp",
|
||||||
@@ -927,6 +940,8 @@ MLN_DRAWABLES_SOURCE = [
|
|||||||
"src/mbgl/renderer/layers/background_layer_tweaker.hpp",
|
"src/mbgl/renderer/layers/background_layer_tweaker.hpp",
|
||||||
"src/mbgl/renderer/layers/circle_layer_tweaker.cpp",
|
"src/mbgl/renderer/layers/circle_layer_tweaker.cpp",
|
||||||
"src/mbgl/renderer/layers/circle_layer_tweaker.hpp",
|
"src/mbgl/renderer/layers/circle_layer_tweaker.hpp",
|
||||||
|
"src/mbgl/renderer/layers/color_relief_layer_tweaker.cpp",
|
||||||
|
"src/mbgl/renderer/layers/color_relief_layer_tweaker.hpp",
|
||||||
"src/mbgl/renderer/layers/fill_layer_tweaker.cpp",
|
"src/mbgl/renderer/layers/fill_layer_tweaker.cpp",
|
||||||
"src/mbgl/renderer/layers/fill_layer_tweaker.hpp",
|
"src/mbgl/renderer/layers/fill_layer_tweaker.hpp",
|
||||||
"src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.cpp",
|
"src/mbgl/renderer/layers/fill_extrusion_layer_tweaker.cpp",
|
||||||
@@ -987,6 +1002,7 @@ MLN_DRAWABLES_HEADERS = [
|
|||||||
"include/mbgl/shaders/heatmap_layer_ubo.hpp",
|
"include/mbgl/shaders/heatmap_layer_ubo.hpp",
|
||||||
"include/mbgl/shaders/heatmap_texture_layer_ubo.hpp",
|
"include/mbgl/shaders/heatmap_texture_layer_ubo.hpp",
|
||||||
"include/mbgl/shaders/hillshade_layer_ubo.hpp",
|
"include/mbgl/shaders/hillshade_layer_ubo.hpp",
|
||||||
|
"include/mbgl/shaders/color_relief_layer_ubo.hpp",
|
||||||
"include/mbgl/shaders/hillshade_prepare_layer_ubo.hpp",
|
"include/mbgl/shaders/hillshade_prepare_layer_ubo.hpp",
|
||||||
"include/mbgl/shaders/layer_ubo.hpp",
|
"include/mbgl/shaders/layer_ubo.hpp",
|
||||||
"include/mbgl/shaders/line_layer_ubo.hpp",
|
"include/mbgl/shaders/line_layer_ubo.hpp",
|
||||||
@@ -1063,6 +1079,7 @@ MLN_DRAWABLES_MTL_SOURCE = [
|
|||||||
"src/mbgl/shaders/mtl/heatmap_texture.cpp",
|
"src/mbgl/shaders/mtl/heatmap_texture.cpp",
|
||||||
"src/mbgl/shaders/mtl/hillshade.cpp",
|
"src/mbgl/shaders/mtl/hillshade.cpp",
|
||||||
"src/mbgl/shaders/mtl/hillshade_prepare.cpp",
|
"src/mbgl/shaders/mtl/hillshade_prepare.cpp",
|
||||||
|
"src/mbgl/shaders/mtl/color_relief.cpp",
|
||||||
"src/mbgl/shaders/mtl/line.cpp",
|
"src/mbgl/shaders/mtl/line.cpp",
|
||||||
"src/mbgl/shaders/mtl/location_indicator.cpp",
|
"src/mbgl/shaders/mtl/location_indicator.cpp",
|
||||||
"src/mbgl/shaders/mtl/raster.cpp",
|
"src/mbgl/shaders/mtl/raster.cpp",
|
||||||
@@ -1105,6 +1122,7 @@ MLN_DRAWABLES_MTL_HEADERS = [
|
|||||||
"include/mbgl/shaders/mtl/heatmap_texture.hpp",
|
"include/mbgl/shaders/mtl/heatmap_texture.hpp",
|
||||||
"include/mbgl/shaders/mtl/hillshade.hpp",
|
"include/mbgl/shaders/mtl/hillshade.hpp",
|
||||||
"include/mbgl/shaders/mtl/hillshade_prepare.hpp",
|
"include/mbgl/shaders/mtl/hillshade_prepare.hpp",
|
||||||
|
"include/mbgl/shaders/mtl/color_relief.hpp",
|
||||||
"include/mbgl/shaders/mtl/line.hpp",
|
"include/mbgl/shaders/mtl/line.hpp",
|
||||||
"include/mbgl/shaders/mtl/location_indicator.hpp",
|
"include/mbgl/shaders/mtl/location_indicator.hpp",
|
||||||
"include/mbgl/shaders/mtl/raster.hpp",
|
"include/mbgl/shaders/mtl/raster.hpp",
|
||||||
@@ -1150,6 +1168,7 @@ MLN_DRAWABLES_WEBGPU_SOURCE = [
|
|||||||
"src/mbgl/shaders/webgpu/heatmap_texture.cpp",
|
"src/mbgl/shaders/webgpu/heatmap_texture.cpp",
|
||||||
"src/mbgl/shaders/webgpu/hillshade.cpp",
|
"src/mbgl/shaders/webgpu/hillshade.cpp",
|
||||||
"src/mbgl/shaders/webgpu/hillshade_prepare.cpp",
|
"src/mbgl/shaders/webgpu/hillshade_prepare.cpp",
|
||||||
|
"src/mbgl/shaders/webgpu/color_relief.cpp",
|
||||||
"src/mbgl/shaders/webgpu/line.cpp",
|
"src/mbgl/shaders/webgpu/line.cpp",
|
||||||
"src/mbgl/shaders/webgpu/location_indicator.cpp",
|
"src/mbgl/shaders/webgpu/location_indicator.cpp",
|
||||||
"src/mbgl/shaders/webgpu/raster.cpp",
|
"src/mbgl/shaders/webgpu/raster.cpp",
|
||||||
@@ -1192,6 +1211,7 @@ MLN_DRAWABLES_WEBGPU_HEADERS = [
|
|||||||
"include/mbgl/shaders/webgpu/heatmap_texture.hpp",
|
"include/mbgl/shaders/webgpu/heatmap_texture.hpp",
|
||||||
"include/mbgl/shaders/webgpu/hillshade.hpp",
|
"include/mbgl/shaders/webgpu/hillshade.hpp",
|
||||||
"include/mbgl/shaders/webgpu/hillshade_prepare.hpp",
|
"include/mbgl/shaders/webgpu/hillshade_prepare.hpp",
|
||||||
|
"include/mbgl/shaders/webgpu/color_relief.hpp",
|
||||||
"include/mbgl/shaders/webgpu/line.hpp",
|
"include/mbgl/shaders/webgpu/line.hpp",
|
||||||
"include/mbgl/shaders/webgpu/location_indicator.hpp",
|
"include/mbgl/shaders/webgpu/location_indicator.hpp",
|
||||||
"include/mbgl/shaders/webgpu/raster.hpp",
|
"include/mbgl/shaders/webgpu/raster.hpp",
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ list(APPEND
|
|||||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/heatmap_texture.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/heatmap_texture.hpp
|
||||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/hillshade.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/hillshade.hpp
|
||||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/hillshade_prepare.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/hillshade_prepare.hpp
|
||||||
|
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/color_relief.hpp
|
||||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/line.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/line.hpp
|
||||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/location_indicator.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/location_indicator.hpp
|
||||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/raster.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/raster.hpp
|
||||||
@@ -86,6 +87,7 @@ list(APPEND
|
|||||||
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/heatmap_texture.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/heatmap_texture.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/hillshade.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/hillshade.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/hillshade_prepare.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/hillshade_prepare.cpp
|
||||||
|
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/color_relief.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/line.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/line.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/location_indicator.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/location_indicator.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/raster.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/raster.cpp
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ list(APPEND
|
|||||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/heatmap_texture.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/heatmap_texture.hpp
|
||||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/hillshade_prepare.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/hillshade_prepare.hpp
|
||||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/hillshade.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/hillshade.hpp
|
||||||
|
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/color_relief.hpp
|
||||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/line.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/line.hpp
|
||||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/line_gradient.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/line_gradient.hpp
|
||||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/line_pattern.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/gl/line_pattern.hpp
|
||||||
@@ -113,6 +114,7 @@ list(APPEND INCLUDE_FILES
|
|||||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/heatmap_layer_ubo.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/heatmap_layer_ubo.hpp
|
||||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/heatmap_texture_layer_ubo.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/heatmap_texture_layer_ubo.hpp
|
||||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/hillshade_layer_ubo.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/hillshade_layer_ubo.hpp
|
||||||
|
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/color_relief_layer_ubo.hpp
|
||||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/hillshade_prepare_layer_ubo.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/hillshade_prepare_layer_ubo.hpp
|
||||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/layer_ubo.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/layer_ubo.hpp
|
||||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/line_layer_ubo.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/line_layer_ubo.hpp
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ list(APPEND
|
|||||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/vulkan/heatmap_texture.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/vulkan/heatmap_texture.hpp
|
||||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/vulkan/hillshade.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/vulkan/hillshade.hpp
|
||||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/vulkan/hillshade_prepare.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/vulkan/hillshade_prepare.hpp
|
||||||
|
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/vulkan/color_relief.hpp
|
||||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/vulkan/line.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/vulkan/line.hpp
|
||||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/vulkan/location_indicator.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/vulkan/location_indicator.hpp
|
||||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/vulkan/raster.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/vulkan/raster.hpp
|
||||||
@@ -91,6 +92,7 @@ list(APPEND
|
|||||||
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/vulkan/heatmap_texture.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/vulkan/heatmap_texture.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/vulkan/hillshade.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/vulkan/hillshade.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/vulkan/hillshade_prepare.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/vulkan/hillshade_prepare.cpp
|
||||||
|
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/vulkan/color_relief.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/vulkan/line.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/vulkan/line.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/vulkan/location_indicator.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/vulkan/location_indicator.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/vulkan/raster.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/vulkan/raster.cpp
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ list(APPEND
|
|||||||
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/webgpu/heatmap_texture.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/webgpu/heatmap_texture.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/webgpu/hillshade.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/webgpu/hillshade.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/webgpu/hillshade_prepare.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/webgpu/hillshade_prepare.cpp
|
||||||
|
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/webgpu/color_relief.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/webgpu/line.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/webgpu/line.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/webgpu/location_indicator.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/webgpu/location_indicator.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/webgpu/raster.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/webgpu/raster.cpp
|
||||||
@@ -75,6 +76,7 @@ list(APPEND
|
|||||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/webgpu/heatmap_texture.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/webgpu/heatmap_texture.hpp
|
||||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/webgpu/hillshade.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/webgpu/hillshade.hpp
|
||||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/webgpu/hillshade_prepare.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/webgpu/hillshade_prepare.hpp
|
||||||
|
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/webgpu/color_relief.hpp
|
||||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/webgpu/line.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/webgpu/line.hpp
|
||||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/webgpu/location_indicator.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/webgpu/location_indicator.hpp
|
||||||
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/webgpu/raster.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/webgpu/raster.hpp
|
||||||
|
|||||||
15
include/mbgl/layermanager/color_relief_layer_factory.hpp
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <mbgl/layermanager/layer_factory.hpp>
|
||||||
|
|
||||||
|
namespace mbgl {
|
||||||
|
|
||||||
|
class ColorReliefLayerFactory : public LayerFactory {
|
||||||
|
protected:
|
||||||
|
const style::LayerTypeInfo* getTypeInfo() const noexcept final;
|
||||||
|
std::unique_ptr<style::Layer> createLayer(const std::string& id,
|
||||||
|
const style::conversion::Convertible& value) noexcept final;
|
||||||
|
std::unique_ptr<RenderLayer> createRenderLayer(Immutable<style::Layer::Impl>) noexcept final;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mbgl
|
||||||
32
include/mbgl/shaders/color_relief_layer_ubo.hpp
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <mbgl/shaders/layer_ubo.hpp>
|
||||||
|
|
||||||
|
namespace mbgl {
|
||||||
|
namespace shaders {
|
||||||
|
|
||||||
|
struct alignas(16) ColorReliefDrawableUBO {
|
||||||
|
/* 0 */ std::array<float, 4 * 4> matrix;
|
||||||
|
/* 64 */
|
||||||
|
};
|
||||||
|
static_assert(sizeof(ColorReliefDrawableUBO) == 64);
|
||||||
|
|
||||||
|
struct alignas(16) ColorReliefTilePropsUBO {
|
||||||
|
/* 0 */ std::array<float, 4> unpack; // DEM unpack vector
|
||||||
|
/* 16 */ std::array<float, 2> dimension; // Texture dimensions
|
||||||
|
/* 24 */ int32_t color_ramp_size; // Number of color stops
|
||||||
|
/* 28 */ float pad_tile0; // Padding for alignment
|
||||||
|
/* 32 */
|
||||||
|
};
|
||||||
|
static_assert(sizeof(ColorReliefTilePropsUBO) == 32);
|
||||||
|
|
||||||
|
struct alignas(16) ColorReliefEvaluatedPropsUBO {
|
||||||
|
/* 0 */ float opacity;
|
||||||
|
/* 4 */ float pad_eval0;
|
||||||
|
/* 8 */ float pad_eval1;
|
||||||
|
/* 12 */ float pad_eval2;
|
||||||
|
/* 16 */
|
||||||
|
};
|
||||||
|
static_assert(sizeof(ColorReliefEvaluatedPropsUBO) == 16);
|
||||||
|
|
||||||
|
} // namespace shaders
|
||||||
|
} // namespace mbgl
|
||||||
119
include/mbgl/shaders/gl/color_relief.hpp
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
// Generated code, do not modify this file!
|
||||||
|
#pragma once
|
||||||
|
#include <mbgl/shaders/shader_source.hpp>
|
||||||
|
|
||||||
|
namespace mbgl {
|
||||||
|
namespace shaders {
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct ShaderSource<BuiltIn::ColorReliefShader, gfx::Backend::Type::OpenGL> {
|
||||||
|
static constexpr const char* name = "ColorReliefShader";
|
||||||
|
static constexpr const char* vertex = R"(layout(std140) uniform ColorReliefDrawableUBO {
|
||||||
|
highp mat4 u_matrix;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(std140) uniform ColorReliefTilePropsUBO {
|
||||||
|
highp vec4 u_unpack;
|
||||||
|
highp vec2 u_dimension;
|
||||||
|
highp int u_color_ramp_size;
|
||||||
|
highp float pad_tile0;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout (location = 0) in vec2 a_pos;
|
||||||
|
layout (location = 1) in vec2 a_texture_pos;
|
||||||
|
out vec2 v_pos;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
gl_Position = u_matrix * vec4(a_pos, 0, 1);
|
||||||
|
|
||||||
|
highp vec2 epsilon = 1.0 / u_dimension;
|
||||||
|
float scale = (u_dimension.x - 2.0) / u_dimension.x;
|
||||||
|
v_pos = (a_texture_pos / 8192.0) * scale + epsilon;
|
||||||
|
|
||||||
|
// Handle poles
|
||||||
|
if (a_pos.y < -32767.5) v_pos.y = 0.0;
|
||||||
|
if (a_pos.y > 32766.5) v_pos.y = 1.0;
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
static constexpr const char* fragment = R"(layout(std140) uniform ColorReliefDrawableUBO {
|
||||||
|
highp mat4 u_matrix;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(std140) uniform ColorReliefTilePropsUBO {
|
||||||
|
highp vec4 u_unpack;
|
||||||
|
highp vec2 u_dimension;
|
||||||
|
highp int u_color_ramp_size;
|
||||||
|
highp float pad_tile0;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(std140) uniform ColorReliefEvaluatedPropsUBO {
|
||||||
|
highp float u_opacity;
|
||||||
|
highp float pad_eval0;
|
||||||
|
highp float pad_eval1;
|
||||||
|
highp float pad_eval2;
|
||||||
|
};
|
||||||
|
|
||||||
|
uniform sampler2D u_image;
|
||||||
|
uniform sampler2D u_elevation_stops;
|
||||||
|
uniform sampler2D u_color_stops;
|
||||||
|
|
||||||
|
in vec2 v_pos;
|
||||||
|
|
||||||
|
float getElevation(vec2 coord) {
|
||||||
|
// Convert encoded elevation value to meters
|
||||||
|
vec4 data = texture(u_image, coord) * 255.0;
|
||||||
|
data.a = -1.0;
|
||||||
|
return dot(data, u_unpack);
|
||||||
|
}
|
||||||
|
|
||||||
|
float getElevationStop(int stop) {
|
||||||
|
// Elevation stops are plain float values, not terrain-RGB encoded
|
||||||
|
float x = (float(stop) + 0.5) / float(u_color_ramp_size);
|
||||||
|
return texture(u_elevation_stops, vec2(x, 0.5)).r;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 getColorStop(int stop) {
|
||||||
|
float x = (float(stop) + 0.5) / float(u_color_ramp_size);
|
||||||
|
return texture(u_color_stops, vec2(x, 0.5));
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
float el = getElevation(v_pos);
|
||||||
|
|
||||||
|
// Binary search for color stops
|
||||||
|
int r = (u_color_ramp_size - 1);
|
||||||
|
int l = 0;
|
||||||
|
|
||||||
|
while (r - l > 1) {
|
||||||
|
int m = (r + l) / 2;
|
||||||
|
float el_m = getElevationStop(m);
|
||||||
|
if (el < el_m) {
|
||||||
|
r = m;
|
||||||
|
} else {
|
||||||
|
l = m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get elevation values for interpolation
|
||||||
|
float el_l = getElevationStop(l);
|
||||||
|
float el_r = getElevationStop(r);
|
||||||
|
|
||||||
|
// Get colors for interpolation
|
||||||
|
vec4 color_l = getColorStop(l);
|
||||||
|
vec4 color_r = getColorStop(r);
|
||||||
|
|
||||||
|
// Interpolate between the two colors
|
||||||
|
// Guard against division by zero when el_r == el_l
|
||||||
|
float denom = el_r - el_l;
|
||||||
|
float t = (abs(denom) < 0.0001) ? 0.0 : clamp((el - el_l) / denom, 0.0, 1.0);
|
||||||
|
fragColor = u_opacity * mix(color_l, color_r, t);
|
||||||
|
|
||||||
|
#ifdef OVERDRAW_INSPECTOR
|
||||||
|
fragColor = vec4(1.0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace shaders
|
||||||
|
} // namespace mbgl
|
||||||
@@ -69,7 +69,7 @@ mediump float radius = u_radius;
|
|||||||
// weight * u_intensity * GAUSS_COEF * exp(-0.5 * 3.0^2 * S^2) == ZERO
|
// weight * u_intensity * GAUSS_COEF * exp(-0.5 * 3.0^2 * S^2) == ZERO
|
||||||
// Which solves to:
|
// Which solves to:
|
||||||
// S = sqrt(-2.0 * log(ZERO / (weight * u_intensity * GAUSS_COEF))) / 3.0
|
// S = sqrt(-2.0 * log(ZERO / (weight * u_intensity * GAUSS_COEF))) / 3.0
|
||||||
float S = sqrt(-2.0 * log(ZERO / weight / u_intensity / GAUSS_COEF)) / 3.0;
|
float S = sqrt(-2.0 * log(ZERO / (max(weight, ZERO) * max(u_intensity, ZERO) * GAUSS_COEF))) / 3.0;
|
||||||
|
|
||||||
// Pass the varying in units of radius
|
// Pass the varying in units of radius
|
||||||
v_extrude = S * unscaled_extrude;
|
v_extrude = S * unscaled_extrude;
|
||||||
|
|||||||
@@ -27,53 +27,183 @@ uniform sampler2D u_image;
|
|||||||
|
|
||||||
layout(std140) uniform HillshadeTilePropsUBO {
|
layout(std140) uniform HillshadeTilePropsUBO {
|
||||||
highp vec2 u_latrange;
|
highp vec2 u_latrange;
|
||||||
highp vec2 u_light;
|
highp float u_exaggeration;
|
||||||
|
highp int u_method; // Hillshade method (0: STANDARD, 1: COMBINED, 2: IGOR, 3: MULTIDIRECTIONAL, 4: BASIC)
|
||||||
|
highp int u_num_lights; // Number of light sources (1-4)
|
||||||
|
highp float u_pad0;
|
||||||
|
highp float u_pad1;
|
||||||
|
highp float u_pad2;
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(std140) uniform HillshadeEvaluatedPropsUBO {
|
layout(std140) uniform HillshadeEvaluatedPropsUBO {
|
||||||
highp vec4 u_highlight;
|
|
||||||
highp vec4 u_shadow;
|
|
||||||
highp vec4 u_accent;
|
highp vec4 u_accent;
|
||||||
|
highp vec4 u_altitudes; // Up to 4 altitude values (in radians)
|
||||||
|
highp vec4 u_azimuths; // Up to 4 azimuth values (in radians)
|
||||||
|
highp vec4 u_shadows[4]; // Shadow colors (up to 4 lights)
|
||||||
|
highp vec4 u_highlights[4]; // Highlight colors (up to 4 lights)
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PI 3.141592653589793
|
#define PI 3.141592653589793
|
||||||
|
|
||||||
|
#define STANDARD 0
|
||||||
|
#define COMBINED 1
|
||||||
|
#define IGOR 2
|
||||||
|
#define MULTIDIRECTIONAL 3
|
||||||
|
#define BASIC 4
|
||||||
|
|
||||||
|
float get_aspect(vec2 deriv) {
|
||||||
|
return deriv.x != 0.0 ?
|
||||||
|
atan(deriv.y, -deriv.x) : PI / 2.0 * (deriv.y > 0.0 ? 1.0 : -1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// MapLibre's legacy hillshade algorithm (Method 0)
|
||||||
|
void standard_hillshade(vec2 deriv) {
|
||||||
|
float azimuth = u_azimuths.x + PI;
|
||||||
|
float slope = atan(0.625 * length(deriv));
|
||||||
|
float aspect = get_aspect(deriv);
|
||||||
|
|
||||||
|
// Note: This implementation uses u_exaggeration as intensity, though it typically should be derived from u_altitudes.x.
|
||||||
|
float intensity = u_exaggeration;
|
||||||
|
|
||||||
|
// Scale the slope exponentially based on intensity
|
||||||
|
float base = 1.875 - intensity * 1.75;
|
||||||
|
float maxValue = 0.5 * PI;
|
||||||
|
float scaledSlope = abs(intensity - 0.5) > 1e-6 ? ((pow(base, slope) - 1.0) / (pow(base, maxValue) - 1.0)) * maxValue : slope;
|
||||||
|
|
||||||
|
float accent = cos(scaledSlope);
|
||||||
|
vec4 accent_color = (1.0 - accent) * u_accent * clamp(intensity * 2.0, 0.0, 1.0);
|
||||||
|
|
||||||
|
// Calculate shadow/highlight based on aspect
|
||||||
|
float shade = abs(mod((aspect + azimuth) / PI + 0.5, 2.0) - 1.0);
|
||||||
|
vec4 shade_color = mix(u_shadows[0], u_highlights[0], shade) * sin(scaledSlope) * clamp(intensity * 2.0, 0.0, 1.0);
|
||||||
|
|
||||||
|
fragColor = accent_color * (1.0 - shade_color.a) + shade_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Basic directional hillshade (Method 4)
|
||||||
|
void basic_hillshade(vec2 deriv) {
|
||||||
|
deriv = deriv * u_exaggeration * 2.0; // Exaggerate the slope derivative
|
||||||
|
float azimuth = u_azimuths.x + PI;
|
||||||
|
float cos_az = cos(azimuth);
|
||||||
|
float sin_az = sin(azimuth);
|
||||||
|
float cos_alt = cos(u_altitudes.x);
|
||||||
|
float sin_alt = sin(u_altitudes.x);
|
||||||
|
|
||||||
|
// Calculate the cosine of the angle between the light vector and the surface normal
|
||||||
|
float cang = (sin_alt - (deriv.y * cos_az * cos_alt - deriv.x * sin_az * cos_alt)) / sqrt(1.0 + dot(deriv, deriv));
|
||||||
|
float shade = clamp(cang, 0.0, 1.0); // cang is the hillshade intensity [0, 1]
|
||||||
|
|
||||||
|
// Blend shadow and highlight based on intensity
|
||||||
|
if (shade > 0.5) {
|
||||||
|
fragColor = u_highlights[0] * (2.0 * shade - 1.0); // Highlight strength [0, 1]
|
||||||
|
} else {
|
||||||
|
fragColor = u_shadows[0] * (1.0 - 2.0 * shade); // Shadow strength [0, 1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Multidirectional hillshade (Method 3)
|
||||||
|
void multidirectional_hillshade(vec2 deriv) {
|
||||||
|
deriv = deriv * u_exaggeration * 2.0; // Exaggerate the slope derivative
|
||||||
|
fragColor = vec4(0, 0, 0, 0);
|
||||||
|
|
||||||
|
// Iterate through all light sources (up to u_num_lights, max 4)
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
if (i >= u_num_lights) break;
|
||||||
|
|
||||||
|
// Access altitude and azimuth from vec4 UBOs
|
||||||
|
float altitude = (i == 0) ? u_altitudes.x : (i == 1) ? u_altitudes.y : (i == 2) ? u_altitudes.z : u_altitudes.w;
|
||||||
|
float azimuth = (i == 0) ? u_azimuths.x : (i == 1) ? u_azimuths.y : (i == 2) ? u_azimuths.z : u_azimuths.w;
|
||||||
|
|
||||||
|
float cos_alt = cos(altitude);
|
||||||
|
float sin_alt = sin(altitude);
|
||||||
|
// Negate cos/sin azimuth for correct light direction in the normal calculation
|
||||||
|
float cos_az = -cos(azimuth);
|
||||||
|
float sin_az = -sin(azimuth);
|
||||||
|
|
||||||
|
// Calculate the cosine of the angle between the light vector and the surface normal
|
||||||
|
float cang = (sin_alt - (deriv.y * cos_az * cos_alt - deriv.x * sin_az * cos_alt)) /
|
||||||
|
sqrt(1.0 + dot(deriv, deriv));
|
||||||
|
float shade = clamp(cang, 0.0, 1.0); // cang is the hillshade intensity [0, 1]
|
||||||
|
|
||||||
|
// Accumulate shadow/highlight contribution from each light
|
||||||
|
if (shade > 0.5) {
|
||||||
|
fragColor += u_highlights[i] * (2.0 * shade - 1.0) / float(u_num_lights);
|
||||||
|
} else {
|
||||||
|
fragColor += u_shadows[i] * (1.0 - 2.0 * shade) / float(u_num_lights);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Combined shadow and highlight method (Method 1)
|
||||||
|
void combined_hillshade(vec2 deriv) {
|
||||||
|
// Only supports one light source (index 0)
|
||||||
|
deriv = deriv * u_exaggeration * 2.0;
|
||||||
|
float azimuth = u_azimuths.x + PI;
|
||||||
|
float cos_az = cos(azimuth);
|
||||||
|
float sin_az = sin(azimuth);
|
||||||
|
float cos_alt = cos(u_altitudes.x);
|
||||||
|
float sin_alt = sin(u_altitudes.x);
|
||||||
|
|
||||||
|
// Calculate the angle between the light vector and the surface normal
|
||||||
|
float cang = acos((sin_alt - (deriv.y * cos_az * cos_alt - deriv.x * sin_az * cos_alt)) /
|
||||||
|
sqrt(1.0 + dot(deriv, deriv)));
|
||||||
|
|
||||||
|
cang = clamp(cang, 0.0, PI / 2.0); // Clamp angle to 90 degrees (half hemisphere)
|
||||||
|
|
||||||
|
// The "shade" and "highlight" components are calculated from cang (angle) and the magnitude of the slope
|
||||||
|
float shade = cang * atan(length(deriv)) * 4.0 / PI / PI;
|
||||||
|
float highlight = (PI / 2.0 - cang) * atan(length(deriv)) * 4.0 / PI / PI;
|
||||||
|
|
||||||
|
fragColor = u_shadows[0] * shade + u_highlights[0] * highlight;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Igor's shadow/highlight method (Method 2)
|
||||||
|
void igor_hillshade(vec2 deriv) {
|
||||||
|
// Only supports one light source (index 0)
|
||||||
|
deriv = deriv * u_exaggeration * 2.0;
|
||||||
|
float aspect = get_aspect(deriv);
|
||||||
|
float azimuth = u_azimuths.x + PI;
|
||||||
|
|
||||||
|
// Slope strength is magnitude of slope vector, normalized to [0, 1]
|
||||||
|
float slope_strength = atan(length(deriv)) * 2.0 / PI;
|
||||||
|
|
||||||
|
// Aspect strength is difference between aspect and light azimuth, normalized to [0, 1]
|
||||||
|
float aspect_strength = 1.0 - abs(mod((aspect + azimuth) / PI + 0.5, 2.0) - 1.0);
|
||||||
|
|
||||||
|
float shadow_strength = slope_strength * aspect_strength;
|
||||||
|
float highlight_strength = slope_strength * (1.0 - aspect_strength);
|
||||||
|
|
||||||
|
fragColor = u_shadows[0] * shadow_strength + u_highlights[0] * highlight_strength;
|
||||||
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec4 pixel = texture(u_image, v_pos);
|
vec4 pixel = texture(u_image, v_pos);
|
||||||
|
|
||||||
vec2 deriv = ((pixel.rg * 2.0) - 1.0);
|
// Scale the derivative based on the mercator distortion at this latitude (v_pos.y)
|
||||||
|
|
||||||
// We divide the slope by a scale factor based on the cosin of the pixel's approximate latitude
|
|
||||||
// to account for mercator projection distortion. see #4807 for details
|
|
||||||
float scaleFactor = cos(radians((u_latrange[0] - u_latrange[1]) * (1.0 - v_pos.y) + u_latrange[1]));
|
float scaleFactor = cos(radians((u_latrange[0] - u_latrange[1]) * (1.0 - v_pos.y) + u_latrange[1]));
|
||||||
// We also multiply the slope by an arbitrary z-factor of 1.25
|
|
||||||
float slope = atan(1.25 * length(deriv) / scaleFactor);
|
|
||||||
float aspect = deriv.x != 0.0 ? atan(deriv.y, -deriv.x) : PI / 2.0 * (deriv.y > 0.0 ? 1.0 : -1.0);
|
|
||||||
|
|
||||||
float intensity = u_light.x;
|
// The derivative is scaled back from [0, 1] texture range to world-space slope
|
||||||
// We add PI to make this property match the global light object, which adds PI/2 to the light's azimuthal
|
// Texture range [0, 1] corresponds to slope range [-4, 4] (8.0 * 0.5 * deriv)
|
||||||
// position property to account for 0deg corresponding to north/the top of the viewport in the style spec
|
vec2 deriv = ((pixel.rg * 8.0) - 4.0) / scaleFactor;
|
||||||
// and the original shader was written to accept (-illuminationDirection - 90) as the azimuthal.
|
|
||||||
float azimuth = u_light.y + PI;
|
|
||||||
|
|
||||||
// We scale the slope exponentially based on intensity, using a calculation similar to
|
// Dispatch to the selected hillshade method
|
||||||
// the exponential interpolation function in the style spec:
|
switch (u_method) {
|
||||||
// https://github.com/mapbox/mapbox-gl-js/blob/master/src/style-spec/expression/definitions/interpolate.js#L217-L228
|
case BASIC:
|
||||||
// so that higher intensity values create more opaque hillshading.
|
basic_hillshade(deriv);
|
||||||
float base = 1.875 - intensity * 1.75;
|
break;
|
||||||
float maxValue = 0.5 * PI;
|
case COMBINED:
|
||||||
float scaledSlope = intensity != 0.5 ? ((pow(base, slope) - 1.0) / (pow(base, maxValue) - 1.0)) * maxValue : slope;
|
combined_hillshade(deriv);
|
||||||
|
break;
|
||||||
// The accent color is calculated with the cosine of the slope while the shade color is calculated with the sine
|
case IGOR:
|
||||||
// so that the accent color's rate of change eases in while the shade color's eases out.
|
igor_hillshade(deriv);
|
||||||
float accent = cos(scaledSlope);
|
break;
|
||||||
// We multiply both the accent and shade color by a clamped intensity value
|
case MULTIDIRECTIONAL:
|
||||||
// so that intensities >= 0.5 do not additionally affect the color values
|
multidirectional_hillshade(deriv);
|
||||||
// while intensity values < 0.5 make the overall color more transparent.
|
break;
|
||||||
vec4 accent_color = (1.0 - accent) * u_accent * clamp(intensity * 2.0, 0.0, 1.0);
|
case STANDARD:
|
||||||
float shade = abs(mod((aspect + azimuth) / PI + 0.5, 2.0) - 1.0);
|
default:
|
||||||
vec4 shade_color = mix(u_shadow, u_highlight, shade) * sin(scaledSlope) * clamp(intensity * 2.0, 0.0, 1.0);
|
standard_hillshade(deriv);
|
||||||
fragColor = accent_color * (1.0 - shade_color.a) + shade_color;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef OVERDRAW_INSPECTOR
|
#ifdef OVERDRAW_INSPECTOR
|
||||||
fragColor = vec4(1.0);
|
fragColor = vec4(1.0);
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ precision highp float;
|
|||||||
|
|
||||||
in vec2 v_pos;
|
in vec2 v_pos;
|
||||||
uniform sampler2D u_image;
|
uniform sampler2D u_image;
|
||||||
|
|
||||||
layout (std140) uniform HillshadePrepareTilePropsUBO {
|
layout (std140) uniform HillshadePrepareTilePropsUBO {
|
||||||
highp vec4 u_unpack;
|
highp vec4 u_unpack;
|
||||||
highp vec2 u_dimension;
|
highp vec2 u_dimension;
|
||||||
@@ -50,13 +49,14 @@ float getElevation(vec2 coord, float bias) {
|
|||||||
// Convert encoded elevation value to meters
|
// Convert encoded elevation value to meters
|
||||||
vec4 data = texture(u_image, coord) * 255.0;
|
vec4 data = texture(u_image, coord) * 255.0;
|
||||||
data.a = -1.0;
|
data.a = -1.0;
|
||||||
return dot(data, u_unpack) / 4.0;
|
return dot(data, u_unpack);
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec2 epsilon = 1.0 / u_dimension;
|
vec2 epsilon = 1.0 / u_dimension;
|
||||||
|
float tileSize = u_dimension.x - 2.0;
|
||||||
|
|
||||||
// queried pixels:
|
// queried pixels (using Sobel operator kernel):
|
||||||
// +-----------+
|
// +-----------+
|
||||||
// | | | |
|
// | | | |
|
||||||
// | a | b | c |
|
// | a | b | c |
|
||||||
@@ -81,30 +81,28 @@ void main() {
|
|||||||
float h = getElevation(v_pos + vec2(0, epsilon.y), 0.0);
|
float h = getElevation(v_pos + vec2(0, epsilon.y), 0.0);
|
||||||
float i = getElevation(v_pos + vec2(epsilon.x, epsilon.y), 0.0);
|
float i = getElevation(v_pos + vec2(epsilon.x, epsilon.y), 0.0);
|
||||||
|
|
||||||
// here we divide the x and y slopes by 8 * pixel size
|
// Convert the raw pixel-space derivative (slope) into world-space slope.
|
||||||
// where pixel size (aka meters/pixel) is:
|
// The conversion factor is: tileSize / (8 * meters_per_pixel).
|
||||||
// circumference of the world / (pixels per tile * number of tiles)
|
// meters_per_pixel is calculated as pow(2.0, 28.2562 - u_zoom).
|
||||||
// which is equivalent to: 8 * 40075016.6855785 / (512 * pow(2, u_zoom))
|
// The exaggeration factor is applied to scale the effect at lower zooms.
|
||||||
// which can be reduced to: pow(2, 19.25619978527 - u_zoom)
|
// See nickidlugash's awesome breakdown for more info
|
||||||
// we want to vertically exaggerate the hillshading though, because otherwise
|
|
||||||
// it is barely noticeable at low zooms. to do this, we multiply this by some
|
|
||||||
// scale factor pow(2, (u_zoom - u_maxzoom) * a) where a is an arbitrary value
|
|
||||||
// Here we use a=0.3 which works out to the expression below. see
|
|
||||||
// nickidlugash's awesome breakdown for more info
|
|
||||||
// https://github.com/mapbox/mapbox-gl-js/pull/5286#discussion_r148419556
|
// https://github.com/mapbox/mapbox-gl-js/pull/5286#discussion_r148419556
|
||||||
float exaggeration = u_zoom < 2.0 ? 0.4 : u_zoom < 4.5 ? 0.35 : 0.3;
|
float exaggerationFactor = u_zoom < 2.0 ? 0.4 : u_zoom < 4.5 ? 0.35 : 0.3;
|
||||||
|
float exaggeration = u_zoom < 15.0 ? (u_zoom - 15.0) * exaggerationFactor : 0.0;
|
||||||
|
|
||||||
vec2 deriv = vec2(
|
vec2 deriv = vec2(
|
||||||
(c + f + f + i) - (a + d + d + g),
|
(c + f + f + i) - (a + d + d + g),
|
||||||
(g + h + h + i) - (a + b + b + c)
|
(g + h + h + i) - (a + b + b + c)
|
||||||
) / pow(2.0, (u_zoom - u_maxzoom) * exaggeration + 19.2562 - u_zoom);
|
) * tileSize / pow(2.0, exaggeration + (28.2562 - u_zoom));
|
||||||
|
|
||||||
|
// Encode the derivative into the color channels (r and g)
|
||||||
|
// The derivative is scaled from world-space slope to the range [0, 1] for texture storage.
|
||||||
|
// The maximum possible world-space derivative is assumed to be 4 (hence division by 8.0).
|
||||||
fragColor = clamp(vec4(
|
fragColor = clamp(vec4(
|
||||||
deriv.x / 2.0 + 0.5,
|
deriv.x / 8.0 + 0.5,
|
||||||
deriv.y / 2.0 + 0.5,
|
deriv.y / 8.0 + 0.5,
|
||||||
1.0,
|
1.0,
|
||||||
1.0), 0.0, 1.0);
|
1.0), 0.0, 1.0);
|
||||||
|
|
||||||
#ifdef OVERDRAW_INSPECTOR
|
#ifdef OVERDRAW_INSPECTOR
|
||||||
fragColor = vec4(1.0);
|
fragColor = vec4(1.0);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -163,6 +163,13 @@ struct ShaderInfo<BuiltIn::HillshadeShader, gfx::Backend::Type::OpenGL> {
|
|||||||
static const std::vector<TextureInfo> textures;
|
static const std::vector<TextureInfo> textures;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct ShaderInfo<BuiltIn::ColorReliefShader, gfx::Backend::Type::OpenGL> {
|
||||||
|
static const std::vector<AttributeInfo> attributes;
|
||||||
|
static const std::vector<UniformBlockInfo> uniformBlocks;
|
||||||
|
static const std::vector<TextureInfo> textures;
|
||||||
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct ShaderInfo<BuiltIn::LineGradientShader, gfx::Backend::Type::OpenGL> {
|
struct ShaderInfo<BuiltIn::LineGradientShader, gfx::Backend::Type::OpenGL> {
|
||||||
static const std::vector<AttributeInfo> attributes;
|
static const std::vector<AttributeInfo> attributes;
|
||||||
|
|||||||
@@ -1,10 +1,20 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <mbgl/shaders/layer_ubo.hpp>
|
#include <mbgl/shaders/layer_ubo.hpp>
|
||||||
|
|
||||||
namespace mbgl {
|
namespace mbgl {
|
||||||
namespace shaders {
|
namespace shaders {
|
||||||
|
|
||||||
|
// Maximum number of illumination sources supported
|
||||||
|
constexpr int MAX_ILLUMINATION_SOURCES = 4;
|
||||||
|
|
||||||
|
enum class HillshadeMethod : int32_t {
|
||||||
|
Standard = 0,
|
||||||
|
Combined = 1,
|
||||||
|
Igor = 2,
|
||||||
|
Multidirectional = 3,
|
||||||
|
Basic = 4
|
||||||
|
};
|
||||||
|
|
||||||
struct alignas(16) HillshadeDrawableUBO {
|
struct alignas(16) HillshadeDrawableUBO {
|
||||||
/* 0 */ std::array<float, 4 * 4> matrix;
|
/* 0 */ std::array<float, 4 * 4> matrix;
|
||||||
/* 64 */
|
/* 64 */
|
||||||
@@ -13,19 +23,26 @@ static_assert(sizeof(HillshadeDrawableUBO) == 4 * 16);
|
|||||||
|
|
||||||
struct alignas(16) HillshadeTilePropsUBO {
|
struct alignas(16) HillshadeTilePropsUBO {
|
||||||
/* 0 */ std::array<float, 2> latrange;
|
/* 0 */ std::array<float, 2> latrange;
|
||||||
/* 8 */ std::array<float, 2> light;
|
/* 8 */ float exaggeration; // NEW: replaces light[0] (intensity)
|
||||||
/* 16 */
|
/* 12 */ int32_t method; // NEW: hillshade method (0-4)
|
||||||
|
/* 16 */ int32_t num_lights; // NEW: number of light sources (1-4)
|
||||||
|
/* 20 */ float pad0; // Padding for alignment
|
||||||
|
/* 24 */ float pad1; // Padding for alignment
|
||||||
|
/* 28 */ float pad2; // Padding for alignment
|
||||||
|
/* 32 */
|
||||||
};
|
};
|
||||||
static_assert(sizeof(HillshadeTilePropsUBO) == 16);
|
static_assert(sizeof(HillshadeTilePropsUBO) == 32);
|
||||||
|
|
||||||
/// Evaluated properties that do not depend on the tile
|
/// Evaluated properties that do not depend on the tile
|
||||||
struct alignas(16) HillshadeEvaluatedPropsUBO {
|
struct alignas(16) HillshadeEvaluatedPropsUBO {
|
||||||
/* 0 */ Color highlight;
|
/* 0 */ Color accent;
|
||||||
/* 16 */ Color shadow;
|
/* 16 */ std::array<float, 4> altitudes; // NEW: altitude values in radians (up to 4)
|
||||||
/* 32 */ Color accent;
|
/* 32 */ std::array<float, 4> azimuths; // NEW: azimuth values in radians (up to 4)
|
||||||
/* 48 */
|
/* 48 */ std::array<float, 16> shadows; // NEW: 4 shadow colors (4 colors × 4 RGBA)
|
||||||
|
/* 112 */ std::array<float, 16> highlights; // NEW: 4 highlight colors (4 colors × 4 RGBA)
|
||||||
|
/* 176 */
|
||||||
};
|
};
|
||||||
static_assert(sizeof(HillshadeEvaluatedPropsUBO) == 3 * 16);
|
static_assert(sizeof(HillshadeEvaluatedPropsUBO) == 176);
|
||||||
|
|
||||||
} // namespace shaders
|
} // namespace shaders
|
||||||
} // namespace mbgl
|
} // namespace mbgl
|
||||||
|
|||||||
170
include/mbgl/shaders/mtl/color_relief.hpp
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <mbgl/shaders/color_relief_layer_ubo.hpp>
|
||||||
|
#include <mbgl/shaders/shader_source.hpp>
|
||||||
|
#include <mbgl/shaders/mtl/shader_program.hpp>
|
||||||
|
|
||||||
|
namespace mbgl {
|
||||||
|
namespace shaders {
|
||||||
|
|
||||||
|
constexpr auto colorReliefShaderPrelude = R"(
|
||||||
|
|
||||||
|
enum {
|
||||||
|
idColorReliefDrawableUBO = idDrawableReservedVertexOnlyUBO,
|
||||||
|
idColorReliefTilePropsUBO = drawableReservedUBOCount,
|
||||||
|
idColorReliefEvaluatedPropsUBO,
|
||||||
|
colorReliefUBOCount
|
||||||
|
};
|
||||||
|
|
||||||
|
struct alignas(16) ColorReliefDrawableUBO {
|
||||||
|
/* 0 */ float4x4 matrix;
|
||||||
|
/* 64 */
|
||||||
|
};
|
||||||
|
static_assert(sizeof(ColorReliefDrawableUBO) == 4 * 16, "wrong size");
|
||||||
|
|
||||||
|
struct alignas(16) ColorReliefTilePropsUBO {
|
||||||
|
/* 0 */ float4 unpack;
|
||||||
|
/* 16 */ float2 dimension;
|
||||||
|
/* 24 */ int32_t color_ramp_size;
|
||||||
|
/* 28 */ float pad_tile0;
|
||||||
|
/* 32 */
|
||||||
|
};
|
||||||
|
static_assert(sizeof(ColorReliefTilePropsUBO) == 2 * 16, "wrong size");
|
||||||
|
|
||||||
|
struct alignas(16) ColorReliefEvaluatedPropsUBO {
|
||||||
|
/* 0 */ float opacity;
|
||||||
|
/* 4 */ float pad_eval0;
|
||||||
|
/* 8 */ float pad_eval1;
|
||||||
|
/* 12 */ float pad_eval2;
|
||||||
|
/* 16 */
|
||||||
|
};
|
||||||
|
static_assert(sizeof(ColorReliefEvaluatedPropsUBO) == 16, "wrong size");
|
||||||
|
|
||||||
|
)";
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct ShaderSource<BuiltIn::ColorReliefShader, gfx::Backend::Type::Metal> {
|
||||||
|
static constexpr auto name = "ColorReliefShader";
|
||||||
|
static constexpr auto vertexMainFunction = "vertexMain";
|
||||||
|
static constexpr auto fragmentMainFunction = "fragmentMain";
|
||||||
|
|
||||||
|
static const std::array<AttributeInfo, 2> attributes;
|
||||||
|
static constexpr std::array<AttributeInfo, 0> instanceAttributes{};
|
||||||
|
static const std::array<TextureInfo, 3> textures;
|
||||||
|
|
||||||
|
static constexpr auto prelude = colorReliefShaderPrelude;
|
||||||
|
static constexpr auto source = R"(
|
||||||
|
|
||||||
|
struct VertexStage {
|
||||||
|
short2 pos [[attribute(colorReliefUBOCount + 0)]];
|
||||||
|
short2 texture_pos [[attribute(colorReliefUBOCount + 1)]];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FragmentStage {
|
||||||
|
float4 position [[position, invariant]];
|
||||||
|
float2 pos;
|
||||||
|
};
|
||||||
|
|
||||||
|
FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]],
|
||||||
|
device const uint32_t& uboIndex [[buffer(idGlobalUBOIndex)]],
|
||||||
|
device const ColorReliefDrawableUBO* drawableVector [[buffer(idColorReliefDrawableUBO)]],
|
||||||
|
device const ColorReliefTilePropsUBO* tilePropsVector [[buffer(idColorReliefTilePropsUBO)]]) {
|
||||||
|
|
||||||
|
device const ColorReliefDrawableUBO& drawable = drawableVector[uboIndex];
|
||||||
|
device const ColorReliefTilePropsUBO& tileProps = tilePropsVector[uboIndex];
|
||||||
|
|
||||||
|
const float4 position = drawable.matrix * float4(float2(vertx.pos), 0, 1);
|
||||||
|
|
||||||
|
// Calculate texture coordinate
|
||||||
|
float2 epsilon = 1.0 / tileProps.dimension;
|
||||||
|
float scale = (tileProps.dimension.x - 2.0) / tileProps.dimension.x;
|
||||||
|
float2 pos = (float2(vertx.pos) / 8192.0) * scale + epsilon;
|
||||||
|
|
||||||
|
// Handle poles (use vertx.pos, not texture_pos, to match GLSL a_pos)
|
||||||
|
if (float(vertx.pos.y) < -32767.5) pos.y = 0.0;
|
||||||
|
if (float(vertx.pos.y) > 32766.5) pos.y = 1.0;
|
||||||
|
|
||||||
|
return {
|
||||||
|
.position = position,
|
||||||
|
.pos = pos,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to convert terrain-RGB encoded elevation value to meters
|
||||||
|
float getElevation(float2 coord, texture2d<float, access::sample> image, sampler image_sampler, float4 unpack) {
|
||||||
|
float4 data = image.sample(image_sampler, coord) * 255.0;
|
||||||
|
data.a = -1.0;
|
||||||
|
return dot(data, unpack);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to get the elevation value at a specific color ramp stop
|
||||||
|
float getElevationStop(int stop, int color_ramp_size, texture2d<float, access::sample> elevationStops, sampler elevation_sampler) {
|
||||||
|
// Elevation stops are plain float values, stored in the R channel
|
||||||
|
float x = (float(stop) + 0.5) / float(color_ramp_size);
|
||||||
|
return elevationStops.sample(elevation_sampler, float2(x, 0.5)).r;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to get the color value at a specific color ramp stop
|
||||||
|
float4 getColorStop(int stop, int color_ramp_size, texture2d<float, access::sample> colorStops, sampler color_sampler) {
|
||||||
|
float x = (float(stop) + 0.5) / float(color_ramp_size);
|
||||||
|
return colorStops.sample(color_sampler, float2(x, 0.5));
|
||||||
|
}
|
||||||
|
|
||||||
|
half4 fragment fragmentMain(FragmentStage in [[stage_in]],
|
||||||
|
device const uint32_t& uboIndex [[buffer(idGlobalUBOIndex)]],
|
||||||
|
device const ColorReliefTilePropsUBO* tilePropsVector [[buffer(idColorReliefTilePropsUBO)]],
|
||||||
|
device const ColorReliefEvaluatedPropsUBO& props [[buffer(idColorReliefEvaluatedPropsUBO)]],
|
||||||
|
texture2d<float, access::sample> image [[texture(0)]],
|
||||||
|
texture2d<float, access::sample> elevationStops [[texture(1)]],
|
||||||
|
texture2d<float, access::sample> colorStops [[texture(2)]],
|
||||||
|
sampler image_sampler [[sampler(0)]],
|
||||||
|
sampler elevation_stops_sampler [[sampler(1)]],
|
||||||
|
sampler color_stops_sampler [[sampler(2)]]) {
|
||||||
|
#if defined(OVERDRAW_INSPECTOR)
|
||||||
|
return half4(1.0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
device const ColorReliefTilePropsUBO& tileProps = tilePropsVector[uboIndex];
|
||||||
|
|
||||||
|
// 1. Get elevation at this pixel from DEM
|
||||||
|
float el = getElevation(in.pos, image, image_sampler, tileProps.unpack);
|
||||||
|
|
||||||
|
// 2. Binary search to find surrounding elevation stops (l and r indices)
|
||||||
|
int r = tileProps.color_ramp_size - 1;
|
||||||
|
int l = 0;
|
||||||
|
|
||||||
|
// Perform binary search
|
||||||
|
while (r - l > 1) {
|
||||||
|
int m = (r + l) / 2;
|
||||||
|
float el_m = getElevationStop(m, tileProps.color_ramp_size, elevationStops, elevation_stops_sampler);
|
||||||
|
|
||||||
|
if (el < el_m) {
|
||||||
|
r = m;
|
||||||
|
} else {
|
||||||
|
l = m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Get the elevation values and colors at the stops
|
||||||
|
float el_l = getElevationStop(l, tileProps.color_ramp_size, elevationStops, elevation_stops_sampler);
|
||||||
|
float el_r = getElevationStop(r, tileProps.color_ramp_size, elevationStops, elevation_stops_sampler);
|
||||||
|
|
||||||
|
float4 color_l = getColorStop(l, tileProps.color_ramp_size, colorStops, color_stops_sampler);
|
||||||
|
float4 color_r = getColorStop(r, tileProps.color_ramp_size, colorStops, color_stops_sampler);
|
||||||
|
|
||||||
|
// 4. Interpolate color based on elevation
|
||||||
|
// Guard against division by zero when el_r == el_l
|
||||||
|
float denom = el_r - el_l;
|
||||||
|
float t = (abs(denom) < 0.0001) ? 0.0 : clamp((el - el_l) / denom, 0.0, 1.0);
|
||||||
|
|
||||||
|
thread half4 fragColor;
|
||||||
|
float4 color = mix(color_l, color_r, t);
|
||||||
|
color *= props.opacity;
|
||||||
|
fragColor = half4(color);
|
||||||
|
return fragColor;
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace shaders
|
||||||
|
} // namespace mbgl
|
||||||
@@ -23,7 +23,7 @@ using namespace metal;
|
|||||||
template <typename T1, typename T2>
|
template <typename T1, typename T2>
|
||||||
inline auto glMod(T1 x, T2 y) { return x - y * metal::floor(x/y); }
|
inline auto glMod(T1 x, T2 y) { return x - y * metal::floor(x/y); }
|
||||||
|
|
||||||
float radians(float degrees) {
|
inline float radians(float degrees) {
|
||||||
return M_PI_F * degrees / 180.0;
|
return M_PI_F * degrees / 180.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]],
|
|||||||
// weight * u_intensity * GAUSS_COEF * exp(-0.5 * 3.0^2 * S^2) == ZERO
|
// weight * u_intensity * GAUSS_COEF * exp(-0.5 * 3.0^2 * S^2) == ZERO
|
||||||
// Which solves to:
|
// Which solves to:
|
||||||
// S = sqrt(-2.0 * log(ZERO / (weight * u_intensity * GAUSS_COEF))) / 3.0
|
// S = sqrt(-2.0 * log(ZERO / (weight * u_intensity * GAUSS_COEF))) / 3.0
|
||||||
const float S = sqrt(-2.0 * log(ZERO / weight / props.intensity / GAUSS_COEF)) / 3.0;
|
const float S = sqrt(-2.0 * log(ZERO / (max(weight, ZERO) * max(props.intensity, ZERO) * GAUSS_COEF))) / 3.0;
|
||||||
|
|
||||||
// Pass the varying in units of radius
|
// Pass the varying in units of radius
|
||||||
const float2 extrude = S * unscaled_extrude;
|
const float2 extrude = S * unscaled_extrude;
|
||||||
|
|||||||
@@ -24,19 +24,26 @@ static_assert(sizeof(HillshadeDrawableUBO) == 4 * 16, "wrong size");
|
|||||||
|
|
||||||
struct alignas(16) HillshadeTilePropsUBO {
|
struct alignas(16) HillshadeTilePropsUBO {
|
||||||
/* 0 */ float2 latrange;
|
/* 0 */ float2 latrange;
|
||||||
/* 8 */ float2 light;
|
/* 8 */ float exaggeration;
|
||||||
/* 16 */
|
/* 12 */ int32_t method;
|
||||||
|
/* 16 */ int32_t num_lights;
|
||||||
|
/* 20 */ float pad0;
|
||||||
|
/* 24 */ float pad1;
|
||||||
|
/* 28 */ float pad2;
|
||||||
|
/* 32 */
|
||||||
};
|
};
|
||||||
static_assert(sizeof(HillshadeTilePropsUBO) == 16, "wrong size");
|
static_assert(sizeof(HillshadeTilePropsUBO) == 2 * 16, "wrong size");
|
||||||
|
|
||||||
/// Evaluated properties that do not depend on the tile
|
/// Evaluated properties that do not depend on the tile
|
||||||
struct alignas(16) HillshadeEvaluatedPropsUBO {
|
struct alignas(16) HillshadeEvaluatedPropsUBO {
|
||||||
/* 0 */ float4 highlight;
|
/* 0 */ float4 accent;
|
||||||
/* 16 */ float4 shadow;
|
/* 16 */ float4 altitudes; // Up to 4 altitude values (in radians)
|
||||||
/* 32 */ float4 accent;
|
/* 32 */ float4 azimuths; // Up to 4 azimuth values (in radians)
|
||||||
/* 48 */
|
/* 48 */ float4 shadows[4]; // Shadow colors (up to 4 lights)
|
||||||
|
/* 112 */ float4 highlights[4]; // Highlight colors (up to 4 lights)
|
||||||
|
/* 176 */
|
||||||
};
|
};
|
||||||
static_assert(sizeof(HillshadeEvaluatedPropsUBO) == 3 * 16, "wrong size");
|
static_assert(sizeof(HillshadeEvaluatedPropsUBO) == 11 * 16, "wrong size");
|
||||||
|
|
||||||
)";
|
)";
|
||||||
|
|
||||||
@@ -53,6 +60,13 @@ struct ShaderSource<BuiltIn::HillshadeShader, gfx::Backend::Type::Metal> {
|
|||||||
static constexpr auto prelude = hillshadeShaderPrelude;
|
static constexpr auto prelude = hillshadeShaderPrelude;
|
||||||
static constexpr auto source = R"(
|
static constexpr auto source = R"(
|
||||||
|
|
||||||
|
#define PI 3.141592653589793
|
||||||
|
#define STANDARD 0
|
||||||
|
#define COMBINED 1
|
||||||
|
#define IGOR 2
|
||||||
|
#define MULTIDIRECTIONAL 3
|
||||||
|
#define BASIC 4
|
||||||
|
|
||||||
struct VertexStage {
|
struct VertexStage {
|
||||||
short2 pos [[attribute(hillshadeUBOCount + 0)]];
|
short2 pos [[attribute(hillshadeUBOCount + 0)]];
|
||||||
short2 texture_pos [[attribute(hillshadeUBOCount + 1)]];
|
short2 texture_pos [[attribute(hillshadeUBOCount + 1)]];
|
||||||
@@ -71,6 +85,8 @@ FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]],
|
|||||||
|
|
||||||
const float4 position = drawable.matrix * float4(float2(vertx.pos), 0, 1);
|
const float4 position = drawable.matrix * float4(float2(vertx.pos), 0, 1);
|
||||||
float2 pos = float2(vertx.texture_pos) / 8192.0;
|
float2 pos = float2(vertx.texture_pos) / 8192.0;
|
||||||
|
// Metal's texture coordinate origin differs from some renderers;
|
||||||
|
// restore Y-flip to match prepare pass and historical behavior.
|
||||||
pos.y = 1.0 - pos.y;
|
pos.y = 1.0 - pos.y;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -79,6 +95,129 @@ FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]],
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper function to calculate aspect (normalized direction of slope)
|
||||||
|
float get_aspect(float2 deriv) {
|
||||||
|
return deriv.x != 0.0 ? atan2(deriv.y, -deriv.x) : PI / 2.0 * (deriv.y > 0.0 ? 1.0 : -1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// MapLibre's legacy hillshade algorithm (Method 0: STANDARD)
|
||||||
|
void standard_hillshade(float2 deriv, device const HillshadeTilePropsUBO& tileProps, device const HillshadeEvaluatedPropsUBO& props, thread half4& fragColor) {
|
||||||
|
float azimuth = props.azimuths.x + PI;
|
||||||
|
float slope = atan(0.625 * length(deriv));
|
||||||
|
float aspect = get_aspect(deriv);
|
||||||
|
|
||||||
|
float intensity = tileProps.exaggeration;
|
||||||
|
|
||||||
|
// Scale the slope exponentially based on intensity
|
||||||
|
float base = 1.875 - intensity * 1.75;
|
||||||
|
float maxValue = 0.5 * PI;
|
||||||
|
float scaledSlope = abs(intensity - 0.5) > 1e-6 ? ((pow(base, slope) - 1.0) / (pow(base, maxValue) - 1.0)) * maxValue : slope;
|
||||||
|
|
||||||
|
float accent = cos(scaledSlope);
|
||||||
|
float4 accent_color = (1.0 - accent) * props.accent * clamp(intensity * 2.0, 0.0, 1.0);
|
||||||
|
|
||||||
|
float shade = abs(glMod((aspect + azimuth) / PI + 0.5, 2.0) - 1.0);
|
||||||
|
float4 shade_color = mix(props.shadows[0], props.highlights[0], shade) * sin(scaledSlope) * clamp(intensity * 2.0, 0.0, 1.0);
|
||||||
|
|
||||||
|
fragColor = half4(accent_color * (1.0 - shade_color.a) + shade_color);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Basic directional hillshade (Method 4: BASIC)
|
||||||
|
void basic_hillshade(float2 deriv, device const HillshadeTilePropsUBO& tileProps, device const HillshadeEvaluatedPropsUBO& props, thread half4& fragColor) {
|
||||||
|
deriv = deriv * tileProps.exaggeration * 2.0;
|
||||||
|
float azimuth = props.azimuths.x + PI;
|
||||||
|
float cos_az = cos(azimuth);
|
||||||
|
float sin_az = sin(azimuth);
|
||||||
|
float cos_alt = cos(props.altitudes.x);
|
||||||
|
float sin_alt = sin(props.altitudes.x);
|
||||||
|
|
||||||
|
// Calculate the cosine of the angle between the light vector and the surface normal
|
||||||
|
float cang = (sin_alt - (deriv.y * cos_az * cos_alt - deriv.x * sin_az * cos_alt)) / sqrt(1.0 + dot(deriv, deriv));
|
||||||
|
float shade = clamp(cang, 0.0, 1.0);
|
||||||
|
|
||||||
|
// Blend shadow and highlight based on intensity
|
||||||
|
if (shade > 0.5) {
|
||||||
|
fragColor = half4(props.highlights[0] * (2.0 * shade - 1.0));
|
||||||
|
} else {
|
||||||
|
fragColor = half4(props.shadows[0] * (1.0 - 2.0 * shade));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Multidirectional hillshade (Method 3: MULTIDIRECTIONAL)
|
||||||
|
void multidirectional_hillshade(float2 deriv, device const HillshadeTilePropsUBO& tileProps, device const HillshadeEvaluatedPropsUBO& props, thread half4& fragColor) {
|
||||||
|
deriv = deriv * tileProps.exaggeration * 2.0;
|
||||||
|
float4 total_color = float4(0, 0, 0, 0);
|
||||||
|
|
||||||
|
int num_lights = min(tileProps.num_lights, 4);
|
||||||
|
|
||||||
|
// Iterate through all light sources
|
||||||
|
for (int i = 0; i < num_lights; i++) {
|
||||||
|
// Access altitude and azimuth from vec4 UBOs
|
||||||
|
float altitude = (i == 0) ? props.altitudes.x : (i == 1) ? props.altitudes.y : (i == 2) ? props.altitudes.z : props.altitudes.w;
|
||||||
|
float azimuth = (i == 0) ? props.azimuths.x : (i == 1) ? props.azimuths.y : (i == 2) ? props.azimuths.z : props.azimuths.w;
|
||||||
|
|
||||||
|
float cos_alt = cos(altitude);
|
||||||
|
float sin_alt = sin(altitude);
|
||||||
|
// Negate cos/sin azimuth for correct light direction
|
||||||
|
float cos_az = -cos(azimuth);
|
||||||
|
float sin_az = -sin(azimuth);
|
||||||
|
|
||||||
|
// Calculate the cosine of the angle between the light vector and the surface normal
|
||||||
|
float cang = (sin_alt - (deriv.y * cos_az * cos_alt - deriv.x * sin_az * cos_alt)) / sqrt(1.0 + dot(deriv, deriv));
|
||||||
|
float shade = clamp(cang, 0.0, 1.0);
|
||||||
|
|
||||||
|
// Accumulate shadow/highlight contribution from each light
|
||||||
|
if (shade > 0.5) {
|
||||||
|
total_color += props.highlights[i] * (2.0 * shade - 1.0) / float(num_lights);
|
||||||
|
} else {
|
||||||
|
total_color += props.shadows[i] * (1.0 - 2.0 * shade) / float(num_lights);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fragColor = half4(total_color);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Combined shadow and highlight method (Method 1: COMBINED)
|
||||||
|
void combined_hillshade(float2 deriv, device const HillshadeTilePropsUBO& tileProps, device const HillshadeEvaluatedPropsUBO& props, thread half4& fragColor) {
|
||||||
|
// Only supports one light source (index 0)
|
||||||
|
deriv = deriv * tileProps.exaggeration * 2.0;
|
||||||
|
float azimuth = props.azimuths.x + PI;
|
||||||
|
float cos_az = cos(azimuth);
|
||||||
|
float sin_az = sin(azimuth);
|
||||||
|
float cos_alt = cos(props.altitudes.x);
|
||||||
|
float sin_alt = sin(props.altitudes.x);
|
||||||
|
|
||||||
|
// Calculate the angle between the light vector and the surface normal
|
||||||
|
float cang = acos((sin_alt - (deriv.y * cos_az * cos_alt - deriv.x * sin_az * cos_alt)) / sqrt(1.0 + dot(deriv, deriv)));
|
||||||
|
|
||||||
|
cang = clamp(cang, 0.0, PI / 2.0);
|
||||||
|
|
||||||
|
// Calculate shade and highlight components from angle and slope magnitude
|
||||||
|
float shade = cang * atan(length(deriv)) * 4.0 / PI / PI;
|
||||||
|
float highlight = (PI / 2.0 - cang) * atan(length(deriv)) * 4.0 / PI / PI;
|
||||||
|
|
||||||
|
fragColor = half4(props.shadows[0] * shade + props.highlights[0] * highlight);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Igor's shadow/highlight method (Method 2: IGOR)
|
||||||
|
void igor_hillshade(float2 deriv, device const HillshadeTilePropsUBO& tileProps, device const HillshadeEvaluatedPropsUBO& props, thread half4& fragColor) {
|
||||||
|
// Only supports one light source (index 0)
|
||||||
|
deriv = deriv * tileProps.exaggeration * 2.0;
|
||||||
|
float aspect = get_aspect(deriv);
|
||||||
|
float azimuth = props.azimuths.x + PI;
|
||||||
|
|
||||||
|
// Slope strength is magnitude of slope vector, normalized to [0, 1]
|
||||||
|
float slope_strength = atan(length(deriv)) * 2.0 / PI;
|
||||||
|
|
||||||
|
// Aspect strength is difference between aspect and light azimuth, normalized to [0, 1]
|
||||||
|
float aspect_strength = 1.0 - abs(glMod((aspect + azimuth) / PI + 0.5, 2.0) - 1.0);
|
||||||
|
|
||||||
|
float shadow_strength = slope_strength * aspect_strength;
|
||||||
|
float highlight_strength = slope_strength * (1.0 - aspect_strength);
|
||||||
|
|
||||||
|
fragColor = half4(props.shadows[0] * shadow_strength + props.highlights[0] * highlight_strength);
|
||||||
|
}
|
||||||
|
|
||||||
half4 fragment fragmentMain(FragmentStage in [[stage_in]],
|
half4 fragment fragmentMain(FragmentStage in [[stage_in]],
|
||||||
device const uint32_t& uboIndex [[buffer(idGlobalUBOIndex)]],
|
device const uint32_t& uboIndex [[buffer(idGlobalUBOIndex)]],
|
||||||
device const HillshadeTilePropsUBO* tilePropsVector [[buffer(idHillshadeTilePropsUBO)]],
|
device const HillshadeTilePropsUBO* tilePropsVector [[buffer(idHillshadeTilePropsUBO)]],
|
||||||
@@ -90,44 +229,33 @@ half4 fragment fragmentMain(FragmentStage in [[stage_in]],
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
device const HillshadeTilePropsUBO& tileProps = tilePropsVector[uboIndex];
|
device const HillshadeTilePropsUBO& tileProps = tilePropsVector[uboIndex];
|
||||||
|
thread half4 fragColor;
|
||||||
|
|
||||||
float4 pixel = image.sample(image_sampler, in.pos);
|
float4 pixel = image.sample(image_sampler, in.pos);
|
||||||
|
|
||||||
float2 deriv = ((pixel.rg * 2.0) - 1.0);
|
// Scale the derivative based on the mercator distortion at this latitude
|
||||||
|
float latitude = (tileProps.latrange.x - tileProps.latrange.y) * in.pos.y + tileProps.latrange.y;
|
||||||
|
float scaleFactor = cos(radians(latitude));
|
||||||
|
|
||||||
// We divide the slope by a scale factor based on the cosin of the pixel's approximate latitude
|
// The derivative is scaled back from [0, 1] texture range to world-space slope
|
||||||
// to account for mercator projection distortion. see #4807 for details
|
// Texture range [0, 1] corresponds to slope range [-4, 4]
|
||||||
float scaleFactor = cos(radians((tileProps.latrange[0] - tileProps.latrange[1]) * in.pos.y + tileProps.latrange[1]));
|
float2 deriv = ((pixel.rg * 8.0) - 4.0) / scaleFactor;
|
||||||
// We also multiply the slope by an arbitrary z-factor of 1.25
|
|
||||||
float slope = atan(1.25 * length(deriv) / scaleFactor);
|
|
||||||
float aspect = deriv.x != 0.0 ? atan2(deriv.y, -deriv.x) : M_PI_F / 2.0 * (deriv.y > 0.0 ? 1.0 : -1.0);
|
|
||||||
|
|
||||||
float intensity = tileProps.light.x;
|
// Dispatch to the selected hillshade method
|
||||||
// We add PI to make this property match the global light object, which adds PI/2 to the light's azimuthal
|
if (tileProps.method == BASIC) {
|
||||||
// position property to account for 0deg corresponding to north/the top of the viewport in the style spec
|
basic_hillshade(deriv, tileProps, props, fragColor);
|
||||||
// and the original shader was written to accept (-illuminationDirection - 90) as the azimuthal.
|
} else if (tileProps.method == COMBINED) {
|
||||||
float azimuth = tileProps.light.y + M_PI_F;
|
combined_hillshade(deriv, tileProps, props, fragColor);
|
||||||
|
} else if (tileProps.method == IGOR) {
|
||||||
|
igor_hillshade(deriv, tileProps, props, fragColor);
|
||||||
|
} else if (tileProps.method == MULTIDIRECTIONAL) {
|
||||||
|
multidirectional_hillshade(deriv, tileProps, props, fragColor);
|
||||||
|
} else {
|
||||||
|
// Default to STANDARD
|
||||||
|
standard_hillshade(deriv, tileProps, props, fragColor);
|
||||||
|
}
|
||||||
|
|
||||||
// We scale the slope exponentially based on intensity, using a calculation similar to
|
return fragColor;
|
||||||
// the exponential interpolation function in the style spec:
|
|
||||||
// https://github.com/mapbox/mapbox-gl-js/blob/master/src/style-spec/expression/definitions/interpolate.js#L217-L228
|
|
||||||
// so that higher intensity values create more opaque hillshading.
|
|
||||||
float base = 1.875 - intensity * 1.75;
|
|
||||||
float maxValue = 0.5 * M_PI_F;
|
|
||||||
float scaledSlope = intensity != 0.5 ? ((pow(base, slope) - 1.0) / (pow(base, maxValue) - 1.0)) * maxValue : slope;
|
|
||||||
|
|
||||||
// The accent color is calculated with the cosine of the slope while the shade color is calculated with the sine
|
|
||||||
// so that the accent color's rate of change eases in while the shade color's eases out.
|
|
||||||
float accent = cos(scaledSlope);
|
|
||||||
// We multiply both the accent and shade color by a clamped intensity value
|
|
||||||
// so that intensities >= 0.5 do not additionally affect the color values
|
|
||||||
// while intensity values < 0.5 make the overall color more transparent.
|
|
||||||
float4 accent_color = (1.0 - accent) * props.accent * clamp(intensity * 2.0, 0.0, 1.0);
|
|
||||||
float shade = abs(glMod((aspect + azimuth) / M_PI_F + 0.5, 2.0) - 1.0);
|
|
||||||
float4 shade_color = mix(props.shadow, props.highlight, shade) * sin(scaledSlope) * clamp(intensity * 2.0, 0.0, 1.0);
|
|
||||||
float4 color = accent_color * (1.0 - shade_color.a) + shade_color;
|
|
||||||
|
|
||||||
return half4(color);
|
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]],
|
|||||||
|
|
||||||
float2 epsilon = 1.0 / tileProps.dimension;
|
float2 epsilon = 1.0 / tileProps.dimension;
|
||||||
float scale = (tileProps.dimension.x - 2.0) / tileProps.dimension.x;
|
float scale = (tileProps.dimension.x - 2.0) / tileProps.dimension.x;
|
||||||
const float2 pos = (float2(vertx.texture_pos) / 8192.0) * scale + epsilon;
|
float2 pos = (float2(vertx.texture_pos) / 8192.0) * scale + epsilon;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
.position = position,
|
.position = position,
|
||||||
@@ -75,7 +75,7 @@ float getElevation(float2 coord, float bias, texture2d<float, access::sample> im
|
|||||||
// Convert encoded elevation value to meters
|
// Convert encoded elevation value to meters
|
||||||
float4 data = image.sample(image_sampler, coord) * 255.0;
|
float4 data = image.sample(image_sampler, coord) * 255.0;
|
||||||
data.a = -1.0;
|
data.a = -1.0;
|
||||||
return dot(data, unpack) / 4.0;
|
return dot(data, unpack);
|
||||||
}
|
}
|
||||||
|
|
||||||
half4 fragment fragmentMain(FragmentStage in [[stage_in]],
|
half4 fragment fragmentMain(FragmentStage in [[stage_in]],
|
||||||
@@ -87,8 +87,9 @@ half4 fragment fragmentMain(FragmentStage in [[stage_in]],
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
float2 epsilon = 1.0 / tileProps.dimension;
|
float2 epsilon = 1.0 / tileProps.dimension;
|
||||||
|
float tileSize = tileProps.dimension.x - 2.0;
|
||||||
|
|
||||||
// queried pixels:
|
// queried pixels (using Sobel operator kernel):
|
||||||
// +-----------+
|
// +-----------+
|
||||||
// | | | |
|
// | | | |
|
||||||
// | a | b | c |
|
// | a | b | c |
|
||||||
@@ -102,7 +103,6 @@ half4 fragment fragmentMain(FragmentStage in [[stage_in]],
|
|||||||
// | g | h | i |
|
// | g | h | i |
|
||||||
// | | | |
|
// | | | |
|
||||||
// +-----------+
|
// +-----------+
|
||||||
|
|
||||||
float a = getElevation(in.pos + float2(-epsilon.x, -epsilon.y), 0.0, image, image_sampler, tileProps.unpack);
|
float a = getElevation(in.pos + float2(-epsilon.x, -epsilon.y), 0.0, image, image_sampler, tileProps.unpack);
|
||||||
float b = getElevation(in.pos + float2(0, -epsilon.y), 0.0, image, image_sampler, tileProps.unpack);
|
float b = getElevation(in.pos + float2(0, -epsilon.y), 0.0, image, image_sampler, tileProps.unpack);
|
||||||
float c = getElevation(in.pos + float2(epsilon.x, -epsilon.y), 0.0, image, image_sampler, tileProps.unpack);
|
float c = getElevation(in.pos + float2(epsilon.x, -epsilon.y), 0.0, image, image_sampler, tileProps.unpack);
|
||||||
@@ -113,27 +113,24 @@ half4 fragment fragmentMain(FragmentStage in [[stage_in]],
|
|||||||
float h = getElevation(in.pos + float2(0, epsilon.y), 0.0, image, image_sampler, tileProps.unpack);
|
float h = getElevation(in.pos + float2(0, epsilon.y), 0.0, image, image_sampler, tileProps.unpack);
|
||||||
float i = getElevation(in.pos + float2(epsilon.x, epsilon.y), 0.0, image, image_sampler, tileProps.unpack);
|
float i = getElevation(in.pos + float2(epsilon.x, epsilon.y), 0.0, image, image_sampler, tileProps.unpack);
|
||||||
|
|
||||||
// here we divide the x and y slopes by 8 * pixel size
|
// Convert the raw pixel-space derivative (slope) into world-space slope.
|
||||||
// where pixel size (aka meters/pixel) is:
|
// The conversion factor is: tileSize / (8 * meters_per_pixel).
|
||||||
// circumference of the world / (pixels per tile * number of tiles)
|
// meters_per_pixel is calculated as pow(2.0, 28.2562 - u_zoom).
|
||||||
// which is equivalent to: 8 * 40075016.6855785 / (512 * pow(2, u_zoom))
|
// The exaggeration factor is applied to scale the effect at lower zooms.
|
||||||
// which can be reduced to: pow(2, 19.25619978527 - u_zoom)
|
float exaggerationFactor = tileProps.zoom < 2.0 ? 0.4 : tileProps.zoom < 4.5 ? 0.35 : 0.3;
|
||||||
// we want to vertically exaggerate the hillshading though, because otherwise
|
float exaggeration = tileProps.zoom < 15.0 ? (tileProps.zoom - 15.0) * exaggerationFactor : 0.0;
|
||||||
// it is barely noticeable at low zooms. to do this, we multiply this by some
|
|
||||||
// scale factor pow(2, (u_zoom - u_maxzoom) * a) where a is an arbitrary value
|
|
||||||
// Here we use a=0.3 which works out to the expression below. see
|
|
||||||
// nickidlugash's awesome breakdown for more info
|
|
||||||
// https://github.com/mapbox/mapbox-gl-js/pull/5286#discussion_r148419556
|
|
||||||
float exaggeration = tileProps.zoom < 2.0 ? 0.4 : tileProps.zoom < 4.5 ? 0.35 : 0.3;
|
|
||||||
|
|
||||||
float2 deriv = float2(
|
float2 deriv = float2(
|
||||||
(c + f + f + i) - (a + d + d + g),
|
(c + f + f + i) - (a + d + d + g),
|
||||||
(g + h + h + i) - (a + b + b + c)
|
(g + h + h + i) - (a + b + b + c)
|
||||||
) / pow(2.0, (tileProps.zoom - tileProps.maxzoom) * exaggeration + 19.2562 - tileProps.zoom);
|
) * tileSize / pow(2.0, exaggeration + (28.2562 - tileProps.zoom));
|
||||||
|
|
||||||
|
// Encode the derivative into the color channels (r and g)
|
||||||
|
// The derivative is scaled from world-space slope to the range [0, 1] for texture storage.
|
||||||
|
// The maximum possible world-space derivative is assumed to be 4 (hence division by 8.0).
|
||||||
float4 color = clamp(float4(
|
float4 color = clamp(float4(
|
||||||
deriv.x / 2.0 + 0.5,
|
deriv.x / 8.0 + 0.5,
|
||||||
deriv.y / 2.0 + 0.5,
|
deriv.y / 8.0 + 0.5,
|
||||||
1.0,
|
1.0,
|
||||||
1.0), 0.0, 1.0);
|
1.0), 0.0, 1.0);
|
||||||
|
|
||||||
|
|||||||
@@ -78,6 +78,12 @@ enum {
|
|||||||
hillshadePrepareDrawableUBOCount
|
hillshadePrepareDrawableUBOCount
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
idColorReliefDrawableUBO = idDrawableReservedVertexOnlyUBO,
|
||||||
|
idColorReliefTilePropsUBO = drawableReservedUBOCount,
|
||||||
|
colorReliefDrawableUBOCount
|
||||||
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
idLineDrawableUBO = idDrawableReservedVertexOnlyUBO,
|
idLineDrawableUBO = idDrawableReservedVertexOnlyUBO,
|
||||||
idLineTilePropsUBO = idDrawableReservedFragmentOnlyUBO,
|
idLineTilePropsUBO = idDrawableReservedFragmentOnlyUBO,
|
||||||
@@ -120,6 +126,7 @@ static constexpr uint32_t layerUBOStartId = std::max({static_cast<uint32_t>(back
|
|||||||
static_cast<uint32_t>(heatmapTextureDrawableUBOCount),
|
static_cast<uint32_t>(heatmapTextureDrawableUBOCount),
|
||||||
static_cast<uint32_t>(hillshadeDrawableUBOCount),
|
static_cast<uint32_t>(hillshadeDrawableUBOCount),
|
||||||
static_cast<uint32_t>(hillshadePrepareDrawableUBOCount),
|
static_cast<uint32_t>(hillshadePrepareDrawableUBOCount),
|
||||||
|
static_cast<uint32_t>(colorReliefDrawableUBOCount),
|
||||||
static_cast<uint32_t>(lineDrawableUBOCount),
|
static_cast<uint32_t>(lineDrawableUBOCount),
|
||||||
static_cast<uint32_t>(locationIndicatorDrawableUBOCount),
|
static_cast<uint32_t>(locationIndicatorDrawableUBOCount),
|
||||||
static_cast<uint32_t>(rasterDrawableUBOCount),
|
static_cast<uint32_t>(rasterDrawableUBOCount),
|
||||||
@@ -195,6 +202,11 @@ enum {
|
|||||||
hillshadePrepareUBOCount = getLayerStartValue(hillshadePrepareDrawableUBOCount)
|
hillshadePrepareUBOCount = getLayerStartValue(hillshadePrepareDrawableUBOCount)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
idColorReliefEvaluatedPropsUBO = getLayerStartValue(colorReliefDrawableUBOCount),
|
||||||
|
colorReliefUBOCount
|
||||||
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
idLineEvaluatedPropsUBO = getLayerStartValue(lineDrawableUBOCount),
|
idLineEvaluatedPropsUBO = getLayerStartValue(lineDrawableUBOCount),
|
||||||
idLineExpressionUBO,
|
idLineExpressionUBO,
|
||||||
@@ -233,6 +245,7 @@ static constexpr uint32_t maxUBOCountPerShader = std::max({static_cast<uint32_t>
|
|||||||
static_cast<uint32_t>(heatmapTextureUBOCount),
|
static_cast<uint32_t>(heatmapTextureUBOCount),
|
||||||
static_cast<uint32_t>(hillshadeUBOCount),
|
static_cast<uint32_t>(hillshadeUBOCount),
|
||||||
static_cast<uint32_t>(hillshadePrepareUBOCount),
|
static_cast<uint32_t>(hillshadePrepareUBOCount),
|
||||||
|
static_cast<uint32_t>(colorReliefUBOCount),
|
||||||
static_cast<uint32_t>(lineUBOCount),
|
static_cast<uint32_t>(lineUBOCount),
|
||||||
static_cast<uint32_t>(locationIndicatorUBOCount),
|
static_cast<uint32_t>(locationIndicatorUBOCount),
|
||||||
static_cast<uint32_t>(rasterUBOCount),
|
static_cast<uint32_t>(rasterUBOCount),
|
||||||
@@ -296,6 +309,13 @@ enum {
|
|||||||
hillshadeTextureCount
|
hillshadeTextureCount
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
idColorReliefImageTexture,
|
||||||
|
idColorReliefElevationStopsTexture,
|
||||||
|
idColorReliefColorStopsTexture,
|
||||||
|
colorReliefTextureCount
|
||||||
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
idLocationIndicatorTexture,
|
idLocationIndicatorTexture,
|
||||||
locationIndicatorTextureCount
|
locationIndicatorTextureCount
|
||||||
@@ -329,6 +349,7 @@ static constexpr uint32_t maxTextureCountPerShader = std::max({static_cast<uint3
|
|||||||
static_cast<uint32_t>(fillExtrusionTextureCount),
|
static_cast<uint32_t>(fillExtrusionTextureCount),
|
||||||
static_cast<uint32_t>(heatmapTextureCount),
|
static_cast<uint32_t>(heatmapTextureCount),
|
||||||
static_cast<uint32_t>(hillshadeTextureCount),
|
static_cast<uint32_t>(hillshadeTextureCount),
|
||||||
|
static_cast<uint32_t>(colorReliefTextureCount),
|
||||||
static_cast<uint32_t>(lineTextureCount),
|
static_cast<uint32_t>(lineTextureCount),
|
||||||
static_cast<uint32_t>(locationIndicatorTextureCount),
|
static_cast<uint32_t>(locationIndicatorTextureCount),
|
||||||
static_cast<uint32_t>(rasterTextureCount),
|
static_cast<uint32_t>(rasterTextureCount),
|
||||||
@@ -429,6 +450,12 @@ enum {
|
|||||||
hillshadeVertexAttributeCount
|
hillshadeVertexAttributeCount
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
idColorReliefPosVertexAttribute,
|
||||||
|
idColorReliefTexturePosVertexAttribute,
|
||||||
|
colorReliefVertexAttributeCount
|
||||||
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
idLinePosNormalVertexAttribute,
|
idLinePosNormalVertexAttribute,
|
||||||
idLineDataVertexAttribute,
|
idLineDataVertexAttribute,
|
||||||
@@ -505,6 +532,7 @@ static constexpr uint32_t maxVertexAttributeCountPerShader = std::max({
|
|||||||
static_cast<uint32_t>(fillExtrusionVertexAttributeCount),
|
static_cast<uint32_t>(fillExtrusionVertexAttributeCount),
|
||||||
static_cast<uint32_t>(heatmapVertexAttributeCount),
|
static_cast<uint32_t>(heatmapVertexAttributeCount),
|
||||||
static_cast<uint32_t>(hillshadeVertexAttributeCount),
|
static_cast<uint32_t>(hillshadeVertexAttributeCount),
|
||||||
|
static_cast<uint32_t>(colorReliefVertexAttributeCount),
|
||||||
static_cast<uint32_t>(lineVertexAttributeCount),
|
static_cast<uint32_t>(lineVertexAttributeCount),
|
||||||
static_cast<uint32_t>(locationIndicatorVertexAttributeCount),
|
static_cast<uint32_t>(locationIndicatorVertexAttributeCount),
|
||||||
static_cast<uint32_t>(rasterVertexAttributeCount),
|
static_cast<uint32_t>(rasterVertexAttributeCount),
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include <mbgl/shaders/gl/heatmap.hpp>
|
#include <mbgl/shaders/gl/heatmap.hpp>
|
||||||
#include <mbgl/shaders/gl/heatmap_texture.hpp>
|
#include <mbgl/shaders/gl/heatmap_texture.hpp>
|
||||||
#include <mbgl/shaders/gl/hillshade_prepare.hpp>
|
#include <mbgl/shaders/gl/hillshade_prepare.hpp>
|
||||||
|
#include <mbgl/shaders/gl/color_relief.hpp>
|
||||||
#include <mbgl/shaders/gl/hillshade.hpp>
|
#include <mbgl/shaders/gl/hillshade.hpp>
|
||||||
#include <mbgl/shaders/gl/line.hpp>
|
#include <mbgl/shaders/gl/line.hpp>
|
||||||
#include <mbgl/shaders/gl/line_gradient.hpp>
|
#include <mbgl/shaders/gl/line_gradient.hpp>
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ enum class BuiltIn {
|
|||||||
HeatmapShader,
|
HeatmapShader,
|
||||||
HeatmapTextureShader,
|
HeatmapTextureShader,
|
||||||
HillshadePrepareShader,
|
HillshadePrepareShader,
|
||||||
|
ColorReliefShader,
|
||||||
HillshadeShader,
|
HillshadeShader,
|
||||||
LineShader,
|
LineShader,
|
||||||
LineGradientShader,
|
LineGradientShader,
|
||||||
|
|||||||
167
include/mbgl/shaders/vulkan/color_relief.hpp
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <mbgl/shaders/shader_source.hpp>
|
||||||
|
#include <mbgl/shaders/vulkan/shader_program.hpp>
|
||||||
|
|
||||||
|
namespace mbgl {
|
||||||
|
namespace shaders {
|
||||||
|
|
||||||
|
constexpr auto colorReliefShaderPrelude = R"(
|
||||||
|
|
||||||
|
#define idColorReliefDrawableUBO idDrawableReservedVertexOnlyUBO
|
||||||
|
#define idColorReliefTilePropsUBO drawableReservedUBOCount
|
||||||
|
#define idColorReliefEvaluatedPropsUBO layerUBOStartId
|
||||||
|
|
||||||
|
)";
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct ShaderSource<BuiltIn::ColorReliefShader, gfx::Backend::Type::Vulkan> {
|
||||||
|
static constexpr const char* name = "ColorReliefShader";
|
||||||
|
|
||||||
|
static const std::array<AttributeInfo, 2> attributes;
|
||||||
|
static constexpr std::array<AttributeInfo, 0> instanceAttributes{};
|
||||||
|
static const std::array<TextureInfo, 3> textures;
|
||||||
|
|
||||||
|
static constexpr auto prelude = colorReliefShaderPrelude;
|
||||||
|
|
||||||
|
static constexpr auto vertex = R"(
|
||||||
|
|
||||||
|
layout(location = 0) in ivec2 in_position;
|
||||||
|
|
||||||
|
layout(push_constant) uniform Constants {
|
||||||
|
int ubo_index;
|
||||||
|
} constant;
|
||||||
|
|
||||||
|
struct ColorReliefDrawableUBO {
|
||||||
|
mat4 matrix;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ColorReliefTilePropsUBO {
|
||||||
|
vec4 unpack;
|
||||||
|
vec2 dimension;
|
||||||
|
int color_ramp_size;
|
||||||
|
float pad_tile0;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(std140, set = LAYER_SET_INDEX, binding = idColorReliefDrawableUBO) readonly buffer ColorReliefDrawableUBOVector {
|
||||||
|
ColorReliefDrawableUBO drawable_ubo[];
|
||||||
|
} drawableVector;
|
||||||
|
|
||||||
|
layout(std140, set = LAYER_SET_INDEX, binding = idColorReliefTilePropsUBO) readonly buffer ColorReliefTilePropsUBOVector {
|
||||||
|
ColorReliefTilePropsUBO tile_props_ubo[];
|
||||||
|
} tilePropsVector;
|
||||||
|
|
||||||
|
layout(location = 0) out vec2 frag_position;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
const ColorReliefDrawableUBO drawable = drawableVector.drawable_ubo[constant.ubo_index];
|
||||||
|
const ColorReliefTilePropsUBO tileProps = tilePropsVector.tile_props_ubo[constant.ubo_index];
|
||||||
|
|
||||||
|
gl_Position = drawable.matrix * vec4(in_position, 0, 1);
|
||||||
|
applySurfaceTransform();
|
||||||
|
|
||||||
|
highp vec2 epsilon = 1.0 / tileProps.dimension;
|
||||||
|
float scale = (tileProps.dimension.x - 2.0) / tileProps.dimension.x;
|
||||||
|
frag_position = (vec2(in_position) / 8192.0) * scale + epsilon;
|
||||||
|
|
||||||
|
// Handle poles (use in_position to match GLSL a_pos)
|
||||||
|
if (float(in_position.y) < -32767.5) frag_position.y = 0.0;
|
||||||
|
if (float(in_position.y) > 32766.5) frag_position.y = 1.0;
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
static constexpr auto fragment = R"(
|
||||||
|
|
||||||
|
layout(location = 0) in vec2 frag_position;
|
||||||
|
layout(location = 0) out vec4 out_color;
|
||||||
|
|
||||||
|
layout(push_constant) uniform Constants {
|
||||||
|
int ubo_index;
|
||||||
|
} constant;
|
||||||
|
|
||||||
|
struct ColorReliefTilePropsUBO {
|
||||||
|
vec4 unpack;
|
||||||
|
vec2 dimension;
|
||||||
|
int color_ramp_size;
|
||||||
|
float pad_tile0;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(std140, set = LAYER_SET_INDEX, binding = idColorReliefTilePropsUBO) readonly buffer ColorReliefTilePropsUBOVector {
|
||||||
|
ColorReliefTilePropsUBO tile_props_ubo[];
|
||||||
|
} tilePropsVector;
|
||||||
|
|
||||||
|
layout(set = LAYER_SET_INDEX, binding = idColorReliefEvaluatedPropsUBO) uniform ColorReliefEvaluatedPropsUBO {
|
||||||
|
float opacity;
|
||||||
|
float pad_eval0;
|
||||||
|
float pad_eval1;
|
||||||
|
float pad_eval2;
|
||||||
|
} props;
|
||||||
|
|
||||||
|
layout(set = DRAWABLE_IMAGE_SET_INDEX, binding = 0) uniform sampler2D image_sampler;
|
||||||
|
layout(set = DRAWABLE_IMAGE_SET_INDEX, binding = 1) uniform sampler2D elevation_stops_sampler;
|
||||||
|
layout(set = DRAWABLE_IMAGE_SET_INDEX, binding = 2) uniform sampler2D color_stops_sampler;
|
||||||
|
|
||||||
|
float getElevation(vec2 coord, vec4 unpack) {
|
||||||
|
// Convert encoded elevation value to meters
|
||||||
|
vec4 data = texture(image_sampler, coord) * 255.0;
|
||||||
|
data.a = -1.0;
|
||||||
|
return dot(data, unpack);
|
||||||
|
}
|
||||||
|
|
||||||
|
float getElevationStop(int stop, int color_ramp_size) {
|
||||||
|
// Elevation stops are plain float values, not terrain-RGB encoded
|
||||||
|
float x = (float(stop) + 0.5) / float(color_ramp_size);
|
||||||
|
return texture(elevation_stops_sampler, vec2(x, 0.5)).r;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 getColorStop(int stop, int color_ramp_size) {
|
||||||
|
float x = (float(stop) + 0.5) / float(color_ramp_size);
|
||||||
|
return texture(color_stops_sampler, vec2(x, 0.5));
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
|
||||||
|
#if defined(OVERDRAW_INSPECTOR)
|
||||||
|
out_color = vec4(1.0);
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const ColorReliefTilePropsUBO tileProps = tilePropsVector.tile_props_ubo[constant.ubo_index];
|
||||||
|
|
||||||
|
float el = getElevation(frag_position, tileProps.unpack);
|
||||||
|
|
||||||
|
// Binary search to find surrounding elevation stops (l and r indices)
|
||||||
|
int r = tileProps.color_ramp_size - 1;
|
||||||
|
int l = 0;
|
||||||
|
|
||||||
|
// Perform binary search
|
||||||
|
while (r - l > 1) {
|
||||||
|
int m = (r + l) / 2;
|
||||||
|
float el_m = getElevationStop(m, tileProps.color_ramp_size);
|
||||||
|
|
||||||
|
if (el < el_m) {
|
||||||
|
r = m;
|
||||||
|
} else {
|
||||||
|
l = m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get elevation values and colors at the stops
|
||||||
|
float el_l = getElevationStop(l, tileProps.color_ramp_size);
|
||||||
|
float el_r = getElevationStop(r, tileProps.color_ramp_size);
|
||||||
|
|
||||||
|
vec4 color_l = getColorStop(l, tileProps.color_ramp_size);
|
||||||
|
vec4 color_r = getColorStop(r, tileProps.color_ramp_size);
|
||||||
|
|
||||||
|
// Interpolate color based on elevation
|
||||||
|
// Guard against division by zero when el_r == el_l
|
||||||
|
float denom = el_r - el_l;
|
||||||
|
float t = (abs(denom) < 0.0001) ? 0.0 : clamp((el - el_l) / denom, 0.0, 1.0);
|
||||||
|
|
||||||
|
out_color = props.opacity * mix(color_l, color_r, t);
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace shaders
|
||||||
|
} // namespace mbgl
|
||||||
@@ -98,7 +98,7 @@ void main() {
|
|||||||
// weight * u_intensity * GAUSS_COEF * exp(-0.5 * 3.0^2 * S^2) == ZERO
|
// weight * u_intensity * GAUSS_COEF * exp(-0.5 * 3.0^2 * S^2) == ZERO
|
||||||
// Which solves to:
|
// Which solves to:
|
||||||
// S = sqrt(-2.0 * log(ZERO / (weight * u_intensity * GAUSS_COEF))) / 3.0
|
// S = sqrt(-2.0 * log(ZERO / (weight * u_intensity * GAUSS_COEF))) / 3.0
|
||||||
const float S = sqrt(-2.0 * log(ZERO / weight / props.intensity / GAUSS_COEF)) / 3.0;
|
const float S = sqrt(-2.0 * log(ZERO / (max(weight, ZERO) * max(props.intensity, ZERO) * GAUSS_COEF))) / 3.0;
|
||||||
|
|
||||||
// Pass the varying in units of radius
|
// Pass the varying in units of radius
|
||||||
const vec2 extrude = S * unscaled_extrude;
|
const vec2 extrude = S * unscaled_extrude;
|
||||||
|
|||||||
@@ -49,12 +49,19 @@ void main() {
|
|||||||
applySurfaceTransform();
|
applySurfaceTransform();
|
||||||
|
|
||||||
frag_position = vec2(in_texture_position) / 8192.0;
|
frag_position = vec2(in_texture_position) / 8192.0;
|
||||||
frag_position.y = 1.0 - frag_position.y; // TODO check this. prepare should ignore the flip
|
frag_position.y = 1.0 - frag_position.y;
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
|
||||||
static constexpr auto fragment = R"(
|
static constexpr auto fragment = R"(
|
||||||
|
|
||||||
|
#define PI 3.141592653589793
|
||||||
|
#define STANDARD 0
|
||||||
|
#define COMBINED 1
|
||||||
|
#define IGOR 2
|
||||||
|
#define MULTIDIRECTIONAL 3
|
||||||
|
#define BASIC 4
|
||||||
|
|
||||||
layout(location = 0) in vec2 frag_position;
|
layout(location = 0) in vec2 frag_position;
|
||||||
layout(location = 0) out vec4 out_color;
|
layout(location = 0) out vec4 out_color;
|
||||||
|
|
||||||
@@ -64,7 +71,12 @@ layout(push_constant) uniform Constants {
|
|||||||
|
|
||||||
struct HillshadeTilePropsUBO {
|
struct HillshadeTilePropsUBO {
|
||||||
vec2 latrange;
|
vec2 latrange;
|
||||||
vec2 light;
|
float exaggeration;
|
||||||
|
int method;
|
||||||
|
int num_lights;
|
||||||
|
float pad0;
|
||||||
|
float pad1;
|
||||||
|
float pad2;
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(std140, set = LAYER_SET_INDEX, binding = idHillshadeTilePropsUBO) readonly buffer HillshadeTilePropsUBOVector {
|
layout(std140, set = LAYER_SET_INDEX, binding = idHillshadeTilePropsUBO) readonly buffer HillshadeTilePropsUBOVector {
|
||||||
@@ -72,13 +84,140 @@ layout(std140, set = LAYER_SET_INDEX, binding = idHillshadeTilePropsUBO) readonl
|
|||||||
} tilePropsVector;
|
} tilePropsVector;
|
||||||
|
|
||||||
layout(set = LAYER_SET_INDEX, binding = idHillshadeEvaluatedPropsUBO) uniform HillshadeEvaluatedPropsUBO {
|
layout(set = LAYER_SET_INDEX, binding = idHillshadeEvaluatedPropsUBO) uniform HillshadeEvaluatedPropsUBO {
|
||||||
vec4 highlight;
|
|
||||||
vec4 shadow;
|
|
||||||
vec4 accent;
|
vec4 accent;
|
||||||
|
vec4 altitudes;
|
||||||
|
vec4 azimuths;
|
||||||
|
vec4 shadows[4];
|
||||||
|
vec4 highlights[4];
|
||||||
} props;
|
} props;
|
||||||
|
|
||||||
layout(set = DRAWABLE_IMAGE_SET_INDEX, binding = 0) uniform sampler2D image_sampler;
|
layout(set = DRAWABLE_IMAGE_SET_INDEX, binding = 0) uniform sampler2D image_sampler;
|
||||||
|
|
||||||
|
float get_aspect(vec2 deriv) {
|
||||||
|
return deriv.x != 0.0 ? atan(deriv.y, -deriv.x) : PI / 2.0 * (deriv.y > 0.0 ? 1.0 : -1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// MapLibre's legacy hillshade algorithm (Method 0: STANDARD)
|
||||||
|
void standard_hillshade(vec2 deriv, const HillshadeTilePropsUBO tileProps) {
|
||||||
|
float azimuth = props.azimuths.x + PI;
|
||||||
|
float slope = atan(0.625 * length(deriv));
|
||||||
|
float aspect = get_aspect(deriv);
|
||||||
|
|
||||||
|
float intensity = tileProps.exaggeration;
|
||||||
|
|
||||||
|
// Scale the slope exponentially based on intensity
|
||||||
|
float base = 1.875 - intensity * 1.75;
|
||||||
|
float maxValue = 0.5 * PI;
|
||||||
|
float scaledSlope = abs(intensity - 0.5) > 1e-6 ? ((pow(base, slope) - 1.0) / (pow(base, maxValue) - 1.0)) * maxValue : slope;
|
||||||
|
|
||||||
|
float accent = cos(scaledSlope);
|
||||||
|
vec4 accent_color = (1.0 - accent) * props.accent * clamp(intensity * 2.0, 0.0, 1.0);
|
||||||
|
|
||||||
|
float shade = abs(mod((aspect + azimuth) / PI + 0.5, 2.0) - 1.0);
|
||||||
|
vec4 shade_color = mix(props.shadows[0], props.highlights[0], shade) * sin(scaledSlope) * clamp(intensity * 2.0, 0.0, 1.0);
|
||||||
|
|
||||||
|
out_color = accent_color * (1.0 - shade_color.a) + shade_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Basic directional hillshade (Method 4: BASIC)
|
||||||
|
void basic_hillshade(vec2 deriv, const HillshadeTilePropsUBO tileProps) {
|
||||||
|
deriv = deriv * tileProps.exaggeration * 2.0;
|
||||||
|
float azimuth = props.azimuths.x + PI;
|
||||||
|
float cos_az = cos(azimuth);
|
||||||
|
float sin_az = sin(azimuth);
|
||||||
|
float cos_alt = cos(props.altitudes.x);
|
||||||
|
float sin_alt = sin(props.altitudes.x);
|
||||||
|
|
||||||
|
// Calculate the cosine of the angle between the light vector and the surface normal
|
||||||
|
float cang = (sin_alt - (deriv.y * cos_az * cos_alt - deriv.x * sin_az * cos_alt)) / sqrt(1.0 + dot(deriv, deriv));
|
||||||
|
float shade = clamp(cang, 0.0, 1.0);
|
||||||
|
|
||||||
|
// Blend shadow and highlight based on intensity
|
||||||
|
if (shade > 0.5) {
|
||||||
|
out_color = props.highlights[0] * (2.0 * shade - 1.0);
|
||||||
|
} else {
|
||||||
|
out_color = props.shadows[0] * (1.0 - 2.0 * shade);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Multidirectional hillshade (Method 3: MULTIDIRECTIONAL)
|
||||||
|
void multidirectional_hillshade(vec2 deriv, const HillshadeTilePropsUBO tileProps) {
|
||||||
|
deriv = deriv * tileProps.exaggeration * 2.0;
|
||||||
|
vec4 total_color = vec4(0, 0, 0, 0);
|
||||||
|
|
||||||
|
// Access altitude and azimuth from vec4 UBOs
|
||||||
|
float altitudes[4] = float[4](props.altitudes.x, props.altitudes.y, props.altitudes.z, props.altitudes.w);
|
||||||
|
float azimuths[4] = float[4](props.azimuths.x, props.azimuths.y, props.azimuths.z, props.azimuths.w);
|
||||||
|
|
||||||
|
int num_lights = min(tileProps.num_lights, 4);
|
||||||
|
|
||||||
|
// Iterate through all light sources
|
||||||
|
for (int i = 0; i < num_lights; i++) {
|
||||||
|
float altitude = altitudes[i];
|
||||||
|
float azimuth = azimuths[i];
|
||||||
|
|
||||||
|
float cos_alt = cos(altitude);
|
||||||
|
float sin_alt = sin(altitude);
|
||||||
|
// Negate cos/sin azimuth for correct light direction
|
||||||
|
float cos_az = -cos(azimuth);
|
||||||
|
float sin_az = -sin(azimuth);
|
||||||
|
|
||||||
|
// Calculate the cosine of the angle between the light vector and the surface normal
|
||||||
|
float cang = (sin_alt - (deriv.y * cos_az * cos_alt - deriv.x * sin_az * cos_alt)) / sqrt(1.0 + dot(deriv, deriv));
|
||||||
|
float shade = clamp(cang, 0.0, 1.0);
|
||||||
|
|
||||||
|
// Accumulate shadow/highlight contribution from each light
|
||||||
|
if (shade > 0.5) {
|
||||||
|
total_color += props.highlights[i] * (2.0 * shade - 1.0) / float(num_lights);
|
||||||
|
} else {
|
||||||
|
total_color += props.shadows[i] * (1.0 - 2.0 * shade) / float(num_lights);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out_color = total_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Combined shadow and highlight method (Method 1: COMBINED)
|
||||||
|
void combined_hillshade(vec2 deriv, const HillshadeTilePropsUBO tileProps) {
|
||||||
|
// Only supports one light source (index 0)
|
||||||
|
deriv = deriv * tileProps.exaggeration * 2.0;
|
||||||
|
float azimuth = props.azimuths.x + PI;
|
||||||
|
float cos_az = cos(azimuth);
|
||||||
|
float sin_az = sin(azimuth);
|
||||||
|
float cos_alt = cos(props.altitudes.x);
|
||||||
|
float sin_alt = sin(props.altitudes.x);
|
||||||
|
|
||||||
|
// Calculate the angle between the light vector and the surface normal
|
||||||
|
float cang = acos((sin_alt - (deriv.y * cos_az * cos_alt - deriv.x * sin_az * cos_alt)) / sqrt(1.0 + dot(deriv, deriv)));
|
||||||
|
|
||||||
|
cang = clamp(cang, 0.0, PI / 2.0);
|
||||||
|
|
||||||
|
// Calculate shade and highlight components from angle and slope magnitude
|
||||||
|
float shade = cang * atan(length(deriv)) * 4.0 / PI / PI;
|
||||||
|
float highlight = (PI / 2.0 - cang) * atan(length(deriv)) * 4.0 / PI / PI;
|
||||||
|
|
||||||
|
out_color = props.shadows[0] * shade + props.highlights[0] * highlight;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Igor's shadow/highlight method (Method 2: IGOR)
|
||||||
|
void igor_hillshade(vec2 deriv, const HillshadeTilePropsUBO tileProps) {
|
||||||
|
// Only supports one light source (index 0)
|
||||||
|
deriv = deriv * tileProps.exaggeration * 2.0;
|
||||||
|
float aspect = get_aspect(deriv);
|
||||||
|
float azimuth = props.azimuths.x + PI;
|
||||||
|
|
||||||
|
// Slope strength is magnitude of slope vector, normalized to [0, 1]
|
||||||
|
float slope_strength = atan(length(deriv)) * 2.0 / PI;
|
||||||
|
|
||||||
|
// Aspect strength is difference between aspect and light azimuth, normalized to [0, 1]
|
||||||
|
float aspect_strength = 1.0 - abs(mod((aspect + azimuth) / PI + 0.5, 2.0) - 1.0);
|
||||||
|
|
||||||
|
float shadow_strength = slope_strength * aspect_strength;
|
||||||
|
float highlight_strength = slope_strength * (1.0 - aspect_strength);
|
||||||
|
|
||||||
|
out_color = props.shadows[0] * shadow_strength + props.highlights[0] * highlight_strength;
|
||||||
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|
||||||
#if defined(OVERDRAW_INSPECTOR)
|
#if defined(OVERDRAW_INSPECTOR)
|
||||||
@@ -90,41 +229,26 @@ void main() {
|
|||||||
|
|
||||||
vec4 pixel = texture(image_sampler, frag_position);
|
vec4 pixel = texture(image_sampler, frag_position);
|
||||||
|
|
||||||
vec2 deriv = pixel.rg * 2.0 - 1.0;
|
// Scale the derivative based on the mercator distortion at this latitude
|
||||||
|
|
||||||
// We divide the slope by a scale factor based on the cosin of the pixel's approximate latitude
|
|
||||||
// to account for mercator projection distortion. see #4807 for details
|
|
||||||
float scaleFactor = cos(radians((tileProps.latrange[0] - tileProps.latrange[1]) * frag_position.y + tileProps.latrange[1]));
|
float scaleFactor = cos(radians((tileProps.latrange[0] - tileProps.latrange[1]) * frag_position.y + tileProps.latrange[1]));
|
||||||
// We also multiply the slope by an arbitrary z-factor of 1.25
|
|
||||||
float slope = atan(1.25 * length(deriv) / scaleFactor);
|
|
||||||
float aspect = deriv.x != 0.0 ? atan(deriv.y, -deriv.x) : M_PI / 2.0 * (deriv.y > 0.0 ? 1.0 : -1.0);
|
|
||||||
|
|
||||||
float intensity = tileProps.light.x;
|
// The derivative is scaled back from [0, 1] texture range to world-space slope
|
||||||
// We add PI to make this property match the global light object, which adds PI/2 to the light's azimuthal
|
// Texture range [0, 1] corresponds to slope range [-4, 4]
|
||||||
// position property to account for 0deg corresponding to north/the top of the viewport in the style spec
|
vec2 deriv = ((pixel.rg * 8.0) - 4.0) / scaleFactor;
|
||||||
// and the original shader was written to accept (-illuminationDirection - 90) as the azimuthal.
|
|
||||||
float azimuth = tileProps.light.y + M_PI;
|
|
||||||
|
|
||||||
// We scale the slope exponentially based on intensity, using a calculation similar to
|
// Dispatch to the selected hillshade method
|
||||||
// the exponential interpolation function in the style spec:
|
if (tileProps.method == BASIC) {
|
||||||
// https://github.com/mapbox/mapbox-gl-js/blob/master/src/style-spec/expression/definitions/interpolate.js#L217-L228
|
basic_hillshade(deriv, tileProps);
|
||||||
// so that higher intensity values create more opaque hillshading.
|
} else if (tileProps.method == COMBINED) {
|
||||||
float base = 1.875 - intensity * 1.75;
|
combined_hillshade(deriv, tileProps);
|
||||||
float maxValue = 0.5 * M_PI;
|
} else if (tileProps.method == IGOR) {
|
||||||
float scaledSlope = intensity != 0.5 ? ((pow(base, slope) - 1.0) / (pow(base, maxValue) - 1.0)) * maxValue : slope;
|
igor_hillshade(deriv, tileProps);
|
||||||
|
} else if (tileProps.method == MULTIDIRECTIONAL) {
|
||||||
// The accent color is calculated with the cosine of the slope while the shade color is calculated with the sine
|
multidirectional_hillshade(deriv, tileProps);
|
||||||
// so that the accent color's rate of change eases in while the shade color's eases out.
|
} else {
|
||||||
float accent = cos(scaledSlope);
|
// Default to STANDARD
|
||||||
// We multiply both the accent and shade color by a clamped intensity value
|
standard_hillshade(deriv, tileProps);
|
||||||
// so that intensities >= 0.5 do not additionally affect the color values
|
}
|
||||||
// while intensity values < 0.5 make the overall color more transparent.
|
|
||||||
vec4 accent_color = (1.0 - accent) * props.accent * clamp(intensity * 2.0, 0.0, 1.0);
|
|
||||||
float shade = abs(mod((aspect + azimuth) / M_PI + 0.5, 2.0) - 1.0);
|
|
||||||
vec4 shade_color = mix(props.shadow, props.highlight, shade) * sin(scaledSlope) * clamp(intensity * 2.0, 0.0, 1.0);
|
|
||||||
vec4 color = accent_color * (1.0 - shade_color.a) + shade_color;
|
|
||||||
|
|
||||||
out_color = color;
|
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ float getElevation(vec2 coord, float bias, sampler2D image_sampler, vec4 unpack)
|
|||||||
// Convert encoded elevation value to meters
|
// Convert encoded elevation value to meters
|
||||||
vec4 data = texture(image_sampler, coord) * 255.0;
|
vec4 data = texture(image_sampler, coord) * 255.0;
|
||||||
data.a = -1.0;
|
data.a = -1.0;
|
||||||
return dot(data, unpack) / 4.0;
|
return dot(data, unpack);
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
@@ -80,8 +80,9 @@ void main() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
const vec2 epsilon = 1.0 / tileProps.dimension;
|
const vec2 epsilon = 1.0 / tileProps.dimension;
|
||||||
|
const float tileSize = tileProps.dimension.x - 2.0;
|
||||||
|
|
||||||
// queried pixels:
|
// queried pixels (using Sobel operator kernel):
|
||||||
// +-----------+
|
// +-----------+
|
||||||
// | | | |
|
// | | | |
|
||||||
// | a | b | c |
|
// | a | b | c |
|
||||||
@@ -106,27 +107,24 @@ void main() {
|
|||||||
float h = getElevation(frag_position + vec2(0, epsilon.y), 0.0, image_sampler, tileProps.unpack);
|
float h = getElevation(frag_position + vec2(0, epsilon.y), 0.0, image_sampler, tileProps.unpack);
|
||||||
float i = getElevation(frag_position + vec2(epsilon.x, epsilon.y), 0.0, image_sampler, tileProps.unpack);
|
float i = getElevation(frag_position + vec2(epsilon.x, epsilon.y), 0.0, image_sampler, tileProps.unpack);
|
||||||
|
|
||||||
// here we divide the x and y slopes by 8 * pixel size
|
// Convert the raw pixel-space derivative (slope) into world-space slope.
|
||||||
// where pixel size (aka meters/pixel) is:
|
// The conversion factor is: tileSize / (8 * meters_per_pixel).
|
||||||
// circumference of the world / (pixels per tile * number of tiles)
|
// meters_per_pixel is calculated as pow(2.0, 28.2562 - u_zoom).
|
||||||
// which is equivalent to: 8 * 40075016.6855785 / (512 * pow(2, u_zoom))
|
// The exaggeration factor is applied to scale the effect at lower zooms.
|
||||||
// which can be reduced to: pow(2, 19.25619978527 - u_zoom)
|
float exaggerationFactor = tileProps.zoom < 2.0 ? 0.4 : tileProps.zoom < 4.5 ? 0.35 : 0.3;
|
||||||
// we want to vertically exaggerate the hillshading though, because otherwise
|
float exaggeration = tileProps.zoom < 15.0 ? (tileProps.zoom - 15.0) * exaggerationFactor : 0.0;
|
||||||
// it is barely noticeable at low zooms. to do this, we multiply this by some
|
|
||||||
// scale factor pow(2, (u_zoom - u_maxzoom) * a) where a is an arbitrary value
|
|
||||||
// Here we use a=0.3 which works out to the expression below. see
|
|
||||||
// nickidlugash's awesome breakdown for more info
|
|
||||||
// https://github.com/mapbox/mapbox-gl-js/pull/5286#discussion_r148419556
|
|
||||||
float exaggeration = tileProps.zoom < 2.0 ? 0.4 : tileProps.zoom < 4.5 ? 0.35 : 0.3;
|
|
||||||
|
|
||||||
vec2 deriv = vec2(
|
vec2 deriv = vec2(
|
||||||
(c + f + f + i) - (a + d + d + g),
|
(c + f + f + i) - (a + d + d + g),
|
||||||
(g + h + h + i) - (a + b + b + c)
|
(g + h + h + i) - (a + b + b + c)
|
||||||
) / pow(2.0, (tileProps.zoom - tileProps.maxzoom) * exaggeration + 19.2562 - tileProps.zoom);
|
) * tileSize / pow(2.0, exaggeration + (28.2562 - tileProps.zoom));
|
||||||
|
|
||||||
|
// Encode the derivative into the color channels (r and g)
|
||||||
|
// The derivative is scaled from world-space slope to the range [0, 1] for texture storage.
|
||||||
|
// The maximum possible world-space derivative is assumed to be 4 (hence division by 8.0).
|
||||||
out_color = clamp(vec4(
|
out_color = clamp(vec4(
|
||||||
deriv.x / 2.0 + 0.5,
|
deriv.x / 8.0 + 0.5,
|
||||||
deriv.y / 2.0 + 0.5,
|
deriv.y / 8.0 + 0.5,
|
||||||
1.0,
|
1.0,
|
||||||
1.0), 0.0, 1.0);
|
1.0), 0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|||||||
163
include/mbgl/shaders/webgpu/color_relief.hpp
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <mbgl/shaders/shader_source.hpp>
|
||||||
|
#include <mbgl/shaders/webgpu/shader_program.hpp>
|
||||||
|
#include <mbgl/shaders/color_relief_layer_ubo.hpp>
|
||||||
|
|
||||||
|
namespace mbgl {
|
||||||
|
namespace shaders {
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct ShaderSource<BuiltIn::ColorReliefShader, gfx::Backend::Type::WebGPU> {
|
||||||
|
static constexpr const char* name = "ColorReliefShader";
|
||||||
|
static const std::array<AttributeInfo, 2> attributes;
|
||||||
|
static constexpr std::array<AttributeInfo, 0> instanceAttributes{};
|
||||||
|
static const std::array<TextureInfo, 3> textures;
|
||||||
|
|
||||||
|
static constexpr auto vertex = R"(
|
||||||
|
struct VertexInput {
|
||||||
|
@location(5) position: vec2<i32>,
|
||||||
|
@location(6) texture_pos: vec2<i32>,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VertexOutput {
|
||||||
|
@builtin(position) position: vec4<f32>,
|
||||||
|
@location(0) frag_position: vec2<f32>,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GlobalIndexUBO {
|
||||||
|
value: u32,
|
||||||
|
pad0: vec3<u32>,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ColorReliefDrawableUBO {
|
||||||
|
matrix: mat4x4<f32>,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ColorReliefTilePropsUBO {
|
||||||
|
unpack: vec4<f32>,
|
||||||
|
dimension: vec2<f32>,
|
||||||
|
color_ramp_size: i32,
|
||||||
|
pad_tile0: f32,
|
||||||
|
};
|
||||||
|
|
||||||
|
@group(0) @binding(1) var<uniform> globalIndex: GlobalIndexUBO;
|
||||||
|
@group(0) @binding(2) var<storage, read> drawableVector: array<ColorReliefDrawableUBO>;
|
||||||
|
@group(0) @binding(4) var<storage, read> tilePropsVector: array<ColorReliefTilePropsUBO>;
|
||||||
|
|
||||||
|
@vertex
|
||||||
|
fn main(in: VertexInput) -> VertexOutput {
|
||||||
|
var out: VertexOutput;
|
||||||
|
let drawable = drawableVector[globalIndex.value];
|
||||||
|
let tileProps = tilePropsVector[globalIndex.value];
|
||||||
|
|
||||||
|
out.position = drawable.matrix * vec4<f32>(f32(in.position.x), f32(in.position.y), 0.0, 1.0);
|
||||||
|
|
||||||
|
let a_pos = vec2<f32>(f32(in.position.x), f32(in.position.y));
|
||||||
|
let epsilon = vec2<f32>(1.0, 1.0) / tileProps.dimension;
|
||||||
|
let scale = (tileProps.dimension.x - 2.0) / tileProps.dimension.x;
|
||||||
|
out.frag_position = (a_pos / 8192.0) * scale + epsilon;
|
||||||
|
|
||||||
|
// Handle poles
|
||||||
|
out.frag_position.y = select(out.frag_position.y, 0.0, a_pos.y < -32767.5);
|
||||||
|
out.frag_position.y = select(out.frag_position.y, 1.0, a_pos.y > 32766.5);
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
static constexpr auto fragment = R"(
|
||||||
|
struct FragmentInput {
|
||||||
|
@location(0) frag_position: vec2<f32>,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GlobalIndexUBO {
|
||||||
|
value: u32,
|
||||||
|
pad0: vec3<u32>,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ColorReliefTilePropsUBO {
|
||||||
|
unpack: vec4<f32>,
|
||||||
|
dimension: vec2<f32>,
|
||||||
|
color_ramp_size: i32,
|
||||||
|
pad_tile0: f32,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ColorReliefEvaluatedPropsUBO {
|
||||||
|
opacity: f32,
|
||||||
|
pad_eval0: f32,
|
||||||
|
pad_eval1: f32,
|
||||||
|
pad_eval2: f32,
|
||||||
|
};
|
||||||
|
|
||||||
|
@group(0) @binding(1) var<uniform> globalIndex: GlobalIndexUBO;
|
||||||
|
@group(0) @binding(4) var<storage, read> tilePropsVector: array<ColorReliefTilePropsUBO>;
|
||||||
|
@group(0) @binding(5) var<uniform> props: ColorReliefEvaluatedPropsUBO;
|
||||||
|
@group(1) @binding(0) var texture_sampler: sampler;
|
||||||
|
@group(1) @binding(1) var dem_texture: texture_2d<f32>;
|
||||||
|
@group(1) @binding(2) var elevation_stops_texture: texture_2d<f32>;
|
||||||
|
@group(1) @binding(3) var color_stops_texture: texture_2d<f32>;
|
||||||
|
|
||||||
|
fn getElevation(coord: vec2<f32>, unpack: vec4<f32>) -> f32 {
|
||||||
|
var data = textureSample(dem_texture, texture_sampler, coord) * 255.0;
|
||||||
|
data.a = -1.0;
|
||||||
|
return dot(data, unpack);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn getElevationStop(stop: i32, color_ramp_size: i32) -> f32 {
|
||||||
|
// Use textureLoad for RGBA32Float texture (not filterable in WebGPU)
|
||||||
|
return textureLoad(elevation_stops_texture, vec2<i32>(stop, 0), 0).r;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn getColorStop(stop: i32, color_ramp_size: i32) -> vec4<f32> {
|
||||||
|
let x = (f32(stop) + 0.5) / f32(color_ramp_size);
|
||||||
|
return textureSample(color_stops_texture, texture_sampler, vec2<f32>(x, 0.5));
|
||||||
|
}
|
||||||
|
|
||||||
|
@fragment
|
||||||
|
fn main(in: FragmentInput) -> @location(0) vec4<f32> {
|
||||||
|
#ifdef OVERDRAW_INSPECTOR
|
||||||
|
return vec4<f32>(1.0, 1.0, 1.0, 1.0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
let tileProps = tilePropsVector[globalIndex.value];
|
||||||
|
let el = getElevation(in.frag_position, tileProps.unpack);
|
||||||
|
|
||||||
|
// Binary search to find surrounding elevation stops
|
||||||
|
var r: i32 = tileProps.color_ramp_size - 1;
|
||||||
|
var l: i32 = 0;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
if (r - l <= 1) { break; }
|
||||||
|
let m = (r + l) / 2;
|
||||||
|
let el_m = getElevationStop(m, tileProps.color_ramp_size);
|
||||||
|
if (el < el_m) {
|
||||||
|
r = m;
|
||||||
|
} else {
|
||||||
|
l = m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get elevation values and colors at the stops
|
||||||
|
let el_l = getElevationStop(l, tileProps.color_ramp_size);
|
||||||
|
let el_r = getElevationStop(r, tileProps.color_ramp_size);
|
||||||
|
|
||||||
|
let color_l = getColorStop(l, tileProps.color_ramp_size);
|
||||||
|
let color_r = getColorStop(r, tileProps.color_ramp_size);
|
||||||
|
|
||||||
|
// Interpolate color based on elevation
|
||||||
|
// Guard against division by zero when el_r == el_l
|
||||||
|
let denom = el_r - el_l;
|
||||||
|
var t: f32 = 0.0;
|
||||||
|
if (abs(denom) >= 0.0001) {
|
||||||
|
t = clamp((el - el_l) / denom, 0.0, 1.0);
|
||||||
|
}
|
||||||
|
let final_color = mix(color_l, color_r, t) * props.opacity;
|
||||||
|
|
||||||
|
return vec4<f32>(final_color);
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace shaders
|
||||||
|
} // namespace mbgl
|
||||||
@@ -51,6 +51,12 @@ fn main(in: VertexInput) -> VertexOutput {
|
|||||||
)";
|
)";
|
||||||
|
|
||||||
static constexpr auto fragment = R"(
|
static constexpr auto fragment = R"(
|
||||||
|
const STANDARD: i32 = 0;
|
||||||
|
const COMBINED: i32 = 1;
|
||||||
|
const IGOR: i32 = 2;
|
||||||
|
const MULTIDIRECTIONAL: i32 = 3;
|
||||||
|
const BASIC: i32 = 4;
|
||||||
|
|
||||||
struct FragmentInput {
|
struct FragmentInput {
|
||||||
@location(0) tex_coord: vec2<f32>,
|
@location(0) tex_coord: vec2<f32>,
|
||||||
};
|
};
|
||||||
@@ -62,13 +68,20 @@ struct GlobalIndexUBO {
|
|||||||
|
|
||||||
struct HillshadeTilePropsUBO {
|
struct HillshadeTilePropsUBO {
|
||||||
latrange: vec2<f32>,
|
latrange: vec2<f32>,
|
||||||
light: vec2<f32>,
|
exaggeration: f32,
|
||||||
|
method: i32,
|
||||||
|
num_lights: i32,
|
||||||
|
pad0: f32,
|
||||||
|
pad1: f32,
|
||||||
|
pad2: f32,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct HillshadeEvaluatedPropsUBO {
|
struct HillshadeEvaluatedPropsUBO {
|
||||||
highlight: vec4<f32>,
|
|
||||||
shadow: vec4<f32>,
|
|
||||||
accent: vec4<f32>,
|
accent: vec4<f32>,
|
||||||
|
altitudes: vec4<f32>,
|
||||||
|
azimuths: vec4<f32>,
|
||||||
|
shadows: array<vec4<f32>, 4>,
|
||||||
|
highlights: array<vec4<f32>, 4>,
|
||||||
};
|
};
|
||||||
|
|
||||||
@group(0) @binding(1) var<uniform> globalIndex: GlobalIndexUBO;
|
@group(0) @binding(1) var<uniform> globalIndex: GlobalIndexUBO;
|
||||||
@@ -77,6 +90,108 @@ struct HillshadeEvaluatedPropsUBO {
|
|||||||
@group(1) @binding(0) var texture_sampler: sampler;
|
@group(1) @binding(0) var texture_sampler: sampler;
|
||||||
@group(1) @binding(1) var hillshade_texture: texture_2d<f32>;
|
@group(1) @binding(1) var hillshade_texture: texture_2d<f32>;
|
||||||
|
|
||||||
|
fn get_aspect(deriv: vec2<f32>) -> f32 {
|
||||||
|
let aspectDefault = 0.5 * PI * select(-1.0, 1.0, deriv.y > 0.0);
|
||||||
|
return select(aspectDefault, atan2(deriv.y, -deriv.x), deriv.x != 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn standard_hillshade(deriv: vec2<f32>, tileProps: HillshadeTilePropsUBO) -> vec4<f32> {
|
||||||
|
let azimuth = props.azimuths.x + PI;
|
||||||
|
let slope = atan(0.625 * length(deriv));
|
||||||
|
let aspect = get_aspect(deriv);
|
||||||
|
|
||||||
|
let intensity = tileProps.exaggeration;
|
||||||
|
|
||||||
|
let base = 1.875 - intensity * 1.75;
|
||||||
|
let maxValue = 0.5 * PI;
|
||||||
|
let denom = pow(base, maxValue) - 1.0;
|
||||||
|
let useNonLinear = abs(intensity - 0.5) > 1e-6;
|
||||||
|
let scaledSlope = select(slope, ((pow(base, slope) - 1.0) / denom) * maxValue, useNonLinear);
|
||||||
|
|
||||||
|
let accent = cos(scaledSlope);
|
||||||
|
let accentColor = (1.0 - accent) * props.accent * clamp(intensity * 2.0, 0.0, 1.0);
|
||||||
|
|
||||||
|
let shade = abs(glMod((aspect + azimuth) / PI + 0.5, 2.0) - 1.0);
|
||||||
|
let shadeColor = mix(props.shadows[0], props.highlights[0], shade) * sin(scaledSlope) * clamp(intensity * 2.0, 0.0, 1.0);
|
||||||
|
|
||||||
|
return accentColor * (1.0 - shadeColor.a) + shadeColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn basic_hillshade(deriv: vec2<f32>, tileProps: HillshadeTilePropsUBO) -> vec4<f32> {
|
||||||
|
let scaled_deriv = deriv * tileProps.exaggeration * 2.0;
|
||||||
|
let azimuth = props.azimuths.x + PI;
|
||||||
|
let cos_az = cos(azimuth);
|
||||||
|
let sin_az = sin(azimuth);
|
||||||
|
let cos_alt = cos(props.altitudes.x);
|
||||||
|
let sin_alt = sin(props.altitudes.x);
|
||||||
|
|
||||||
|
let cang = (sin_alt - (scaled_deriv.y * cos_az * cos_alt - scaled_deriv.x * sin_az * cos_alt)) / sqrt(1.0 + dot(scaled_deriv, scaled_deriv));
|
||||||
|
let shade = clamp(cang, 0.0, 1.0);
|
||||||
|
|
||||||
|
return select(props.shadows[0] * (1.0 - 2.0 * shade),
|
||||||
|
props.highlights[0] * (2.0 * shade - 1.0),
|
||||||
|
shade > 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn multidirectional_hillshade(deriv: vec2<f32>, tileProps: HillshadeTilePropsUBO) -> vec4<f32> {
|
||||||
|
let scaled_deriv = deriv * tileProps.exaggeration * 2.0;
|
||||||
|
var total_color = vec4<f32>(0.0, 0.0, 0.0, 0.0);
|
||||||
|
|
||||||
|
let num_lights = min(tileProps.num_lights, 4);
|
||||||
|
|
||||||
|
for (var i: i32 = 0; i < num_lights; i = i + 1) {
|
||||||
|
let altitude = select(select(select(props.altitudes.x, props.altitudes.y, i == 1), props.altitudes.z, i == 2), props.altitudes.w, i == 3);
|
||||||
|
let azimuth = select(select(select(props.azimuths.x, props.azimuths.y, i == 1), props.azimuths.z, i == 2), props.azimuths.w, i == 3);
|
||||||
|
|
||||||
|
let cos_alt = cos(altitude);
|
||||||
|
let sin_alt = sin(altitude);
|
||||||
|
let cos_az = -cos(azimuth);
|
||||||
|
let sin_az = -sin(azimuth);
|
||||||
|
|
||||||
|
let cang = (sin_alt - (scaled_deriv.y * cos_az * cos_alt - scaled_deriv.x * sin_az * cos_alt)) / sqrt(1.0 + dot(scaled_deriv, scaled_deriv));
|
||||||
|
let shade = clamp(cang, 0.0, 1.0);
|
||||||
|
|
||||||
|
if (shade > 0.5) {
|
||||||
|
total_color = total_color + props.highlights[i] * (2.0 * shade - 1.0) / f32(num_lights);
|
||||||
|
} else {
|
||||||
|
total_color = total_color + props.shadows[i] * (1.0 - 2.0 * shade) / f32(num_lights);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return total_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn combined_hillshade(deriv: vec2<f32>, tileProps: HillshadeTilePropsUBO) -> vec4<f32> {
|
||||||
|
let scaled_deriv = deriv * tileProps.exaggeration * 2.0;
|
||||||
|
let azimuth = props.azimuths.x + PI;
|
||||||
|
let cos_az = cos(azimuth);
|
||||||
|
let sin_az = sin(azimuth);
|
||||||
|
let cos_alt = cos(props.altitudes.x);
|
||||||
|
let sin_alt = sin(props.altitudes.x);
|
||||||
|
|
||||||
|
let cang = acos((sin_alt - (scaled_deriv.y * cos_az * cos_alt - scaled_deriv.x * sin_az * cos_alt)) / sqrt(1.0 + dot(scaled_deriv, scaled_deriv)));
|
||||||
|
let clamped_cang = clamp(cang, 0.0, PI / 2.0);
|
||||||
|
|
||||||
|
let shade = clamped_cang * atan(length(scaled_deriv)) * 4.0 / PI / PI;
|
||||||
|
let highlight = (PI / 2.0 - clamped_cang) * atan(length(scaled_deriv)) * 4.0 / PI / PI;
|
||||||
|
|
||||||
|
return props.shadows[0] * shade + props.highlights[0] * highlight;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn igor_hillshade(deriv: vec2<f32>, tileProps: HillshadeTilePropsUBO) -> vec4<f32> {
|
||||||
|
let scaled_deriv = deriv * tileProps.exaggeration * 2.0;
|
||||||
|
let aspect = get_aspect(scaled_deriv);
|
||||||
|
let azimuth = props.azimuths.x + PI;
|
||||||
|
|
||||||
|
let slope_strength = atan(length(scaled_deriv)) * 2.0 / PI;
|
||||||
|
let aspect_strength = 1.0 - abs(glMod((aspect + azimuth) / PI + 0.5, 2.0) - 1.0);
|
||||||
|
|
||||||
|
let shadow_strength = slope_strength * aspect_strength;
|
||||||
|
let highlight_strength = slope_strength * (1.0 - aspect_strength);
|
||||||
|
|
||||||
|
return props.shadows[0] * shadow_strength + props.highlights[0] * highlight_strength;
|
||||||
|
}
|
||||||
|
|
||||||
@fragment
|
@fragment
|
||||||
fn main(in: FragmentInput) -> @location(0) vec4<f32> {
|
fn main(in: FragmentInput) -> @location(0) vec4<f32> {
|
||||||
#ifdef OVERDRAW_INSPECTOR
|
#ifdef OVERDRAW_INSPECTOR
|
||||||
@@ -86,34 +201,23 @@ fn main(in: FragmentInput) -> @location(0) vec4<f32> {
|
|||||||
let tileProps = tilePropsVector[globalIndex.value];
|
let tileProps = tilePropsVector[globalIndex.value];
|
||||||
let pixel = textureSample(hillshade_texture, texture_sampler, in.tex_coord);
|
let pixel = textureSample(hillshade_texture, texture_sampler, in.tex_coord);
|
||||||
|
|
||||||
let deriv = pixel.rg * 2.0 - vec2<f32>(1.0, 1.0);
|
|
||||||
|
|
||||||
let latRange = tileProps.latrange;
|
let latRange = tileProps.latrange;
|
||||||
let latitude = (latRange.x - latRange.y) * in.tex_coord.y + latRange.y;
|
let latitude = (latRange.x - latRange.y) * in.tex_coord.y + latRange.y;
|
||||||
let scaleFactor = cos(radians(latitude));
|
let scaleFactor = cos(radians(latitude));
|
||||||
let slope = atan(1.25 * length(deriv) / scaleFactor);
|
|
||||||
let aspectDefault = 0.5 * PI * select(-1.0, 1.0, deriv.y > 0.0);
|
|
||||||
let aspect = select(aspectDefault, atan2(deriv.y, -deriv.x), deriv.x != 0.0);
|
|
||||||
|
|
||||||
let intensity = tileProps.light.x;
|
let deriv = ((pixel.rg * 8.0) - vec2<f32>(4.0, 4.0)) / scaleFactor;
|
||||||
let azimuth = tileProps.light.y + PI;
|
|
||||||
|
|
||||||
let base = 1.875 - intensity * 1.75;
|
if (tileProps.method == BASIC) {
|
||||||
let maxValue = 0.5 * PI;
|
return basic_hillshade(deriv, tileProps);
|
||||||
let denom = pow(base, maxValue) - 1.0;
|
} else if (tileProps.method == COMBINED) {
|
||||||
let useLinear = abs(intensity - 0.5) < 1e-6;
|
return combined_hillshade(deriv, tileProps);
|
||||||
let scaledSlope = select(((pow(base, slope) - 1.0) / denom) * maxValue,
|
} else if (tileProps.method == IGOR) {
|
||||||
slope,
|
return igor_hillshade(deriv, tileProps);
|
||||||
useLinear);
|
} else if (tileProps.method == MULTIDIRECTIONAL) {
|
||||||
|
return multidirectional_hillshade(deriv, tileProps);
|
||||||
let accent = cos(scaledSlope);
|
} else {
|
||||||
let accentColor = (1.0 - accent) * props.accent * clamp(intensity * 2.0, 0.0, 1.0);
|
return standard_hillshade(deriv, tileProps);
|
||||||
|
}
|
||||||
let shade = abs(glMod((aspect + azimuth) / PI + 0.5, 2.0) - 1.0);
|
|
||||||
let shadeColor = mix(props.shadow, props.highlight, shade) * sin(scaledSlope) * clamp(intensity * 2.0, 0.0, 1.0);
|
|
||||||
|
|
||||||
let color = accentColor * (1.0 - shadeColor.a) + shadeColor;
|
|
||||||
return color;
|
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ struct HillshadePrepareTilePropsUBO {
|
|||||||
fn getElevation(coord: vec2<f32>) -> f32 {
|
fn getElevation(coord: vec2<f32>) -> f32 {
|
||||||
var data = textureSample(dem_texture, texture_sampler, coord) * 255.0;
|
var data = textureSample(dem_texture, texture_sampler, coord) * 255.0;
|
||||||
data.a = -1.0;
|
data.a = -1.0;
|
||||||
return dot(data, tileProps.unpack) / 4.0;
|
return dot(data, tileProps.unpack);
|
||||||
}
|
}
|
||||||
|
|
||||||
@fragment
|
@fragment
|
||||||
@@ -80,6 +80,7 @@ fn main(in: FragmentInput) -> @location(0) vec4<f32> {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
let epsilon = vec2<f32>(1.0, 1.0) / tileProps.dimension;
|
let epsilon = vec2<f32>(1.0, 1.0) / tileProps.dimension;
|
||||||
|
let tileSize = tileProps.dimension.x - 2.0;
|
||||||
|
|
||||||
let a = getElevation(in.tex_coord + vec2<f32>(-epsilon.x, -epsilon.y));
|
let a = getElevation(in.tex_coord + vec2<f32>(-epsilon.x, -epsilon.y));
|
||||||
let b = getElevation(in.tex_coord + vec2<f32>(0.0, -epsilon.y));
|
let b = getElevation(in.tex_coord + vec2<f32>(0.0, -epsilon.y));
|
||||||
@@ -90,20 +91,24 @@ fn main(in: FragmentInput) -> @location(0) vec4<f32> {
|
|||||||
let h = getElevation(in.tex_coord + vec2<f32>(0.0, epsilon.y));
|
let h = getElevation(in.tex_coord + vec2<f32>(0.0, epsilon.y));
|
||||||
let i = getElevation(in.tex_coord + vec2<f32>(epsilon.x, epsilon.y));
|
let i = getElevation(in.tex_coord + vec2<f32>(epsilon.x, epsilon.y));
|
||||||
|
|
||||||
var exaggeration = 0.3;
|
var exaggerationFactor = 0.3;
|
||||||
if (tileProps.zoom < 4.5) {
|
if (tileProps.zoom < 4.5) {
|
||||||
exaggeration = 0.35;
|
exaggerationFactor = 0.35;
|
||||||
}
|
}
|
||||||
if (tileProps.zoom < 2.0) {
|
if (tileProps.zoom < 2.0) {
|
||||||
exaggeration = 0.4;
|
exaggerationFactor = 0.4;
|
||||||
|
}
|
||||||
|
var exaggeration = 0.0;
|
||||||
|
if (tileProps.zoom < 15.0) {
|
||||||
|
exaggeration = (tileProps.zoom - 15.0) * exaggerationFactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
let denom = pow(2.0, (tileProps.zoom - tileProps.maxzoom) * exaggeration + 19.2562 - tileProps.zoom);
|
let denom = pow(2.0, exaggeration + (28.2562 - tileProps.zoom));
|
||||||
let deriv = vec2<f32>((c + f + f + i) - (a + d + d + g),
|
let deriv = vec2<f32>((c + f + f + i) - (a + d + d + g),
|
||||||
(g + h + h + i) - (a + b + b + c)) / denom;
|
(g + h + h + i) - (a + b + b + c)) * tileSize / denom;
|
||||||
|
|
||||||
let color = clamp(vec4<f32>(deriv.x / 2.0 + 0.5,
|
let color = clamp(vec4<f32>(deriv.x / 8.0 + 0.5,
|
||||||
deriv.y / 2.0 + 0.5,
|
deriv.y / 8.0 + 0.5,
|
||||||
1.0,
|
1.0,
|
||||||
1.0),
|
1.0),
|
||||||
vec4<f32>(0.0, 0.0, 0.0, 0.0),
|
vec4<f32>(0.0, 0.0, 0.0, 0.0),
|
||||||
|
|||||||
@@ -66,7 +66,8 @@ public:
|
|||||||
ReadOnlyStorageBuffer,
|
ReadOnlyStorageBuffer,
|
||||||
StorageBuffer,
|
StorageBuffer,
|
||||||
Sampler,
|
Sampler,
|
||||||
Texture
|
Texture,
|
||||||
|
UnfilterableTexture // For RGBA32Float textures that require textureLoad instead of textureSample
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BindingInfo {
|
struct BindingInfo {
|
||||||
|
|||||||
@@ -46,6 +46,11 @@ struct Converter<Color> {
|
|||||||
std::optional<Color> operator()(const Convertible& value, Error& error) const;
|
std::optional<Color> operator()(const Convertible& value, Error& error) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct Converter<std::vector<Color>> {
|
||||||
|
std::optional<std::vector<Color>> operator()(const Convertible& value, Error& error) const;
|
||||||
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct Converter<Padding> {
|
struct Converter<Padding> {
|
||||||
std::optional<Padding> operator()(const Convertible& value, Error& error) const;
|
std::optional<Padding> operator()(const Convertible& value, Error& error) const;
|
||||||
|
|||||||
@@ -51,6 +51,15 @@ public:
|
|||||||
feature(feature_),
|
feature(feature_),
|
||||||
colorRampParameter(std::move(colorRampParameter_)) {}
|
colorRampParameter(std::move(colorRampParameter_)) {}
|
||||||
|
|
||||||
|
EvaluationContext(std::optional<float> zoom_,
|
||||||
|
GeometryTileFeature const* feature_,
|
||||||
|
std::optional<double> colorRampParameter_,
|
||||||
|
std::optional<float> elevation_) noexcept
|
||||||
|
: zoom(std::move(zoom_)),
|
||||||
|
feature(feature_),
|
||||||
|
colorRampParameter(std::move(colorRampParameter_)),
|
||||||
|
elevation(std::move(elevation_)) {}
|
||||||
|
|
||||||
EvaluationContext& withFormattedSection(const Value* formattedSection_) noexcept {
|
EvaluationContext& withFormattedSection(const Value* formattedSection_) noexcept {
|
||||||
formattedSection = formattedSection_;
|
formattedSection = formattedSection_;
|
||||||
return *this;
|
return *this;
|
||||||
@@ -71,10 +80,16 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
EvaluationContext& withElevation(float elevation_) noexcept {
|
||||||
|
elevation = elevation_;
|
||||||
|
return *this;
|
||||||
|
};
|
||||||
|
|
||||||
std::optional<float> zoom;
|
std::optional<float> zoom;
|
||||||
std::optional<mbgl::Value> accumulated;
|
std::optional<mbgl::Value> accumulated;
|
||||||
GeometryTileFeature const* feature = nullptr;
|
GeometryTileFeature const* feature = nullptr;
|
||||||
std::optional<double> colorRampParameter;
|
std::optional<double> colorRampParameter;
|
||||||
|
std::optional<float> elevation;
|
||||||
// Contains formatted section object, std::unordered_map<std::string, Value>.
|
// Contains formatted section object, std::unordered_map<std::string, Value>.
|
||||||
const Value* formattedSection = nullptr;
|
const Value* formattedSection = nullptr;
|
||||||
const FeatureState* featureState = nullptr;
|
const FeatureState* featureState = nullptr;
|
||||||
@@ -202,7 +217,8 @@ enum class Dependency : uint32_t {
|
|||||||
Bind = 1 << 4, // Create variable binding ("let")
|
Bind = 1 << 4, // Create variable binding ("let")
|
||||||
Var = 1 << 5, // Use variable binding
|
Var = 1 << 5, // Use variable binding
|
||||||
Override = 1 << 6, // Property override
|
Override = 1 << 6, // Property override
|
||||||
MaskCount = 7,
|
Elevation = 1 << 7, // Elevation from DEM
|
||||||
|
MaskCount = 8,
|
||||||
All = (1 << MaskCount) - 1,
|
All = (1 << MaskCount) - 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
59
include/mbgl/style/layers/color_relief_layer.hpp
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
// clang-format off
|
||||||
|
|
||||||
|
// This file is generated. Do not edit.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <mbgl/style/color_ramp_property_value.hpp>
|
||||||
|
#include <mbgl/style/layer.hpp>
|
||||||
|
#include <mbgl/style/filter.hpp>
|
||||||
|
#include <mbgl/style/property_value.hpp>
|
||||||
|
#include <mbgl/util/color.hpp>
|
||||||
|
|
||||||
|
namespace mbgl {
|
||||||
|
namespace style {
|
||||||
|
|
||||||
|
class TransitionOptions;
|
||||||
|
|
||||||
|
class ColorReliefLayer final : public Layer {
|
||||||
|
public:
|
||||||
|
ColorReliefLayer(const std::string& layerID, const std::string& sourceID);
|
||||||
|
~ColorReliefLayer() override;
|
||||||
|
|
||||||
|
// Paint properties
|
||||||
|
|
||||||
|
static ColorRampPropertyValue getDefaultColorReliefColor();
|
||||||
|
const ColorRampPropertyValue& getColorReliefColor() const;
|
||||||
|
void setColorReliefColor(const ColorRampPropertyValue&);
|
||||||
|
void setColorReliefColorTransition(const TransitionOptions&);
|
||||||
|
TransitionOptions getColorReliefColorTransition() const;
|
||||||
|
|
||||||
|
static PropertyValue<float> getDefaultColorReliefOpacity();
|
||||||
|
const PropertyValue<float>& getColorReliefOpacity() const;
|
||||||
|
void setColorReliefOpacity(const PropertyValue<float>&);
|
||||||
|
void setColorReliefOpacityTransition(const TransitionOptions&);
|
||||||
|
TransitionOptions getColorReliefOpacityTransition() const;
|
||||||
|
|
||||||
|
// Private implementation
|
||||||
|
|
||||||
|
class Impl;
|
||||||
|
const Impl& impl() const;
|
||||||
|
|
||||||
|
Mutable<Impl> mutableImpl() const;
|
||||||
|
ColorReliefLayer(Immutable<Impl>);
|
||||||
|
std::unique_ptr<Layer> cloneRef(const std::string& id) const final;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Dynamic properties
|
||||||
|
std::optional<conversion::Error> setPropertyInternal(const std::string& name, const conversion::Convertible& value) final;
|
||||||
|
|
||||||
|
StyleProperty getProperty(const std::string& name) const final;
|
||||||
|
Value serialize() const final;
|
||||||
|
|
||||||
|
Mutable<Layer::Impl> mutableBaseImpl() const final;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace style
|
||||||
|
} // namespace mbgl
|
||||||
|
|
||||||
|
// clang-format on
|
||||||
@@ -33,27 +33,39 @@ public:
|
|||||||
void setHillshadeExaggerationTransition(const TransitionOptions&);
|
void setHillshadeExaggerationTransition(const TransitionOptions&);
|
||||||
TransitionOptions getHillshadeExaggerationTransition() const;
|
TransitionOptions getHillshadeExaggerationTransition() const;
|
||||||
|
|
||||||
static PropertyValue<Color> getDefaultHillshadeHighlightColor();
|
static PropertyValue<std::vector<Color>> getDefaultHillshadeHighlightColor();
|
||||||
const PropertyValue<Color>& getHillshadeHighlightColor() const;
|
const PropertyValue<std::vector<Color>>& getHillshadeHighlightColor() const;
|
||||||
void setHillshadeHighlightColor(const PropertyValue<Color>&);
|
void setHillshadeHighlightColor(const PropertyValue<std::vector<Color>>&);
|
||||||
void setHillshadeHighlightColorTransition(const TransitionOptions&);
|
void setHillshadeHighlightColorTransition(const TransitionOptions&);
|
||||||
TransitionOptions getHillshadeHighlightColorTransition() const;
|
TransitionOptions getHillshadeHighlightColorTransition() const;
|
||||||
|
|
||||||
|
static PropertyValue<std::vector<float>> getDefaultHillshadeIlluminationAltitude();
|
||||||
|
const PropertyValue<std::vector<float>>& getHillshadeIlluminationAltitude() const;
|
||||||
|
void setHillshadeIlluminationAltitude(const PropertyValue<std::vector<float>>&);
|
||||||
|
void setHillshadeIlluminationAltitudeTransition(const TransitionOptions&);
|
||||||
|
TransitionOptions getHillshadeIlluminationAltitudeTransition() const;
|
||||||
|
|
||||||
static PropertyValue<HillshadeIlluminationAnchorType> getDefaultHillshadeIlluminationAnchor();
|
static PropertyValue<HillshadeIlluminationAnchorType> getDefaultHillshadeIlluminationAnchor();
|
||||||
const PropertyValue<HillshadeIlluminationAnchorType>& getHillshadeIlluminationAnchor() const;
|
const PropertyValue<HillshadeIlluminationAnchorType>& getHillshadeIlluminationAnchor() const;
|
||||||
void setHillshadeIlluminationAnchor(const PropertyValue<HillshadeIlluminationAnchorType>&);
|
void setHillshadeIlluminationAnchor(const PropertyValue<HillshadeIlluminationAnchorType>&);
|
||||||
void setHillshadeIlluminationAnchorTransition(const TransitionOptions&);
|
void setHillshadeIlluminationAnchorTransition(const TransitionOptions&);
|
||||||
TransitionOptions getHillshadeIlluminationAnchorTransition() const;
|
TransitionOptions getHillshadeIlluminationAnchorTransition() const;
|
||||||
|
|
||||||
static PropertyValue<float> getDefaultHillshadeIlluminationDirection();
|
static PropertyValue<std::vector<float>> getDefaultHillshadeIlluminationDirection();
|
||||||
const PropertyValue<float>& getHillshadeIlluminationDirection() const;
|
const PropertyValue<std::vector<float>>& getHillshadeIlluminationDirection() const;
|
||||||
void setHillshadeIlluminationDirection(const PropertyValue<float>&);
|
void setHillshadeIlluminationDirection(const PropertyValue<std::vector<float>>&);
|
||||||
void setHillshadeIlluminationDirectionTransition(const TransitionOptions&);
|
void setHillshadeIlluminationDirectionTransition(const TransitionOptions&);
|
||||||
TransitionOptions getHillshadeIlluminationDirectionTransition() const;
|
TransitionOptions getHillshadeIlluminationDirectionTransition() const;
|
||||||
|
|
||||||
static PropertyValue<Color> getDefaultHillshadeShadowColor();
|
static PropertyValue<HillshadeMethodType> getDefaultHillshadeMethod();
|
||||||
const PropertyValue<Color>& getHillshadeShadowColor() const;
|
const PropertyValue<HillshadeMethodType>& getHillshadeMethod() const;
|
||||||
void setHillshadeShadowColor(const PropertyValue<Color>&);
|
void setHillshadeMethod(const PropertyValue<HillshadeMethodType>&);
|
||||||
|
void setHillshadeMethodTransition(const TransitionOptions&);
|
||||||
|
TransitionOptions getHillshadeMethodTransition() const;
|
||||||
|
|
||||||
|
static PropertyValue<std::vector<Color>> getDefaultHillshadeShadowColor();
|
||||||
|
const PropertyValue<std::vector<Color>>& getHillshadeShadowColor() const;
|
||||||
|
void setHillshadeShadowColor(const PropertyValue<std::vector<Color>>&);
|
||||||
void setHillshadeShadowColorTransition(const TransitionOptions&);
|
void setHillshadeShadowColorTransition(const TransitionOptions&);
|
||||||
TransitionOptions getHillshadeShadowColorTransition() const;
|
TransitionOptions getHillshadeShadowColorTransition() const;
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
<% if (type === 'heatmap' || type === 'line') { -%>
|
<% if (type === 'heatmap' || type === 'line' || type === 'color-relief') { -%>
|
||||||
#include <mbgl/style/color_ramp_property_value.hpp>
|
#include <mbgl/style/color_ramp_property_value.hpp>
|
||||||
<% } -%>
|
<% } -%>
|
||||||
#include <mbgl/style/layer.hpp>
|
#include <mbgl/style/layer.hpp>
|
||||||
|
|||||||
@@ -48,6 +48,14 @@ enum class HillshadeIlluminationAnchorType : bool {
|
|||||||
Viewport
|
Viewport
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class HillshadeMethodType : uint8_t {
|
||||||
|
Standard,
|
||||||
|
Combined,
|
||||||
|
Igor,
|
||||||
|
Multidirectional,
|
||||||
|
Basic
|
||||||
|
};
|
||||||
|
|
||||||
enum class TranslateAnchorType : bool {
|
enum class TranslateAnchorType : bool {
|
||||||
Map,
|
Map,
|
||||||
Viewport
|
Viewport
|
||||||
|
|||||||
|
After Width: | Height: | Size: 152 KiB |
@@ -0,0 +1,59 @@
|
|||||||
|
{
|
||||||
|
"version": 8,
|
||||||
|
"metadata": {
|
||||||
|
"test": {
|
||||||
|
"height": 256,
|
||||||
|
"width": 256
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"center": [-113.26903, 35.9654],
|
||||||
|
"zoom": 11,
|
||||||
|
"sources": {
|
||||||
|
"source": {
|
||||||
|
"type": "raster-dem",
|
||||||
|
"tiles": [
|
||||||
|
"local://tiles/{z}-{x}-{y}.terrain.png"
|
||||||
|
],
|
||||||
|
"maxzoom": 15,
|
||||||
|
"tileSize": 256
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"layers": [
|
||||||
|
{
|
||||||
|
"id": "color-relief",
|
||||||
|
"type": "color-relief",
|
||||||
|
"source": "source",
|
||||||
|
"paint": {
|
||||||
|
"color-relief-opacity": 1,
|
||||||
|
"color-relief-color": [
|
||||||
|
"interpolate",
|
||||||
|
["linear"],
|
||||||
|
["elevation"],
|
||||||
|
400, "rgb(112, 209, 255)",
|
||||||
|
494.1176471, "rgb(113, 211, 247)",
|
||||||
|
588.2352941, "rgb(114, 212, 234)",
|
||||||
|
682.3529412, "rgb(117, 213, 222)",
|
||||||
|
776.4705882, "rgb(120, 214, 209)",
|
||||||
|
870.5882353, "rgb(124, 215, 196)",
|
||||||
|
964.7058824, "rgb(130, 215, 183)",
|
||||||
|
1058.823529, "rgb(138, 215, 169)",
|
||||||
|
1152.941176, "rgb(149, 214, 155)",
|
||||||
|
1247.058824, "rgb(163, 212, 143)",
|
||||||
|
1341.176471, "rgb(178, 209, 134)",
|
||||||
|
1435.294118, "rgb(193, 205, 127)",
|
||||||
|
1529.411765, "rgb(207, 202, 121)",
|
||||||
|
1623.529412, "rgb(220, 197, 118)",
|
||||||
|
1717.647059, "rgb(233, 193, 118)",
|
||||||
|
1811.764706, "rgb(244, 188, 120)",
|
||||||
|
1905.882353, "rgb(255, 183, 124)",
|
||||||
|
2000, "rgb(255, 178, 129)"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "hillshade",
|
||||||
|
"type": "hillshade",
|
||||||
|
"source": "source"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 51 KiB |
@@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
"version": 8,
|
||||||
|
"metadata": {
|
||||||
|
"test": {
|
||||||
|
"height": 256,
|
||||||
|
"width": 256,
|
||||||
|
"description": "This test verifies color-relief rendering at low zoom levels (zoom 1) where exaggeration scaling is applied"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"center": [0, 45],
|
||||||
|
"zoom": 1,
|
||||||
|
"sources": {
|
||||||
|
"source": {
|
||||||
|
"type": "raster-dem",
|
||||||
|
"tiles": [
|
||||||
|
"local://tiles/{z}-{x}-{y}.terrain.png"
|
||||||
|
],
|
||||||
|
"maxzoom": 15,
|
||||||
|
"tileSize": 512
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"layers": [
|
||||||
|
{
|
||||||
|
"id": "background",
|
||||||
|
"type": "background",
|
||||||
|
"paint": {
|
||||||
|
"background-color": "white"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "color-relief",
|
||||||
|
"type": "color-relief",
|
||||||
|
"source": "source",
|
||||||
|
"paint": {
|
||||||
|
"color-relief-opacity": 1,
|
||||||
|
"color-relief-color": [
|
||||||
|
"interpolate",
|
||||||
|
["linear"],
|
||||||
|
["elevation"],
|
||||||
|
0, "#006600",
|
||||||
|
500, "#00FF00",
|
||||||
|
1000, "#FFFF00",
|
||||||
|
2000, "#FF8800",
|
||||||
|
3000, "#FF0000",
|
||||||
|
5000, "#FFFFFF"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 70 KiB |
@@ -0,0 +1,43 @@
|
|||||||
|
{
|
||||||
|
"version": 8,
|
||||||
|
"metadata": {
|
||||||
|
"test": {
|
||||||
|
"height": 256,
|
||||||
|
"width": 256
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"center": [-113.26903, 35.9654],
|
||||||
|
"zoom": 11,
|
||||||
|
"sources": {
|
||||||
|
"source": {
|
||||||
|
"type": "raster-dem",
|
||||||
|
"tiles": [
|
||||||
|
"local://tiles/{z}-{x}-{y}.terrain.png"
|
||||||
|
],
|
||||||
|
"maxzoom": 15,
|
||||||
|
"tileSize": 256
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"layers": [
|
||||||
|
{
|
||||||
|
"id": "color-relief",
|
||||||
|
"type": "color-relief",
|
||||||
|
"source": "source",
|
||||||
|
"paint": {
|
||||||
|
"color-relief-opacity": 0.5,
|
||||||
|
"color-relief-color": [
|
||||||
|
"interpolate",
|
||||||
|
["linear"],
|
||||||
|
["elevation"],
|
||||||
|
400, "#F00",
|
||||||
|
800, "#AA0",
|
||||||
|
1000, "#AF0",
|
||||||
|
1200, "#0F0",
|
||||||
|
1400, "#0AA",
|
||||||
|
1600, "#00F",
|
||||||
|
2000, "#C0C"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 84 KiB |
@@ -0,0 +1,43 @@
|
|||||||
|
{
|
||||||
|
"version": 8,
|
||||||
|
"metadata": {
|
||||||
|
"test": {
|
||||||
|
"height": 256,
|
||||||
|
"width": 256
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"center": [-113.26903, 35.9654],
|
||||||
|
"zoom": 11,
|
||||||
|
"sources": {
|
||||||
|
"source": {
|
||||||
|
"type": "raster-dem",
|
||||||
|
"tiles": [
|
||||||
|
"local://tiles/{z}-{x}-{y}.terrain.png"
|
||||||
|
],
|
||||||
|
"maxzoom": 15,
|
||||||
|
"tileSize": 256
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"layers": [
|
||||||
|
{
|
||||||
|
"id": "color-relief",
|
||||||
|
"type": "color-relief",
|
||||||
|
"source": "source",
|
||||||
|
"paint": {
|
||||||
|
"color-relief-opacity": 1,
|
||||||
|
"color-relief-color": [
|
||||||
|
"interpolate",
|
||||||
|
["linear"],
|
||||||
|
["elevation"],
|
||||||
|
400, "#F00",
|
||||||
|
800, "#AA0",
|
||||||
|
1000, "#AF0",
|
||||||
|
1200, "#0F0",
|
||||||
|
1400, "#0AA",
|
||||||
|
1600, "#00F",
|
||||||
|
2000, "#C0C"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 95 KiB |
@@ -0,0 +1,43 @@
|
|||||||
|
{
|
||||||
|
"version": 8,
|
||||||
|
"metadata": {
|
||||||
|
"test": {
|
||||||
|
"height": 256,
|
||||||
|
"width": 256
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"center": [-113.26903, 35.9654],
|
||||||
|
"zoom": 11,
|
||||||
|
"sources": {
|
||||||
|
"source": {
|
||||||
|
"type": "raster-dem",
|
||||||
|
"tiles": [
|
||||||
|
"local://tiles/{z}-{x}-{y}.terrain.png"
|
||||||
|
],
|
||||||
|
"maxzoom": 15,
|
||||||
|
"tileSize": 256
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"layers": [
|
||||||
|
{
|
||||||
|
"id": "color-relief",
|
||||||
|
"type": "color-relief",
|
||||||
|
"source": "source",
|
||||||
|
"paint": {
|
||||||
|
"color-relief-opacity": 1,
|
||||||
|
"color-relief-color": [
|
||||||
|
"interpolate",
|
||||||
|
["linear"],
|
||||||
|
["elevation"],
|
||||||
|
400, "#F00C",
|
||||||
|
800, "#AA0A",
|
||||||
|
1000, "#AF09",
|
||||||
|
1200, "#0F08",
|
||||||
|
1400, "#0AA7",
|
||||||
|
1600, "#00F6",
|
||||||
|
2000, "#C0C4"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 88 KiB |
@@ -0,0 +1,66 @@
|
|||||||
|
{
|
||||||
|
"version": 8,
|
||||||
|
"metadata": {
|
||||||
|
"test": {
|
||||||
|
"height": 256,
|
||||||
|
"width": 256,
|
||||||
|
"description": "This test verifies combined hillshade and color-relief rendering at low zoom levels (zoom 1) where exaggeration scaling is applied"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"center": [0, 45],
|
||||||
|
"zoom": 1,
|
||||||
|
"sources": {
|
||||||
|
"dem-hillshade": {
|
||||||
|
"type": "raster-dem",
|
||||||
|
"tiles": [
|
||||||
|
"local://tiles/{z}-{x}-{y}.terrain.png"
|
||||||
|
],
|
||||||
|
"maxzoom": 15,
|
||||||
|
"tileSize": 512
|
||||||
|
},
|
||||||
|
"dem-color-relief": {
|
||||||
|
"type": "raster-dem",
|
||||||
|
"tiles": [
|
||||||
|
"local://tiles/{z}-{x}-{y}.terrain.png"
|
||||||
|
],
|
||||||
|
"maxzoom": 15,
|
||||||
|
"tileSize": 512
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"layers": [
|
||||||
|
{
|
||||||
|
"id": "background",
|
||||||
|
"type": "background",
|
||||||
|
"paint": {
|
||||||
|
"background-color": "white"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "color-relief",
|
||||||
|
"type": "color-relief",
|
||||||
|
"source": "dem-color-relief",
|
||||||
|
"paint": {
|
||||||
|
"color-relief-opacity": 1,
|
||||||
|
"color-relief-color": [
|
||||||
|
"interpolate",
|
||||||
|
["linear"],
|
||||||
|
["elevation"],
|
||||||
|
0, "#006600",
|
||||||
|
500, "#00FF00",
|
||||||
|
1000, "#FFFF00",
|
||||||
|
2000, "#FF8800",
|
||||||
|
3000, "#FF0000",
|
||||||
|
5000, "#FFFFFF"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "hillshade",
|
||||||
|
"type": "hillshade",
|
||||||
|
"source": "dem-hillshade",
|
||||||
|
"paint": {
|
||||||
|
"hillshade-method": "standard"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 8.2 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 99 KiB |
@@ -0,0 +1,39 @@
|
|||||||
|
{
|
||||||
|
"version": 8,
|
||||||
|
"metadata": {
|
||||||
|
"test": {
|
||||||
|
"height": 256,
|
||||||
|
"width": 256
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"center": [-113.26903, 35.9654],
|
||||||
|
"zoom": 11,
|
||||||
|
"sources": {
|
||||||
|
"source": {
|
||||||
|
"type": "raster-dem",
|
||||||
|
"tiles": [
|
||||||
|
"local://tiles/{z}-{x}-{y}.terrain.png"
|
||||||
|
],
|
||||||
|
"maxzoom": 15,
|
||||||
|
"tileSize": 256
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"layers": [
|
||||||
|
{
|
||||||
|
"id": "background",
|
||||||
|
"type": "background",
|
||||||
|
"paint": {
|
||||||
|
"background-color": "gray"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "hillshade",
|
||||||
|
"type": "hillshade",
|
||||||
|
"source": "source",
|
||||||
|
"paint": {
|
||||||
|
"hillshade-method": "basic",
|
||||||
|
"hillshade-illumination-altitude": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 162 KiB |
@@ -0,0 +1,39 @@
|
|||||||
|
{
|
||||||
|
"version": 8,
|
||||||
|
"metadata": {
|
||||||
|
"test": {
|
||||||
|
"height": 256,
|
||||||
|
"width": 256
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"center": [-113.26903, 35.9654],
|
||||||
|
"zoom": 11,
|
||||||
|
"sources": {
|
||||||
|
"source": {
|
||||||
|
"type": "raster-dem",
|
||||||
|
"tiles": [
|
||||||
|
"local://tiles/{z}-{x}-{y}.terrain.png"
|
||||||
|
],
|
||||||
|
"maxzoom": 15,
|
||||||
|
"tileSize": 256
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"layers": [
|
||||||
|
{
|
||||||
|
"id": "background",
|
||||||
|
"type": "background",
|
||||||
|
"paint": {
|
||||||
|
"background-color": "gray"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "hillshade",
|
||||||
|
"type": "hillshade",
|
||||||
|
"source": "source",
|
||||||
|
"paint": {
|
||||||
|
"hillshade-method": "basic",
|
||||||
|
"hillshade-illumination-altitude": 90
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 139 KiB |
@@ -0,0 +1,39 @@
|
|||||||
|
{
|
||||||
|
"version": 8,
|
||||||
|
"metadata": {
|
||||||
|
"test": {
|
||||||
|
"height": 256,
|
||||||
|
"width": 256
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"center": [-113.26903, 35.9654],
|
||||||
|
"zoom": 11,
|
||||||
|
"sources": {
|
||||||
|
"source": {
|
||||||
|
"type": "raster-dem",
|
||||||
|
"tiles": [
|
||||||
|
"local://tiles/{z}-{x}-{y}.terrain.png"
|
||||||
|
],
|
||||||
|
"maxzoom": 15,
|
||||||
|
"tileSize": 256
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"layers": [
|
||||||
|
{
|
||||||
|
"id": "background",
|
||||||
|
"type": "background",
|
||||||
|
"paint": {
|
||||||
|
"background-color": "gray"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "hillshade",
|
||||||
|
"type": "hillshade",
|
||||||
|
"source": "source",
|
||||||
|
"paint": {
|
||||||
|
"hillshade-method": "combined",
|
||||||
|
"hillshade-illumination-altitude": 60
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 5.5 KiB |
@@ -0,0 +1,39 @@
|
|||||||
|
{
|
||||||
|
"version": 8,
|
||||||
|
"metadata": {
|
||||||
|
"test": {
|
||||||
|
"height": 256,
|
||||||
|
"width": 256,
|
||||||
|
"description": "This test verifies hillshade rendering with basic method at low zoom levels (zoom 1) where exaggeration scaling is applied"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"center": [0, 45],
|
||||||
|
"zoom": 1,
|
||||||
|
"sources": {
|
||||||
|
"source": {
|
||||||
|
"type": "raster-dem",
|
||||||
|
"tiles": [
|
||||||
|
"local://tiles/{z}-{x}-{y}.terrain.png"
|
||||||
|
],
|
||||||
|
"maxzoom": 15,
|
||||||
|
"tileSize": 512
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"layers": [
|
||||||
|
{
|
||||||
|
"id": "background",
|
||||||
|
"type": "background",
|
||||||
|
"paint": {
|
||||||
|
"background-color": "white"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "hillshade",
|
||||||
|
"type": "hillshade",
|
||||||
|
"source": "source",
|
||||||
|
"paint": {
|
||||||
|
"hillshade-method": "basic"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 26 KiB |
@@ -0,0 +1,39 @@
|
|||||||
|
{
|
||||||
|
"version": 8,
|
||||||
|
"metadata": {
|
||||||
|
"test": {
|
||||||
|
"height": 256,
|
||||||
|
"width": 256,
|
||||||
|
"description": "This test verifies hillshade rendering with combined method at low zoom levels (zoom 1) where exaggeration scaling is applied"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"center": [0, 45],
|
||||||
|
"zoom": 1,
|
||||||
|
"sources": {
|
||||||
|
"source": {
|
||||||
|
"type": "raster-dem",
|
||||||
|
"tiles": [
|
||||||
|
"local://tiles/{z}-{x}-{y}.terrain.png"
|
||||||
|
],
|
||||||
|
"maxzoom": 15,
|
||||||
|
"tileSize": 512
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"layers": [
|
||||||
|
{
|
||||||
|
"id": "background",
|
||||||
|
"type": "background",
|
||||||
|
"paint": {
|
||||||
|
"background-color": "white"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "hillshade",
|
||||||
|
"type": "hillshade",
|
||||||
|
"source": "source",
|
||||||
|
"paint": {
|
||||||
|
"hillshade-method": "combined"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 32 KiB |
@@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"version": 8,
|
||||||
|
"metadata": {
|
||||||
|
"test": {
|
||||||
|
"height": 256,
|
||||||
|
"width": 256,
|
||||||
|
"description": "This test verifies hillshade rendering at low zoom levels (zoom 1) where exaggeration scaling is applied to make hillshading more visible"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"center": [0, 45],
|
||||||
|
"zoom": 1,
|
||||||
|
"sources": {
|
||||||
|
"source": {
|
||||||
|
"type": "raster-dem",
|
||||||
|
"tiles": [
|
||||||
|
"local://tiles/{z}-{x}-{y}.terrain.png"
|
||||||
|
],
|
||||||
|
"maxzoom": 15,
|
||||||
|
"tileSize": 512
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"layers": [
|
||||||
|
{
|
||||||
|
"id": "background",
|
||||||
|
"type": "background",
|
||||||
|
"paint": {
|
||||||
|
"background-color": "white"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "hillshade",
|
||||||
|
"type": "hillshade",
|
||||||
|
"source": "source"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 31 KiB |
@@ -0,0 +1,39 @@
|
|||||||
|
{
|
||||||
|
"version": 8,
|
||||||
|
"metadata": {
|
||||||
|
"test": {
|
||||||
|
"height": 256,
|
||||||
|
"width": 256,
|
||||||
|
"description": "This test verifies hillshade rendering with igor method at low zoom levels (zoom 1) where exaggeration scaling is applied"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"center": [0, 45],
|
||||||
|
"zoom": 1,
|
||||||
|
"sources": {
|
||||||
|
"source": {
|
||||||
|
"type": "raster-dem",
|
||||||
|
"tiles": [
|
||||||
|
"local://tiles/{z}-{x}-{y}.terrain.png"
|
||||||
|
],
|
||||||
|
"maxzoom": 15,
|
||||||
|
"tileSize": 512
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"layers": [
|
||||||
|
{
|
||||||
|
"id": "background",
|
||||||
|
"type": "background",
|
||||||
|
"paint": {
|
||||||
|
"background-color": "white"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "hillshade",
|
||||||
|
"type": "hillshade",
|
||||||
|
"source": "source",
|
||||||
|
"paint": {
|
||||||
|
"hillshade-method": "igor"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 50 KiB |
@@ -0,0 +1,42 @@
|
|||||||
|
{
|
||||||
|
"version": 8,
|
||||||
|
"metadata": {
|
||||||
|
"test": {
|
||||||
|
"height": 256,
|
||||||
|
"width": 256,
|
||||||
|
"description": "This test verifies hillshade rendering with multidirectional method at low zoom levels (zoom 1) where exaggeration scaling is applied"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"center": [0, 45],
|
||||||
|
"zoom": 1,
|
||||||
|
"sources": {
|
||||||
|
"source": {
|
||||||
|
"type": "raster-dem",
|
||||||
|
"tiles": [
|
||||||
|
"local://tiles/{z}-{x}-{y}.terrain.png"
|
||||||
|
],
|
||||||
|
"maxzoom": 15,
|
||||||
|
"tileSize": 512
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"layers": [
|
||||||
|
{
|
||||||
|
"id": "background",
|
||||||
|
"type": "background",
|
||||||
|
"paint": {
|
||||||
|
"background-color": "white"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "hillshade",
|
||||||
|
"type": "hillshade",
|
||||||
|
"source": "source",
|
||||||
|
"paint": {
|
||||||
|
"hillshade-method": "multidirectional",
|
||||||
|
"hillshade-highlight-color": ["#FF4000", "#FFFF00", "#40ff00", "#00FF80"],
|
||||||
|
"hillshade-shadow-color": ["#00bfff", "#0000ff", "#bf00ff", "#FF0080"],
|
||||||
|
"hillshade-illumination-direction": [270, 315, 0, 45]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 32 KiB |
@@ -0,0 +1,39 @@
|
|||||||
|
{
|
||||||
|
"version": 8,
|
||||||
|
"metadata": {
|
||||||
|
"test": {
|
||||||
|
"height": 256,
|
||||||
|
"width": 256,
|
||||||
|
"description": "This test verifies hillshade rendering with standard method at low zoom levels (zoom 1) where exaggeration scaling is applied"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"center": [0, 45],
|
||||||
|
"zoom": 1,
|
||||||
|
"sources": {
|
||||||
|
"source": {
|
||||||
|
"type": "raster-dem",
|
||||||
|
"tiles": [
|
||||||
|
"local://tiles/{z}-{x}-{y}.terrain.png"
|
||||||
|
],
|
||||||
|
"maxzoom": 15,
|
||||||
|
"tileSize": 512
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"layers": [
|
||||||
|
{
|
||||||
|
"id": "background",
|
||||||
|
"type": "background",
|
||||||
|
"paint": {
|
||||||
|
"background-color": "white"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "hillshade",
|
||||||
|
"type": "hillshade",
|
||||||
|
"source": "source",
|
||||||
|
"paint": {
|
||||||
|
"hillshade-method": "standard"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 81 KiB |
@@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"version": 8,
|
||||||
|
"metadata": {
|
||||||
|
"test": {
|
||||||
|
"height": 256,
|
||||||
|
"width": 256,
|
||||||
|
"description": "This test verifies that setting a lower maxzoom on the raster-dem source produces the same output as a higher maxzoom (hillshade-accent-color/default) when the map zoom level is lower than the maxzoom (i.e., maxzoom does not alter rendering at lower zooms)"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"center": [-113.26903, 35.9654],
|
||||||
|
"zoom": 11,
|
||||||
|
"sources": {
|
||||||
|
"source": {
|
||||||
|
"type": "raster-dem",
|
||||||
|
"tiles": [
|
||||||
|
"local://tiles/{z}-{x}-{y}.terrain.png"
|
||||||
|
],
|
||||||
|
"maxzoom": 12,
|
||||||
|
"tileSize": 256
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"layers": [
|
||||||
|
{
|
||||||
|
"id": "background",
|
||||||
|
"type": "background",
|
||||||
|
"paint": {
|
||||||
|
"background-color": "white"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "hillshade",
|
||||||
|
"type": "hillshade",
|
||||||
|
"source": "source"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 53 KiB |
@@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"version": 8,
|
||||||
|
"metadata": {
|
||||||
|
"test": {
|
||||||
|
"height": 256,
|
||||||
|
"width": 256,
|
||||||
|
"description": "This test verifies that setting a maximum zoom on the raster-dem source lower than the layer results in overzooming the source."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"center": [-113.26903, 35.9654],
|
||||||
|
"zoom": 13,
|
||||||
|
"sources": {
|
||||||
|
"source": {
|
||||||
|
"type": "raster-dem",
|
||||||
|
"tiles": [
|
||||||
|
"local://tiles/{z}-{x}-{y}.terrain.png"
|
||||||
|
],
|
||||||
|
"maxzoom": 12,
|
||||||
|
"tileSize": 256
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"layers": [
|
||||||
|
{
|
||||||
|
"id": "background",
|
||||||
|
"type": "background",
|
||||||
|
"paint": {
|
||||||
|
"background-color": "white"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "hillshade",
|
||||||
|
"type": "hillshade",
|
||||||
|
"source": "source"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 169 KiB |
@@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"version": 8,
|
||||||
|
"metadata": {
|
||||||
|
"test": {
|
||||||
|
"height": 256,
|
||||||
|
"width": 256
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"center": [-113.26903, 35.9654],
|
||||||
|
"zoom": 11,
|
||||||
|
"sources": {
|
||||||
|
"source": {
|
||||||
|
"type": "raster-dem",
|
||||||
|
"tiles": [
|
||||||
|
"local://tiles/{z}-{x}-{y}.terrain.png"
|
||||||
|
],
|
||||||
|
"maxzoom": 15,
|
||||||
|
"tileSize": 256
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"layers": [
|
||||||
|
{
|
||||||
|
"id": "background",
|
||||||
|
"type": "background",
|
||||||
|
"paint": {
|
||||||
|
"background-color": "gray"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "hillshade",
|
||||||
|
"type": "hillshade",
|
||||||
|
"source": "source",
|
||||||
|
"paint": {
|
||||||
|
"hillshade-method": "basic"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 144 KiB |
@@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"version": 8,
|
||||||
|
"metadata": {
|
||||||
|
"test": {
|
||||||
|
"height": 256,
|
||||||
|
"width": 256
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"center": [-113.26903, 35.9654],
|
||||||
|
"zoom": 11,
|
||||||
|
"sources": {
|
||||||
|
"source": {
|
||||||
|
"type": "raster-dem",
|
||||||
|
"tiles": [
|
||||||
|
"local://tiles/{z}-{x}-{y}.terrain.png"
|
||||||
|
],
|
||||||
|
"maxzoom": 15,
|
||||||
|
"tileSize": 256
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"layers": [
|
||||||
|
{
|
||||||
|
"id": "background",
|
||||||
|
"type": "background",
|
||||||
|
"paint": {
|
||||||
|
"background-color": "gray"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "hillshade",
|
||||||
|
"type": "hillshade",
|
||||||
|
"source": "source",
|
||||||
|
"paint": {
|
||||||
|
"hillshade-method": "combined"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 142 KiB |
@@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"version": 8,
|
||||||
|
"metadata": {
|
||||||
|
"test": {
|
||||||
|
"height": 256,
|
||||||
|
"width": 256
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"center": [-113.26903, 35.9654],
|
||||||
|
"zoom": 11,
|
||||||
|
"sources": {
|
||||||
|
"source": {
|
||||||
|
"type": "raster-dem",
|
||||||
|
"tiles": [
|
||||||
|
"local://tiles/{z}-{x}-{y}.terrain.png"
|
||||||
|
],
|
||||||
|
"maxzoom": 15,
|
||||||
|
"tileSize": 256
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"layers": [
|
||||||
|
{
|
||||||
|
"id": "background",
|
||||||
|
"type": "background",
|
||||||
|
"paint": {
|
||||||
|
"background-color": "gray"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "hillshade",
|
||||||
|
"type": "hillshade",
|
||||||
|
"source": "source",
|
||||||
|
"paint": {
|
||||||
|
"hillshade-method": "igor"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 158 KiB |
@@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"version": 8,
|
||||||
|
"metadata": {
|
||||||
|
"test": {
|
||||||
|
"height": 256,
|
||||||
|
"width": 256
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"center": [-113.26903, 35.9654],
|
||||||
|
"zoom": 11,
|
||||||
|
"sources": {
|
||||||
|
"source": {
|
||||||
|
"type": "raster-dem",
|
||||||
|
"tiles": [
|
||||||
|
"local://tiles/{z}-{x}-{y}.terrain.png"
|
||||||
|
],
|
||||||
|
"maxzoom": 15,
|
||||||
|
"tileSize": 256
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"layers": [
|
||||||
|
{
|
||||||
|
"id": "background",
|
||||||
|
"type": "background",
|
||||||
|
"paint": {
|
||||||
|
"background-color": "gray"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "hillshade",
|
||||||
|
"type": "hillshade",
|
||||||
|
"source": "source",
|
||||||
|
"paint": {
|
||||||
|
"hillshade-method": "multidirectional",
|
||||||
|
"hillshade-highlight-color": ["#FF4000", "#FFFF00", "#40ff00", "#00FF80"],
|
||||||
|
"hillshade-shadow-color": ["#00bfff", "#0000ff", "#bf00ff", "#FF0080"],
|
||||||
|
"hillshade-illumination-direction": [270,315,0,45]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 84 KiB |
@@ -0,0 +1,74 @@
|
|||||||
|
{
|
||||||
|
"version": 8,
|
||||||
|
"metadata": {
|
||||||
|
"test": {
|
||||||
|
"width": 256,
|
||||||
|
"height": 256,
|
||||||
|
"description": "This test verifies that changing hillshade array properties one at a time (causing temporary length mismatch) does not cause crashes or rendering artifacts. Starts with 4 lights, changes direction to 1, then updates colors to 1. Using a dramatic 4->1 change makes any issues more visible (per HarelM's suggestion).",
|
||||||
|
"operations": [
|
||||||
|
[
|
||||||
|
"setPaintProperty",
|
||||||
|
"hillshade",
|
||||||
|
"hillshade-illumination-direction",
|
||||||
|
315
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"wait"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"setPaintProperty",
|
||||||
|
"hillshade",
|
||||||
|
"hillshade-highlight-color",
|
||||||
|
"#FFFFFF"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"wait"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"setPaintProperty",
|
||||||
|
"hillshade",
|
||||||
|
"hillshade-shadow-color",
|
||||||
|
"#000000"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"wait"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"transition": {
|
||||||
|
"duration": 0
|
||||||
|
},
|
||||||
|
"center": [-113.26903, 35.9654],
|
||||||
|
"zoom": 11,
|
||||||
|
"sources": {
|
||||||
|
"source": {
|
||||||
|
"type": "raster-dem",
|
||||||
|
"tiles": [
|
||||||
|
"local://tiles/{z}-{x}-{y}.terrain.png"
|
||||||
|
],
|
||||||
|
"maxzoom": 15,
|
||||||
|
"tileSize": 256
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"layers": [
|
||||||
|
{
|
||||||
|
"id": "background",
|
||||||
|
"type": "background",
|
||||||
|
"paint": {
|
||||||
|
"background-color": "gray"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "hillshade",
|
||||||
|
"type": "hillshade",
|
||||||
|
"source": "source",
|
||||||
|
"paint": {
|
||||||
|
"hillshade-method": "multidirectional",
|
||||||
|
"hillshade-highlight-color": ["#FF4000", "#FFFF00", "#40ff00", "#00FF80"],
|
||||||
|
"hillshade-shadow-color": ["#00bfff", "#0000ff", "#bf00ff", "#FF0080"],
|
||||||
|
"hillshade-illumination-direction": [270, 315, 0, 45]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
BIN
metrics/integration/tiles/0-0-0.terrain.png
Normal file
|
After Width: | Height: | Size: 195 KiB |
BIN
metrics/integration/tiles/1-0-0.terrain.png
Normal file
|
After Width: | Height: | Size: 172 KiB |
BIN
metrics/integration/tiles/1-1-0.terrain.png
Normal file
|
After Width: | Height: | Size: 205 KiB |
BIN
metrics/integration/tiles/2-1-0.terrain.png
Normal file
|
After Width: | Height: | Size: 216 KiB |
BIN
metrics/integration/tiles/2-1-1.terrain.png
Normal file
|
After Width: | Height: | Size: 134 KiB |
BIN
metrics/integration/tiles/2-2-0.terrain.png
Normal file
|
After Width: | Height: | Size: 68 KiB |
BIN
metrics/integration/tiles/2-2-1.terrain.png
Normal file
|
After Width: | Height: | Size: 329 KiB |
2500
package-lock.json
generated
@@ -8,7 +8,7 @@
|
|||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.11.1",
|
"@actions/core": "^1.11.1",
|
||||||
"@maplibre/maplibre-gl-style-spec": "^20.3.1",
|
"@maplibre/maplibre-gl-style-spec": "^24.3.1",
|
||||||
"minimatch": "^10.2.2",
|
"minimatch": "^10.2.2",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"simple-git": "^3.25.0"
|
"simple-git": "^3.25.0"
|
||||||
|
|||||||
@@ -147,6 +147,8 @@ add_library(maplibre SHARED
|
|||||||
${PROJECT_SOURCE_DIR}/style/layers/background_layer.hpp
|
${PROJECT_SOURCE_DIR}/style/layers/background_layer.hpp
|
||||||
${PROJECT_SOURCE_DIR}/style/layers/circle_layer.cpp
|
${PROJECT_SOURCE_DIR}/style/layers/circle_layer.cpp
|
||||||
${PROJECT_SOURCE_DIR}/style/layers/circle_layer.hpp
|
${PROJECT_SOURCE_DIR}/style/layers/circle_layer.hpp
|
||||||
|
${PROJECT_SOURCE_DIR}/style/layers/color_relief_layer.cpp
|
||||||
|
${PROJECT_SOURCE_DIR}/style/layers/color_relief_layer.hpp
|
||||||
${PROJECT_SOURCE_DIR}/style/layers/custom_layer.cpp
|
${PROJECT_SOURCE_DIR}/style/layers/custom_layer.cpp
|
||||||
${PROJECT_SOURCE_DIR}/style/layers/custom_layer.hpp
|
${PROJECT_SOURCE_DIR}/style/layers/custom_layer.hpp
|
||||||
${PROJECT_SOURCE_DIR}/style/layers/fill_extrusion_layer.cpp
|
${PROJECT_SOURCE_DIR}/style/layers/fill_extrusion_layer.cpp
|
||||||
|
|||||||
@@ -101,6 +101,17 @@ Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, std::vect
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, std::vector<Color>>::operator()(
|
||||||
|
jni::JNIEnv& env, const std::vector<Color>& value) const {
|
||||||
|
auto result = jni::Array<jni::String>::New(env, value.size());
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < value.size(); i++) {
|
||||||
|
result.Set(env, i, jni::Make<jni::String>(env, value.at(i).stringify()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, style::expression::Image>::operator()(
|
Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, style::expression::Image>::operator()(
|
||||||
jni::JNIEnv& env, const style::expression::Image& value) const {
|
jni::JNIEnv& env, const style::expression::Image& value) const {
|
||||||
return jni::Make<jni::String>(env, value.id());
|
return jni::Make<jni::String>(env, value.id());
|
||||||
|
|||||||
@@ -111,6 +111,11 @@ struct Converter<jni::Local<jni::Object<>>, std::vector<double>> {
|
|||||||
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const std::vector<double>& value) const;
|
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const std::vector<double>& value) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct Converter<jni::Local<jni::Object<>>, std::vector<Color>> {
|
||||||
|
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const std::vector<Color>& value) const;
|
||||||
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
struct Converter<jni::Local<jni::Object<>>, T, typename std::enable_if_t<std::is_enum<T>::value>> {
|
struct Converter<jni::Local<jni::Object<>>, T, typename std::enable_if_t<std::is_enum<T>::value>> {
|
||||||
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const T& value) const {
|
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const T& value) const {
|
||||||
|
|||||||
@@ -0,0 +1,130 @@
|
|||||||
|
// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
|
||||||
|
|
||||||
|
#include "color_relief_layer.hpp"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "../conversion/property_value.hpp"
|
||||||
|
#include "../conversion/transition_options.hpp"
|
||||||
|
|
||||||
|
#include <mbgl/style/layer_impl.hpp>
|
||||||
|
|
||||||
|
namespace mbgl {
|
||||||
|
namespace android {
|
||||||
|
|
||||||
|
inline mbgl::style::ColorReliefLayer& toColorReliefLayer(mbgl::style::Layer& layer) {
|
||||||
|
return static_cast<mbgl::style::ColorReliefLayer&>(layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an owning peer object (for layers not attached to the map) from the JVM side
|
||||||
|
*/
|
||||||
|
ColorReliefLayer::ColorReliefLayer(jni::JNIEnv& env, jni::String& layerId, jni::String& sourceId)
|
||||||
|
: Layer(std::make_unique<mbgl::style::ColorReliefLayer>(jni::Make<std::string>(env, layerId),
|
||||||
|
jni::Make<std::string>(env, sourceId))) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a non-owning peer object (for layers currently attached to the map)
|
||||||
|
*/
|
||||||
|
ColorReliefLayer::ColorReliefLayer(mbgl::style::ColorReliefLayer& coreLayer)
|
||||||
|
: Layer(coreLayer) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an owning peer object (for layers not attached to the map)
|
||||||
|
*/
|
||||||
|
ColorReliefLayer::ColorReliefLayer(std::unique_ptr<mbgl::style::ColorReliefLayer> coreLayer)
|
||||||
|
: Layer(std::move(coreLayer)) {}
|
||||||
|
|
||||||
|
ColorReliefLayer::~ColorReliefLayer() = default;
|
||||||
|
|
||||||
|
// Property getters
|
||||||
|
|
||||||
|
jni::Local<jni::Object<>> ColorReliefLayer::getColorReliefOpacity(jni::JNIEnv& env) {
|
||||||
|
using namespace mbgl::android::conversion;
|
||||||
|
auto layer = layerPtr.get();
|
||||||
|
if (!layer) {
|
||||||
|
return std::move(
|
||||||
|
*convert<jni::Local<jni::Object<>>>(env, style::ColorReliefLayer::getDefaultColorReliefOpacity()));
|
||||||
|
}
|
||||||
|
return std::move(*convert<jni::Local<jni::Object<>>>(env, toColorReliefLayer(*layer).getColorReliefOpacity()));
|
||||||
|
}
|
||||||
|
|
||||||
|
jni::Local<jni::Object<TransitionOptions>> ColorReliefLayer::getColorReliefOpacityTransition(jni::JNIEnv& env) {
|
||||||
|
using namespace mbgl::android::conversion;
|
||||||
|
auto layer = layerPtr.get();
|
||||||
|
if (!layer) {
|
||||||
|
return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, mbgl::style::TransitionOptions()));
|
||||||
|
}
|
||||||
|
mbgl::style::TransitionOptions options = toColorReliefLayer(*layer).getColorReliefOpacityTransition();
|
||||||
|
return std::move(*convert<jni::Local<jni::Object<TransitionOptions>>>(env, options));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ColorReliefLayer::setColorReliefOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay) {
|
||||||
|
auto layer = layerPtr.get();
|
||||||
|
if (!layer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mbgl::style::TransitionOptions options;
|
||||||
|
options.duration.emplace(mbgl::Milliseconds(duration));
|
||||||
|
options.delay.emplace(mbgl::Milliseconds(delay));
|
||||||
|
toColorReliefLayer(*layer).setColorReliefOpacityTransition(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
jni::Local<jni::Object<>> ColorReliefLayer::getColorReliefColor(jni::JNIEnv& env) {
|
||||||
|
using namespace mbgl::android::conversion;
|
||||||
|
auto layer = layerPtr.get();
|
||||||
|
if (!layer) {
|
||||||
|
return std::move(
|
||||||
|
*convert<jni::Local<jni::Object<>>>(env, style::ColorReliefLayer::getDefaultColorReliefColor()));
|
||||||
|
}
|
||||||
|
return std::move(*convert<jni::Local<jni::Object<>>>(env, toColorReliefLayer(*layer).getColorReliefColor()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ColorReliefJavaLayerPeerFactory
|
||||||
|
|
||||||
|
ColorReliefJavaLayerPeerFactory::~ColorReliefJavaLayerPeerFactory() = default;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
jni::Local<jni::Object<Layer>> createJavaPeer(jni::JNIEnv& env, Layer* layer) {
|
||||||
|
static auto& javaClass = jni::Class<ColorReliefLayer>::Singleton(env);
|
||||||
|
static auto constructor = javaClass.GetConstructor<jni::jlong>(env);
|
||||||
|
return javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(layer));
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
jni::Local<jni::Object<Layer>> ColorReliefJavaLayerPeerFactory::createJavaLayerPeer(jni::JNIEnv& env,
|
||||||
|
mbgl::style::Layer& layer) {
|
||||||
|
assert(layer.baseImpl->getTypeInfo() == getTypeInfo());
|
||||||
|
return createJavaPeer(env, new ColorReliefLayer(toColorReliefLayer(layer)));
|
||||||
|
}
|
||||||
|
|
||||||
|
jni::Local<jni::Object<Layer>> ColorReliefJavaLayerPeerFactory::createJavaLayerPeer(
|
||||||
|
jni::JNIEnv& env, std::unique_ptr<mbgl::style::Layer> layer) {
|
||||||
|
assert(layer->baseImpl->getTypeInfo() == getTypeInfo());
|
||||||
|
return createJavaPeer(env,
|
||||||
|
new ColorReliefLayer(std::unique_ptr<mbgl::style::ColorReliefLayer>(
|
||||||
|
static_cast<mbgl::style::ColorReliefLayer*>(layer.release()))));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ColorReliefJavaLayerPeerFactory::registerNative(jni::JNIEnv& env) {
|
||||||
|
// Lookup the class
|
||||||
|
static auto& javaClass = jni::Class<ColorReliefLayer>::Singleton(env);
|
||||||
|
|
||||||
|
#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
|
||||||
|
|
||||||
|
// Register the peer
|
||||||
|
jni::RegisterNativePeer<ColorReliefLayer>(
|
||||||
|
env,
|
||||||
|
javaClass,
|
||||||
|
"nativePtr",
|
||||||
|
jni::MakePeer<ColorReliefLayer, jni::String&, jni::String&>,
|
||||||
|
"initialize",
|
||||||
|
"finalize",
|
||||||
|
METHOD(&ColorReliefLayer::getColorReliefOpacityTransition, "nativeGetColorReliefOpacityTransition"),
|
||||||
|
METHOD(&ColorReliefLayer::setColorReliefOpacityTransition, "nativeSetColorReliefOpacityTransition"),
|
||||||
|
METHOD(&ColorReliefLayer::getColorReliefOpacity, "nativeGetColorReliefOpacity"),
|
||||||
|
METHOD(&ColorReliefLayer::getColorReliefColor, "nativeGetColorReliefColor"));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace android
|
||||||
|
} // namespace mbgl
|
||||||