Dies ist das Repository meines kleinen Portfolios.
Im Hintergrund läuft eine Planetensimulation, geschrieben in JavaScript und Three.js.
Die zu sehenden Texturen stammen von:
https://www.solarsystemscope.com/textures/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
145 lines
5.1 KiB
145 lines
5.1 KiB
( function () { |
|
|
|
class CSMHelper extends THREE.Group { |
|
|
|
constructor( csm ) { |
|
|
|
super(); |
|
this.csm = csm; |
|
this.displayFrustum = true; |
|
this.displayPlanes = true; |
|
this.displayShadowBounds = true; |
|
const indices = new Uint16Array( [ 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7 ] ); |
|
const positions = new Float32Array( 24 ); |
|
const frustumGeometry = new THREE.BufferGeometry(); |
|
frustumGeometry.setIndex( new THREE.BufferAttribute( indices, 1 ) ); |
|
frustumGeometry.setAttribute( 'position', new THREE.BufferAttribute( positions, 3, false ) ); |
|
const frustumLines = new THREE.LineSegments( frustumGeometry, new THREE.LineBasicMaterial() ); |
|
this.add( frustumLines ); |
|
this.frustumLines = frustumLines; |
|
this.cascadeLines = []; |
|
this.cascadePlanes = []; |
|
this.shadowLines = []; |
|
|
|
} |
|
|
|
updateVisibility() { |
|
|
|
const displayFrustum = this.displayFrustum; |
|
const displayPlanes = this.displayPlanes; |
|
const displayShadowBounds = this.displayShadowBounds; |
|
const frustumLines = this.frustumLines; |
|
const cascadeLines = this.cascadeLines; |
|
const cascadePlanes = this.cascadePlanes; |
|
const shadowLines = this.shadowLines; |
|
|
|
for ( let i = 0, l = cascadeLines.length; i < l; i ++ ) { |
|
|
|
const cascadeLine = cascadeLines[ i ]; |
|
const cascadePlane = cascadePlanes[ i ]; |
|
const shadowLineGroup = shadowLines[ i ]; |
|
cascadeLine.visible = displayFrustum; |
|
cascadePlane.visible = displayFrustum && displayPlanes; |
|
shadowLineGroup.visible = displayShadowBounds; |
|
|
|
} |
|
|
|
frustumLines.visible = displayFrustum; |
|
|
|
} |
|
|
|
update() { |
|
|
|
const csm = this.csm; |
|
const camera = csm.camera; |
|
const cascades = csm.cascades; |
|
const mainFrustum = csm.mainFrustum; |
|
const frustums = csm.frustums; |
|
const lights = csm.lights; |
|
const frustumLines = this.frustumLines; |
|
const frustumLinePositions = frustumLines.geometry.getAttribute( 'position' ); |
|
const cascadeLines = this.cascadeLines; |
|
const cascadePlanes = this.cascadePlanes; |
|
const shadowLines = this.shadowLines; |
|
this.position.copy( camera.position ); |
|
this.quaternion.copy( camera.quaternion ); |
|
this.scale.copy( camera.scale ); |
|
this.updateMatrixWorld( true ); |
|
|
|
while ( cascadeLines.length > cascades ) { |
|
|
|
this.remove( cascadeLines.pop() ); |
|
this.remove( cascadePlanes.pop() ); |
|
this.remove( shadowLines.pop() ); |
|
|
|
} |
|
|
|
while ( cascadeLines.length < cascades ) { |
|
|
|
const cascadeLine = new THREE.Box3Helper( new THREE.Box3(), 0xffffff ); |
|
const planeMat = new THREE.MeshBasicMaterial( { |
|
transparent: true, |
|
opacity: 0.1, |
|
depthWrite: false, |
|
side: THREE.DoubleSide |
|
} ); |
|
const cascadePlane = new THREE.Mesh( new THREE.PlaneGeometry(), planeMat ); |
|
const shadowLineGroup = new THREE.Group(); |
|
const shadowLine = new THREE.Box3Helper( new THREE.Box3(), 0xffff00 ); |
|
shadowLineGroup.add( shadowLine ); |
|
this.add( cascadeLine ); |
|
this.add( cascadePlane ); |
|
this.add( shadowLineGroup ); |
|
cascadeLines.push( cascadeLine ); |
|
cascadePlanes.push( cascadePlane ); |
|
shadowLines.push( shadowLineGroup ); |
|
|
|
} |
|
|
|
for ( let i = 0; i < cascades; i ++ ) { |
|
|
|
const frustum = frustums[ i ]; |
|
const light = lights[ i ]; |
|
const shadowCam = light.shadow.camera; |
|
const farVerts = frustum.vertices.far; |
|
const cascadeLine = cascadeLines[ i ]; |
|
const cascadePlane = cascadePlanes[ i ]; |
|
const shadowLineGroup = shadowLines[ i ]; |
|
const shadowLine = shadowLineGroup.children[ 0 ]; |
|
cascadeLine.box.min.copy( farVerts[ 2 ] ); |
|
cascadeLine.box.max.copy( farVerts[ 0 ] ); |
|
cascadeLine.box.max.z += 1e-4; |
|
cascadePlane.position.addVectors( farVerts[ 0 ], farVerts[ 2 ] ); |
|
cascadePlane.position.multiplyScalar( 0.5 ); |
|
cascadePlane.scale.subVectors( farVerts[ 0 ], farVerts[ 2 ] ); |
|
cascadePlane.scale.z = 1e-4; |
|
this.remove( shadowLineGroup ); |
|
shadowLineGroup.position.copy( shadowCam.position ); |
|
shadowLineGroup.quaternion.copy( shadowCam.quaternion ); |
|
shadowLineGroup.scale.copy( shadowCam.scale ); |
|
shadowLineGroup.updateMatrixWorld( true ); |
|
this.attach( shadowLineGroup ); |
|
shadowLine.box.min.set( shadowCam.bottom, shadowCam.left, - shadowCam.far ); |
|
shadowLine.box.max.set( shadowCam.top, shadowCam.right, - shadowCam.near ); |
|
|
|
} |
|
|
|
const nearVerts = mainFrustum.vertices.near; |
|
const farVerts = mainFrustum.vertices.far; |
|
frustumLinePositions.setXYZ( 0, farVerts[ 0 ].x, farVerts[ 0 ].y, farVerts[ 0 ].z ); |
|
frustumLinePositions.setXYZ( 1, farVerts[ 3 ].x, farVerts[ 3 ].y, farVerts[ 3 ].z ); |
|
frustumLinePositions.setXYZ( 2, farVerts[ 2 ].x, farVerts[ 2 ].y, farVerts[ 2 ].z ); |
|
frustumLinePositions.setXYZ( 3, farVerts[ 1 ].x, farVerts[ 1 ].y, farVerts[ 1 ].z ); |
|
frustumLinePositions.setXYZ( 4, nearVerts[ 0 ].x, nearVerts[ 0 ].y, nearVerts[ 0 ].z ); |
|
frustumLinePositions.setXYZ( 5, nearVerts[ 3 ].x, nearVerts[ 3 ].y, nearVerts[ 3 ].z ); |
|
frustumLinePositions.setXYZ( 6, nearVerts[ 2 ].x, nearVerts[ 2 ].y, nearVerts[ 2 ].z ); |
|
frustumLinePositions.setXYZ( 7, nearVerts[ 1 ].x, nearVerts[ 1 ].y, nearVerts[ 1 ].z ); |
|
frustumLinePositions.needsUpdate = true; |
|
|
|
} |
|
|
|
} |
|
|
|
THREE.CSMHelper = CSMHelper; |
|
|
|
} )();
|
|
|