|
<!doctype html>
|
|
<html lang="en">
|
|
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<title>depthmap-viewer-three</title>
|
|
<style>
|
|
body {
|
|
font-family: sans-serif;
|
|
margin: 0;
|
|
}
|
|
|
|
.dropzone {
|
|
box-sizing: border-box;
|
|
display: none;
|
|
position: fixed;
|
|
width: 100%;
|
|
height: 100%;
|
|
left: 0;
|
|
top: 0;
|
|
z-index: 99999;
|
|
background: rgba(#60a7dc, .8);
|
|
border: 11px dashed #60a7dc;
|
|
}
|
|
</style>
|
|
<script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script>
|
|
<script type="importmap">
|
|
{
|
|
"imports": {
|
|
"three": "https://unpkg.com/three@0.154.0/build/three.module.js",
|
|
"three/addons/": "https://unpkg.com/three@0.154.0/examples/jsm/"
|
|
}
|
|
}
|
|
</script>
|
|
<script type="module">
|
|
import * as THREE from 'three';
|
|
import { OrbitControls } from "three/addons/controls/OrbitControls";
|
|
import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
|
|
|
|
var rgbBase64Img = window.frameElement?.getAttribute('data-rgb') || "public/images/rgb.png"
|
|
var depthBase64Img = window.frameElement?.getAttribute('data-depth') || "public/images/depth.png"
|
|
|
|
|
|
|
|
let mesh;
|
|
let material;
|
|
let stopAnimation = false;
|
|
|
|
const settings = {
|
|
metalness: 0.0,
|
|
roughness: 0.5,
|
|
ambientIntensity: 0.85,
|
|
displacementScale: 100,
|
|
displacementBias: -0.5,
|
|
};
|
|
const meshSettings = {
|
|
rotation: {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
}
|
|
}
|
|
|
|
|
|
const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
|
|
camera.position.z = 3;
|
|
|
|
const scene = new THREE.Scene();
|
|
|
|
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
|
|
scene.add(ambientLight);
|
|
|
|
const pointLight = new THREE.PointLight(0xff0000, 0.5);
|
|
pointLight.position.z = 2500;
|
|
scene.add(pointLight);
|
|
|
|
|
|
const renderer = new THREE.WebGLRenderer({ antialias: true });
|
|
renderer.setSize(window.innerWidth, window.innerHeight);
|
|
renderer.setAnimationLoop(animation);
|
|
|
|
renderer.toneMapping = THREE.ACESFilmicToneMapping;
|
|
renderer.toneMappingExposure = 1;
|
|
renderer.outputEncoding = THREE.sRGBEncoding;
|
|
document.body.appendChild(renderer.domElement);
|
|
|
|
|
|
function animation(time) {
|
|
if (mesh && !stopAnimation) {
|
|
mesh.rotation.x = 0.5 * Math.sin(time / 2000);
|
|
mesh.rotation.y = 0.5 * Math.sin(time / 2000);
|
|
meshSettings.rotation.x = mesh.rotation.x;
|
|
meshSettings.rotation.y = mesh.rotation.y;
|
|
}
|
|
renderer.render(scene, camera);
|
|
|
|
}
|
|
|
|
function onWindowResize() {
|
|
|
|
const aspect = window.innerWidth / window.innerHeight;
|
|
camera.aspect = aspect;
|
|
camera.updateProjectionMatrix();
|
|
|
|
renderer.setSize(window.innerWidth, window.innerHeight);
|
|
|
|
}
|
|
window.addEventListener('resize', onWindowResize);
|
|
|
|
|
|
|
|
const controls = new OrbitControls(camera, renderer.domElement);
|
|
controls.enableZoom = true;
|
|
controls.enableDamping = true;
|
|
|
|
async function getCanvasTexture(imageSrc) {
|
|
return new Promise((resolve, reject) => {
|
|
const image = new Image();
|
|
image.src = imageSrc;
|
|
image.onload = () => {
|
|
const ctx = document.createElement('canvas').getContext('2d');
|
|
ctx.canvas.width = image.width;
|
|
ctx.canvas.height = image.height;
|
|
ctx.drawImage(image, 0, 0, image.width, image.height);
|
|
const texture = new THREE.CanvasTexture(ctx.canvas);
|
|
resolve(texture);
|
|
}
|
|
})
|
|
|
|
}
|
|
(async () => {
|
|
const rgbTexture = await getCanvasTexture(rgbBase64Img);
|
|
const depthTexture = await getCanvasTexture(depthBase64Img);
|
|
|
|
if (mesh) {
|
|
mesh.geometry.dispose();
|
|
mesh.material.dispose();
|
|
scene.remove(mesh);
|
|
}
|
|
|
|
material = new THREE.MeshStandardMaterial({
|
|
|
|
color: 0xaaaaaa,
|
|
roughness: settings.roughness,
|
|
metalness: settings.metalness,
|
|
|
|
map: rgbTexture,
|
|
|
|
displacementMap: depthTexture,
|
|
displacementScale: settings.displacementScale,
|
|
displacementBias: settings.displacementBias,
|
|
|
|
side: THREE.DoubleSide
|
|
|
|
});
|
|
|
|
const geometry = new THREE.PlaneGeometry(rgbTexture.image.width, rgbTexture.image.height, 512, 512);
|
|
mesh = new THREE.Mesh(geometry, material);
|
|
const scale = 1 / Math.max(rgbTexture.image.width, rgbTexture.image.height);
|
|
mesh.scale.set(scale, scale, scale);
|
|
scene.add(mesh);
|
|
|
|
})()
|
|
|
|
|
|
|
|
|
|
const gui = new GUI();
|
|
gui.close();
|
|
const sceneGUI = gui.addFolder('Scene');
|
|
sceneGUI.add(settings, 'metalness').min(0).max(1).onChange(function (value) {
|
|
material.metalness = value;
|
|
});
|
|
sceneGUI.add(settings, 'roughness').min(0).max(1).onChange(function (value) {
|
|
material.roughness = value;
|
|
});
|
|
sceneGUI.add(settings, 'ambientIntensity').min(0).max(1).onChange(function (value) {
|
|
ambientLight.intensity = value;
|
|
});
|
|
sceneGUI.add(settings, 'displacementScale').min(0).max(500.0).onChange(function (value) {
|
|
material.displacementScale = value;
|
|
});
|
|
sceneGUI.add(settings, 'displacementBias').min(-500).max(500).onChange(function (value) {
|
|
material.displacementBias = value;
|
|
});
|
|
const meshGUI = gui.addFolder('Mesh');
|
|
meshGUI.add(meshSettings.rotation, 'x').min(-Math.PI).max(Math.PI).step(0.0001).onChange(function (value) {
|
|
mesh.rotation.x = value;
|
|
stopAnimation = true;
|
|
}).listen()
|
|
|
|
|
|
meshGUI.add(meshSettings.rotation, 'y').min(-Math.PI).max(Math.PI).step(0.0001).onChange(function (value) {
|
|
mesh.rotation.y = value;
|
|
stopAnimation = true;
|
|
}).listen()
|
|
|
|
|
|
meshGUI.add(meshSettings.rotation, 'z').min(-Math.PI).max(Math.PI).step(0.0001).onChange(function (value) {
|
|
mesh.rotation.z = value;
|
|
stopAnimation = true;
|
|
}).listen()
|
|
|
|
|
|
</script>
|
|
</head>
|
|
|
|
<body>
|
|
</body>
|
|
|
|
</html> |