playcanvas
Version:
PlayCanvas WebGL game engine
74 lines (71 loc) • 5.49 kB
JavaScript
import { Kernel } from '../../core/math/kernel.js';
import { RenderPassShaderQuad } from '../../scene/graphics/render-pass-shader-quad.js';
/**
* @import { GraphicsDevice } from '../../platform/graphics/graphics-device.js'
* @import { Texture } from '../../platform/graphics/texture.js'
*/ /**
* Render pass implementation of a down-sample filter used by the Depth of Field pass. Based on
* a texel of the CoC texture, it generates blurred version of the near or far texture.
*
* @category Graphics
* @ignore
*/ class RenderPassDofBlur extends RenderPassShaderQuad {
set blurRings(value) {
if (this._blurRings !== value) {
this._blurRings = value;
this.shader = null;
}
}
get blurRings() {
return this._blurRings;
}
set blurRingPoints(value) {
if (this._blurRingPoints !== value) {
this._blurRingPoints = value;
this.shader = null;
}
}
get blurRingPoints() {
return this._blurRingPoints;
}
createShader() {
this.kernel = new Float32Array(Kernel.concentric(this.blurRings, this.blurRingPoints));
var kernelCount = this.kernel.length >> 1;
var nearBlur = this.nearTexture !== null;
var shaderName = "DofBlurShader-" + kernelCount + "-" + (nearBlur ? 'nearBlur' : 'noNearBlur');
this.shader = this.createQuadShader(shaderName, /* glsl */ "\n\n " + (nearBlur ? '#define NEAR_BLUR' : '') + "\n\n #if defined(NEAR_BLUR)\n uniform sampler2D nearTexture;\n #endif\n uniform sampler2D farTexture;\n uniform sampler2D cocTexture;\n uniform float blurRadiusNear;\n uniform float blurRadiusFar;\n uniform vec2 kernel[" + kernelCount + "];\n\n varying vec2 uv0;\n\n void main()\n {\n vec2 coc = texture2D(cocTexture, uv0).rg;\n float cocFar = coc.r;\n\n vec3 sum = vec3(0.0, 0.0, 0.0);\n\n #if defined(NEAR_BLUR)\n // near blur\n float cocNear = coc.g;\n if (cocNear > 0.0001) {\n\n ivec2 nearTextureSize = textureSize(nearTexture, 0);\n vec2 step = cocNear * blurRadiusNear / vec2(nearTextureSize);\n\n for (int i = 0; i < " + kernelCount + "; i++) {\n vec2 uv = uv0 + step * kernel[i];\n vec3 tap = texture2DLod(nearTexture, uv, 0.0).rgb;\n sum += tap.rgb;\n }\n\n sum *= " + 1.0 / kernelCount + ";\n\n } else\n #endif\n \n if (cocFar > 0.0001) { // far blur\n\n ivec2 farTextureSize = textureSize(farTexture, 0);\n vec2 step = cocFar * blurRadiusFar / vec2(farTextureSize);\n\n float sumCoC = 0.0; \n for (int i = 0; i < " + kernelCount + "; i++) {\n vec2 uv = uv0 + step * kernel[i];\n vec3 tap = texture2DLod(farTexture, uv, 0.0).rgb;\n\n // block out sharp objects to avoid leaking to far blur\n float cocThis = texture2DLod(cocTexture, uv, 0.0).r;\n tap *= cocThis;\n sumCoC += cocThis;\n\n sum += tap.rgb;\n }\n\n // average out the sum\n if (sumCoC > 0.0)\n sum /= sumCoC;\n\n // compensate for the fact the farTexture was premultiplied by CoC\n sum /= cocFar;\n }\n\n pcFragColor0 = vec4(sum, 1.0);\n }");
}
execute() {
if (!this.shader) {
this.createShader();
}
this.nearTextureId.setValue(this.nearTexture);
this.farTextureId.setValue(this.farTexture);
this.cocTextureId.setValue(this.cocTexture);
this.kernelId.setValue(this.kernel);
this.kernelCountId.setValue(this.kernel.length >> 1);
this.blurRadiusNearId.setValue(this.blurRadiusNear);
this.blurRadiusFarId.setValue(this.blurRadiusFar);
super.execute();
}
/**
* @param {GraphicsDevice} device - The graphics device.
* @param {Texture|null} nearTexture - The near texture to blur. Skip near blur if the texture is null.
* @param {Texture} farTexture - The far texture to blur.
* @param {Texture} cocTexture - The CoC texture.
*/ constructor(device, nearTexture, farTexture, cocTexture){
super(device), this.blurRadiusNear = 1, this.blurRadiusFar = 1, this._blurRings = 3, this._blurRingPoints = 3;
this.nearTexture = nearTexture;
this.farTexture = farTexture;
this.cocTexture = cocTexture;
var { scope } = device;
this.kernelId = scope.resolve('kernel[0]');
this.kernelCountId = scope.resolve('kernelCount');
this.blurRadiusNearId = scope.resolve('blurRadiusNear');
this.blurRadiusFarId = scope.resolve('blurRadiusFar');
this.nearTextureId = scope.resolve('nearTexture');
this.farTextureId = scope.resolve('farTexture');
this.cocTextureId = scope.resolve('cocTexture');
}
}
export { RenderPassDofBlur };