🤖

본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.

⚠️

본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.

이미지 로딩 중...

Blender 텍스처링 완벽 가이드 - 슬라이드 1/7
A

AI Generated

2025. 12. 29. · 0 Views

Blender 텍스처링 완벽 가이드

3D 모델에 생명을 불어넣는 텍스처링 기법을 처음부터 차근차근 배워봅니다. 이미지 준비부터 UV 매핑, Shader Editor 활용까지 실무에 바로 적용할 수 있는 내용으로 구성했습니다.


목차

  1. 이미지_텍스처_준비하기
  2. UV_매핑_심화_학습
  3. 프로젝션_매핑_기법
  4. Shader_Editor_기본_사용법
  5. 텍스처를_프로젝트에_입히기
  6. PBR_텍스처_워크플로우

1. 이미지 텍스처 준비하기

김개발 씨는 Blender로 처음 3D 모델을 만들어봤습니다. 하지만 회색 덩어리처럼 보이는 모델을 보며 고민에 빠졌습니다.

"어떻게 하면 이 모델을 실제 나무처럼 보이게 할 수 있을까요?"

텍스처 이미지는 3D 모델의 표면에 입히는 2D 그림 파일입니다. 마치 선물 상자에 포장지를 씌우는 것처럼, 3D 모델에 색상과 디테일을 부여합니다.

PNG, JPG, TIFF 등 다양한 형식을 사용할 수 있으며, 해상도가 높을수록 더 세밀한 표현이 가능합니다.

다음 코드를 살펴봅시다.

import bpy

# 이미지 파일을 Blender로 불러옵니다
image_path = "/path/to/texture/wood_diffuse.png"
texture_image = bpy.data.images.load(image_path)

# 이미지 정보 확인
print(f"이미지 이름: {texture_image.name}")
print(f"해상도: {texture_image.size[0]} x {texture_image.size[1]}")
print(f"컬러 채널: {texture_image.channels}")

# 현재 선택된 오브젝트의 머티리얼에 이미지 할당
obj = bpy.context.active_object
mat = obj.data.materials[0]
mat.use_nodes = True

김개발 씨는 3D 모델링 첫 프로젝트를 시작했습니다. 블렌더로 나무 상자를 만들었지만, 모델이 온통 회색이었습니다.

렌더링을 해봐도 플라스틱 장난감처럼 보일 뿐, 나무의 질감은 전혀 느껴지지 않았습니다. 선배 디자이너 박시니어 씨가 김개발 씨의 작업 화면을 보더니 웃으며 말했습니다.

"텍스처를 입혀야죠. 지금은 모델에 아무런 표면 정보가 없으니까요." 텍스처 이미지란 정확히 무엇일까요?

쉽게 비유하자면, 텍스처는 마치 벽지와 같습니다. 하얀 벽에 나무 무늬 벽지를 붙이면 벽이 나무처럼 보이는 것처럼, 회색 3D 모델에 나무 텍스처 이미지를 입히면 모델이 나무처럼 보입니다.

벽지가 고해상도 사진일수록 더 실감나게 보이는 것처럼, 텍스처 이미지도 해상도가 높을수록 더욱 세밀한 표현이 가능합니다. 텍스처 없이 3D 작업을 하던 시절에는 어땠을까요?

초창기 3D 그래픽에서는 단순한 색상만으로 모델을 표현했습니다. 빨간 공, 파란 상자처럼 단색으로만 칠할 수 있었죠.

나무 질감을 표현하려면 수백만 개의 폴리곤으로 나무결을 직접 조각해야 했습니다. 이는 엄청난 작업 시간이 필요했고, 컴퓨터 성능도 많이 요구했습니다.

바로 이런 문제를 해결하기 위해 텍스처 매핑 기술이 등장했습니다. 텍스처 이미지를 사용하면 간단한 형태의 모델에도 복잡한 디테일을 표현할 수 있습니다.

나무 상자를 만들 때 나무결을 일일이 조각할 필요 없이, 나무 사진 한 장을 붙이기만 하면 됩니다. 무엇보다 파일 용량이 작고 렌더링 속도도 빠르다는 큰 이점이 있습니다.

Blender에서 텍스처 이미지를 준비하는 과정을 살펴보겠습니다. 먼저 적절한 텍스처 이미지 파일을 선택해야 합니다.

일반적으로 PNGJPG 형식을 많이 사용합니다. PNG는 투명도 정보를 담을 수 있어 유리창이나 나뭇잎 같은 오브젝트에 유용하고, JPG는 파일 크기가 작아 일반적인 용도로 적합합니다.

위의 코드에서 첫 번째 줄을 보면 bpy.data.images.load() 함수로 이미지를 불러옵니다. 이 부분이 핵심입니다.

Blender의 Python API인 bpy를 사용하면 스크립트로 텍스처 작업을 자동화할 수 있습니다. 다음으로 이미지의 해상도와 채널 정보를 확인합니다.

해상도는 1024x1024, 2048x2048, 4096x4096처럼 2의 제곱수로 사용하는 것이 일반적입니다. 이는 GPU에서 효율적으로 처리되기 때문입니다.

채널은 RGB(3채널) 또는 RGBA(4채널, 알파 포함)를 의미합니다. 실제 게임 개발이나 건축 시각화 프로젝트에서는 어떻게 활용할까요?

예를 들어 RPG 게임의 중세 성을 만든다고 가정해봅시다. 성벽, 바닥, 지붕 등 수십 개의 오브젝트에 각각 돌, 나무, 기와 텍스처를 입힙니다.

무료 텍스처 사이트인 Poly Haven이나 Textures.com에서 고품질 이미지를 다운받아 사용할 수 있습니다. 많은 AAA급 게임 스튜디오에서도 이런 리소스를 활용하고 있습니다.

하지만 주의할 점도 있습니다. 초보자들이 흔히 하는 실수 중 하나는 이미지 해상도를 너무 크게 사용하는 것입니다.

8K 텍스처를 작은 소품에 사용하면 메모리 낭비가 심합니다. 이렇게 하면 프로젝트 전체의 성능이 저하될 수 있습니다.

따라서 오브젝트의 크기와 카메라 거리에 맞는 적절한 해상도를 선택해야 합니다. 다시 김개발 씨의 이야기로 돌아가 봅시다.

박시니어 씨의 설명을 듣고 김개발 씨는 인터넷에서 나무 텍스처 이미지를 다운받았습니다. "아, 이제 시작이군요!" 텍스처 이미지를 제대로 준비하면 3D 작업의 퀄리티가 한층 높아집니다.

좋은 텍스처는 좋은 결과물의 시작입니다. 여러분도 다양한 텍스처 리소스를 찾아보고 프로젝트에 적용해 보세요.

실전 팁

💡 - 텍스처 해상도는 2의 제곱수(1024, 2048, 4096)를 사용하세요

  • 반복 패턴이 눈에 띄지 않는 Seamless 텍스처를 선택하세요
  • Poly Haven, Textures.com 같은 무료 리소스 사이트를 활용하세요

2. UV 매핑 심화 학습

김개발 씨는 텍스처 이미지를 준비했지만, 막상 모델에 입혀보니 이상하게 늘어나 있었습니다. 나무 무늬가 한쪽은 크고 한쪽은 작았습니다.

박시니어 씨가 말했습니다. "UV 매핑을 제대로 해야 해요."

UV 매핑은 3D 모델의 표면을 2D 평면으로 펼쳐서 텍스처 이미지와 대응시키는 작업입니다. 마치 지구본을 가위로 잘라 평평한 세계지도로 만드는 것과 같습니다.

U와 V는 2D 텍스처 좌표축을 의미하며, 3D의 XYZ와 구분하기 위해 다른 문자를 사용합니다.

다음 코드를 살펴봅시다.

import bpy
import bmesh

# 현재 선택된 오브젝트를 편집 모드로 전환
obj = bpy.context.active_object
bpy.ops.object.mode_set(mode='EDIT')

# BMesh로 메시 데이터 접근
bm = bmesh.from_edit_mesh(obj.data)

# UV 레이어 생성 또는 가져오기
uv_layer = bm.loops.layers.uv.verify()

# 스마트 UV 프로젝트 실행 (자동 언랩)
bpy.ops.uv.smart_project(angle_limit=66.0, island_margin=0.02)

# UV를 0-1 범위로 정규화
bpy.ops.uv.pack_islands(margin=0.01)

bmesh.update_edit_mesh(obj.data)
bpy.ops.object.mode_set(mode='OBJECT')

김개발 씨는 정성껏 준비한 나무 텍스처를 모델에 입혔습니다. 하지만 결과물을 보고 깜짝 놀랐습니다.

나무 무늬가 한쪽 면에서는 크게 늘어나 있고, 다른 면에서는 뭉개져 있었습니다. 마치 스티커를 구겨서 붙인 것 같았습니다.

"왜 이렇게 되는 거죠?" 김개발 씨가 당황하며 물었습니다. 박시니어 씨가 화면을 가리키며 설명했습니다.

"UV 매핑이 제대로 안 되어 있어서 그래요. UV Editor를 열어볼까요?" UV 매핑이란 정확히 무엇일까요?

쉽게 비유하자면, UV 매핑은 마치 종이 상자를 가위로 잘라 펼치는 것과 같습니다. 선물 상자를 만들 때 먼저 평평한 전개도를 그리고, 거기에 그림을 그린 다음, 접어서 상자로 만들죠.

UV 매핑도 정확히 반대 과정입니다. 완성된 3D 모델을 가위로 잘라서 평평하게 펼치는 작업입니다.

UV 매핑 없이 텍스처를 입히면 어떻게 될까요? Blender는 기본적으로 간단한 투영 방식으로 텍스처를 입힙니다.

정육면체처럼 단순한 형태는 괜찮지만, 사람 얼굴이나 동물 같은 복잡한 모델에서는 심각한 왜곡이 발생합니다. 코 부분은 텍스처가 뭉개지고, 귀 부분은 늘어나는 식입니다.

더 큰 문제는 텍스처 아티스트가 어디에 디테일을 그려야 할지 알 수 없다는 점입니다. 바로 이런 문제를 해결하기 위해 UV 언랩 기술이 필수적입니다.

UV 매핑을 제대로 하면 텍스처가 모델 표면에 정확하게 대응됩니다. 각 면의 크기와 비율이 일정하게 유지되어 왜곡이 최소화됩니다.

또한 텍스처 아티스트가 UV 맵을 보고 정확한 위치에 디테일을 그릴 수 있습니다. 무엇보다 전문적인 퀄리티의 결과물을 만들 수 있다는 큰 이점이 있습니다.

UV 매핑 과정을 단계별로 살펴보겠습니다. 먼저 모델을 편집 모드로 전환합니다.

그다음 어떤 모서리를 따라 모델을 자를지 결정하는데, 이를 심(Seam) 마킹이라고 합니다. 위의 코드에서는 자동으로 심을 찾아주는 Smart UV Project 방식을 사용했습니다.

angle_limit 매개변수는 얼마나 급격한 각도에서 모델을 자를지 결정합니다. 66도는 대부분의 경우에 적합한 기본값입니다.

island_margin은 펼쳐진 UV 조각들 사이의 간격을 의미합니다. 0.02는 2%의 여백을 남깁니다.

마지막으로 uv.pack_islands로 UV 조각들을 0-1 범위 안에 효율적으로 배치합니다. 이는 텍스처 공간을 최대한 활용하기 위함입니다.

빈 공간이 적을수록 같은 텍스처 해상도에서 더 선명한 결과를 얻을 수 있습니다. 실제 게임 캐릭터 제작에서는 어떻게 활용할까요?

예를 들어 RPG 게임의 주인공 캐릭터를 만든다고 가정해봅시다. 얼굴, 몸통, 팔, 다리를 각각 언랩하여 하나의 텍스처 시트에 배치합니다.

중요한 부분인 얼굴은 UV 공간을 더 많이 할당하고, 발끝처럼 잘 안 보이는 부분은 작게 배치합니다. AAA급 게임에서는 한 캐릭터에 여러 장의 4K 텍스처를 사용하기도 합니다.

하지만 주의할 점도 있습니다. 초보자들이 흔히 하는 실수 중 하나는 UV를 너무 많이 자르는 것입니다.

심을 많이 만들면 왜곡은 줄어들지만, UV 조각이 너무 많아져서 텍스처 작업이 어려워집니다. 이렇게 하면 심(Seam) 부분에서 텍스처가 어긋나 보이는 문제도 발생할 수 있습니다.

따라서 적절한 균형을 찾아야 합니다. 다시 김개발 씨의 이야기로 돌아가 봅시다.

박시니어 씨가 UV Editor를 열어서 보여주자, 김개발 씨는 감탄했습니다. "아, 이렇게 펼쳐지는구나!" UV 매핑을 제대로 이해하면 어떤 복잡한 모델에도 완벽하게 텍스처를 입힐 수 있습니다.

처음에는 어렵게 느껴지지만, 연습하면 자연스럽게 손에 익습니다. 여러분도 간단한 모델부터 시작해서 직접 UV를 펼쳐보세요.

실전 팁

💡 - 중요한 부분(얼굴 등)은 UV 공간을 더 많이 할당하세요

  • Seam은 눈에 잘 안 보이는 곳(머리카락 뒤, 옷 솔기 등)에 배치하세요
  • UV 조각들이 너무 작으면 텍스처 해상도가 낭비됩니다

3. 프로젝션 매핑 기법

김개발 씨는 UV 언랩을 배웠지만, 복잡한 모델은 여전히 시간이 오래 걸렸습니다. 간단한 원기둥이나 구체에 일일이 심을 그어야 할까요?

박시니어 씨가 더 빠른 방법을 알려주었습니다. "프로젝션 매핑을 써보세요."

프로젝션 매핑은 3D 모델에 특정 방향에서 텍스처를 투영하는 방식입니다. 마치 프로젝터로 벽에 영상을 비추듯이, 모델 표면에 텍스처를 투사합니다.

Cube, Cylinder, Sphere 등 기본 형태에 최적화된 투영 방식이 있어 빠르고 간편하게 텍스처를 입힐 수 있습니다.

다음 코드를 살펴봅시다.

import bpy

# 현재 선택된 오브젝트
obj = bpy.context.active_object
bpy.ops.object.mode_set(mode='EDIT')

# 모든 면 선택
bpy.ops.mesh.select_all(action='SELECT')

# 원기둥 프로젝션 (Cylinder Projection)
# 원기둥 형태의 오브젝트에 적합
bpy.ops.uv.cylinder_project(
    direction='VIEW_ON_EQUATOR',  # 측면에서 투영
    align='POLAR_ZX',             # Z축 정렬
    radius=1.0,                   # 반경
    scale_to_bounds=False
)

# 또는 구체 프로젝션 (Sphere Projection)
# bpy.ops.uv.sphere_project(direction='VIEW_ON_EQUATOR')

bpy.ops.object.mode_set(mode='OBJECT')

김개발 씨는 UV 언랩을 연습하다가 막막함을 느꼈습니다. 건축 프로젝트에서 기둥 수십 개에 일일이 심을 그어야 했기 때문입니다.

한 개당 5분씩 걸린다면 몇 시간이 걸릴지 모를 일이었습니다. 박시니어 씨가 김개발 씨의 답답한 표정을 보고 웃으며 말했습니다.

"기둥은 원기둥 프로젝션을 쓰면 5초 만에 끝나요." 프로젝션 매핑이란 정확히 무엇일까요? 쉽게 비유하자면, 프로젝션 매핑은 마치 영화 프로젝터와 같습니다.

영화관에서 프로젝터가 스크린에 영상을 비추듯이, 3D 모델에 특정 방향에서 텍스처를 비춥니다. 스크린이 평평할수록 영상이 깨끗하게 보이는 것처럼, 모델의 형태가 투영 방식과 잘 맞을수록 좋은 결과를 얻습니다.

수동으로 UV를 펼치던 시절에는 어땠을까요? 모든 모델에 일일이 심을 그리고 언랩해야 했습니다.

단순한 원기둥 하나를 처리하는 데도 몇 분씩 걸렸습니다. 실수로 심을 잘못 그으면 처음부터 다시 시작해야 했습니다.

더 큰 문제는 대량의 반복 작업이 필요한 프로젝트에서 생산성이 크게 떨어진다는 점이었습니다. 바로 이런 문제를 해결하기 위해 자동 프로젝션 기능이 등장했습니다.

프로젝션 매핑을 사용하면 기본 형태의 모델에 즉시 텍스처를 입힐 수 있습니다. 원기둥은 Cylinder Projection, 구체는 Sphere Projection, 평면은 Plane Projection을 사용하면 됩니다.

또한 여러 오브젝트를 한 번에 처리할 수 있어 작업 속도가 비약적으로 향상됩니다. 무엇보다 일관된 퀄리티를 유지할 수 있다는 큰 이점이 있습니다.

프로젝션 매핑의 종류를 살펴보겠습니다. Cylinder Projection은 원기둥 형태에 최적화되어 있습니다.

위의 코드에서 direction='VIEW_ON_EQUATOR'는 측면에서 텍스처를 감싸듯이 투영한다는 의미입니다. 나무 기둥, 파이프, 병 같은 오브젝트에 적합합니다.

Sphere Projection은 구체에 사용합니다. 지구본에 세계지도를 입히는 것처럼 작동합니다.

공, 행성, 머리 같은 둥근 오브젝트에 유용합니다. 다만 극점(위아래 끝) 부분에서는 약간의 왜곡이 발생할 수 있습니다.

Cube Projection은 육면체나 건물 같은 각진 형태에 적합합니다. 6개 방향에서 동시에 투영하여 박스 모양의 UV를 만듭니다.

매개변수를 조정하면 더 세밀한 제어가 가능합니다. radius 값을 조절하여 투영 범위를 넓히거나 좁힐 수 있고, scale_to_bounds를 True로 설정하면 UV를 자동으로 0-1 범위에 맞춥니다.

실제 건축 시각화 프로젝트에서는 어떻게 활용할까요? 예를 들어 아파트 단지를 모델링한다고 가정해봅시다.

수십 개의 원형 기둥에는 Cylinder Projection을 일괄 적용하고, 돔 형태의 천장에는 Sphere Projection을 사용합니다. 평평한 벽면은 Plane Projection으로 처리합니다.

이렇게 하면 수백 개의 오브젝트를 몇 분 만에 처리할 수 있습니다. 많은 건축 스튜디오에서 이런 방식으로 작업 시간을 단축하고 있습니다.

하지만 주의할 점도 있습니다. 초보자들이 흔히 하는 실수 중 하나는 모든 모델에 프로젝션을 사용하려는 것입니다.

복잡한 유기체 형태나 캐릭터에는 프로젝션이 적합하지 않습니다. 이렇게 하면 심한 왜곡이 발생하고 텍스처가 뭉개집니다.

따라서 기본 형태에 가까운 단순한 모델에만 사용해야 합니다. 다시 김개발 씨의 이야기로 돌아가 봅시다.

박시니어 씨의 조언대로 Cylinder Projection을 적용하자, 수십 개의 기둥이 순식간에 완성되었습니다. "와, 정말 빠르네요!" 프로젝션 매핑을 제대로 활용하면 반복 작업을 크게 줄일 수 있습니다.

어떤 형태에 어떤 프로젝션이 적합한지 이해하는 것이 중요합니다. 여러분도 간단한 모델로 각 프로젝션 방식을 실험해 보세요.

실전 팁

💡 - 원기둥 형태는 Cylinder Projection, 구체는 Sphere Projection을 사용하세요

  • 복잡한 형태에는 프로젝션보다 수동 언랩이 더 적합합니다
  • 여러 오브젝트를 동시에 선택하여 일괄 처리하면 시간을 절약할 수 있습니다

4. Shader Editor 기본 사용법

김개발 씨는 텍스처를 입히는 법을 배웠지만, 더 현실적인 재질을 표현하고 싶었습니다. 금속의 반짝임이나 유리의 투명함은 어떻게 만들까요?

박시니어 씨가 Shader Editor를 열어 보여주었습니다.

Shader Editor는 Blender에서 재질의 모든 속성을 노드 기반으로 편집하는 도구입니다. 마치 전기 회로를 연결하듯이, 여러 노드를 선으로 연결하여 복잡한 재질을 만듭니다.

색상, 반사, 투명도, 범프 등 모든 시각적 요소를 세밀하게 제어할 수 있습니다.

다음 코드를 살펴봅시다.

import bpy

# 현재 선택된 오브젝트의 머티리얼 가져오기
obj = bpy.context.active_object
mat = obj.data.materials[0]

# 노드 사용 활성화
mat.use_nodes = True
nodes = mat.node_tree.nodes
links = mat.node_tree.links

# 기존 노드 삭제
nodes.clear()

# Principled BSDF 노드 생성 (메인 셰이더)
shader = nodes.new(type='ShaderNodeBsdfPrincipled')
shader.location = (0, 0)

# 이미지 텍스처 노드 생성
tex_node = nodes.new(type='ShaderNodeTexImage')
tex_node.location = (-300, 0)
tex_node.image = bpy.data.images.load("/path/to/texture.png")

# Material Output 노드 생성
output = nodes.new(type='ShaderNodeOutputMaterial')
output.location = (300, 0)

# 노드 연결: 텍스처 -> 셰이더 -> 출력
links.new(tex_node.outputs['Color'], shader.inputs['Base Color'])
links.new(shader.outputs['BSDF'], output.inputs['Surface'])

김개발 씨는 나무 텍스처를 입힌 상자를 렌더링했습니다. 그런데 뭔가 아쉬웠습니다.

나무처럼 보이기는 하지만, 사진처럼 평면적이었습니다. 실제 나무의 거친 질감이나 미묘한 반사는 느껴지지 않았습니다.

박시니어 씨가 김개발 씨의 화면을 보더니 말했습니다. "Shader Editor를 열어보세요.

거기서 재질의 모든 것을 조절할 수 있어요." Shader Editor란 정확히 무엇일까요? 쉽게 비유하자면, Shader Editor는 마치 음악 믹싱 콘솔과 같습니다.

믹싱 콘솔에서 여러 악기의 음량, 이퀄라이저, 이펙트를 조절하여 최종 사운드를 만들듯이, Shader Editor에서는 여러 속성을 조합하여 최종 재질을 만듭니다. 각 노드는 하나의 기능을 담당하고, 선으로 연결하여 데이터를 전달합니다.

Shader Editor가 없던 시절에는 어땠을까요? 예전 3D 프로그램에서는 재질 설정이 단순한 슬라이더와 체크박스로만 이루어져 있었습니다.

복잡한 효과를 만들려면 프로그래밍을 직접 해야 했습니다. 아티스트가 쉽게 접근하기 어려웠고, 시행착오를 거치며 결과를 확인하는 데도 오랜 시간이 걸렸습니다.

바로 이런 문제를 해결하기 위해 노드 기반 시스템이 등장했습니다. Shader Editor를 사용하면 프로그래밍 없이도 복잡한 재질을 만들 수 있습니다.

노드를 드래그 앤 드롭으로 배치하고 연결하기만 하면 됩니다. 또한 변경 사항을 실시간으로 확인할 수 있어 작업 흐름이 매우 빠릅니다.

무엇보다 재질을 저장하고 다른 프로젝트에 재사용할 수 있다는 큰 이점이 있습니다. Shader Editor의 핵심 구성 요소를 살펴보겠습니다.

가장 중요한 노드는 Principled BSDF입니다. 이것은 메인 셰이더로, 금속, 플라스틱, 유리 등 거의 모든 재질을 표현할 수 있는 만능 노드입니다.

Disney와 Pixar가 개발한 물리 기반 렌더링(PBR) 원리를 기반으로 합니다. Image Texture 노드는 텍스처 이미지를 불러옵니다.

위의 코드에서 tex_node.image로 이미지 파일을 지정합니다. 이 노드의 Color 출력을 Principled BSDF의 Base Color 입력에 연결하면 텍스처가 적용됩니다.

Material Output 노드는 최종 출력을 담당합니다. 모든 계산의 결과가 이 노드로 모여서 렌더 엔진에 전달됩니다.

Surface 입력은 표면 재질을, Volume 입력은 볼륨 효과를 담당합니다. 노드를 연결하는 방법은 간단합니다.

links.new()로 출력 소켓과 입력 소켓을 연결합니다. 데이터는 왼쪽에서 오른쪽으로 흐릅니다.

색상 데이터는 노란색 선으로, 숫자 데이터는 회색 선으로 표시됩니다. 실제 제품 시각화 프로젝트에서는 어떻게 활용할까요?

예를 들어 스마트폰을 렌더링한다고 가정해봅시다. 금속 프레임에는 Metallic을 1.0으로 설정하고, 유리 스크린에는 Transmission을 높여 투명도를 줍니다.

카메라 렌즈에는 Roughness를 낮춰 반들반들한 느낌을 냅니다. 이런 디테일이 모여 사진처럼 현실적인 결과물이 만들어집니다.

Apple, Samsung 같은 기업의 제품 이미지도 이런 방식으로 제작됩니다. 하지만 주의할 점도 있습니다.

초보자들이 흔히 하는 실수 중 하나는 너무 많은 노드를 연결하는 것입니다. 복잡할수록 좋아 보이지만, 실제로는 렌더링 시간만 늘어나고 결과는 비슷합니다.

이렇게 하면 나중에 수정할 때도 어려워집니다. 따라서 필요한 만큼만 사용하는 것이 좋습니다.

다시 김개발 씨의 이야기로 돌아가 봅시다. 박시니어 씨가 Shader Editor를 열어서 Roughness 값을 조절하자, 나무 표면에 미묘한 반사가 생겼습니다.

"우와, 진짜 나무 같아요!" Shader Editor를 제대로 활용하면 어떤 재질이든 표현할 수 있습니다. 처음에는 복잡해 보이지만, 몇 가지 핵심 노드만 이해하면 쉽게 응용할 수 있습니다.

여러분도 기본 노드부터 하나씩 실험해 보세요.

실전 팁

💡 - Principled BSDF 하나로 대부분의 재질을 표현할 수 있습니다

  • Shift+A로 노드 추가 메뉴를 열 수 있습니다
  • Ctrl+Shift+클릭으로 노드 미리보기를 볼 수 있습니다

5. 텍스처를 프로젝트에 입히기

김개발 씨는 이제 Shader Editor도 다룰 줄 알게 되었습니다. 하지만 실제 프로젝트에서는 하나의 텍스처가 아니라 여러 장의 맵을 사용한다고 들었습니다.

Diffuse, Normal, Roughness... 이게 다 뭘까요?

텍스처 맵은 재질의 서로 다른 속성을 제어하는 여러 이미지들의 집합입니다. Diffuse(색상), Normal(표면 디테일), Roughness(거칠기), Metallic(금속성) 등 각 맵이 특정 역할을 담당합니다.

이들을 조합하면 단순한 3D 모델도 사진처럼 현실적으로 보이게 할 수 있습니다.

다음 코드를 살펴봅시다.

import bpy

obj = bpy.context.active_object
mat = obj.data.materials[0]
mat.use_nodes = True
nodes = mat.node_tree.nodes
links = mat.node_tree.links

# Principled BSDF 노드 가져오기
shader = nodes.get("Principled BSDF")

# Diffuse(Base Color) 맵
diffuse = nodes.new('ShaderNodeTexImage')
diffuse.image = bpy.data.images.load("/textures/wood_diffuse.png")
diffuse.location = (-600, 300)
links.new(diffuse.outputs['Color'], shader.inputs['Base Color'])

# Normal 맵
normal_tex = nodes.new('ShaderNodeTexImage')
normal_tex.image = bpy.data.images.load("/textures/wood_normal.png")
normal_tex.image.colorspace_settings.name = 'Non-Color'  # 중요!
normal_map = nodes.new('ShaderNodeNormalMap')
normal_tex.location = (-600, 0)
normal_map.location = (-300, 0)
links.new(normal_tex.outputs['Color'], normal_map.inputs['Color'])
links.new(normal_map.outputs['Normal'], shader.inputs['Normal'])

# Roughness 맵
rough = nodes.new('ShaderNodeTexImage')
rough.image = bpy.data.images.load("/textures/wood_roughness.png")
rough.image.colorspace_settings.name = 'Non-Color'
rough.location = (-600, -300)
links.new(rough.outputs['Color'], shader.inputs['Roughness'])

김개발 씨는 무료 텍스처 사이트에서 나무 텍스처를 다운받았습니다. 그런데 zip 파일을 열어보니 이미지가 여러 장 들어있었습니다.

wood_diffuse.png, wood_normal.png, wood_roughness.png... 이게 다 필요한 걸까요?

박시니어 씨가 설명했습니다. "현대적인 텍스처는 여러 맵의 조합이에요.

각 맵이 다른 역할을 하죠." 텍스처 맵 시스템이란 정확히 무엇일까요? 쉽게 비유하자면, 텍스처 맵은 마치 인쇄소의 인쇄판과 같습니다.

컬러 인쇄를 할 때 CMYK 네 가지 판을 겹쳐서 최종 이미지를 만들듯이, 3D에서도 여러 맵을 겹쳐서 완성된 재질을 만듭니다. 각 판이 다른 색을 담당하는 것처럼, 각 맵도 다른 속성을 담당합니다.

단순히 색상만 있던 시절에는 어땠을까요? 초창기에는 Diffuse 맵 하나만 사용했습니다.

나무 사진을 붙이면 끝이었죠. 하지만 평면적으로 보였습니다.

나무결의 울퉁불퉁함, 오래된 부분의 거칠기, 왁스 칠한 부분의 반질거림 같은 디테일을 표현할 수 없었습니다. 더 큰 문제는 조명이 바뀌어도 재질의 반응이 단조로웠다는 점입니다.

바로 이런 문제를 해결하기 위해 다중 맵 시스템이 발전했습니다. 여러 맵을 사용하면 재질의 모든 측면을 세밀하게 제어할 수 있습니다.

Normal 맵으로 표면의 미세한 요철을 표현하고, Roughness 맵으로 부분마다 다른 반사도를 줍니다. 또한 조명 환경이 바뀌어도 자연스럽게 반응합니다.

무엇보다 영화나 AAA급 게임 수준의 퀄리티를 달성할 수 있다는 큰 이점이 있습니다. 각 맵의 역할을 자세히 살펴보겠습니다.

Diffuse 맵(또는 Base Color 맵)은 재질의 기본 색상을 담당합니다. 나무의 갈색, 녹슨 부분의 붉은색 같은 것들입니다.

이것이 가장 기본이 되는 맵입니다. Normal 맵은 표면의 디테일을 가짜로 만듭니다.

실제로 폴리곤을 추가하지 않고도 울퉁불퉁한 효과를 냅니다. 보라색과 파란색으로 보이는 이상한 이미지인데, 이는 표면의 각도 정보를 색상으로 인코딩한 것입니다.

위의 코드에서 colorspace_settings.name = 'Non-Color'로 설정하는 것이 매우 중요합니다. 이렇게 하지 않으면 Normal 맵이 제대로 작동하지 않습니다.

Roughness 맵은 표면의 거칠기를 제어합니다. 흰색 부분은 거칠고(반사 약함), 검은색 부분은 매끄럽습니다(반사 강함).

나무에서 왁스 칠한 부분은 검게, 오래된 부분은 희게 칠합니다. Metallic 맵은 금속성을 제어합니다.

1(흰색)이면 완전한 금속, 0(검은색)이면 비금속입니다. 중간값은 거의 사용하지 않습니다.

노드를 연결하는 과정을 살펴보겠습니다. Normal 맵의 경우 Image Texture 노드와 Principled BSDF 사이에 Normal Map 노드를 반드시 끼워야 합니다.

이 노드가 색상 정보를 실제 방향 벡터로 변환해주기 때문입니다. 실제 게임 개발에서는 어떻게 활용할까요?

예를 들어 판타지 게임의 돌벽을 만든다고 가정해봅시다. Diffuse로 돌의 색상을, Normal로 돌 사이의 틈과 표면 질감을, Roughness로 이끼 낀 부분과 깨끗한 부분의 반사 차이를, Ambient Occlusion으로 틈새의 그림자를 표현합니다.

이렇게 4-5장의 맵을 조합하면 수백만 폴리곤으로 조각한 것 같은 효과를 얻습니다. Unreal Engine, Unity 같은 게임 엔진에서도 똑같은 원리를 사용합니다.

하지만 주의할 점도 있습니다. 초보자들이 흔히 하는 실수 중 하나는 Normal 맵의 색상 공간을 바꾸지 않는 것입니다.

그대로 사용하면 Blender가 색상 보정을 적용하여 맵이 왜곡됩니다. 이렇게 하면 Normal 맵 효과가 이상하게 나타나거나 아예 작동하지 않습니다.

따라서 반드시 'Non-Color'로 설정해야 합니다. Roughness, Metallic 같은 데이터 맵도 마찬가지입니다.

다시 김개발 씨의 이야기로 돌아가 봅시다. 박시니어 씨가 알려준 대로 모든 맵을 연결하고 렌더링을 해봤습니다.

"와! 이제 진짜 나무네요!" 텍스처 맵을 제대로 활용하면 단순한 모델도 놀라운 퀄리티로 만들 수 있습니다.

각 맵의 역할을 이해하고 올바르게 연결하는 것이 핵심입니다. 여러분도 무료 텍스처 사이트에서 PBR 텍스처 세트를 다운받아 실험해 보세요.

실전 팁

💡 - Normal, Roughness, Metallic 맵은 반드시 'Non-Color' 색상 공간으로 설정하세요

  • Poly Haven(polyhaven.com)에서 무료 PBR 텍스처를 다운받을 수 있습니다
  • 모든 맵의 해상도는 같아야 합니다(예: 모두 2048x2048)

6. PBR 텍스처 워크플로우

김개발 씨는 여러 맵을 사용하는 법을 배웠습니다. 그런데 선배들이 자주 언급하는 "PBR"이란 단어가 궁금했습니다.

박시니어 씨가 설명했습니다. "PBR은 현대 3D 그래픽의 표준이에요."

PBR(Physically Based Rendering)은 물리 법칙에 기반한 렌더링 방식입니다. 실제 세계의 빛과 재질이 반응하는 방식을 수학적으로 시뮬레이션하여, 어떤 조명 환경에서도 자연스럽게 보이는 재질을 만듭니다.

Disney, Pixar, Epic Games 등이 개발한 산업 표준입니다.

다음 코드를 살펴봅시다.

import bpy

# PBR 텍스처 세트를 한 번에 설정하는 함수
def setup_pbr_material(obj, texture_folder):
    mat = obj.data.materials[0]
    mat.use_nodes = True
    nodes = mat.node_tree.nodes
    links = mat.node_tree.links

    shader = nodes.get("Principled BSDF")

    # PBR 맵 목록: (파일명, 입력 소켓, 색상공간)
    pbr_maps = [
        ('BaseColor.png', 'Base Color', 'sRGB'),
        ('Normal.png', 'Normal', 'Non-Color'),
        ('Roughness.png', 'Roughness', 'Non-Color'),
        ('Metallic.png', 'Metallic', 'Non-Color'),
        ('AO.png', 'Base Color', 'Non-Color'),  # AO는 별도 처리
    ]

    y_offset = 0
    for filename, socket, colorspace in pbr_maps:
        tex = nodes.new('ShaderNodeTexImage')
        tex.image = bpy.data.images.load(f"{texture_folder}/{filename}")
        tex.image.colorspace_settings.name = colorspace
        tex.location = (-600, y_offset)

        if 'Normal' in filename:
            # Normal 맵은 Normal Map 노드를 거쳐야 함
            normal_node = nodes.new('ShaderNodeNormalMap')
            normal_node.location = (-300, y_offset)
            links.new(tex.outputs['Color'], normal_node.inputs['Color'])
            links.new(normal_node.outputs['Normal'], shader.inputs['Normal'])
        else:
            links.new(tex.outputs['Color'], shader.inputs[socket])

        y_offset -= 300

# 사용 예시
obj = bpy.context.active_object
setup_pbr_material(obj, "/path/to/pbr_textures")

김개발 씨는 프로젝트를 진행하면서 이상한 점을 발견했습니다. 실내에서는 멋지게 보이던 재질이 야외 씬에서는 이상하게 보였습니다.

왜 조명이 바뀌면 재질도 다시 조정해야 할까요? 박시니어 씨가 웃으며 말했습니다.

"PBR 워크플로우를 사용하면 그런 문제가 없어요. 한 번만 제대로 설정하면 어디서든 자연스럽게 보입니다." PBR이란 정확히 무엇일까요?

쉽게 비유하자면, PBR은 마치 실제 카메라로 촬영하는 것과 같습니다. 실제 세계에서는 물체의 재질이 조명에 따라 변하지 않습니다.

금속은 항상 금속이고, 나무는 항상 나무입니다. 햇빛 아래든 실내등 아래든 재질 자체는 동일하고, 단지 빛의 반사 방식만 다를 뿐입니다.

PBR도 이 원리를 따릅니다. PBR 이전의 렌더링 방식은 어땠을까요?

예전에는 아티스트가 "경험과 감"으로 재질을 만들었습니다. 이 조명에서 멋져 보이도록 Specular를 이만큼, Diffuse는 저만큼 조절했습니다.

문제는 조명이 바뀌면 다시 조정해야 한다는 점이었습니다. 또한 아티스트마다 결과가 달랐고, 일관성을 유지하기 어려웠습니다.

더 큰 문제는 실제 사진과 비교했을 때 "뭔가 이상한" 느낌이 든다는 것이었습니다. 바로 이런 문제를 해결하기 위해 PBR 워크플로우가 표준으로 자리 잡았습니다.

PBR을 사용하면 재질이 물리적으로 정확하게 동작합니다. 금속은 Fresnel 효과로 측면에서 더 밝게 반사되고, 거친 표면은 반사를 흐트러뜨립니다.

또한 에너지 보존 법칙을 따라 반사된 빛과 흡수된 빛의 합이 항상 100%입니다. 무엇보다 한 번 만든 재질을 어떤 프로젝트, 어떤 조명에서도 재사용할 수 있다는 큰 이점이 있습니다.

PBR 워크플로우의 핵심 원칙을 살펴보겠습니다. 첫 번째 원칙은 에너지 보존입니다.

재질이 반사하는 빛은 들어온 빛보다 많을 수 없습니다. Blender의 Principled BSDF는 자동으로 이를 보장합니다.

Roughness가 높으면 Specular가 자동으로 분산되고, Metallic이 높으면 Base Color가 반사색이 됩니다. 두 번째 원칙은 Fresnel 효과입니다.

모든 재질은 각도에 따라 반사도가 달라집니다. 물을 위에서 보면 투명하지만, 옆에서 보면 거울처럼 반사됩니다.

Principled BSDF는 이것도 자동으로 계산합니다. 세 번째 원칙은 물리적으로 올바른 값 사용입니다.

금속은 Metallic을 1.0으로, 비금속은 0.0으로 설정합니다. 중간값은 특수한 경우(녹슨 금속 등)에만 사용합니다.

Roughness도 실제 재질의 값을 참고합니다. 새 플라스틱은 0.2, 오래된 나무는 0.8 같은 식입니다.

위의 코드는 PBR 텍스처 세트를 자동으로 설정하는 함수입니다. 반복 작업을 줄이기 위해 맵 목록을 배열로 정의하고, 반복문으로 처리합니다.

특히 Normal 맵은 별도로 처리하여 Normal Map 노드를 자동으로 추가합니다. colorspace 매개변수를 보면 Base Color는 'sRGB'를, 나머지는 'Non-Color'를 사용합니다.

이는 PBR 워크플로우의 중요한 규칙입니다. 색상 정보는 sRGB로, 데이터 정보는 Non-Color로 설정해야 합니다.

실제 영화 VFX 제작에서는 어떻게 활용할까요? 예를 들어 마블 영화의 아이언맨 슈트를 만든다고 가정해봅시다.

금속 부분은 Metallic 1.0, 적당한 Roughness로 설정합니다. 조인트 부분은 Roughness를 높여 긁힌 느낌을 냅니다.

라이팅 아티스트가 어떤 조명을 설정하든, 재질은 자동으로 물리적으로 정확하게 반응합니다. ILM, Weta Digital 같은 VFX 스튜디오에서 PBR을 표준으로 사용하는 이유입니다.

하지만 주의할 점도 있습니다. 초보자들이 흔히 하는 실수 중 하나는 Metallic 값을 0.5처럼 중간으로 설정하는 것입니다.

실제 세계에는 "반만 금속"인 재질이 거의 없습니다. 이렇게 하면 비현실적으로 보입니다.

따라서 금속은 1.0, 비금속은 0.0으로 명확하게 구분해야 합니다. 예외는 녹이나 먼지가 낀 경우인데, 이때는 텍스처로 부분적으로 다르게 설정합니다.

다시 김개발 씨의 이야기로 돌아가 봅시다. 박시니어 씨가 PBR 설정을 도와주고, 여러 조명 환경에서 렌더링해 봤습니다.

놀랍게도 모든 환경에서 자연스러웠습니다. "이게 PBR의 힘이군요!" PBR 워크플로우를 제대로 이해하면 전문가 수준의 재질을 만들 수 있습니다.

물리 법칙을 따르기 때문에 직관적이고, 한 번 배우면 Blender뿐만 아니라 Unreal, Unity, Cinema 4D 등 모든 3D 툴에서 활용할 수 있습니다. 여러분도 PBR 원칙을 따라 재질을 만들어 보세요.

실전 팁

💡 - Metallic은 0 또는 1로 명확하게 설정하세요(중간값은 특수한 경우만)

  • 실제 재질의 Roughness 값을 참고하세요(검색하면 참고 차트가 많습니다)
  • Blender, Unreal, Unity 모두 같은 PBR 원칙을 따르므로 재질을 쉽게 전환할 수 있습니다

이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!

#Blender#Texturing#UV Mapping#Shader Editor#PBR Workflow#Three.js,Blender,3D웹개발

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.