Преглед изворни кода

Implement SSAOPlugin and example.

master
Palash Bansal пре 2 година
родитељ
комит
d017cdb29c
No account linked to committer's email address

+ 34
- 0
README.md Прегледај датотеку

@@ -95,6 +95,7 @@ To make changes and run the example, click on the CodePen button on the top righ
- [DepthBufferPlugin](#depthbufferplugin) - Pre-rendering of depth buffer
- [NormalBufferPlugin](#normalbufferplugin) - Pre-rendering of normal buffer
- [GBufferPlugin](#gbufferplugin) - Pre-rendering of depth-normal and flags buffers in a single pass
- [SSAOPlugin](#ssaoplugin) - Add SSAO(Screen Space Ambient Occlusion) for physical materials.
- [CanvasSnapshotPlugin](#canvassnapshotplugin) - Add support for taking snapshots of the canvas
- [PickingPlugin](#pickingplugin) - Adds support for selecting objects in the viewer with user interactions and selection widgets
- [TransformControlsPlugin](#transformcontrolsplugin) - Adds support for moving, rotating and scaling objects in the viewer with interactive widgets
@@ -2265,6 +2266,39 @@ const normalDepth = gBufferPlugin.normalDepthTexture;
const gBufferFlags = gBufferPlugin.flagsTexture;
```

## SSAOPlugin

[//]: # (todo: image)

[Example](https://threepipe.org/examples/#ssao-plugin/) —
[Source Code](./src/plugins/pipeline/SSAOPlugin.ts) —
[API Reference](https://threepipe.org/docs/classes/SSAOPlugin.html)

SSAO Plugin adds support for [Screen Space Ambient Occlusion](https://en.wikipedia.org/wiki/Screen_space_ambient_occlusion) to the viewer. Simply add the plugin to the viewer to use it.

This is done by adding a pre-render pass to the render manager which renders SSAO to a custom render target. SSAOPlugin depends on [GBufferPlugin](#gbufferplugin), and is automatically added if not already.

This render target is then used by all PhysicalMaterial(s) in the scene during the main RenderPass to get the AO data. SSAO can also be disabled from the UI of the material.

Note: Use with [ProgressivePlugin](#progressiveplugin) and `TemporalAAPlugin` for best results.

```typescript
import {ThreeViewer, SSAOPlugin} from 'threepipe'

const viewer = new ThreeViewer({...})

const ssaoPlugin = viewer.addPluginSync(new SSAOPlugin())

// get the buffer.
console.log(ssaoPlugin.target);

// disable ssao for a material in the scene
material.userData.ssaoDisabled = true
```
> In the target/buffer - The ssao data is in the `r` channel to remain compatible with ORM. `gba` contains the depth in vec3(xyz) format.
> Note that its `ssaoDisabled`, so setting it to `true` will disable the effect.


## CanvasSnapshotPlugin

[//]: # (todo: image)

+ 1
- 0
examples/index.html Прегледај датотеку

@@ -326,6 +326,7 @@
<li><a href="./depth-buffer-plugin/">Depth Buffer Plugin </a></li>
<li><a href="./normal-buffer-plugin/">Normal Buffer Plugin </a></li>
<li><a href="./gbuffer-plugin/">GBuffer Plugin <br/>(NormalDepth+Flags) </a></li>
<li><a href="./ssao-plugin/">SSAO Plugin </a></li>
<li><a href="./virtual-cameras-plugin/">Virtual Cameras Plugin </a></li>
<li><a href="./virtual-camera/">Virtual Camera (Animated) </a></li>
</ul>

+ 36
- 0
examples/ssao-plugin/index.html Прегледај датотеку

@@ -0,0 +1,36 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>SSAO Plugin</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Import maps polyfill -->
<!-- Remove this when import maps will be widely supported -->
<script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script>

<script type="importmap">
{
"imports": {
"threepipe": "./../../dist/index.mjs",
"@threepipe/plugin-tweakpane": "./../../plugins/tweakpane/dist/index.mjs"
}
}

</script>
<style id="example-style">
html, body, #canvas-container, #mcanvas {
width: 100%;
height: 100%;
margin: 0;
overflow: hidden;
}
</style>
<script type="module" src="../examples-utils/simple-code-preview.mjs"></script>
<script id="example-script" type="module" src="./script.js" data-scripts="./script.ts;./script.js"></script>
</head>
<body>
<div id="canvas-container">
<canvas id="mcanvas"></canvas>
</div>

</body>

+ 42
- 0
examples/ssao-plugin/script.ts Прегледај датотеку

@@ -0,0 +1,42 @@
import {
_testFinish,
ProgressivePlugin,
RenderTargetPreviewPlugin,
SSAOPlugin,
ThreeViewer,
UnsignedByteType,
} from 'threepipe'
import {TweakpaneUiPlugin} from '@threepipe/plugin-tweakpane'

const viewer = new ThreeViewer({
canvas: document.getElementById('mcanvas') as HTMLCanvasElement,
msaa: true,
plugins: [ProgressivePlugin],
})

async function init() {

const ssaoPlugin = viewer.addPluginSync(new SSAOPlugin(UnsignedByteType, 1))

await viewer.setEnvironmentMap('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr')
await viewer.load('https://threejs.org/examples/models/gltf/kira.glb', {
autoCenter: true,
autoScale: true,
})

const ssaoTarget = ssaoPlugin.target
if (!ssaoTarget) {
throw new Error('ssaoPlugin.target returned undefined')
}

// to render ssao buffer to screen, uncomment this line:
// viewer.renderManager.screenPass.overrideReadBuffer = ssaoTarget

const targetPreview = await viewer.addPlugin(RenderTargetPreviewPlugin)
targetPreview.addTarget(()=>ssaoTarget, 'ssao', false, true, true, (s)=>`${s} = vec4(${s}.r);`)

const ui = viewer.addPluginSync(TweakpaneUiPlugin, true)
ui.setupPluginUi(SSAOPlugin)
}

init().finally(_testFinish)

+ 0
- 4
src/core/IMaterial.ts Прегледај датотеку

@@ -79,10 +79,6 @@ export interface IMaterialUserData extends IImportResultUserData{

// todo: move these to respective plugins

/**
* For SSAOPlugin
*/
ssaoDisabled?: boolean
/**
* For SSCSPlugin
*/

+ 1
- 0
src/plugins/index.ts Прегледај датотеку

@@ -14,6 +14,7 @@ export type {ProgressivePluginEventTypes, ProgressivePluginTarget} from './pipel
export type {GBufferPluginEventTypes, GBufferPluginPass, GBufferUpdater, GBufferUpdaterContext} from './pipeline/GBufferPlugin'
export type {DepthBufferPluginEventTypes, DepthBufferPluginPass, DepthBufferPluginTarget} from './pipeline/DepthBufferPlugin'
export type {NormalBufferPluginEventTypes, NormalBufferPluginPass, NormalBufferPluginTarget} from './pipeline/NormalBufferPlugin'
export {SSAOPlugin, SSAOPluginPass, type SSAOPluginEventTypes, type SSAOPluginTarget} from './pipeline/SSAOPlugin'

// ui
export {RenderTargetPreviewPlugin} from './ui/RenderTargetPreviewPlugin'

+ 1
- 0
src/plugins/pipeline/GBufferPlugin.ts Прегледај датотеку

@@ -137,6 +137,7 @@ export class GBufferPlugin
['GBUFFER_HAS_FLAGS']: ()=>this.flagsTexture ? 1 : undefined,
// ['HAS_FLAGS_BUFFER']: ()=>this.flagsTexture ? 1 : undefined,
['HAS_GBUFFER']: ()=>this.isPrimaryGBuffer && this.normalDepthTexture ? 1 : undefined,
// LINEAR_DEPTH: 1, // to tell that the depth is linear. todo; see SSAOPlugin. also add support in DepthBufferPlugin?
},
priority: 100,
isCompatible: () => true,

+ 326
- 0
src/plugins/pipeline/SSAOPlugin.ts Прегледај датотеку

@@ -0,0 +1,326 @@
import {Matrix4, Texture, TextureDataType, UnsignedByteType, Vector2, Vector3, Vector4, WebGLRenderTarget} from 'three'
import {ExtendedShaderPass, IPassID, IPipelinePass} from '../../postprocessing'
import {ThreeViewer} from '../../viewer'
import {PipelinePassPlugin} from '../base/PipelinePassPlugin'
import {uiConfig, uiFolderContainer, uiImage, uiSlider} from 'uiconfig.js'
import {ICamera, IMaterial, IRenderManager, IScene, IWebGLRenderer, PhysicalMaterial} from '../../core'
import {getOrCall, glsl, onChange2, serialize, ValOrFunc} from 'ts-browser-helpers'
import {MaterialExtension} from '../../materials'
import {shaderReplaceString, shaderUtils} from '../../utils'
import {getTexelDecoding, matDefine} from '../../three'
import ssaoPass from './shaders/SSAOPlugin.pass.glsl'
import ssaoPatch from './shaders/SSAOPlugin.patch.glsl'
import {uiConfigMaterialExtension} from '../../materials/MaterialExtender'
import {GBufferPlugin} from './GBufferPlugin'

export type SSAOPluginEventTypes = ''
export type SSAOPluginTarget = WebGLRenderTarget

/**
* SSAO Plugin
*
* Adds a post-render pass to blend the last frame with the current frame.
* This can be used to create a progressive rendering effect which is useful for progressive shadows, gi, denoising, baking, anti-aliasing, and many other effects.
* @category Plugins
*/
@uiFolderContainer('SSAO Plugin')
export class SSAOPlugin
extends PipelinePassPlugin<SSAOPluginPass, 'ssao', SSAOPluginEventTypes> {

readonly passId = 'ssao'
public static readonly PluginType = 'SSAOPlugin'

dependencies = [GBufferPlugin]

target?: SSAOPluginTarget
@uiImage('SSAO Buffer' /* {readOnly: true}*/) texture?: Texture

@uiConfig() protected _pass?: SSAOPluginPass

// @onChange2(SSAOPlugin.prototype._createTarget)
// @uiDropdown('Buffer Type', threeConstMappings.TextureDataType.uiConfig)
readonly bufferType: TextureDataType // cannot be changed after creation (for now)

// @onChange2(SSAOPlugin.prototype._createTarget)
// @uiSlider('Buffer Size Multiplier', [0.25, 2.0], 0.25)
readonly sizeMultiplier: number // cannot be changed after creation (for now)

constructor(
bufferType: TextureDataType = UnsignedByteType,
sizeMultiplier = 1,
enabled = true,
) {
super()
this.enabled = enabled
this.bufferType = bufferType
this.sizeMultiplier = sizeMultiplier
}

protected _createTarget(recreate = true) {
if (!this._viewer) return
if (recreate) this._disposeTarget()
if (!this.target)
this.target = this._viewer.renderManager.createTarget<SSAOPluginTarget>(
{
depthBuffer: false,
type: this.bufferType,
sizeMultiplier: this.sizeMultiplier,
// magFilter: NearestFilter,
// minFilter: NearestFilter,
// generateMipmaps: false,
// encoding: LinearEncoding,
})

this.texture = this.target.texture
this.texture.name = 'ssaoBuffer'

if (this._pass) this._pass.target = this.target
}

protected _disposeTarget() {
if (!this._viewer) return
if (this.target) {
this._viewer.renderManager.disposeTarget(this.target)
this.target = undefined
}
this.texture = undefined
}

private _gbufferUnpackExtension = undefined as MaterialExtension|undefined
private _gbufferUnpackExtensionChanged = ()=>{
if (!this._pass || !this._viewer) throw new Error('SSAOPlugin: pass/viewer not created yet')
const newExtension = this._viewer.renderManager.gbufferUnpackExtension
if (this._gbufferUnpackExtension === newExtension) return
if (this._gbufferUnpackExtension) this._pass.material.unregisterMaterialExtensions([this._gbufferUnpackExtension])
this._gbufferUnpackExtension = newExtension
if (this._gbufferUnpackExtension) this._pass.material.registerMaterialExtensions([this._gbufferUnpackExtension])
else this._viewer.console.warn('SSAOPlugin: GBuffer unpack extension removed')
}

protected _createPass() {
if (!this._viewer) throw new Error('SSAOPlugin: viewer not set')
if (!this._viewer.renderManager.gbufferTarget || !this._viewer.renderManager.gbufferUnpackExtension)
throw new Error('SSAOPlugin: GBuffer target not created. GBufferPlugin or DepthBufferPlugin is required.')
this._createTarget(true)
const pass = new SSAOPluginPass(this.passId, this.target)
pass.before = ['render']
pass.after = ['gbuffer', 'depth']
pass.required = ['render'] // gbuffer required check above.
return pass
}

onAdded(viewer: ThreeViewer) {
super.onAdded(viewer)
this._gbufferUnpackExtensionChanged()
viewer.renderManager.addEventListener('gbufferUnpackExtensionChanged', this._gbufferUnpackExtensionChanged)
}

onRemove(viewer: ThreeViewer): void {
this._disposeTarget()
return super.onRemove(viewer)
}

/**
* @deprecated use {@link target} instead
*/
get aoTarget() {
console.warn('SSAOPlugin: aoTarget is deprecated, use target instead')
return this.target
}

}

@uiFolderContainer('SSAO Pass')
export class SSAOPluginPass extends ExtendedShaderPass implements IPipelinePass {
before = ['screen']
after = ['render']
required = ['render']

// todo bilateralPass
// @serialize() readonly bilateralPass: BilateralFilterPass

// todo old deserialize
// @serialize() readonly parameters: SSAOParams = {
// intensity: 0.25,
// occlusionWorldRadius: 1,
// bias: 0.001,
// falloff: 1.3,
// }
@serialize()
@uiSlider('Intensity', [0, 4], 0.01)
@onChange2(SSAOPluginPass.prototype.setDirty)
intensity = 0.25

@serialize()
@uiSlider('Occlusion World Radius', [0.1, 8], 0.01)
@onChange2(SSAOPluginPass.prototype.setDirty)
occlusionWorldRadius = 1

@serialize()
@uiSlider('Bias', [0.00001, 0.01], 0.00001)
@onChange2(SSAOPluginPass.prototype.setDirty)
bias = 0.001

@serialize()
@uiSlider('Falloff', [0.01, 3], 0.01)
@onChange2(SSAOPluginPass.prototype.setDirty)
falloff = 1.3

@serialize()
@uiSlider('Num Samples', [1, 11], 1)
@matDefine('NUM_SAMPLES', undefined, undefined, SSAOPluginPass.prototype.setDirty)
numSamples = 8

// todo after bilateralPass is implemented
// @bindToValue({obj: 'bilateralPass', key: 'enabled', onChange: 'setDirty'})
// smoothEnabled = true
// todo after bilateralPass is implemented
// @bindToValue({obj: 'bilateralPass', key: 'enabled', onChange: 'setDirty'})
// smoothEdgeSharpness = true

constructor(public readonly passId: IPassID, public target?: ValOrFunc<WebGLRenderTarget|undefined>) {
super({
defines: {
LINEAR_DEPTH: 1, // todo set from unpack extension
NUM_SAMPLES: 11,
NUM_SPIRAL_TURNS: 3,
PERSPECTIVE_CAMERA: 1, // set in PerspectiveCamera2
},
uniforms: {
tLastThis: {value: null},
screenSize: {value: new Vector2(0, 0)}, // set in ExtendedRenderMaterial
saoData: {value: new Vector4()},
frameCount: {value: 0}, // set in RenderManager
cameraNearFar: {value: new Vector2(0.1, 1000)}, // set in PerspectiveCamera2
projection: {value: new Matrix4()}, // set in PerspectiveCamera2
saoBiasEpsilon: {value: new Vector3(1, 1, 1)},
},

vertexShader: shaderUtils.defaultVertex,

fragmentShader: ssaoPass,

}, 'tDiffuse')

this.needsSwap = false
this.clear = true
// this.bilateralPass = new BilateralFilterPass(this._target as any, gBufferUnpack, 'rrrr')
// this._multiplyPass = new GenericBlendTexturePass(this._target.texture as any, 'c = vec4((1.0-b.r) * a.xyz, a.a);')
}

render(renderer: IWebGLRenderer, writeBuffer: WebGLRenderTarget, readBuffer: WebGLRenderTarget, deltaTime: number, maskActive: boolean) {
if (!this.enabled) return
const target = getOrCall(this.target)
if (!target) {
console.warn('SSAOPluginPass: target not defined')
return
}
this._updateParameters()
if (!this.material.defines.HAS_GBUFFER) {
console.warn('SSAOPluginPass: DepthNormalBuffer required for ssao')
}
renderer.renderManager.blit(writeBuffer, {
source: target.texture,
})
this.uniforms.tLastThis.value = writeBuffer.texture
super.render(renderer, target, readBuffer, deltaTime, maskActive)

// todo
// if (this.smoothEnabled) {
// this.bilateralPass.render(renderer, writeBuffer, readBuffer, deltaTime, maskActive)
// }
}

private _updateParameters() {
// const projectionScale = 1 / (Math.tan(DEG2RAD * (camera as any).fov / 2) * 2);
const saoData = this.material.uniforms.saoData.value
// saoData.x = projectionScale;
saoData.y = this.intensity
saoData.z = this.occlusionWorldRadius
// saoData.w = this.accIndex_++;

const saoBiasEpsilon = this.material.uniforms.saoBiasEpsilon.value
saoBiasEpsilon.x = this.bias
saoBiasEpsilon.y = 0.001
saoBiasEpsilon.z = this.falloff

// this.material.uniforms.size.value.set(this._target.texture.image?.width, this._target.texture.image?.height)
}

beforeRender(_: IScene, camera: ICamera, renderManager: IRenderManager) {
if (!this.enabled) return
this.updateShaderProperties([camera, renderManager])
}

readonly materialExtension: MaterialExtension = {
extraUniforms: {
tSSAOMap: ()=>({value: getOrCall(this.target)?.texture ?? null}),
},
shaderExtender: (shader, _material, _renderer) => {
if (!shader.defines.SSAO_ENABLED) return
shader.fragmentShader = shaderReplaceString(shader.fragmentShader, '#include <aomap_fragment>', ssaoPatch)
},
onObjectRender: (_object, material, renderer: any) => {
const opaque = !material.transparent && (!material.transmission || material.transmission < 0.001)
const x: any = this.enabled && opaque &&
renderer.userData.screenSpaceRendering !== false &&
!material.userData?.ssaoDisabled ? 1 : 0

if (material.defines!.SSAO_ENABLED !== x) {
material.defines!.SSAO_ENABLED = x
material.needsUpdate = true
}
},
parsFragmentSnippet: (renderer)=>glsl`
uniform sampler2D tSSAOMap;
${getTexelDecoding('tSSAOMap', getOrCall(this.target)?.texture, renderer!.capabilities.isWebGL2)}
#include <simpleCameraHelpers>
`,
computeCacheKey: () => {
return this.enabled ? '1' : '0' + getOrCall(this.target)?.texture?.colorSpace
},
uuid: SSAOPlugin.PluginType,
...uiConfigMaterialExtension(this._getUiConfig, SSAOPlugin.PluginType),
isCompatible: material => {
return (material as PhysicalMaterial).isPhysicalMaterial
},
}

/**
* Returns a uiConfig to toggle SSAO on a material.
* This uiConfig is added to each material by extension
* @param material
* @private
*/
protected _getUiConfig(material: IMaterial) {
return {
type: 'folder',
label: 'SSAO',
children: [
{
type: 'checkbox',
label: 'Enabled',
get value() {
return !(material.userData.ssaoDisabled ?? false)
},
set value(v) {
if (v === !(material.userData.ssaoDisabled ?? false)) return
material.userData.ssaoDisabled = !v
material.setDirty()
},
onChange: this.setDirty,
},
],
}
}

}

declare module '../../core/IMaterial' {
interface IMaterialUserData {
/**
* Disable SSAOPlugin for this material.
*/
ssaoDisabled?: boolean
}
}

+ 166
- 0
src/plugins/pipeline/shaders/SSAOPlugin.pass.glsl Прегледај датотеку

@@ -0,0 +1,166 @@
#include <randomHelpers>
#include <common>
#include <packing>
#define THREE_PACKING_INCLUDED
#include <cameraHelpers>

varying vec2 vUv;

uniform sampler2D tLastThis;
uniform float frameCount;

uniform vec4 saoData;
uniform vec3 saoBiasEpsilon;
uniform vec2 screenSize;

const float INV_NUM_SAMPLES = 1.0 / float(NUM_SAMPLES);

//int getSelectionBit(in int number) {
// #ifdef WebGL2Context
// return (number/4) % 2;
// #else
// return int(mod(floor(float(number)/4.), 2.));
// #endif
//}

vec3 packFloatToRGB(const in float x) {
const vec3 code = vec3(1.0, 255.0, 65025.0);
vec3 pack = vec3(code * x);
pack.gb = fract(pack.gb);
pack.rg -= pack.gb * (1.0 / 256.0);
return pack;
}

vec3 getPositionFromOffset(const in vec2 uv,
const in vec2 offset,
const in float screenSpaceRadius) {

vec2 uvOffset = uv + floor(screenSpaceRadius * offset) / screenSize;
#if defined(HAS_DEPTH_BUFFER) || defined(HAS_NORMAL_DEPTH_BUFFER)
float d = getDepth(uvOffset);
#else
float d = 0.5;
#endif

#if LINEAR_DEPTH == 0
float centerViewZ = viewZFromNDCZ(d);
return screenToView(uvOffset, centerViewZ);
#else
d = mix(-cameraNearFar.x, -cameraNearFar.y, d);
return screenToView(uvOffset, d);
#endif
}

float getOcclusion(const in vec2 uv,
const in int id,
const in float randomAngle,
const in float occlusionSphereRadius,
const in vec3 centerPosition,
const in vec3 centerNormal) {
float screenSpaceRadius = (float(id) + mod(randomAngle, 1.) + 0.5) * INV_NUM_SAMPLES;

float angle = screenSpaceRadius * (float(NUM_SPIRAL_TURNS) * 6.28) + randomAngle;

screenSpaceRadius = (screenSpaceRadius * occlusionSphereRadius);

vec2 offset = vec2(cos(angle), sin(angle));

vec3 samplePosition = getPositionFromOffset(uv, offset, screenSpaceRadius);
vec3 direction = samplePosition - centerPosition;
float d2 = dot(direction, direction);
float ao = max((dot(centerNormal, direction) + centerPosition.z * saoBiasEpsilon.x) / (saoBiasEpsilon.z * d2 + saoBiasEpsilon.y), 0.0);
return ao;
}

void main() {

// initial values
float centerDepth = 0.5;
vec3 centerNormal = vec3(0, 1, 0);

#ifdef HAS_NORMAL_DEPTH_BUFFER
getDepthNormal(vUv, centerDepth, centerNormal);
#else
#ifdef HAS_DEPTH_BUFFER
centerDepth = getDepth(vUv);
#endif

// todo - add support for NormalBufferPlugin
// #ifdef HAS_NORMAL_BUFFER
// centerDepth = getDepth(vUv);
// #endif

#endif

// if (centerDepth >= (1.0 - EPSILON)) {
// discard;
// }

#if LINEAR_DEPTH == 0
float centerViewZ = viewZFromNDCZ(centerDepth);
#else
float centerViewZ = mix(-cameraNearFar.x, -cameraNearFar.y, centerDepth);
#endif

vec3 centerPosition = screenToView(vUv, centerViewZ);


float occlusionSphereScreenRadius = 200. * saoData.z / (-centerPosition.z);

// if (occlusionSphereScreenRadius < 1.) {
// discard;
// }

float randomAngle = 6.2 * random3(vec3(vUv, frameCount * 0.1));

float sum = 0.0;

sum += getOcclusion(vUv, 0, randomAngle, occlusionSphereScreenRadius, centerPosition, centerNormal);
#if NUM_SAMPLES > 1
sum += getOcclusion(vUv, 1, randomAngle, occlusionSphereScreenRadius, centerPosition, centerNormal);
#endif
#if NUM_SAMPLES > 2
sum += getOcclusion(vUv, 2, randomAngle, occlusionSphereScreenRadius, centerPosition, centerNormal);
#endif
#if NUM_SAMPLES > 3
sum += getOcclusion(vUv, 3, randomAngle, occlusionSphereScreenRadius, centerPosition, centerNormal);
#endif
#if NUM_SAMPLES > 4
sum += getOcclusion(vUv, 4, randomAngle, occlusionSphereScreenRadius, centerPosition, centerNormal);
#endif
#if NUM_SAMPLES > 5
sum += getOcclusion(vUv, 5, randomAngle, occlusionSphereScreenRadius, centerPosition, centerNormal);
#endif
#if NUM_SAMPLES > 6
sum += getOcclusion(vUv, 6, randomAngle, occlusionSphereScreenRadius, centerPosition, centerNormal);
#endif
#if NUM_SAMPLES > 7
sum += getOcclusion(vUv, 7, randomAngle, occlusionSphereScreenRadius, centerPosition, centerNormal);
#endif
#if NUM_SAMPLES > 8
sum += getOcclusion(vUv, 8, randomAngle, occlusionSphereScreenRadius, centerPosition, centerNormal);
#endif
#if NUM_SAMPLES > 9
sum += getOcclusion(vUv, 9, randomAngle, occlusionSphereScreenRadius, centerPosition, centerNormal);
#endif
#if NUM_SAMPLES > 10
sum += getOcclusion(vUv, 10, randomAngle, occlusionSphereScreenRadius, centerPosition, centerNormal);
#endif

float aoValue = sum * saoData.y * INV_NUM_SAMPLES;

// bool disableAO = getSelectionBit(getGBufferFlags(vUv).a) > 0 ? true : false;

aoValue = 1. - clamp(aoValue, 0., 1.);

// so that depth can also be sampled with ssao if required?
gl_FragColor.gba = packFloatToRGB(centerDepth);

// vec4 lastAO = texture2D( tLastThis, vUv );

// gl_FragColor.r = (vec4(aoValue)).r;// + (lastAO.r) * frameCount)/(frameCount+1.);
gl_FragColor.r = aoValue;// + (lastAO.r) * frameCount)/(frameCount+1.);
// gl_FragColor.r = aoValue;

// gl_FragColor = vec4(centerDepth);
}

+ 24
- 0
src/plugins/pipeline/shaders/SSAOPlugin.patch.glsl Прегледај датотеку

@@ -0,0 +1,24 @@

#ifndef USE_TRANSMISSION

#if defined(SSAO_ENABLED) && SSAO_ENABLED > 0

// reads channel R, compatible with a combined OcclusionRoughnessMetallic (RGB) texture
float ambientOcclusion = tSSAOMapTexelToLinear ( texture2D( tSSAOMap, viewToScreen(vViewPosition.xyz).xy )).r; //todo: check encoding for tSSAOMap

reflectedLight.indirectDiffuse *= ambientOcclusion;

#if defined( USE_ENVMAP )

float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );

reflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.roughness );

#endif

#else
#include <aomap_fragment>
#endif

#endif


+ 6
- 0
src/utils/shaders/defaultVertex.glsl Прегледај датотеку

@@ -0,0 +1,6 @@

varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}

Loading…
Откажи
Сачувај