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
a233c588f4
|
@ -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) {
|
export default function circleBuffer(layerData) {
|
||||||
const index = [];
|
const index = [];
|
||||||
const aExtrude = [];
|
|
||||||
const aRadius = [];
|
|
||||||
const aColor = [];
|
|
||||||
const aPickingId = [];
|
|
||||||
const aPosition = [];
|
const aPosition = [];
|
||||||
|
const aPackedData = [];
|
||||||
layerData.forEach(({ size = 0, color, id, coordinates }, i) => {
|
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
|
// construct point coords
|
||||||
aExtrude.push(-1, -1, 1, -1, 1, 1, -1, 1);
|
[
|
||||||
aRadius.push(size, size, size, size);
|
[ -1, -1 ],
|
||||||
aColor.push(...color, ...color, ...color, ...color);
|
[ 1, -1 ],
|
||||||
aPickingId.push(id, id, id, id);
|
[ 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);
|
aPosition.push(...coordinates, ...coordinates, ...coordinates, ...coordinates);
|
||||||
index.push(...[ 0, 1, 2, 0, 2, 3 ].map(n => n + i * 4));
|
index.push(...[ 0, 1, 2, 0, 2, 3 ].map(n => n + i * 4));
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
aExtrude,
|
|
||||||
aRadius,
|
|
||||||
aColor,
|
|
||||||
aPickingId,
|
|
||||||
aPosition,
|
aPosition,
|
||||||
index
|
index,
|
||||||
|
aPackedData
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
attribute float a_radius;
|
attribute vec4 a_packed_data;
|
||||||
attribute vec2 a_shape;
|
|
||||||
attribute vec4 a_color;
|
|
||||||
|
|
||||||
uniform float u_zoom : 1;
|
uniform float u_zoom : 1;
|
||||||
uniform float u_stroke_width : 2;
|
uniform float u_stroke_width : 2;
|
||||||
|
@ -11,24 +9,44 @@ varying vec3 v_data;
|
||||||
varying vec4 v_color;
|
varying vec4 v_color;
|
||||||
varying float v_radius;
|
varying float v_radius;
|
||||||
|
|
||||||
void main() {
|
#pragma include "decode"
|
||||||
v_color = a_color;
|
|
||||||
v_radius = a_radius;
|
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);
|
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);
|
gl_Position = projectionMatrix * modelViewMatrix * vec4(position.xy + offset, 0.0, 1.0);
|
||||||
|
|
||||||
// anti-alias
|
// anti-alias
|
||||||
float antialiasblur = 1.0 / (a_radius + u_stroke_width);
|
float antialiasblur = 1.0 / (radius + u_stroke_width);
|
||||||
|
|
||||||
// construct point coords
|
// construct point coords
|
||||||
v_data = vec3(a_shape, antialiasblur);
|
v_data = vec3(extrude, antialiasblur);
|
||||||
|
|
||||||
// picking
|
// picking
|
||||||
if(pickingId == u_activeId) {
|
if(picking_id == u_activeId) {
|
||||||
v_color = u_activeColor;
|
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 common from './common.glsl';
|
||||||
import { registerModule } from '../../util/shaderModule';
|
import { registerModule } from '../../util/shaderModule';
|
||||||
import pick_color from './shaderChunks/pick_color.glsl';
|
import pick_color from './shaderChunks/pick_color.glsl';
|
||||||
|
import decode from './shaderChunks/decode.glsl';
|
||||||
|
|
||||||
export function compileBuiltinModules() {
|
export function compileBuiltinModules() {
|
||||||
registerModule('point', { vs: point_vert, fs: point_frag });
|
registerModule('point', { vs: point_vert, fs: point_frag });
|
||||||
registerModule('common', { vs: common, fs: common });
|
registerModule('common', { vs: common, fs: common });
|
||||||
|
registerModule('decode', { vs: decode, fs: '' });
|
||||||
registerModule('pick_color', { vs: pick_color, fs: pick_color });
|
registerModule('pick_color', { vs: pick_color, fs: pick_color });
|
||||||
registerModule('circle', { vs: circle_vert, fs: circle_frag });
|
registerModule('circle', { vs: circle_vert, fs: circle_frag });
|
||||||
registerModule('polygon', { vs: polygon_vert, fs: polygon_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 style = layer.get('styleOptions');
|
||||||
const activeOption = layer.get('activedOptions');
|
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();
|
const geometry = new THREE.BufferGeometry();
|
||||||
geometry.setIndex(index);
|
geometry.setIndex(index);
|
||||||
geometry.addAttribute('position', new THREE.Float32BufferAttribute(aPosition, 3));
|
geometry.addAttribute('position', new THREE.Float32BufferAttribute(aPosition, 3));
|
||||||
geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(aColor, 4));
|
geometry.addAttribute('a_packed_data', new THREE.Float32BufferAttribute(aPackedData, 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));
|
|
||||||
|
|
||||||
const material = new CircleMaterial({
|
const material = new CircleMaterial({
|
||||||
u_opacity: style.opacity,
|
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