Three.js - 如何更新 PlaneBufferGeometry?
Three.js - How to update a PlaneBufferGeometry?
我正在尝试为我的 Three.js 应用程序创建一个海洋。我从这个网站拿了例子:
https://codepen.io/RemiRuc/pen/gJMwOe?fbclid=IwAR2caTQL-AOPE2Gv6x4rzSWBrOmAh2j-raqesOO0XbYQAuSG37imbMszSis
var params = {
res : 32,
speed : 8,
amp : 2,
wireframe : true,
backgroundColor : 0x9c81e3,
planeColor : 0x4a4a4a
}
var scene = new THREE.Scene();
scene.background = new THREE.Color(params.backgroundColor)
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 )
let canvas = document.getElementById("webgl")
var renderer = new THREE.WebGLRenderer({canvas:canvas, antialias: true})
renderer.setSize( window.innerWidth, window.innerHeight )
var simplex = new SimplexNoise()
var light = new THREE.AmbientLight( 0xcccccc ); // soft white light
scene.add( light );
var pointLight = new THREE.PointLight( 0xeeeeee, 1, 100 );
pointLight.position.set( 0, 20, -20 );
scene.add( pointLight );
let geometry, material, plane
createPlane()
camera.position.z = 5;
camera.position.y = 3;
camera.lookAt(new THREE.Vector3( 0, 3, 0 ))
var animate = function () {
requestAnimationFrame( animate );
for (var i = 0; i < geometry.vertices.length; i++) {
var z = (i + Date.now() * params.speed/100000)
geometry.vertices[i].z = simplex.noise4D(z,z,z,z) * params.amp
plane.geometry.verticesNeedUpdate = true;
}
scene.background = new THREE.Color(params.backgroundColor)
material.color = new THREE.Color(params.planeColor)
material.wireframe = params.wireframe
camera.rotation.y += 0.001
renderer.render( scene, camera );
};
animate();
function createPlane(){
geometry = new THREE.PlaneGeometry( 200, 200, params.res,params.res );
material = new THREE.MeshLambertMaterial( {color: params.planeColor, side: THREE.DoubleSide, wireframe: params.wireframe} );
plane = new THREE.Mesh( geometry, material );
scene.add( plane );
plane.rotation.x = Math.PI/2
}
/***RESIZE***/
window.addEventListener('resize', ()=>{
document.querySelector('canvas').style.width = window.innerWidth + "px"
document.querySelector('canvas').style.height = window.innerHeight + "px"
renderer.setSize( window.innerWidth, window.innerHeight )
camera.aspect = window.innerWidth / window.innerHeight
camera.updateProjectionMatrix()
})
var gui = new dat.GUI()
var controller = gui.add(params, "res", 0, 100).name("Plane resolution")
gui.add(params, "speed", 0, 500).name("Wave speed")
gui.add(params, "amp", 0, 20).name("Wave amplitude")
gui.add(params, "wireframe", 0, 20).name("Wireframe")
gui.addColor(params, "backgroundColor").name("Background color")
gui.addColor(params, "planeColor").name("Plane color")
controller.onChange(()=>{
scene.remove(plane)
createPlane()
})
问题是,我使用的是 PlaneBufferGeometry
而不是 PlaneGeometry
,看起来有些不同
我在创建水面后 render
中的代码
for (var i = 0; i < waterGeometry.attributes.position.count; i++) {
var z = (i + Date.now() * params.speed/100000);
waterGeometry.attributes.position[i] = simplex.noise4D(z,z,z,z) * params.amp;
}
waterGeometry.attributes.position.needsUpdate = true;
waterPlaneMesh.attributes.position.needsUpdate = true;
我没有收到任何错误,但无论我做什么,我得到的只是一个平面线框平面几何图形,它不会移动或任何东西。我认为问题出在飞机的更新上?
这是一个示例,说明如何使用 SimplexNoise
库置换缓冲区几何体的顶点:
body {
margin: 0;
background-color: #000;
color: #fff;
font-family: Monospace;
font-size: 13px;
line-height: 24px;
overscroll-behavior: none;
}
<script type="module">
import * as THREE from "https://cdn.skypack.dev/three@0.136.0";
import { OrbitControls } from "https://cdn.skypack.dev/three@0.136.0/examples/jsm/controls/OrbitControls";
import SimplexNoise from "https://cdn.skypack.dev/simplex-noise";
let simplex = new SimplexNoise('seed');
let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 2000);
camera.position.set(0, 0.5, 1).setLength(12);
let renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);
window.addEventListener("resize", onWindowResize);
//scene.add(new THREE.GridHelper())
let controls = new OrbitControls(camera, renderer.domElement);
let light = new THREE.DirectionalLight(0xffffff, 0.5);
light.position.setScalar(1);
scene.add(light, new THREE.AmbientLight(0xffffff, 0.5));
let v3 = new THREE.Vector3();
let v2 = new THREE.Vector2();
let g = new THREE.PlaneGeometry(200, 200, 100, 100);
g.rotateX(-Math.PI *0.5);
let m = new THREE.MeshLambertMaterial({color: "aqua", wireframe: false});
let o = new THREE.Mesh(g, m);
scene.add(o);
let clock = new THREE.Clock();
renderer.setAnimationLoop(() => {
renderer.render(scene, camera);
let t = clock.getElapsedTime();
for(let i = 0; i < g.attributes.position.count; i++){
v2.fromBufferAttribute(g.attributes.uv, i).addScalar(t * 0.01).multiplyScalar(20);
let h = simplex.noise3D(v2.x, v2.y, t * 0.1);
g.attributes.position.setY(i, h);
}
g.computeVertexNormals();
g.attributes.position.needsUpdate = true;
});
function onWindowResize() {
camera.aspect = innerWidth / innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(innerWidth, innerHeight);
}
</script>
我正在尝试为我的 Three.js 应用程序创建一个海洋。我从这个网站拿了例子: https://codepen.io/RemiRuc/pen/gJMwOe?fbclid=IwAR2caTQL-AOPE2Gv6x4rzSWBrOmAh2j-raqesOO0XbYQAuSG37imbMszSis
var params = {
res : 32,
speed : 8,
amp : 2,
wireframe : true,
backgroundColor : 0x9c81e3,
planeColor : 0x4a4a4a
}
var scene = new THREE.Scene();
scene.background = new THREE.Color(params.backgroundColor)
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 )
let canvas = document.getElementById("webgl")
var renderer = new THREE.WebGLRenderer({canvas:canvas, antialias: true})
renderer.setSize( window.innerWidth, window.innerHeight )
var simplex = new SimplexNoise()
var light = new THREE.AmbientLight( 0xcccccc ); // soft white light
scene.add( light );
var pointLight = new THREE.PointLight( 0xeeeeee, 1, 100 );
pointLight.position.set( 0, 20, -20 );
scene.add( pointLight );
let geometry, material, plane
createPlane()
camera.position.z = 5;
camera.position.y = 3;
camera.lookAt(new THREE.Vector3( 0, 3, 0 ))
var animate = function () {
requestAnimationFrame( animate );
for (var i = 0; i < geometry.vertices.length; i++) {
var z = (i + Date.now() * params.speed/100000)
geometry.vertices[i].z = simplex.noise4D(z,z,z,z) * params.amp
plane.geometry.verticesNeedUpdate = true;
}
scene.background = new THREE.Color(params.backgroundColor)
material.color = new THREE.Color(params.planeColor)
material.wireframe = params.wireframe
camera.rotation.y += 0.001
renderer.render( scene, camera );
};
animate();
function createPlane(){
geometry = new THREE.PlaneGeometry( 200, 200, params.res,params.res );
material = new THREE.MeshLambertMaterial( {color: params.planeColor, side: THREE.DoubleSide, wireframe: params.wireframe} );
plane = new THREE.Mesh( geometry, material );
scene.add( plane );
plane.rotation.x = Math.PI/2
}
/***RESIZE***/
window.addEventListener('resize', ()=>{
document.querySelector('canvas').style.width = window.innerWidth + "px"
document.querySelector('canvas').style.height = window.innerHeight + "px"
renderer.setSize( window.innerWidth, window.innerHeight )
camera.aspect = window.innerWidth / window.innerHeight
camera.updateProjectionMatrix()
})
var gui = new dat.GUI()
var controller = gui.add(params, "res", 0, 100).name("Plane resolution")
gui.add(params, "speed", 0, 500).name("Wave speed")
gui.add(params, "amp", 0, 20).name("Wave amplitude")
gui.add(params, "wireframe", 0, 20).name("Wireframe")
gui.addColor(params, "backgroundColor").name("Background color")
gui.addColor(params, "planeColor").name("Plane color")
controller.onChange(()=>{
scene.remove(plane)
createPlane()
})
问题是,我使用的是 PlaneBufferGeometry
而不是 PlaneGeometry
,看起来有些不同
我在创建水面后 render
中的代码
for (var i = 0; i < waterGeometry.attributes.position.count; i++) {
var z = (i + Date.now() * params.speed/100000);
waterGeometry.attributes.position[i] = simplex.noise4D(z,z,z,z) * params.amp;
}
waterGeometry.attributes.position.needsUpdate = true;
waterPlaneMesh.attributes.position.needsUpdate = true;
我没有收到任何错误,但无论我做什么,我得到的只是一个平面线框平面几何图形,它不会移动或任何东西。我认为问题出在飞机的更新上?
这是一个示例,说明如何使用 SimplexNoise
库置换缓冲区几何体的顶点:
body {
margin: 0;
background-color: #000;
color: #fff;
font-family: Monospace;
font-size: 13px;
line-height: 24px;
overscroll-behavior: none;
}
<script type="module">
import * as THREE from "https://cdn.skypack.dev/three@0.136.0";
import { OrbitControls } from "https://cdn.skypack.dev/three@0.136.0/examples/jsm/controls/OrbitControls";
import SimplexNoise from "https://cdn.skypack.dev/simplex-noise";
let simplex = new SimplexNoise('seed');
let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 2000);
camera.position.set(0, 0.5, 1).setLength(12);
let renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);
window.addEventListener("resize", onWindowResize);
//scene.add(new THREE.GridHelper())
let controls = new OrbitControls(camera, renderer.domElement);
let light = new THREE.DirectionalLight(0xffffff, 0.5);
light.position.setScalar(1);
scene.add(light, new THREE.AmbientLight(0xffffff, 0.5));
let v3 = new THREE.Vector3();
let v2 = new THREE.Vector2();
let g = new THREE.PlaneGeometry(200, 200, 100, 100);
g.rotateX(-Math.PI *0.5);
let m = new THREE.MeshLambertMaterial({color: "aqua", wireframe: false});
let o = new THREE.Mesh(g, m);
scene.add(o);
let clock = new THREE.Clock();
renderer.setAnimationLoop(() => {
renderer.render(scene, camera);
let t = clock.getElapsedTime();
for(let i = 0; i < g.attributes.position.count; i++){
v2.fromBufferAttribute(g.attributes.uv, i).addScalar(t * 0.01).multiplyScalar(20);
let h = simplex.noise3D(v2.x, v2.y, t * 0.1);
g.attributes.position.setY(i, h);
}
g.computeVertexNormals();
g.attributes.position.needsUpdate = true;
});
function onWindowResize() {
camera.aspect = innerWidth / innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(innerWidth, innerHeight);
}
</script>