diff --git a/cocos/render-scene/scene/camera.ts b/cocos/render-scene/scene/camera.ts index eff16e74171..8a29b406809 100644 --- a/cocos/render-scene/scene/camera.ts +++ b/cocos/render-scene/scene/camera.ts @@ -767,6 +767,14 @@ export class Camera { return this._matView$; } + /** + * @en The inverse of the view matrix of the camera + * @zh 相机的逆视图矩阵 + */ + get matViewInv (): Mat4 { + return this._matViewInv$; + } + /** * @en The projection matrix of the camera * @zh 相机的投影矩阵 @@ -835,6 +843,7 @@ export class Camera { private _curTransform$ = SurfaceTransform.IDENTITY; private _isProjDirty$ = true; private _matView$: Mat4 = mat4(); + private _matViewInv$: Mat4 = mat4(); private _matProj$: Mat4 = mat4(); private _matProjInv$: Mat4 = mat4(); private _matViewProj$: Mat4 = mat4(); @@ -1021,6 +1030,7 @@ export class Camera { this._forward$.z = -this._matView$.m10; // Remove scale Mat4.multiply(this._matView$, new Mat4().scale(this._node$.worldScale), this._matView$); + Mat4.invert(this._matViewInv$, this._matView$); this._node$.getWorldPosition(this._position$); viewProjDirty = true; } diff --git a/editor/assets/default_renderpipeline/builtin-pipeline-settings.ts b/editor/assets/default_renderpipeline/builtin-pipeline-settings.ts index 2f3fd0e0e12..8c830f33f5a 100644 --- a/editor/assets/default_renderpipeline/builtin-pipeline-settings.ts +++ b/editor/assets/default_renderpipeline/builtin-pipeline-settings.ts @@ -32,6 +32,7 @@ import { Material, rendering, Texture2D, + Vec3, } from 'cc'; import { EDITOR } from 'cc/env'; @@ -179,7 +180,7 @@ export class BuiltinPipelineSettings extends Component { @property({ group: { id: 'DepthOfField', name: 'DepthOfField (PostProcessing)', style: 'section' }, type: CCBoolean, - visible: false, + visible: true, }) set dofEnable(value: boolean) { this._settings.depthOfField.enabled = value; @@ -194,7 +195,7 @@ export class BuiltinPipelineSettings extends Component { @property({ group: { id: 'DepthOfField', name: 'DepthOfField (PostProcessing)', style: 'section' }, type: Material, - visible: false, + visible: true, }) set dofMaterial(value: Material) { if (this._settings.depthOfField.material === value) { @@ -213,41 +214,69 @@ export class BuiltinPipelineSettings extends Component { group: { id: 'DepthOfField', name: 'DepthOfField (PostProcessing)', style: 'section' }, type: CCFloat, min: 0, - visible: false, + visible: true, }) - set dofFocusDistance(value: number) { - this._settings.depthOfField.focusDistance = value; + set dofMinRange(value: number) { + this._settings.depthOfField.minRange = value; } - get dofFocusDistance(): number { - return this._settings.depthOfField.focusDistance; + get dofMinRange(): number { + return this._settings.depthOfField.minRange; } @property({ group: { id: 'DepthOfField', name: 'DepthOfField (PostProcessing)', style: 'section' }, type: CCFloat, min: 0, - visible: false, + visible: true, }) - set dofFocusRange(value: number) { - this._settings.depthOfField.focusRange = value; + set dofMaxRange(value: number) { + this._settings.depthOfField.maxRange = value; } - get dofFocusRange(): number { - return this._settings.depthOfField.focusRange; + get dofMaxRange(): number { + return this._settings.depthOfField.maxRange; } + @property({ + group: { id: 'DepthOfField', name: 'DepthOfField (PostProcessing)', style: 'section' }, + type: CCFloat, + min: 0, + max: 1, + visible: true, + }) + set dofIntensity(value: number) { + this._settings.depthOfField.intensity = value; + } + get dofIntensity(): number { + return this._settings.depthOfField.intensity; + } + + @type(CCFloat) @property({ group: { id: 'DepthOfField', name: 'DepthOfField (PostProcessing)', style: 'section' }, type: CCFloat, - range: [1, 10, 0.01], + range: [0.01, 10, 0.01], slide: true, - visible: false, + visible: true, + }) + set dofBlurRadius(value: number) { + this._settings.depthOfField.blurRadius = value; + } + get dofBlurRadius(): number { + return this._settings.depthOfField.blurRadius; + } + + @type(Vec3) + @property({ + group: { id: 'DepthOfField', name: 'DepthOfField (PostProcessing)', style: 'section' }, + type: Vec3, + visible: true, }) - set dofBokehRadius(value: number) { - this._settings.depthOfField.bokehRadius = value; + set dofFocusPos(value: Vec3) { + this._settings.depthOfField.focusPos = value; } - get dofBokehRadius(): number { - return this._settings.depthOfField.bokehRadius; + get dofFocusPos(): Vec3 { + return this._settings.depthOfField.focusPos; } // Bloom diff --git a/editor/assets/default_renderpipeline/builtin-pipeline-types.ts b/editor/assets/default_renderpipeline/builtin-pipeline-types.ts index 698268717d7..9301cb4432e 100644 --- a/editor/assets/default_renderpipeline/builtin-pipeline-types.ts +++ b/editor/assets/default_renderpipeline/builtin-pipeline-types.ts @@ -28,7 +28,7 @@ * ========================= !DO NOT CHANGE THE FOLLOWING SECTION MANUALLY! ========================= */ /* eslint-disable max-len */ -import { Material, Texture2D, gfx } from 'cc'; +import { Material, Texture2D, gfx, Vec3 } from 'cc'; const { SampleCount } = gfx; @@ -99,9 +99,11 @@ export function fillRequiredHBAO(value: HBAO): void { export interface DepthOfField { enabled: boolean; /* false */ /* refcount */ material: Material | null; - focusDistance: number; /* 0 */ - focusRange: number; /* 0 */ - bokehRadius: number; /* 1 */ + minRange: number; /* 0 */ + maxRange: number; /* 0 */ + blurRadius: number; /* 1 */ + intensity: number; + focusPos: Vec3; [name: string]: unknown; } @@ -109,9 +111,11 @@ export function makeDepthOfField(): DepthOfField { return { enabled: false, material: null, - focusDistance: 0, - focusRange: 0, - bokehRadius: 1, + minRange: 0, + maxRange: 50, + blurRadius: 1, + intensity: 0.2, + focusPos: new Vec3(0, 0, 0), }; } @@ -122,14 +126,17 @@ export function fillRequiredDepthOfField(value: DepthOfField): void { if (value.material === undefined) { value.material = null; } - if (value.focusDistance === undefined) { - value.focusDistance = 0; + if (value.minRange === undefined) { + value.minRange = 0; } - if (value.focusRange === undefined) { - value.focusRange = 0; + if (value.maxRange === undefined) { + value.maxRange = 0; } - if (value.bokehRadius === undefined) { - value.bokehRadius = 1; + if (value.blurRadius === undefined) { + value.blurRadius = 1; + } + if (value.focusPos === undefined) { + value.focusPos = new Vec3(); } } diff --git a/editor/assets/default_renderpipeline/builtin-pipeline.ts b/editor/assets/default_renderpipeline/builtin-pipeline.ts index 1ee29f85794..f08ee3e228e 100644 --- a/editor/assets/default_renderpipeline/builtin-pipeline.ts +++ b/editor/assets/default_renderpipeline/builtin-pipeline.ts @@ -461,6 +461,7 @@ if (rendering) { private readonly _cameraConfigs = new CameraConfigs(); // DepthOfField private readonly _cocParams = new Vec4(0, 0, 0, 0); + private readonly _focusPos = new Vec4(0, 0, 0, 1); private readonly _cocTexSize = new Vec4(0, 0, 0, 0); // Bloom private readonly _bloomParams = new Vec4(0, 0, 0, 0); @@ -1031,77 +1032,44 @@ if (rendering) { ): void { // https://catlikecoding.com/unity/tutorials/advanced-rendering/depth-of-field/ - this._cocParams.x = settings.depthOfField.focusDistance; - this._cocParams.y = settings.depthOfField.focusRange; - this._cocParams.z = settings.depthOfField.bokehRadius; - this._cocParams.w = 0.0; + this._cocParams.x = settings.depthOfField.minRange; + this._cocParams.y = settings.depthOfField.maxRange;// camera.farClip;// settings.depthOfField.focusRange; + this._cocParams.z = settings.depthOfField.blurRadius; + this._cocParams.w = settings.depthOfField.intensity; + this._focusPos.x = settings.depthOfField.focusPos.x; + this._focusPos.y = settings.depthOfField.focusPos.y; + this._focusPos.z = settings.depthOfField.focusPos.z; this._cocTexSize.x = 1.0 / width; this._cocTexSize.y = 1.0 / height; this._cocTexSize.z = width; this._cocTexSize.w = height; - - const halfWidth = Math.max(Math.floor(width / 2), 1); - const halfHeight = Math.max(Math.floor(height / 2), 1); - - const cocName = ldrColorName; - const prefilterName = `DofPrefilter${id}`; - const bokehName = `DofBokeh${id}`; - const filterName = `DofFilter${id}`; - - // CoC + const blurName = ldrColorName; + + // Blur Pass + const blurPass = ppl.addRenderPass(width, height, 'cc-dof-blur'); + blurPass.addRenderTarget(blurName, LoadOp.CLEAR, StoreOp.STORE, this._clearColorTransparentBlack); + blurPass.addTexture(dofRadianceName, 'screenTex'); + blurPass.setVec4('g_platform', this._configs.platform); + blurPass.setVec4('blurParams', this._cocParams); + blurPass.setVec4('mainTexTexelSize', this._cocTexSize); + blurPass + .addQueue(QueueHint.OPAQUE) + .addCameraQuad(camera, dofMaterial, 0); // addCameraQuad will set camera related UBOs + // coc pass const cocPass = ppl.addRenderPass(width, height, 'cc-dof-coc'); - cocPass.addRenderTarget(cocName, LoadOp.CLEAR, StoreOp.STORE, this._clearColorTransparentBlack); - cocPass.addTexture(depthStencil, 'DepthTex'); + cocPass.addRenderTarget(radianceName, LoadOp.CLEAR, StoreOp.STORE, this._clearColorTransparentBlack); + cocPass.addTexture(blurName, 'colorTex'); + cocPass.addTexture(depthStencil, "DepthTex"); + cocPass.addTexture(dofRadianceName, "screenTex"); cocPass.setVec4('g_platform', this._configs.platform); cocPass.setMat4('proj', camera.matProj); + cocPass.setMat4('invProj', camera.matProjInv); + cocPass.setMat4('viewMatInv', camera.matViewInv); cocPass.setVec4('cocParams', this._cocParams); + cocPass.setVec4('focus', this._focusPos); cocPass .addQueue(QueueHint.OPAQUE) - .addCameraQuad(camera, dofMaterial, 0); // addCameraQuad will set camera related UBOs - - // Downsample and Prefilter - const prefilterPass = ppl.addRenderPass(halfWidth, halfHeight, 'cc-dof-prefilter'); - prefilterPass.addRenderTarget(prefilterName, LoadOp.CLEAR, StoreOp.STORE, this._clearColorTransparentBlack); - prefilterPass.addTexture(dofRadianceName, 'colorTex'); - prefilterPass.addTexture(cocName, 'cocTex'); - prefilterPass.setVec4('g_platform', this._configs.platform); - prefilterPass.setVec4('mainTexTexelSize', this._cocTexSize); - prefilterPass - .addQueue(QueueHint.OPAQUE) - .addFullscreenQuad(dofMaterial, 1); - - // Bokeh blur - const bokehPass = ppl.addRenderPass(halfWidth, halfHeight, 'cc-dof-bokeh'); - bokehPass.addRenderTarget(bokehName, LoadOp.CLEAR, StoreOp.STORE, this._clearColorTransparentBlack); - bokehPass.addTexture(prefilterName, 'prefilterTex'); - bokehPass.setVec4('g_platform', this._configs.platform); - bokehPass.setVec4('mainTexTexelSize', this._cocTexSize); - bokehPass.setVec4('cocParams', this._cocParams); - bokehPass - .addQueue(QueueHint.OPAQUE) - .addFullscreenQuad(dofMaterial, 2); - - // Filtering - const filterPass = ppl.addRenderPass(halfWidth, halfHeight, 'cc-dof-filter'); - filterPass.addRenderTarget(filterName, LoadOp.CLEAR, StoreOp.STORE, this._clearColorTransparentBlack); - filterPass.addTexture(bokehName, 'bokehTex'); - filterPass.setVec4('g_platform', this._configs.platform); - filterPass.setVec4('mainTexTexelSize', this._cocTexSize); - filterPass - .addQueue(QueueHint.OPAQUE) - .addFullscreenQuad(dofMaterial, 3); - - // Combine - const combinePass = ppl.addRenderPass(width, height, 'cc-dof-combine'); - combinePass.addRenderTarget(radianceName, LoadOp.CLEAR, StoreOp.STORE, this._clearColorTransparentBlack); - combinePass.addTexture(dofRadianceName, 'colorTex'); - combinePass.addTexture(cocName, 'cocTex'); - combinePass.addTexture(filterName, 'filterTex'); - combinePass.setVec4('g_platform', this._configs.platform); - combinePass.setVec4('cocParams', this._cocParams); - combinePass - .addQueue(QueueHint.OPAQUE) - .addFullscreenQuad(dofMaterial, 4); + .addCameraQuad(camera, dofMaterial, 1); } private _addKawaseDualFilterBloomPasses( diff --git a/editor/assets/effects/pipeline/post-process/chunks/depth.chunk b/editor/assets/effects/pipeline/post-process/chunks/depth.chunk index 19dde87f7fb..eb96b100797 100644 --- a/editor/assets/effects/pipeline/post-process/chunks/depth.chunk +++ b/editor/assets/effects/pipeline/post-process/chunks/depth.chunk @@ -4,8 +4,11 @@ #pragma rate DepthTex pass uniform sampler2D DepthTex; //Sample_Point_Clamp +float GetDepthFromTex(vec2 uv) { + return texture(DepthTex, saturate(uv)).r; +} float GetLinearDepthWithProj(vec2 uv, mat4 proj) { - float depthHS = texture(DepthTex, saturate(uv)).r * 2.0 - 1.0; // -1.0 ~ +1.0 + float depthHS = GetDepthFromTex(uv) * 2.0 - 1.0; // -1.0 ~ +1.0 return -GetCameraDepthRH(depthHS, proj); } diff --git a/editor/assets/effects/pipeline/post-process/dof.effect b/editor/assets/effects/pipeline/post-process/dof.effect index 3d19bfb4c93..6e29134e8fb 100644 --- a/editor/assets/effects/pipeline/post-process/dof.effect +++ b/editor/assets/effects/pipeline/post-process/dof.effect @@ -1,274 +1,273 @@ // Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd. CCEffect %{ - - techniques: +techniques: - passes: - - vert: dof-vs - frag: dof-coc-fs - pass: dof-coc - depthStencilState: - depthTest: false - depthWrite: false - - vert: dof-vs - frag: dof-prefilter-fs - pass: dof-prefilter - depthStencilState: - depthTest: false - depthWrite: false - - vert: dof-vs - frag: dof-bokeh-fs - pass: dof-bokeh - depthStencilState: - depthTest: false - depthWrite: false - - vert: dof-vs - frag: dof-filter-fs - pass: dof-filter - depthStencilState: - depthTest: false - depthWrite: false - - vert: dof-vs - frag: dof-combine-fs - pass: dof-combine - depthStencilState: - depthTest: false - depthWrite: false + - vert: dof-vs + frag: dof-coc-fs + pass: dof-coc + depthStencilState: + depthTest: false + depthWrite: false + - vert: dof-vs + frag: dof-prefilter-fs + pass: dof-prefilter + depthStencilState: + depthTest: false + depthWrite: false + - vert: dof-vs + frag: dof-bokeh-fs + pass: dof-bokeh + depthStencilState: + depthTest: false + depthWrite: false + - vert: dof-vs + frag: dof-filter-fs + pass: dof-filter + depthStencilState: + depthTest: false + depthWrite: false + - vert: dof-vs + frag: dof-combine-fs + pass: dof-combine + depthStencilState: + depthTest: false + depthWrite: false blendState: targets: - - blend: true - blendSrc: zero - blendDst: src_alpha - blendSrcAlpha: zero - blendDstAlpha: one + - blend: true + blendSrc: zero + blendDst: src_alpha + blendSrcAlpha: zero + blendDstAlpha: one + }% CCProgram ubo %{ - #include - uniform ColorGradingUBO { - vec4 cocParams; - vec4 mainTexTexelSize; - }; +#include +uniform ColorGradingUBO { + vec4 cocParams; + vec4 mainTexTexelSize; +}; - #pragma rate colorTex pass - uniform sampler2D colorTex; +#pragma rate colorTex pass +uniform sampler2D colorTex; - #pragma rate cocTex pass - uniform sampler2D cocTex; +#pragma rate cocTex pass +uniform sampler2D cocTex; - #pragma rate prefilterTex pass - uniform sampler2D prefilterTex; +#pragma rate prefilterTex pass +uniform sampler2D prefilterTex; - #pragma rate bokehTex pass - uniform sampler2D bokehTex; +#pragma rate bokehTex pass +uniform sampler2D bokehTex; - #pragma rate filterTex pass - uniform sampler2D filterTex; - - #define focusDistance cocParams.x - #define focusRange cocParams.y - #define bokehRadius cocParams.z +#pragma rate filterTex pass +uniform sampler2D filterTex; - float FloatToUint8(float v) { - return (v * 127.0 + 128.0 + 0.5) / 255.0; - } +#define focusDistance cocParams.x +#define focusRange cocParams.y +#define bokehRadius cocParams.z - float Uint8ToFloat(float v) { - v *= 255.0; - return ((v - 128.0) / 127.0); - } +float FloatToUint8(float v) { + return (v * 127.0 + 128.0 + 0.5) / 255.0; +} + +float Uint8ToFloat(float v) { + v *= 255.0; + return ((v - 128.0) / 127.0); +} }% CCProgram dof-vs %{ - precision highp float; - #include - #include - out vec2 v_uv; - void main () { - StandardVertInput In; - CCDecode(In); - CC_HANDLE_GET_CLIP_FLIP(In.position.xy); - gl_Position = In.position; - v_uv = a_texCoord; - } +precision highp float; +#include +#include +out vec2 v_uv; +void main() { + StandardVertInput In; + CCDecode(In); + CC_HANDLE_GET_CLIP_FLIP(In.position.xy); + gl_Position = In.position; + v_uv = a_texCoord; +} }% CCProgram dof-coc-fs %{ - precision highp float; - #include - #include - #include - in vec2 v_uv; - layout(location = 0) out vec4 fragColor; - - void main () { - float depth = GetLinearDepth(v_uv); - //get circle of confusion - float coc = (depth - focusDistance) / focusRange; - coc = clamp(coc, -1.0, 1.0); - fragColor = vec4(FloatToUint8(coc), 0.0, 0.0, 1.0); - } +precision highp float; +#include +#include +#include +in vec2 v_uv; +layout(location = 0)out vec4 fragColor; + +void main() { + float depth = GetLinearDepth(v_uv); + //get circle of confusion + float coc = (depth - focusDistance) / focusRange; + coc = clamp(coc, - 1.0, 1.0); + fragColor = vec4(FloatToUint8(coc), 0.0, 0.0, 1.0); +} }% CCProgram dof-prefilter-fs %{ - precision highp float; - #include - #include - - in vec2 v_uv; - layout(location = 0) out vec4 fragColor; - - float Weigh (vec3 c) { - return 1.0 / (1.0 + max(max(c.r, c.g), c.b)); - } +precision highp float; +#include +#include + +in vec2 v_uv; +layout(location = 0)out vec4 fragColor; + +float Weigh(vec3 c) { + return 1.0 / (1.0 + max(max(c.r, c.g), c.b)); +} + +void main() { + //use lower resolution in order to cover more area + //downsampling + vec4 o = mainTexTexelSize.xyxy * vec2(-0.5, 0.5).xxyy; + vec2 uv0 = v_uv + o.xy; + vec2 uv1 = v_uv + o.zy; + vec2 uv2 = v_uv + o.xw; + vec2 uv3 = v_uv + o.zw; - void main () { - //use lower resolution in order to cover more area - //downsampling - vec4 o = mainTexTexelSize.xyxy * vec2(-0.5, 0.5).xxyy; - vec2 uv0 = v_uv + o.xy; - vec2 uv1 = v_uv + o.zy; - vec2 uv2 = v_uv + o.xw; - vec2 uv3 = v_uv + o.zw; - - vec3 s0 = texture(colorTex, uv0).rgb; - vec3 s1 = texture(colorTex, uv1).rgb; - vec3 s2 = texture(colorTex, uv2).rgb; - vec3 s3 = texture(colorTex, uv3).rgb; - - float w0 = Weigh(s0); - float w1 = Weigh(s1); - float w2 = Weigh(s2); - float w3 = Weigh(s3); - - // get the weighted average - vec3 avg = s0 * w0 + s1 * w1 + s2 * w2 + s3 * w3; - avg /= max(w0 + w1 + w2 + s3, 0.00001); - - float coc0 = Uint8ToFloat(texture(cocTex, uv0).r); - float coc1 = Uint8ToFloat(texture(cocTex, uv1).r); - float coc2 = Uint8ToFloat(texture(cocTex, uv2).r); - float coc3 = Uint8ToFloat(texture(cocTex, uv3).r); - - //get the largest CoC value of the four texture pixels - float cocMin = min(min(min(coc0, coc1), coc2), coc3); - float cocMax = max(max(max(coc0, coc1), coc2), coc3); - float coc = cocMax >= -cocMin ? cocMax : cocMin; - - fragColor = vec4(avg, FloatToUint8(coc)); - } + vec3 s0 = texture(colorTex, uv0).rgb; + vec3 s1 = texture(colorTex, uv1).rgb; + vec3 s2 = texture(colorTex, uv2).rgb; + vec3 s3 = texture(colorTex, uv3).rgb; + + float w0 = Weigh(s0); + float w1 = Weigh(s1); + float w2 = Weigh(s2); + float w3 = Weigh(s3); + + // get the weighted average + vec3 avg = s0 * w0 + s1 * w1 + s2 * w2 + s3 * w3; + avg /= max(w0 + w1 + w2 + s3, 0.00001); + + float coc0 = Uint8ToFloat(texture(cocTex, uv0).r); + float coc1 = Uint8ToFloat(texture(cocTex, uv1).r); + float coc2 = Uint8ToFloat(texture(cocTex, uv2).r); + float coc3 = Uint8ToFloat(texture(cocTex, uv3).r); + + //get the largest CoC value of the four texture pixels + float cocMin = min(min(min(coc0, coc1), coc2), coc3); + float cocMax = max(max(max(coc0, coc1), coc2), coc3); + float coc = cocMax >= -cocMin ? cocMax : cocMin; + + fragColor = vec4(avg, FloatToUint8(coc)); +} }% CCProgram dof-bokeh-fs %{ - precision highp float; - #include - #include - - in vec2 v_uv; - layout(location = 0) out vec4 fragColor; - - const int SAMPLE_COUNT = 16; - vec2 bokehKernel[SAMPLE_COUNT]; - void initKernel() - { - bokehKernel[0] = vec2(0.0, 0.0); - bokehKernel[1] = vec2(0.54545456, 0.0); - bokehKernel[2] = vec2(0.16855472, 0.5187581); - bokehKernel[3] = vec2(-0.44128203, 0.3206101); - bokehKernel[4] = vec2(-0.44128197, -0.3206102); - bokehKernel[5] = vec2(0.1685548, -0.5187581); - bokehKernel[6] = vec2(1.0, 0.0); - bokehKernel[7] = vec2(0.809017, 0.58778524); - bokehKernel[8] = vec2(0.30901697, 0.95105654); - bokehKernel[9] = vec2(-0.30901703, 0.9510565); - bokehKernel[10] = vec2(-0.80901706, 0.5877852); - bokehKernel[11] = vec2(-1.0, 0.0); - bokehKernel[12] = vec2(-0.80901694, -0.58778536); - bokehKernel[13] = vec2(-0.30901664, -0.9510566); - bokehKernel[14] = vec2(0.30901712, -0.9510565); - bokehKernel[15] = vec2(0.80901694, -0.5877853); - } - - - //smooth transition between focal areas and boken areas - float Weigh (float coc, float dist) { - return saturate((abs(coc) - dist + 2.0) / 2.0); - } - - void Accumulate(float coc, vec2 displacement, inout vec4 farAcc, inout vec4 nearAcc) { - float dist = length(displacement); - vec2 offset = displacement * mainTexTexelSize.xy * 2.0; - - vec4 prefilterColor = texture(prefilterTex, v_uv + offset); - prefilterColor.a = Uint8ToFloat(prefilterColor.a) * bokehRadius; - - float fw = Weigh(max(0.0, min(prefilterColor.a, coc)), dist); - farAcc.rgb += prefilterColor.rgb * fw; - farAcc.a += fw; - - float nw = Weigh(-prefilterColor.a, dist); - nearAcc.rgb += prefilterColor.rgb * nw; - nearAcc.a += nw; - } - - void main () { - initKernel(); - - float coc = Uint8ToFloat(texture(prefilterTex, v_uv).a) * bokehRadius; - - vec4 farAcc = vec4(0.0); // background - vec4 nearAcc = vec4(0.0); // foreground - - for (int k = 0; k < SAMPLE_COUNT; k++) { - vec2 displacement = bokehKernel[k] * bokehRadius; - Accumulate(coc, displacement, farAcc, nearAcc); - } - - farAcc.rgb *= 1.0 / (farAcc.a + (farAcc.a == 0.0 ? 1.0 : 0.0)); - nearAcc.rgb *= 1.0 / (nearAcc.a + (nearAcc.a == 0.0 ? 1.0 : 0.0)); - - //enhance foreground effects with a factor - float alpha = min(1.0, nearAcc.a * PI / float(SAMPLE_COUNT)); +precision highp float; +#include +#include + +in vec2 v_uv; +layout(location = 0)out vec4 fragColor; + +const int SAMPLE_COUNT = 16; +vec2 bokehKernel[SAMPLE_COUNT]; +void initKernel() +{ + bokehKernel[0] = vec2(0.0, 0.0); + bokehKernel[1] = vec2(0.54545456, 0.0); + bokehKernel[2] = vec2(0.16855472, 0.5187581); + bokehKernel[3] = vec2(-0.44128203, 0.3206101); + bokehKernel[4] = vec2(-0.44128197, - 0.3206102); + bokehKernel[5] = vec2(0.1685548, - 0.5187581); + bokehKernel[6] = vec2(1.0, 0.0); + bokehKernel[7] = vec2(0.809017, 0.58778524); + bokehKernel[8] = vec2(0.30901697, 0.95105654); + bokehKernel[9] = vec2(-0.30901703, 0.9510565); + bokehKernel[10] = vec2(-0.80901706, 0.5877852); + bokehKernel[11] = vec2(-1.0, 0.0); + bokehKernel[12] = vec2(-0.80901694, - 0.58778536); + bokehKernel[13] = vec2(-0.30901664, - 0.9510566); + bokehKernel[14] = vec2(0.30901712, - 0.9510565); + bokehKernel[15] = vec2(0.80901694, - 0.5877853); +} + +//smooth transition between focal areas and boken areas +float Weigh(float coc, float dist) { + return saturate((abs(coc) - dist + 2.0) / 2.0); +} + +void Accumulate(float coc, vec2 displacement, inout vec4 farAcc, inout vec4 nearAcc) { + float dist = length(displacement); + vec2 offset = displacement * mainTexTexelSize.xy * 2.0; + + vec4 prefilterColor = texture(prefilterTex, v_uv + offset); + prefilterColor.a = Uint8ToFloat(prefilterColor.a) * bokehRadius; + + float fw = Weigh(max(0.0, min(prefilterColor.a, coc)), dist); + farAcc.rgb += prefilterColor.rgb * fw; + farAcc.a += fw; + + float nw = Weigh(-prefilterColor.a, dist); + nearAcc.rgb += prefilterColor.rgb * nw; + nearAcc.a += nw; +} - vec3 rgb = lerp(farAcc.rgb, nearAcc.rgb, alpha); - fragColor = vec4(rgb, alpha); +void main() { + initKernel(); + + float coc = Uint8ToFloat(texture(prefilterTex, v_uv).a) * bokehRadius; + + vec4 farAcc = vec4(0.0); // background + vec4 nearAcc = vec4(0.0); // foreground + + for(int k = 0; k < SAMPLE_COUNT; k ++ ) { + vec2 displacement = bokehKernel[k] * bokehRadius; + Accumulate(coc, displacement, farAcc, nearAcc); } + + farAcc.rgb *= 1.0 / (farAcc.a + (farAcc.a == 0.0 ? 1.0 : 0.0)); + nearAcc.rgb *= 1.0 / (nearAcc.a + (nearAcc.a == 0.0 ? 1.0 : 0.0)); + + //enhance foreground effects with a factor + float alpha = min(1.0, nearAcc.a * PI / float(SAMPLE_COUNT)); + + vec3 rgb = lerp(farAcc.rgb, nearAcc.rgb, alpha); + fragColor = vec4(rgb, alpha); +} }% CCProgram dof-filter-fs %{ - precision highp float; - #include - in vec2 v_uv; - layout(location = 0) out vec4 fragColor; - - void main () { - //use tent filter,reduce the gap between sampling points - vec4 o = mainTexTexelSize.xyxy * 2.0 * vec2(-0.5, 0.5).xxyy; - vec4 s = - texture(bokehTex, v_uv + o.xy) + - texture(bokehTex, v_uv + o.zy) + - texture(bokehTex, v_uv + o.xw) + - texture(bokehTex, v_uv + o.zw); - fragColor = s * 0.25; - } +precision highp float; +#include +in vec2 v_uv; +layout(location = 0)out vec4 fragColor; + +void main() { + //use tent filter,reduce the gap between sampling points + vec4 o = mainTexTexelSize.xyxy * 2.0 * vec2(-0.5, 0.5).xxyy; + vec4 s = + texture(bokehTex, v_uv + o.xy) + + texture(bokehTex, v_uv + o.zy) + + texture(bokehTex, v_uv + o.xw) + + texture(bokehTex, v_uv + o.zw); + fragColor = s * 0.25; +} }% CCProgram dof-combine-fs %{ - precision highp float; - #include - #include +precision highp float; +#include +#include - in vec2 v_uv; - layout(location = 0) out vec4 fragColor; +in vec2 v_uv; +layout(location = 0)out vec4 fragColor; - void main () { - vec4 source = texture(colorTex, v_uv); - float coc = Uint8ToFloat(texture(cocTex, v_uv).r) * bokehRadius; - vec4 dof = texture(filterTex, v_uv); - - float dofStrength = smoothstep(0.1, 1.0, abs(coc)); - vec3 color = lerp(source.rgb, dof.rgb, dofStrength + dof.a - dofStrength * dof.a); - fragColor = vec4(color.rgb, source.a); - } +void main() { + vec4 source = texture(colorTex, v_uv); + float coc = Uint8ToFloat(texture(cocTex, v_uv).r) * bokehRadius; + vec4 dof = texture(filterTex, v_uv); + + float dofStrength = smoothstep(0.1, 1.0, abs(coc)); + vec3 color = lerp(source.rgb, dof.rgb, dofStrength + dof.a - dofStrength * dof.a); + fragColor = vec4(color.rgb, source.a); +} }% diff --git a/editor/assets/effects/pipeline/post-process/dof1.effect b/editor/assets/effects/pipeline/post-process/dof1.effect index ed456a1a4c4..6ca5c5bc40f 100644 --- a/editor/assets/effects/pipeline/post-process/dof1.effect +++ b/editor/assets/effects/pipeline/post-process/dof1.effect @@ -1,291 +1,103 @@ // Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd. CCEffect %{ - - techniques: +techniques: - passes: - - vert: dof-vs - frag: dof-coc-fs - pass: cc-dof-coc - depthStencilState: - depthTest: false - depthWrite: false - - vert: dof-vs - frag: dof-prefilter-fs - pass: cc-dof-prefilter - depthStencilState: - depthTest: false - depthWrite: false - - vert: dof-vs - frag: dof-bokeh-fs - pass: cc-dof-bokeh - depthStencilState: - depthTest: false - depthWrite: false - - vert: dof-vs - frag: dof-filter-fs - pass: cc-dof-filter - depthStencilState: - depthTest: false - depthWrite: false - - vert: dof-vs - frag: dof-combine-fs - pass: cc-dof-combine - depthStencilState: - depthTest: false - depthWrite: false - blendState: - targets: - - blend: true - blendSrc: zero - blendDst: src_alpha - blendSrcAlpha: zero - blendDstAlpha: one + - vert: dof-vs + frag: dof-blur-fs + pass: cc-dof-blur + depthStencilState: + depthTest: false + depthWrite: false + - vert: dof-vs + frag: dof-coc-fs + pass: cc-dof-coc + depthStencilState: + depthTest: false + depthWrite: false + }% CCProgram ubo %{ - #include - - #define focusDistance cocParams.x - #define focusRange cocParams.y - #define bokehRadius cocParams.z - - float FloatToUint8(float v) { - return (v * 127.0 + 128.0 + 0.5) / 255.0; - } +#include - float Uint8ToFloat(float v) { - v *= 255.0; - return ((v - 128.0) / 127.0); - } +#define focusDistance params.x +#define focusRange params.y +#define blurRadius params.z }% - CCProgram dof-vs %{ - #include <./chunks/vs1> +#include <./chunks/vs1> }% -CCProgram dof-coc-fs %{ - precision highp float; - #include - #include <./chunks/depth> - - #pragma rate DofCocUBO pass - uniform DofCocUBO { - mat4 proj; - vec4 cocParams; - }; - - in vec2 v_uv; - layout(location = 0) out vec4 fragColor; - - void main () { - float depth = GetLinearDepthWithProj(v_uv, proj); - //get circle of confusion - float coc = (depth - focusDistance) / focusRange; - coc = clamp(coc, -1.0, 1.0); - fragColor = vec4(FloatToUint8(coc), 0.0, 0.0, 1.0); - } +CCProgram dof-blur-fs %{ +precision highp float; +#pragma rate DofUBO pass +uniform DofUBO { + vec4 blurParams; + vec4 mainTexTexelSize; +}; +layout(location = 0)out vec4 fragColor; +#pragma rate screenTex pass +uniform sampler2D screenTex; +in vec2 v_uv; +vec4 blur(sampler2D image, vec2 uv) { + vec4 color = vec4(0.0); + vec2 resolution = mainTexTexelSize.zw; + vec2 off1 = vec2(1.411764705882353); + vec2 off2 = vec2(3.2941176470588234); + vec2 off3 = vec2(5.176470588235294); + color += texture(image, uv) * 0.1964825501511404; + color += texture(image, uv + (off1 / resolution)) * 0.2969069646728344; + color += texture(image, uv - (off1 / resolution)) * 0.2969069646728344; + color += texture(image, uv + (off2 / resolution)) * 0.09447039785044732; + color += texture(image, uv - (off2 / resolution)) * 0.09447039785044732; + color += texture(image, uv + (off3 / resolution)) * 0.010381362401148057; + color += texture(image, uv - (off3 / resolution)) * 0.010381362401148057; + return color; +} +void main() { + vec4 pixelOffset = vec4(-1.0, - 1.0, 1.0, 1.0); + vec4 offsets = mainTexTexelSize.xyxy * pixelOffset * blurParams.z; + vec4 outColor = blur(screenTex, v_uv + offsets.xy); + outColor += blur(screenTex, v_uv + offsets.zy); + outColor += blur(screenTex, v_uv + offsets.xw); + outColor += blur(screenTex, v_uv + offsets.zw); + fragColor = outColor * blurParams.w; +} }% -CCProgram dof-prefilter-fs %{ - precision highp float; - #include - - #pragma rate DofPrefilterUBO pass - uniform DofPrefilterUBO { - vec4 mainTexTexelSize; - }; - - #pragma rate colorTex pass - uniform sampler2D colorTex; - - #pragma rate cocTex pass - uniform sampler2D cocTex; - - in vec2 v_uv; - layout(location = 0) out vec4 fragColor; - - float Weigh (vec3 c) { - return 1.0 / (1.0 + max(max(c.r, c.g), c.b)); - } +CCProgram dof-coc-fs %{ +precision highp float; +#include <./chunks/depth> + +layout(location = 0)out vec4 fragColor; +in vec2 v_uv; +#pragma rate screenTex pass +uniform sampler2D screenTex; +#pragma rate colorTex pass +uniform sampler2D colorTex; +#pragma rate DofCocUBO pass +uniform DofCocUBO { + mat4 proj; + mat4 invProj; + mat4 viewMatInv; + vec4 focus; + vec4 cocParams; +}; +void main() { + vec4 blurPixel = texture(colorTex, v_uv); + vec4 screenPixel = texture(screenTex, v_uv); + float depth = GetDepthFromTex(v_uv) * 2.0 - 1.0; + vec4 screenPos = vec4(v_uv.x * 2.0 - 1.0, v_uv.y * 2.0 - 1.0, depth, 1.0); + vec4 viewPos = invProj * screenPos; + viewPos /= viewPos.w; + vec4 worldPos = viewMatInv * viewPos; + float blur = + smoothstep + (cocParams.x + , cocParams.y + , length(worldPos - vec4(focus.xyz, 1.0)) + ); + fragColor = mix(screenPixel, blurPixel, blur); - void main () { - //use lower resolution in order to cover more area - //downsampling - vec4 o = mainTexTexelSize.xyxy * vec2(-0.5, 0.5).xxyy; - vec2 uv0 = v_uv + o.xy; - vec2 uv1 = v_uv + o.zy; - vec2 uv2 = v_uv + o.xw; - vec2 uv3 = v_uv + o.zw; - - vec3 s0 = texture(colorTex, uv0).rgb; - vec3 s1 = texture(colorTex, uv1).rgb; - vec3 s2 = texture(colorTex, uv2).rgb; - vec3 s3 = texture(colorTex, uv3).rgb; - - float w0 = Weigh(s0); - float w1 = Weigh(s1); - float w2 = Weigh(s2); - float w3 = Weigh(s3); - - // get the weighted average - vec3 avg = s0 * w0 + s1 * w1 + s2 * w2 + s3 * w3; - avg /= max(w0 + w1 + w2 + s3, 0.00001); - - float coc0 = Uint8ToFloat(texture(cocTex, uv0).r); - float coc1 = Uint8ToFloat(texture(cocTex, uv1).r); - float coc2 = Uint8ToFloat(texture(cocTex, uv2).r); - float coc3 = Uint8ToFloat(texture(cocTex, uv3).r); - - //get the largest CoC value of the four texture pixels - float cocMin = min(min(min(coc0, coc1), coc2), coc3); - float cocMax = max(max(max(coc0, coc1), coc2), coc3); - float coc = cocMax >= -cocMin ? cocMax : cocMin; - - fragColor = vec4(avg, FloatToUint8(coc)); - } - -}% - -CCProgram dof-bokeh-fs %{ - precision highp float; - #include - - #pragma rate DofBokehUBO pass - uniform DofBokehUBO { - vec4 mainTexTexelSize; - vec4 cocParams; - }; - - #pragma rate prefilterTex pass - uniform sampler2D prefilterTex; - - in vec2 v_uv; - layout(location = 0) out vec4 fragColor; - - const int SAMPLE_COUNT = 16; - vec2 bokehKernel[SAMPLE_COUNT]; - void initKernel() - { - bokehKernel[0] = vec2(0.0, 0.0); - bokehKernel[1] = vec2(0.54545456, 0.0); - bokehKernel[2] = vec2(0.16855472, 0.5187581); - bokehKernel[3] = vec2(-0.44128203, 0.3206101); - bokehKernel[4] = vec2(-0.44128197, -0.3206102); - bokehKernel[5] = vec2(0.1685548, -0.5187581); - bokehKernel[6] = vec2(1.0, 0.0); - bokehKernel[7] = vec2(0.809017, 0.58778524); - bokehKernel[8] = vec2(0.30901697, 0.95105654); - bokehKernel[9] = vec2(-0.30901703, 0.9510565); - bokehKernel[10] = vec2(-0.80901706, 0.5877852); - bokehKernel[11] = vec2(-1.0, 0.0); - bokehKernel[12] = vec2(-0.80901694, -0.58778536); - bokehKernel[13] = vec2(-0.30901664, -0.9510566); - bokehKernel[14] = vec2(0.30901712, -0.9510565); - bokehKernel[15] = vec2(0.80901694, -0.5877853); - } - - - //smooth transition between focal areas and boken areas - float Weigh (float coc, float dist) { - return saturate((abs(coc) - dist + 2.0) / 2.0); - } - - void Accumulate(float coc, vec2 displacement, inout vec4 farAcc, inout vec4 nearAcc) { - float dist = length(displacement); - vec2 offset = displacement * mainTexTexelSize.xy * 2.0; - - vec4 prefilterColor = texture(prefilterTex, v_uv + offset); - prefilterColor.a = Uint8ToFloat(prefilterColor.a) * bokehRadius; - - float fw = Weigh(max(0.0, min(prefilterColor.a, coc)), dist); - farAcc.rgb += prefilterColor.rgb * fw; - farAcc.a += fw; - - float nw = Weigh(-prefilterColor.a, dist); - nearAcc.rgb += prefilterColor.rgb * nw; - nearAcc.a += nw; - } - - void main () { - initKernel(); - - float coc = Uint8ToFloat(texture(prefilterTex, v_uv).a) * bokehRadius; - - vec4 farAcc = vec4(0.0); // background - vec4 nearAcc = vec4(0.0); // foreground - - for (int k = 0; k < SAMPLE_COUNT; k++) { - vec2 displacement = bokehKernel[k] * bokehRadius; - Accumulate(coc, displacement, farAcc, nearAcc); - } - - farAcc.rgb *= 1.0 / (farAcc.a + (farAcc.a == 0.0 ? 1.0 : 0.0)); - nearAcc.rgb *= 1.0 / (nearAcc.a + (nearAcc.a == 0.0 ? 1.0 : 0.0)); - - //enhance foreground effects with a factor - float alpha = min(1.0, nearAcc.a * PI / float(SAMPLE_COUNT)); - - vec3 rgb = lerp(farAcc.rgb, nearAcc.rgb, alpha); - fragColor = vec4(rgb, alpha); - } -}% - -CCProgram dof-filter-fs %{ - precision highp float; - #include - - #pragma rate DofFilterUBO pass - uniform DofFilterUBO { - vec4 mainTexTexelSize; - }; - - #pragma rate bokehTex pass - uniform sampler2D bokehTex; - - in vec2 v_uv; - layout(location = 0) out vec4 fragColor; - - void main () { - //use tent filter,reduce the gap between sampling points - vec4 o = mainTexTexelSize.xyxy * 2.0 * vec2(-0.5, 0.5).xxyy; - vec4 s = - texture(bokehTex, v_uv + o.xy) + - texture(bokehTex, v_uv + o.zy) + - texture(bokehTex, v_uv + o.xw) + - texture(bokehTex, v_uv + o.zw); - fragColor = s * 0.25; - } -}% - -CCProgram dof-combine-fs %{ - precision highp float; - #include - #include - - #pragma rate DofCombineUBO pass - uniform DofCombineUBO { - vec4 cocParams; - }; - - #pragma rate colorTex pass - uniform sampler2D colorTex; - - #pragma rate cocTex pass - uniform sampler2D cocTex; - - #pragma rate filterTex pass - uniform sampler2D filterTex; - - in vec2 v_uv; - layout(location = 0) out vec4 fragColor; - - void main () { - vec4 source = texture(colorTex, v_uv); - float coc = Uint8ToFloat(texture(cocTex, v_uv).r) * bokehRadius; - vec4 dof = texture(filterTex, v_uv); - - float dofStrength = smoothstep(0.1, 1.0, abs(coc)); - vec3 color = lerp(source.rgb, dof.rgb, dofStrength + dof.a - dofStrength * dof.a); - fragColor = vec4(color.rgb, source.a); - } -}% +} +}% \ No newline at end of file