From d6829f30b993e84d3e3017a46116e09245b7f089 Mon Sep 17 00:00:00 2001 From: "mipha.ly" Date: Thu, 28 Feb 2019 11:55:04 +0800 Subject: [PATCH] =?UTF-8?q?fix(heatmap):=20=E8=A7=A3=E5=86=B3=E9=A2=9C?= =?UTF-8?q?=E8=89=B2=E6=8F=92=E5=80=BC=E9=97=AE=E9=A2=98=EF=BC=8C=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E6=B8=B2=E6=9F=93=E6=80=A7=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- demos/heatmap.html | 8 +++--- src/core/engine/renderpass.js | 20 +++++++-------- src/geom/buffer/heatmap/heatmap.js | 20 ++++++++------- src/geom/material/heatmapMateial.js | 3 ++- src/geom/shader/heatmap_colorize_frag.glsl | 2 +- src/geom/shader/heatmap_intensity_frag.glsl | 7 +++--- src/geom/shader/heatmap_intensity_vert.glsl | 2 +- src/layer/render/heatmap/heatmap.js | 28 +++++++++++++++++---- 8 files changed, 55 insertions(+), 35 deletions(-) diff --git a/demos/heatmap.html b/demos/heatmap.html index 415af28ee5..7d6538e09d 100644 --- a/demos/heatmap.html +++ b/demos/heatmap.html @@ -34,11 +34,11 @@ scene.on('loaded', () => { .source(data) .size('mag', [ 0, 1 ]) // weight映射通道 .style({ - intensity: 1, - radius: 10, + intensity: 3, + radius: 20, 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)' ], - positions: [ 0.0, 0.2, 0.4, 0.6, 0.8, 1.0 ] + 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.2, 0.4, 0.6, 0.8, 1.0 ] } }) .render(); diff --git a/src/core/engine/renderpass.js b/src/core/engine/renderpass.js index 70311302be..b39cb5de07 100644 --- a/src/core/engine/renderpass.js +++ b/src/core/engine/renderpass.js @@ -8,21 +8,20 @@ export default class RenderPass { this.clearColor = cfg.clear.clearColor; this.clearAlpha = cfg.clear.clearAlpha; 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); } _init() { this.scene = new THREE.Scene(); - const parameters = { - // 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.pass = new THREE.WebGLRenderTarget(this.size.width, this.size.height, this.renderCfg); this.originClearColor = this.renderer.getClearColor(); this.originClearAlpha = this.renderer.getClearAlpha(); this.texture = this.pass.texture; @@ -40,6 +39,5 @@ export default class RenderPass { this.renderer.setClearColor(this.clearColor, this.clearAlpha); this.renderer.render(this.scene, this.camera, this.pass, true); this.renderer.setClearColor(this.originClearColor, this.originClearAlpha); - this.texture = this.pass.texture; } } diff --git a/src/geom/buffer/heatmap/heatmap.js b/src/geom/buffer/heatmap/heatmap.js index 6d394a8ea7..c915b5dfa4 100644 --- a/src/geom/buffer/heatmap/heatmap.js +++ b/src/geom/buffer/heatmap/heatmap.js @@ -60,9 +60,9 @@ function getColorRamp(name) { const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); - canvas.width = 256; - canvas.height = 1; - const gradient = ctx.createLinearGradient(0, 0, 256, 0); + canvas.width = 1; + canvas.height = 256; + const gradient = ctx.createLinearGradient(0, 0, 0, 256); let data = null; if (typeof (colorscale) === 'string') { colorscale = colorScales[name]; @@ -76,21 +76,23 @@ function getColorRamp(name) { gradient.addColorStop(value, colorscale.colors[i]); } ctx.fillStyle = gradient; - ctx.fillRect(0, 0, 256, 1); - data = new Uint8ClampedArray(ctx.getImageData(0, 0, 256, 1).data); + ctx.fillRect(0, 0, 1, 256); + data = new Uint8ClampedArray(ctx.getImageData(0, 0, 1, 256).data); } 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) { const texture = new THREE.Texture(image); - texture.magFilter = THREE.LinearFilter; - texture.minFilter = THREE.LinearFilter; + texture.wrapS = THREE.ClampToEdgeWrapping; + texture.wrapT = THREE.ClampToEdgeWrapping; + texture.magFilter = THREE.NearestFilter; + texture.minFilter = THREE.NearestFilter; texture.format = THREE.RGBAFormat; texture.type = THREE.UnsignedByteType; texture.needsUpdate = true; diff --git a/src/geom/material/heatmapMateial.js b/src/geom/material/heatmapMateial.js index 31e1064c37..c3ce362658 100644 --- a/src/geom/material/heatmapMateial.js +++ b/src/geom/material/heatmapMateial.js @@ -27,7 +27,8 @@ export function HeatmapColorizeMaterial(opt) { u_colorRamp: { value: opt.colorRamp } }, vertexShader: heatmap_colorize_vert, - fragmentShader: heatmap_colorize_frag + fragmentShader: heatmap_colorize_frag, + transparent: true }); return material; } diff --git a/src/geom/shader/heatmap_colorize_frag.glsl b/src/geom/shader/heatmap_colorize_frag.glsl index e408ca3852..e2c790b914 100644 --- a/src/geom/shader/heatmap_colorize_frag.glsl +++ b/src/geom/shader/heatmap_colorize_frag.glsl @@ -5,5 +5,5 @@ varying vec2 v_uv; void main(){ float intensity = texture2D(u_texture,v_uv).r; vec4 color = texture2D(u_colorRamp,vec2(0.5,1.0-intensity)); - gl_FragColor = color * intensity; + gl_FragColor = color; } \ No newline at end of file diff --git a/src/geom/shader/heatmap_intensity_frag.glsl b/src/geom/shader/heatmap_intensity_frag.glsl index a70f8dd848..de324a2cb8 100644 --- a/src/geom/shader/heatmap_intensity_frag.glsl +++ b/src/geom/shader/heatmap_intensity_frag.glsl @@ -1,4 +1,5 @@ precision highp float; +uniform float u_intensity; varying float v_weight; varying vec2 v_extrude; @@ -6,6 +7,6 @@ varying vec2 v_extrude; void main(){ float GAUSS_COEF = 0.3989422804014327; float d = -0.5 * 3.0 * 3.0 * dot(v_extrude, v_extrude); - float val = v_weight * 10.0 * GAUSS_COEF * exp(d); - gl_FragColor = vec4(val, val, val, 1.0); -} + float val = v_weight * u_intensity * GAUSS_COEF * exp(d); + gl_FragColor = vec4(val, val, val, val); +} \ No newline at end of file diff --git a/src/geom/shader/heatmap_intensity_vert.glsl b/src/geom/shader/heatmap_intensity_vert.glsl index 504355316b..b3d884c360 100644 --- a/src/geom/shader/heatmap_intensity_vert.glsl +++ b/src/geom/shader/heatmap_intensity_vert.glsl @@ -16,7 +16,7 @@ void main(){ vec2 extrude_dir = normalize(vec2(extrude_x,extrude_y)); float S = sqrt(-2.0 * log(ZERO / a_weight / u_intensity / GAUSS_COEF)) / 3.0; 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); gl_Position = projectionMatrix * modelViewMatrix * pos; } \ No newline at end of file diff --git a/src/layer/render/heatmap/heatmap.js b/src/layer/render/heatmap/heatmap.js index 02ab1063c0..3386cbbd5e 100644 --- a/src/layer/render/heatmap/heatmap.js +++ b/src/layer/render/heatmap/heatmap.js @@ -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); passOrth.position.set(bbox.minX + bbox.width / 2, bbox.minY + bbox.height / 2, 1000); // 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({ - renderer: layer.scene._engine._renderer, + renderer, camera: passOrth, size: { - width: 10000, - height: 10000 * (bbox.height / bbox.width) + width: 2000, + height: 2000 * (bbox.height / bbox.width) }, clear: { 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); @@ -56,8 +70,12 @@ function createIntensityPass(layer, bbox) { render(); function 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(); - mesh.material.uniforms.u_zoom.value = scene.getZoom(); } } function createColorizePass(layer, bbox) {