ErgiS
ErgiS

Reputation: 223

convert png into height in three.js plane

I am visualizing this image in three.js https://i.sstatic.net/EzfcS.png using a plane geometry, and I want to add height to the plane corresponding to this image https://i.sstatic.net/hMj91.png (the white area is of greater height)

How can I achieve this?

This is my current simple three.js code:

<!DOCTYPE html>
<html lang="en">

<head>
    <title>Vis</title>
    <style>
      body {
        margin: 0;
        height: 100vh;
      }
      canvas {
        display: block;
      }
     </style>
</head>

<body>
    <script src="lib/three.js"></script>
    <script src="lib/OrbitControls.js"></script>
    <script>
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = 10;
var renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var geometry = new THREE.PlaneGeometry(15, 12);
var loader = new THREE.TextureLoader();
var material = new THREE.MeshLambertMaterial({
    map: loader.load('https://i.imgur.com/hHZICLa.jpg', render),
    side: THREE.DoubleSide
});
var mesh = new THREE.Mesh(geometry, material);
mesh.position.set(0, 0, 0);
scene.add(mesh);
var light = new THREE.DirectionalLight(0xffffff);
light.position.set(1, 1, 1);
scene.add(light);
var controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.addEventListener('change', render); // call this only in static scenes (i.e., if there is no animation loop)
controls.minDistance = 5;
controls.maxDistance = 50;
controls.minPolarAngle = 0.05;
controls.maxPolarAngle = Math.PI / 1.01;
controls.minAzimuthAngle = -Math.PI / 2.02;
controls.maxAzimuthAngle = Math.PI / 2.02;

function render() {
    renderer.render(scene, camera);
}
</script>

I figured I should add segments to geometry but the current image and the height map are of 1500 x 1200 dimensions, and creating a plane with new THREE.PlaneGeometry(15, 12, 1500, 1200); demands a lot of memory and crashes the browser.

I thought I should read the height map as pixels and apply their value in a loop like this

for (var i = 0; i <  i < mesh.geometry.vertices.length; i++) {
    mesh.geometry.vertices[i].z = pixelvalue;
} 

but I don't know how to load the pixel value as height and how to make it correspond to the exact same pixel, or vertex in this case, of the image.

Thank you for reading

Upvotes: 0

Views: 447

Answers (1)

Mugen87
Mugen87

Reputation: 31076

You can perform this type of vertex displacement in the vertex shader with a displacementMap. You only have to switch to MeshPhongMaterial in order to use this kind of texture.

The material properties displacementScale and displacementBias allow you to adjust the effect based on your requirements.

Upvotes: 2

Related Questions