러프니스를 스무스니스로 변환 · Unity용 채널 반전
Unity 메탈릭 워크플로는 스무스니스를 읽는데 대부분의 텍스처 도구는 러프니스를 씁니다. 반전은 간단한 계산이지만 바이트가 살아남아야 합니다. 텍스처 랩은 PNG를 직접 읽으므로 저장된 값이 정확히 255 − 러프니스입니다.
Unity 메탈릭 워크플로는 스무스니스를 읽는데, glTF·Godot와 대부분의 PBR 텍스처 소스는 러프니스를 줍니다. Unity 셰이더 라이브러리는 지각 러프니스를 1 − 스무스니스로 정의하므로 변환은 정확한 반전입니다. 스무스니스 = 1 − 러프니스, 8비트 PNG로는 255 − 값입니다(러프니스 80 → 스무스니스 175). 리니어 데이터 상태에서 반전하고, 결과를 Unity가 읽는 곳, 곧 URP·내장 메탈릭 맵의 알파나 HDRP 마스크 맵의 알파에 넣으세요. Nerulio는 브라우저에서 채널을 바이트 단위로 정확히 반전하며(측정함), Unity 가져오기는 실행하지 않았습니다.

- Channel PNGs측정 확인· numpy
- Normal map측정 확인· numpy
- Packed mask / ORM측정 확인· Pillow
- Engine import미검증
러프니스·스무스니스와 감마가 중요한 이유
두 맵은 같은 성질을 반대쪽에서 나타냅니다. 러프니스 0은 거울, 1은 완전히 거칢이고, 스무스니스 1이 거울입니다. Unity 렌더 파이프라인 셰이더 라이브러리의 PerceptualSmoothnessToPerceptualRoughness는 1 − 스무스니스를 돌려주고, 그 뒤에야 값을 제곱합니다(PerceptualRoughnessToRoughness). 두 맵 모두 아티스트가 칠하는 지각 값을 저장하므로 반전만 하면 되고 제곱이나 제곱근은 하지 않습니다.
반전이 정확한 것은 리니어 데이터일 때뿐입니다. 러프니스 맵의 바이트는 색이 아니라 숫자입니다. 색 관리를 하는 편집기나 sRGB를 켠 임포터처럼 어디서든 sRGB로 취급되면 값이 움직입니다. 스무스니스 바이트 175는 리니어 데이터로는 0.686이지만 sRGB로 디코딩하면 약 0.429입니다. 그러니 결과는 sRGB (Color Texture)를 끄고 가져오고, 감마 곡선으로 "보정"하지 마세요.
스무스니스가 들어갈 곳. URP Lit은 Metallic Map의 알파(Smoothness › Source Metallic Alpha, 기본값)나 베이스 맵의 알파에서 읽습니다. URP 채널 패킹 텍스처와 내장 Standard 셰이더의 메탈릭 맵은 A에, HDRP 마스크 맵도 A에 담습니다. 회색 스무스니스 PNG 한 장은 커스텀 셰이더나 패킹에만 쓸모가 있습니다.
글로스(glossiness) 맵은 이미 스무스니스입니다. 그래서 Nerulio의 이름 규칙은 gloss를 스무스니스로 분류하며, 반전하면 러프니스로 되돌아갑니다.
- 러프니스
- 0 = 거울처럼 매끈, 1(255) = 완전히 거칢. glTF·Godot·Unreal의 규약.
- 스무스니스
- Unity의 반대값: 1 − 러프니스.
- 지각 러프니스
- 칠해서 저장하는 값. 엔진은 조명 계산 전에 제곱합니다.
- 리니어(비색상) 데이터
- sRGB 디코딩 없이 저장된 그대로 쓰는 값.
예시: 숫자로 보기
러프니스 바이트 네 개를 랩이 쓰는 방식 그대로 반전한 값입니다.
러프니스 바이트 러프니스 스무스니스 = 1 − r 스무스니스 바이트 (255 − v)
0 0.000 1.000 255
80 0.314 0.686 175
128 0.502 0.498 127
255 1.000 0.000 0
같은 바이트 175를 sRGB (Color Texture) 켠 채로 가져오면:
175 / 255 = 0.686 → sRGB 디코딩 → 0.429 (눈에 띄게 거친 표면)두 번 반전하면 원래 바이트로 돌아오므로 변환에 손실이 없습니다. 랩은 내려받은 파일에서 저장된 평면이 모든 텍셀에서 255 − 러프니스와 같음을 측정했습니다.
러프니스에서 Unity 스무스니스로
| 가진 것 | Nerulio에서 | Unity에서 |
|---|---|---|
| 회색 러프니스 PNG | 채널: 러프니스로 표시된 채널을 반전해 저장 | 회색 스무스니스 맵(패킹이나 커스텀 셰이더용) |
| 러프니스 + 메탈릭 PNG | 마스크 패커, "Unity 메탈릭+스무스니스" 프리셋: R ← 메탈릭, A ← 러프니스 반전 | URP·내장: Metallic Map, 스무스니스는 Metallic Alpha에서 |
| 러프니스 + 메탈릭 + AO(+ 디테일) | 마스크 패커, "Unity HDRP 마스크" 프리셋: R 메탈릭, G AO, B 디테일 또는 0, A 러프니스 반전 | HDRP Lit: Mask Map |
| ORM 텍스처(G에 러프니스) | 채널, ORM 배치: G 반전 후 저장, 그다음 A에 패킹 | 메탈릭 맵이나 마스크 맵의 알파 |
| 글로스·glossiness 맵 | 반전할 것 없음: 이미 스무스니스 | 그대로 A에 패킹 |
이렇게 작동합니다
- 정확히 255 − v를 쓰는 채널 반전(내려받은 파일을 numpy로 확인).
- 브라우저 캔버스라면 잃었을 완전히 투명한 텍셀 아래의 바이트 유지.
- Unity HDRP(마스크 맵)나 URP(알파의 메탈릭 + 스무스니스)에서의 의미와 함께 채널 미리보기.
- 패커로 이어서: 스무스니스는 URP 메탈릭 맵이나 HDRP 마스크 맵의 알파에 들어갑니다.
사용 방법
- 러프니스 맵(PNG)을 끌어다 놓습니다.
- 채널을 반전합니다.
- 스무스니스 맵을 받거나 마스크 패커를 엽니다.
- Unity 프리셋으로 메탈릭(HDRP는 AO도)과 함께 패킹합니다.
받게 되는 파일
| 파일 | 용도 |
|---|---|
rock_roughness-g-inverted-roughness.png | 반전한 평면을 담은 8비트 회색 PNG. 이름은 원래 역할(roughness) 앞에 inverted-가 붙으므로 내용은 스무스니스입니다. |
rock_metallic-mask.png | 마스크 패커 결과: R에 메탈릭, A에 반전한 러프니스(HDRP면 AO와 디테일도). Unity 머티리얼에 바로 씁니다. |
Unity가 읽는 곳에 스무스니스 넣기
Unity 단계는 Unity 6·HDRP 17.1 문서를 따르며, Nerulio가 가져오기를 실행하지는 않았습니다.
- 마스크 패커를 열고 메탈릭 맵을 먼저, 러프니스 맵을 두 번째로 넣은 뒤 "Unity 메탈릭+스무스니스"(URP·내장)나 "Unity HDRP 마스크"를 고릅니다(HDRP에서 디테일 마스크가 없으면 AO를 G에, B는 0으로).
- A 채널의 "반전"을 체크하고 패킹한 PNG를 받습니다. URP에서 앰비언트 오클루전도 쓰려면 직접 배치로 바꿔 AO 파일을 G에 둡니다.
- Unity에서 텍스처를 선택해
sRGB (Color Texture)를 끕니다. HDRP는 Texture Type도Default로 둡니다. - URP Lit: Workflow Mode
Metallic, 텍스처를 Metallic Map(G에 AO가 있으면 Occlusion Map에도)에 지정하고 Smoothness › Source는Metallic Alpha로 둡니다. - HDRP Lit: Surface Inputs의 Mask Map에 지정합니다. 결과를 조정해야 하면 Smoothness Remapping 슬라이더로 범위를 다시 맞춥니다.
결과 확인
- 패킹한 PNG를 채널 분리기에서 풉니다. A는 어디서나 255 − 러프니스여야 합니다(러프니스 80인 텍셀은 175).
- Unity에서 거친 곳(흐리고 넓은 하이라이트)과 연마된 곳(날카로운 하이라이트)을 비교합니다. 반대라면 반전하지 않았거나 두 번 반전한 것입니다.
- 텍스처 인스펙터에서 패킹 맵의
sRGB (Color Texture)가 꺼져 있어야 합니다.
문제 해결
| 증상 | 유력한 원인 | 확인 방법 | 해결 |
|---|---|---|---|
| 전부 젖은 듯하거나 거울처럼 보임 | 러프니스를 반전 없이 알파에 넣음 | A를 풀어 러프니스 맵과 비교하면 반전되지 않고 똑같음 | A의 "반전"을 체크하고 다시 패킹 |
| 텍스처링 프로그램보다 표면이 거칠어 보임 | 패킹 맵을 sRGB로 가져옴(175가 약 0.429로 읽힘) | Unity 인스펙터에서 sRGB (Color Texture)가 켜짐 | 끄기. 감마 곡선으로 보정하지 않기 |
| 스무스니스 맵이 효과가 없음 | Smoothness › Source가 Albedo Alpha이거나, 어떤 도구가 알파 채널 없이 PNG를 저장함 | 머티리얼 인스펙터 확인, PNG를 풀어 A가 상수 255가 아닌지 확인 | Source를 Metallic Alpha로, 패킹 맵은 RGBA PNG로 저장 |
| 반짝이던 곳이 거칠어진 글로스 맵 | 글로스 맵은 이미 스무스니스인데 반전함 | 원본 파일 이름에 gloss나 glossiness가 있음 | 반전 없이 패킹 |
| URP 머티리얼이 주변광에서 어두워짐 | 패킹 텍스처를 Occlusion에도 지정했는데 G가 0으로 쓰임 | G를 풀면 상수 0 | 직접 배치로 AO 파일을 G에 두거나 Occlusion Map 비우기 |
다른 방법
| 방법 | 이럴 때 더 낫습니다 |
|---|---|
| 이미지 편집기에서 반전 | 색 관리를 하지 않는 편집기에서 8비트 회색 러프니스 맵을 다룰 때. 반전 결과는 똑같이 255 − v지만 알파로 패킹하는 것은 직접 해야 합니다. |
| Shader Graph (Unity) | 러프니스 텍스처를 그대로 두고 셰이더에서 반전하고 싶을 때. Unity URP 문서는 기본 패킹과 다른 배치에 Shader Graph를 안내합니다. |
| 채널 분리기 | 러프니스가 다른 패킹 텍스처(ORM의 G) 안에 있어 먼저 꺼내야 할 때. |
출력 파일과 검증 방법
"측정 확인"은 내려받은 파일을 페이지 밖에서(Pillow·numpy·별도 파서) 다시 열어 그 속성을 측정했다는 뜻입니다. 게임 엔진에서 불러오는 것은 시험하지 않았습니다.
| 대상 | 파일 | 검증 |
|---|---|---|
| Channel PNGs | <name>-r/g/b/a.png (8-bit grey) | 측정 확인 numpy채널마다 바이트가 같고 완전히 투명한 텍셀 아래의 RGB도 유지됩니다. |
| Normal map | PNG · OpenGL (+Y) or DirectX (−Y) | 측정 확인 numpy디코딩한 벡터가 단위 길이(최대 오차 0.0002)이고, OpenGL과 DirectX는 초록 채널만 다릅니다. |
| Packed mask / ORM | Unity HDRP mask · URP metallic · ORM (glTF, Godot) | 측정 확인 Pillow패킹된 바이트 확인: ORM 프리셋, AO 10 / 러프니스 80 / 메탈릭 220 → (10, 80, 220, 255). |
| Engine import | Unity · Unreal · Godot | 미검증어떤 엔진에서도 불러오지 않았습니다. |
검증 근거
채널 분리가 네 채널 모두 바이트 동일(최대 차이 0), 투명 텍셀 2048개가 RGB 유지. 가장자리 번짐은 알파 0인 텍셀 448개만 바꾸고 알파 바이트는 하나도 건드리지 않음. OpenGL ↔ DirectX는 초록(255 − g)만 다름. 변환한 노멀은 단위 벡터.
한계
- 정확한 채널 바이트는 PNG에서만 보장됩니다. JPEG·WebP는 브라우저가 디코딩하며 "바이트 동일 아님"으로 표시합니다.
- 인터레이스 PNG와 16비트 출력은 지원하지 않습니다. 정확 경로는 3,355만 픽셀까지입니다.
- 노멀맵의 규약은 픽셀로 알아낼 수 없고 변환만 할 수 있습니다.
- Unity·Unreal·Godot에서 불러오지 않았습니다. 채널 순서는 각 문서와 엔진 소스에 근거합니다.
버전과 출처
텍스처 랩에서 측정(docs/TEXTURE-LAB.md): 러프니스 맵의 G를 반전해 내려받으면 평면이 정확히 255 − 러프니스였고, 단계 화면에 원본 → 결과가 나란히 나왔습니다. 패커의 R 반전 점검은 AO 10에서 (245, 80, 220, 255)를 냈습니다. 1 − 스무스니스 관계는 Unity 렌더 파이프라인 소스에서, 채널 위치와 가져오기 설정은 아래 Unity 문서에서 왔습니다. Unity 가져오기는 실행하지 않았습니다.
참고한 공식 문서
자주 묻는 질문
Unity는 스무스니스를 어느 채널에서 읽나요?
URP 메탈릭은 메탈릭 맵의 알파, HDRP 마스크 맵도 알파입니다(R 메탈릭·G AO·B 디테일 마스크). 두 순서 모두 Unity 문서에 근거하며 랩에 인용합니다.
Unity에서 불러와 봤나요?
아니요. 바이트는 확인했지만 여기서 Unity 가져오기는 하지 않았습니다.
무료인가요? 계정이 필요한가요?
이 페이지의 기능은 모두 무료이며 계정 없이 쓸 수 있습니다. 워터마크나 막혀 있는 내보내기가 없습니다.
스프라이트가 업로드되나요?
아니요. Studio는 이 브라우저 탭 안에서 디코딩·패킹·내보내기를 합니다. 프로젝트는 브라우저(IndexedDB)에 자동 저장되며 .nerulio 파일로 저장할 수 있습니다.
Aseprite나 엔진 플러그인을 설치해야 하나요?
아니요. .aseprite 파일은 브라우저에서 읽고 씁니다. 엔진별 번들에는 그 엔진에 필요한 것이 들어 있습니다(Godot는 가져오기 설정과 씬, Unity와 Godot 타일셋은 작은 편집기 스크립트).