three#WebGLRenderer JavaScript Examples
The following examples show how to use
three#WebGLRenderer.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: PlayerInInventory.js From webmc with MIT License | 6 votes |
constructor (game) {
this.game = game
this.renderer = new WebGLRenderer({
canvas: this.game.pcanvas,
PixelRatio: window.devicePixelRatio
})
this.scene = new Scene()
this.scene.background = new Color('black')
const light = new AmbientLight(0xffffff)
this.scene.add(light)
}
Example #2
Source File: main.js From architect3d with MIT License | 6 votes |
getARenderer()
{
// scope.renderer = new WebGLRenderer({antialias: true, preserveDrawingBuffer:
// true, alpha:true}); // preserveDrawingBuffer:true - required to support
// .toDataURL()
var renderer = new WebGLRenderer({antialias: true, alpha:true});
// scope.renderer.autoClear = false;
renderer.shadowMap.enabled = true;
renderer.shadowMapSoft = true;
renderer.shadowMap.type = PCFSoftShadowMap;
renderer.setClearColor( 0xFFFFFF, 1 );
renderer.clippingPlanes = this.clippingEmpty;
renderer.localClippingEnabled = false;
// renderer.setPixelRatio(window.devicePixelRatio);
// renderer.sortObjects = false;
return renderer;
}
Example #3
Source File: cmptExample.js From 3DTilesRendererJS with Apache License 2.0 | 5 votes |
function init() {
scene = new Scene();
// primary camera view
renderer = new WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0x151c1f );
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = PCFSoftShadowMap;
renderer.outputEncoding = sRGBEncoding;
document.body.appendChild( renderer.domElement );
camera = new PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 4000 );
camera.position.set( 400, 400, 400 );
// controls
controls = new OrbitControls( camera, renderer.domElement );
controls.screenSpacePanning = false;
controls.minDistance = 1;
controls.maxDistance = 2000;
// lights
dirLight = new DirectionalLight( 0xffffff, 1.25 );
dirLight.position.set( 1, 2, 3 ).multiplyScalar( 40 );
dirLight.castShadow = true;
dirLight.shadow.bias = - 0.01;
dirLight.shadow.mapSize.setScalar( 2048 );
const shadowCam = dirLight.shadow.camera;
shadowCam.left = - 200;
shadowCam.bottom = - 200;
shadowCam.right = 200;
shadowCam.top = 200;
shadowCam.updateProjectionMatrix();
scene.add( dirLight );
const ambLight = new AmbientLight( 0xffffff, 0.05 );
scene.add( ambLight );
new CMPTLoader()
.load( '...' )
.then( res => {
console.log( res );
// console.log( res );
// scene.add( res.scene );
} );
onWindowResize();
window.addEventListener( 'resize', onWindowResize, false );
}
Example #4
Source File: index.js From map33.js with MIT License | 5 votes |
renderer = new WebGLRenderer({
antialias: true,
alpha: true,
logarithmicDepthBuffer: false,
})
Example #5
Source File: pntsExample.js From 3DTilesRendererJS with Apache License 2.0 | 5 votes |
function init() {
scene = new Scene();
// primary camera view
renderer = new WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0x151c1f );
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = PCFSoftShadowMap;
renderer.outputEncoding = sRGBEncoding;
document.body.appendChild( renderer.domElement );
camera = new PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 4000 );
camera.position.set( 2, 2, 2 );
// controls
controls = new OrbitControls( camera, renderer.domElement );
controls.screenSpacePanning = false;
controls.minDistance = 1;
controls.maxDistance = 2000;
// lights
dirLight = new DirectionalLight( 0xffffff, 1.25 );
dirLight.position.set( 1, 2, 3 ).multiplyScalar( 40 );
dirLight.castShadow = true;
dirLight.shadow.bias = - 0.01;
dirLight.shadow.mapSize.setScalar( 2048 );
const shadowCam = dirLight.shadow.camera;
shadowCam.left = - 200;
shadowCam.bottom = - 200;
shadowCam.right = 200;
shadowCam.top = 200;
shadowCam.updateProjectionMatrix();
scene.add( dirLight );
const ambLight = new AmbientLight( 0xffffff, 0.05 );
scene.add( ambLight );
new PNTSLoader()
.load( 'https://raw.githubusercontent.com/CesiumGS/3d-tiles-samples/main/1.0/TilesetWithRequestVolume/points.pnts' )
.then( res => {
console.log( res );
scene.add( res.scene );
} );
onWindowResize();
window.addEventListener( 'resize', onWindowResize, false );
}
Example #6
Source File: MapViewer.js From BlueMapWeb with MIT License | 5 votes |
/**
* @param element {Element}
* @param events {EventTarget}
*/
constructor(element, events = element) {
Object.defineProperty( this, 'isMapViewer', { value: true } );
this.rootElement = element;
this.events = events;
this.data = {
map: null,
camera: null,
controlsManager: null,
uniforms: {
sunlightStrength: { value: 1 },
ambientLight: { value: 0 },
skyColor: { value: new Color(0.5, 0.5, 1) },
hiresTileMap: {
value: {
map: null,
size: TileManager.tileMapSize,
scale: new Vector2(1, 1),
translate: new Vector2(),
pos: new Vector2(),
}
}
},
superSampling: 1,
loadedCenter: new Vector2(0, 0),
loadedHiresViewDistance: 200,
loadedLowresViewDistance: 2000,
}
this.tileCacheHash = generateCacheHash();
this.stats = new Stats();
this.stats.hide();
// renderer
this.renderer = new WebGLRenderer({
antialias: true,
sortObjects: true,
preserveDrawingBuffer: true,
logarithmicDepthBuffer: true,
});
this.renderer.autoClear = false;
this.renderer.uniforms = this.data.uniforms;
// CSS2D renderer
this.css2dRenderer = new CSS2DRenderer(this.events);
this.skyboxScene = new SkyboxScene(this.data.uniforms);
this.camera = new CombinedCamera(75, 1, 0.1, 10000, 0);
this.skyboxCamera = new PerspectiveCamera(75, 1, 0.1, 10000);
this.controlsManager = new ControlsManager(this, this.camera);
this.raycaster = new Raycaster();
this.raycaster.layers.enableAll();
this.raycaster.params.Line2 = {threshold: 20}
/** @type {Map} */
this.map = null;
this.markers = new MarkerSet("bm-root");
this.lastFrame = 0;
// initialize
this.initializeRootElement();
// handle window resizes
window.addEventListener("resize", this.handleContainerResize);
// start render-loop
requestAnimationFrame(this.renderLoop);
}
Example #7
Source File: mars.js From 3DTilesRendererJS with Apache License 2.0 | 5 votes |
function init() {
const fog = new FogExp2( 0xd8cec0, .0075, 250 );
scene = new Scene();
// primary camera view
renderer = new WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0xd8cec0 );
renderer.outputEncoding = sRGBEncoding;
document.body.appendChild( renderer.domElement );
renderer.domElement.tabIndex = 1;
camera = new PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 4000 );
camera.position.set( 20, 10, 20 );
// controls
controls = new FlyOrbitControls( camera, renderer.domElement );
controls.screenSpacePanning = false;
controls.minDistance = 1;
controls.maxDistance = 2000;
controls.maxPolarAngle = Math.PI / 2;
controls.baseSpeed = 0.1;
controls.fastSpeed = 0.2;
// lights
const dirLight = new DirectionalLight( 0xffffff );
dirLight.position.set( 1, 2, 3 );
scene.add( dirLight );
const ambLight = new AmbientLight( 0xffffff, 0.2 );
scene.add( ambLight );
const tilesParent = new Group();
tilesParent.rotation.set( Math.PI / 2, 0, 0 );
scene.add( tilesParent );
groundTiles = new TilesRenderer( 'https://raw.githubusercontent.com/NASA-AMMOS/3DTilesSampleData/master/msl-dingo-gap/0528_0260184_to_s64o256_colorize/0528_0260184_to_s64o256_colorize/0528_0260184_to_s64o256_colorize_tileset.json' );
groundTiles.fetchOptions.mode = 'cors';
groundTiles.lruCache.minSize = 900;
groundTiles.lruCache.maxSize = 1300;
groundTiles.errorTarget = 12;
skyTiles = new TilesRenderer( 'https://raw.githubusercontent.com/NASA-AMMOS/3DTilesSampleData/master/msl-dingo-gap/0528_0260184_to_s64o256_colorize/0528_0260184_to_s64o256_sky/0528_0260184_to_s64o256_sky_tileset.json' );
skyTiles.fetchOptions.mode = 'cors';
skyTiles.lruCache = groundTiles.lruCache;
tilesParent.add( groundTiles.group, skyTiles.group );
onWindowResize();
window.addEventListener( 'resize', onWindowResize, false );
const gui = new GUI();
gui.add( params, 'fog' ).onChange( v => {
scene.fog = v ? fog : null;
} );
gui.add( params, 'displayBoxBounds' );
gui.add( params, 'errorTarget', 0, 100 );
gui.open();
}
Example #8
Source File: offscreenShadows.js From 3DTilesRendererJS with Apache License 2.0 | 5 votes |
function init() {
scene = new Scene();
// primary camera view
renderer = new WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0x151c1f );
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = PCFSoftShadowMap;
renderer.outputEncoding = sRGBEncoding;
document.body.appendChild( renderer.domElement );
camera = new PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 4000 );
camera.position.set( - 56, 232, 260 );
orthoCamera = new OrthographicCamera();
// controls
controls = new OrbitControls( camera, renderer.domElement );
controls.screenSpacePanning = false;
controls.minDistance = 1;
controls.maxDistance = 2000;
// lights
dirLight = new DirectionalLight( 0xffffff, 1.25 );
dirLight.position.set( - 100, 40, 10 );
dirLight.castShadow = true;
dirLight.shadow.bias = - 1e-4;
dirLight.shadow.normalBias = 0.2;
dirLight.shadow.mapSize.setScalar( 2048 );
const shadowCam = dirLight.shadow.camera;
shadowCam.left = - 120;
shadowCam.bottom = - 120;
shadowCam.right = 120;
shadowCam.top = 120;
shadowCam.updateProjectionMatrix();
scene.add( dirLight );
const ambLight = new AmbientLight( 0xffffff, 0.05 );
scene.add( ambLight );
box = new Box3();
sphere = new Sphere();
offsetParent = new Group();
scene.add( offsetParent );
// tiles
const url = window.location.hash.replace( /^#/, '' ) || '../data/tileset.json';
tiles = new TilesRenderer( url );
tiles.onLoadModel = onLoadModel;
tiles.onDisposeModel = onDisposeModel;
offsetParent.add( tiles.group );
onWindowResize();
window.addEventListener( 'resize', onWindowResize, false );
// GUI
const gui = new GUI();
gui.width = 300;
gui.add( params, 'orthographic' );
gui.add( params, 'errorTarget' ).min( 0 ).max( 25 ).step( 1 );
gui.add( params, 'shadowStrategy', { NONE, DISPLAY_ACTIVE_TILES, USE_SHADOW_CAMERA } );
gui.open();
// Stats
stats = new Stats();
stats.showPanel( 0 );
document.body.appendChild( stats.dom );
}
Example #9
Source File: ionExample.js From 3DTilesRendererJS with Apache License 2.0 | 4 votes |
function init() {
scene = new Scene();
// primary camera view
renderer = new WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0x151c1f );
renderer.outputEncoding = sRGBEncoding;
document.body.appendChild( renderer.domElement );
renderer.domElement.tabIndex = 1;
camera = new PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 4000 );
camera.position.set( 400, 400, 400 );
cameraHelper = new CameraHelper( camera );
scene.add( cameraHelper );
orthoCamera = new OrthographicCamera();
orthoCameraHelper = new CameraHelper( orthoCamera );
scene.add( orthoCameraHelper );
// secondary camera view
secondCamera = new PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 4000 );
secondCamera.position.set( 400, 400, - 400 );
secondCamera.lookAt( 0, 0, 0 );
secondRenderer = new WebGLRenderer( { antialias: true } );
secondRenderer.setPixelRatio( window.devicePixelRatio );
secondRenderer.setSize( window.innerWidth, window.innerHeight );
secondRenderer.setClearColor( 0x151c1f );
secondRenderer.outputEncoding = sRGBEncoding;
document.body.appendChild( secondRenderer.domElement );
secondRenderer.domElement.style.position = 'absolute';
secondRenderer.domElement.style.right = '0';
secondRenderer.domElement.style.top = '0';
secondRenderer.domElement.style.outline = '#0f1416 solid 2px';
secondRenderer.domElement.tabIndex = 1;
secondControls = new FlyOrbitControls( secondCamera, secondRenderer.domElement );
secondControls.screenSpacePanning = false;
secondControls.minDistance = 1;
secondControls.maxDistance = 2000;
secondCameraHelper = new CameraHelper( secondCamera );
scene.add( secondCameraHelper );
// Third person camera view
thirdPersonCamera = new PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 4000 );
thirdPersonCamera.position.set( 50, 40, 40 );
thirdPersonCamera.lookAt( 0, 0, 0 );
thirdPersonRenderer = new WebGLRenderer( { antialias: true } );
thirdPersonRenderer.setPixelRatio( window.devicePixelRatio );
thirdPersonRenderer.setSize( window.innerWidth, window.innerHeight );
thirdPersonRenderer.setClearColor( 0x0f1416 );
thirdPersonRenderer.outputEncoding = sRGBEncoding;
document.body.appendChild( thirdPersonRenderer.domElement );
thirdPersonRenderer.domElement.style.position = 'fixed';
thirdPersonRenderer.domElement.style.left = '5px';
thirdPersonRenderer.domElement.style.bottom = '5px';
thirdPersonRenderer.domElement.tabIndex = 1;
thirdPersonControls = new FlyOrbitControls( thirdPersonCamera, thirdPersonRenderer.domElement );
thirdPersonControls.screenSpacePanning = false;
thirdPersonControls.minDistance = 1;
thirdPersonControls.maxDistance = 2000;
// controls
controls = new FlyOrbitControls( camera, renderer.domElement );
controls.screenSpacePanning = false;
controls.minDistance = 1;
controls.maxDistance = 2000;
// lights
const dirLight = new DirectionalLight( 0xffffff );
dirLight.position.set( 1, 2, 3 );
scene.add( dirLight );
const ambLight = new AmbientLight( 0xffffff, 0.2 );
scene.add( ambLight );
offsetParent = new Group();
scene.add( offsetParent );
// Raycasting init
raycaster = new Raycaster();
mouse = new Vector2();
rayIntersect = new Group();
const rayIntersectMat = new MeshBasicMaterial( { color: 0xe91e63 } );
const rayMesh = new Mesh( new CylinderBufferGeometry( 0.25, 0.25, 6 ), rayIntersectMat );
rayMesh.rotation.x = Math.PI / 2;
rayMesh.position.z += 3;
rayIntersect.add( rayMesh );
const rayRing = new Mesh( new TorusBufferGeometry( 1.5, 0.2, 16, 100 ), rayIntersectMat );
rayIntersect.add( rayRing );
scene.add( rayIntersect );
rayIntersect.visible = false;
reinstantiateTiles();
onWindowResize();
window.addEventListener( 'resize', onWindowResize, false );
renderer.domElement.addEventListener( 'mousemove', onMouseMove, false );
renderer.domElement.addEventListener( 'mousedown', onMouseDown, false );
renderer.domElement.addEventListener( 'mouseup', onMouseUp, false );
renderer.domElement.addEventListener( 'mouseleave', onMouseLeave, false );
secondRenderer.domElement.addEventListener( 'mousemove', onMouseMove, false );
secondRenderer.domElement.addEventListener( 'mousedown', onMouseDown, false );
secondRenderer.domElement.addEventListener( 'mouseup', onMouseUp, false );
secondRenderer.domElement.addEventListener( 'mouseleave', onMouseLeave, false );
// GUI
const gui = new GUI();
gui.width = 300;
const ionOptions = gui.addFolder( 'Ion' );
ionOptions.add( params, 'ionAssetId' );
ionOptions.add( params, 'ionAccessToken' );
ionOptions.add( params, 'reload' );
ionOptions.open();
const tileOptions = gui.addFolder( 'Tiles Options' );
tileOptions.add( params, 'loadSiblings' );
tileOptions.add( params, 'stopAtEmptyTiles' );
tileOptions.add( params, 'displayActiveTiles' );
tileOptions.add( params, 'errorTarget' ).min( 0 ).max( 50 );
tileOptions.add( params, 'errorThreshold' ).min( 0 ).max( 1000 );
tileOptions.add( params, 'maxDepth' ).min( 1 ).max( 100 );
tileOptions.add( params, 'up', [ '+Y', '+Z', '-Z' ] );
const debug = gui.addFolder( 'Debug Options' );
debug.add( params, 'displayBoxBounds' );
debug.add( params, 'colorMode', {
NONE,
SCREEN_ERROR,
GEOMETRIC_ERROR,
DISTANCE,
DEPTH,
RELATIVE_DEPTH,
IS_LEAF,
RANDOM_COLOR,
} );
const exampleOptions = gui.addFolder( 'Example Options' );
exampleOptions.add( params, 'resolutionScale' ).min( 0.01 ).max( 2.0 ).step( 0.01 ).onChange( onWindowResize );
exampleOptions.add( params, 'orthographic' );
exampleOptions.add( params, 'showThirdPerson' );
exampleOptions.add( params, 'showSecondView' ).onChange( onWindowResize );
exampleOptions.add( params, 'enableUpdate' ).onChange( v => {
tiles.parseQueue.autoUpdate = v;
tiles.downloadQueue.autoUpdate = v;
if ( v ) {
tiles.parseQueue.scheduleJobRun();
tiles.downloadQueue.scheduleJobRun();
}
} );
exampleOptions.add( params, 'raycast', { NONE, ALL_HITS, FIRST_HIT_ONLY } );
exampleOptions.add( params, 'enableCacheDisplay' );
exampleOptions.add( params, 'enableRendererStats' );
gui.open();
statsContainer = document.createElement( 'div' );
document.getElementById( 'info' ).appendChild( statsContainer );
// Stats
stats = new Stats();
stats.showPanel( 0 );
document.body.appendChild( stats.dom );
}
Example #10
Source File: Setup.js From webmc with MIT License | 4 votes |
function Setup (game) {
game.canvas = document.querySelector('#c')
game.pcanvas = document.querySelector('#c_player')
game.renderer = new WebGLRenderer({
canvas: game.canvas,
PixelRatio: window.devicePixelRatio
})
game.renderer.sortObjects = true
game.scene = new Scene()
game.camera = new PerspectiveCamera(game.fov.normal, 2, 0.1, 1000)
game.camera.rotation.order = 'YXZ'
game.camera.position.set(26, 26, 26)
game.scene.add(new AmbientLight(0xdddddd))
if (!game.production) {
game.stats = new Stats()
game.drawcalls = game.stats.addPanel(
new Stats.Panel('calls', '#ff8', '#221')
)
game.stats.showPanel(0)
document.body.appendChild(game.stats.dom)
}
game.distanceBasedFog = new DistanceBasedFog(game)
game.servers = {
production: game.al.get('config').minecraftProduction,
development: game.al.get('config').minecraftDevelopment
}
UrlParams(game)
console.warn(gpuInfo())
game.socket = new Socket(game)
game.pii = new PlayerInInventory(game)
game.bb = new BlockBreak(game)
game.bp = new BlockPlace(game)
game.world = new World(game)
game.ent = new Entities(game)
game.chat = new Chat(game)
game.inv_bar = new InventoryBar(game)
game.tl = new TabList(game)
game.ls = new LoadingScreen(game)
game.ls.show('Waiting for proxy...')
let hostname, port, pars
if (game.proxy === 'local') {
hostname = document.location.hostname
port = document.location.port
} else if (game.proxy === 'production') {
pars = game.al.get('config').proxy.split(':')
hostname = pars[0]
port = pars[1]
} else {
pars = game.proxy.split(':')
hostname = pars[0]
port = pars[1]
}
window.fetch(`${document.location.protocol}//${hostname}:${port}/proxyCheck`)
.then(response => response.text())
.then(data => {
if (data === 'OK') {
game.ls.show(`Connecting to ${game.server}...`)
// PLAYER UUID
window.fetch(`${document.location.protocol}//${hostname}:${port}/getId?nick=${game.nick}`)
.then(response => response.text())
.then(id => {
if (id !== 'ERR') {
console.log(`UUID: ${id}`)
// SKIN
game.skinUrl = `${document.location.protocol}//${hostname}:${port}/getSkin?id=${id}`
console.log(game.skinUrl)
new TextureLoader().load(game.skinUrl, (texture) => {
game.pii.setup(texture)
})
} else {
console.log('UUID not found!')
game.pii.setup(game.al.get('playerTex'))
}
})
}
})
game.distanceBasedFog.addShaderToMaterials([
game.world.material,
game.ent.mobMaterial,
game.ent.playerMaterial,
game.ent.objectMaterial
])
const gui = new dat.GUI()
game.params = {
chunkdist: 4,
frustumtest: false
}
game.distanceBasedFog.updateDistance(game.params.chunkdist)
gui
.add(game.params, 'chunkdist', 2, 10, 1)
.name('Render distance')
.onChange(function (val) {
if (game.distanceBasedFog.visible) {
game.distanceBasedFog.updateDistance(val)
}
})
.listen()
gui
.add(game.fov, 'normal', 30, 110, 1)
.name('FOV')
.onChange(function (val) {
game.fov.sprint = game.fov.normal + 10
game.camera.fov = game.fov.normal
game.camera.updateProjectionMatrix()
})
.listen()
gui
.add(game.distanceBasedFog, 'visible')
.name('Enable fog')
.onChange(function (val) {
if (val) {
game.distanceBasedFog.updateDistance(game.params.chunkdist)
} else {
game.distanceBasedFog.updateDistance(1000)
}
})
.listen()
gui
.add(game.world.chunkManager, 'smooth')
.name('Smooth chunks')
.listen()
gui
.add(game.world.material, 'wireframe')
.name('Wireframe')
.listen()
gui
.add(game.params, 'frustumtest')
.name('Frustum test')
.listen()
game.eh = new EventHandler(game)
}
Example #11
Source File: vr.js From 3DTilesRendererJS with Apache License 2.0 | 4 votes |
function init() {
scene = new Scene();
// primary camera view
renderer = new WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0xbbbbbb );
renderer.outputEncoding = sRGBEncoding;
renderer.xr.enabled = true;
document.body.appendChild( renderer.domElement );
renderer.domElement.tabIndex = 1;
renderer.setAnimationLoop( animate );
// create workspace
workspace = new Group();
scene.add( workspace );
grid = new GridHelper( 10, 10, 0xffffff, 0xffffff );
grid.material.transparent = true;
grid.material.opacity = 0.5;
grid.material.depthWrite = false;
workspace.add( grid );
camera = new PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 0.1, 4000 );
camera.position.set( 0, 1, 0 );
workspace.add( camera );
// lights
const dirLight = new DirectionalLight( 0xffffff );
dirLight.position.set( 1, 2, 3 );
scene.add( dirLight );
const ambLight = new AmbientLight( 0xffffff, 0.2 );
scene.add( ambLight );
// tile set
box = new Box3();
sphere = new Sphere();
// parent for centering the tileset
offsetParent = new Group();
offsetParent.rotation.x = Math.PI / 2;
offsetParent.position.y = 32;
scene.add( offsetParent );
tiles = new TilesRenderer( 'https://raw.githubusercontent.com/NASA-AMMOS/3DTilesSampleData/master/msl-dingo-gap/0528_0260184_to_s64o256_colorize/scene-tileset.json' );
offsetParent.add( tiles.group );
// We set camera for tileset
tiles.setCamera( camera );
tiles.setResolutionFromRenderer( camera, renderer );
// We define a custom scheduling callback to handle also active WebXR sessions
const tilesSchedulingCB = func => {
tasks.push( func );
};
// We set our scheduling callback for tiles downloading and parsing
tiles.downloadQueue.schedulingCallback = tilesSchedulingCB;
tiles.parseQueue.schedulingCallback = tilesSchedulingCB;
tiles.lruCache.maxSize = 1200;
tiles.lruCache.minSize = 900;
// Raycasting init
raycaster = new Raycaster();
fwdVector = new Vector3( 0, 0, 1 );
const rayIntersectMat = new MeshBasicMaterial( { color: 0xb2dfdb } );
intersectRing = new Mesh( new TorusBufferGeometry( 1.5, 0.2, 16, 100 ), rayIntersectMat );
intersectRing.visible = false;
scene.add( intersectRing );
// vr setup
document.body.appendChild( VRButton.createButton( renderer ) );
controller = renderer.xr.getController( 0 );
controller.addEventListener( 'selectstart', () => {
if ( intersectRing.visible ) {
workspace.position.copy( intersectRing.position );
}
} );
controller.addEventListener( 'connected', function ( event ) {
this.controllerActive = true;
this.add( buildController( event.data ) );
} );
controller.addEventListener( 'disconnected', function () {
this.controllerActive = false;
this.remove( this.children[ 0 ] );
} );
workspace.add( controller );
// controller models
const controllerModelFactory = new XRControllerModelFactory();
controllerGrip = renderer.xr.getControllerGrip( 0 );
controllerGrip.add( controllerModelFactory.createControllerModel( controllerGrip ) );
workspace.add( controllerGrip );
onWindowResize();
window.addEventListener( 'resize', onWindowResize, false );
// GUI
const gui = new GUI();
gui.width = 300;
gui.add( params, 'displayGrid' );
gui.add( params, 'displayBoxBounds' );
gui.add( params, 'colorMode', {
NONE,
SCREEN_ERROR,
GEOMETRIC_ERROR,
DISTANCE,
DEPTH,
RELATIVE_DEPTH,
IS_LEAF,
RANDOM_COLOR,
} );
gui.open();
}
Example #12
Source File: index.js From 3DTilesRendererJS with Apache License 2.0 | 4 votes |
function init() {
scene = new Scene();
// primary camera view
renderer = new WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0x151c1f );
renderer.outputEncoding = sRGBEncoding;
document.body.appendChild( renderer.domElement );
renderer.domElement.tabIndex = 1;
camera = new PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 4000 );
camera.position.set( 400, 400, 400 );
cameraHelper = new CameraHelper( camera );
scene.add( cameraHelper );
orthoCamera = new OrthographicCamera();
orthoCameraHelper = new CameraHelper( orthoCamera );
scene.add( orthoCameraHelper );
// secondary camera view
secondCamera = new PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 4000 );
secondCamera.position.set( 400, 400, - 400 );
secondCamera.lookAt( 0, 0, 0 );
secondRenderer = new WebGLRenderer( { antialias: true } );
secondRenderer.setPixelRatio( window.devicePixelRatio );
secondRenderer.setSize( window.innerWidth, window.innerHeight );
secondRenderer.setClearColor( 0x151c1f );
secondRenderer.outputEncoding = sRGBEncoding;
document.body.appendChild( secondRenderer.domElement );
secondRenderer.domElement.style.position = 'absolute';
secondRenderer.domElement.style.right = '0';
secondRenderer.domElement.style.top = '0';
secondRenderer.domElement.style.outline = '#0f1416 solid 2px';
secondRenderer.domElement.tabIndex = 1;
secondControls = new FlyOrbitControls( secondCamera, secondRenderer.domElement );
secondControls.screenSpacePanning = false;
secondControls.minDistance = 1;
secondControls.maxDistance = 2000;
secondCameraHelper = new CameraHelper( secondCamera );
scene.add( secondCameraHelper );
// Third person camera view
thirdPersonCamera = new PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 4000 );
thirdPersonCamera.position.set( 50, 40, 40 );
thirdPersonCamera.lookAt( 0, 0, 0 );
thirdPersonRenderer = new WebGLRenderer( { antialias: true } );
thirdPersonRenderer.setPixelRatio( window.devicePixelRatio );
thirdPersonRenderer.setSize( window.innerWidth, window.innerHeight );
thirdPersonRenderer.setClearColor( 0x0f1416 );
thirdPersonRenderer.outputEncoding = sRGBEncoding;
document.body.appendChild( thirdPersonRenderer.domElement );
thirdPersonRenderer.domElement.style.position = 'fixed';
thirdPersonRenderer.domElement.style.left = '5px';
thirdPersonRenderer.domElement.style.bottom = '5px';
thirdPersonRenderer.domElement.tabIndex = 1;
thirdPersonControls = new FlyOrbitControls( thirdPersonCamera, thirdPersonRenderer.domElement );
thirdPersonControls.screenSpacePanning = false;
thirdPersonControls.minDistance = 1;
thirdPersonControls.maxDistance = 2000;
// controls
controls = new FlyOrbitControls( camera, renderer.domElement );
controls.screenSpacePanning = false;
controls.minDistance = 1;
controls.maxDistance = 2000;
// lights
const dirLight = new DirectionalLight( 0xffffff );
dirLight.position.set( 1, 2, 3 );
scene.add( dirLight );
const ambLight = new AmbientLight( 0xffffff, 0.2 );
scene.add( ambLight );
box = new Box3();
sphere = new Sphere();
offsetParent = new Group();
scene.add( offsetParent );
// Raycasting init
raycaster = new Raycaster();
mouse = new Vector2();
rayIntersect = new Group();
const rayIntersectMat = new MeshBasicMaterial( { color: 0xe91e63 } );
const rayMesh = new Mesh( new CylinderBufferGeometry( 0.25, 0.25, 6 ), rayIntersectMat );
rayMesh.rotation.x = Math.PI / 2;
rayMesh.position.z += 3;
rayIntersect.add( rayMesh );
const rayRing = new Mesh( new TorusBufferGeometry( 1.5, 0.2, 16, 100 ), rayIntersectMat );
rayIntersect.add( rayRing );
scene.add( rayIntersect );
rayIntersect.visible = false;
reinstantiateTiles();
onWindowResize();
window.addEventListener( 'resize', onWindowResize, false );
renderer.domElement.addEventListener( 'pointermove', onPointerMove, false );
renderer.domElement.addEventListener( 'pointerdown', onPointerDown, false );
renderer.domElement.addEventListener( 'pointerup', onPointerUp, false );
renderer.domElement.addEventListener( 'pointerleave', onPointerLeave, false );
secondRenderer.domElement.addEventListener( 'pointermove', onPointerMove, false );
secondRenderer.domElement.addEventListener( 'pointerdown', onPointerDown, false );
secondRenderer.domElement.addEventListener( 'pointerup', onPointerUp, false );
secondRenderer.domElement.addEventListener( 'pointerleave', onPointerLeave, false );
// GUI
const gui = new GUI();
gui.width = 300;
const tileOptions = gui.addFolder( 'Tiles Options' );
tileOptions.add( params, 'loadSiblings' );
tileOptions.add( params, 'stopAtEmptyTiles' );
tileOptions.add( params, 'displayActiveTiles' );
tileOptions.add( params, 'errorTarget' ).min( 0 ).max( 50 );
tileOptions.add( params, 'errorThreshold' ).min( 0 ).max( 1000 );
tileOptions.add( params, 'maxDepth' ).min( 1 ).max( 100 );
tileOptions.add( params, 'up', [ '+Y', '+Z', '-Z' ] );
tileOptions.open();
const debug = gui.addFolder( 'Debug Options' );
debug.add( params, 'displayBoxBounds' );
debug.add( params, 'colorMode', {
NONE,
SCREEN_ERROR,
GEOMETRIC_ERROR,
DISTANCE,
DEPTH,
RELATIVE_DEPTH,
IS_LEAF,
RANDOM_COLOR,
RANDOM_NODE_COLOR,
CUSTOM_COLOR
} );
debug.open();
const exampleOptions = gui.addFolder( 'Example Options' );
exampleOptions.add( params, 'resolutionScale' ).min( 0.01 ).max( 2.0 ).step( 0.01 ).onChange( onWindowResize );
exampleOptions.add( params, 'orthographic' );
exampleOptions.add( params, 'showThirdPerson' );
exampleOptions.add( params, 'showSecondView' ).onChange( onWindowResize );
exampleOptions.add( params, 'enableUpdate' ).onChange( v => {
tiles.parseQueue.autoUpdate = v;
tiles.downloadQueue.autoUpdate = v;
if ( v ) {
tiles.parseQueue.scheduleJobRun();
tiles.downloadQueue.scheduleJobRun();
}
} );
exampleOptions.add( params, 'raycast', { NONE, ALL_HITS, FIRST_HIT_ONLY } );
exampleOptions.add( params, 'optimizeRaycast', );
exampleOptions.add( params, 'enableCacheDisplay' );
exampleOptions.add( params, 'enableRendererStats' );
exampleOptions.open();
gui.add( params, 'reload' );
gui.open();
statsContainer = document.createElement( 'div' );
statsContainer.style.position = 'absolute';
statsContainer.style.top = 0;
statsContainer.style.left = 0;
statsContainer.style.color = 'white';
statsContainer.style.width = '100%';
statsContainer.style.textAlign = 'center';
statsContainer.style.padding = '5px';
statsContainer.style.pointerEvents = 'none';
statsContainer.style.lineHeight = '1.5em';
document.body.appendChild( statsContainer );
// Stats
stats = new Stats();
stats.showPanel( 0 );
document.body.appendChild( stats.dom );
}
Example #13
Source File: i3dmExample.js From 3DTilesRendererJS with Apache License 2.0 | 4 votes |
function init() {
scene = new Scene();
// primary camera view
renderer = new WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0x151c1f );
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = PCFSoftShadowMap;
renderer.outputEncoding = sRGBEncoding;
document.body.appendChild( renderer.domElement );
camera = new PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 4000 );
camera.position.set( 100, 100, 100 );
// controls
controls = new OrbitControls( camera, renderer.domElement );
controls.screenSpacePanning = false;
controls.minDistance = 1;
controls.maxDistance = 2000;
// lights
dirLight = new DirectionalLight( 0xffffff, 1.25 );
dirLight.position.set( 1, 2, 3 ).multiplyScalar( 40 );
dirLight.castShadow = true;
dirLight.shadow.bias = - 0.01;
dirLight.shadow.mapSize.setScalar( 2048 );
const shadowCam = dirLight.shadow.camera;
shadowCam.left = - 200;
shadowCam.bottom = - 200;
shadowCam.right = 200;
shadowCam.top = 200;
shadowCam.updateProjectionMatrix();
scene.add( dirLight );
const ambLight = new AmbientLight( 0xffffff, 0.05 );
scene.add( ambLight );
new I3DMLoader()
.load( 'https://raw.githubusercontent.com/CesiumGS/3d-tiles-samples/main/1.0/TilesetWithTreeBillboards/tree.i3dm' )
.then( res => {
let instance = null;
res.scene.traverse( c => {
if ( ! instance && c.isInstancedMesh ) {
instance = c;
}
} );
if ( instance ) {
res.scene.updateMatrixWorld( true );
const pos = new Vector3();
const quat = new Quaternion();
const sca = new Vector3();
const mat = new Matrix4();
const averagePos = new Vector3();
for ( let i = 0, l = instance.count; i < l; i ++ ) {
instance.getMatrixAt( i, mat );
mat.premultiply( instance.matrixWorld );
mat.decompose( pos, quat, sca );
averagePos.add( pos );
}
averagePos.divideScalar( instance.count );
controls.target.copy( averagePos );
camera.position.add( averagePos );
controls.update();
}
console.log( res );
scene.add( res.scene );
} );
onWindowResize();
window.addEventListener( 'resize', onWindowResize, false );
}
Example #14
Source File: gltf.js From 3DTilesRendererJS with Apache License 2.0 | 4 votes |
function init() {
scene = new Scene();
// primary camera view
renderer = new WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0x151c1f );
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = PCFSoftShadowMap;
renderer.outputEncoding = sRGBEncoding;
document.body.appendChild( renderer.domElement );
camera = new PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 4000 );
camera.position.set( 3, 10, 20 );
// controls
controls = new OrbitControls( camera, renderer.domElement );
controls.screenSpacePanning = false;
controls.minDistance = 1;
controls.maxDistance = 2000;
// lights
dirLight = new DirectionalLight( 0xffffff, 1.25 );
dirLight.position.set( 1, 2, 3 ).multiplyScalar( 40 );
dirLight.castShadow = true;
dirLight.shadow.bias = - 0.01;
dirLight.shadow.mapSize.setScalar( 2048 );
const shadowCam = dirLight.shadow.camera;
shadowCam.left = - 200;
shadowCam.bottom = - 200;
shadowCam.right = 200;
shadowCam.top = 200;
shadowCam.updateProjectionMatrix();
scene.add( dirLight );
const ambLight = new AmbientLight( 0xffffff, 0.05 );
scene.add( ambLight );
// basic gltf test files
let insertPosition = 0;
const gltfModelTests = [
'https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/CesiumMilkTruck/glTF-Binary/CesiumMilkTruck.glb',
'https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/CesiumMilkTruck/glTF-Embedded/CesiumMilkTruck.gltf',
'https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/CesiumMilkTruck/glTF/CesiumMilkTruck.gltf',
];
for ( const url of gltfModelTests ) {
const loader = new GLTFExtensionLoader();
loader.workingPath = loader.workingPathForURL( url );
loader.load( url )
.then( res => {
res.scene.position.set( insertPosition += 5, 0, 0 );
controls.target.set( insertPosition / 2, 0, 0 );
controls.update();
console.log( 'default loader:', { gltf: res, url } );
scene.add( res.scene );
} );
}
// gltf with extensions
const delegatedLoaderTests = [
'https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/CesiumMilkTruck/glTF-Draco/CesiumMilkTruck.gltf',
'https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/Box/glTF-Binary/Box.glb',
];
const manager = new LoadingManager();
const gltfLoader = new GLTFLoader( manager );
const dracoLoader = new DRACOLoader( manager );
dracoLoader.setDecoderPath( 'https://unpkg.com/[email protected]/examples/js/libs/draco/gltf/' );
gltfLoader.setDRACOLoader( dracoLoader );
manager.addHandler( /\.gltf$/, gltfLoader );
manager.addHandler( /\.glb$/, gltfLoader );
for ( const url of delegatedLoaderTests ) {
const loader = new GLTFExtensionLoader( manager );
loader.workingPath = loader.workingPathForURL( url );
loader.load( url )
.then( res => {
res.scene.position.set( insertPosition += 5, 0, 0 );
controls.target.set( insertPosition / 2, 0, 0 );
controls.update();
console.log( 'custom loader:', { gltf: res, url } );
scene.add( res.scene );
} );
}
onWindowResize();
window.addEventListener( 'resize', onWindowResize, false );
}
Example #15
Source File: customMaterial.js From 3DTilesRendererJS with Apache License 2.0 | 4 votes |
function init() {
scene = new Scene();
// primary camera view
renderer = new WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0x151c1f );
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = PCFSoftShadowMap;
renderer.outputEncoding = sRGBEncoding;
document.body.appendChild( renderer.domElement );
camera = new PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 4000 );
camera.position.set( 400, 400, 400 );
orthoCamera = new OrthographicCamera();
// controls
controls = new OrbitControls( camera, renderer.domElement );
controls.screenSpacePanning = false;
controls.minDistance = 1;
controls.maxDistance = 2000;
// lights
dirLight = new DirectionalLight( 0xffffff, 1.25 );
dirLight.position.set( 1, 2, 3 ).multiplyScalar( 40 );
dirLight.castShadow = true;
dirLight.shadow.bias = - 0.01;
dirLight.shadow.mapSize.setScalar( 2048 );
const shadowCam = dirLight.shadow.camera;
shadowCam.left = - 200;
shadowCam.bottom = - 200;
shadowCam.right = 200;
shadowCam.top = 200;
shadowCam.updateProjectionMatrix();
scene.add( dirLight );
const ambLight = new AmbientLight( 0xffffff, 0.05 );
scene.add( ambLight );
box = new Box3();
sphere = new Sphere();
offsetParent = new Group();
scene.add( offsetParent );
initTiles();
onWindowResize();
window.addEventListener( 'resize', onWindowResize, false );
// GUI
const gui = new GUI();
gui.width = 300;
gui.add( params, 'orthographic' );
gui.add( params, 'material', { DEFAULT, GRADIENT, TOPOGRAPHIC_LINES, LIGHTING } )
.onChange( () => {
tiles.forEachLoadedModel( updateMaterial );
} );
gui.add( params, 'rebuild' );
gui.open();
// Stats
stats = new Stats();
stats.showPanel( 0 );
document.body.appendChild( stats.dom );
statsContainer = document.createElement( 'div' );
statsContainer.style.position = 'absolute';
statsContainer.style.top = 0;
statsContainer.style.left = 0;
statsContainer.style.color = 'white';
statsContainer.style.width = '100%';
statsContainer.style.textAlign = 'center';
statsContainer.style.padding = '5px';
statsContainer.style.pointerEvents = 'none';
statsContainer.style.lineHeight = '1.5em';
document.body.appendChild( statsContainer );
}
Example #16
Source File: b3dmExample.js From 3DTilesRendererJS with Apache License 2.0 | 4 votes |
function init() {
infoEl = document.getElementById( 'info' );
scene = new Scene();
// primary camera view
renderer = new WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0x151c1f );
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = PCFSoftShadowMap;
renderer.outputEncoding = sRGBEncoding;
document.body.appendChild( renderer.domElement );
camera = new PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 4000 );
camera.position.set( 400, 400, 400 );
// controls
controls = new OrbitControls( camera, renderer.domElement );
controls.screenSpacePanning = false;
controls.minDistance = 1;
controls.maxDistance = 2000;
// lights
dirLight = new DirectionalLight( 0xffffff, 1.25 );
dirLight.position.set( 1, 2, 3 ).multiplyScalar( 40 );
dirLight.castShadow = true;
dirLight.shadow.bias = - 0.01;
dirLight.shadow.mapSize.setScalar( 2048 );
const shadowCam = dirLight.shadow.camera;
shadowCam.left = - 200;
shadowCam.bottom = - 200;
shadowCam.right = 200;
shadowCam.top = 200;
shadowCam.updateProjectionMatrix();
scene.add( dirLight );
const ambLight = new AmbientLight( 0xffffff, 0.05 );
scene.add( ambLight );
offsetGroup = new Group();
scene.add( offsetGroup );
new B3DMLoader()
.load( 'https://raw.githubusercontent.com/CesiumGS/3d-tiles-samples/main/1.0/TilesetWithRequestVolume/city/lr.b3dm' )
.then( res => {
console.log( res );
model = res.scene;
offsetGroup.add( model );
const box = new Box3();
box.setFromObject( model );
box.getCenter( offsetGroup.position ).multiplyScalar( - 1 );
// reassign the material to use the batchid highlight variant.
// in practice this should copy over any needed uniforms from the
// original material.
model.traverse( c => {
if ( c.isMesh ) {
c.material = new ShaderMaterial( batchIdHighlightShaderMixin( ShaderLib.standard ) );
}
} );
} );
raycaster = new Raycaster();
mouse = new Vector2();
onWindowResize();
window.addEventListener( 'resize', onWindowResize, false );
renderer.domElement.addEventListener( 'mousemove', onMouseMove, false );
}
Example #17
Source File: DisplacementSphere.js From personal-website-react with MIT License | 4 votes |
DisplacementSphere = (props) => {
const { theme } = useContext(ThemeContext);
const rgbBackground = theme === "light" ? "250 250 250" : "17 17 17";
const width = useRef(window.innerWidth);
const height = useRef(window.innerHeight);
const start = useRef(Date.now());
const canvasRef = useRef();
const mouse = useRef();
const renderer = useRef();
const camera = useRef();
const scene = useRef();
const lights = useRef();
const uniforms = useRef();
const material = useRef();
const geometry = useRef();
const sphere = useRef();
const tweenRef = useRef();
const sphereSpring = useRef();
const prefersReducedMotion = Boolean(usePrefersReducedMotion() && false); //disabled until switching themes fixed
const isInViewport = useInViewport(canvasRef);
useEffect(() => {
mouse.current = new Vector2(0.8, 0.5);
renderer.current = new WebGLRenderer({
canvas: canvasRef.current,
powerPreference: "high-performance",
});
renderer.current.setSize(width.current, height.current);
renderer.current.setPixelRatio(1);
renderer.current.outputEncoding = sRGBEncoding;
camera.current = new PerspectiveCamera(
55,
width.current / height.current,
0.1,
200
);
camera.current.position.z = 52;
scene.current = new Scene();
material.current = new MeshPhongMaterial();
material.current.onBeforeCompile = (shader) => {
uniforms.current = UniformsUtils.merge([
UniformsLib["ambient"],
UniformsLib["lights"],
shader.uniforms,
{ time: { type: "f", value: 0 } },
]);
shader.uniforms = uniforms.current;
shader.vertexShader = vertShader;
shader.fragmentShader = fragShader;
shader.lights = true;
};
geometry.current = new SphereBufferGeometry(32, 128, 128);
sphere.current = new Mesh(geometry.current, material.current);
sphere.current.position.z = 0;
sphere.current.modifier = Math.random();
scene.current.add(sphere.current);
return () => {
cleanScene(scene.current);
cleanRenderer(renderer.current);
};
}, []);
useEffect(() => {
const dirLight = new DirectionalLight(
rgbToThreeColor("250 250 250"),
0.6
);
const ambientLight = new AmbientLight(
rgbToThreeColor("250 250 250"),
theme === "light" ? 0.8 : 0.1
);
dirLight.position.z = 200;
dirLight.position.x = 100;
dirLight.position.y = 100;
lights.current = [dirLight, ambientLight];
scene.current.background = rgbToThreeColor(rgbBackground);
lights.current.forEach((light) => scene.current.add(light));
return () => {
removeLights(lights.current);
};
}, [rgbBackground, theme]);
useEffect(() => {
const handleResize = () => {
const canvasHeight = innerHeight();
const windowWidth = window.innerWidth;
const fullHeight = canvasHeight + canvasHeight * 0.3;
canvasRef.current.style.height = fullHeight;
renderer.current.setSize(windowWidth, fullHeight);
camera.current.aspect = windowWidth / fullHeight;
camera.current.updateProjectionMatrix();
// Render a single frame on resize when not animating
if (prefersReducedMotion) {
renderer.current.render(scene.current, camera.current);
}
if (windowWidth <= media.mobile) {
sphere.current.position.x = 14;
sphere.current.position.y = 10;
} else if (windowWidth <= media.tablet) {
sphere.current.position.x = 18;
sphere.current.position.y = 14;
} else {
sphere.current.position.x = 22;
sphere.current.position.y = 16;
}
};
window.addEventListener("resize", handleResize);
handleResize();
return () => {
window.removeEventListener("resize", handleResize);
};
}, [prefersReducedMotion]);
useEffect(() => {
const onMouseMove = (event) => {
const { rotation } = sphere.current;
const position = {
x: event.clientX / window.innerWidth,
y: event.clientY / window.innerHeight,
};
if (!sphereSpring.current) {
sphereSpring.current = value(rotation.toArray(), (values) =>
rotation.set(
values[0],
values[1],
sphere.current.rotation.z
)
);
}
tweenRef.current = spring({
from: sphereSpring.current.get(),
to: [position.y / 2, position.x / 2],
stiffness: 30,
damping: 20,
velocity: sphereSpring.current.getVelocity(),
mass: 2,
restSpeed: 0.0001,
}).start(sphereSpring.current);
};
if (!prefersReducedMotion && isInViewport) {
window.addEventListener("mousemove", onMouseMove);
}
return () => {
window.removeEventListener("mousemove", onMouseMove);
if (tweenRef.current) {
tweenRef.current.stop();
}
};
}, [isInViewport, prefersReducedMotion]);
useEffect(() => {
let animation;
const animate = () => {
animation = requestAnimationFrame(animate);
if (uniforms.current !== undefined) {
uniforms.current.time.value =
0.00005 * (Date.now() - start.current);
}
sphere.current.rotation.z += 0.001;
renderer.current.render(scene.current, camera.current);
};
if (!prefersReducedMotion && isInViewport) {
animate();
} else {
renderer.current.render(scene.current, camera.current);
}
return () => {
cancelAnimationFrame(animation);
};
}, [isInViewport, prefersReducedMotion]);
return (
<Transition appear in onEnter={reflow} timeout={3000}>
{(status) => (
<canvas
aria-hidden
className={classNames(
"displacement-sphere",
`displacement-sphere--${status}`
)}
ref={canvasRef}
{...props}
/>
)}
</Transition>
);
}