오늘은 커스텀으로 디퓨즈, 앰비언트 , 스페큘러를 텍스처맵핑을 구현해보려한다.
가르쳐주는 블로그가아닌 공부하는 블로그이기 때문에 자세한 내용은 생략하고,
우선 차근차근 텍스처부터 씌워보도록 하겠다
위의 모델에 텍스처를 입히려면 일단 머테리얼이 필요한데
일단 DuckMat 머테리얼과 DuckShader라는 언릿 쉐이더를 추가해보았다. 당연히 DuckMat는 DuckShader를 사용
기본적으로 세팅되있는 쉐이더를 깔끔하게 Fog 설정부분을 삭제해준뒤에.. vert frag 쉐이더를 보면..
이와 같은 걸 볼 수 있다.
_MainTex는 프로퍼티에서 받아온 텍스처!
결국 이 부분이 텍스처를 넣는 부분이라는 것!
appdata 의 uv 좌표에 texture를 씌어넣는 작업이
o.uv = TRNASFORM_TEX(v.uv, _MainTex);이고
마지막으로 frag쉐이더에서
tex2D(_MainTex, i.uv);를 해줌으로써 해당 픽셀의 색상에 텍스처의 해당 픽셀 색상을 집어넣음으로서 결정!
참고 : _MainTex_ST 라는 프로퍼티에 추가도 하지 않은 변수가 있는데 이게 TRNSFORM_TEX를 사용하기 위해 존재한다고합니당 ㅇㅇ 일단 초보니까 넘어가도록 하죵
이제 디퓨즈,앰비언트를 계산해보자!
디퓨즈를 사용하기 위해선
우선 빛의 방향, 노멀벡터 가 필요 ( 빛의 밝기를 정하기 위해서)
vert 쉐이더에서
worldNormal = float3 worldNormal = UnityObjectToWorldNormal(v.normal);
// 월드 노멀벡터계산
o.worldNormal = worldNormal;
o.vertexWorld = mul(unity_ObjectToWorld, v.vertex);
//mul함수는 두행렬의 곱을 계산하는 것 unity_ObjectToWorld는 오브젝트의 모델행렬
frag 쉐이더에서
float3 normalVector = normalize(i.worldNormal);
float3 lightDirection = normalize(UnityWorldSpaceLightDir(i.vertexWorld));
float nl = max(0.0f, dot(lightDirection, normalVector)); //위를 통해서 밝기를 찾아내서
float diffuseTerm = nl*_Color*tex*_LightColor0;//디퓨즈의 컬러를 구한다!
_LightColoor0는 셰이더 내장 변수로 lightColor를 반환함
출처)
https://docs.unity3d.com/kr/530/Manual/SL-UnityShaderVariables.html
디퓨즈는 이대로 되었고
다음은 앰비언트인데 앰비언트는 cutOff의 역할을 수행한다고한다 ( 조명이 없어도 최소밝기 )
그래서
float nl = max(_Ambient, dot(lightDirection, normalVector));
프로퍼티에_Ambient라는 Range(0,1)값을 추가해서 이런식으로 디퓨즈에서 사용하면 된다.
위의 코드를 수행하고나면??
오오.. 영롱하군여
앰비언트 값을 변경해주면 이렇게된다
이제 마지막으로 스펙큘러!
스펙큘러는 퐁쉐이딩을 사용할 예정이고
프로퍼티에 추가해야할 값
_Shininess("Shininess", Float) = 10.0
_SpecCol ("SpecColor", Color) = (1,1,1,1)
frag 쉐이더에서 처리해줘야할 일
float3 reflectDirection = normalize(reflect(-lightDirection, normalVector));
//정반사 빛의 방향
float3 specularNL = max(0.0, dot(viewDirection, reflectDirection));
//해당 frag의 정반사된 빛의 밝기
float3 specular = pow(specularNL, _Shininess);
//원하는만큼 제곱해서 더밝게하기
float4 specularTerm = float4(specular, 1.0f)*_SpecCol * _LightColor0;
//결과
//참고로 specularNL과 specular는 원래 float만 해도되는데 내가 공부했던 책에는 이렇게 되있어서 올림..
float specularNL = max(0.0f, dot(viewDirection, reflectDirection));
float specular = pow(specularNL, _Shininess);
float4 specularTerm = specular *_SpecCol * _LightColor0;
이렇게해도 상관없음
요로코롬 해주면?
float4 finalCol = diffuseTerm+specularTerm;
return finalCol;
해줬을시에
완성!
역시 쉐이더쪽은 뭔가 보이는게 확실해서 너무 재밌는거같다
번외) 다중 라이팅을 지원하려면 어떻게해야하는가??
오른쪽이 다중라이팅을 지원하지 않는 지금까지 만든 쉐이더이고
왼쪽은 다중라이팅을 지원하는 쉐이더이다.
이를 만드려면
기존 페스에
#pragma multi_compile_fwdbase를 추가하고
새로운 페스를 추가하고 복붙한뒤에
"LightMode" = "FowardBase" -> "LightMode" = " ForwardAdd"
Blend One One
#pragma multi_compile_fwdadd
을 추가한 뒤
새로운 페스의 디퓨즈값에 Ambient값을 0.0으로 해주면 된다.