diff --git a/docs/examples/en/postprocessing/EffectComposer.html b/docs/examples/en/postprocessing/EffectComposer.html index 9531cfc4561992..db75f3f86ee10d 100644 --- a/docs/examples/en/postprocessing/EffectComposer.html +++ b/docs/examples/en/postprocessing/EffectComposer.html @@ -41,6 +41,7 @@

Examples

[example:webgl_postprocessing_godrays postprocessing godrays]
[example:webgl_postprocessing_gtao postprocessing gtao]
[example:webgl_postprocessing_masking postprocessing masking]
+ [example:webgl_postprocessing_material_ao postprocessing material ao]
[example:webgl_postprocessing_outline postprocessing outline]
[example:webgl_postprocessing_pixel postprocessing pixelate]
[example:webgl_postprocessing_procedural postprocessing procedural]
diff --git a/docs/examples/zh/postprocessing/EffectComposer.html b/docs/examples/zh/postprocessing/EffectComposer.html index 6d480877cc04e5..33d2aac17112d0 100644 --- a/docs/examples/zh/postprocessing/EffectComposer.html +++ b/docs/examples/zh/postprocessing/EffectComposer.html @@ -40,6 +40,7 @@

例子

[example:webgl_postprocessing_godrays postprocessing godrays]
[example:webgl_postprocessing_gtao postprocessing gtao]
[example:webgl_postprocessing_masking postprocessing masking]
+ [example:webgl_postprocessing_material_ao postprocessing material ao]
[example:webgl_postprocessing_outline postprocessing outline]
[example:webgl_postprocessing_pixel postprocessing pixelate]
[example:webgl_postprocessing_procedural postprocessing procedural]
diff --git a/examples/files.json b/examples/files.json index 63efedff6746fe..28087dc28c46ee 100644 --- a/examples/files.json +++ b/examples/files.json @@ -249,6 +249,7 @@ "webgl_postprocessing_gtao", "webgl_postprocessing_rgb_halftone", "webgl_postprocessing_masking", + "webgl_postprocessing_material_ao", "webgl_postprocessing_ssaa", "webgl_postprocessing_outline", "webgl_postprocessing_pixel", diff --git a/examples/jsm/materials/MeshPostProcessingMaterial.js b/examples/jsm/materials/MeshPostProcessingMaterial.js new file mode 100644 index 00000000000000..d2fa48f9cbc46d --- /dev/null +++ b/examples/jsm/materials/MeshPostProcessingMaterial.js @@ -0,0 +1,144 @@ +import { MeshPhysicalMaterial } from 'three'; + +/** + * The aim of this mesh material is to use information from a post processing pass in the diffuse color pass. + * This material is based on the MeshPhysicalMaterial. + * + * In the current state, only the information of a screen space AO pass can be used in the material. + * Actually, the output of any screen space AO (SSAO, GTAO) can be used, + * as it is only necessary to provide the AO in one color channel of a texture, + * however the AO pass must be rendered prior to the color pass, + * which makes the post-processing pass somewhat of a pre-processing pass. + * Fot this purpose a new map (`aoPassMap`) is added to the material. + * The value of the map is used the same way as the `aoMap` value. + * + * Motivation to use the outputs AO pass directly in the material: + * The incident light of a fragment is composed of ambient light, direct light and indirect light + * Ambient Occlusion only occludes ambient light and environment light, but not direct light. + * Direct light is only occluded by geometry that casts shadows. + * And of course the emitted light should not be darkened by ambient occlusion either. + * This cannot be achieved if the AO post processing pass is simply blended with the diffuse render pass. + * + * Further extension work might be to use the output of an SSR pass or an HBIL pass from a previous frame. + * This would then create the possibility of SSR and IR depending on material properties such as `roughness`, `metalness` and `reflectivity`. +**/ + +class MeshPostProcessingMaterial extends MeshPhysicalMaterial { + + constructor( parameters ) { + + const aoPassMap = parameters.aoPassMap; + const aoPassMapScale = parameters.aoPassMapScale || 1.0; + delete parameters.aoPassMap; + delete parameters.aoPassMapScale; + + super( parameters ); + + this.onBeforeCompile = this._onBeforeCompile; + this.customProgramCacheKey = this._customProgramCacheKey; + this._aoPassMap = aoPassMap; + this.aoPassMapScale = aoPassMapScale; + this._shader = null; + + } + + get aoPassMap() { + + return this._aoPassMap; + + } + + set aoPassMap( aoPassMap ) { + + this._aoPassMap = aoPassMap; + this.needsUpdate = true; + this._setUniforms(); + + } + + _customProgramCacheKey() { + + return this._aoPassMap !== undefined && this._aoPassMap !== null ? 'aoPassMap' : ''; + + } + + _onBeforeCompile( shader ) { + + this._shader = shader; + + if ( this._aoPassMap !== undefined && this._aoPassMap !== null ) { + + shader.fragmentShader = shader.fragmentShader.replace( + '#include ', + aomap_pars_fragment_replacement + ); + shader.fragmentShader = shader.fragmentShader.replace( + '#include ', + aomap_fragment_replacement + ); + + } + + this._setUniforms(); + + } + + _setUniforms() { + + if ( this._shader ) { + + this._shader.uniforms.tAoPassMap = { value: this._aoPassMap }; + this._shader.uniforms.aoPassMapScale = { value: this.aoPassMapScale }; + + } + + } + +} + +const aomap_pars_fragment_replacement = /* glsl */` +#ifdef USE_AOMAP + + uniform sampler2D aoMap; + uniform float aoMapIntensity; + +#endif + + uniform sampler2D tAoPassMap; + uniform float aoPassMapScale; +`; + +const aomap_fragment_replacement = /* glsl */` +#ifndef AOPASSMAP_SWIZZLE + #define AOPASSMAP_SWIZZLE r +#endif + float ambientOcclusion = texelFetch( tAoPassMap, ivec2( gl_FragCoord.xy * aoPassMapScale ), 0 ).AOPASSMAP_SWIZZLE; + +#ifdef USE_AOMAP + + // reads channel R, compatible with a combined OcclusionRoughnessMetallic (RGB) texture + ambientOcclusion = min( ambientOcclusion, texture2D( aoMap, vAoMapUv ).r ); + ambientOcclusion *= ( ambientOcclusion - 1.0 ) * aoMapIntensity + 1.0; + +#endif + + reflectedLight.indirectDiffuse *= ambientOcclusion; + + #if defined( USE_CLEARCOAT ) + clearcoatSpecularIndirect *= ambientOcclusion; + #endif + + #if defined( USE_SHEEN ) + sheenSpecularIndirect *= ambientOcclusion; + #endif + + #if defined( USE_ENVMAP ) && defined( STANDARD ) + + float dotNV = saturate( dot( geometryNormal, geometryViewDir ) ); + + reflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.roughness ); + + #endif +`; + +export { MeshPostProcessingMaterial }; diff --git a/examples/jsm/postprocessing/GTAOPass.js b/examples/jsm/postprocessing/GTAOPass.js index 14a06338a48a26..ad0a76214bbcbc 100644 --- a/examples/jsm/postprocessing/GTAOPass.js +++ b/examples/jsm/postprocessing/GTAOPass.js @@ -162,6 +162,12 @@ class GTAOPass extends Pass { } + get gtaoMap() { + + return this.pdRenderTarget.texture; + + } + setGBuffer( depthTexture, normalTexture ) { if ( depthTexture !== undefined ) { @@ -359,6 +365,9 @@ class GTAOPass extends Pass { switch ( this.output ) { + case GTAOPass.OUTPUT.Off: + break; + case GTAOPass.OUTPUT.Diffuse: this.copyMaterial.uniforms.tDiffuse.value = readBuffer.texture; @@ -561,6 +570,7 @@ class GTAOPass extends Pass { } GTAOPass.OUTPUT = { + 'Off': - 1, 'Default': 0, 'Diffuse': 1, 'Depth': 2, diff --git a/examples/screenshots/webgl_postprocessing_material_ao.jpg b/examples/screenshots/webgl_postprocessing_material_ao.jpg new file mode 100644 index 00000000000000..210f06ddbe9577 Binary files /dev/null and b/examples/screenshots/webgl_postprocessing_material_ao.jpg differ diff --git a/examples/tags.json b/examples/tags.json index a5bf7deca1fb33..540e1e3c2809ea 100644 --- a/examples/tags.json +++ b/examples/tags.json @@ -88,6 +88,7 @@ "webgl_postprocessing_fxaa": [ "msaa", "multisampled" ], "webgl_postprocessing_godrays": [ "light scattering" ], "webgl_postprocessing_gtao": [ "ambient occlusion" ], + "webgl_postprocessing_material_ao": [ "ambient occlusion"], "webgl_shadowmap_progressive": [ "shadow", "soft", "lightmap", "onBeforeCompile" ], "webgl_postprocessing_ssaa": [ "msaa", "multisampled" ], "webgl_postprocessing_ssaa_unbiased": [ "msaa", "multisampled" ], diff --git a/examples/webgl_postprocessing_material_ao.html b/examples/webgl_postprocessing_material_ao.html new file mode 100644 index 00000000000000..b97144e3740c02 --- /dev/null +++ b/examples/webgl_postprocessing_material_ao.html @@ -0,0 +1,278 @@ + + + + three.js webgl - postprocessing - GTAO + + + + + + +
+ three.js - Mesh Post Processing Material by Rabbid76
+

Improved application of the AO passes by using the AO directly in the material shader instead of simply blending with the whole scene

+
+ + + + + +