Skip to content

Commit ec02bf7

Browse files
WebGPURenderer: fix cameraHelper (#30136)
* fix camera helper * Updated screenshot. --------- Co-authored-by: Mugen87 <[email protected]>
1 parent 53711ab commit ec02bf7

File tree

4 files changed

+285
-13
lines changed

4 files changed

+285
-13
lines changed

examples/files.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,7 @@
299299
"webgpu_backdrop",
300300
"webgpu_backdrop_area",
301301
"webgpu_backdrop_water",
302+
"webgpu_camera",
302303
"webgpu_camera_logarithmicdepthbuffer",
303304
"webgpu_clearcoat",
304305
"webgpu_clipping",
69.2 KB
Loading

examples/webgpu_camera.html

Lines changed: 268 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,268 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<title>three.js webgpu - cameras</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+
b {
10+
color: lightgreen;
11+
}
12+
</style>
13+
</head>
14+
<body>
15+
<div id="info"><a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - cameras<br/>
16+
<b>O</b> orthographic <b>P</b> perspective
17+
</div>
18+
19+
<script type="importmap">
20+
{
21+
"imports": {
22+
"three": "../build/three.webgpu.js",
23+
"three/webgpu": "../build/three.webgpu.js",
24+
"three/tsl": "../build/three.tsl.js",
25+
"three/addons/": "./jsm/"
26+
}
27+
}
28+
</script>
29+
30+
<script type="module">
31+
32+
import * as THREE from 'three';
33+
import { color } from 'three/tsl';
34+
35+
let SCREEN_WIDTH = window.innerWidth;
36+
let SCREEN_HEIGHT = window.innerHeight;
37+
let aspect = SCREEN_WIDTH / SCREEN_HEIGHT;
38+
39+
let container;
40+
let camera, scene, renderer, mesh;
41+
let cameraRig, activeCamera, activeHelper;
42+
let cameraPerspective, cameraOrtho;
43+
let cameraPerspectiveHelper, cameraOrthoHelper;
44+
let backgroundNode;
45+
const frustumSize = 600;
46+
47+
init();
48+
49+
function init() {
50+
51+
container = document.createElement( 'div' );
52+
document.body.appendChild( container );
53+
54+
scene = new THREE.Scene();
55+
56+
//
57+
58+
camera = new THREE.PerspectiveCamera( 50, 0.5 * aspect, 1, 10000 );
59+
camera.position.z = 2500;
60+
61+
cameraPerspective = new THREE.PerspectiveCamera( 50, 0.5 * aspect, 150, 1000 );
62+
63+
cameraPerspectiveHelper = new THREE.CameraHelper( cameraPerspective );
64+
scene.add( cameraPerspectiveHelper );
65+
66+
//
67+
cameraOrtho = new THREE.OrthographicCamera( 0.5 * frustumSize * aspect / - 2, 0.5 * frustumSize * aspect / 2, frustumSize / 2, frustumSize / - 2, 150, 1000 );
68+
69+
cameraOrthoHelper = new THREE.CameraHelper( cameraOrtho );
70+
scene.add( cameraOrthoHelper );
71+
72+
//
73+
74+
activeCamera = cameraPerspective;
75+
activeHelper = cameraPerspectiveHelper;
76+
77+
78+
// counteract different front orientation of cameras vs rig
79+
80+
cameraOrtho.rotation.y = Math.PI;
81+
cameraPerspective.rotation.y = Math.PI;
82+
83+
cameraRig = new THREE.Group();
84+
85+
cameraRig.add( cameraPerspective );
86+
cameraRig.add( cameraOrtho );
87+
88+
scene.add( cameraRig );
89+
90+
//
91+
92+
mesh = new THREE.Mesh(
93+
new THREE.SphereGeometry( 100, 16, 8 ),
94+
new THREE.MeshBasicMaterial( { color: 0xffffff, wireframe: true } )
95+
);
96+
scene.add( mesh );
97+
98+
const mesh2 = new THREE.Mesh(
99+
new THREE.SphereGeometry( 50, 16, 8 ),
100+
new THREE.MeshBasicMaterial( { color: 0x00ff00, wireframe: true } )
101+
);
102+
mesh2.position.y = 150;
103+
mesh.add( mesh2 );
104+
105+
const mesh3 = new THREE.Mesh(
106+
new THREE.SphereGeometry( 5, 16, 8 ),
107+
new THREE.MeshBasicMaterial( { color: 0x0000ff, wireframe: true } )
108+
);
109+
mesh3.position.z = 150;
110+
cameraRig.add( mesh3 );
111+
112+
//
113+
114+
const geometry = new THREE.BufferGeometry();
115+
const vertices = [];
116+
117+
for ( let i = 0; i < 10000; i ++ ) {
118+
119+
vertices.push( THREE.MathUtils.randFloatSpread( 2000 ) ); // x
120+
vertices.push( THREE.MathUtils.randFloatSpread( 2000 ) ); // y
121+
vertices.push( THREE.MathUtils.randFloatSpread( 2000 ) ); // z
122+
123+
}
124+
125+
geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) );
126+
127+
const particles = new THREE.Points( geometry, new THREE.PointsMaterial( { color: 0x888888 } ) );
128+
scene.add( particles );
129+
130+
//
131+
132+
renderer = new THREE.WebGPURenderer( { antialias: true } );
133+
renderer.setPixelRatio( window.devicePixelRatio );
134+
renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
135+
renderer.setAnimationLoop( animate );
136+
container.appendChild( renderer.domElement );
137+
138+
renderer.setScissorTest( true );
139+
backgroundNode = color( 0x111111 );
140+
renderer.setClearColor( 0x000000, 1 );
141+
142+
//
143+
144+
window.addEventListener( 'resize', onWindowResize );
145+
document.addEventListener( 'keydown', onKeyDown );
146+
147+
}
148+
149+
//
150+
151+
function onKeyDown( event ) {
152+
153+
switch ( event.keyCode ) {
154+
155+
case 79: /*O*/
156+
157+
activeCamera = cameraOrtho;
158+
activeHelper = cameraOrthoHelper;
159+
160+
break;
161+
162+
case 80: /*P*/
163+
164+
activeCamera = cameraPerspective;
165+
activeHelper = cameraPerspectiveHelper;
166+
167+
break;
168+
169+
}
170+
171+
}
172+
173+
//
174+
175+
function onWindowResize() {
176+
177+
SCREEN_WIDTH = window.innerWidth;
178+
SCREEN_HEIGHT = window.innerHeight;
179+
aspect = SCREEN_WIDTH / SCREEN_HEIGHT;
180+
181+
renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
182+
183+
camera.aspect = 0.5 * aspect;
184+
camera.updateProjectionMatrix();
185+
186+
cameraPerspective.aspect = 0.5 * aspect;
187+
cameraPerspective.updateProjectionMatrix();
188+
189+
cameraOrtho.left = - 0.5 * frustumSize * aspect / 2;
190+
cameraOrtho.right = 0.5 * frustumSize * aspect / 2;
191+
cameraOrtho.top = frustumSize / 2;
192+
cameraOrtho.bottom = - frustumSize / 2;
193+
cameraOrtho.updateProjectionMatrix();
194+
195+
}
196+
197+
//
198+
199+
function animate() {
200+
201+
render();
202+
203+
}
204+
205+
206+
function render() {
207+
208+
const r = Date.now() * 0.0005;
209+
210+
mesh.position.x = 700 * Math.cos( r );
211+
mesh.position.z = 700 * Math.sin( r );
212+
mesh.position.y = 700 * Math.sin( r );
213+
214+
mesh.children[ 0 ].position.x = 70 * Math.cos( 2 * r );
215+
mesh.children[ 0 ].position.z = 70 * Math.sin( r );
216+
217+
if ( activeCamera === cameraPerspective ) {
218+
219+
cameraPerspective.fov = 35 + 30 * Math.sin( 0.5 * r );
220+
cameraPerspective.far = mesh.position.length();
221+
cameraPerspective.updateProjectionMatrix();
222+
223+
cameraPerspectiveHelper.update();
224+
cameraPerspectiveHelper.visible = true;
225+
226+
cameraOrthoHelper.visible = false;
227+
228+
} else {
229+
230+
cameraOrtho.far = mesh.position.length();
231+
cameraOrtho.updateProjectionMatrix();
232+
233+
cameraOrthoHelper.update();
234+
cameraOrthoHelper.visible = true;
235+
236+
cameraPerspectiveHelper.visible = false;
237+
238+
}
239+
240+
cameraRig.lookAt( mesh.position );
241+
242+
//
243+
244+
activeHelper.visible = false;
245+
246+
renderer.autoClear = true;
247+
248+
renderer.setScissor( 0, 0, SCREEN_WIDTH / 2, SCREEN_HEIGHT );
249+
renderer.setViewport( 0, 0, SCREEN_WIDTH / 2, SCREEN_HEIGHT );
250+
scene.backgroundNode = null;
251+
renderer.render( scene, activeCamera );
252+
253+
//
254+
255+
activeHelper.visible = true;
256+
257+
renderer.setScissor( SCREEN_WIDTH / 2, 0, SCREEN_WIDTH / 2, SCREEN_HEIGHT );
258+
renderer.setViewport( SCREEN_WIDTH / 2, 0, SCREEN_WIDTH / 2, SCREEN_HEIGHT );
259+
renderer.autoClear = false;
260+
scene.backgroundNode = backgroundNode;
261+
renderer.render( scene, camera );
262+
263+
}
264+
265+
</script>
266+
267+
</body>
268+
</html>

src/helpers/CameraHelper.js

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { Color } from '../math/Color.js';
55
import { LineBasicMaterial } from '../materials/LineBasicMaterial.js';
66
import { BufferGeometry } from '../core/BufferGeometry.js';
77
import { Float32BufferAttribute } from '../core/BufferAttribute.js';
8+
import { WebGLCoordinateSystem } from '../constants.js';
89

910
const _vector = /*@__PURE__*/ new Vector3();
1011
const _camera = /*@__PURE__*/ new Camera();
@@ -195,17 +196,19 @@ class CameraHelper extends LineSegments {
195196

196197
_camera.projectionMatrixInverse.copy( this.camera.projectionMatrixInverse );
197198

198-
// center / target
199+
// Adjust z values based on coordinate system
200+
const nearZ = this.camera.coordinateSystem === WebGLCoordinateSystem ? - 1 : 0;
199201

200-
setPoint( 'c', pointMap, geometry, _camera, 0, 0, - 1 );
202+
// center / target
203+
setPoint( 'c', pointMap, geometry, _camera, 0, 0, nearZ );
201204
setPoint( 't', pointMap, geometry, _camera, 0, 0, 1 );
202205

203206
// near
204207

205-
setPoint( 'n1', pointMap, geometry, _camera, - w, - h, - 1 );
206-
setPoint( 'n2', pointMap, geometry, _camera, w, - h, - 1 );
207-
setPoint( 'n3', pointMap, geometry, _camera, - w, h, - 1 );
208-
setPoint( 'n4', pointMap, geometry, _camera, w, h, - 1 );
208+
setPoint( 'n1', pointMap, geometry, _camera, - w, - h, nearZ );
209+
setPoint( 'n2', pointMap, geometry, _camera, w, - h, nearZ );
210+
setPoint( 'n3', pointMap, geometry, _camera, - w, h, nearZ );
211+
setPoint( 'n4', pointMap, geometry, _camera, w, h, nearZ );
209212

210213
// far
211214

@@ -216,9 +219,9 @@ class CameraHelper extends LineSegments {
216219

217220
// up
218221

219-
setPoint( 'u1', pointMap, geometry, _camera, w * 0.7, h * 1.1, - 1 );
220-
setPoint( 'u2', pointMap, geometry, _camera, - w * 0.7, h * 1.1, - 1 );
221-
setPoint( 'u3', pointMap, geometry, _camera, 0, h * 2, - 1 );
222+
setPoint( 'u1', pointMap, geometry, _camera, w * 0.7, h * 1.1, nearZ );
223+
setPoint( 'u2', pointMap, geometry, _camera, - w * 0.7, h * 1.1, nearZ );
224+
setPoint( 'u3', pointMap, geometry, _camera, 0, h * 2, nearZ );
222225

223226
// cross
224227

@@ -227,10 +230,10 @@ class CameraHelper extends LineSegments {
227230
setPoint( 'cf3', pointMap, geometry, _camera, 0, - h, 1 );
228231
setPoint( 'cf4', pointMap, geometry, _camera, 0, h, 1 );
229232

230-
setPoint( 'cn1', pointMap, geometry, _camera, - w, 0, - 1 );
231-
setPoint( 'cn2', pointMap, geometry, _camera, w, 0, - 1 );
232-
setPoint( 'cn3', pointMap, geometry, _camera, 0, - h, - 1 );
233-
setPoint( 'cn4', pointMap, geometry, _camera, 0, h, - 1 );
233+
setPoint( 'cn1', pointMap, geometry, _camera, - w, 0, nearZ );
234+
setPoint( 'cn2', pointMap, geometry, _camera, w, 0, nearZ );
235+
setPoint( 'cn3', pointMap, geometry, _camera, 0, - h, nearZ );
236+
setPoint( 'cn4', pointMap, geometry, _camera, 0, h, nearZ );
234237

235238
geometry.getAttribute( 'position' ).needsUpdate = true;
236239

0 commit comments

Comments
 (0)