I want to create a sun surrounded with a large ring or orbit in three.js. Here is my source code (using require.js modules):
require(['js/interactive.js', 'js/OrbitControls.js', 'js/three.min.js'], function (InteractionManager, OrbitControls, THREE) {
const ZOOM = 300;
const scene = new THREE.Scene();
const camera = new THREE.OrthographicCamera(window.innerWidth / -ZOOM, window.innerWidth / ZOOM, window.innerHeight / ZOOM, window.innerHeight / - ZOOM, 1, 1000);
const renderer = new THREE.WebGLRenderer({ preserveDrawingBuffer: true });
renderer.setSize(window.innerWidth, window.innerHeight);
// renderer.setClearColorHex( 0x555555, 1 );
document.body.appendChild(renderer.domElement);
// new a interaction, then you can add interaction-event with your free style
const interaction = new InteractionManager(renderer, camera, renderer.domElement);
const loader = new THREE.TextureLoader();
const controls = new OrbitControls(camera, renderer.domElement);
const light = new THREE.AmbientLight(0xffffff); // soft white light
scene.add(light);
// const light2 = new THREE.PointLight(0xffffff); // soft white light
// light2.position.set(10, 0, 0);
// scene.add(light2);
const geometry = new THREE.SphereGeometry(1, 32, 32);
const material = new THREE.MeshPhongMaterial({
map: loader.load('./resources/2k_sun.jpeg'),
specular: 0x555555,
shininess: 50
});
const sun = new THREE.Mesh(geometry, material);
scene.add(sun);
interaction.add(sun);
sun.addEventListener('click', function(ev) {
var bb = new THREE.Box3()
bb.setFromObject(sun);
bb.getCenter(controls.target);
camera.zoom = 1;
camera.updateProjectionMatrix();
});
const ringGeometry = new THREE.RingGeometry(50, 51, 32);
const ringMaterial = new THREE.MeshBasicMaterial( { color: 0x808080, side: THREE.DoubleSide } );
const ring = new THREE.Mesh( ringGeometry, ringMaterial );
scene.add( ring );
camera.position.set(0, 0, 5);
controls.update();
const animate = function () {
requestAnimationFrame(animate);
sun.rotation.x += 0.01;
sun.rotation.y += 0.01;
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.render(scene, camera);
};
animate();
})
interactive.js is an interaction library I downloaded from here. I used it to zoom in on the sun when it's clicked.
However, when I run this code, parts of the ring will not render at certain angles. This is only fixed if I make the ring much smaller. Below is a screenshot of this behavior:
My question: How can I make this ring fully visible at any angle and maintain the large size?
Related
I'm trying to smooth the normals of a mesh starting from a non indexed BufferGeometry.
This question has been answered before however the Three.js api has changed substantially since and I can't get it to work on r130
From what I've understood, I need to first merge the vertices to get an indexed BufferGeometry then re-compute the normals, but it doesn't seem to work.
Here is a minimal example using the defaulf cube :
// Scene
const scene = new THREE.Scene();
// Geometry
const boxGeometry = new THREE.BoxGeometry(.7,.7,.7);
// Materials
const shadedMaterial = new THREE.MeshStandardMaterial();
shadedMaterial.metalness = 0.4;
shadedMaterial.roughness = 0.4;
shadedMaterial.color = new THREE.Color(0xffffff);
// Mesh
const smoothBoxGeometry=BufferGeometryUtils
.mergeVertices(new THREE.BufferGeometry().copy(boxGeometry))
smoothBoxGeometry.computeVertexNormals();
smoothBoxGeometry.computeBoundingBox();
smoothBoxGeometry.normalizeNormals();
const box = new THREE.Mesh(smoothBoxGeometry, shadedMaterial);
scene.add(box);
flat shaded cube instead of expected smooth shaded cube
What am I missing ?
Try it like so:
let camera, scene, renderer;
let mesh;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.01, 10);
camera.position.z = 4;
scene = new THREE.Scene();
const hemiLight = new THREE.HemisphereLight(0xffffff, 0x444444);
hemiLight.position.set(0, 20, 0);
scene.add(hemiLight);
const dirLight = new THREE.DirectionalLight(0xffffff);
dirLight.position.set(-3, 10, -10);
scene.add(dirLight);
let geometry = new THREE.BoxGeometry();
geometry.deleteAttribute('normal');
geometry.deleteAttribute('uv');
geometry = THREE.BufferGeometryUtils.mergeVertices(geometry);
geometry.computeVertexNormals();
const material = new THREE.MeshStandardMaterial();
mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
}
function animate() {
requestAnimationFrame(animate);
mesh.rotation.x += 0.01;
mesh.rotation.y += 0.02;
renderer.render(scene, camera);
}
body {
margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.130.1/build/three.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.130.1/examples/js/utils/BufferGeometryUtils.js"></script>
BufferGeometryUtils.mergeVertices() can only perform the merge if vertex data are identical. To ensure this, it is necessary to remove the existing normal and uv attribute.
I have a simple 3d cube (BoxGeometry of 100, 100, 100) and I am trying to rotate it. If we call all 100x100x100 a tile - when I rotate it I can see it's overlapping the below tile.
(by changing color, now I totally understand the behaviour).
tl.to(this.cube4.rotation, 0.5, {z: -45* Math.PI/180});
[
What if I want to rotate it based on an anchor point of right bottom? So instead of overflowing inside the below tile, it will overflow that portion to above tile.
So it will look like the green example and not the red example:
The red example here is achieved by
tl.to(this.cube4.rotation, 0.5, {z: -45* Math.PI/180});
tl.to(this.cube4.position, 0.5, {x: 50 }, 0.5);
I am very new to three.js so if any terminology is wrong, please warn me
Add the ("red") cube to a THREE.Group, in that way that the rotation axis (the edge) is in the origin of the group. This means the cube has to be shifted by the half side length.
If you rotate the group object, then the cube (which is inside the group) will rotate around the edge and not around its center.
e.g.
var bbox = new THREE.Box3().setFromObject(cube);
cube.position.set(bbox.min.x, bbox.max.y, 0);
var pivot = new THREE.Group();
pivot.add(cube);
scene.add(pivot);
See also the answer to How to center a group of objects?, which uses this solution to rotate a group of objects.
(function onLoad() {
var camera, scene, renderer, orbitControls, pivot;
var rot = 0.02;
init();
animate();
function init() {
container = document.getElementById('container');
renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
container.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 100);
camera.position.set(4, 1, 2);
//camera.lookAt( -1, 0, 0 );
loader = new THREE.TextureLoader();
loader.setCrossOrigin("");
scene = new THREE.Scene();
scene.background = new THREE.Color(0xffffff);
scene.add(camera);
window.onresize = function() {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
}
orbitControls = new THREE.OrbitControls(camera, container);
var ambientLight = new THREE.AmbientLight(0x404040);
scene.add(ambientLight);
var directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
directionalLight.position.set(1,2,-1.5);
scene.add( directionalLight );
addGridHelper();
createModel();
}
function createModel() {
var material = new THREE.MeshPhongMaterial({color:'#80f080'});
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var cube1 = new THREE.Mesh(geometry, material);
cube1.position.set(0,-0.5,-0.5);
var cube2 = new THREE.Mesh(geometry, material);
cube2.position.set(0,0.5,-0.5);
var cube3 = new THREE.Mesh(geometry, material);
cube3.position.set(0,-0.5,0.5);
var material2 = new THREE.MeshPhongMaterial({color:'#f08080'});
var cube4 = new THREE.Mesh(geometry, material2);
var bbox = new THREE.Box3().setFromObject(cube4);
cube4.position.set(bbox.min.x, bbox.max.y, 0);
pivot = new THREE.Group();
pivot.add(cube4);
pivot.position.set(-bbox.min.x, 0.5-bbox.max.y, 0.5);
scene.add(cube1);
scene.add(cube2);
scene.add(cube3);
scene.add(pivot);
}
function addGridHelper() {
var helper = new THREE.GridHelper(100, 100);
helper.material.opacity = 0.25;
helper.material.transparent = true;
scene.add(helper);
var axis = new THREE.AxesHelper(1000);
scene.add(axis);
}
function animate() {
requestAnimationFrame(animate);
orbitControls.update();
pivot.rotation.z += rot;
if (pivot.rotation.z > 0.0 || pivot.rotation.z < -Math.PI/2) rot *= -1;
render();
}
function render() {
renderer.render(scene, camera);
}
})();
<!--script src="https://threejs.org/build/three.js"></!--script-->
<script src="https://rawcdn.githack.com/mrdoob/three.js/r124/build/three.js"></script>
<script src="https://rawcdn.githack.com/mrdoob/three.js/r124/examples/js/controls/OrbitControls.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tween.js/17.2.0/Tween.js"></script>
<div id="container"></div>
From the first image, it appears that the pivot of your red tile is at its center.
For the rotation you want, you would ideally change the pivot to the lower right of the cube. This is impossible without modifying the geometry of the cube.
BUT a simple trick is to create an empty node at that pivot point, parent your cube to that empty, and apply your rotation to the empty. (Don't forget to remove your translation, you don't need it anymore)
Here is some pseudo code, assuming your red box is centered at (0,0,0) and has a width and height of 100:
// create an empty node at desired rotation pivot
var empty = new Object3D or group
empty.position = (50, -50, 0)
// parent your cube to the empty
var cube = your box
empty.add(cube)
// you may need to change the local position of your cube to bring it back to its global position of (0,0,0)
cube.position = (-50, 50, 0)
rotate empty by 45°
I think you can get the bounds of the rotated object like this:
bounds = new THREE.Box3().setFromObject( theRedObject )
Then reposition the object.y based on its bounds.min.y
let scene, camera, controls, ambient, point, loader, renderer, container, stats;
const targetRotation = 0;
const targetRotationOnMouseDown = 0;
const mouseX = 0;
const mouseXOnMouseDown = 0;
const windowHalfX = window.innerWidth / 2;
const windowHalfY = window.innerHeight / 2;
init();
animate();
var box, b1, b2, b3;
function init() {
// Create a scene which will hold all our meshes to be rendered
scene = new THREE.Scene();
// Create and position a camera
camera = new THREE.PerspectiveCamera(
60, // Field of view
window.innerWidth / window.innerHeight, // Aspect ratio
/*window.innerWidth / -8,
window.innerWidth / 8,
window.innerHeight / 8,
window.innerHeight / -8,
*/
0.1, // Near clipping pane
1000 // Far clipping pane
);
scene.add(camera)
// Reposition the camera
camera.position.set(0, 5, 10);
// Point the camera at a given coordinate
camera.lookAt(new THREE.Vector3(0, 0, 0));
// Add orbit control
controls = new THREE.OrbitControls(camera);
controls.target.set(0, -0.5, 0);
controls.update();
// Add an ambient lights
ambient = new THREE.AmbientLight(0xffffff, 0.2);
scene.add(ambient);
// Add a point light that will cast shadows
point = new THREE.PointLight(0xffffff, 1);
point.position.set(25, 50, 25);
point.castShadow = true;
point.shadow.mapSize.width = 1024;
point.shadow.mapSize.height = 1024;
scene.add(point);
group = new THREE.Group();
group.position.y = 0;
scene.add(group);
rotationAnchor = new THREE.Object3D()
group.add(rotationAnchor);
box = new THREE.Mesh(new THREE.BoxGeometry(), new THREE.MeshStandardMaterial({
color: 'grey'
}))
b1 = box.clone();
b2 = box.clone();
b3 = box.clone();
b3.material = b3.material.clone()
b3.material.color.set('red')
group.add(box);
group.add(b1);
b1.position.y += 1
group.add(b2);
b2.position.z += 1
rotationAnchor.add(b3);
rotationAnchor.position.set(0.5, 0.5, 1.5)
b3.position.set(-.5, -.5, -.5)
// Create a renderer
renderer = new THREE.WebGLRenderer({
antialias: true
});
// Set size
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
// Set color
renderer.setClearColor(0xf8a5c2);
renderer.gammaOutput = true;
// Enable shadow mapping
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
// Append to the document
container = document.createElement("div");
document.body.appendChild(container);
document.body.appendChild(renderer.domElement);
// Add resize listener
window.addEventListener("resize", onWindowResize, false);
// Enable FPS stats
stats = new Stats();
container.appendChild(stats.dom);
var gui = new dat.GUI({
height: 5 * 32 - 1
});
let params = {
'test': 4,
'bevelThickness': 1,
'bevelSize': 1.5,
'bevelSegments': 3
}
gui.add(params, 'test', 0, 10).onChange(val => {
test = val
})
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function animate() {
rotationAnchor.rotation.z = (Math.cos(performance.now() * 0.001) * Math.PI * 0.25) + (Math.PI * 1.25)
requestAnimationFrame(animate);
// Re-render scene
renderer.render(scene, camera);
// Update stats
stats.update();
}
body {
overflow: hidden;
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/96/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script src="https://threejs.org/examples/js/libs/stats.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.2/dat.gui.min.js"></script>
I am working in a three.js project. In the project I have to show all edges of geometries even those edges are intersecting with other objects' surfaces.
Here is the snippet code that illustrates my problem.
var camera, scene, renderer, material, stats, group, wireframeMaterial;
init();
animate();
function init() {
// Renderer.
renderer = new THREE.WebGLRenderer({antialias: true, alpha:true,clearAlpha:0,clearColor: 0xff0000});
//renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
// Add renderer to page
document.body.appendChild(renderer.domElement);
// Create camera.
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = 400;
// Create scene.
scene = new THREE.Scene();
group=new THREE.Group()
// Create material
material = new THREE.MeshBasicMaterial();
wireframeMaterial=new THREE.LineBasicMaterial( { color: 0x000000, side:THREE.FrontSide ,transparent:false,opacity:1,linewidth: 1 })
// Create cube and add to scene.
var geometry = new THREE.BoxGeometry(200, 200, 200);
var mesh1 = new THREE.Mesh(geometry, material);
group.add(mesh1);
var geometry2 = new THREE.BoxGeometry(100,100,100);
var mesh2 = new THREE.Mesh(geometry2, material);
group.add(mesh2);
mesh2.position.fromArray([0,150,0])
var edges = new THREE.EdgesGeometry( geometry );
var line = new THREE.LineSegments( edges, wireframeMaterial );
mesh1.add( line );
var edges2 = new THREE.EdgesGeometry( geometry2 );
var line2 = new THREE.LineSegments( edges2, wireframeMaterial );
mesh2.add( line2 );
scene.add(group)
// Add listener for window resize.
window.addEventListener('resize', onWindowResize, false);
}
function animate() {
requestAnimationFrame(animate);
group.rotation.x += 0.005;
group.rotation.y += 0.01;
renderer.render(scene, camera);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
body {
padding: 0;
margin: 0;
}
canvas {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/97/three.min.js"></script>
In fiddle code you can see there are two cubes top of each other. I want bottom edges of small cube to become visible. One solution is making mesh basic material transparent. However in that situation edges that are behind cubes it self will be visible too which is not allowed in the project.
So are there any alternative solution for this issue?
Found a good solution, you need to use the polygonOffset parameters of the basic material.
var material = new THREE.MeshBasicMaterial({
polygonOffset: true,
polygonOffsetFactor: 1, // positive value pushes polygon further away
polygonOffsetUnits: 1
});
Found it on this question: three.js EdgesHelper showing certain diagonal lines on Collada model
EdgesGeometry will render the hard edges only.
WireframeGeometry will render all edges.
var camera, scene, renderer, material, stats, group, wireframeMaterial;
init();
animate();
function init() {
// Renderer.
renderer = new THREE.WebGLRenderer({antialias: true, alpha:true,clearAlpha:0,clearColor: 0xff0000});
//renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
// Add renderer to page
document.body.appendChild(renderer.domElement);
// Create camera.
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = 400;
// Create scene.
scene = new THREE.Scene();
group=new THREE.Group()
// Create materials
var material = new THREE.MeshBasicMaterial({
polygonOffset: true,
polygonOffsetFactor: 1, // positive value pushes polygon further away
polygonOffsetUnits: 1
});
var wireframeMaterial= new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 2 } );
// Create cube and add to scene.
var geometry = new THREE.BoxGeometry(200, 200, 200);
var edges = new THREE.EdgesGeometry(geometry);
var line = new THREE.LineSegments( edges, wireframeMaterial );
var mesh = new THREE.Mesh(geometry, material);
group.add(mesh, line);
var geometry2 = new THREE.BoxGeometry(100,100,100);
var wire = new THREE.EdgesGeometry(geometry2);
var line2 = new THREE.LineSegments( wire, wireframeMaterial );
var mesh2 = new THREE.Mesh(geometry2, material);
line2.position.fromArray([0,150,0]);
mesh2.position.fromArray([0,150,0]);
group.add(mesh2, line2);
scene.add(group)
// Add listener for window resize.
window.addEventListener('resize', onWindowResize, false);
// Add stats to page.
stats = new Stats();
document.body.appendChild( stats.dom );
}
function animate() {
requestAnimationFrame(animate);
group.rotation.x += 0.005;
group.rotation.y += 0.01;
renderer.render(scene, camera);
stats.update();
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
<script type="text/javascript" src="https://rawgit.com/mrdoob/three.js/master/build/three.min.js"></script>
<script type="text/javascript" src="https://cdn.rawgit.com/mrdoob/stats.js/r17/build/stats.min.js"></script>
Hi I have this code that draws the image below
window.onload = function()
{
// init renderer
var renderer=new THREE.WebGLRenderer();
canvas_width=side; canvas_height=side;
renderer.setSize(canvas_width,canvas_height);
document.body.appendChild(renderer.domElement);
// init scene and camera
var scene=new THREE.Scene();
var camera=new THREE.PerspectiveCamera(90,canvas_width/canvas_height,1,100);
camera.position.y=5;
camera.position.z=25;
var texture = new THREE.TextureLoader().load( 'arrow.png' );
var img = new THREE.MeshBasicMaterial( { map: texture } );
// mesh
mesh = new THREE.Mesh(new THREE.PlaneGeometry(25,25),img);
mesh.overdraw = true;
scene.add(mesh);
// a light
var light=new THREE.HemisphereLight(0xffffff,0x000000,1.5);
light.position.set(1,1,1);
scene.add(light);
// render
requestAnimationFrame(function animate(){
requestAnimationFrame(animate);
renderer.render(scene,camera);
})
}
but I want to draw the PlaneGeometry horizontally instead of vertically, not rotating it with mesh.rotation.x=THREE.Math.degToRad(-90);, to get this at x=0 y=0 z=0:
so that with
mesh.rotation.x=THREE.Math.degToRad(-90);
the arrow will pointing down
and with:
mesh.rotation.x=THREE.Math.degToRad(90);
the arrow will pointing up
can you help me?
You can do it, rotating the geometry with .rotateX():
// init renderer
var renderer = new THREE.WebGLRenderer();
canvas_width = window.innerWidth;
canvas_height = window.innerHeight;
renderer.setSize(canvas_width, canvas_height);
document.body.appendChild(renderer.domElement);
// init scene and camera
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(90, canvas_width / canvas_height, 1, 100);
camera.position.y = 5;
camera.position.z = 25;
var texture = new THREE.TextureLoader().load('https://threejs.org/examples/textures/uv_grid_opengl.jpg');
var img = new THREE.MeshBasicMaterial({
map: texture,
side: THREE.DoubleSide
});
// mesh
geom = new THREE.PlaneGeometry(25, 25);
geom.rotateX(-Math.PI * 0.5); // this is how you can do it
mesh = new THREE.Mesh(geom, img);
mesh.overdraw = true;
scene.add(mesh);
// a light
var light = new THREE.HemisphereLight(0xffffff, 0x000000, 1.5);
light.position.set(1, 1, 1);
scene.add(light);
// render
requestAnimationFrame(function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
})
body {
overflow: hidden;
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/92/three.min.js"></script>
I was trying to render text in three.js using TextGeometry but got an empty black screen. I suspected that was an issue with the camera and I added simple green box, that box was rendered correctly.
// tslint:disable-next-line:no-var-requires
const fontJson = require("./fonts/gentilis_bold.typeface.json");
import "./index.scss";
import * as THREE from "three";
(window as any).THREE = THREE;
import "./controls/OrbitControls";
const scene = new THREE.Scene();
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 0, 5);
camera.lookAt(scene.position);
const textMaterial = new THREE.MeshPhongMaterial({ color: 0x00ff00 });
console.log(new THREE.Font(fontJson))
const textGeometry = new THREE.TextGeometry("Hello amigo", {
font: new THREE.Font(fontJson),
size: 80,
height: 5,
curveSegments: 12,
bevelEnabled: true,
bevelThickness: 10,
bevelSize: 8,
});
const textMesh = new THREE.Mesh(textGeometry, textMaterial);
// const geometry = new THREE.BoxGeometry(1, 1, 1);
// const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
// const mesh = new THREE.Mesh(geometry, material);
// scene.add(mesh);
scene.add(textMesh);
const controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.addEventListener("change", () => {
renderer.render(scene, camera);
});
renderer.render(scene, camera);
I have found the problem, sorry for the delay. If you use MeshPhongMaterial texture or others (except MeshBasicMaterial) you should add some lights to your scene. Just add this lines to your scene.
const pointLight = new THREE.PointLight(0xffffff, 1.5); pointLight.position.set(0, 100, 90);
scene.add(pointLight);
pointLight.color.setHSL(Math.random(), 1, 0.5);
const textMaterials = [
new THREE.MeshPhongMaterial({ color: 0xffffff, flatShading: true }),
new THREE.MeshPhongMaterial({ color: 0xffffff }),
];