-
-
Notifications
You must be signed in to change notification settings - Fork 932
Hypsometric Tint from terrain-RGB tiles #5913
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 54 commits
Commits
Show all changes
60 commits
Select commit
Hold shift + click to select a range
e8a5bba
Basic color relief layer working, with a hardcoded colormap
NathanMOlson 57b9b1b
use texture for color-relief colormap
NathanMOlson b729d3e
add color relief benchmark
NathanMOlson 3fe4707
fix border rendering error and ugliness
NathanMOlson bf5e974
do lookup table in shader
NathanMOlson 002cc7b
Merge branch 'main' into hypsometric2
NathanMOlson df7af32
Merge branch 'main' into hypsometric2
NathanMOlson 23ff672
fix merge error
NathanMOlson f0c048d
fix initialization of _featureFilter with stytle-spec update (global …
NathanMOlson 700c675
remove dead code (pulling colormap from texture)
NathanMOlson 98ac2b9
remove more dead code related to rendering color relief from texture
NathanMOlson b83cf42
add unit tests for ColorReliefStyleLayer
NathanMOlson 8b1bc49
add render tests and global opacity handling
NathanMOlson 06bedd4
Add a color relief example
NathanMOlson c15de0a
add render test with color relief and hillshade
NathanMOlson 57f03a3
Merge branch 'main' into hypsometric2
NathanMOlson ab7edd3
fix lint
NathanMOlson f3acf20
fix benchmark and update changelog
NathanMOlson 77d2c1e
Merge branch 'main' into hypsometric2
NathanMOlson 8883d0d
updat to use latest version of style spec
NathanMOlson 5f9dd70
add "hypsometric" to spelling list
NathanMOlson d9c3cfd
update expectedBytes
NathanMOlson 82d8fe9
improve function name
NathanMOlson bb11461
remove "as any", simplify colorramp creation, add comment
NathanMOlson e22d1b6
remove colorramp requirement length = 2^N + 1
NathanMOlson b085c1d
Remap the color-relief color ramp if the length exceeds the WebGL cap…
NathanMOlson 2774b1f
add unit test for getColorRamp()
NathanMOlson b98e027
handle empty and single-color color ramps
NathanMOlson 0a629b4
account for presence of other uniforms in calculation of maxLength fo…
NathanMOlson 9512079
return arrays in _updateColorRamp()
NathanMOlson 3740a55
sinplify getColorRamp()
NathanMOlson ae5cc80
add (messy) type to createColorReliefLayerSpec() argument
NathanMOlson a861180
fix colorRampLength
NathanMOlson 8bcd98f
add color relief layer benchmarks
NathanMOlson 7db8b75
use defined type
NathanMOlson f889b77
add DEMData::pack() function and unit tests
NathanMOlson a2dbc6d
version of color relief that uses textures instead of uniforms for co…
NathanMOlson d9be1a8
get the right size limit for color ramp
NathanMOlson 6840b70
update expectedBytes
NathanMOlson f59ead7
fix off-by-one error
NathanMOlson 0f61df7
use texture lookup instead of shader interpolation
NathanMOlson 0b96139
function nameing and comment formating
NathanMOlson ca69c39
defer color ramp creation until getColorRamp
NathanMOlson 8e05248
Merge branch 'hypsometric2' into hypsometric3
NathanMOlson 71b0e5a
update unit tests
NathanMOlson ebd061d
Merge branch 'hypsometric2' into hypsometric3
NathanMOlson a583485
remove unneeded shader #define
NathanMOlson 60c1bf4
fix colorRampLength calculation
NathanMOlson dd43722
Merge branch 'main' into hypsometric2
NathanMOlson 8a3513b
Merge branch 'hypsometric2' into hypsometric3
NathanMOlson b200ba1
use first available textures
NathanMOlson df1cf4c
Merge branch 'main' into hypsometric3
NathanMOlson aa7b450
fix expectedBytes
NathanMOlson 1677f63
enable color ramp to be dynamically changes using map.setPaintProperty()
NathanMOlson 560163a
reduce indentation
NathanMOlson c562d13
remove unneeded member variable colorRamp and combine _createColorRam…
NathanMOlson d9d8738
fix build
NathanMOlson a71d5d4
add RGBAImage::setPixel()
NathanMOlson 3c1cfaf
fix lint
NathanMOlson c78c931
Merge branch 'main' into hypsometric3
HarelM File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -62,6 +62,7 @@ | |
| "highp", | ||
| "Hira", | ||
| "Hoare", | ||
| "hypsometric", | ||
| "ifdef", | ||
| "ifdefs", | ||
| "iframes", | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,107 @@ | ||
| import {Texture} from './texture'; | ||
| import type {StencilMode} from '../gl/stencil_mode'; | ||
| import {DepthMode} from '../gl/depth_mode'; | ||
| import {CullFaceMode} from '../gl/cull_face_mode'; | ||
| import {type ColorMode} from '../gl/color_mode'; | ||
| import { | ||
| colorReliefUniformValues | ||
| } from './program/color_relief_program'; | ||
|
|
||
| import type {Painter, RenderOptions} from './painter'; | ||
| import type {SourceCache} from '../source/source_cache'; | ||
| import type {ColorReliefStyleLayer} from '../style/style_layer/color_relief_style_layer'; | ||
| import type {OverscaledTileID} from '../source/tile_id'; | ||
|
|
||
| export function drawColorRelief(painter: Painter, sourceCache: SourceCache, layer: ColorReliefStyleLayer, tileIDs: Array<OverscaledTileID>, renderOptions: RenderOptions) { | ||
| if (painter.renderPass !== 'translucent') return; | ||
| if (!tileIDs.length) return; | ||
|
|
||
| const {isRenderingToTexture} = renderOptions; | ||
| const projection = painter.style.projection; | ||
| const useSubdivision = projection.useSubdivision; | ||
|
|
||
| const depthMode = painter.getDepthModeForSublayer(0, DepthMode.ReadOnly); | ||
| const colorMode = painter.colorModeForRenderPass(); | ||
|
|
||
| // Globe (or any projection with subdivision) needs two-pass rendering to avoid artifacts when rendering texture tiles. | ||
| // See comments in draw_raster.ts for more details. | ||
| if (useSubdivision) { | ||
| // Two-pass rendering | ||
| const [stencilBorderless, stencilBorders, coords] = painter.stencilConfigForOverlapTwoPass(tileIDs); | ||
| renderColorRelief(painter, sourceCache, layer, coords, stencilBorderless, depthMode, colorMode, false, isRenderingToTexture); // draw without borders | ||
| renderColorRelief(painter, sourceCache, layer, coords, stencilBorders, depthMode, colorMode, true, isRenderingToTexture); // draw with borders | ||
| } else { | ||
| // Simple rendering | ||
| const [stencil, coords] = painter.getStencilConfigForOverlapAndUpdateStencilID(tileIDs); | ||
| renderColorRelief(painter, sourceCache, layer, coords, stencil, depthMode, colorMode, false, isRenderingToTexture); | ||
| } | ||
| } | ||
|
|
||
| function renderColorRelief( | ||
| painter: Painter, | ||
| sourceCache: SourceCache, | ||
| layer: ColorReliefStyleLayer, | ||
| coords: Array<OverscaledTileID>, | ||
| stencilModes: {[_: number]: Readonly<StencilMode>}, | ||
| depthMode: Readonly<DepthMode>, | ||
| colorMode: Readonly<ColorMode>, | ||
| useBorder: boolean, | ||
| isRenderingToTexture: boolean | ||
| ) { | ||
| const projection = painter.style.projection; | ||
| const context = painter.context; | ||
| const transform = painter.transform; | ||
| const gl = context.gl; | ||
| const program = painter.useProgram('colorRelief'); | ||
| const align = !painter.options.moving; | ||
|
|
||
| let firstTile = true; | ||
|
|
||
| for (const coord of coords) { | ||
| const tile = sourceCache.getTile(coord); | ||
| const dem = tile.dem; | ||
| if(firstTile) { | ||
| const maxLength = gl.getParameter(gl.MAX_TEXTURE_SIZE); | ||
| const {elevationTexture, colorTexture} = layer.getColorRampTextures(context, maxLength, dem.getUnpackVector()); | ||
| context.activeTexture.set(gl.TEXTURE1); | ||
| elevationTexture.bind(gl.NEAREST, gl.CLAMP_TO_EDGE); | ||
| context.activeTexture.set(gl.TEXTURE4); | ||
| colorTexture.bind(gl.LINEAR, gl.CLAMP_TO_EDGE); | ||
| firstTile = false; | ||
| } | ||
|
|
||
| if (!dem || !dem.data) { | ||
| continue; | ||
| } | ||
|
|
||
| const textureStride = dem.stride; | ||
|
|
||
| const pixelData = dem.getPixels(); | ||
| context.activeTexture.set(gl.TEXTURE0); | ||
|
|
||
| context.pixelStoreUnpackPremultiplyAlpha.set(false); | ||
| tile.demTexture = tile.demTexture || painter.getTileTexture(textureStride); | ||
| if (tile.demTexture) { | ||
| const demTexture = tile.demTexture; | ||
| demTexture.update(pixelData, {premultiply: false}); | ||
| demTexture.bind(gl.LINEAR, gl.CLAMP_TO_EDGE); | ||
| } else { | ||
| tile.demTexture = new Texture(context, pixelData, gl.RGBA, {premultiply: false}); | ||
| tile.demTexture.bind(gl.LINEAR, gl.CLAMP_TO_EDGE); | ||
| } | ||
|
|
||
| const mesh = projection.getMeshFromTileID(context, coord.canonical, useBorder, true, 'raster'); | ||
|
|
||
| const terrainData = painter.style.map.terrain?.getTerrainData(coord); | ||
|
|
||
| const projectionData = transform.getProjectionData({ | ||
| overscaledTileID: coord, | ||
| aligned: align, | ||
| applyGlobeMatrix: !isRenderingToTexture, | ||
| applyTerrainMatrix: true | ||
| }); | ||
|
|
||
| program.draw(context, gl.TRIANGLES, depthMode, stencilModes[coord.overscaledZ], colorMode, CullFaceMode.backCCW, | ||
| colorReliefUniformValues(layer, tile.dem), terrainData, projectionData, layer.id, mesh.vertexBuffer, mesh.indexBuffer, mesh.segments); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| import { | ||
| Uniform1i, | ||
| Uniform1f, | ||
| Uniform2f, | ||
| Uniform4f | ||
| } from '../uniform_binding'; | ||
|
|
||
| import type {Context} from '../../gl/context'; | ||
| import type {UniformValues, UniformLocations} from '../uniform_binding'; | ||
| import type {ColorReliefStyleLayer} from '../../style/style_layer/color_relief_style_layer'; | ||
| import type {DEMData} from '../../data/dem_data'; | ||
|
|
||
| export type ColorReliefUniformsType = { | ||
| 'u_image': Uniform1i; | ||
| 'u_unpack': Uniform4f; | ||
| 'u_dimension': Uniform2f; | ||
| 'u_elevation_stops': Uniform1i; | ||
| 'u_color_stops': Uniform1i; | ||
| 'u_opacity': Uniform1f; | ||
| }; | ||
|
|
||
| const colorReliefUniforms = (context: Context, locations: UniformLocations): ColorReliefUniformsType => ({ | ||
| 'u_image': new Uniform1i(context, locations.u_image), | ||
| 'u_unpack': new Uniform4f(context, locations.u_unpack), | ||
| 'u_dimension': new Uniform2f(context, locations.u_dimension), | ||
| 'u_elevation_stops': new Uniform1i(context, locations.u_elevation_stops), | ||
| 'u_color_stops': new Uniform1i(context, locations.u_color_stops), | ||
| 'u_opacity': new Uniform1f(context, locations.u_opacity) | ||
| }); | ||
|
|
||
| const colorReliefUniformValues = ( | ||
| layer: ColorReliefStyleLayer, | ||
| dem: DEMData | ||
| ): UniformValues<ColorReliefUniformsType> => { | ||
|
|
||
| return { | ||
| 'u_image': 0, | ||
| 'u_unpack': dem.getUnpackVector(), | ||
| 'u_dimension': [dem.stride, dem.stride], | ||
| 'u_elevation_stops': 1, | ||
| 'u_color_stops': 4, | ||
| 'u_opacity': layer.paint.get('color-relief-opacity') | ||
| }; | ||
| }; | ||
|
|
||
| export { | ||
| colorReliefUniforms, | ||
| colorReliefUniformValues, | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| uniform sampler2D u_image; | ||
| uniform vec4 u_unpack; | ||
| uniform sampler2D u_elevation_stops; | ||
| uniform sampler2D u_color_stops; | ||
| uniform float u_opacity; | ||
|
|
||
| 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) { | ||
| // Convert encoded elevation value to meters | ||
| float x = (float(stop)+0.5)/float(textureSize(u_elevation_stops, 0)[0]); | ||
| vec4 data = texture(u_elevation_stops, vec2(x, 0)) * 255.0; | ||
| data.a = -1.0; | ||
| return dot(data, u_unpack); | ||
| } | ||
|
|
||
| void main() { | ||
| float el = getElevation(v_pos); | ||
|
|
||
| int num_elevation_stops = textureSize(u_elevation_stops, 0)[0]; | ||
|
|
||
| // Binary search | ||
| int r = (num_elevation_stops - 1); | ||
| int l = 0; | ||
| float el_l = getElevationStop(l); | ||
| float el_r = getElevationStop(r); | ||
| while(r - l > 1) | ||
| { | ||
| int m = (r + l) / 2; | ||
| float el_m = getElevationStop(m); | ||
| if(el < el_m) | ||
| { | ||
| r = m; | ||
| el_r = el_m; | ||
| } | ||
| else | ||
| { | ||
| l = m; | ||
| el_l = el_m; | ||
| } | ||
| } | ||
|
|
||
| float x = (float(l) + (el - el_l) / (el_r - el_l) + 0.5)/float(textureSize(u_color_stops, 0)[0]); | ||
| fragColor = u_opacity*texture(u_color_stops, vec2(x, 0)); | ||
|
|
||
| #ifdef OVERDRAW_INSPECTOR | ||
| fragColor = vec4(1.0); | ||
| #endif | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| uniform vec2 u_dimension; | ||
|
|
||
| in vec2 a_pos; | ||
|
|
||
| out vec2 v_pos; | ||
|
|
||
| void main() { | ||
| gl_Position = projectTile(a_pos, a_pos); | ||
| highp vec2 epsilon = 1.0 / u_dimension; | ||
| float scale = (u_dimension.x - 2.0) / u_dimension.x; | ||
| v_pos = (a_pos / 8192.0) * scale + epsilon; | ||
| // North pole | ||
| if (a_pos.y < -32767.5) { | ||
| v_pos.y = 0.0; | ||
| } | ||
| // South pole | ||
| if (a_pos.y > 32766.5) { | ||
| v_pos.y = 1.0; | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.