I am trying to create a terrain in the shape of a cube that will allow the vertices to move along the y axis of those on the upper plane. All vertices adjacent to the vertices of the upper plane must be connected.
As a result, user input from the desktop or mobile device will move them up or down.
From what I read, it’s better to turn off expensive GPU operations. I thought that achieving vertex offsets in ShaderMaterialwith moving attributeseemed perfect, until I read the following:
As with THREE r72, direct attribute assignment in ShaderMaterial is no longer supported. Instead, use an instance of BufferGeometry (instead of an instance of Geometry).
So it seems that use attributefor mine is Geometryout of the question?
My attempt to shift the vertices along the upper plane with the help BufferGeometryof ShaderMaterialleads to the following:

The vertices of the upper plane are BufferGeometrynot connected with other planes, unlike those associated with Geometrywhich are connected using the method mergeVertices. As far as I know, this method is not available for objects BufferGeometry?
Basically, what started with my fear, uncertainty, and doubt about Geometryit was the message I read mrdoob.
Summary
I Geometry, ShaderMaterial attributes, -, BufferGeometry, , , Geometry .
, :
let winX = window.innerWidth;
let winY = window.innerHeight;
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(50, winX / winY, 0.1, 100);
camera.position.set(2, 1, 2);
camera.lookAt(scene.position);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(winX, winY);
document.body.appendChild(renderer.domElement);
const terrainGeo = new THREE.BoxBufferGeometry(1, 1, 1);
const terrainMat = new THREE.ShaderMaterial({
vertexShader: `
attribute float displacement;
varying vec3 dPosition;
void main() {
dPosition = position;
dPosition.y += displacement;
gl_Position = projectionMatrix * modelViewMatrix * vec4(dPosition, 1.0);
}
`,
fragmentShader: `
void main() {
gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);
}
`
});
const terrainObj = new THREE.Mesh(terrainGeo, terrainMat);
let displacement = new Float32Array(terrainObj.geometry.attributes.position.count);
displacement.forEach((elem, index) => {
if (index >= 8 && index <= 11) {
displacement[index] = Math.random() * 0.1 + 0.25;
}
});
terrainObj.geometry.addAttribute('displacement',
new THREE.BufferAttribute(displacement, 1)
);
scene.add(camera);
scene.add(terrainObj);
const render = () => {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
render();
const gui = new dat.GUI();
const updateBufferAttribute = () => {
terrainObj.geometry.attributes.displacement.needsUpdate = true;
};
gui.add(displacement, 8).min(0).max(2).step(0.05).onChange(updateBufferAttribute);
gui.add(displacement, 9).min(0).max(2).step(0.05).onChange(updateBufferAttribute);
gui.add(displacement, 10).min(0).max(2).step(0.05).onChange(updateBufferAttribute);
gui.add(displacement, 11).min(0).max(2).step(0.05).onChange(updateBufferAttribute);
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.5.1/dat.gui.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r76/three.min.js"></script>
<style type="text/css">body { margin: 0 } canvas { display: block }</style>
Hide result