240 lines
6.2 KiB
JavaScript
240 lines
6.2 KiB
JavaScript
import { WebGLCoordinateSystem, WebGPUCoordinateSystem } from '../constants.js';
|
|
import { Object3D } from '../core/Object3D.js';
|
|
import { PerspectiveCamera } from './PerspectiveCamera.js';
|
|
|
|
const fov = - 90; // negative fov is not an error
|
|
const aspect = 1;
|
|
|
|
/**
|
|
* A special type of camera that is positioned in 3D space to render its surroundings into a
|
|
* cube render target. The render target can then be used as an environment map for rendering
|
|
* realtime reflections in your scene.
|
|
*
|
|
* ```js
|
|
* // Create cube render target
|
|
* const cubeRenderTarget = new THREE.WebGLCubeRenderTarget( 256, { generateMipmaps: true, minFilter: THREE.LinearMipmapLinearFilter } );
|
|
*
|
|
* // Create cube camera
|
|
* const cubeCamera = new THREE.CubeCamera( 1, 100000, cubeRenderTarget );
|
|
* scene.add( cubeCamera );
|
|
*
|
|
* // Create car
|
|
* const chromeMaterial = new THREE.MeshLambertMaterial( { color: 0xffffff, envMap: cubeRenderTarget.texture } );
|
|
* const car = new THREE.Mesh( carGeometry, chromeMaterial );
|
|
* scene.add( car );
|
|
*
|
|
* // Update the render target cube
|
|
* car.visible = false;
|
|
* cubeCamera.position.copy( car.position );
|
|
* cubeCamera.update( renderer, scene );
|
|
*
|
|
* // Render the scene
|
|
* car.visible = true;
|
|
* renderer.render( scene, camera );
|
|
* ```
|
|
*
|
|
* @augments Object3D
|
|
*/
|
|
class CubeCamera extends Object3D {
|
|
|
|
/**
|
|
* Constructs a new cube camera.
|
|
*
|
|
* @param {number} near - The camera's near plane.
|
|
* @param {number} far - The camera's far plane.
|
|
* @param {WebGLCubeRenderTarget} renderTarget - The cube render target.
|
|
*/
|
|
constructor( near, far, renderTarget ) {
|
|
|
|
super();
|
|
|
|
this.type = 'CubeCamera';
|
|
|
|
/**
|
|
* A reference to the cube render target.
|
|
*
|
|
* @type {WebGLCubeRenderTarget}
|
|
*/
|
|
this.renderTarget = renderTarget;
|
|
|
|
/**
|
|
* The current active coordinate system.
|
|
*
|
|
* @type {?(WebGLCoordinateSystem|WebGPUCoordinateSystem)}
|
|
* @default null
|
|
*/
|
|
this.coordinateSystem = null;
|
|
|
|
/**
|
|
* The current active mipmap level
|
|
*
|
|
* @type {number}
|
|
* @default 0
|
|
*/
|
|
this.activeMipmapLevel = 0;
|
|
|
|
const cameraPX = new PerspectiveCamera( fov, aspect, near, far );
|
|
cameraPX.layers = this.layers;
|
|
this.add( cameraPX );
|
|
|
|
const cameraNX = new PerspectiveCamera( fov, aspect, near, far );
|
|
cameraNX.layers = this.layers;
|
|
this.add( cameraNX );
|
|
|
|
const cameraPY = new PerspectiveCamera( fov, aspect, near, far );
|
|
cameraPY.layers = this.layers;
|
|
this.add( cameraPY );
|
|
|
|
const cameraNY = new PerspectiveCamera( fov, aspect, near, far );
|
|
cameraNY.layers = this.layers;
|
|
this.add( cameraNY );
|
|
|
|
const cameraPZ = new PerspectiveCamera( fov, aspect, near, far );
|
|
cameraPZ.layers = this.layers;
|
|
this.add( cameraPZ );
|
|
|
|
const cameraNZ = new PerspectiveCamera( fov, aspect, near, far );
|
|
cameraNZ.layers = this.layers;
|
|
this.add( cameraNZ );
|
|
|
|
}
|
|
|
|
/**
|
|
* Must be called when the coordinate system of the cube camera is changed.
|
|
*/
|
|
updateCoordinateSystem() {
|
|
|
|
const coordinateSystem = this.coordinateSystem;
|
|
|
|
const cameras = this.children.concat();
|
|
|
|
const [ cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ ] = cameras;
|
|
|
|
for ( const camera of cameras ) this.remove( camera );
|
|
|
|
if ( coordinateSystem === WebGLCoordinateSystem ) {
|
|
|
|
cameraPX.up.set( 0, 1, 0 );
|
|
cameraPX.lookAt( 1, 0, 0 );
|
|
|
|
cameraNX.up.set( 0, 1, 0 );
|
|
cameraNX.lookAt( - 1, 0, 0 );
|
|
|
|
cameraPY.up.set( 0, 0, - 1 );
|
|
cameraPY.lookAt( 0, 1, 0 );
|
|
|
|
cameraNY.up.set( 0, 0, 1 );
|
|
cameraNY.lookAt( 0, - 1, 0 );
|
|
|
|
cameraPZ.up.set( 0, 1, 0 );
|
|
cameraPZ.lookAt( 0, 0, 1 );
|
|
|
|
cameraNZ.up.set( 0, 1, 0 );
|
|
cameraNZ.lookAt( 0, 0, - 1 );
|
|
|
|
} else if ( coordinateSystem === WebGPUCoordinateSystem ) {
|
|
|
|
cameraPX.up.set( 0, - 1, 0 );
|
|
cameraPX.lookAt( - 1, 0, 0 );
|
|
|
|
cameraNX.up.set( 0, - 1, 0 );
|
|
cameraNX.lookAt( 1, 0, 0 );
|
|
|
|
cameraPY.up.set( 0, 0, 1 );
|
|
cameraPY.lookAt( 0, 1, 0 );
|
|
|
|
cameraNY.up.set( 0, 0, - 1 );
|
|
cameraNY.lookAt( 0, - 1, 0 );
|
|
|
|
cameraPZ.up.set( 0, - 1, 0 );
|
|
cameraPZ.lookAt( 0, 0, 1 );
|
|
|
|
cameraNZ.up.set( 0, - 1, 0 );
|
|
cameraNZ.lookAt( 0, 0, - 1 );
|
|
|
|
} else {
|
|
|
|
throw new Error( 'THREE.CubeCamera.updateCoordinateSystem(): Invalid coordinate system: ' + coordinateSystem );
|
|
|
|
}
|
|
|
|
for ( const camera of cameras ) {
|
|
|
|
this.add( camera );
|
|
|
|
camera.updateMatrixWorld();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Calling this method will render the given scene with the given renderer
|
|
* into the cube render target of the camera.
|
|
*
|
|
* @param {(Renderer|WebGLRenderer)} renderer - The renderer.
|
|
* @param {Scene} scene - The scene to render.
|
|
*/
|
|
update( renderer, scene ) {
|
|
|
|
if ( this.parent === null ) this.updateMatrixWorld();
|
|
|
|
const { renderTarget, activeMipmapLevel } = this;
|
|
|
|
if ( this.coordinateSystem !== renderer.coordinateSystem ) {
|
|
|
|
this.coordinateSystem = renderer.coordinateSystem;
|
|
|
|
this.updateCoordinateSystem();
|
|
|
|
}
|
|
|
|
const [ cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ ] = this.children;
|
|
|
|
const currentRenderTarget = renderer.getRenderTarget();
|
|
const currentActiveCubeFace = renderer.getActiveCubeFace();
|
|
const currentActiveMipmapLevel = renderer.getActiveMipmapLevel();
|
|
|
|
const currentXrEnabled = renderer.xr.enabled;
|
|
|
|
renderer.xr.enabled = false;
|
|
|
|
const generateMipmaps = renderTarget.texture.generateMipmaps;
|
|
|
|
renderTarget.texture.generateMipmaps = false;
|
|
|
|
renderer.setRenderTarget( renderTarget, 0, activeMipmapLevel );
|
|
renderer.render( scene, cameraPX );
|
|
|
|
renderer.setRenderTarget( renderTarget, 1, activeMipmapLevel );
|
|
renderer.render( scene, cameraNX );
|
|
|
|
renderer.setRenderTarget( renderTarget, 2, activeMipmapLevel );
|
|
renderer.render( scene, cameraPY );
|
|
|
|
renderer.setRenderTarget( renderTarget, 3, activeMipmapLevel );
|
|
renderer.render( scene, cameraNY );
|
|
|
|
renderer.setRenderTarget( renderTarget, 4, activeMipmapLevel );
|
|
renderer.render( scene, cameraPZ );
|
|
|
|
// mipmaps are generated during the last call of render()
|
|
// at this point, all sides of the cube render target are defined
|
|
|
|
renderTarget.texture.generateMipmaps = generateMipmaps;
|
|
|
|
renderer.setRenderTarget( renderTarget, 5, activeMipmapLevel );
|
|
renderer.render( scene, cameraNZ );
|
|
|
|
renderer.setRenderTarget( currentRenderTarget, currentActiveCubeFace, currentActiveMipmapLevel );
|
|
|
|
renderer.xr.enabled = currentXrEnabled;
|
|
|
|
renderTarget.texture.needsPMREMUpdate = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
export { CubeCamera };
|