mirror of https://gitee.com/antv-l7/antv-l7
feat(point-layer): use 2d sdf functions
This commit is contained in:
parent
1733971fcf
commit
6ec70396b9
|
@ -59,7 +59,14 @@ scene.on('loaded', () => {
|
|||
.source(data,{
|
||||
isCluster:true
|
||||
})
|
||||
.shape('circle')
|
||||
// .shape('circle')
|
||||
.shape('point_count', [ 'circle', 'triangle', 'hexagon' ])
|
||||
// .shape('triangle')
|
||||
// .shape('square')
|
||||
// .shape('hexagon')
|
||||
// .shape('octogon')
|
||||
// .shape('hexagram')
|
||||
// .shape('pentagon')
|
||||
.size('point_count', [ 5, 40]) // default 1
|
||||
//.size('value', [ 10, 300]) // default 1
|
||||
.active(true)
|
||||
|
|
|
@ -1,13 +1,24 @@
|
|||
import { packUint8ToFloat } from '../../../util/vertex-compress';
|
||||
import Global from '../../../global';
|
||||
const { pointShape } = Global;
|
||||
|
||||
const LEFT_SHIFT18 = 262144.0;
|
||||
const LEFT_SHIFT20 = 1048576.0;
|
||||
const LEFT_SHIFT17 = 131072.0;
|
||||
// const LEFT_SHIFT18 = 262144.0;
|
||||
// const LEFT_SHIFT19 = 524288.0;
|
||||
// const LEFT_SHIFT20 = 1048576.0;
|
||||
const LEFT_SHIFT21 = 2097152.0;
|
||||
// const LEFT_SHIFT22 = 4194304.0;
|
||||
const LEFT_SHIFT23 = 8388608.0;
|
||||
// const LEFT_SHIFT24 = 16777216.0;
|
||||
|
||||
export default function circleBuffer(layerData) {
|
||||
const index = [];
|
||||
const aPosition = [];
|
||||
const aPackedData = [];
|
||||
layerData.forEach(({ size = 0, color, id, coordinates }, i) => {
|
||||
|
||||
layerData.forEach(({ size = 0, color, id, coordinates, shape }, i) => {
|
||||
|
||||
const shapeIndex = pointShape['2d'].indexOf(shape) || 0;
|
||||
|
||||
if (isNaN(size)) {
|
||||
size = 0;
|
||||
|
@ -26,10 +37,12 @@ export default function circleBuffer(layerData) {
|
|||
[ 1, 1 ],
|
||||
[ -1, 1 ]
|
||||
].forEach(extrude => {
|
||||
// vec4(color, color, (4-bit extrude, 16-bit size), id)
|
||||
// vec4(color, color, (4-bit extrude, 4-bit shape, 16-bit size), id)
|
||||
aPackedData.push(
|
||||
...packedColor,
|
||||
(extrude[0] + 1) * LEFT_SHIFT20 + (extrude[1] + 1) * LEFT_SHIFT18 + size,
|
||||
(extrude[0] + 1) * LEFT_SHIFT23 + (extrude[1] + 1) * LEFT_SHIFT21
|
||||
+ shapeIndex * LEFT_SHIFT17
|
||||
+ size,
|
||||
id
|
||||
);
|
||||
});
|
||||
|
|
|
@ -4,22 +4,57 @@ uniform float u_stroke_width : 1;
|
|||
uniform vec4 u_stroke_color : [1, 1, 1, 1];
|
||||
uniform float u_stroke_opacity : 1;
|
||||
|
||||
varying vec3 v_data;
|
||||
varying vec4 v_data;
|
||||
varying vec4 v_color;
|
||||
varying float v_radius;
|
||||
|
||||
#pragma include "sdf_2d"
|
||||
|
||||
void main() {
|
||||
float extrude_length = length(v_data.xy);
|
||||
int shape = int(floor(v_data.w + 0.5));
|
||||
|
||||
lowp float antialiasblur = v_data.z;
|
||||
float antialiased_blur = -max(u_blur, antialiasblur);
|
||||
float r = v_radius / (v_radius + u_stroke_width);
|
||||
|
||||
float opacity_t = smoothstep(0.0, antialiased_blur, extrude_length - 1.0);
|
||||
float outer_df;
|
||||
float inner_df;
|
||||
// 'circle', 'triangle', 'square', 'pentagon', 'hexagon', 'octogon', 'hexagram', 'rhombus', 'vesica'
|
||||
if (shape == 0) {
|
||||
outer_df = sdCircle(v_data.xy, 1.0);
|
||||
inner_df = sdCircle(v_data.xy, r);
|
||||
} else if (shape == 1) {
|
||||
outer_df = sdEquilateralTriangle(1.1 * v_data.xy);
|
||||
inner_df = sdEquilateralTriangle(1.1 / r * v_data.xy);
|
||||
} else if (shape == 2) {
|
||||
outer_df = sdBox(v_data.xy, vec2(1.));
|
||||
inner_df = sdBox(v_data.xy, vec2(r));
|
||||
} else if (shape == 3) {
|
||||
outer_df = sdPentagon(v_data.xy, 0.8);
|
||||
inner_df = sdPentagon(v_data.xy, r * 0.8);
|
||||
} else if (shape == 4) {
|
||||
outer_df = sdHexagon(v_data.xy, 0.8);
|
||||
inner_df = sdHexagon(v_data.xy, r * 0.8);
|
||||
} else if (shape == 5) {
|
||||
outer_df = sdOctogon(v_data.xy, 1.0);
|
||||
inner_df = sdOctogon(v_data.xy, r);
|
||||
} else if (shape == 6) {
|
||||
outer_df = sdHexagram(v_data.xy, 0.52);
|
||||
inner_df = sdHexagram(v_data.xy, r * 0.52);
|
||||
} else if (shape == 7) {
|
||||
outer_df = sdRhombus(v_data.xy, vec2(1.0));
|
||||
inner_df = sdRhombus(v_data.xy, vec2(r));
|
||||
} else if (shape == 8) {
|
||||
outer_df = sdVesica(v_data.xy, 1.1, 0.8);
|
||||
inner_df = sdVesica(v_data.xy, r * 1.1, r * 0.8);
|
||||
}
|
||||
|
||||
float opacity_t = smoothstep(0.0, antialiased_blur, outer_df);
|
||||
|
||||
float color_t = u_stroke_width < 0.01 ? 0.0 : smoothstep(
|
||||
antialiased_blur,
|
||||
0.0,
|
||||
extrude_length - v_radius / (v_radius + u_stroke_width)
|
||||
inner_df
|
||||
);
|
||||
|
||||
gl_FragColor = opacity_t * mix(v_color * u_opacity, u_stroke_color * u_stroke_opacity, color_t);
|
||||
|
|
|
@ -5,7 +5,7 @@ uniform float u_stroke_width : 2;
|
|||
uniform float u_activeId : 0;
|
||||
uniform vec4 u_activeColor : [ 1.0, 0, 0, 1.0 ];
|
||||
|
||||
varying vec3 v_data;
|
||||
varying vec4 v_data;
|
||||
varying vec4 v_color;
|
||||
varying float v_radius;
|
||||
|
||||
|
@ -22,14 +22,17 @@ void main() {
|
|||
|
||||
// extrude(4-bit)
|
||||
vec2 extrude;
|
||||
extrude.x = floor(compressed * SHIFT_RIGHT20);
|
||||
compressed -= extrude.x * SHIFT_LEFT20;
|
||||
extrude.x = floor(compressed * SHIFT_RIGHT23);
|
||||
compressed -= extrude.x * SHIFT_LEFT23;
|
||||
extrude.x = extrude.x - 1.;
|
||||
|
||||
extrude.y = floor(compressed * SHIFT_RIGHT18);
|
||||
compressed -= extrude.y * SHIFT_LEFT18;
|
||||
extrude.y = floor(compressed * SHIFT_RIGHT21);
|
||||
compressed -= extrude.y * SHIFT_LEFT21;
|
||||
extrude.y = extrude.y - 1.;
|
||||
|
||||
float shape_type = floor(compressed * SHIFT_RIGHT17);
|
||||
compressed -= shape_type * SHIFT_LEFT17;
|
||||
|
||||
// radius(16-bit)
|
||||
float radius = compressed;
|
||||
v_radius = radius;
|
||||
|
@ -42,7 +45,7 @@ void main() {
|
|||
float antialiasblur = 1.0 / (radius + u_stroke_width);
|
||||
|
||||
// construct point coords
|
||||
v_data = vec3(extrude, antialiasblur);
|
||||
v_data = vec4(extrude, antialiasblur, shape_type);
|
||||
|
||||
// picking
|
||||
if(picking_id == u_activeId) {
|
||||
|
|
|
@ -52,11 +52,13 @@ import common from './common.glsl';
|
|||
import { registerModule } from '../../util/shaderModule';
|
||||
import pick_color from './shaderChunks/pick_color.glsl';
|
||||
import decode from './shaderChunks/decode.glsl';
|
||||
import sdf_2d from './shaderChunks/sdf_2d.glsl';
|
||||
|
||||
export function compileBuiltinModules() {
|
||||
registerModule('point', { vs: point_vert, fs: point_frag });
|
||||
registerModule('common', { vs: common, fs: common });
|
||||
registerModule('decode', { vs: decode, fs: '' });
|
||||
registerModule('sdf_2d', { vs: '', fs: sdf_2d });
|
||||
registerModule('pick_color', { vs: pick_color, fs: pick_color });
|
||||
registerModule('circle', { vs: circle_vert, fs: circle_frag });
|
||||
registerModule('polygon', { vs: polygon_vert, fs: polygon_frag });
|
||||
|
|
|
@ -1,7 +1,20 @@
|
|||
#define SHIFT_RIGHT17 1.0 / 131072.0
|
||||
#define SHIFT_RIGHT18 1.0 / 262144.0
|
||||
#define SHIFT_RIGHT19 1.0 / 524288.0
|
||||
#define SHIFT_RIGHT20 1.0 / 1048576.0
|
||||
#define SHIFT_RIGHT21 1.0 / 2097152.0
|
||||
#define SHIFT_RIGHT22 1.0 / 4194304.0
|
||||
#define SHIFT_RIGHT23 1.0 / 8388608.0
|
||||
#define SHIFT_RIGHT24 1.0 / 16777216.0
|
||||
|
||||
#define SHIFT_LEFT17 131072.0
|
||||
#define SHIFT_LEFT18 262144.0
|
||||
#define SHIFT_LEFT19 524288.0
|
||||
#define SHIFT_LEFT20 1048576.0
|
||||
#define SHIFT_LEFT21 2097152.0
|
||||
#define SHIFT_LEFT22 4194304.0
|
||||
#define SHIFT_LEFT23 8388608.0
|
||||
#define SHIFT_LEFT24 16777216.0
|
||||
|
||||
vec2 unpack_float(const float packedValue) {
|
||||
int packedIntValue = int(packedValue);
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
/**
|
||||
* 2D signed distance field functions
|
||||
* @see http://www.iquilezles.org/www/articles/distfunctions2d/distfunctions2d.htm
|
||||
*/
|
||||
|
||||
float ndot(vec2 a, vec2 b ) { return a.x*b.x - a.y*b.y; }
|
||||
|
||||
float sdCircle(vec2 p, float r) {
|
||||
return length(p) - r;
|
||||
}
|
||||
|
||||
float sdEquilateralTriangle(vec2 p) {
|
||||
const float k = sqrt(3.0);
|
||||
p.x = abs(p.x) - 1.0;
|
||||
p.y = p.y + 1.0/k;
|
||||
if( p.x + k*p.y > 0.0 ) p = vec2(p.x-k*p.y,-k*p.x-p.y)/2.0;
|
||||
p.x -= clamp( p.x, -2.0, 0.0 );
|
||||
return -length(p)*sign(p.y);
|
||||
}
|
||||
|
||||
float sdBox(vec2 p, vec2 b) {
|
||||
vec2 d = abs(p)-b;
|
||||
return length(max(d,vec2(0))) + min(max(d.x,d.y),0.0);
|
||||
}
|
||||
|
||||
float sdPentagon(vec2 p, float r) {
|
||||
const vec3 k = vec3(0.809016994,0.587785252,0.726542528);
|
||||
p.x = abs(p.x);
|
||||
p -= 2.0*min(dot(vec2(-k.x,k.y),p),0.0)*vec2(-k.x,k.y);
|
||||
p -= 2.0*min(dot(vec2( k.x,k.y),p),0.0)*vec2( k.x,k.y);
|
||||
p -= vec2(clamp(p.x,-r*k.z,r*k.z),r);
|
||||
return length(p)*sign(p.y);
|
||||
}
|
||||
|
||||
float sdHexagon(vec2 p, float r) {
|
||||
const vec3 k = vec3(-0.866025404,0.5,0.577350269);
|
||||
p = abs(p);
|
||||
p -= 2.0*min(dot(k.xy,p),0.0)*k.xy;
|
||||
p -= vec2(clamp(p.x, -k.z*r, k.z*r), r);
|
||||
return length(p)*sign(p.y);
|
||||
}
|
||||
|
||||
float sdOctogon(vec2 p, float r) {
|
||||
const vec3 k = vec3(-0.9238795325, 0.3826834323, 0.4142135623 );
|
||||
p = abs(p);
|
||||
p -= 2.0*min(dot(vec2( k.x,k.y),p),0.0)*vec2( k.x,k.y);
|
||||
p -= 2.0*min(dot(vec2(-k.x,k.y),p),0.0)*vec2(-k.x,k.y);
|
||||
p -= vec2(clamp(p.x, -k.z*r, k.z*r), r);
|
||||
return length(p)*sign(p.y);
|
||||
}
|
||||
|
||||
float sdHexagram(vec2 p, float r) {
|
||||
const vec4 k=vec4(-0.5,0.8660254038,0.5773502692,1.7320508076);
|
||||
p = abs(p);
|
||||
p -= 2.0*min(dot(k.xy,p),0.0)*k.xy;
|
||||
p -= 2.0*min(dot(k.yx,p),0.0)*k.yx;
|
||||
p -= vec2(clamp(p.x,r*k.z,r*k.w),r);
|
||||
return length(p)*sign(p.y);
|
||||
}
|
||||
|
||||
float sdRhombus(vec2 p, vec2 b) {
|
||||
vec2 q = abs(p);
|
||||
float h = clamp((-2.0*ndot(q,b)+ndot(b,b))/dot(b,b),-1.0,1.0);
|
||||
float d = length( q - 0.5*b*vec2(1.0-h,1.0+h) );
|
||||
return d * sign( q.x*b.y + q.y*b.x - b.x*b.y );
|
||||
}
|
||||
|
||||
float sdVesica(vec2 p, float r, float d) {
|
||||
p = abs(p);
|
||||
float b = sqrt(r*r-d*d); // can delay this sqrt
|
||||
return ((p.y-b)*d>p.x*b)
|
||||
? length(p-vec2(0.0,b))
|
||||
: length(p-vec2(-d,0.0))-r;
|
||||
}
|
|
@ -23,7 +23,7 @@ const Global = {
|
|||
shape: 'circle',
|
||||
snapArray: [ 0, 1, 2, 4, 5, 10 ],
|
||||
pointShape: {
|
||||
'2d': [ 'circle', 'square', 'hexagon', 'triangle' ],
|
||||
'2d': [ 'circle', 'triangle', 'square', 'pentagon', 'hexagon', 'octogon', 'hexagram', 'rhombus', 'vesica' ],
|
||||
'3d': [ 'cylinder', 'triangleColumn', 'hexagonColumn', 'squareColumn' ]
|
||||
},
|
||||
sdfHomeUrl: 'https://sdf.amap.com',
|
||||
|
|
|
@ -30,13 +30,9 @@ export default class PointLayer extends Layer {
|
|||
}
|
||||
|
||||
// 2D circle 特殊处理
|
||||
if (shape === 'circle') {
|
||||
if (pointShape['2d'].indexOf(shape) !== -1) {
|
||||
return 'circle';
|
||||
}
|
||||
if (
|
||||
pointShape['2d'].indexOf(shape) !== -1 ||
|
||||
pointShape['3d'].indexOf(shape) !== -1
|
||||
) {
|
||||
} else if (pointShape['3d'].indexOf(shape) !== -1) {
|
||||
return 'fill';
|
||||
} else if (this.scene.image.imagesIds.indexOf(shape) !== -1) {
|
||||
return 'image';
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* 针对绘制圆形的优化
|
||||
* 绘制 SDF,不仅是圆形
|
||||
* 手动构建点阵坐标系,便于实现描边、反走样效果
|
||||
*/
|
||||
import * as THREE from '../../../core/three';
|
||||
|
|
Loading…
Reference in New Issue