粒子球仅在 three.js 中显示为直线
particle sphere only displaying as straight line in three.js
我正在学习使用 THREE.js 库,方法是在我的 React 应用程序中创建一个粒子球体。参考 this 项目,我已经 有点 的开始,但有点死胡同了。
出于某种原因,尽管我的所有代码本质上都是相同的——除了一些已弃用的方法被换掉了——THREE 每次都会呈现一条奇怪的直线。
看了几个小时的文档,试图学习这个组件的各个方法,还是摸不着头脑。
我有这个(现场版可以看here):
let camera;
let renderer;
let scene;
const vector3D = new THREE.Vector3();
// Get constraints of the canvas.
const getConstraints = () => {
const canvas = document.getElementById("canvas");
const { width, height } = canvas.getBoundingClientRect();
// Get attribute-set width and height - defaulting to computed constraints.
return [canvas.width ?? width, canvas.height ?? height];
};
// Retrieve a random point in the sphere for a particle to be set at.
const getRandomPointInSphere = radius => {
const x = THREE.MathUtils.randFloat(-1, 1);
const y = THREE.MathUtils.randFloat(-1, 1);
const z = THREE.MathUtils.randFloat(-1, 1);
const normaliseRatio = 1 / Math.sqrt(x * x + y * y + z * z);
vector3D.x = x * normaliseRatio * radius;
vector3D.y = y * normaliseRatio * radius;
vector3D.z = z * normaliseRatio * radius;
return vector3D;
};
// Initialisation methods.
const initScene = () => {
const [canvasWidth, canvasHeight] = getConstraints();
// Renderer initialisation.
renderer = new THREE.WebGLRenderer({
canvas: document.getElementById("canvas"),
antialias: true, alpha: true,
});
renderer.setSize(canvasWidth, canvasHeight);
renderer.setPixelRatio(window.devicePixelRatio);
// Scene initialisation.
scene = new THREE.Scene();
// Camera initialisation.
camera = new THREE.PerspectiveCamera(45, canvasWidth, canvasHeight, 1, 1000);
camera.position.set(100, 0, 100);
};
const initPoints = () => {
const geometry = new THREE.BufferGeometry();
const positions = [];
const particleSize = 0.2;
const particleColor = 0x1826e0; // Dark blue
const particleCount = 50000 / (particleSize * 10);
for(let i = 0; i < particleCount; i++){
let vertex = getRandomPointInSphere(50);
positions.push(vertex.x, vertex.y, vertex.z);
}
geometry.setAttribute("position", new THREE.Float32BufferAttribute(positions, 3));
const material = new THREE.PointsMaterial({ size: particleSize, color: particleColor });
const particles = new THREE.Points(geometry, material);
scene.add(particles);
};
initScene();
initPoints();
renderer.render(scene, camera);
我对 THREE(以及一般的画布)还很陌生,所以非常感谢大家的帮助。
首先,相机实例化的行必须是这样的:camera = new THREE.PerspectiveCamera(45, canvasWidth / canvasHeight, 1, 1000);
,有斜线而不是逗号。
然后,相机必须看场景的中心,因此camera.lookAt(scene.position);
带有固定代码的代码段:
body{
overflow: hidden;
margin: 0;
}
canvas{
border: 1px solid red;
}
<canvas id="canvas" width="400" height="400" />
<script type="module">
import * as THREE from "https://cdn.skypack.dev/three@0.136.0";
// THREE variables
let camera;
let renderer;
let scene;
let v3 = new THREE.Vector3();
// Get constraints of the canvas.
const getConstraints = () => {
const canvas = document.getElementById("canvas");
const { width, height } = canvas.getBoundingClientRect();
// Get attribute-set width and height - defaulting to computed constraints.
return [canvas.width ?? width, canvas.height ?? height];
};
// Retrieve a random point in the sphere for a particle to be set at.
const getRandomPointInSphere = radius => {
v3.randomDirection();
const normaliseRatio = 1 / Math.hypot(v3.x, v3.y, v3.z);
v3.setLength(radius * normaliseRatio);
return v3;
};
// Initialisation methods.
const initScene = () => {
const [canvasWidth, canvasHeight] = getConstraints();
// Renderer initialisation.
renderer = new THREE.WebGLRenderer({
canvas: document.getElementById("canvas"),
antialias: true, alpha: true,
});
renderer.setSize(canvasWidth, canvasHeight);
renderer.setPixelRatio(window.devicePixelRatio);
// Scene initialisation.
scene = new THREE.Scene();
// Camera initialisation.
camera = new THREE.PerspectiveCamera(45, canvasWidth / canvasHeight, 1, 1000);
camera.position.set(100, 0, 100);
camera.lookAt(scene.position);
};
const initPoints = () => {
const geometry = new THREE.BufferGeometry();
const positions = [];
const particleSize = 0.2;
const particleColor = 0x1826e0; // Dark blue
const particleCount = 50000 / (particleSize * 10);
for(let i = 0; i < particleCount; i++){
let vertex = getRandomPointInSphere(50);
positions.push(vertex.x, vertex.y, vertex.z);
}
geometry.setAttribute("position", new THREE.Float32BufferAttribute(positions, 3));
const material = new THREE.PointsMaterial({ size: particleSize, color: particleColor });
const particles = new THREE.Points(geometry, material);
scene.add(particles);
};
initScene();
initPoints();
renderer.render(scene, camera);
</script>
我正在学习使用 THREE.js 库,方法是在我的 React 应用程序中创建一个粒子球体。参考 this 项目,我已经 有点 的开始,但有点死胡同了。
出于某种原因,尽管我的所有代码本质上都是相同的——除了一些已弃用的方法被换掉了——THREE 每次都会呈现一条奇怪的直线。
看了几个小时的文档,试图学习这个组件的各个方法,还是摸不着头脑。
我有这个(现场版可以看here):
let camera;
let renderer;
let scene;
const vector3D = new THREE.Vector3();
// Get constraints of the canvas.
const getConstraints = () => {
const canvas = document.getElementById("canvas");
const { width, height } = canvas.getBoundingClientRect();
// Get attribute-set width and height - defaulting to computed constraints.
return [canvas.width ?? width, canvas.height ?? height];
};
// Retrieve a random point in the sphere for a particle to be set at.
const getRandomPointInSphere = radius => {
const x = THREE.MathUtils.randFloat(-1, 1);
const y = THREE.MathUtils.randFloat(-1, 1);
const z = THREE.MathUtils.randFloat(-1, 1);
const normaliseRatio = 1 / Math.sqrt(x * x + y * y + z * z);
vector3D.x = x * normaliseRatio * radius;
vector3D.y = y * normaliseRatio * radius;
vector3D.z = z * normaliseRatio * radius;
return vector3D;
};
// Initialisation methods.
const initScene = () => {
const [canvasWidth, canvasHeight] = getConstraints();
// Renderer initialisation.
renderer = new THREE.WebGLRenderer({
canvas: document.getElementById("canvas"),
antialias: true, alpha: true,
});
renderer.setSize(canvasWidth, canvasHeight);
renderer.setPixelRatio(window.devicePixelRatio);
// Scene initialisation.
scene = new THREE.Scene();
// Camera initialisation.
camera = new THREE.PerspectiveCamera(45, canvasWidth, canvasHeight, 1, 1000);
camera.position.set(100, 0, 100);
};
const initPoints = () => {
const geometry = new THREE.BufferGeometry();
const positions = [];
const particleSize = 0.2;
const particleColor = 0x1826e0; // Dark blue
const particleCount = 50000 / (particleSize * 10);
for(let i = 0; i < particleCount; i++){
let vertex = getRandomPointInSphere(50);
positions.push(vertex.x, vertex.y, vertex.z);
}
geometry.setAttribute("position", new THREE.Float32BufferAttribute(positions, 3));
const material = new THREE.PointsMaterial({ size: particleSize, color: particleColor });
const particles = new THREE.Points(geometry, material);
scene.add(particles);
};
initScene();
initPoints();
renderer.render(scene, camera);
我对 THREE(以及一般的画布)还很陌生,所以非常感谢大家的帮助。
首先,相机实例化的行必须是这样的:camera = new THREE.PerspectiveCamera(45, canvasWidth / canvasHeight, 1, 1000);
,有斜线而不是逗号。
然后,相机必须看场景的中心,因此camera.lookAt(scene.position);
带有固定代码的代码段:
body{
overflow: hidden;
margin: 0;
}
canvas{
border: 1px solid red;
}
<canvas id="canvas" width="400" height="400" />
<script type="module">
import * as THREE from "https://cdn.skypack.dev/three@0.136.0";
// THREE variables
let camera;
let renderer;
let scene;
let v3 = new THREE.Vector3();
// Get constraints of the canvas.
const getConstraints = () => {
const canvas = document.getElementById("canvas");
const { width, height } = canvas.getBoundingClientRect();
// Get attribute-set width and height - defaulting to computed constraints.
return [canvas.width ?? width, canvas.height ?? height];
};
// Retrieve a random point in the sphere for a particle to be set at.
const getRandomPointInSphere = radius => {
v3.randomDirection();
const normaliseRatio = 1 / Math.hypot(v3.x, v3.y, v3.z);
v3.setLength(radius * normaliseRatio);
return v3;
};
// Initialisation methods.
const initScene = () => {
const [canvasWidth, canvasHeight] = getConstraints();
// Renderer initialisation.
renderer = new THREE.WebGLRenderer({
canvas: document.getElementById("canvas"),
antialias: true, alpha: true,
});
renderer.setSize(canvasWidth, canvasHeight);
renderer.setPixelRatio(window.devicePixelRatio);
// Scene initialisation.
scene = new THREE.Scene();
// Camera initialisation.
camera = new THREE.PerspectiveCamera(45, canvasWidth / canvasHeight, 1, 1000);
camera.position.set(100, 0, 100);
camera.lookAt(scene.position);
};
const initPoints = () => {
const geometry = new THREE.BufferGeometry();
const positions = [];
const particleSize = 0.2;
const particleColor = 0x1826e0; // Dark blue
const particleCount = 50000 / (particleSize * 10);
for(let i = 0; i < particleCount; i++){
let vertex = getRandomPointInSphere(50);
positions.push(vertex.x, vertex.y, vertex.z);
}
geometry.setAttribute("position", new THREE.Float32BufferAttribute(positions, 3));
const material = new THREE.PointsMaterial({ size: particleSize, color: particleColor });
const particles = new THREE.Points(geometry, material);
scene.add(particles);
};
initScene();
initPoints();
renderer.render(scene, camera);
</script>