Textures

100pearlcent·2021년 10월 23일
0

Three.js

목록 보기
8/8
post-thumbnail

Textures

  • 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.) 카펫은 표면이 거치므로 빛 반사가 거의 없지만 물의 표면은 부드럽기 때문에 빛 반사가 이루어짐



PBR (Physically Based Rendering)

텍스쳐(특히 metalness와 roughness)들은 PBR principles를 따른다
다른 많은 기술들이 있지만 PBR이 realistic render의 표준이 되어가고 있으며 많은 소프트웨어, 엔진 그리고 라이브러리가 사용하고 있다

참고 글 1
참고 글 2



텍스쳐 로드하기

이미지 URL 가져오기

웹팩을 사용할 경우 두 가지 방식이 존재한다

  1. /src/ 폴더에 이미지 텍스쳐를 넣고 JS 디펜던시 처럼 임포트 하는 방법
import imageSource from './image.png'

console.log(imageSource)

  1. /static/ 폴더에 이미지를 넣고 이미지 경로를 추가하기
const imageSource = '/image.png'

console.log(imageSource)

⚠️ 2번째 방법 사용 시 다른 타입의 번들러 사용하려면 추가 설정이 필요하다


이미지 로드하기

- 네이티브 JS 활용

Image 인스턴스를 생성하고 load 이벤트를 걸어준다

const image = new Image()
image.addEventListener('load', () =>
{
    const texture = new THREE.Texture(image)
})
image.src = '/textures/door/color.jpg'

texturematerial에서 사용해야하는데 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 })



- TextureLoader 활용

네이티브 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 활용

여러 이미지들을 로드해야하고 모든 이미지들이 로드 되었을 때 이벤트를 발생시키고자 한다면 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들이 로드 되었을 시 로더를 숨겨줄 때 유용하다




UV Unwrapping

평면도를 떠올리면 쉽다

console.log(geometry.attributes.uv)

geometry.attributs.uv 프로퍼티를 사용해서 조회해볼 수 있다




텍스쳐 관련 사이트


0개의 댓글