mirror of https://gitee.com/antv-l7/antv-l7
Shihui (#955)
* feat: 优化后处理 bloom 的效果 * feat: 修改交替绘制 bloom 的写法 * style: lint style
This commit is contained in:
parent
556f9c5c75
commit
ef1d867ba7
|
@ -1,5 +1,6 @@
|
||||||
import { ILayer } from '../layer/ILayerService';
|
import { ILayer } from '../layer/ILayerService';
|
||||||
import { IFramebuffer } from './IFramebuffer';
|
import { IFramebuffer } from './IFramebuffer';
|
||||||
|
import { ITexture2D } from './ITexture2D';
|
||||||
|
|
||||||
export enum PassType {
|
export enum PassType {
|
||||||
Normal = 'normal',
|
Normal = 'normal',
|
||||||
|
@ -16,7 +17,7 @@ export interface IPass<InitializationOptions> {
|
||||||
getName(): string;
|
getName(): string;
|
||||||
getType(): PassType;
|
getType(): PassType;
|
||||||
init(layer: ILayer, config?: Partial<InitializationOptions>): void;
|
init(layer: ILayer, config?: Partial<InitializationOptions>): void;
|
||||||
render(layer: ILayer): void;
|
render(layer: ILayer, tex?: ITexture2D): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -76,6 +76,19 @@ export interface ITexture2DInitializationOptions {
|
||||||
colorSpace?: gl.NONE | gl.BROWSER_DEFAULT_WEBGL;
|
colorSpace?: gl.NONE | gl.BROWSER_DEFAULT_WEBGL;
|
||||||
|
|
||||||
mipmap?: boolean | gl.DONT_CARE | gl.NICEST | gl.FASTEST;
|
mipmap?: boolean | gl.DONT_CARE | gl.NICEST | gl.FASTEST;
|
||||||
|
|
||||||
|
/* 是否复制当前的 framebuffer */
|
||||||
|
x?: number;
|
||||||
|
y?: number;
|
||||||
|
copy?: boolean;
|
||||||
|
// From the pixels in the current frame buffer
|
||||||
|
// var copyPixels = regl.texture({
|
||||||
|
// x: 5,
|
||||||
|
// y: 1,
|
||||||
|
// width: 10,
|
||||||
|
// height: 10,
|
||||||
|
// copy: true
|
||||||
|
// })
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ITexture2D {
|
export interface ITexture2D {
|
||||||
|
|
|
@ -10,6 +10,7 @@ import quad from '../../../shaders/post-processing/quad.glsl';
|
||||||
import { TYPES } from '../../../types';
|
import { TYPES } from '../../../types';
|
||||||
import { ILayer } from '../../layer/ILayerService';
|
import { ILayer } from '../../layer/ILayerService';
|
||||||
import { IPostProcessingPass, PassType } from '../IMultiPassRenderer';
|
import { IPostProcessingPass, PassType } from '../IMultiPassRenderer';
|
||||||
|
import { ITexture2D } from '../ITexture2D';
|
||||||
import { IUniform } from '../IUniform';
|
import { IUniform } from '../IUniform';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -106,7 +107,7 @@ export default class BasePostProcessingPass<InitializationOptions = {}>
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public render(layer: ILayer) {
|
public render(layer: ILayer, tex?: ITexture2D) {
|
||||||
const postProcessor = layer.multiPassRenderer.getPostProcessor();
|
const postProcessor = layer.multiPassRenderer.getPostProcessor();
|
||||||
const { useFramebuffer, getViewportSize, clear } = this.rendererService;
|
const { useFramebuffer, getViewportSize, clear } = this.rendererService;
|
||||||
const { width, height } = getViewportSize();
|
const { width, height } = getViewportSize();
|
||||||
|
@ -119,12 +120,20 @@ export default class BasePostProcessingPass<InitializationOptions = {}>
|
||||||
depth: 1,
|
depth: 1,
|
||||||
stencil: 0,
|
stencil: 0,
|
||||||
});
|
});
|
||||||
this.model.draw({
|
|
||||||
uniforms: {
|
const uniformOptions: { [key: string]: any } = {
|
||||||
|
u_BloomFinal: 0.0,
|
||||||
u_Texture: postProcessor.getReadFBO(),
|
u_Texture: postProcessor.getReadFBO(),
|
||||||
|
// u_Texture: tex ? tex : postProcessor.getReadFBO(),
|
||||||
u_ViewportSize: [width, height],
|
u_ViewportSize: [width, height],
|
||||||
...this.convertOptionsToUniforms(this.optionsToUpdate),
|
...this.convertOptionsToUniforms(this.optionsToUpdate),
|
||||||
},
|
};
|
||||||
|
if (tex) {
|
||||||
|
uniformOptions.u_BloomFinal = 1.0;
|
||||||
|
uniformOptions.u_Texture2 = tex;
|
||||||
|
}
|
||||||
|
this.model.draw({
|
||||||
|
uniforms: uniformOptions,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { gl } from '../gl';
|
||||||
import { IFramebuffer } from '../IFramebuffer';
|
import { IFramebuffer } from '../IFramebuffer';
|
||||||
import { IPostProcessingPass, IPostProcessor } from '../IMultiPassRenderer';
|
import { IPostProcessingPass, IPostProcessor } from '../IMultiPassRenderer';
|
||||||
import { IRendererService } from '../IRendererService';
|
import { IRendererService } from '../IRendererService';
|
||||||
|
import { ITexture2D } from '../ITexture2D';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ported from Three.js EffectComposer
|
* ported from Three.js EffectComposer
|
||||||
|
@ -28,24 +29,69 @@ export default class PostProcessor implements IPostProcessor {
|
||||||
return this.writeFBO;
|
return this.writeFBO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从当前的 framebuffer 中获取贴图
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
public getCurrentFBOTex() {
|
||||||
|
const { getViewportSize, createTexture2D } = this.rendererService;
|
||||||
|
const { width, height } = getViewportSize();
|
||||||
|
return createTexture2D({
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
copy: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从 readFBO 中获取贴图
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
public getReadFBOTex() {
|
||||||
|
const { useFramebuffer } = this.rendererService;
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
useFramebuffer(this.readFBO, async () => {
|
||||||
|
resolve(this.getCurrentFBOTex());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async renderBloomPass(
|
||||||
|
layer: ILayer,
|
||||||
|
pass: IPostProcessingPass<unknown>,
|
||||||
|
) {
|
||||||
|
const tex = (await this.getReadFBOTex()) as ITexture2D;
|
||||||
|
// count 定义 bloom 交替绘制的次数
|
||||||
|
let count = 0;
|
||||||
|
while (count < 4) {
|
||||||
|
await pass.render(layer, tex);
|
||||||
|
this.swap();
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async render(layer: ILayer) {
|
public async render(layer: ILayer) {
|
||||||
for (let i = 0; i < this.passes.length; i++) {
|
for (let i = 0; i < this.passes.length; i++) {
|
||||||
const pass = this.passes[i];
|
const pass = this.passes[i];
|
||||||
// last pass should render to screen
|
// last pass should render to screen
|
||||||
pass.setRenderToScreen(this.isLastEnabledPass(i));
|
pass.setRenderToScreen(this.isLastEnabledPass(i));
|
||||||
|
|
||||||
|
// await pass.render(layer);
|
||||||
|
// // pingpong
|
||||||
|
// if (i !== this.passes.length - 1) {
|
||||||
|
// this.swap();
|
||||||
|
// }
|
||||||
|
if (pass.getName() === 'bloom') {
|
||||||
|
await this.renderBloomPass(layer, pass);
|
||||||
|
} else {
|
||||||
await pass.render(layer);
|
await pass.render(layer);
|
||||||
// pingpong
|
// pingpong
|
||||||
if (i !== this.passes.length - 1) {
|
if (i !== this.passes.length - 1) {
|
||||||
this.swap();
|
this.swap();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// if (pass.getName() === 'bloom') {
|
|
||||||
// await pass.render(layer);
|
|
||||||
// this.swap();
|
|
||||||
// await pass.render(layer);
|
|
||||||
// this.swap();
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,9 @@ import { IUniform } from '../../IUniform';
|
||||||
import BasePostProcessingPass from '../BasePostProcessingPass';
|
import BasePostProcessingPass from '../BasePostProcessingPass';
|
||||||
|
|
||||||
export interface IBloomPassConfig {
|
export interface IBloomPassConfig {
|
||||||
|
bloomBaseRadio: number;
|
||||||
bloomRadius: number;
|
bloomRadius: number;
|
||||||
|
bloomIntensity: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
|
@ -47,6 +49,12 @@ export default class BloomPass extends BasePostProcessingPass<
|
||||||
if (!isNil(options.bloomRadius)) {
|
if (!isNil(options.bloomRadius)) {
|
||||||
uniforms.u_radius = options.bloomRadius;
|
uniforms.u_radius = options.bloomRadius;
|
||||||
}
|
}
|
||||||
|
if (!isNil(options.bloomIntensity)) {
|
||||||
|
uniforms.u_intensity = options.bloomIntensity;
|
||||||
|
}
|
||||||
|
if (!isNil(options.bloomBaseRadio)) {
|
||||||
|
uniforms.u_baseRadio = options.bloomBaseRadio;
|
||||||
|
}
|
||||||
|
|
||||||
return uniforms;
|
return uniforms;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
varying vec2 v_UV;
|
varying vec2 v_UV;
|
||||||
|
|
||||||
|
uniform float u_BloomFinal: 0.0;
|
||||||
uniform sampler2D u_Texture;
|
uniform sampler2D u_Texture;
|
||||||
|
uniform sampler2D u_Texture2;
|
||||||
|
|
||||||
uniform vec2 u_ViewportSize: [1.0, 1.0];
|
uniform vec2 u_ViewportSize: [1.0, 1.0];
|
||||||
uniform float u_radius: 5.0;
|
uniform float u_radius: 5.0;
|
||||||
|
uniform float u_intensity: 0.3;
|
||||||
|
uniform float u_baseRadio: 0.5;
|
||||||
|
|
||||||
// https://github.com/Jam3/glsl-fast-gaussian-blur/blob/master/9.glsl
|
// https://github.com/Jam3/glsl-fast-gaussian-blur/blob/master/9.glsl
|
||||||
vec4 blur9(sampler2D image, vec2 uv, vec2 resolution, vec2 direction) {
|
vec4 blur9(sampler2D image, vec2 uv, vec2 resolution, vec2 direction) {
|
||||||
|
@ -18,51 +22,97 @@ vec4 blur9(sampler2D image, vec2 uv, vec2 resolution, vec2 direction) {
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float luminance(vec4 color) {
|
||||||
|
return 0.2125 * color.r + 0.7154 * color.g + 0.0721 * color.b;
|
||||||
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
// vec4 baseColor = texture2D(u_Texture, v_UV);
|
||||||
|
// float lum = luminance(baseColor);
|
||||||
|
// baseColor.a *= lum;
|
||||||
|
|
||||||
|
// gl_FragColor = baseColor;
|
||||||
|
|
||||||
|
// if(u_BloomFinal > 0.0) { //
|
||||||
|
// gl_FragColor = baseColor; //--
|
||||||
|
// }
|
||||||
|
|
||||||
float r = sqrt(u_radius);
|
float r = sqrt(u_radius);
|
||||||
|
|
||||||
vec4 c1 = blur9(u_Texture, v_UV, u_ViewportSize, vec2(u_radius, 0.0));
|
vec4 c1 = blur9(u_Texture, v_UV, u_ViewportSize, vec2(u_radius, 0.0));
|
||||||
|
// c1 *= luminance(c1);
|
||||||
vec4 c2 = blur9(u_Texture, v_UV, u_ViewportSize, vec2(0.0, u_radius));
|
vec4 c2 = blur9(u_Texture, v_UV, u_ViewportSize, vec2(0.0, u_radius));
|
||||||
|
// c2 *= luminance(c2);
|
||||||
vec4 c3 = blur9(u_Texture, v_UV, u_ViewportSize, vec2(r, r));
|
vec4 c3 = blur9(u_Texture, v_UV, u_ViewportSize, vec2(r, r));
|
||||||
|
// c3 *= luminance(c3);
|
||||||
vec4 c4 = 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;
|
// c4 *= luminance(c4);
|
||||||
|
vec4 inbloomColor = (c1 + c2 + c3 + c4) * 0.25;
|
||||||
|
|
||||||
|
// float lum = luminance(inbloomColor);
|
||||||
|
// inbloomColor.rgb *= lum;
|
||||||
|
|
||||||
|
if(u_BloomFinal > 0.0) {
|
||||||
|
vec4 baseColor = texture2D(u_Texture2, v_UV);
|
||||||
|
float baselum = luminance(baseColor);
|
||||||
|
// float lum = luminance(inbloomColor);
|
||||||
|
// vec4 bloom = vec4(lum);
|
||||||
|
// inbloomColor.a *= lum;
|
||||||
|
// gl_FragColor = inbloomColor * u_intensity + texture2D(u_Texture2, v_UV);
|
||||||
|
// gl_FragColor = inbloomColor * 0.5 + texture2D(u_Texture2, v_UV);
|
||||||
|
// gl_FragColor = baseColor;
|
||||||
|
// gl_FragColor = inbloomColor;
|
||||||
|
// vec4 mixColor = mix(baseColor, inbloomColor, max(u_intensity - 0.3, 0.0));
|
||||||
|
// mixColor.a = max(baseColor.a, mixColor.a);
|
||||||
|
gl_FragColor = mix(inbloomColor, baseColor, max(1.0 - u_intensity, u_baseRadio));
|
||||||
|
// gl_FragColor = mixColor;
|
||||||
|
// gl_FragColor = baseColor;
|
||||||
|
|
||||||
float h = 0.01;
|
if(baselum <= 0.0) {
|
||||||
vec4 baseColor = texture2D(u_Texture, v_UV);
|
// float lum = luminance(inbloomColor);
|
||||||
|
// inbloomColor.rgb *= lum;
|
||||||
vec4 color11 = texture2D( u_Texture, vec2( v_UV.x - 1.0 * h, v_UV.y + 1.0 * h) );
|
gl_FragColor += inbloomColor * u_intensity;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
// gl_FragColor = inbloomColor * baseColor + baseColor;
|
||||||
|
// gl_FragColor = baseColor + bloom * 0.5;
|
||||||
|
} else {
|
||||||
|
gl_FragColor = inbloomColor;
|
||||||
|
}
|
||||||
|
// gl_FragColor = inbloomColor;
|
||||||
|
|
||||||
|
// float h = 0.01;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
// }
|
||||||
}
|
}
|
|
@ -36,6 +36,9 @@ export default class ReglTexture2D implements ITexture2D {
|
||||||
mag = gl.NEAREST,
|
mag = gl.NEAREST,
|
||||||
min = gl.NEAREST,
|
min = gl.NEAREST,
|
||||||
colorSpace = gl.BROWSER_DEFAULT_WEBGL,
|
colorSpace = gl.BROWSER_DEFAULT_WEBGL,
|
||||||
|
x = 0,
|
||||||
|
y = 0,
|
||||||
|
copy = false,
|
||||||
} = options;
|
} = options;
|
||||||
this.width = width;
|
this.width = width;
|
||||||
this.height = height;
|
this.height = height;
|
||||||
|
@ -56,6 +59,11 @@ export default class ReglTexture2D implements ITexture2D {
|
||||||
colorSpace: colorSpaceMap[colorSpace],
|
colorSpace: colorSpaceMap[colorSpace],
|
||||||
premultiplyAlpha,
|
premultiplyAlpha,
|
||||||
aniso,
|
aniso,
|
||||||
|
|
||||||
|
// copy pixels from current bind framebuffer
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
copy,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
|
|
|
@ -26,14 +26,14 @@ export default class Bloom extends React.Component {
|
||||||
const scene = new Scene({
|
const scene = new Scene({
|
||||||
id: 'map',
|
id: 'map',
|
||||||
map: new Mapbox({
|
map: new Mapbox({
|
||||||
// style: 'mapbox://styles/mapbox/streets-v9',
|
style: 'mapbox://styles/mapbox/streets-v9',
|
||||||
style: 'blank',
|
// style: 'blank',
|
||||||
center: [110.19382669582967, 50.258134],
|
center: [110.19382669582967, 50.258134],
|
||||||
pitch: 0,
|
pitch: 0,
|
||||||
zoom: 3,
|
zoom: 3,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
scene.setBgColor('#000');
|
// scene.setBgColor('#000');
|
||||||
const layer = new PolygonLayer({
|
const layer = new PolygonLayer({
|
||||||
zIndex: 0,
|
zIndex: 0,
|
||||||
// enablePicking: true,
|
// enablePicking: true,
|
||||||
|
@ -43,7 +43,9 @@ export default class Bloom extends React.Component {
|
||||||
[
|
[
|
||||||
'bloom',
|
'bloom',
|
||||||
{
|
{
|
||||||
bloomRadius: 8,
|
// bloomBaseRadio: 0.5,
|
||||||
|
bloomRadius: 25,
|
||||||
|
bloomIntensity: 1,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
|
Loading…
Reference in New Issue