Skip to content

Commit 6dff7ce

Browse files
authored
WebGPURenderer: Introduce CanvasTarget (#31919)
* Introduce `CanvasTarget` * add `webgpu_multiple_canvas` example * cleanup * rev * cleanup * cleanup * Update CanvasTarget.js
1 parent ae1ecc9 commit 6dff7ce

File tree

10 files changed

+753
-202
lines changed

10 files changed

+753
-202
lines changed

examples/files.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,7 @@
384384
"webgpu_morphtargets",
385385
"webgpu_morphtargets_face",
386386
"webgpu_mrt",
387+
"webgpu_multiple_canvas",
387388
"webgpu_multiple_elements",
388389
"webgpu_mrt_mask",
389390
"webgpu_multiple_rendertargets",
32.4 KB
Loading
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<title>three.js webgpu - multiple canvas</title>
5+
<meta charset="utf-8">
6+
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
7+
<link type="text/css" rel="stylesheet" href="main.css">
8+
<style>
9+
10+
* {
11+
box-sizing: border-box;
12+
-moz-box-sizing: border-box;
13+
}
14+
15+
body {
16+
background-color: #fff;
17+
color: #444;
18+
}
19+
20+
a {
21+
color: #08f;
22+
}
23+
24+
#content {
25+
position: absolute;
26+
top: 0; width: 100%;
27+
z-index: 1;
28+
padding: 3em 0 0 0;
29+
}
30+
31+
.list-item {
32+
display: inline-block;
33+
margin: 1em;
34+
padding: 1em;
35+
box-shadow: 1px 2px 4px 0px rgba(0,0,0,0.25);
36+
}
37+
38+
.list-item > canvas:nth-child(1) {
39+
width: 200px;
40+
height: 200px;
41+
}
42+
43+
.list-item > div:nth-child(2) {
44+
color: #888;
45+
font-family: sans-serif;
46+
font-size: large;
47+
width: 200px;
48+
margin-top: 0.5em;
49+
}
50+
51+
</style>
52+
</head>
53+
<body>
54+
55+
<div id="content">
56+
<div id="info"><a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - multiple canvas</div>
57+
</div>
58+
59+
<script type="importmap">
60+
{
61+
"imports": {
62+
"three": "../build/three.webgpu.js",
63+
"three/webgpu": "../build/three.webgpu.js",
64+
"three/tsl": "../build/three.tsl.js",
65+
"three/addons/": "./jsm/"
66+
}
67+
}
68+
</script>
69+
70+
<script type="module">
71+
72+
import * as THREE from 'three';
73+
import { color } from 'three/tsl';
74+
75+
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
76+
77+
import WebGPU from 'three/addons/capabilities/WebGPU.js';
78+
79+
//
80+
81+
if ( WebGPU.isAvailable() === false ) {
82+
83+
document.body.appendChild( WebGPU.getErrorMessage() );
84+
85+
throw new Error( 'No WebGPU support' );
86+
87+
}
88+
89+
//
90+
91+
let renderer;
92+
93+
const scenes = [];
94+
95+
init();
96+
97+
function init() {
98+
99+
const geometries = [
100+
new THREE.BoxGeometry( 1, 1, 1 ),
101+
new THREE.SphereGeometry( 0.5, 12, 8 ),
102+
new THREE.DodecahedronGeometry( 0.5 ),
103+
new THREE.CylinderGeometry( 0.5, 0.5, 1, 12 )
104+
];
105+
106+
const content = document.getElementById( 'content' );
107+
108+
for ( let i = 0; i < 40; i ++ ) {
109+
110+
const scene = new THREE.Scene();
111+
scene.backgroundNode = color( 0xeeeeee );
112+
113+
// make a list item
114+
const element = document.createElement( 'div' );
115+
element.className = 'list-item';
116+
117+
const sceneCanvas = document.createElement( 'canvas' );
118+
element.appendChild( sceneCanvas );
119+
120+
const descriptionElement = document.createElement( 'div' );
121+
descriptionElement.innerText = 'Scene ' + ( i + 1 );
122+
element.appendChild( descriptionElement );
123+
124+
const canvasTarget = new THREE.CanvasTarget( sceneCanvas, { antialias: true } );
125+
canvasTarget.setPixelRatio( window.devicePixelRatio );
126+
canvasTarget.setSize( 200, 200 );
127+
128+
// the element that represents the area we want to render the scene
129+
scene.userData.canvasTarget = canvasTarget;
130+
content.appendChild( element );
131+
132+
const camera = new THREE.PerspectiveCamera( 50, 1, 1, 10 );
133+
camera.position.z = 2;
134+
scene.userData.camera = camera;
135+
136+
const controls = new OrbitControls( scene.userData.camera, scene.userData.canvasTarget.domElement );
137+
controls.minDistance = 2;
138+
controls.maxDistance = 5;
139+
controls.enablePan = false;
140+
controls.enableZoom = false;
141+
scene.userData.controls = controls;
142+
143+
// add one random mesh to each scene
144+
const geometry = geometries[ geometries.length * Math.random() | 0 ];
145+
146+
const material = new THREE.MeshStandardMaterial( {
147+
148+
color: new THREE.Color().setHSL( Math.random(), 1, 0.75, THREE.SRGBColorSpace ),
149+
roughness: 0.5,
150+
metalness: 0,
151+
flatShading: true
152+
153+
} );
154+
155+
scene.add( new THREE.Mesh( geometry, material ) );
156+
157+
scene.add( new THREE.HemisphereLight( 0xaaaaaa, 0x444444, 3 ) );
158+
159+
const light = new THREE.DirectionalLight( 0xffffff, 1.5 );
160+
light.position.set( 1, 1, 1 );
161+
scene.add( light );
162+
163+
scenes.push( scene );
164+
165+
}
166+
167+
renderer = new THREE.WebGPURenderer( { antialias: true } );
168+
renderer.setClearColor( 0xffffff, 1 );
169+
renderer.setPixelRatio( window.devicePixelRatio );
170+
renderer.setAnimationLoop( animate );
171+
172+
}
173+
174+
function animate() {
175+
176+
scenes.forEach( function ( scene ) {
177+
178+
// so something moves
179+
//scene.children[ 0 ].rotation.y = Date.now() * 0.001;
180+
181+
// get the canvas and camera for this scene
182+
const { canvasTarget, camera } = scene.userData;
183+
184+
//camera.aspect = width / height; // not changing in this example
185+
//camera.updateProjectionMatrix();
186+
187+
//scene.userData.controls.update();
188+
189+
renderer.setCanvasTarget( canvasTarget );
190+
renderer.render( scene, camera );
191+
192+
} );
193+
194+
}
195+
196+
</script>
197+
198+
</body>
199+
</html>

src/Three.WebGPU.Nodes.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export { default as NodeLoader } from './loaders/nodes/NodeLoader.js';
1919
export { default as NodeObjectLoader } from './loaders/nodes/NodeObjectLoader.js';
2020
export { default as NodeMaterialLoader } from './loaders/nodes/NodeMaterialLoader.js';
2121
export { default as InspectorBase } from './renderers/common/InspectorBase.js';
22+
export { default as CanvasTarget } from './renderers/common/CanvasTarget.js';
2223
export { ClippingGroup } from './objects/ClippingGroup.js';
2324
export * from './nodes/Nodes.js';
2425
import * as TSL from './nodes/TSL.js';

src/Three.WebGPU.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export { default as NodeLoader } from './loaders/nodes/NodeLoader.js';
2121
export { default as NodeObjectLoader } from './loaders/nodes/NodeObjectLoader.js';
2222
export { default as NodeMaterialLoader } from './loaders/nodes/NodeMaterialLoader.js';
2323
export { default as InspectorBase } from './renderers/common/InspectorBase.js';
24+
export { default as CanvasTarget } from './renderers/common/CanvasTarget.js';
2425
export { ClippingGroup } from './objects/ClippingGroup.js';
2526
export * from './nodes/Nodes.js';
2627
import * as TSL from './nodes/TSL.js';

0 commit comments

Comments
 (0)