23.06.15
DEVOTEE를 활성화 시키면
지금 작성한 커뮤니티 글에 대해 1개의 댓글을 달아줍니다.
버튼을 누르면 글 수정 시 ChatGPT가 작성한 댓글이 수정됩니다.
| 컨텐츠 유형 | 제목 | 저장일 | 삭제 |
|---|
본인인증 로그인에 실패하였습니다.
회원이 아니시거나 본인인증 등록이
완료되지 않은 사용자입니다.
얼마 전에 충격적인 사실을 알았습니다. 지난 기고에 참고했던 문서가 번역본을 제공하더라고요.
알고보니 제가 애써서 번역할 필요가 없었습니다. 코드를 이해하는데 꼭 필요한 기반 지식을 설명하는데 큰 의의가 있기는 했지만요.
이번에는 라이팅(Lighting)와 머티리얼(Material)에 대해 다루려고 합니다.
컴퓨터 그래픽스에서 어떤 물체를 사실적으로 표현하기 위해서는 라이트와 머터리얼, 이 두 가지가 꼭 필요합니다.
지난 편에서 회전하는 초록색 박스가 사실적으로 표현되지 않았는데요. 두 가지를 추가해서 우리에게 익숙한 화면으로 연출해 보겠습니다.
라이팅에 대해 어디까지 다루어야 할지 고민이 되었습니다.
보다 사실적으로 물체를 표현하기 위해서 아주 기본적인 물리적인 요소에서부터 점차 연산량과 고려 사항을 늘려나가 결국 쉐이터와 GPU를 탄생시키는데 일조했기 때문입니다.
여기에서는 WebGL을 활용하여 기본적인 어플리케이션을 만드는데 필요한 수준까지만 설명하고, 이론적으로 알아두면 좋은 것 같은 부분은 문서 마지막에 레퍼런스로 소개하도록 하겠습니다.
기본적으로 라이팅의 종류를 설명할 때는 광원(Light source)으로 분류합니다. 광원은 빛을 방출하는 지점 또는 영역을 의미합니다.
다양한 종류의 광원이 있으며, 각각 고유의 특성을 가지고 있습니다.
방향광(Directional Light): 빛이 일정한 방향으로 평행하게 쏟아지는 광원으로, 태양광과 비슷합니다.
아주 먼 곳에서 다량의 광선이 쏟아져 온다고 가정하는 것으로, 빛의 방향은 모두 평행합니다.
방향광이 중요한 이유는 우리 실생활에서 느끼는 자연광과 매우 유사한 결과를 만들어주며, 마찬가지로 직관적으로 이해할 수 있는 그림자를 생성하기 때문입니다.
점광원(Point Light): 특정 지점에서 모든 방향으로 빛을 방출하는 광원입니다. 전구와 같은 방식으로 빛이 퍼집니다.
빛의 세기는 광원으로부터 거리와 비례합니다. 다음의 예제를 통해 쉽게 이해할 수 있습니다.
스포트라이트(Spotlight): 특정 방향으로만 빛이 집중되도록 방출되는 광원입니다.
손전등처럼 빛의 범위가 제한됩니다. 광원으로부터 콘(cone) 모양으로 방출됩니다.
환경광(Ambient Light): 장면 전체에 고르게 퍼진 빛으로, 특정한 광원에서 오는 것이 아닌 전체적인 분위기를 조성하는 데 사용됩니다.
모든 물체의 표면에 동일하게 작용합니다.
하나의 장면(scene)에 하나의 조명(light)만 사용하는 것은 아닙니다.
연출하고자 하는 장면에 따라 여러개의 다양한 조명을 쓰기도 하는데요.
지난 시간에 사용했던 예제에 다음의 코드를 추가해 주겠습니다.
const directionalLight = new THREE.DirectionalLight( 0xffffff, 5.5 );
directionalLight.position.set(-1, 5, 0);
scene.add( directionalLight );DirectionalLight의 파라미터는 빛의 색상과 강도입니다. 이후에 3차원 좌표로 위치를 설정해줬고요.
무엇이 바뀌었나요? 아무것도 바뀌지 않았습니다. 이제 머티리얼을 배울 차례입니다.
머티리얼(Material; 재질)은 어떠한 물체의 외관을 묘사하는 다양한 속성들을 말합니다.
금속은 빛을 잘 반사하기 때문에 반짝거리는 특성이 있습니다. 반면 마른 흙이나 고무 등은 금속보다 빛을 덜 반사합니다.
옷감 중에서도 면과 벨벳은 명확하게 구분되는 시각적 차이를 가지고 있습니다.
컴퓨터 그래픽스는 물체의 색상, 질감, 형태, 빛의 반사 등의 다양한 특성을 조합하여 시각적으로 표현하고자 하며, 이러한 특성들의 조합을 머티리얼이라고 지칭하는 것입니다.
Three.js 라이브러리에서 자주 사용하는 대표적인 몇 가지 Material을 다루어 보겠습니다.
아래로 갈수록 더 많은 계산 비용이 필요하며, 더 사실적으로 표현할 수 있습니다.
MeshLambertMaterial
반사율을 계산하기 위해 Lamberial 모델을 사용합니다.
이 모델은 광택(specular highlights)에 대한 고려가 되어 있지 않기 때문에 나무나 돌과 같은 표면은 잘 표현할 수 있지만, 금속이나 반짝이는 재질을 표현하기는 어렵습니다.
하지만 빠르게 동작하고 고유의 색을 표현하는데에는 부족함이 없기 때문에 활용할 부분이 많아요.
MeshPhongMaterial
비물리 기반의 Blinn-Phong 모델을 사용합니다. Lambertian 모델과는 달리 반사되는 광택을 더 잘 표현할 수 있습니다.
MeshStandardMaterial
Unity, Unreal 등에서 자주 사용하고 3D Max, Maya등의 그래픽스 스탠다드 도구에서도 프로 레벨에서 많이 사용하는 모델입니다.
물리 기반 렌더링(PBR; Physically based rendering) 기법의 일부를 사용합니다. 물리 기반 렌더링이란 빛을 물리적, 수치적으로 모델링하여 정확하게 계산해보자는 접근 방법입니다.
다른 기법들보다 더 사실적이고 정확한 표현이 가능하지만 계산량이 아주 많다는 단점이 있습니다.
예전에는 영화 쪽에서나 사용할 수 있던 기법인데 최근 GPU의 등장으로 실시간 계산 성능이 좋아지면서 게임이나 Web 쪽으로 적용되고 있는 추세입니다.
MeshPhysicalMaterial
Standard material의 확장판으로, 더 다양한 속성의 물리 기반 렌더링을 지원합니다. 더 많은 계산 비용을 사용하지만, 활용하기에 따라서 더 사실적인 결과를 연출할 수 있습니다.
머티리얼 몇 개를 사용해보고 차이점을 눈으로 확인해보도록 하지요. 우리의 cube를 MeshLambertMaterial로 바꾸어 보겠습니다.
const cubeGeometry = new THREE.BoxGeometry( 1, 1, 1 );
const cubeMaterial = new THREE.MeshLambertMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh( cubeGeometry, cubeMaterial );
scene.add( cube );실행해보니 뭔가 이상합니다. 이제 큐브가 3차원인 느낌이 나는 것 같긴 한데 자꾸 중간에 사라집니다.
이유는 이렇습니다. 우리는 윗쪽에 directional light를 설정했고, 그 조명의 빛을 받는 면만 화면에 그려지고 있는 것입니다.
실생활에서는 조명과 떨어져 있더라도 환경에 의해 반사되는 빛들로 다른 부분도 표현이 되지만, 그래픽스의 세상에서는 반사되는 빛을 표현하려면 이것 역시 계산해 줘야 합니다.
그렇다면 간단하게 극복할 수 있는 방법은 무엇일까요? 위에서 언급한 ambient light를 이럴 때 사용합니다.
이 공간에는 “기본적으로 반사되는 빛이 있어”라고 설정해버리는 것이죠. Directional light 다음에 아래의 코드를 추가합니다.
AmbientLight의 파라미터는 색상 값과 빛의 강도입니다.
const ambientLight = new THREE.AmbientLight( 0x404040, 3.0 ); // soft white light
scene.add( ambientLight );이렇게 설정하는게 찜찜할 수도 있습니다. 뭔가 정확한 느낌은 아니잖아요?
그러나 계산량을 줄이면서 그럴싸해 보이도록 설정하는 것, 이것이 바로 비 물리적 렌더링입니다. 간단하지만 효과적입니다.
Directional light 하나를 더 추가하는 것 만으로도 시각적으로 탁월해집니다.
const directionalLight2 = new THREE.DirectionalLight( 0xffffff, 1.5 );
directionalLight2.position.set(-1, 1, 0);
scene.add( directionalLight2 );이제 물리 기반 렌더링이 궁금하실텐데요. 정확한 구현은 조금 복잡하기 때문에 아주 간단하게 차이점만 느껴보도록 하겠습니다.
우선 scene에 배경색을 넣어주겠습니다. 연한 회색이 될거예요.
scene.background = new THREE.Color( 0x333333 );그리고 cube의 머티리얼을 다음과 같이 바꾸어줍니다.
const cubeMaterial = new THREE.MeshPhysicalMaterial({
color: 0xff0000,
metalness: 1.0,
roughness: 0.5,
clearcoat: 1.0,
clearcoatRoughness: 0.03
});뭔가 메탈릭하게 반짝이는 큐브를 보실 수 있을거예요.
원래는 환경 맵이라는 것을 설정해서 표면에 더 많은 반사 효과를 넣어야 합니다만 현재로서는 차이점을 맛보는 것으로 만족하도록 하겠습니다.
큐브 두 개의 머티리얼을 다르게 설정한 뒤에 동시에 렌더링하면 확연한 차이를 느낄 수 있습니다.
아래에 코드 전체를 넣어두겠습니다. 라이브 링크는 여기(https://jsfiddle.net/3x71pmk8/42/)입니다.
고맙습니다. 다음 시간도 재미있는 기법과 지식을 들고 오겠습니다.
라이팅의 종류에 대해서는 다음의 레퍼런스들을 참고하세요
three.js와 WebGL에서의 머티리얼 정보는 아래를 참고하세요.
환경 맵과 물리 기반 렌더링에 대한 레퍼런스는 아래의 페이지가 좋습니다.
DEVOTEE를 활성화 시키면
지금 작성한 댓글에 AI가 댓글을 달아줍니다.