Skip to content

Commit

Permalink
LightProbeGenerator: adapt for WebGPU compatibility (mrdoob#29335)
Browse files Browse the repository at this point in the history
* adapt for webGPU

* improve backend detection

* rework

* rework

* exclude from tests

---------

Co-authored-by: aardgoose <angus.sawyer@email.com>
  • Loading branch information
aardgoose and aardgoose committed Sep 9, 2024
1 parent 5eabead commit bac758d
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 12 deletions.
1 change: 1 addition & 0 deletions examples/files.json
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,7 @@
"webgpu_instance_uniform",
"webgpu_instancing_morph",
"webgpu_lightprobe",
"webgpu_lightprobe_cubecamera",
"webgpu_lights_custom",
"webgpu_lights_ies_spotlight",
"webgpu_lights_phong",
Expand Down
34 changes: 24 additions & 10 deletions examples/jsm/lights/LightProbeGenerator.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import {
SRGBColorSpace,
NoColorSpace,
HalfFloatType,
DataUtils
DataUtils,
WebGLCoordinateSystem
} from 'three';

class LightProbeGenerator {
Expand Down Expand Up @@ -126,7 +127,9 @@ class LightProbeGenerator {

}

static fromCubeRenderTarget( renderer, cubeRenderTarget ) {
static async fromCubeRenderTarget( renderer, cubeRenderTarget ) {

const flip = renderer.coordinateSystem === WebGLCoordinateSystem ? -1 : 1;

// The renderTarget must be set to RGBA in order to make readRenderTargetPixels works
let totalWeight = 0;
Expand All @@ -143,12 +146,11 @@ class LightProbeGenerator {
const shCoefficients = sh.coefficients;

const dataType = cubeRenderTarget.texture.type;
const imageWidth = cubeRenderTarget.width; // assumed to be square

for ( let faceIndex = 0; faceIndex < 6; faceIndex ++ ) {

const imageWidth = cubeRenderTarget.width; // assumed to be square
let data;

let data;
if ( renderer.isWebGLRenderer ) {

if ( dataType === HalfFloatType ) {

Expand All @@ -162,7 +164,19 @@ class LightProbeGenerator {

}

renderer.readRenderTargetPixels( cubeRenderTarget, 0, 0, imageWidth, imageWidth, data, faceIndex );
}

for ( let faceIndex = 0; faceIndex < 6; faceIndex ++ ) {

if ( renderer.isWebGLRenderer ) {

await renderer.readRenderTargetPixelsAsync( cubeRenderTarget, 0, 0, imageWidth, imageWidth, data, faceIndex );

} else {

data = await renderer.readRenderTargetPixelsAsync( cubeRenderTarget, 0, 0, imageWidth, imageWidth, 0, faceIndex );

}

const pixelSize = 2 / imageWidth;

Expand Down Expand Up @@ -194,15 +208,15 @@ class LightProbeGenerator {

const pixelIndex = i / 4;

const col = - 1 + ( pixelIndex % imageWidth + 0.5 ) * pixelSize;
const col = ( 1 - ( pixelIndex % imageWidth + 0.5 ) * pixelSize ) * flip;

const row = 1 - ( Math.floor( pixelIndex / imageWidth ) + 0.5 ) * pixelSize;

switch ( faceIndex ) {

case 0: coord.set( 1, row, - col ); break;
case 0: coord.set( - 1 * flip, row, col * flip ); break;

case 1: coord.set( - 1, row, col ); break;
case 1: coord.set( 1 * flip, row, - col * flip ); break;

case 2: coord.set( col, 1, - row ); break;

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 4 additions & 2 deletions examples/webgl_lightprobe_cubecamera.html
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,15 @@

const urls = genCubeUrls( 'textures/cube/pisa/', '.png' );

new THREE.CubeTextureLoader().load( urls, function ( cubeTexture ) {
new THREE.CubeTextureLoader().load( urls, async function ( cubeTexture ) {

scene.background = cubeTexture;

cubeCamera.update( renderer, scene );

lightProbe.copy( LightProbeGenerator.fromCubeRenderTarget( renderer, cubeRenderTarget ) );
const probe = await LightProbeGenerator.fromCubeRenderTarget( renderer, cubeRenderTarget );

lightProbe.copy( probe );

scene.add( new LightProbeHelper( lightProbe, 5 ) );

Expand Down
125 changes: 125 additions & 0 deletions examples/webgpu_lightprobe_cubecamera.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgpu - light probe from cubeCamera</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>
<div id="info">
<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - light probe from cubeCamera
</div>

<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 { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { LightProbeHelper } from 'three/addons/helpers/LightProbeHelperGPU.js';
import { LightProbeGenerator } from 'three/addons/lights/LightProbeGenerator.js';

let renderer, scene, camera, cubeCamera;

let lightProbe;

init();

function init() {

// renderer
renderer = new THREE.WebGPURenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );

// scene
scene = new THREE.Scene();

// camera
camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set( 0, 0, 30 );

const cubeRenderTarget = new THREE.WebGLCubeRenderTarget( 256 );

cubeCamera = new THREE.CubeCamera( 1, 1000, cubeRenderTarget );

// controls
const controls = new OrbitControls( camera, renderer.domElement );
controls.addEventListener( 'change', render );
controls.minDistance = 10;
controls.maxDistance = 50;
controls.enablePan = false;

// probe
lightProbe = new THREE.LightProbe();
scene.add( lightProbe );

// envmap
const genCubeUrls = function ( prefix, postfix ) {

return [
prefix + 'px' + postfix, prefix + 'nx' + postfix,
prefix + 'py' + postfix, prefix + 'ny' + postfix,
prefix + 'pz' + postfix, prefix + 'nz' + postfix
];

};

const urls = genCubeUrls( 'textures/cube/pisa/', '.png' );

new THREE.CubeTextureLoader().load( urls, async function ( cubeTexture ) {

scene.background = cubeTexture;

await renderer.init();

cubeCamera.update( renderer, scene );

const probe = await LightProbeGenerator.fromCubeRenderTarget( renderer, cubeRenderTarget );

lightProbe.copy( probe );

scene.add( new LightProbeHelper( lightProbe, 5 ) );

render();

} );

// listener
window.addEventListener( 'resize', onWindowResize );

}

function onWindowResize() {

renderer.setSize( window.innerWidth, window.innerHeight );

camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();

render();

}

function render() {

renderer.render( scene, camera );

}

</script>

</body>
</html>
1 change: 1 addition & 0 deletions test/e2e/puppeteer.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ const exceptionList = [
// WebGPURenderer: Unknown problem
'webgpu_camera_logarithmicdepthbuffer',
'webgpu_clipping',
'webgpu_lightprobe_cubecamera',
'webgpu_loader_materialx',
'webgpu_materials_video',
'webgpu_materialx_noise',
Expand Down

0 comments on commit bac758d

Please sign in to comment.