Jelajahi Sumber

Core: Introduce Coordinate System (#26140)

* Core: Introduce Coordinate System.

* WebGPURenderer: Move hack to .coordinateSystem

* cleanup
sunag 2 tahun lalu
induk
melakukan
78e97a9ea3

+ 19 - 1
examples/jsm/renderers/common/Renderer.js

@@ -148,6 +148,12 @@ class Renderer {
 
 
 	}
 	}
 
 
+	get coordinateSystem() {
+
+		return this.backend.coordinateSystem;
+
+	}
+
 	async compile( scene, camera ) {
 	async compile( scene, camera ) {
 
 
 		console.warn( 'THREE.Renderer: .compile() is not implemented yet.' );
 		console.warn( 'THREE.Renderer: .compile() is not implemented yet.' );
@@ -176,6 +182,18 @@ class Renderer {
 
 
 		//
 		//
 
 
+		const coordinateSystem = this.coordinateSystem;
+
+		if ( camera.coordinateSystem !== coordinateSystem ) {
+
+			camera.coordinateSystem = coordinateSystem;
+
+			camera.updateProjectionMatrix();
+
+		}
+
+		//
+
 		if ( this._animation.isAnimating === false ) nodeFrame.update();
 		if ( this._animation.isAnimating === false ) nodeFrame.update();
 
 
 		if ( scene.matrixWorldAutoUpdate === true ) scene.updateMatrixWorld();
 		if ( scene.matrixWorldAutoUpdate === true ) scene.updateMatrixWorld();
@@ -218,7 +236,7 @@ class Renderer {
 		//
 		//
 
 
 		_projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
 		_projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
-		_frustum.setFromProjectionMatrix( _projScreenMatrix );
+		_frustum.setFromProjectionMatrix( _projScreenMatrix, coordinateSystem );
 
 
 		const renderList = this._renderLists.get( scene, camera );
 		const renderList = this._renderLists.get( scene, camera );
 		renderList.init();
 		renderList.init();

+ 7 - 77
examples/jsm/renderers/webgpu/WebGPUBackend.js

@@ -3,7 +3,7 @@ import { GPUFeatureName, GPUTextureFormat, GPULoadOp, GPUStoreOp, GPUIndexFormat
 import WebGPUNodeBuilder from './nodes/WGSLNodeBuilder.js';
 import WebGPUNodeBuilder from './nodes/WGSLNodeBuilder.js';
 import Backend from '../common/Backend.js';
 import Backend from '../common/Backend.js';
 
 
-import { Matrix4, Frustum, DepthFormat } from 'three';
+import { DepthFormat, WebGPUCoordinateSystem } from 'three';
 
 
 import WebGPUUtils from './utils/WebGPUUtils.js';
 import WebGPUUtils from './utils/WebGPUUtils.js';
 import WebGPUAttributeUtils from './utils/WebGPUAttributeUtils.js';
 import WebGPUAttributeUtils from './utils/WebGPUAttributeUtils.js';
@@ -21,82 +21,6 @@ if ( navigator.gpu !== undefined ) {
 
 
 }
 }
 
 
-// hacks
-
-let _initializedHack = false;
-
-function _initWebGPUHack() {
-
-	if ( _initializedHack ) return;
-
-	console.info( 'THREE.WebGPURenderer: Modified Matrix4.makePerspective() and Matrix4.makeOrtographic() to work with WebGPU, see https://github.com/mrdoob/three.js/issues/20276.' );
-
-	Matrix4.prototype.makePerspective = function ( left, right, top, bottom, near, far ) {
-
-		const te = this.elements;
-		const x = 2 * near / ( right - left );
-		const y = 2 * near / ( top - bottom );
-
-		const a = ( right + left ) / ( right - left );
-		const b = ( top + bottom ) / ( top - bottom );
-		const c = - far / ( far - near );
-		const d = - far * near / ( far - near );
-
-		te[ 0 ] = x;	te[ 4 ] = 0;	te[ 8 ] = a;	te[ 12 ] = 0;
-		te[ 1 ] = 0;	te[ 5 ] = y;	te[ 9 ] = b;	te[ 13 ] = 0;
-		te[ 2 ] = 0;	te[ 6 ] = 0;	te[ 10 ] = c;	te[ 14 ] = d;
-		te[ 3 ] = 0;	te[ 7 ] = 0;	te[ 11 ] = - 1;	te[ 15 ] = 0;
-
-		return this;
-
-	};
-
-	Matrix4.prototype.makeOrthographic = function ( left, right, top, bottom, near, far ) {
-
-		const te = this.elements;
-		const w = 1.0 / ( right - left );
-		const h = 1.0 / ( top - bottom );
-		const p = 1.0 / ( far - near );
-
-		const x = ( right + left ) * w;
-		const y = ( top + bottom ) * h;
-		const z = near * p;
-
-		te[ 0 ] = 2 * w;	te[ 4 ] = 0;		te[ 8 ] = 0;		te[ 12 ] = - x;
-		te[ 1 ] = 0;		te[ 5 ] = 2 * h;	te[ 9 ] = 0;		te[ 13 ] = - y;
-		te[ 2 ] = 0;		te[ 6 ] = 0;		te[ 10 ] = - 1 * p;	te[ 14 ] = - z;
-		te[ 3 ] = 0;		te[ 7 ] = 0;		te[ 11 ] = 0;		te[ 15 ] = 1;
-
-		return this;
-
-	};
-
-	Frustum.prototype.setFromProjectionMatrix = function ( m ) {
-
-		const planes = this.planes;
-		const me = m.elements;
-		const me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ];
-		const me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ];
-		const me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ];
-		const me12 = me[ 12 ], me13 = me[ 13 ], me14 = me[ 14 ], me15 = me[ 15 ];
-
-		planes[ 0 ].setComponents( me3 - me0, me7 - me4, me11 - me8, me15 - me12 ).normalize();
-		planes[ 1 ].setComponents( me3 + me0, me7 + me4, me11 + me8, me15 + me12 ).normalize();
-		planes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize();
-		planes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize();
-		planes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize();
-		planes[ 5 ].setComponents( me2, me6, me10, me14 ).normalize();
-
-		return this;
-
-	};
-
-	_initializedHack = true;
-
-}
-
-_initWebGPUHack();
-
 //
 //
 
 
 class WebGPUBackend extends Backend {
 class WebGPUBackend extends Backend {
@@ -188,6 +112,12 @@ class WebGPUBackend extends Backend {
 
 
 	}
 	}
 
 
+	get coordinateSystem() {
+
+		return WebGPUCoordinateSystem;
+
+	}
+
 	async getArrayBuffer( attribute ) {
 	async getArrayBuffer( attribute ) {
 
 
 		return await this.attributeUtils.getArrayBuffer( attribute );
 		return await this.attributeUtils.getArrayBuffer( attribute );

+ 5 - 0
src/cameras/Camera.js

@@ -1,3 +1,4 @@
+import { WebGLCoordinateSystem } from '../constants.js';
 import { Matrix4 } from '../math/Matrix4.js';
 import { Matrix4 } from '../math/Matrix4.js';
 import { Object3D } from '../core/Object3D.js';
 import { Object3D } from '../core/Object3D.js';
 
 
@@ -16,6 +17,8 @@ class Camera extends Object3D {
 		this.projectionMatrix = new Matrix4();
 		this.projectionMatrix = new Matrix4();
 		this.projectionMatrixInverse = new Matrix4();
 		this.projectionMatrixInverse = new Matrix4();
 
 
+		this.coordinateSystem = WebGLCoordinateSystem;
+
 	}
 	}
 
 
 	copy( source, recursive ) {
 	copy( source, recursive ) {
@@ -27,6 +30,8 @@ class Camera extends Object3D {
 		this.projectionMatrix.copy( source.projectionMatrix );
 		this.projectionMatrix.copy( source.projectionMatrix );
 		this.projectionMatrixInverse.copy( source.projectionMatrixInverse );
 		this.projectionMatrixInverse.copy( source.projectionMatrixInverse );
 
 
+		this.coordinateSystem = source.coordinateSystem;
+
 		return this;
 		return this;
 
 
 	}
 	}

+ 1 - 1
src/cameras/OrthographicCamera.js

@@ -107,7 +107,7 @@ class OrthographicCamera extends Camera {
 
 
 		}
 		}
 
 
-		this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far );
+		this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far, this.coordinateSystem );
 
 
 		this.projectionMatrixInverse.copy( this.projectionMatrix ).invert();
 		this.projectionMatrixInverse.copy( this.projectionMatrix ).invert();
 
 

+ 1 - 1
src/cameras/PerspectiveCamera.js

@@ -200,7 +200,7 @@ class PerspectiveCamera extends Camera {
 		const skew = this.filmOffset;
 		const skew = this.filmOffset;
 		if ( skew !== 0 ) left += near * skew / this.getFilmWidth();
 		if ( skew !== 0 ) left += near * skew / this.getFilmWidth();
 
 
-		this.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far );
+		this.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far, this.coordinateSystem );
 
 
 		this.projectionMatrixInverse.copy( this.projectionMatrix ).invert();
 		this.projectionMatrixInverse.copy( this.projectionMatrix ).invert();
 
 

+ 3 - 0
src/constants.js

@@ -196,3 +196,6 @@ export const GLSL1 = '100';
 export const GLSL3 = '300 es';
 export const GLSL3 = '300 es';
 
 
 export const _SRGBAFormat = 1035; // fallback for WebGL 1
 export const _SRGBAFormat = 1035; // fallback for WebGL 1
+
+export const WebGLCoordinateSystem = 2000;
+export const WebGPUCoordinateSystem = 2001;

+ 16 - 2
src/math/Frustum.js

@@ -1,3 +1,4 @@
+import { WebGLCoordinateSystem, WebGPUCoordinateSystem } from '../constants.js';
 import { Vector3 } from './Vector3.js';
 import { Vector3 } from './Vector3.js';
 import { Sphere } from './Sphere.js';
 import { Sphere } from './Sphere.js';
 import { Plane } from './Plane.js';
 import { Plane } from './Plane.js';
@@ -42,7 +43,7 @@ class Frustum {
 
 
 	}
 	}
 
 
-	setFromProjectionMatrix( m ) {
+	setFromProjectionMatrix( m, coordinateSystem = WebGLCoordinateSystem ) {
 
 
 		const planes = this.planes;
 		const planes = this.planes;
 		const me = m.elements;
 		const me = m.elements;
@@ -56,7 +57,20 @@ class Frustum {
 		planes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize();
 		planes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize();
 		planes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize();
 		planes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize();
 		planes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize();
 		planes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize();
-		planes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize();
+
+		if ( coordinateSystem === WebGLCoordinateSystem ) {
+
+			planes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize();
+
+		} else if ( coordinateSystem === WebGPUCoordinateSystem ) {
+
+			planes[ 5 ].setComponents( me2, me6, me10, me14 ).normalize();
+
+		} else {
+
+			throw new Error( 'THREE.Frustum.setFromProjectionMatrix(): Invalid coordinate system: ' + coordinateSystem );
+
+		}
 
 
 		return this;
 		return this;
 
 

+ 46 - 12
src/math/Matrix4.js

@@ -1,3 +1,4 @@
+import { WebGLCoordinateSystem, WebGPUCoordinateSystem } from '../constants.js';
 import { Vector3 } from './Vector3.js';
 import { Vector3 } from './Vector3.js';
 
 
 class Matrix4 {
 class Matrix4 {
@@ -773,7 +774,7 @@ class Matrix4 {
 
 
 	}
 	}
 
 
-	makePerspective( left, right, top, bottom, near, far ) {
+	makePerspective( left, right, top, bottom, near, far, coordinateSystem = WebGLCoordinateSystem ) {
 
 
 		const te = this.elements;
 		const te = this.elements;
 		const x = 2 * near / ( right - left );
 		const x = 2 * near / ( right - left );
@@ -781,19 +782,35 @@ class Matrix4 {
 
 
 		const a = ( right + left ) / ( right - left );
 		const a = ( right + left ) / ( right - left );
 		const b = ( top + bottom ) / ( top - bottom );
 		const b = ( top + bottom ) / ( top - bottom );
-		const c = - ( far + near ) / ( far - near );
-		const d = - 2 * far * near / ( far - near );
 
 
-		te[ 0 ] = x;	te[ 4 ] = 0;	te[ 8 ] = a;	te[ 12 ] = 0;
-		te[ 1 ] = 0;	te[ 5 ] = y;	te[ 9 ] = b;	te[ 13 ] = 0;
-		te[ 2 ] = 0;	te[ 6 ] = 0;	te[ 10 ] = c;	te[ 14 ] = d;
+		let c, d;
+
+		if ( coordinateSystem === WebGLCoordinateSystem ) {
+
+			c = - ( far + near ) / ( far - near );
+			d = ( - 2 * far * near ) / ( far - near );
+
+		} else if ( coordinateSystem === WebGPUCoordinateSystem ) {
+
+			c = - far / ( far - near );
+			d = ( - far * near ) / ( far - near );
+
+		} else {
+
+			throw new Error( 'THREE.Matrix4.makePerspective(): Invalid coordinate system: ' + coordinateSystem );
+
+		}
+
+		te[ 0 ] = x;	te[ 4 ] = 0;	te[ 8 ] = a; 	te[ 12 ] = 0;
+		te[ 1 ] = 0;	te[ 5 ] = y;	te[ 9 ] = b; 	te[ 13 ] = 0;
+		te[ 2 ] = 0;	te[ 6 ] = 0;	te[ 10 ] = c; 	te[ 14 ] = d;
 		te[ 3 ] = 0;	te[ 7 ] = 0;	te[ 11 ] = - 1;	te[ 15 ] = 0;
 		te[ 3 ] = 0;	te[ 7 ] = 0;	te[ 11 ] = - 1;	te[ 15 ] = 0;
 
 
 		return this;
 		return this;
 
 
 	}
 	}
 
 
-	makeOrthographic( left, right, top, bottom, near, far ) {
+	makeOrthographic( left, right, top, bottom, near, far, coordinateSystem = WebGLCoordinateSystem ) {
 
 
 		const te = this.elements;
 		const te = this.elements;
 		const w = 1.0 / ( right - left );
 		const w = 1.0 / ( right - left );
@@ -802,12 +819,29 @@ class Matrix4 {
 
 
 		const x = ( right + left ) * w;
 		const x = ( right + left ) * w;
 		const y = ( top + bottom ) * h;
 		const y = ( top + bottom ) * h;
-		const z = ( far + near ) * p;
 
 
-		te[ 0 ] = 2 * w;	te[ 4 ] = 0;	te[ 8 ] = 0;	te[ 12 ] = - x;
-		te[ 1 ] = 0;	te[ 5 ] = 2 * h;	te[ 9 ] = 0;	te[ 13 ] = - y;
-		te[ 2 ] = 0;	te[ 6 ] = 0;	te[ 10 ] = - 2 * p;	te[ 14 ] = - z;
-		te[ 3 ] = 0;	te[ 7 ] = 0;	te[ 11 ] = 0;	te[ 15 ] = 1;
+		let z, zInv;
+
+		if ( coordinateSystem === WebGLCoordinateSystem ) {
+
+			z = ( far + near ) * p;
+			zInv = - 2 * p;
+
+		} else if ( coordinateSystem === WebGPUCoordinateSystem ) {
+
+			z = near * p;
+			zInv = - 1 * p;
+
+		} else {
+
+			throw new Error( 'THREE.Matrix4.makeOrthographic(): Invalid coordinate system: ' + coordinateSystem );
+
+		}
+
+		te[ 0 ] = 2 * w;	te[ 4 ] = 0;		te[ 8 ] = 0; 		te[ 12 ] = - x;
+		te[ 1 ] = 0; 		te[ 5 ] = 2 * h;	te[ 9 ] = 0; 		te[ 13 ] = - y;
+		te[ 2 ] = 0; 		te[ 6 ] = 0;		te[ 10 ] = zInv;	te[ 14 ] = - z;
+		te[ 3 ] = 0; 		te[ 7 ] = 0;		te[ 11 ] = 0;		te[ 15 ] = 1;
 
 
 		return this;
 		return this;
 
 

+ 8 - 1
src/renderers/WebGLRenderer.js

@@ -20,7 +20,8 @@ import {
 	UnsignedShortType,
 	UnsignedShortType,
 	UnsignedInt248Type,
 	UnsignedInt248Type,
 	UnsignedShort4444Type,
 	UnsignedShort4444Type,
-	UnsignedShort5551Type
+	UnsignedShort5551Type,
+	WebGLCoordinateSystem
 } from '../constants.js';
 } from '../constants.js';
 import { Color } from '../math/Color.js';
 import { Color } from '../math/Color.js';
 import { Frustum } from '../math/Frustum.js';
 import { Frustum } from '../math/Frustum.js';
@@ -2410,6 +2411,12 @@ class WebGLRenderer {
 
 
 	}
 	}
 
 
+	get coordinateSystem() {
+
+		return WebGLCoordinateSystem;
+
+	}
+
 	get physicallyCorrectLights() { // @deprecated, r150
 	get physicallyCorrectLights() { // @deprecated, r150
 
 
 		console.warn( 'THREE.WebGLRenderer: the property .physicallyCorrectLights has been removed. Set renderer.useLegacyLights instead.' );
 		console.warn( 'THREE.WebGLRenderer: the property .physicallyCorrectLights has been removed. Set renderer.useLegacyLights instead.' );