Skip to content
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

Prototype pixel snapping icons with GL_LINEAR #8738

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/data/bucket/symbol_bucket.js
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,6 @@ class SymbolBucket implements Bucket {
index: number;
sdfIcons: boolean;
iconsInText: boolean;
iconsNeedLinear: boolean;
bucketInstanceId: number;
justReloaded: boolean;
hasPattern: boolean;
Expand Down
30 changes: 10 additions & 20 deletions src/render/draw_symbol.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@ type SymbolTileRenderState = {
uniformValues: any,
atlasTexture: Texture,
atlasTextureIcon: Texture | null,
atlasInterpolation: any,
atlasInterpolationIcon: any,
isSDF: boolean,
hasHalo: boolean
}
Expand Down Expand Up @@ -257,35 +255,29 @@ function drawLayerSymbols(painter, sourceCache, layer, coords, isText, translate
const isSDF = isText || bucket.sdfIcons;

const sizeData = isText ? bucket.textSizeData : bucket.iconSizeData;
const transformed = pitchWithMap || tr.pitch !== 0;

if (!program) {
program = painter.useProgram(getSymbolProgramName(isSDF, isText, bucket), programConfiguration);
size = symbolSize.evaluateSizeForZoom(sizeData, tr.zoom);
}

let texSize: [number, number];
let texSizeIcon: [number, number] = [0, 0];
let atlasTexture;
let atlasInterpolation;
let texSizeIcon: [number, number] = [0, 0];
let atlasTextureIcon = null;
let atlasInterpolationIcon;

const isCrisp: boolean = (!pitchWithMap || !painter.transform.pitch) && !painter.options.rotating && !painter.options.zooming;
const canvasSize = [ painter.width, painter.height ];

if (isText) {
atlasTexture = tile.glyphAtlasTexture;
atlasInterpolation = gl.LINEAR;
texSize = tile.glyphAtlasTexture.size;
if (bucket.iconsInText) {
texSizeIcon = tile.imageAtlasTexture.size;
atlasTextureIcon = tile.imageAtlasTexture;
const zoomDependentSize = sizeData.kind === 'composite' || sizeData.kind === 'camera';
atlasInterpolationIcon = transformed || painter.options.rotating || painter.options.zooming || zoomDependentSize ? gl.LINEAR : gl.NEAREST;
}
} else {
const iconScaled = layer.layout.get('icon-size').constantOr(0) !== 1 || bucket.iconsNeedLinear;
atlasTexture = tile.imageAtlasTexture;
atlasInterpolation = isSDF || painter.options.rotating || painter.options.zooming || iconScaled || transformed ?
gl.LINEAR :
gl.NEAREST;
texSize = tile.imageAtlasTexture.size;
}

Expand Down Expand Up @@ -313,16 +305,16 @@ function drawLayerSymbols(painter, sourceCache, layer, coords, isText, translate
if (!bucket.iconsInText) {
uniformValues = symbolSDFUniformValues(sizeData.kind,
size, rotateInShader, pitchWithMap, painter, matrix,
uLabelPlaneMatrix, uglCoordMatrix, isText, texSize, true);
uLabelPlaneMatrix, uglCoordMatrix, isText, isCrisp, canvasSize, texSize, true);
} else {
uniformValues = symbolTextAndIconUniformValues(sizeData.kind,
size, rotateInShader, pitchWithMap, painter, matrix,
uLabelPlaneMatrix, uglCoordMatrix, texSize, texSizeIcon);
uLabelPlaneMatrix, uglCoordMatrix, isCrisp, canvasSize, texSize, texSizeIcon);
}
} else {
uniformValues = symbolIconUniformValues(sizeData.kind,
size, rotateInShader, pitchWithMap, painter, matrix,
uLabelPlaneMatrix, uglCoordMatrix, isText, texSize);
uLabelPlaneMatrix, uglCoordMatrix, isText, isCrisp, canvasSize, texSize);
}

const state = {
Expand All @@ -331,8 +323,6 @@ function drawLayerSymbols(painter, sourceCache, layer, coords, isText, translate
uniformValues,
atlasTexture,
atlasTextureIcon,
atlasInterpolation,
atlasInterpolationIcon,
isSDF,
hasHalo
};
Expand Down Expand Up @@ -363,11 +353,11 @@ function drawLayerSymbols(painter, sourceCache, layer, coords, isText, translate
const state = segmentState.state;

context.activeTexture.set(gl.TEXTURE0);
state.atlasTexture.bind(state.atlasInterpolation, gl.CLAMP_TO_EDGE);
state.atlasTexture.bind(gl.LINEAR, gl.CLAMP_TO_EDGE);
if (state.atlasTextureIcon) {
context.activeTexture.set(gl.TEXTURE1);
if (state.atlasTextureIcon) {
state.atlasTextureIcon.bind(state.atlasInterpolationIcon, gl.CLAMP_TO_EDGE);
state.atlasTextureIcon.bind(gl.LINEAR, gl.CLAMP_TO_EDGE);
}
}

Expand Down
31 changes: 25 additions & 6 deletions src/render/program/symbol_program.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,14 @@ export type SymbolIconUniformsType = {|
'u_pitch': Uniform1f,
'u_rotate_symbol': Uniform1i,
'u_aspect_ratio': Uniform1f,
'u_device_pixel_ratio': Uniform1f,
'u_fade_change': Uniform1f,
'u_matrix': UniformMatrix4f,
'u_label_plane_matrix': UniformMatrix4f,
'u_coord_matrix': UniformMatrix4f,
'u_is_text': Uniform1f,
'u_crisp': Uniform1i,
'u_canvas_size': Uniform2f,
'u_pitch_with_map': Uniform1i,
'u_texsize': Uniform2f,
'u_texture': Uniform1i
Expand All @@ -41,6 +44,7 @@ export type SymbolSDFUniformsType = {|
'u_pitch': Uniform1f,
'u_rotate_symbol': Uniform1i,
'u_aspect_ratio': Uniform1f,
'u_device_pixel_ratio': Uniform1f,
'u_fade_change': Uniform1f,
'u_matrix': UniformMatrix4f,
'u_label_plane_matrix': UniformMatrix4f,
Expand All @@ -50,7 +54,6 @@ export type SymbolSDFUniformsType = {|
'u_texsize': Uniform2f,
'u_texture': Uniform1i,
'u_gamma_scale': Uniform1f,
'u_device_pixel_ratio': Uniform1f,
'u_is_halo': Uniform1f
|};

Expand All @@ -63,11 +66,14 @@ export type symbolTextAndIconUniformsType = {|
'u_pitch': Uniform1f,
'u_rotate_symbol': Uniform1i,
'u_aspect_ratio': Uniform1f,
'u_device_pixel_ratio': Uniform1f,
'u_fade_change': Uniform1f,
'u_matrix': UniformMatrix4f,
'u_label_plane_matrix': UniformMatrix4f,
'u_coord_matrix': UniformMatrix4f,
'u_is_text': Uniform1f,
'u_crisp': Uniform1i,
'u_canvas_size': Uniform2f,
'u_pitch_with_map': Uniform1i,
'u_texsize': Uniform2f,
'u_texsize_icon': Uniform2f,
Expand All @@ -87,11 +93,14 @@ const symbolIconUniforms = (context: Context, locations: UniformLocations): Symb
'u_pitch': new Uniform1f(context, locations.u_pitch),
'u_rotate_symbol': new Uniform1i(context, locations.u_rotate_symbol),
'u_aspect_ratio': new Uniform1f(context, locations.u_aspect_ratio),
'u_device_pixel_ratio': new Uniform1f(context, locations.u_device_pixel_ratio),
'u_fade_change': new Uniform1f(context, locations.u_fade_change),
'u_matrix': new UniformMatrix4f(context, locations.u_matrix),
'u_label_plane_matrix': new UniformMatrix4f(context, locations.u_label_plane_matrix),
'u_coord_matrix': new UniformMatrix4f(context, locations.u_coord_matrix),
'u_is_text': new Uniform1f(context, locations.u_is_text),
'u_crisp': new Uniform1i(context, locations.u_crisp),
'u_canvas_size': new Uniform2f(context, locations.u_canvas_size),
'u_pitch_with_map': new Uniform1i(context, locations.u_pitch_with_map),
'u_texsize': new Uniform2f(context, locations.u_texsize),
'u_texture': new Uniform1i(context, locations.u_texture)
Expand All @@ -106,6 +115,7 @@ const symbolSDFUniforms = (context: Context, locations: UniformLocations): Symbo
'u_pitch': new Uniform1f(context, locations.u_pitch),
'u_rotate_symbol': new Uniform1i(context, locations.u_rotate_symbol),
'u_aspect_ratio': new Uniform1f(context, locations.u_aspect_ratio),
'u_device_pixel_ratio': new Uniform1f(context, locations.u_device_pixel_ratio),
'u_fade_change': new Uniform1f(context, locations.u_fade_change),
'u_matrix': new UniformMatrix4f(context, locations.u_matrix),
'u_label_plane_matrix': new UniformMatrix4f(context, locations.u_label_plane_matrix),
Expand All @@ -115,7 +125,6 @@ const symbolSDFUniforms = (context: Context, locations: UniformLocations): Symbo
'u_texsize': new Uniform2f(context, locations.u_texsize),
'u_texture': new Uniform1i(context, locations.u_texture),
'u_gamma_scale': new Uniform1f(context, locations.u_gamma_scale),
'u_device_pixel_ratio': new Uniform1f(context, locations.u_device_pixel_ratio),
'u_is_halo': new Uniform1f(context, locations.u_is_halo)
});

Expand All @@ -128,18 +137,20 @@ const symbolTextAndIconUniforms = (context: Context, locations: UniformLocations
'u_pitch': new Uniform1f(context, locations.u_pitch),
'u_rotate_symbol': new Uniform1i(context, locations.u_rotate_symbol),
'u_aspect_ratio': new Uniform1f(context, locations.u_aspect_ratio),
'u_device_pixel_ratio': new Uniform1f(context, locations.u_device_pixel_ratio),
'u_fade_change': new Uniform1f(context, locations.u_fade_change),
'u_matrix': new UniformMatrix4f(context, locations.u_matrix),
'u_label_plane_matrix': new UniformMatrix4f(context, locations.u_label_plane_matrix),
'u_coord_matrix': new UniformMatrix4f(context, locations.u_coord_matrix),
'u_is_text': new Uniform1f(context, locations.u_is_text),
'u_crisp': new Uniform1i(context, locations.u_crisp),
'u_canvas_size': new Uniform2f(context, locations.u_canvas_size),
'u_pitch_with_map': new Uniform1i(context, locations.u_pitch_with_map),
'u_texsize': new Uniform2f(context, locations.u_texsize),
'u_texsize_icon': new Uniform2f(context, locations.u_texsize_icon),
'u_texture': new Uniform1i(context, locations.u_texture),
'u_texture_icon': new Uniform1i(context, locations.u_texture_icon),
'u_gamma_scale': new Uniform1f(context, locations.u_gamma_scale),
'u_device_pixel_ratio': new Uniform1f(context, locations.u_device_pixel_ratio),
'u_is_halo': new Uniform1f(context, locations.u_is_halo)
});

Expand All @@ -153,6 +164,8 @@ const symbolIconUniformValues = (
labelPlaneMatrix: Float32Array,
glCoordMatrix: Float32Array,
isText: boolean,
isCrisp: boolean,
canvasSize: [number, number],
texSize: [number, number]
): UniformValues<SymbolIconUniformsType> => {
const transform = painter.transform;
Expand All @@ -171,6 +184,9 @@ const symbolIconUniformValues = (
'u_label_plane_matrix': labelPlaneMatrix,
'u_coord_matrix': glCoordMatrix,
'u_is_text': +isText,
'u_crisp': +isCrisp,
'u_device_pixel_ratio': browser.devicePixelRatio,
'u_canvas_size': canvasSize,
'u_pitch_with_map': +pitchWithMap,
'u_texsize': texSize,
'u_texture': 0
Expand All @@ -187,16 +203,17 @@ const symbolSDFUniformValues = (
labelPlaneMatrix: Float32Array,
glCoordMatrix: Float32Array,
isText: boolean,
isCrisp: boolean,
canvasSize: [number, number],
texSize: [number, number],
isHalo: boolean
): UniformValues<SymbolSDFUniformsType> => {
const transform = painter.transform;

return extend(symbolIconUniformValues(functionType, size,
rotateInShader, pitchWithMap, painter, matrix, labelPlaneMatrix,
glCoordMatrix, isText, texSize), {
glCoordMatrix, isText, isCrisp, canvasSize, texSize), {
'u_gamma_scale': (pitchWithMap ? Math.cos(transform._pitch) * transform.cameraToCenterDistance : 1),
'u_device_pixel_ratio': browser.devicePixelRatio,
'u_is_halo': +isHalo
});
};
Expand All @@ -210,12 +227,14 @@ const symbolTextAndIconUniformValues = (
matrix: Float32Array,
labelPlaneMatrix: Float32Array,
glCoordMatrix: Float32Array,
isCrisp: boolean,
canvasSize: [number, number],
texSizeSDF: [number, number],
texSizeIcon: [number, number]
): UniformValues<SymbolIconUniformsType> => {
return extend(symbolSDFUniformValues(functionType, size,
rotateInShader, pitchWithMap, painter, matrix, labelPlaneMatrix,
glCoordMatrix, true, texSizeSDF, true), {
glCoordMatrix, true, isCrisp, canvasSize, texSizeSDF, true), {
'u_texsize_icon': texSizeIcon,
'u_texture_icon': 1
});
Expand Down
8 changes: 8 additions & 0 deletions src/shaders/_prelude.vertex.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,11 @@ vec2 get_pattern_pos(const vec2 pixel_coord_upper, const vec2 pixel_coord_lower,
vec2 offset = mod(mod(mod(pixel_coord_upper, pattern_size) * 256.0, pattern_size) * 256.0 + pixel_coord_lower, pattern_size);
return (tile_units_to_pixels * pos + offset) / pattern_size;
}

// OpenGL ES 2 doesn't have round().
vec2 round_vec2(vec2 value) {
vec2 result = fract(value);
value.x += (result.x > 0.5 ? 1.0 : 0.0) - result.x;
value.y += (result.y > 0.5 ? 1.0 : 0.0) - result.y;
return value;
}
9 changes: 9 additions & 0 deletions src/shaders/symbol_icon.vertex.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ uniform mat4 u_label_plane_matrix;
uniform mat4 u_coord_matrix;

uniform bool u_is_text;
uniform bool u_crisp;
uniform float u_device_pixel_ratio;
uniform vec2 u_canvas_size;
uniform bool u_pitch_with_map;

uniform vec2 u_texsize;
Expand Down Expand Up @@ -87,6 +90,12 @@ void main() {
vec4 projected_pos = u_label_plane_matrix * vec4(a_projected_pos.xy, 0.0, 1.0);
gl_Position = u_coord_matrix * vec4(projected_pos.xy / projected_pos.w + rotation_matrix * (a_offset / 32.0 * max(a_minFontScale, fontScale) + a_pxoffset / 16.0), 0.0, 1.0);

if (u_crisp) {
vec2 half_canvas_size = u_canvas_size / 2.0;
vec2 factor = half_canvas_size / gl_Position.w;
gl_Position.xy = (round_vec2(gl_Position.xy * factor) + fract(half_canvas_size)) / factor;
}

v_tex = a_tex / u_texsize;
vec2 fade_opacity = unpack_opacity(a_fade_opacity);
float fade_change = fade_opacity[1] > 0.5 ? u_fade_change : -u_fade_change;
Expand Down
9 changes: 9 additions & 0 deletions src/shaders/symbol_text_and_icon.vertex.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ uniform mat4 u_matrix;
uniform mat4 u_label_plane_matrix;
uniform mat4 u_coord_matrix;
uniform bool u_is_text;
uniform bool u_crisp;
uniform lowp float u_device_pixel_ratio;
uniform vec2 u_canvas_size;
uniform bool u_pitch_with_map;
uniform highp float u_pitch;
uniform bool u_rotate_symbol;
Expand Down Expand Up @@ -106,6 +109,12 @@ void main() {
gl_Position = u_coord_matrix * vec4(projected_pos.xy / projected_pos.w + rotation_matrix * (a_offset / 32.0 * fontScale), 0.0, 1.0);
float gamma_scale = gl_Position.w;

if (u_crisp && is_sdf == 0.0) {
vec2 half_canvas_size = u_canvas_size / 2.0;
vec2 factor = half_canvas_size / gl_Position.w;
gl_Position.xy = (round_vec2(gl_Position.xy * factor) + fract(half_canvas_size)) / factor;
}

vec2 fade_opacity = unpack_opacity(a_fade_opacity);
float fade_change = fade_opacity[1] > 0.5 ? u_fade_change : -u_fade_change;
float interpolated_fade_opacity = max(0.0, min(1.0, fade_opacity[0] + fade_change));
Expand Down
6 changes: 0 additions & 6 deletions src/symbol/symbol_layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,6 @@ export function performSymbolLayout(bucket: SymbolBucket,
const tileSize = 512 * bucket.overscaling;
bucket.tilePixelRatio = EXTENT / tileSize;
bucket.compareText = {};
bucket.iconsNeedLinear = false;

const layout = bucket.layers[0].layout;
const unevaluatedLayoutValues = bucket.layers[0]._unevaluatedLayout._values;
Expand Down Expand Up @@ -305,11 +304,6 @@ export function performSymbolLayout(bucket: SymbolBucket,
} else if (bucket.sdfIcons !== image.sdf) {
warnOnce('Style sheet warning: Cannot mix SDF and non-SDF icons in one buffer');
}
if (image.pixelRatio !== bucket.pixelRatio) {
bucket.iconsNeedLinear = true;
} else if (layout.get('icon-rotate').constantOr(1) !== 0) {
bucket.iconsNeedLinear = true;
}
}
}

Expand Down
65 changes: 65 additions & 0 deletions test/integration/geojson/shields.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"icon": "a"
},
"geometry": {
"type": "Point",
"coordinates": [-17.5, 0]
}
},
{
"type": "Feature",
"properties": {
"icon": "b"
},
"geometry": {
"type": "Point",
"coordinates": [-10.5, 0]
}
},
{
"type": "Feature",
"properties": {
"icon": "c"
},
"geometry": {
"type": "Point",
"coordinates": [-3.5, 0]
}
},
{
"type": "Feature",
"properties": {
"icon": "d"
},
"geometry": {
"type": "Point",
"coordinates": [3.5, 0]
}
},
{
"type": "Feature",
"properties": {
"icon": "e"
},
"geometry": {
"type": "Point",
"coordinates": [10.5, 0]
}
},
{
"type": "Feature",
"properties": {
"icon": "f"
},
"geometry": {
"type": "Point",
"coordinates": [17.5, 0]
}
}
]
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading