[Three.js] 1. vue 로 빨간 육각면체 만들기
화면에 무언가를 그리려면 4가지 요소가 필요합니다.
1. 오브젝트를 포함한 scene
2. 오브젝트
3. 카메라
4. 랜더러
1. scene
scene은 컨테이너와 같습니다.
그 안에 오브젝트, 조명, 카메라 등을 배치할 수 있으며, Three.js에 해당 장면을 렌더링하도록 요청합니다
import {
PerspectiveCamera,
Scene,
BoxGeometry,
MeshBasicMaterial,
Mesh,
WebGLRenderer
} from 'three'
const scene = new Scene()
특징
- 컨테이너: 씬은 다양한 3D 객체들(메쉬, 조명, 카메라 등)을 포함하는 컨테이너로서의 역할을 합니다.
- 조직화: 씬 내에서 객체들은 계층적으로 조직될 수 있으며, 이는 복잡한 3D 환경을 효과적으로 관리할 수 있게 해줍니다.
- 렌더링 대상: 렌더러는 씬 객체를 입력으로 받아 화면에 그림을 그립니다. 씬에 포함된 모든 요소들이 렌더링 과정을 통해 시각화됩니다.
scene은 Object3D을 상속 받고 있으므로 .add( object ) 메서드를 사용해 객체를 그룹핑해서 오브젝트를 자식으로
추가하는 데에 사용할 수도 있지만, Group를 사용하는 것이 더 낫습니다.
https://threejs.org/docs/index.html#api/en/objects/Group
three.js docs
threejs.org
2. Object
object 는 여러 가지가 될 수 있습니다. primitive 지오메트리, import 된 모델, 파티클, 조명 등이 있을 수 있습니다.
네모 상자를 그린다고 가정했을 때,
3D 공간에서 렌더링할 수 있는 메쉬 객체를 생성하고 파라미터로
geometry(기하학적 형태), material(재질)을 설정해야 합니다
이 메쉬는 기하학적 형태와 재질을 결합하여 실제로 보이는 객체를 만듭니다.
.
const geometry = new BoxGeometry(1, 1, 1)
const material = new MeshBasicMaterial({ color: 'red' })
// Mesh 생성자는 속성 2개만 있다. ( geometry : BufferGeometry, material : Material )
const mesh = new Mesh(geometry, material)
scene.add(mesh)
- geometry: THREE.Geometry 또는 THREE.BufferGeometry의 인스턴스로, 메쉬의 형태를 정의합니다.
예를 들어, BoxGeometry, SphereGeometry 등이 있습니다. - material: THREE.Material의 인스턴스로, 메쉬의 표면 처리 방식을 정의합니다.
예를 들어, MeshBasicMaterial, MeshStandardMaterial 등이 있습니다.
이 코드는 크기가 1x1x1인 정육면체를 생성하고, 빨간색을 적용한 후, 이를 씬에 추가합니다.
생성된 메쉬는 렌더러를 통해 화면에 그려집니다.
Mesh 객체는 다양한 속성과 메서드를 가지고 있어, 위치 조정, 크기 변경, 회전 등 다양한 변형을 적용할 수 있습니다.
또한, 메쉬는 조명, 그림자, 텍스처 등의 다양한 3D 그래픽 효과와 함께 사용될 수 있습니다.
이러한 기능들을 통해 사용자는 복잡하고 다양한 3D 씬을 구성할 수 있습니다.
2-1. BoxGeometry
BoxGeometry는 Three.js에서 정육면체 형태의 기하학적 객체를 생성하는 데 사용되는 클래스입니다.
이 클래스는 각 면이 직사각형인 상자 모양의 메쉬를 생성할 수 있게 해줍니다.
사용자는 상자의 너비, 높이, 깊이 등을 지정할 수 있으며, 각 면을 구성하는 세그먼트의 수도 조절할 수 있습니다.
BoxGeometry를 사용하면 간단하게 3D 상자 모델을 생성하고, 이를 씬에 추가하여 렌더링할 수 있습니다.
이는 게임, 시뮬레이션, 시각화 등 다양한 3D 애플리케이션에서 기본적인 형태로 많이 사용됩니다
생성자 )
const geometry = new BoxGeometry(width, height, depth, widthSegments, heightSegments, depthSegments);
width: 상자의 너비(가로, x축) height: 상자의 높이(세로, y축) depth: 상자의 깊이(z축) 각각 floot 단위 입니다
widthSegments: 상자의 너비 방향 세그먼트 수입니다. 기본값은 1입니다. integer 단위 입니다
heightSegments: 상자의 높이 방향 세그먼트 수입니다. 기본값은 1입니다. integer 단위 입니다
depthSegments: 상자의 깊이 방향 세그먼트 수입니다. 기본값은 1입니다. integer 단위 입니다
세그먼트 2,2,2 라면 각 면이 2x2 격자로 나뉘어 총 4개의 사각형으로 구성된 정육면체를 생성합니다.
각 방향으로 세그먼트 수를 늘리면, 정육면체의 각 면은 더 많은 사각형으로 나뉘어 더 세밀하게 표현됩니다.
2-2. MeshBasicMaterial
MeshBasicMaterial은 Three.js에서 가장 기본적인 재질(material) 유형 중 하나로,
빛의 영향을 받지 않는 단순한 색상이나 텍스처를 물체에 적용할 때 사용됩니다.
이 재질은 조명이 없는 환경에서도 물체의 색상을 그대로 표현할 수 있고, 빠른 렌더링이 요구되는 상황에서 유용하게 사용됩니다. 예를 들어, 배경 요소, 디버깅 목적의 객체, 또는 빛의 영향을 받지 않는 UI 요소 등에 적합합니다.
- 특징
- 조명 무시: MeshBasicMaterial은 빛을 전혀 반영하지 않으므로, 조명 설정에 관계없이 동일한 색상을 유지합니다.
- 색상과 텍스처: color 속성을 통해 색상을 지정할 수 있으며, map 속성을 사용하여 텍스처를 적용할 수 있습니다.
- 투명도 지원: transparent와 opacity 속성을 조합하여 재질의 투명도를 조절할 수 있습니다.
3. camera
const sizes = {
width: 800,
height: 600
}
/* Camera */
// PerspectiveCamera : 투영카메라
// 투영 모드는 사람의 눈으로 보는 방식을 모방하여 설계됨
const camera = new PerspectiveCamera(60, sizes.width / sizes.height)
/* camera.position.z 값을 주지 않으면 카메라는 객체의 안에 있게 되어 object 가 안보이게 된다 */
/* 꼭 값을 줄 것*/
camera.position.z = 3
scene.add(camera)
3-1 . PerspectiveCamera
PerspectiveCamera는 Three.js에서 원근 투영 카메라를 나타내는 클래스입니다.
이 카메라는 사람의 눈이 보는 것과 유사한 방식으로 3D 장면을 렌더링합니다.
원근 투영은 멀리 있는 객체가 가까이 있는 객체보다 작게 보이는 효과를 만들어 냅니다.
생성자
const camera = new PerspectiveCamera(fov, aspect, near, far);
파라미터
- fov: Field of View(시야각)으로, 카메라가 수직 방향으로 볼 수 있는 범위를 도(degree) 단위로 나타냅니다.
일반적으로 50에서 75도 사이의 값이 사용됩니다. - aspect: 종횡비(aspect ratio)로, 렌더링되는 화면의 너비를 높이로 나눈 값입니다.
대부분의 경우 화면의 너비를 높이로 나눈 값이 사용됩니다. - near: 근접 클리핑 평면(near clipping plane)으로, 이 평면 앞의 객체들은 화면에 보이지 않습니다.
일반적으로 매우 작은 값(예: 0.1)이 사용됩니다. - far: 원거리 클리핑 평면(far clipping plane)으로, 이 평면 뒤의 객체들은 화면에 보이지 않습니다.
시야에서 멀리 떨어진 객체를 제한하기 위해 사용되며, 값은 장면의 크기에 따라 달라질 수 있습니다.
4. renderer
4-1. WebGLRenderer
3D 그래픽을 렌더링하는 데 사용되는 클래스입니다.
이 렌더러는 GPU를 활용하여 고성능의 3D 시각화를 가능하게 합니다.
웹 기반의 3D 애플리케이션에서 널리 사용되며, 다양한 설정 옵션을 제공하여 렌더링 과정을 세밀하게 제어할 수 있습니다.
생성자
const renderer = new WebGLRenderer(options);
// options: 렌더러를 구성하는 다양한 옵션을 설정할 수 있는 객체입니다.
// 주요 옵션으로는 canvas, antialias, alpha, precision 등이 있습니다.
주요옵션들
- canvas: 렌더링할 HTML canvas 요소를 지정합니다. 지정하지 않으면 자동으로 새 canvas가 생성됩니다.
- antialias: 안티앨리어싱(계단 현상 감소)을 활성화할지 여부를 지정합니다. 기본값은 false입니다.
- alpha: 캔버스에 알파(투명도) 버퍼를 사용할지 여부를 지정합니다. 기본값은 false입니다.
- precision: 셰이더의 정밀도를 설정합니다. highp, mediump, lowp 중 선택할 수 있습니다.
WebGLRenderer는 씬(scene)과 카메라(camera)를 입력으로 받아 화면에 3D 그래픽을 렌더링합니다
const renderer = new WebGLRenderer({
canvas: canvasRef.value
})
renderer.setSize(sizes.width, sizes.height)
// .render ( scene : Object3D, camera : Camera )
renderer.render(scene, camera)
정리하자면
- scene.add(new Mesh(geometry, material))
- scene.add(camera)
- renderer.setSize(sizes.width, sizes.height)
- renderer.render(scene, camera)
<script setup>
import { ref, onMounted } from 'vue'
import {
PerspectiveCamera,
Scene,
BoxGeometry,
MeshBasicMaterial,
Mesh,
WebGLRenderer
} from 'three'
const canvasRef = ref(null)
const initScene = () => {
const scene = new Scene()
return scene
}
const initCamera = (sizes) => {
const camera = new PerspectiveCamera(80, sizes.width / sizes.height)
camera.position.set(1, 1, 3)
return camera
}
const initRenderer = (canvas) => {
const renderer = new WebGLRenderer({ canvas })
return renderer
}
const createBox = () => {
const geometry = new BoxGeometry(1, 1, 1)
const material = new MeshBasicMaterial({ color: 'red' })
const mesh = new Mesh(geometry, material)
return mesh
}
const setThree = () => {
const sizes = { width: 800, height: 600 }
const scene = initScene()
const camera = initCamera(sizes)
const renderer = initRenderer(canvasRef.value)
renderer.setSize(sizes.width, sizes.height)
const box = createBox()
scene.add(box)
scene.add(camera)
renderer.render(scene, camera)
}
onMounted(() => {
setThree()
})
</script>
<template>
<canvas ref="canvasRef"></canvas>
</template>
<style scoped>
canvas {
display: block;
width: 100%;
height: 100%;
}
</style>
위 코드 작성시 아래와 같은 사진이 나오면 된다