mirror of https://gitee.com/antv-l7/antv-l7
Shihui (#952)
* feat: 增加 bloomPass1.0、修改渲染流程,让 multiPass 有正确的渲染顺序 * style: lint style
This commit is contained in:
parent
fd2788b893
commit
a13b5ff2c8
|
@ -51,6 +51,7 @@ import {
|
|||
import ClearPass from './services/renderer/passes/ClearPass';
|
||||
import MultiPassRenderer from './services/renderer/passes/MultiPassRenderer';
|
||||
import PixelPickingPass from './services/renderer/passes/PixelPickingPass';
|
||||
import BloomPass from './services/renderer/passes/post-processing/BloomPass';
|
||||
import BlurHPass from './services/renderer/passes/post-processing/BlurHPass';
|
||||
import BlurVPass from './services/renderer/passes/post-processing/BlurVPass';
|
||||
import ColorHalfTonePass from './services/renderer/passes/post-processing/ColorHalfTonePass';
|
||||
|
@ -221,6 +222,10 @@ export function createSceneContainer() {
|
|||
.bind<IPostProcessingPass<unknown>>(TYPES.IPostProcessingPass)
|
||||
.to(CopyPass)
|
||||
.whenTargetNamed('copy');
|
||||
sceneContainer
|
||||
.bind<IPostProcessingPass<unknown>>(TYPES.IPostProcessingPass)
|
||||
.to(BloomPass)
|
||||
.whenTargetNamed('bloom');
|
||||
sceneContainer
|
||||
.bind<IPostProcessingPass<unknown>>(TYPES.IPostProcessingPass)
|
||||
.to(BlurHPass)
|
||||
|
|
|
@ -199,6 +199,9 @@ export interface ILayer {
|
|||
// animate(field: string, option: any): ILayer;
|
||||
renderLayers(): void;
|
||||
render(): ILayer;
|
||||
|
||||
renderMultiPass(): any;
|
||||
|
||||
clear(): void;
|
||||
clearModels(): void;
|
||||
destroy(): void;
|
||||
|
|
|
@ -116,19 +116,31 @@ export default class LayerService implements ILayerService {
|
|||
this.enableRender = flag;
|
||||
}
|
||||
|
||||
public renderLayers() {
|
||||
public async renderLayers() {
|
||||
if (this.alreadyInRendering || !this.enableRender) {
|
||||
return;
|
||||
}
|
||||
this.alreadyInRendering = true;
|
||||
this.clear();
|
||||
|
||||
this.layerList.forEach((layer) => {
|
||||
for (const layer of this.layerList) {
|
||||
layer.hooks.beforeRenderData.call();
|
||||
layer.hooks.beforeRender.call();
|
||||
layer.render();
|
||||
if (layer.getLayerConfig().enableMultiPassRenderer) {
|
||||
// multiPassRender 不是同步渲染完成的
|
||||
await layer.renderMultiPass();
|
||||
} else {
|
||||
layer.render();
|
||||
}
|
||||
layer.hooks.afterRender.call();
|
||||
});
|
||||
}
|
||||
|
||||
// this.layerList.forEach((layer) => {
|
||||
// layer.hooks.beforeRenderData.call();
|
||||
// layer.hooks.beforeRender.call();
|
||||
// layer.render();
|
||||
// layer.hooks.afterRender.call();
|
||||
// });
|
||||
this.alreadyInRendering = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,12 +33,19 @@ export default class PostProcessor implements IPostProcessor {
|
|||
const pass = this.passes[i];
|
||||
// last pass should render to screen
|
||||
pass.setRenderToScreen(this.isLastEnabledPass(i));
|
||||
await pass.render(layer);
|
||||
|
||||
await pass.render(layer);
|
||||
// pingpong
|
||||
if (i !== this.passes.length - 1) {
|
||||
this.swap();
|
||||
}
|
||||
|
||||
if (pass.getName() === 'bloom') {
|
||||
await pass.render(layer);
|
||||
this.swap();
|
||||
await pass.render(layer);
|
||||
this.swap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,14 @@ export default class RenderPass<
|
|||
});
|
||||
// render to post processor
|
||||
layer.multiPassRenderer.setRenderFlag(false);
|
||||
layer.render();
|
||||
// layer.render();
|
||||
|
||||
layer.models.forEach((model) => {
|
||||
model.draw({
|
||||
uniforms: layer.layerModel.getUninforms(),
|
||||
});
|
||||
});
|
||||
|
||||
layer.multiPassRenderer.setRenderFlag(true);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
import { injectable } from 'inversify';
|
||||
import { isNil } from 'lodash';
|
||||
import 'reflect-metadata';
|
||||
import blur from '../../../../shaders/post-processing/bloom.glsl';
|
||||
import quad from '../../../../shaders/post-processing/quad.glsl';
|
||||
import { IUniform } from '../../IUniform';
|
||||
import BasePostProcessingPass from '../BasePostProcessingPass';
|
||||
|
||||
export interface IBloomPassConfig {
|
||||
bloomRadius: number;
|
||||
}
|
||||
|
||||
@injectable()
|
||||
export default class BloomPass extends BasePostProcessingPass<
|
||||
IBloomPassConfig
|
||||
> {
|
||||
protected setupShaders() {
|
||||
this.shaderModuleService.registerModule('blur-pass', {
|
||||
vs: quad,
|
||||
fs: blur,
|
||||
});
|
||||
|
||||
const { vs, fs, uniforms } = this.shaderModuleService.getModule(
|
||||
'blur-pass',
|
||||
);
|
||||
const { width, height } = this.rendererService.getViewportSize();
|
||||
|
||||
return {
|
||||
vs,
|
||||
fs,
|
||||
uniforms: {
|
||||
...uniforms,
|
||||
u_ViewportSize: [width, height],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected convertOptionsToUniforms(
|
||||
options: Partial<IBloomPassConfig>,
|
||||
): {
|
||||
[uniformName: string]: IUniform;
|
||||
} | void {
|
||||
const uniforms: {
|
||||
[key: string]: IUniform;
|
||||
} = {};
|
||||
|
||||
if (!isNil(options.bloomRadius)) {
|
||||
uniforms.u_radius = options.bloomRadius;
|
||||
}
|
||||
|
||||
return uniforms;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
varying vec2 v_UV;
|
||||
|
||||
uniform sampler2D u_Texture;
|
||||
|
||||
uniform vec2 u_ViewportSize: [1.0, 1.0];
|
||||
uniform float u_radius: 5.0;
|
||||
|
||||
// https://github.com/Jam3/glsl-fast-gaussian-blur/blob/master/9.glsl
|
||||
vec4 blur9(sampler2D image, vec2 uv, vec2 resolution, vec2 direction) {
|
||||
vec4 color = vec4(0.0);
|
||||
vec2 off1 = vec2(1.3846153846) * direction;
|
||||
vec2 off2 = vec2(3.2307692308) * direction;
|
||||
color += texture2D(image, uv) * 0.2270270270;
|
||||
color += texture2D(image, uv + (off1 / resolution)) * 0.3162162162;
|
||||
color += texture2D(image, uv - (off1 / resolution)) * 0.3162162162;
|
||||
color += texture2D(image, uv + (off2 / resolution)) * 0.0702702703;
|
||||
color += texture2D(image, uv - (off2 / resolution)) * 0.0702702703;
|
||||
return color;
|
||||
}
|
||||
|
||||
void main() {
|
||||
float r = sqrt(u_radius);
|
||||
|
||||
vec4 c1 = blur9(u_Texture, v_UV, u_ViewportSize, vec2(u_radius, 0.0));
|
||||
vec4 c2 = blur9(u_Texture, v_UV, u_ViewportSize, vec2(0.0, u_radius));
|
||||
vec4 c3 = blur9(u_Texture, v_UV, u_ViewportSize, vec2(r, r));
|
||||
vec4 c4 = blur9(u_Texture, v_UV, u_ViewportSize, vec2(r, -r));
|
||||
vec4 inbloomColor = c1 * 0.25 + c2 * 0.25 + c3 * 0.25 + c4 * 0.25;
|
||||
|
||||
|
||||
|
||||
float h = 0.01;
|
||||
vec4 baseColor = texture2D(u_Texture, v_UV);
|
||||
|
||||
vec4 color11 = texture2D( u_Texture, vec2( v_UV.x - 1.0 * h, v_UV.y + 1.0 * h) );
|
||||
vec4 color12 = texture2D( u_Texture, vec2( v_UV.x - 0.0 * h, v_UV.y + 1.0 * h) );
|
||||
vec4 color13 = texture2D( u_Texture, vec2( v_UV.x + 1.0 * h, v_UV.y + 1.0 * h) );
|
||||
|
||||
vec4 color21 = texture2D( u_Texture, vec2( v_UV.x - 1.0 * h, v_UV.y) );
|
||||
vec4 color23 = texture2D( u_Texture, vec2( v_UV.x + 1.0 * h, v_UV.y) );
|
||||
|
||||
vec4 color31 = texture2D( u_Texture, vec2( v_UV.x - 1.0 * h, v_UV.y-1.0*h) );
|
||||
vec4 color32 = texture2D( u_Texture, vec2( v_UV.x - 0.0 * h, v_UV.y-1.0*h) );
|
||||
vec4 color33 = texture2D( u_Texture, vec2( v_UV.x + 1.0 * h, v_UV.y-1.0*h) );
|
||||
|
||||
vec4 bloomColor =
|
||||
color11 +
|
||||
color12 +
|
||||
color13 +
|
||||
color21 +
|
||||
color21 +
|
||||
color23 +
|
||||
color31 +
|
||||
color32 +
|
||||
color33;
|
||||
|
||||
if(baseColor.a > 0.0) {
|
||||
|
||||
gl_FragColor.r = min(bloomColor.r, baseColor.r);
|
||||
gl_FragColor.g = min(bloomColor.g, baseColor.g);
|
||||
gl_FragColor.b = min(bloomColor.b, baseColor.b);
|
||||
gl_FragColor.a = min(bloomColor.a, baseColor.a);
|
||||
|
||||
gl_FragColor = mix(inbloomColor, gl_FragColor, 0.7);
|
||||
} else {
|
||||
gl_FragColor = bloomColor/9.0;
|
||||
}
|
||||
}
|
|
@ -560,37 +560,28 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
|
|||
}
|
||||
|
||||
public render(): ILayer {
|
||||
// if (
|
||||
// this.needPick() &&
|
||||
// this.multiPassRenderer &&
|
||||
// this.multiPassRenderer.getRenderFlag()
|
||||
// ) {
|
||||
// this.multiPassRenderer.render();
|
||||
// } else if (this.needPick() && this.multiPassRenderer) {
|
||||
// this.renderModels();
|
||||
// } else {
|
||||
// this.renderModels();
|
||||
// }
|
||||
|
||||
// TODO: this.getEncodedData().length !== 0 这个判断是为了解决在 2.5.x 引入数据纹理后产生的 空数据渲染导致 texture 超出上限问题
|
||||
if (this.getEncodedData().length !== 0) {
|
||||
this.renderModels();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* renderMultiPass 专门用于渲染支持 multipass 的 layer
|
||||
*/
|
||||
public async renderMultiPass() {
|
||||
if (this.getEncodedData().length !== 0) {
|
||||
if (this.multiPassRenderer && this.multiPassRenderer.getRenderFlag()) {
|
||||
// multi render 开始执行 multiPassRender 的渲染流程
|
||||
this.multiPassRenderer.render();
|
||||
await this.multiPassRenderer.render();
|
||||
} else if (this.multiPassRenderer) {
|
||||
// renderPass 触发的渲染
|
||||
this.renderModels();
|
||||
} else {
|
||||
this.renderModels();
|
||||
}
|
||||
|
||||
// this.renderModels();
|
||||
}
|
||||
// this.renderModels();
|
||||
|
||||
// this.multiPassRenderer.render();
|
||||
// this.renderModels();
|
||||
return this;
|
||||
}
|
||||
|
||||
public active(options: IActiveOption | boolean) {
|
||||
|
@ -1025,6 +1016,10 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
|
|||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
public async renderMulPass(multiPassRenderer: IMultiPassRenderer) {
|
||||
await multiPassRenderer.render();
|
||||
}
|
||||
|
||||
public renderModels(isPicking?: boolean) {
|
||||
// TODO: this.getEncodedData().length > 0 这个判断是为了解决在 2.5.x 引入数据纹理后产生的 空数据渲染导致 texture 超出上限问题
|
||||
if (this.getEncodedData().length > 0) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { storiesOf } from '@storybook/react';
|
||||
import * as React from 'react';
|
||||
import Bloom from './components/Bloom';
|
||||
import Blur from './components/Blur';
|
||||
import ColorHalftone from './components/ColorHalftone';
|
||||
import CustomPostProcessing from './components/CustomPostProcessing';
|
||||
|
@ -13,6 +14,7 @@ storiesOf('MultiPassRenderer', module)
|
|||
.add('ColorHalftone', () => <ColorHalftone />)
|
||||
.add('HexagonalPixelate', () => <HexagonalPixelate />)
|
||||
.add('Ink', () => <Ink />)
|
||||
.add('Bloom', () => <Bloom />)
|
||||
.add('Blur', () => <Blur />)
|
||||
.add('Noise', () => <Noise />)
|
||||
.add('Sepia', () => <Sepia />)
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
import { PolygonLayer, PointLayer, Scene } from '@antv/l7';
|
||||
import { Mapbox } from '@antv/l7-maps';
|
||||
import * as dat from 'dat.gui';
|
||||
import * as React from 'react';
|
||||
|
||||
export default class Bloom extends React.Component {
|
||||
private gui: dat.GUI;
|
||||
private $stats: Node;
|
||||
private scene: Scene;
|
||||
|
||||
public componentWillUnmount() {
|
||||
if (this.gui) {
|
||||
this.gui.destroy();
|
||||
}
|
||||
if (this.$stats) {
|
||||
document.body.removeChild(this.$stats);
|
||||
}
|
||||
this.scene.destroy();
|
||||
}
|
||||
|
||||
public async componentDidMount() {
|
||||
const response = await fetch(
|
||||
'https://gw.alipayobjects.com/os/basement_prod/d2e0e930-fd44-4fca-8872-c1037b0fee7b.json',
|
||||
);
|
||||
const data = await response.json();
|
||||
const scene = new Scene({
|
||||
id: 'map',
|
||||
map: new Mapbox({
|
||||
// style: 'mapbox://styles/mapbox/streets-v9',
|
||||
style: 'blank',
|
||||
center: [110.19382669582967, 50.258134],
|
||||
pitch: 0,
|
||||
zoom: 3,
|
||||
}),
|
||||
});
|
||||
scene.setBgColor('#000');
|
||||
const layer = new PolygonLayer({
|
||||
zIndex: 0,
|
||||
// enablePicking: true,
|
||||
// enableHighlight: true,
|
||||
enableMultiPassRenderer: true,
|
||||
passes: [
|
||||
[
|
||||
'bloom',
|
||||
{
|
||||
bloomRadius: 8,
|
||||
},
|
||||
],
|
||||
],
|
||||
});
|
||||
|
||||
layer
|
||||
.source(data)
|
||||
.size('name', [0, 10000, 50000, 30000, 100000])
|
||||
.color('name', [
|
||||
'#2E8AE6',
|
||||
'#69D1AB',
|
||||
'#DAF291',
|
||||
'#FFD591',
|
||||
'#FF7A45',
|
||||
'#CF1D49',
|
||||
])
|
||||
.shape('fill')
|
||||
.active(true)
|
||||
.style({
|
||||
// opacity: 0.8,
|
||||
});
|
||||
|
||||
scene.addLayer(layer);
|
||||
|
||||
let pointLayer = new PointLayer({ zIndex: 1 })
|
||||
.source([{ lng: 122, lat: 30 }], {
|
||||
parser: {
|
||||
type: 'json',
|
||||
x: 'lng',
|
||||
y: 'lat',
|
||||
},
|
||||
})
|
||||
.shape('circle')
|
||||
.size(20)
|
||||
.color('red');
|
||||
scene.addLayer(pointLayer);
|
||||
|
||||
this.scene = scene;
|
||||
}
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<div
|
||||
id="map"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -33,8 +33,8 @@ export default class Blur extends React.Component {
|
|||
}),
|
||||
});
|
||||
const layer = new PolygonLayer({
|
||||
enablePicking: true,
|
||||
enableHighlight: true,
|
||||
// enablePicking: true,
|
||||
// enableHighlight: true,
|
||||
enableMultiPassRenderer: true,
|
||||
passes: [
|
||||
[
|
||||
|
@ -64,12 +64,30 @@ export default class Blur extends React.Component {
|
|||
'#CF1D49',
|
||||
])
|
||||
.shape('fill')
|
||||
.active(true)
|
||||
.style({
|
||||
opacity: 0.8,
|
||||
});
|
||||
|
||||
scene.addLayer(layer);
|
||||
|
||||
// const layer2 = new PolygonLayer()
|
||||
// .source(data)
|
||||
// .size('name', [0, 10000, 50000, 30000, 100000])
|
||||
// .color('name', [
|
||||
// '#2E8AE6',
|
||||
// '#69D1AB',
|
||||
// '#DAF291',
|
||||
// '#FFD591',
|
||||
// '#FF7A45',
|
||||
// '#CF1D49',
|
||||
// ])
|
||||
// .shape('fill')
|
||||
// .style({
|
||||
// opacity: 0.8,
|
||||
// });
|
||||
// scene.addLayer(layer2);
|
||||
|
||||
this.scene = scene;
|
||||
|
||||
/*** 运行时修改样式属性 ***/
|
||||
|
|
Loading…
Reference in New Issue