diff --git a/packages/core/src/services/renderer/IMultiPassRenderer.ts b/packages/core/src/services/renderer/IMultiPassRenderer.ts index b4ad1a4494..692a9e42f7 100644 --- a/packages/core/src/services/renderer/IMultiPassRenderer.ts +++ b/packages/core/src/services/renderer/IMultiPassRenderer.ts @@ -1,5 +1,6 @@ import { ILayer } from '../layer/ILayerService'; import { IFramebuffer } from './IFramebuffer'; +import { ITexture2D } from './ITexture2D'; export enum PassType { Normal = 'normal', @@ -16,7 +17,7 @@ export interface IPass { getName(): string; getType(): PassType; init(layer: ILayer, config?: Partial): void; - render(layer: ILayer): void; + render(layer: ILayer, tex?: ITexture2D): void; } /** diff --git a/packages/core/src/services/renderer/ITexture2D.ts b/packages/core/src/services/renderer/ITexture2D.ts index 3c4cb7d3bf..2e7f556f71 100644 --- a/packages/core/src/services/renderer/ITexture2D.ts +++ b/packages/core/src/services/renderer/ITexture2D.ts @@ -76,6 +76,19 @@ export interface ITexture2DInitializationOptions { colorSpace?: gl.NONE | gl.BROWSER_DEFAULT_WEBGL; 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 { diff --git a/packages/core/src/services/renderer/passes/BasePostProcessingPass.ts b/packages/core/src/services/renderer/passes/BasePostProcessingPass.ts index 998ca2ce74..ec9ffa2a75 100644 --- a/packages/core/src/services/renderer/passes/BasePostProcessingPass.ts +++ b/packages/core/src/services/renderer/passes/BasePostProcessingPass.ts @@ -10,6 +10,7 @@ import quad from '../../../shaders/post-processing/quad.glsl'; import { TYPES } from '../../../types'; import { ILayer } from '../../layer/ILayerService'; import { IPostProcessingPass, PassType } from '../IMultiPassRenderer'; +import { ITexture2D } from '../ITexture2D'; import { IUniform } from '../IUniform'; /** @@ -106,7 +107,7 @@ export default class BasePostProcessingPass }); } - public render(layer: ILayer) { + public render(layer: ILayer, tex?: ITexture2D) { const postProcessor = layer.multiPassRenderer.getPostProcessor(); const { useFramebuffer, getViewportSize, clear } = this.rendererService; const { width, height } = getViewportSize(); @@ -119,12 +120,20 @@ export default class BasePostProcessingPass depth: 1, stencil: 0, }); + + const uniformOptions: { [key: string]: any } = { + u_BloomFinal: 0.0, + u_Texture: postProcessor.getReadFBO(), + // u_Texture: tex ? tex : postProcessor.getReadFBO(), + u_ViewportSize: [width, height], + ...this.convertOptionsToUniforms(this.optionsToUpdate), + }; + if (tex) { + uniformOptions.u_BloomFinal = 1.0; + uniformOptions.u_Texture2 = tex; + } this.model.draw({ - uniforms: { - u_Texture: postProcessor.getReadFBO(), - u_ViewportSize: [width, height], - ...this.convertOptionsToUniforms(this.optionsToUpdate), - }, + uniforms: uniformOptions, }); }, ); diff --git a/packages/core/src/services/renderer/passes/PostProcessor.ts b/packages/core/src/services/renderer/passes/PostProcessor.ts index cf3b4cb66e..9514a8a538 100644 --- a/packages/core/src/services/renderer/passes/PostProcessor.ts +++ b/packages/core/src/services/renderer/passes/PostProcessor.ts @@ -6,6 +6,7 @@ import { gl } from '../gl'; import { IFramebuffer } from '../IFramebuffer'; import { IPostProcessingPass, IPostProcessor } from '../IMultiPassRenderer'; import { IRendererService } from '../IRendererService'; +import { ITexture2D } from '../ITexture2D'; /** * ported from Three.js EffectComposer @@ -28,24 +29,69 @@ export default class PostProcessor implements IPostProcessor { 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, + ) { + 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) { for (let i = 0; i < this.passes.length; i++) { const pass = this.passes[i]; // last pass should render to screen pass.setRenderToScreen(this.isLastEnabledPass(i)); - 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); + // 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); + // pingpong + if (i !== this.passes.length - 1) { + this.swap(); + } + } } } diff --git a/packages/core/src/services/renderer/passes/post-processing/BloomPass.ts b/packages/core/src/services/renderer/passes/post-processing/BloomPass.ts index 68ef839621..0775ae3bcc 100644 --- a/packages/core/src/services/renderer/passes/post-processing/BloomPass.ts +++ b/packages/core/src/services/renderer/passes/post-processing/BloomPass.ts @@ -7,7 +7,9 @@ import { IUniform } from '../../IUniform'; import BasePostProcessingPass from '../BasePostProcessingPass'; export interface IBloomPassConfig { + bloomBaseRadio: number; bloomRadius: number; + bloomIntensity: number; } @injectable() @@ -47,6 +49,12 @@ export default class BloomPass extends BasePostProcessingPass< if (!isNil(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; } diff --git a/packages/core/src/shaders/post-processing/bloom.glsl b/packages/core/src/shaders/post-processing/bloom.glsl index 3fcc3007a9..4e2a57e15c 100644 --- a/packages/core/src/shaders/post-processing/bloom.glsl +++ b/packages/core/src/shaders/post-processing/bloom.glsl @@ -1,9 +1,13 @@ varying vec2 v_UV; +uniform float u_BloomFinal: 0.0; uniform sampler2D u_Texture; +uniform sampler2D u_Texture2; uniform vec2 u_ViewportSize: [1.0, 1.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 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; } +float luminance(vec4 color) { + return 0.2125 * color.r + 0.7154 * color.g + 0.0721 * color.b; +} + 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); 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)); + // c2 *= luminance(c2); 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 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; + + if(baselum <= 0.0) { + // float lum = luminance(inbloomColor); + // inbloomColor.rgb *= lum; + gl_FragColor += inbloomColor * u_intensity; + } + // gl_FragColor = inbloomColor * baseColor + baseColor; + // gl_FragColor = baseColor + bloom * 0.5; + } else { + gl_FragColor = inbloomColor; + } + // gl_FragColor = inbloomColor; - float h = 0.01; - vec4 baseColor = texture2D(u_Texture, v_UV); + // 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 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 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 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; - vec4 bloomColor = - color11 + - color12 + - color13 + - color21 + - color21 + - color23 + - color31 + - color32 + - color33; - - if(baseColor.a > 0.0) { + // 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.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 = mix(inbloomColor, gl_FragColor, 0.7); + // } else { + // gl_FragColor = bloomColor/9.0; + // } } \ No newline at end of file diff --git a/packages/renderer/src/regl/ReglTexture2D.ts b/packages/renderer/src/regl/ReglTexture2D.ts index f9c8dff253..28fcbfd424 100644 --- a/packages/renderer/src/regl/ReglTexture2D.ts +++ b/packages/renderer/src/regl/ReglTexture2D.ts @@ -36,6 +36,9 @@ export default class ReglTexture2D implements ITexture2D { mag = gl.NEAREST, min = gl.NEAREST, colorSpace = gl.BROWSER_DEFAULT_WEBGL, + x = 0, + y = 0, + copy = false, } = options; this.width = width; this.height = height; @@ -56,6 +59,11 @@ export default class ReglTexture2D implements ITexture2D { colorSpace: colorSpaceMap[colorSpace], premultiplyAlpha, aniso, + + // copy pixels from current bind framebuffer + x, + y, + copy, }; if (data) { diff --git a/stories/MultiPassRenderer/components/Bloom.tsx b/stories/MultiPassRenderer/components/Bloom.tsx index 8c86fe6769..df94d91b20 100644 --- a/stories/MultiPassRenderer/components/Bloom.tsx +++ b/stories/MultiPassRenderer/components/Bloom.tsx @@ -26,14 +26,14 @@ export default class Bloom extends React.Component { const scene = new Scene({ id: 'map', map: new Mapbox({ - // style: 'mapbox://styles/mapbox/streets-v9', - style: 'blank', + style: 'mapbox://styles/mapbox/streets-v9', + // style: 'blank', center: [110.19382669582967, 50.258134], pitch: 0, zoom: 3, }), }); - scene.setBgColor('#000'); + // scene.setBgColor('#000'); const layer = new PolygonLayer({ zIndex: 0, // enablePicking: true, @@ -43,7 +43,9 @@ export default class Bloom extends React.Component { [ 'bloom', { - bloomRadius: 8, + // bloomBaseRadio: 0.5, + bloomRadius: 25, + bloomIntensity: 1, }, ], ],