by 꽈배기
두 요소를 합성하는 방식의 쉐이더 모델로
#if UNITY_VERSION >= 202120
return UniversalFragmentBlinnPhong(lightingInput,surfaceInput);
#else
return UniversalFragmentBlinnPhong(lightingInput,surfaceInput.albedo
,float4(surfaceInput.specular,1),surfaceInput.smoothness,0,surfaceInput.alpha);
위 내용은 UniversalFragmentBlinnPhong 함수로 블린 퐁 라이트 연산 모델을 수행한다.
ShaderLibrary/Lighting.hlsl 패키지에 포함되어있음.
위를 보면 #if로 되어있는데 이는 해시태그로 유니티의 버전에 따라 다른 쉐이더 형식이 작동되도록 짠것이다.
여기 들어가는 인자는 아래와 같다.
InputData lightingInput = (InputData)0;
// 현재 fragment에서 메쉬의 위치와 방향에 대한 정보를 저장
SurfaceData surfaceInput = (SurfaceData)0;
// material의 물리적 속성들을 가지고 있음.
struct SurfaceData {
half3 albedo;
half3 specular;
half metallic;
half smoothness;
half3 normalTS;
half3 emission;
half occlusion;
half alpha;
// And added in v10 :
half clearCoatMask;
half clearCoatSmoothness;
};
struct InputData {
float3 positionWS;
half3 normalWS;
half3 viewDirectionWS;
float4 shadowCoord;
half fogCoord;
half3 vertexLighting;
half3 bakedGI;
float2 normalizedScreenSpaceUV;
half4 shadowMask;
};
specular highlight 빛의 연산을 위한 worldSpacePos normal 추가
struct Attribute
{
float3 positionOS: POSITION;
float3 normalOS:NORMAL; // specular highlight 연산에 필요한 노말
float2 uv : TEXCOORD0;
};
struct Varyings
{
float4 posCS: SV_POSITION;
float3 normalWS: TEXCOORD1; //TEXCOORD
// 태그를 쓰는 이유는 래스터라이저에서 TEXCOORD로 태그된 모든 필드를 보간하기 떄문임.
float2 uv : TEXCOORD0;
};
정점의 노말이 정점 조립 단계에서 추출되어 Attribute로 들어온다.
들어온 노말은 normalOS로 vertex funtion에서 처리된다.
좌표공간을 변경한 노말은 래스터라이저의 대상이 되어 보간이 진행된다.
여기서 서로 반대 방향을 가진 노말의 사이를 보간 진행될 때, 아래 그림처럼 vector의 값이 변경된다.
라이트 연산에서는 조명의 쿼리티를 위해 모든 벡터를 정규 벡터 (길이가 1)로 만들어주는 노말라이즈 과정을 거쳐 부드러운 라이트를 만들어 내 준다 (제곱근 계산이 있어 꽤 무거운 연산이라고 한다)
정규화가 진행된 벡터
마지막으로 specular light는 view dirction에 영향을 받아 바라보는 각도에 따라 하이라이트 위치가 미세하게 변한다.
이를 계산해주기 위해 아래와 같은 매크로를 사용한다.
lightingInput.viewDirectionWS =
GetWorldSpaceNormalizeViewDir(lightingInput.positionWS);
// 뷰 방향으로부터 정점의 월드까지 방향 벡터 (뷰 위치 - WS)
GetWorldSpaceNormalizeViewDir 매크로는 WS를 이용 뷰어를 가르키는 벡터를 계산함.
float3 GetWorldSpaceViewDir(float3 positionWS)
{
if (IsPerspectiveProjection())
{
return GetCurrentViewPosition() - positionWS;
// 카메라의 월드 위치와 정점의 월드 위치를 계산
}
else
{
return -GetViewForwardDir();
}
}
highlight가 나온 모습
광원을 직접적으로 반사하면서 발생하는 표면의 하이라이트를 뜻한다.
즉 강도가 높을수록 빛을 강하게 반사한다.
맵 중에서 gloss map 이란게 있는데, 검은색은 0 흰색은 1인 alpha 맵으로 1에 가까울수록 반사 강도가 높아진다