이번에는 주사위의 흰색 배경을 없애고 투명하게 처리해 보겠습니다.
주사위 이미지를 만든 PPT에서 주사위 틀의 도형 채우기를 "채우기 없음"으로 변경합니다.
그리고 각각을 PNG 파일로 저장합니다. (기존 파일명에 't'를 추가했습니다.)
프로젝트의 resources \ textures 폴더에 주사위 이미지 파일을 추가합니다.
추가된 주사위 이미지에 배경이 없는 것을 확인할 수 있습니다. (체크무늬가 투명처리되는 부분입니다.)
Material(머티리얼) 배열에서 기존 이미지를 추가된 주사위 이미지로 변경하고 주사위 이미지의 체크무늬 부분이 투명하게 처리되도록 transparent 속성을 true로 추가합니다. (기본적으로 transparent 속성은 false입니다.)
// 머티리얼 배열
const box2Materials = [
new THREE.MeshStandardMaterial({map: box2TextureLoader.load("resources/textures/dice5t.png"), transparent: true}),
new THREE.MeshStandardMaterial({map: box2TextureLoader.load("resources/textures/dice2t.png"), transparent: true}),
new THREE.MeshStandardMaterial({map: box2TextureLoader.load("resources/textures/dice1t.png"), transparent: true}),
new THREE.MeshStandardMaterial({map: box2TextureLoader.load("resources/textures/dice6t.png"), transparent: true}),
new THREE.MeshStandardMaterial({map: box2TextureLoader.load("resources/textures/dice3t.png"), transparent: true}),
new THREE.MeshStandardMaterial({map: box2TextureLoader.load("resources/textures/dice4t.png"), transparent: true})
];
그러면 주사위가 투명하게 처리되어 바닥과 그림자가 보이게 됩니다.
마우스로 이동해서 보면 주사위 뒤에 있는 객체가 보이는 것을 확인할 수 있습니다.
그렇지만, 2가지가 투명하게 처리되지 않았습니다.
첫 번째, 주사위의 그림자가 투명하지 않게 나옵니다.
두 번째, 주사위안이 투명하지 않게 나옵니다. (위를 보면 3번 주사위 왼쪽에 있는 2번, 바닥에 있는 6번, 뒤에 있는 4번 이미지가 보이지 않습니다.)
그럼, 첫 번째 문제인 그림자가 투명한 주사위 이미지에 맞게 투과되어 나오게 하려면 어떻게 해야 할까요?
그림자를 처리하는 방법이 여러 가지 있지만 여기서는 텍스처를 사용하는 Material(머티리얼)에서 처리할 수 있는 방법에 대해 알아보겠습니다.
1. 투명하지 않는 텍스처와 alphaMap(알파 맵), alphaTest(알파 테스트)를 사용하는 방법
2. 투명한 텍스처와 alphaTest(알파 테스트)를 사용하는 방법
주사위 이미지가 투명하기 때문에 우리는 2번째 방법으로 alphaTest(알파 테스트) 속성을 추가하면 간단하게 처리할 수 있습니다.
간단하게 alphaTest(알파 테스트) 속성에 대해 알아보고 진행하겠습니다.
Material(머티리얼)의 alphaTest 속성은 알파 테스트를 실행할 때 사용할 알파 값으로 0.0부터 1.0까지 값을 가질 수 있습니다. (주의할 점은 Material(머티리얼)의 opacity 속성을 사용하고 있다면 opacity 값이 alphaTest 값 보다 작으면 렌더링이 되지 않습니다.)
alphaTest(알파 테스트)는 이미지 조각(픽셀)의 알파 값을 비교하여 조각(픽셀)을 삭제처리 합니다.
alphaTest(알파 테스트)를 위해 주사위 이미지 보다 복잡한 나무 이미지를 사용하여 alphaTest 값에 따라 어떻게 이미지가 삭제 처리되는지 확인해 보겠습니다.
alphaTest(알파 테스트)할 나무 이미지(배경이 투명)입니다.
Material(머티리얼)의 alphaTest 값을 각각 0.1, 0.5, 0.9로 설정하였습니다.
new THREE.MeshStandardMaterial({map: textureLoader.load("resources/textures/tree1.png"), alphaTest: 0.1, transparent: true});
new THREE.MeshStandardMaterial({map: textureLoader.load("resources/textures/tree1.png"), alphaTest: 0.5, transparent: true});
new THREE.MeshStandardMaterial({map: textureLoader.load("resources/textures/tree1.png"), alphaTest: 0.9, transparent: true});
위의 결과처럼 alphaTest 값이 높을수록 더 많은 부분이 삭제가 되는 것을 확인할 수 있습니다.
그리고 계단 현상인 Aliasing(앨리어싱)이 발생되어 이미지가 각지게 됩니다.
그래서 이미지에 맞게 alphaTest 값을 설정해야 합니다. 일반적으로 0.1에서 0.5 이하로 설정합니다.
각각의 Material(머티리얼)에 alphaTest 속성을 0.1로 추가합니다.
// 머티리얼 배열
const box2Materials = [
new THREE.MeshStandardMaterial({map: box2TextureLoader.load("resources/textures/dice5t.png"), alphaTest: 0.1, transparent: true}),
new THREE.MeshStandardMaterial({map: box2TextureLoader.load("resources/textures/dice2t.png"), alphaTest: 0.1, transparent: true}),
new THREE.MeshStandardMaterial({map: box2TextureLoader.load("resources/textures/dice1t.png"), alphaTest: 0.1, transparent: true}),
new THREE.MeshStandardMaterial({map: box2TextureLoader.load("resources/textures/dice6t.png"), alphaTest: 0.1, transparent: true}),
new THREE.MeshStandardMaterial({map: box2TextureLoader.load("resources/textures/dice3t.png"), alphaTest: 0.1, transparent: true}),
new THREE.MeshStandardMaterial({map: box2TextureLoader.load("resources/textures/dice4t.png"), alphaTest: 0.1, transparent: true})
];
그럼 주사위 이미지가 투과되어 보이게 됩니다.
그러나 자세히 보면 투과된 그림자의 주사위 이미지는 오른쪽에 있는 5번, 바닥에 있는 6번, 뒤에 있는 4번 이미지입니다.
주사위의 1번, 2번, 3번은 왜 투과되어 나오지 않는 걸까요?
이 문제는 위의 두 번째 문제인 주사위안이 투명하지 않게 나오는 현상과 같은 문제입니다.
이유는 렌더링 되는 면에 영향을 받기 때문입니다.
기본적으로 Material(머티리얼)에서는 텍스처를 렌더링 할 때 앞면(THREE.FrontSide)만 처리합니다.
그래서 우리가 사용한 육면체는 전부 앞면만 렌더링 된 겁니다.
그렇기 때문에 뒷면(THREE.BackSide)이 없는 주사위의 1번(위), 2번(왼쪽), 3번(앞쪽)은 그림자로 투과되지 않았습니다. 그리고 주사위의 4번(뒤), 5번(오른쪽), 6번(바닥)도 뒷면(THREE.BackSide)이 없어 주사위안에서 보이지 않았던 겁니다.
그래서 Material(머티리얼)에서 렌더링 할 면을 앞면과 뒷면 둘 다 되게 처리하면 됩니다.
각각의 Material(머티리얼)에서 주사위 이미지가 앞면과 뒷면에서 렌더링 되도록 side 속성을 THREE.DoubleSide로 추가합니다. (기본적으로 side 속성은 THREE.FrontSide입니다.)
// 머티리얼 배열
const box2Materials = [
new THREE.MeshStandardMaterial({map: box2TextureLoader.load("resources/textures/dice5t.png"), side: THREE.DoubleSide, alphaTest: 0.1, transparent: true}),
new THREE.MeshStandardMaterial({map: box2TextureLoader.load("resources/textures/dice2t.png"), side: THREE.DoubleSide, alphaTest: 0.1, transparent: true}),
new THREE.MeshStandardMaterial({map: box2TextureLoader.load("resources/textures/dice1t.png"), side: THREE.DoubleSide, alphaTest: 0.1, transparent: true}),
new THREE.MeshStandardMaterial({map: box2TextureLoader.load("resources/textures/dice6t.png"), side: THREE.DoubleSide, alphaTest: 0.1, transparent: true}),
new THREE.MeshStandardMaterial({map: box2TextureLoader.load("resources/textures/dice3t.png"), side: THREE.DoubleSide, alphaTest: 0.1, transparent: true}),
new THREE.MeshStandardMaterial({map: box2TextureLoader.load("resources/textures/dice4t.png"), side: THREE.DoubleSide, alphaTest: 0.1, transparent: true})
];
그럼 주사위 안도 그림자도 모두 이미지가 투과되어 보이게 됩니다.
'Three.js > 기초튼튼' 카테고리의 다른 글
three.js GUI Controls - lil-gui, gui.add (0) | 2023.08.20 |
---|---|
three.js 텍스처 매핑, 알파 맵과 알파 테스트로 이미지 자르기와 그림자 처리 - alphaMap, alphaTest (0) | 2023.08.14 |
three.js 텍스처 매핑, 이미지 입히기 - TextureLoader (0) | 2023.07.16 |
three.js 객체 결합 - Group (0) | 2023.07.09 |
three.js 와이어 프레임 - WireFrame, WireframeGeometry, LineSegments (0) | 2023.07.09 |