Nuxt/docs/components/atoms/Gem.vue

134 lines
3.3 KiB
Vue

<template>
<canvas class="webgl" :style="{ opacity: ready ? 1 : 0 }" />
</template>
<script>
export default {
data () {
return {
ready: false
}
},
async mounted () {
const THREE = await import('three').then(m => m.default || m)
const { OrbitControls } = await import('three/examples/jsm/controls/OrbitControls.js' /* webpackChunkName: "gem" */).then(m => m.default || m)
const { GLTFLoader } = await import('three/examples/jsm/loaders/GLTFLoader.js' /* webpackChunkName: "gem" */).then(m => m.default || m)
// Canvas
const canvas = document.querySelector('canvas.webgl')
// Scene
const scene = new THREE.Scene()
// Models
let gem
let light
const gltfLoader = new GLTFLoader()
gltfLoader.load(
'/3D/gem.gltf',
(gltf) => {
// Gem
gem = gltf.scene.children[6]
// Material setup
const textureLoader = new THREE.TextureLoader()
const roughnessTexture = textureLoader.load('/3D/roughness.jpeg')
gem.material.roughnessMap = roughnessTexture
gem.material.displacementScale = 0.15
gem.material.emissiveIntensity = 0.4
gem.material.refractionRatio = 1
gem.rotation.z = 0
scene.add(gem)
light = gltf.scene.children[0]
scene.add(light)
this.ready = true
}
)
// Lights
const ambientLight = new THREE.AmbientLight(0xFFFFFF, 2)
scene.add(ambientLight)
const directionalLight = new THREE.DirectionalLight(0xFFFFFF, 3)
directionalLight.position.set(1, 1, 1)
scene.add(directionalLight)
const directionalLight2 = new THREE.DirectionalLight(0xFFFFFF, 3)
directionalLight2.position.set(-1, -1, -1)
scene.add(directionalLight2)
// Settings
const sizes = {
width: 200,
height: 200
}
// Base camera
const camera = new THREE.PerspectiveCamera(
75,
sizes.width / sizes.height,
0.1,
100
)
camera.position.set(2, 2, 6)
scene.add(camera)
// Controls
const controls = new OrbitControls(camera, canvas)
controls.enableZoom = false
controls.target.set(0, 0.75, 0)
controls.enableDamping = true
// Lock Y Axis
controls.minPolarAngle = Math.PI / 2
controls.maxPolarAngle = Math.PI / 2
// Render
const renderer = new THREE.WebGLRenderer({
antialiasing: true,
canvas,
alpha: true
})
renderer.setClearColor(0x000000, 0)
renderer.shadowMap.enabled = true
renderer.shadowMap.type = THREE.PCFSoftShadowMap
renderer.setSize(sizes.width, sizes.height)
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
// Animations
const clock = new THREE.Clock()
let previousTime = 0
const tick = () => {
const elapsedTime = clock.getElapsedTime()
const deltaTime = elapsedTime - previousTime
previousTime = elapsedTime
if (gem) {
gem.rotation.y = 1.1 * elapsedTime
}
// Update controls
controls.update()
// Render
renderer.render(scene, camera)
// Call tick again on the next frame
window.requestAnimationFrame(tick)
}
tick()
}
}
</script>
<style scoped>
.webgl {
outline: none;
width: 200px;
height: 200px;
opacity: 0;
transition: opacity 1s ease;
}
</style>