Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/files.json
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,7 @@
"webgpu_postprocessing_3dlut",
"webgpu_postprocessing_afterimage",
"webgpu_postprocessing_anamorphic",
"webgpu_postprocessing_ao",
"webgpu_postprocessing_dof",
"webgpu_postprocessing_sobel",
"webgpu_postprocessing",
Expand Down
Binary file added examples/screenshots/webgpu_postprocessing_ao.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
138 changes: 138 additions & 0 deletions examples/webgpu_postprocessing_ao.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgpu - ambient occlusion (GTAO)</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<link type="text/css" rel="stylesheet" href="main.css">
</head>
<body>
<script type="importmap">
{
"imports": {
"three": "../build/three.webgpu.js",
"three/tsl": "../build/three.webgpu.js",
"three/addons/": "./jsm/"
}
}
</script>

<script type="module">

import * as THREE from 'three';
import { pass, mrt, output, transformedNormalView } from 'three/tsl';

import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js';
import { RGBELoader } from 'three/addons/loaders/RGBELoader.js';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';

import Stats from 'three/addons/libs/stats.module.js';

let camera, scene, renderer, postProcessing, controls, clock, stats, mixer;

init();

async function init() {

camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 100 );
camera.position.set( 5, 2, 8 );

scene = new THREE.Scene();
scene.background = new THREE.Color( 0xbfe3dd );

clock = new THREE.Clock();

const hdrloader = new RGBELoader();
const texture = await hdrloader.loadAsync( 'textures/equirectangular/quarry_01_1k.hdr' );
texture.mapping = THREE.EquirectangularReflectionMapping;

scene.environment = texture;

renderer = new THREE.WebGPURenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setAnimationLoop( animate );
document.body.appendChild( renderer.domElement );

controls = new OrbitControls( camera, renderer.domElement );
controls.target.set( 0, 0.5, 0 );
controls.update();
controls.enablePan = false;
controls.enableDamping = true;

stats = new Stats();
document.body.appendChild( stats.dom );

//

postProcessing = new THREE.PostProcessing( renderer );

const scenePass = pass( scene, camera );
scenePass.setMRT( mrt( {
output: output,
normal: transformedNormalView
} ) );

const scenePassColor = scenePass.getTextureNode( 'output' );
const scenePassNormal = scenePass.getTextureNode( 'normal' );
const scenePassDepth = scenePass.getTextureNode( 'depth' );

const aoPass = scenePassColor.ao( scenePassDepth, scenePassNormal, camera );

postProcessing.outputNode = aoPass;

//

const dracoLoader = new DRACOLoader();
dracoLoader.setDecoderPath( 'jsm/libs/draco/' );
dracoLoader.setDecoderConfig( { type: 'js' } );
const loader = new GLTFLoader();
loader.setDRACOLoader( dracoLoader );
loader.setPath( 'models/gltf/' );

const gltf = await loader.loadAsync( 'LittlestTokyo.glb' );

const model = gltf.scene;
model.position.set( 1, 1, 0 );
model.scale.set( 0.01, 0.01, 0.01 );
scene.add( model );

mixer = new THREE.AnimationMixer( model );
mixer.clipAction( gltf.animations[ 0 ] ).play();

window.addEventListener( 'resize', onWindowResize );

}

function onWindowResize() {

const width = window.innerWidth;
const height = window.innerHeight;

camera.aspect = width / height;
camera.updateProjectionMatrix();

renderer.setSize( width, height );

}

function animate() {

const delta = clock.getDelta();

if ( mixer ) {

mixer.update( delta );

}

controls.update();

postProcessing.render();
stats.update();

}

</script>
</body>
</html>
1 change: 1 addition & 0 deletions src/nodes/Nodes.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ export { default as DotScreenNode, dotScreen } from './display/DotScreenNode.js'
export { default as RGBShiftNode, rgbShift } from './display/RGBShiftNode.js';
export { default as FilmNode, film } from './display/FilmNode.js';
export { default as Lut3DNode, lut3D } from './display/Lut3DNode.js';
export { default as GTAONode, ao } from './display/GTAONode.js';
export { default as RenderOutputNode, renderOutput } from './display/RenderOutputNode.js';

export { default as PassNode, pass, passTexture, depthPass } from './display/PassNode.js';
Expand Down
Loading