2020년 봄 쯤 테스트.
구현 코드는 매우 단순하게 처리 된 형식.
// Specular term
half perceptualRoughness = SmoothnessToPerceptualRoughness(smoothness);
half roughness = PerceptualRoughnessToRoughness(perceptualRoughness);
half a = roughness;
half a2 = a*a;
half d = nh * nh * (a2 - 1.h) + 1.00001h;
half specularTerm = a2 / (max(0.1h, lh*lh) * (roughness + 0.5h) * (d * d) * 4);
float Lobe0Roughness = max(saturate(specularTerm ), 0.002f);
float Lobe1Roughness = clamp(specularTerm, 0.0, 100.0) * _LobeWeight;
#if defined(DUAL_LOBE_GGX)
float sAO = saturate(-0.3f + nv * nv);
sAO = lerp(pow(ao, 8.00f), 1.0f, sAO);
half SpecularOcclusion = sAO;
specularTerm = (Lobe0Roughness / 2 + Lobe1Roughness) * SpecularOcclusion ;
return half4(specularTerm.xxx,1);
#else
specularTerm = clamp(specularTerm, 0.0, 100.0); // Prevent FP16 overflow on mobiles
#endif
2025년 구현 형식.
#ifndef DUAL_SPECULAR_LOBE_BRDF_INCLUDED
#define DUAL_SPECULAR_LOBE_BRDF_INCLUDED
float3 DualSpecularLobe(float3 N, float3 V, float3 L, float Roughness1, float Roughness2, float Weight1, float3 F0)
{
// 뷰 벡터 정규화
V = normalize(V);
// 라이트 벡터 정규화
L = normalize(L);
// 뷰(V)와 라이트(L) 사이의 반각 벡터(H)
float3 H = normalize(V + L);
// 슬릭 근사화(Schlick Approximation)를 사용한 프레넬 항
float3 F = F0 + (1.0 - F0) * pow(1.0 - saturate(dot(V, H)), 5.0);
// 두 개의 GGX 배포 기능(NDF)
float D1 = GGX_Distribution(N, H, Roughness1);
float D2 = GGX_Distribution(N, H, Roughness2);
// 기하학/가시성 항, Cook-Torrance 모델 기반
float G = Geometry_Smith(N, V, L, Roughness1);
// 두 로브를 결합
float Lobe1 = Weight1 * D1 * G / (4.0 * max(0.001, dot(N, V)) * max(0.001, dot(N, L)));
float Lobe2 = (1.0 - Weight1) * D2 * G / (4.0 * max(0.001, dot(N, V)) * max(0.001, dot(N, L)));
// 두 로브의 가중합
return F * max(0.0, dot(N, L)) * (Lobe1 + Lobe2);
}
// GGX 디스트리뷰션 펑션
float GGX_Distribution(float3 N, float3 H, float roughness)
{
float alpha = roughness * roughness;
float alpha2 = alpha * alpha;
float NdotH = saturate(dot(N, H));
float denom = NdotH * NdotH * (alpha2 - 1.0) + 1.0;
return alpha2 / (3.14159265359 * denom * denom);
}
// 기하학 항 (Smith)
float Geometry_Smith(float3 N, float3 V, float3 L, float roughness)
{
float k = (roughness + 1.0) * (roughness + 1.0) * 0.125;
return Geometry_SchlickGGX(N, V, k) * Geometry_SchlickGGX(N, L, k);
}
float Geometry_SchlickGGX(float3 N, float3 V, float k)
{
float NdotV = saturate(dot(N, V));
return NdotV / (NdotV * (1.0 - k) + k);
}
#endif
'UNITY3D' 카테고리의 다른 글
Cursor AI IDE 와 UNITY3D 연동하여 개발하기. (0) | 2025.03.02 |
---|---|
모바일 스킨 셰이더 개발 시 참고 사항. 2019 버전. (0) | 2025.02.18 |
ActorSkinLitGUI (0) | 2025.02.17 |
유니티 6.2 렌더링 패스 (0) | 2025.02.10 |
Scene Templates 좀 알아보자. (0) | 2025.02.05 |