* feat: 增加 bloomPass1.0、修改渲染流程,让 multiPass 有正确的渲染顺序

* style: lint style
This commit is contained in:
YiQianYao 2022-02-08 15:56:12 +08:00 committed by GitHub
parent fd2788b893
commit a13b5ff2c8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 299 additions and 28 deletions

View File

@ -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)

View File

@ -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;

View File

@ -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;
}

View File

@ -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();
}
}
}

View File

@ -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);
});
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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) {

View File

@ -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 />)

View File

@ -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,
}}
/>
);
}
}

View File

@ -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;
/*** 运行时修改样式属性 ***/