Color (albedo) : 가장 단순한 텍스쳐로 텍스쳐의 픽셀만 geometry에 반영한다
Alpha : grayscale 이미지, 흰 부분은 보이고 검은 부분은 보이지 않음
Height : 이미지 릴리프를 만들기 위해 vertices를 이동시키는 grayscale 이미지, 조회 하려면 subdivision 추가 필요
Normal : 퍼포먼스 이슈가 없으면서 디테일을 추가하고자 할 때 유용 👉 geometry를 subdivide 할 필요가 없으므로
Ambient occlusion : 표면의 틈에 가짜 쉐도우를 생성하는 grayscale 이미지, 완전히 정확하지는 않으나 contrast를 발생시키기 좋음
Metalness : 어느 부분이 metalic(흰 부분)인 지 non-metalic(검은 부분)인 지 특정시키는 grayscale 이미지 👉 반사 만들 때 유용
Roughness : metalness처럼 어느 부분이 rough(흰 부분)인 지 smooth(검은 부분)인 지 가려내는 grayscale 이미지
e.g.) 카펫은 표면이 거치므로 빛 반사가 거의 없지만 물의 표면은 부드럽기 때문에 빛 반사가 이루어짐
텍스쳐(특히 metalness와 roughness)들은 PBR principles를 따른다
다른 많은 기술들이 있지만 PBR이 realistic render의 표준이 되어가고 있으며 많은 소프트웨어, 엔진 그리고 라이브러리가 사용하고 있다
웹팩을 사용할 경우 두 가지 방식이 존재한다
/src/
폴더에 이미지 텍스쳐를 넣고 JS 디펜던시 처럼 임포트 하는 방법import imageSource from './image.png'
console.log(imageSource)
/static/
폴더에 이미지를 넣고 이미지 경로를 추가하기const imageSource = '/image.png'
console.log(imageSource)
⚠️ 2번째 방법 사용 시 다른 타입의 번들러 사용하려면 추가 설정이 필요하다
Image
인스턴스를 생성하고 load
이벤트를 걸어준다
const image = new Image()
image.addEventListener('load', () =>
{
const texture = new THREE.Texture(image)
})
image.src = '/textures/door/color.jpg'
texture
를 material
에서 사용해야하는데 texture
변수는 함수 내에서 선언되었으므로 함수 바깥에서 접근할 수 없다 (JS scope)
함수 내에 mesh를 만드는 방법도 있겠으나
const image = new Image()
const texture = new THREE.Texture(image)
image.addEventListener('load', () =>
{
texture.needsUpdate = true
})
image.src = '/textures/door/color.jpg'
위 방법을 사용하면 texture
변수를 즉시 사용할 수 있고 이미지는 로딩이 끝날 때 까지 투명할 것이다
큐브에 텍스쳐가 적용된 모습을 보려면 color
프로퍼티를 map
으로 교체하고 texture
를 value로 설정해주면 된다
const material = new THREE.MeshBasicMaterial({ map: texture })
네이티브 JS를 사용하는 방법도 나쁘지 않지만 TextureLoader라는 더욱 직관적인 방법이 있다
const textureLoader = new THREE.TextureLoader()
const texture = textureLoader.load('/textures/door/color.jpg')
TextureLoader 클래스를 사용해서 변수를 초기화하고 .load(...)
메소드로 텍스쳐를 생성한다
오직 단 하나의 TextureLoader 인스턴스만으로 원하는 만큼의 텍스쳐를 로드할 수 있다
const textureLoader = new THREE.TextureLoader()
const texture = textureLoader.load(
'/textures/door/color.jpg',
() =>
{
console.log('loading finished')
},
() =>
{
console.log('loading progressing')
},
() =>
{
console.log('loading error')
}
)
load
: 이미지가 성공적으로 로드되었을 때progress
: 로딩이 진행 중일 때 error
: 에러만약 텍스쳐가 말을 듣지 않는다면 해당 콜백 함수를 이용하면 무슨 일이 일어나는 지 알 수 있을 것이다
여러 이미지들을 로드해야하고 모든 이미지들이 로드 되었을 때 이벤트를 발생시키고자 한다면 LoadingManager를 사용하면 좋다
const loadingManager = new THREE.LoadingManager()
const textureLoader = new THREE.TextureLoader(loadingManager)
LoadingManager 인스턴스를 생성하고 TextureLoader에게 패스해준다
const loadingManager = new THREE.LoadingManager()
loadingManager.onStart = () =>
{
console.log('loading started')
}
loadingManager.onLoad = () =>
{
console.log('loading finished')
}
loadingManager.onProgress = () =>
{
console.log('loading progressing')
}
loadingManager.onError = () =>
{
console.log('loading error')
}
const textureLoader = new THREE.TextureLoader(loadingManager)
onStart
, onLoad
, onProgress
, onError
등을 사용해서 변수 이벤트를 추적할 수 있다
const colorTexture = textureLoader.load('/textures/door/color.jpg')
const alphaTexture = textureLoader.load('/textures/door/alpha.jpg')
const heightTexture = textureLoader.load('/textures/door/height.jpg')
textureLoader.load('/textures/door/roughness.jpg')
// ...
const material = new THREE.MeshBasicMaterial({ map: colorTexture })
이제 필요한 이미지들을 로드할 수 있다
고로 LoadingManager는 로더를 보여주고 모든 asset들이 로드 되었을 시 로더를 숨겨줄 때 유용하다
평면도를 떠올리면 쉽다
console.log(geometry.attributes.uv)
geometry.attributs.uv
프로퍼티를 사용해서 조회해볼 수 있다