9148c358d0
Topic_Agent/Topic_Blog/Topics/Topics_Biz/Topics_Meeting/Topics_Rag의 마크다운 지식 문서를 Topic_General/Topic_Programming/Topic_Graphic/Topic_Business 4개 카테고리로 재분류. - 중복 제거: frontmatter의 status:duplicate/merged + duplicate_of/redirect_to 필드로 자기 자신을 중복으로 선언한 리다이렉트 stub 1032개 제거, 완전 동일 내용 파일 472개 제거, 동일 파일명·다른 내용 충돌 시 더 큰(완전한) 버전만 유지(162개 제거) — 총 1639개 중복 제거. - 분류: 폴더 단위로 명확한 항목(AI_and_ML/Coding/Architecture 등 → Programming, Comfyui/Visual_Effects → Graphic, Topics_Biz/Topics_Meeting/사업 등 → Business, Poetic_Blog_Writing/창의성/Game_Design 등 → General)은 폴더 우선순위로, 나머지 혼재 폴더(Topic_Agent/Topic_Blog/Topics 루트/Thinking & Reasoning/Other/UI_UX_Assets)는 title/tags 키워드 스코어링으로 파일 단위 분류(불명확한 경우 General로 폴백). 원본 폴더명은 "From_*" 서브폴더로 보존해 추적 가능성 유지. - 최종 배치: Programming 2784 / General 1608 / Graphic 285 / Business 249 = 4926개 문서. - 에이전트 운영 상태(.astra/.agent/.obsidian/sessions/memory/_company/docs/lessons/_shared/src)는 지식 콘텐츠가 아니므로 재분류 대상에서 제외하고 원위치 유지. - Topics/Topic_email(상위 보호 폴더 Topic_email과 파일명 100% 중복) 삭제 — 보호 폴더 자체는 미변경. - 완전히 비게 된 Topic_Agent/Topic_Blog/Topics_Biz/Topics_Rag 폴더 제거.
186 lines
6.2 KiB
Markdown
186 lines
6.2 KiB
Markdown
---
|
||
id: wiki-2026-0508-pbr
|
||
title: PBR (Physically Based Rendering)
|
||
category: 10_Wiki/Topics
|
||
status: verified
|
||
canonical_id: self
|
||
aliases: [Physically Based Rendering, PBR shading, metallic-roughness]
|
||
duplicate_of: none
|
||
source_trust_level: A
|
||
confidence_score: 0.95
|
||
verification_status: applied
|
||
tags: [graphics, shading, rendering, materials]
|
||
raw_sources: []
|
||
last_reinforced: 2026-05-10
|
||
github_commit: pending
|
||
tech_stack:
|
||
language: hlsl
|
||
framework: unreal-engine
|
||
---
|
||
|
||
# PBR (Physically Based Rendering)
|
||
|
||
## 매 한 줄
|
||
> **"매 빛-표면 상호작용을 물리법칙(에너지 보존, microfacet, Fresnel)에 따라 모델링"**. 매 2014 Disney/Burley BRDF + Unreal/Frostbite 의 industry standardization → 매 2026 의 모든 real-time 엔진의 default. 매 metallic-roughness workflow 의 universal.
|
||
|
||
## 매 핵심
|
||
|
||
### 매 핵심 원칙
|
||
1. **에너지 보존**: 매 reflected + transmitted ≤ incoming.
|
||
2. **Fresnel**: 매 grazing angle에서 reflectance ↑.
|
||
3. **Microfacet**: 매 표면을 미세 mirror 의 분포로 모델 (NDF + G + F).
|
||
4. **Linear-space lighting**: 매 sRGB → linear → tonemap.
|
||
|
||
### 매 BRDF 구조 (Cook-Torrance)
|
||
```
|
||
f = kd * Lambert + ks * (D * G * F) / (4 * NoL * NoV)
|
||
```
|
||
- **D**: Normal Distribution Function — Trowbridge-Reitz GGX (default).
|
||
- **G**: Geometry / Shadowing — Smith / Schlick-GGX.
|
||
- **F**: Fresnel — Schlick approx.
|
||
- **kd**: diffuse weight = (1 - F) * (1 - metallic).
|
||
|
||
### 매 workflow
|
||
- **Metallic-Roughness** (Unreal, glTF, Substance default): albedo + metallic + roughness + normal + ao.
|
||
- **Specular-Glossiness** (legacy): 매 deprecated.
|
||
- **Clearcoat / Sheen / Anisotropy / Subsurface** = 매 extensions (glTF KHR\_\*).
|
||
|
||
### 매 IBL (Image-Based Lighting)
|
||
- 매 environment HDR → 매 prefiltered specular cubemap (split-sum approximation) + 매 diffuse irradiance.
|
||
- 매 BRDF LUT (NoV × roughness) precompute.
|
||
|
||
## 💻 패턴
|
||
|
||
### Core PBR PS (HLSL, UE-style)
|
||
```hlsl
|
||
float3 F_Schlick(float3 F0, float VoH) {
|
||
return F0 + (1 - F0) * pow(1 - VoH, 5);
|
||
}
|
||
|
||
float D_GGX(float NoH, float a) {
|
||
float a2 = a * a;
|
||
float d = NoH * NoH * (a2 - 1) + 1;
|
||
return a2 / (PI * d * d);
|
||
}
|
||
|
||
float V_SmithGGX(float NoV, float NoL, float a) {
|
||
float a2 = a * a;
|
||
float gv = NoL * sqrt(NoV * NoV * (1 - a2) + a2);
|
||
float gl = NoV * sqrt(NoL * NoL * (1 - a2) + a2);
|
||
return 0.5 / (gv + gl + 1e-5);
|
||
}
|
||
|
||
float3 PBR(float3 albedo, float metallic, float roughness,
|
||
float3 N, float3 V, float3 L, float3 lightColor) {
|
||
float3 H = normalize(V + L);
|
||
float NoL = saturate(dot(N, L));
|
||
float NoV = saturate(dot(N, V));
|
||
float NoH = saturate(dot(N, H));
|
||
float VoH = saturate(dot(V, H));
|
||
|
||
float a = roughness * roughness;
|
||
float3 F0 = lerp(0.04, albedo, metallic);
|
||
|
||
float D = D_GGX(NoH, a);
|
||
float V_ = V_SmithGGX(NoV, NoL, a);
|
||
float3 F = F_Schlick(F0, VoH);
|
||
|
||
float3 spec = D * V_ * F;
|
||
float3 kd = (1 - F) * (1 - metallic);
|
||
float3 diff = kd * albedo / PI;
|
||
|
||
return (diff + spec) * lightColor * NoL;
|
||
}
|
||
```
|
||
|
||
### IBL (split-sum)
|
||
```hlsl
|
||
float3 IBL(float3 N, float3 V, float roughness, float3 albedo, float metallic,
|
||
TextureCube prefiltered, Texture2D brdfLUT, TextureCube irradiance) {
|
||
float NoV = saturate(dot(N, V));
|
||
float3 R = reflect(-V, N);
|
||
|
||
float3 F0 = lerp(0.04, albedo, metallic);
|
||
float3 F = F_Schlick(F0, NoV);
|
||
|
||
float mip = roughness * 6.0; // 매 mip count - 1
|
||
float3 specIBL = prefiltered.SampleLevel(s, R, mip).rgb;
|
||
float2 brdf = brdfLUT.Sample(s, float2(NoV, roughness)).rg;
|
||
float3 spec = specIBL * (F * brdf.x + brdf.y);
|
||
|
||
float3 kd = (1 - F) * (1 - metallic);
|
||
float3 diff = kd * albedo * irradiance.Sample(s, N).rgb;
|
||
|
||
return diff + spec;
|
||
}
|
||
```
|
||
|
||
### glTF PBR material loader (Three.js / WebGPU)
|
||
```ts
|
||
const mat = new THREE.MeshPhysicalMaterial({
|
||
map: albedo, // sRGB
|
||
metalnessMap: metalRough, normalMap: normal,
|
||
roughnessMap: metalRough, // packed: G=rough, B=metal (glTF spec)
|
||
aoMap: ao,
|
||
clearcoat: 0.5, clearcoatRoughness: 0.1, // KHR_materials_clearcoat
|
||
sheen: 0.3, sheenColor: new THREE.Color(0xff8888), // KHR_materials_sheen
|
||
});
|
||
```
|
||
|
||
### Disney "Principled" BSDF param mapping
|
||
```python
|
||
# Blender Principled BSDF — 매 artist-friendly
|
||
mat.inputs["Base Color"] = albedo
|
||
mat.inputs["Metallic"] = metallic # 0 dielectric, 1 metal
|
||
mat.inputs["Roughness"] = roughness # 0 mirror, 1 chalk
|
||
mat.inputs["IOR"] = 1.5 # dielectric F0 = ((ior-1)/(ior+1))^2
|
||
mat.inputs["Specular IOR Level"] = 0.5 # 매 dielectric strength
|
||
mat.inputs["Coat Weight"] = 0.0
|
||
mat.inputs["Sheen Weight"] = 0.0
|
||
mat.inputs["Subsurface Weight"] = 0.0
|
||
```
|
||
|
||
### Texture authoring rules
|
||
```
|
||
albedo: sRGB, no lighting baked, dielectric ≥ 30 sRGB, metal ≥ 200 sRGB
|
||
metallic: linear, binary 가까이 (0 or 1) — 매 dielectric/metal 의 mix X
|
||
roughness: linear, 0.04 floor (perfect mirror 회피)
|
||
normal: linear, OpenGL or DirectX convention 통일
|
||
ao: linear, multiplied with diffuse only
|
||
```
|
||
|
||
## 매 결정 기준
|
||
| 상황 | Approach |
|
||
|---|---|
|
||
| Real-time game | Metallic-Roughness GGX + IBL |
|
||
| Skin / wax | + Subsurface scattering |
|
||
| Car paint / lacquer | + Clearcoat |
|
||
| Cloth / velvet | + Sheen |
|
||
| Brushed metal / hair | + Anisotropy |
|
||
| Path-traced offline | Disney Principled (super-set) |
|
||
|
||
**기본값**: 매 GGX + Smith + Schlick + metallic-roughness + IBL split-sum.
|
||
|
||
## 🔗 Graph
|
||
|
||
## 🤖 LLM 활용
|
||
**언제**: 매 photoreal real-time/offline rendering. 매 cross-engine asset (glTF). 매 artist 의 physical intuition.
|
||
**언제 X**: 매 stylized non-photoreal (NPR/toon) — 매 PBR 위에 override 또는 별도 model.
|
||
|
||
## ❌ 안티패턴
|
||
- **gamma 안 맞춤**: 매 albedo 의 linear 처리 → 매 wash-out / overbright.
|
||
- **Metallic 0.5**: 매 binary 가까이가 정답. 0.5 = 매 무의미 (전이 영역 없음).
|
||
- **Roughness 0.0**: 매 NaN / fireflies. floor 0.04 + clamp.
|
||
- **AO multiplied with specular**: 매 specular AO 별도 계산 필요.
|
||
- **F0=0.04 for everything**: 매 metal은 albedo 색이 F0.
|
||
|
||
## 🧪 검증 / 중복
|
||
- Verified (Disney 2012 Burley paper, UE5 docs, Filament PBR pipeline doc, glTF 2.0 spec, Real-Time Rendering 4th ed).
|
||
- 신뢰도 A.
|
||
|
||
## 🕓 Changelog
|
||
| 날짜 | 변경 |
|
||
|---|---|
|
||
| 2026-05-08 | Phase 1 |
|
||
| 2026-05-10 | Manual cleanup — Cook-Torrance + IBL + glTF workflow |
|