mirror of https://gitee.com/antv-l7/antv-l7
fix(heatmap): 解决颜色插值问题,优化渲染性能
This commit is contained in:
parent
852c21b312
commit
d6829f30b9
|
@ -34,11 +34,11 @@ scene.on('loaded', () => {
|
||||||
.source(data)
|
.source(data)
|
||||||
.size('mag', [ 0, 1 ]) // weight映射通道
|
.size('mag', [ 0, 1 ]) // weight映射通道
|
||||||
.style({
|
.style({
|
||||||
intensity: 1,
|
intensity: 3,
|
||||||
radius: 10,
|
radius: 20,
|
||||||
rampColors: {
|
rampColors: {
|
||||||
colors: [ 'rgba(33,102,172,0)', 'rgb(103,169,207)', 'rgb(209,229,240)', 'rgb(253,219,199)', 'rgb(239,138,98)', 'rgb(178,24,43)' ],
|
colors: [ 'rgba(33,102,172,0.0)', 'rgb(103,169,207)', 'rgb(209,229,240)', 'rgb(253,219,199)', 'rgb(239,138,98)', 'rgb(178,24,43,1.0)' ],
|
||||||
positions: [ 0.0, 0.2, 0.4, 0.6, 0.8, 1.0 ]
|
positions: [ 0, 0.2, 0.4, 0.6, 0.8, 1.0 ]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.render();
|
.render();
|
||||||
|
|
|
@ -8,21 +8,20 @@ export default class RenderPass {
|
||||||
this.clearColor = cfg.clear.clearColor;
|
this.clearColor = cfg.clear.clearColor;
|
||||||
this.clearAlpha = cfg.clear.clearAlpha;
|
this.clearAlpha = cfg.clear.clearAlpha;
|
||||||
this.size = cfg.size ? cfg.size : cfg.renderer.getSize();
|
this.size = cfg.size ? cfg.size : cfg.renderer.getSize();
|
||||||
|
const defaultRenderCfg = {
|
||||||
|
minFilter: THREE.NearestFilter,
|
||||||
|
magFilter: THREE.NearestFilter,
|
||||||
|
format: THREE.RGBAFormat,
|
||||||
|
stencilBuffer: false,
|
||||||
|
depthBuffer: false
|
||||||
|
};
|
||||||
|
this.renderCfg = cfg.renderCfg ? cfg.renderCfg : defaultRenderCfg;
|
||||||
this._init(cfg);
|
this._init(cfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
_init() {
|
_init() {
|
||||||
this.scene = new THREE.Scene();
|
this.scene = new THREE.Scene();
|
||||||
const parameters = {
|
this.pass = new THREE.WebGLRenderTarget(this.size.width, this.size.height, this.renderCfg);
|
||||||
// minFilter: THREE.NearestFilter,
|
|
||||||
// magFilter: THREE.NearestFilter,
|
|
||||||
minFilter: THREE.LinearFilter,
|
|
||||||
magFilter: THREE.LinearFilter,
|
|
||||||
format: THREE.RGBAFormat,
|
|
||||||
stencilBuffer: false,
|
|
||||||
depthBuffer: false
|
|
||||||
};
|
|
||||||
this.pass = new THREE.WebGLRenderTarget(this.size.width, this.size.height, parameters);
|
|
||||||
this.originClearColor = this.renderer.getClearColor();
|
this.originClearColor = this.renderer.getClearColor();
|
||||||
this.originClearAlpha = this.renderer.getClearAlpha();
|
this.originClearAlpha = this.renderer.getClearAlpha();
|
||||||
this.texture = this.pass.texture;
|
this.texture = this.pass.texture;
|
||||||
|
@ -40,6 +39,5 @@ export default class RenderPass {
|
||||||
this.renderer.setClearColor(this.clearColor, this.clearAlpha);
|
this.renderer.setClearColor(this.clearColor, this.clearAlpha);
|
||||||
this.renderer.render(this.scene, this.camera, this.pass, true);
|
this.renderer.render(this.scene, this.camera, this.pass, true);
|
||||||
this.renderer.setClearColor(this.originClearColor, this.originClearAlpha);
|
this.renderer.setClearColor(this.originClearColor, this.originClearAlpha);
|
||||||
this.texture = this.pass.texture;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,9 +60,9 @@ function getColorRamp(name) {
|
||||||
const canvas = document.createElement('canvas');
|
const canvas = document.createElement('canvas');
|
||||||
const ctx = canvas.getContext('2d');
|
const ctx = canvas.getContext('2d');
|
||||||
|
|
||||||
canvas.width = 256;
|
canvas.width = 1;
|
||||||
canvas.height = 1;
|
canvas.height = 256;
|
||||||
const gradient = ctx.createLinearGradient(0, 0, 256, 0);
|
const gradient = ctx.createLinearGradient(0, 0, 0, 256);
|
||||||
let data = null;
|
let data = null;
|
||||||
if (typeof (colorscale) === 'string') {
|
if (typeof (colorscale) === 'string') {
|
||||||
colorscale = colorScales[name];
|
colorscale = colorScales[name];
|
||||||
|
@ -76,21 +76,23 @@ function getColorRamp(name) {
|
||||||
gradient.addColorStop(value, colorscale.colors[i]);
|
gradient.addColorStop(value, colorscale.colors[i]);
|
||||||
}
|
}
|
||||||
ctx.fillStyle = gradient;
|
ctx.fillStyle = gradient;
|
||||||
ctx.fillRect(0, 0, 256, 1);
|
ctx.fillRect(0, 0, 1, 256);
|
||||||
data = new Uint8ClampedArray(ctx.getImageData(0, 0, 256, 1).data);
|
data = new Uint8ClampedArray(ctx.getImageData(0, 0, 1, 256).data);
|
||||||
}
|
}
|
||||||
if (Object.prototype.toString.call(colorscale) === '[object Uint8Array]') {
|
if (Object.prototype.toString.call(colorscale) === '[object Uint8Array]') {
|
||||||
data = ctx.createImageData(256, 1);
|
data = ctx.createImageData(1, 256);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ImageData(data, 16, 16);
|
return new ImageData(data, 1, 256);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTexture(image) {
|
function getTexture(image) {
|
||||||
const texture = new THREE.Texture(image);
|
const texture = new THREE.Texture(image);
|
||||||
texture.magFilter = THREE.LinearFilter;
|
texture.wrapS = THREE.ClampToEdgeWrapping;
|
||||||
texture.minFilter = THREE.LinearFilter;
|
texture.wrapT = THREE.ClampToEdgeWrapping;
|
||||||
|
texture.magFilter = THREE.NearestFilter;
|
||||||
|
texture.minFilter = THREE.NearestFilter;
|
||||||
texture.format = THREE.RGBAFormat;
|
texture.format = THREE.RGBAFormat;
|
||||||
texture.type = THREE.UnsignedByteType;
|
texture.type = THREE.UnsignedByteType;
|
||||||
texture.needsUpdate = true;
|
texture.needsUpdate = true;
|
||||||
|
|
|
@ -27,7 +27,8 @@ export function HeatmapColorizeMaterial(opt) {
|
||||||
u_colorRamp: { value: opt.colorRamp }
|
u_colorRamp: { value: opt.colorRamp }
|
||||||
},
|
},
|
||||||
vertexShader: heatmap_colorize_vert,
|
vertexShader: heatmap_colorize_vert,
|
||||||
fragmentShader: heatmap_colorize_frag
|
fragmentShader: heatmap_colorize_frag,
|
||||||
|
transparent: true
|
||||||
});
|
});
|
||||||
return material;
|
return material;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,5 +5,5 @@ varying vec2 v_uv;
|
||||||
void main(){
|
void main(){
|
||||||
float intensity = texture2D(u_texture,v_uv).r;
|
float intensity = texture2D(u_texture,v_uv).r;
|
||||||
vec4 color = texture2D(u_colorRamp,vec2(0.5,1.0-intensity));
|
vec4 color = texture2D(u_colorRamp,vec2(0.5,1.0-intensity));
|
||||||
gl_FragColor = color * intensity;
|
gl_FragColor = color;
|
||||||
}
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
precision highp float;
|
precision highp float;
|
||||||
|
uniform float u_intensity;
|
||||||
varying float v_weight;
|
varying float v_weight;
|
||||||
varying vec2 v_extrude;
|
varying vec2 v_extrude;
|
||||||
|
|
||||||
|
@ -6,6 +7,6 @@ varying vec2 v_extrude;
|
||||||
void main(){
|
void main(){
|
||||||
float GAUSS_COEF = 0.3989422804014327;
|
float GAUSS_COEF = 0.3989422804014327;
|
||||||
float d = -0.5 * 3.0 * 3.0 * dot(v_extrude, v_extrude);
|
float d = -0.5 * 3.0 * 3.0 * dot(v_extrude, v_extrude);
|
||||||
float val = v_weight * 10.0 * GAUSS_COEF * exp(d);
|
float val = v_weight * u_intensity * GAUSS_COEF * exp(d);
|
||||||
gl_FragColor = vec4(val, val, val, 1.0);
|
gl_FragColor = vec4(val, val, val, val);
|
||||||
}
|
}
|
|
@ -16,7 +16,7 @@ void main(){
|
||||||
vec2 extrude_dir = normalize(vec2(extrude_x,extrude_y));
|
vec2 extrude_dir = normalize(vec2(extrude_x,extrude_y));
|
||||||
float S = sqrt(-2.0 * log(ZERO / a_weight / u_intensity / GAUSS_COEF)) / 3.0;
|
float S = sqrt(-2.0 * log(ZERO / a_weight / u_intensity / GAUSS_COEF)) / 3.0;
|
||||||
v_extrude = extrude_dir * S;
|
v_extrude = extrude_dir * S;
|
||||||
vec2 extrude = v_extrude * u_radius * pow(2.0,20.0-min(u_zoom,9.0));
|
vec2 extrude = v_extrude * u_radius * pow(2.0,20.0-u_zoom);
|
||||||
vec4 pos = vec4( position.xy+ extrude, 0.0, 1.0);
|
vec4 pos = vec4( position.xy+ extrude, 0.0, 1.0);
|
||||||
gl_Position = projectionMatrix * modelViewMatrix * pos;
|
gl_Position = projectionMatrix * modelViewMatrix * pos;
|
||||||
}
|
}
|
|
@ -37,16 +37,30 @@ function createIntensityPass(layer, bbox) {
|
||||||
const passOrth = new THREE.OrthographicCamera(bbox.width / -2, bbox.width / 2, bbox.height / 2, bbox.height / -2, 1, 10000);
|
const passOrth = new THREE.OrthographicCamera(bbox.width / -2, bbox.width / 2, bbox.height / 2, bbox.height / -2, 1, 10000);
|
||||||
passOrth.position.set(bbox.minX + bbox.width / 2, bbox.minY + bbox.height / 2, 1000);
|
passOrth.position.set(bbox.minX + bbox.width / 2, bbox.minY + bbox.height / 2, 1000);
|
||||||
// renderpass
|
// renderpass
|
||||||
|
const renderer = layer.scene._engine._renderer;
|
||||||
|
// get extension for bilinear texture interpolation:https://threejs.org/docs/#api/en/textures/DataTexture
|
||||||
|
const gl = renderer.domElement.getContext('webgl') ||
|
||||||
|
renderer.domElement.getContext('experimental-webgl');
|
||||||
|
gl.getExtension('OES_texture_float_linear');
|
||||||
const renderpass = new Renderpass({
|
const renderpass = new Renderpass({
|
||||||
renderer: layer.scene._engine._renderer,
|
renderer,
|
||||||
camera: passOrth,
|
camera: passOrth,
|
||||||
size: {
|
size: {
|
||||||
width: 10000,
|
width: 2000,
|
||||||
height: 10000 * (bbox.height / bbox.width)
|
height: 2000 * (bbox.height / bbox.width)
|
||||||
},
|
},
|
||||||
clear: {
|
clear: {
|
||||||
clearColor: 0x000000,
|
clearColor: 0x000000,
|
||||||
clearAlpha: 1.0
|
clearAlpha: 0.0
|
||||||
|
},
|
||||||
|
renderCfg: {
|
||||||
|
wrapS: THREE.ClampToEdgeWrapping,
|
||||||
|
wrapT: THREE.ClampToEdgeWrapping,
|
||||||
|
minFilter: THREE.LinearFilter,
|
||||||
|
magFilter: THREE.LinearFilter,
|
||||||
|
format: THREE.RGBAFormat,
|
||||||
|
stencilBuffer: false,
|
||||||
|
depthBuffer: false
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
renderpass.add(mesh);
|
renderpass.add(mesh);
|
||||||
|
@ -56,8 +70,12 @@ function createIntensityPass(layer, bbox) {
|
||||||
render();
|
render();
|
||||||
function render() {
|
function render() {
|
||||||
requestAnimationFrame(render);
|
requestAnimationFrame(render);
|
||||||
|
const zoom = scene.getZoom();
|
||||||
|
mesh.material.uniforms.u_zoom.value = zoom;
|
||||||
|
const passWidth = Math.min(10000, Math.pow(zoom, 2.0) * 200);
|
||||||
|
const passHeight = passWidth * (bbox.height / bbox.width);
|
||||||
|
renderpass.pass.setSize(passWidth, passHeight);
|
||||||
renderpass.render();
|
renderpass.render();
|
||||||
mesh.material.uniforms.u_zoom.value = scene.getZoom();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function createColorizePass(layer, bbox) {
|
function createColorizePass(layer, bbox) {
|
||||||
|
|
Loading…
Reference in New Issue