Skip to content

Commit

Permalink
yas
Browse files Browse the repository at this point in the history
  • Loading branch information
N8 committed Jan 18, 2024
1 parent b9dce99 commit 380ecba
Show file tree
Hide file tree
Showing 16 changed files with 1,251 additions and 608 deletions.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,17 @@ You can also force N8AO to treat a transparent object as opaque (useful if you a
mesh.userData.treatAsOpaque = true;
```

# Accumulation

When the camera is still, you can enable the accumulation of samples across frames, which will reduce noise and improve the quality of the AO effect. This is done by setting `configuration.accumulate` to `true`:

```js
n8aopass.configuration.accumulate = true;
```

For the best results, `denoiseRadius` should be set to 0 and `denoiseSamples` should be set to 1. This will ensure that the AO effect is not blurred, and that the accumulation is purely temporal.

The accumulation effect works best in scenes with no motion - as it does not calculate motion vectors and will only work with the camera still. If the camera is moving, the accumulation effect will be disabled automatically. But if an object is moving, N8AO won't be able to pick up on that and the object's ambient occlusion will become blurred.
# Stencil

N8AOPass supports stencil buffers, but you must enable them via `configuration.stencil`:
Expand Down
437 changes: 296 additions & 141 deletions dist/N8AO.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/N8AO.js.map

Large diffs are not rendered by default.

437 changes: 296 additions & 141 deletions example/N8AO.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion example/N8AO.js.map

Large diffs are not rendered by default.

21 changes: 14 additions & 7 deletions example/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ async function main() {
renderMode: "Combined",
color: [0, 0, 0],
colorMultiply: true,
stencil: true
stencil: true,
accumulate: false
};
const gui = new GUI();
gui.add(effectController, "aoSamples", 1.0, 64.0, 1.0);
Expand Down Expand Up @@ -143,6 +144,7 @@ async function main() {
gui.add(effectController, "intensity", 0.0, 10.0, 0.01);
gui.addColor(effectController, "color");
gui.add(effectController, "colorMultiply");
gui.add(effectController, "accumulate");
gui.add(effectController, "renderMode", ["Combined", "AO", "No AO", "Split", "Split AO"]);
// Post Effects
const composer = new EffectComposer(renderer);
Expand All @@ -166,15 +168,19 @@ async function main() {
const timerDOM = document.getElementById("aoTime");
const aoMeta = document.getElementById("aoMetadata");
n8aopass.enableDebugMode();
const clock = new THREE.Clock();

function animate() {
aoMeta.innerHTML = `${clientWidth}x${clientHeight}`
torusKnot.rotation.x = performance.now() * 0.002;
torusKnot.rotation.y = performance.now() * 0.002;
torusKnot2.rotation.x = performance.now() * 0.002;
torusKnot2.rotation.y = performance.now() * 0.002;
torusKnot3.rotation.x = performance.now() * 0.002;
torusKnot3.rotation.y = performance.now() * 0.002;
const spin = 2 * clock.getDelta();
if (!effectController.accumulate) {
torusKnot.rotation.x += spin;
torusKnot.rotation.y += spin;
torusKnot2.rotation.x += spin;
torusKnot2.rotation.y += spin;
torusKnot3.rotation.x += spin;
torusKnot3.rotation.y += spin;
}
torusKnot2.material.opacity = Math.sin(performance.now() * 0.001) * 0.5 + 0.5;
torusKnot3.material.opacity = Math.cos(performance.now() * 0.001) * 0.5 + 0.5;
torusKnotShadow2.material.color.g = 1 - 0.6 * torusKnot2.material.opacity;
Expand Down Expand Up @@ -207,6 +213,7 @@ async function main() {
n8aopass.configuration.halfRes = effectController.halfRes;
n8aopass.configuration.depthAwareUpsampling = effectController.depthAwareUpsampling;
n8aopass.configuration.colorMultiply = effectController.colorMultiply;
n8aopass.configuration.accumulate = effectController.accumulate;
composer.render();
timerDOM.innerHTML = n8aopass.lastTime.toFixed(2);
controls.update();
Expand Down
437 changes: 296 additions & 141 deletions example_postprocessing/N8AO.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion example_postprocessing/N8AO.js.map

Large diffs are not rendered by default.

19 changes: 13 additions & 6 deletions example_postprocessing/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ async function main() {
renderMode: "Combined",
color: [0, 0, 0],
colorMultiply: true,
accumulate: false
};
const gui = new GUI();
gui.add(effectController, "aoSamples", 1.0, 64.0, 1.0);
Expand Down Expand Up @@ -139,6 +140,7 @@ async function main() {
gui.add(effectController, "intensity", 0.0, 10.0, 0.01);
gui.addColor(effectController, "color");
gui.add(effectController, "colorMultiply");
gui.add(effectController, "accumulate");
gui.add(effectController, "renderMode", ["Combined", "AO", "No AO", "Split", "Split AO"]);
// Post Effects
// const composer = new EffectComposer(renderer);
Expand Down Expand Up @@ -182,15 +184,19 @@ async function main() {
const aoMeta = document.getElementById("aoMetadata");
n8aopass.enableDebugMode();
torusKnotShadow.userData.treatAsOpaque = true;
const clock = new THREE.Clock();

function animate() {
aoMeta.innerHTML = `${clientWidth}x${clientHeight}`
torusKnot.rotation.x = performance.now() * 0.002;
torusKnot.rotation.y = performance.now() * 0.002;
torusKnot2.rotation.x = performance.now() * 0.002;
torusKnot2.rotation.y = performance.now() * 0.002;
torusKnot3.rotation.x = performance.now() * 0.002;
torusKnot3.rotation.y = performance.now() * 0.002;
const spin = 2 * clock.getDelta();
if (!effectController.accumulate) {
torusKnot.rotation.x += spin;
torusKnot.rotation.y += spin;
torusKnot2.rotation.x += spin;
torusKnot2.rotation.y += spin;
torusKnot3.rotation.x += spin;
torusKnot3.rotation.y += spin;
}
torusKnot2.material.opacity = Math.sin(performance.now() * 0.001) * 0.5 + 0.5;
torusKnot3.material.opacity = Math.cos(performance.now() * 0.001) * 0.5 + 0.5;
torusKnotShadow2.material.color.g = 1 - 0.6 * torusKnot2.material.opacity;
Expand Down Expand Up @@ -221,6 +227,7 @@ async function main() {
n8aopass.configuration.halfRes = effectController.halfRes;
n8aopass.configuration.depthAwareUpsampling = effectController.depthAwareUpsampling;
n8aopass.configuration.colorMultiply = effectController.colorMultiply;
n8aopass.configuration.accumulate = effectController.accumulate;
composer.render();
timerDOM.innerHTML = n8aopass.lastTime.toFixed(2);
controls.update();
Expand Down
46 changes: 18 additions & 28 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "n8ao",
"version": "1.7.4",
"version": "1.8.0",
"description": "An efficient and visually pleasing implementation of SSAO with an emphasis on temporal stability and artist control.",
"main": "dist/N8AO.js",
"scripts": {
Expand Down
10 changes: 5 additions & 5 deletions src/EffectCompositer.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ const EffectCompositer = {
vec2 pUv = vec2(p) / (resolution * 0.5);
float sampleDepth = texelFetch(downsampledDepth,p, 0).x;
vec4 sampleInfo = texelFetch(tDiffuse, p, 0);
vec3 normalSample = sampleInfo.xyz * 2.0 - 1.0;
vec3 normalSample = sampleInfo.gba * 2.0 - 1.0;
vec3 worldPosSample = getWorldPos(sampleDepth, pUv);
float tangentPlaneDist = abs(dot(worldPosSample - worldPos, normal));
float rangeCheck = exp(-1.0 * tangentPlaneDist * (1.0 / distanceFalloffToUse)) * max(dot(normal, normalSample), 0.0);
Expand All @@ -207,13 +207,13 @@ const EffectCompositer = {
#endif
#ifdef LOGDEPTH
texel.a = clamp(texel.a, 0.0, 1.0);
if (texel.a == 0.0) {
texel.a = 1.0;
texel.r = clamp(texel.r, 0.0, 1.0);
if (texel.r == 0.0) {
texel.r = 1.0;
}
#endif
float finalAo = pow(texel.a, intensity);
float finalAo = pow(texel.r, intensity);
float fogFactor;
float fogDepth = distance(
cameraPos,
Expand Down
12 changes: 10 additions & 2 deletions src/EffectShader.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ const EffectShader = {
'far': { value: 1000.0 },
'logDepth': { value: false },
'ortho': { value: false },
'screenSpaceRadius': { value: false }
'screenSpaceRadius': { value: false },
'frame': { value: 0.0 }
},
depthWrite: false,
depthTest: false,
Expand Down Expand Up @@ -52,6 +53,7 @@ uniform float radius;
uniform float distanceFalloff;
uniform float near;
uniform float far;
uniform float frame;
uniform bool logDepth;
uniform bool ortho;
uniform bool screenSpaceRadius;
Expand Down Expand Up @@ -151,6 +153,12 @@ void main() {
vec3 normal = computeNormal(worldPos, vUv);
#endif
vec4 noise = texture2D(bluenoise, gl_FragCoord.xy / 128.0);
vec2 harmoniousNumbers = vec2(
1.618033988749895,
1.324717957244746
);
noise.rg += harmoniousNumbers * frame;
noise.rg = fract(noise.rg);
vec3 helperVec = vec3(0.0, 1.0, 0.0);
if (dot(helperVec, normal) > 0.99) {
helperVec = vec3(1.0, 0.0, 0.0);
Expand Down Expand Up @@ -215,7 +223,7 @@ void main() {
totalWeight += sampleValid;
}
float occ = clamp(1.0 - occluded / (totalWeight == 0.0 ? 1.0 : totalWeight), 0.0, 1.0);
gl_FragColor = vec4(0.5 + 0.5 * normal, occ);
gl_FragColor = vec4(occ, 0.5 + 0.5 * normal);
}`


Expand Down
Loading

0 comments on commit 380ecba

Please sign in to comment.