mirror of https://gitee.com/antv-l7/antv-l7
Merge branch 'dev-vertex-compression' into 'master'
Dev vertex compression 对于 point layer(circle) 压缩顶点数据 https://yuque.antfin-inc.com/yuqi.pyq/fgetpa/wxv543#xzVLo 优化后每个顶点只需要一个 vec4 存储颜色、pickingId 等数据: vec4(color, color, pickingId, (extrude.x, extrude.y, radius)) See merge request !31
This commit is contained in:
commit
336146e4c3
|
@ -1,25 +1,46 @@
|
|||
import { packUint8ToFloat } from '../../../util/vertex-compress';
|
||||
|
||||
const LEFT_SHIFT18 = 262144.0;
|
||||
const LEFT_SHIFT20 = 1048576.0;
|
||||
|
||||
export default function circleBuffer(layerData) {
|
||||
const index = [];
|
||||
const aExtrude = [];
|
||||
const aRadius = [];
|
||||
const aColor = [];
|
||||
const aPickingId = [];
|
||||
const aPosition = [];
|
||||
const aPackedData = [];
|
||||
layerData.forEach(({ size = 0, color, id, coordinates }, i) => {
|
||||
|
||||
if (isNaN(size)) {
|
||||
size = 0;
|
||||
}
|
||||
|
||||
// pack color(vec4) into vec2
|
||||
const packedColor = [
|
||||
packUint8ToFloat(color[0] * 255, color[1] * 255),
|
||||
packUint8ToFloat(color[2] * 255, color[3] * 255)
|
||||
];
|
||||
|
||||
// construct point coords
|
||||
aExtrude.push(-1, -1, 1, -1, 1, 1, -1, 1);
|
||||
aRadius.push(size, size, size, size);
|
||||
aColor.push(...color, ...color, ...color, ...color);
|
||||
aPickingId.push(id, id, id, id);
|
||||
[
|
||||
[ -1, -1 ],
|
||||
[ 1, -1 ],
|
||||
[ 1, 1 ],
|
||||
[ -1, 1 ]
|
||||
].forEach(extrude => {
|
||||
// vec4(color, color, (4-bit extrude, 16-bit size), id)
|
||||
aPackedData.push(
|
||||
...packedColor,
|
||||
(extrude[0] + 1) * LEFT_SHIFT20 + (extrude[1] + 1) * LEFT_SHIFT18 + size,
|
||||
id
|
||||
);
|
||||
});
|
||||
|
||||
// TODO:如果使用相对瓦片坐标,还可以进一步压缩
|
||||
aPosition.push(...coordinates, ...coordinates, ...coordinates, ...coordinates);
|
||||
index.push(...[ 0, 1, 2, 0, 2, 3 ].map(n => n + i * 4));
|
||||
});
|
||||
return {
|
||||
aExtrude,
|
||||
aRadius,
|
||||
aColor,
|
||||
aPickingId,
|
||||
aPosition,
|
||||
index
|
||||
index,
|
||||
aPackedData
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
attribute float a_radius;
|
||||
attribute vec2 a_shape;
|
||||
attribute vec4 a_color;
|
||||
attribute vec4 a_packed_data;
|
||||
|
||||
uniform float u_zoom : 1;
|
||||
uniform float u_stroke_width : 2;
|
||||
|
@ -11,24 +9,44 @@ varying vec3 v_data;
|
|||
varying vec4 v_color;
|
||||
varying float v_radius;
|
||||
|
||||
void main() {
|
||||
v_color = a_color;
|
||||
v_radius = a_radius;
|
||||
#pragma include "decode"
|
||||
|
||||
void main() {
|
||||
// unpack color(vec2)
|
||||
v_color = decode_color(a_packed_data.xy);
|
||||
// unpack picking_id
|
||||
float picking_id = a_packed_data.w;
|
||||
|
||||
// unpack data(extrude(4-bit), radius(16-bit))
|
||||
float compressed = a_packed_data.z;
|
||||
|
||||
// extrude(4-bit)
|
||||
vec2 extrude;
|
||||
extrude.x = floor(compressed * SHIFT_RIGHT20);
|
||||
compressed -= extrude.x * SHIFT_LEFT20;
|
||||
extrude.x = extrude.x - 1.;
|
||||
|
||||
extrude.y = floor(compressed * SHIFT_RIGHT18);
|
||||
compressed -= extrude.y * SHIFT_LEFT18;
|
||||
extrude.y = extrude.y - 1.;
|
||||
|
||||
// radius(16-bit)
|
||||
float radius = compressed;
|
||||
v_radius = radius;
|
||||
|
||||
// extrude
|
||||
float zoom_scale = pow(2., 20. - u_zoom);
|
||||
vec2 offset = a_shape * (a_radius + u_stroke_width) * zoom_scale;
|
||||
vec2 offset = extrude * (radius + u_stroke_width) * zoom_scale;
|
||||
gl_Position = projectionMatrix * modelViewMatrix * vec4(position.xy + offset, 0.0, 1.0);
|
||||
|
||||
// anti-alias
|
||||
float antialiasblur = 1.0 / (a_radius + u_stroke_width);
|
||||
float antialiasblur = 1.0 / (radius + u_stroke_width);
|
||||
|
||||
// construct point coords
|
||||
v_data = vec3(a_shape, antialiasblur);
|
||||
v_data = vec3(extrude, antialiasblur);
|
||||
|
||||
// picking
|
||||
if(pickingId == u_activeId) {
|
||||
if(picking_id == u_activeId) {
|
||||
v_color = u_activeColor;
|
||||
}
|
||||
worldId = id_toPickColor(pickingId);
|
||||
worldId = id_toPickColor(picking_id);
|
||||
}
|
|
@ -51,9 +51,12 @@ import mask_quard_frag from '../shader/tile/mask_quard_frag.glsl';
|
|||
import common from './common.glsl';
|
||||
import { registerModule } from '../../util/shaderModule';
|
||||
import pick_color from './shaderChunks/pick_color.glsl';
|
||||
import decode from './shaderChunks/decode.glsl';
|
||||
|
||||
export function compileBuiltinModules() {
|
||||
registerModule('point', { vs: point_vert, fs: point_frag });
|
||||
registerModule('common', { vs: common, fs: common });
|
||||
registerModule('decode', { vs: decode, fs: '' });
|
||||
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 });
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
#define SHIFT_RIGHT18 1.0 / 262144.0
|
||||
#define SHIFT_RIGHT20 1.0 / 1048576.0
|
||||
#define SHIFT_LEFT18 262144.0
|
||||
#define SHIFT_LEFT20 1048576.0
|
||||
|
||||
vec2 unpack_float(const float packedValue) {
|
||||
int packedIntValue = int(packedValue);
|
||||
int v0 = packedIntValue / 256;
|
||||
return vec2(v0, packedIntValue - v0 * 256);
|
||||
}
|
||||
|
||||
vec4 decode_color(const vec2 encodedColor) {
|
||||
return vec4(
|
||||
unpack_float(encodedColor[0]) / 255.0,
|
||||
unpack_float(encodedColor[1]) / 255.0
|
||||
);
|
||||
}
|
|
@ -9,14 +9,11 @@ export default function drawCircle(layerData, layer) {
|
|||
const style = layer.get('styleOptions');
|
||||
const activeOption = layer.get('activedOptions');
|
||||
|
||||
const { aColor, aExtrude, aPickingId, aPosition, index, aRadius } = PointBuffer.CircleBuffer(layerData, style);
|
||||
const { aPosition, aPackedData, index } = PointBuffer.CircleBuffer(layerData, style);
|
||||
const geometry = new THREE.BufferGeometry();
|
||||
geometry.setIndex(index);
|
||||
geometry.addAttribute('position', new THREE.Float32BufferAttribute(aPosition, 3));
|
||||
geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(aColor, 4));
|
||||
geometry.addAttribute('pickingId', new THREE.Float32BufferAttribute(aPickingId, 1));
|
||||
geometry.addAttribute('a_shape', new THREE.Float32BufferAttribute(aExtrude, 2));
|
||||
geometry.addAttribute('a_radius', new THREE.Float32BufferAttribute(aRadius, 1));
|
||||
geometry.addAttribute('a_packed_data', new THREE.Float32BufferAttribute(aPackedData, 4));
|
||||
|
||||
const material = new CircleMaterial({
|
||||
u_opacity: style.opacity,
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
import clamp from '@antv/util/lib/clamp';
|
||||
|
||||
/**
|
||||
* encode 2 8-bit unsigned int into a 16-bit float
|
||||
* @param {number} a 8-bit int
|
||||
* @param {number} b 8-bit int
|
||||
* @return {number} float
|
||||
*/
|
||||
export function packUint8ToFloat(a, b) {
|
||||
a = clamp(Math.floor(a), 0, 255);
|
||||
b = clamp(Math.floor(b), 0, 255);
|
||||
return 256 * a + b;
|
||||
}
|
Loading…
Reference in New Issue