Spaces:
Sleeping
Sleeping
<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 | |
} | |
} | |
// init | |
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.xr.enabled = true; | |
renderer.toneMapping = THREE.ACESFilmicToneMapping; | |
renderer.toneMappingExposure = 1; | |
renderer.outputEncoding = THREE.sRGBEncoding; | |
document.body.appendChild(renderer.domElement); | |
// animation | |
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); | |
// orbit controls | |
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 | |
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 | |
}); | |
// generating geometry and add mesh to scene | |
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); | |
})() | |
// setup gui | |
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> |