1. 원리
정육면체 공간에 하나씩 이미지를 붙임으로써 하나의 공간을 만들게 된다.
https://opengameart.org/content/skiingpenguins-skybox-pack
위 사이트는 위 공간 구성이 가능하게 이미지를 무료로 풀어놓았다.
1. 텍스쳐 추가
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import { WEBGL } from './webgl'
if (WEBGL.isWebGLAvailable()) {
// 장면 추가
const scene = new THREE.Scene()
scene.background = new THREE.Color(0xeeeeee)
scene.add(new THREE.AxesHelper(5))
// 카메라 추가
const camera = new THREE.PerspectiveCamera(
50,
window.innerWidth / window.innerHeight,
1,
4000
)
camera.position.set(0, 20, 100)
camera.lookAt(0, 0, 0)
// 렌더러 추가
const renderer = new THREE.WebGLRenderer({
alpha: true,
antialias: true,
})
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)
// 카메라 이후에 등장필요
const controls = new OrbitControls(camera, renderer.domElement)
controls.enableDamping = true
controls.minDistance = 100
controls.maxDistance = 800
controls.update()
// 메쉬 추가
const skyGeometry = new THREE.BoxGeometry(24, 24, 24)
const skyMaterial = new THREE.MeshStandardMaterial({
color:0x555555
})
const sky = new THREE.Mesh(skyGeometry, skyMaterial)
scene.add(sky)
//빛
const ambientLight = new THREE.AmbientLight(0xffffff, 0.8)
scene.add(ambientLight)
function animate() {
requestAnimationFrame(animate) //인자로 받은 함수 animate를 반복 실행
renderer.render(scene, camera)
}
animate()
// 반응형 처리
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight
camera.updateProjectionMatrix()
renderer.setSize(window.innerWidth, window.innerHeight)
}
window.addEventListener('resize', onWindowResize)
} else {
var warning = WEBGL.getWebGLErrorMessage()
document.body.appendChild(warning)
}
크기가 (24, 24, 24)인 BoxGeometry가 보인다.
여기에 이미지가 들어간 텍스처를 추가해보자.
const texture = new THREE.TextureLoader().load(
'../static/ex-12/bay_rt.jpg'
)
추가한 텍스처를 Material map에 적용해보자
// 메쉬 추가
const skyGeometry = new THREE.BoxGeometry(24, 24, 24)
const skyMaterial = new THREE.MeshStandardMaterial({
// color:0x555555,
map:texture,
})
const sky = new THREE.Mesh(skyGeometry, skyMaterial)
scene.add(sky)
2. side 개념
// 카메라 이후에 등장필요
const controls = new OrbitControls(camera, renderer.domElement)
controls.enableDamping = true
controls.minDistance = 20
controls.maxDistance = 800
controls.update()
minDistance를 줄여서 더 가깝게 들어가보면 표면에는 이미지가 보이는데 안쪽으로 들어가면 텅 빈 것을 볼 수 있다.
그래서 우리는 BackSide에도 이미지를 적용할 필요가 있다.
// 메쉬 추가
const skyGeometry = new THREE.BoxGeometry(40, 40, 40)
const skyMaterial = new THREE.MeshStandardMaterial({
// color:0x555555,
map:texture,
})
skyMaterial.side = THREE.BackSide //여기
const sky = new THREE.Mesh(skyGeometry, skyMaterial)
scene.add(sky)
이처럼 BackSide에도 skyMaterial을 추가해준다는 코드를 추가하면 된다.
공간을 키워보면 안에 있는 듯한 느낌을 준다.
const skyGeometry = new THREE.BoxGeometry(400, 400, 400)
그런데 이미지가 다 똑같아서 이어지는 느낌이 안난다.
3. 6면에 이미지 다르게 적용하기
배열을 이용해 각 이미지를 push한 뒤 반복문을 돌려 셋팅해줄 것이다.
[1. 배열만들기]
// 배열
const skyMaterialArray = []
const texture_ft = new THREE.TextureLoader().load(
'../static/ex-12/bay_ft.jpg'
)
const texture_bk = new THREE.TextureLoader().load(
'../static/ex-12/bay_bk.jpg'
)
const texture_up = new THREE.TextureLoader().load(
'../static/ex-12/bay_up.jpg'
)
const texture_dn = new THREE.TextureLoader().load(
'../static/ex-12/bay_dn.jpg'
)
const texture_rt = new THREE.TextureLoader().load(
'../static/ex-12/bay_rt.jpg'
)
const texture_lf = new THREE.TextureLoader().load(
'../static/ex-12/bay_lf.jpg'
)
[2. 배열에 텍스처들 넣어주기]
skyMaterialArray.push(
new THREE.MeshBasicMaterial({
map: texture_ft,
})
)
skyMaterialArray.push(
new THREE.MeshBasicMaterial({
map: texture_bk,
})
)
skyMaterialArray.push(
new THREE.MeshBasicMaterial({
map: texture_up,
})
)
skyMaterialArray.push(
new THREE.MeshBasicMaterial({
map: texture_dn,
})
)
skyMaterialArray.push(
new THREE.MeshBasicMaterial({
map: texture_rt,
})
)
skyMaterialArray.push(
new THREE.MeshBasicMaterial({
map: texture_lf,
})
)
[3. 배열을 BackSide 적용하기]
skyMaterial.side = THREE.BackSide
기본 하나의 Material에 BackSide를 적용했었다면, 배열 Material로 바꿔줄 것이다. Material의 집합이라고 보면 된다.
// 반복문
for (let i = 0; i < 6; i++) {
skyMaterialArray[i].side = THREE.BackSide
}
이렇게 반복문을 돌려 각 Material 하나씩 BackSide를 적용한다.
[4. 배열을 Scene에 적용하기]
그리고 기존 하나의 Material을 제거하고, scene에 Material 배열을 적용하면 된다.
// 메쉬 추가
const skyGeometry = new THREE.BoxGeometry(400, 400, 400)
const sky = new THREE.Mesh(skyGeometry, skyMaterialArray)
scene.add(sky)
[5. 카메라 조정]
텍스처 이미지의 크기보다 카메라의 max 값이 커지면 안된다.
// 메쉬 추가
const skyGeometry = new THREE.BoxGeometry(2400, 2400, 2400)
const sky = new THREE.Mesh(skyGeometry, skyMaterialArray)
scene.add(sky)
박스 지오메트리가 2400의 크기를 가졌다면,
// 카메라 이후에 등장필요
const controls = new OrbitControls(camera, renderer.domElement)
controls.enableDamping = true
controls.minDistance = 20
controls.maxDistance = 800
controls.update()
maxDistance도 2400을 넘으면 안된다.
4. AxesHelper
매번 화면에 나왔던 이 표시가 바로 AxesHelper이다.
// 장면 추가
const scene = new THREE.Scene()
scene.background = new THREE.Color(0xeeeeee)
scene.add(new THREE.AxesHelper(5))
내가 어느 방향으로 움직이고 있는지 손쉽게 알게 도와준다.
'FE > Three.js' 카테고리의 다른 글
링고타운 이야기 - R3F 물리엔진 뼈대 제거 (0) | 2023.11.01 |
---|---|
Three.js 12일차 (GLTFLoader로 3D파일 불러오기) (0) | 2023.10.19 |
Three.js 10일차 (안개 효과) (0) | 2023.10.18 |
Three.js 9일차 (OrbitControls) (0) | 2023.10.18 |
Three.js 8일차 (그림자) (0) | 2023.10.18 |