반응형
이미지 한 장을 받는 것을 만들어준다.
----
블린퐁 조명을 만들기 위해서는 공식이 존재한다.
반사 벡터를 구하는 공식 (리플렉션 구하는 공식)
R = 2 N(L * N) - L 이 공식이다.
이건 반사 벡터 구하는거고
우리는 좀더 간략하게 된, 블린 퐁 공식을 사용할 것이다.
하프 백터 = V + I
하프 벡터를 노멀라이즈를 해준다. (방향만)
구한 하프벡터에서 n 벡터와 Dot 연산을 해준다.
------
일단 완전 기본적인 램버트의 라이트를 만들어준다.
커스텀 라이트로
Shader "Custom/Phong"
{
Properties
{
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Normal ("Normal", 2D) = "Normal" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
#pragma surface surf _MyLambert
#pragma target 3.0
sampler2D _MainTex;
sampler2D _Normal;
struct Input
{
float2 uv_MainTex;
float2 uv_Normal;
float3 viewDir;
};
void surf (Input IN, inout SurfaceOutput o)
{
fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
o.Normal = UnpackNormal(tex2D(_Normal, IN.uv_Normal));
o.Albedo = c.rgb;
o.Alpha = c.a;
}
float4 Lighting_MyLambert(SurfaceOutput s, float3 lightDir, float atten){
float ndotl = dot(s.Normal,lightDir);
float4 final;
final.rgb = s.Albedo * ndotl;
final.a = s.Alpha;
return final;
}
ENDCG
}
FallBack "Diffuse"
}
-----
하프 백터 구해보기 -> dot 연산으로 스펙큘러 적용하기
Shader "Custom/Phong"
{
Properties
{
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Normal ("Normal", 2D) = "Normal" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
#pragma surface surf _MyLambert
#pragma target 3.0
sampler2D _MainTex;
sampler2D _Normal;
struct Input
{
float2 uv_MainTex;
float2 uv_Normal;
float3 viewDir;
};
void surf (Input IN, inout SurfaceOutput o)
{
fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
o.Normal = UnpackNormal(tex2D(_Normal, IN.uv_Normal));
o.Albedo = c.rgb;
o.Alpha = c.a;
}
float4 Lighting_MyLambert(SurfaceOutput s, float3 lightDir, float3 viewDir, float atten){
float ndotl = dot(s.Normal,lightDir);
float4 final;
float3 H = normalize(lightDir + viewDir);
float spec = saturate(dot(H,s.Normal));
return spec;
//final.rgb = s.Albedo * ndotl;
//final.a = s.Alpha;
//return final;
}
ENDCG
}
FallBack "Diffuse"
}
float4 Lighting_MyLambert(SurfaceOutput s, float3 lightDir, float3 viewDir, float atten){
float3 로 라이트 디렉션, 뷰 디렉션을 받아줘야한다.
float3 H = normalize(lightDir + viewDir);
퐁 구하는 공식으로 대입해준다.
float spec = saturate(dot(H,s.Normal));
return spec;
구한 H 값을 dot 연산을 해줘야지 spec이 나온다.
-----
final에 알베도도 섞어서 내 보내기
hader "Custom/Test"
{
Properties
{
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Normal ("Normal", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
#pragma surface surf Test noambient
#pragma target 3.0
sampler2D _MainTex;
sampler2D _Normal;
struct Input
{
float2 uv_MainTex;
float2 uv_Normal;
float3 viewDir;
};
void surf (Input IN, inout SurfaceOutput o)
{
fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
o.Normal = UnpackNormal(tex2D(_Normal,IN.uv_Normal));
o.Albedo = c.rgb;
o.Alpha = c.a;
}
float4 LightingTest(SurfaceOutput s, float3 lightDir, float3 viewDir, float atten){
float4 final;
float3 H = normalize(lightDir + viewDir);
float spec = saturate(dot(H, s.Normal));
final.rgb = s.Albedo * spec ;
final.a = s.Alpha;
return final;
}
ENDCG
}
FallBack "Diffuse"
}
---
pow 식으로 스펙큘러 정도 조절하기
Shader "Custom/Test"
{
Properties
{
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Normal ("Normal", 2D) = "white" {}
_SpecPow("SpecPow", Range(0,100)) = 0
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
#pragma surface surf Test
#pragma target 3.0
sampler2D _MainTex;
sampler2D _Normal;
float _SpecPow;
struct Input
{
float2 uv_MainTex;
float2 uv_Normal;
float3 viewDir;
};
void surf (Input IN, inout SurfaceOutput o)
{
fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
o.Normal = UnpackNormal(tex2D(_Normal, IN.uv_Normal));
o.Albedo = c.rgb;
o.Alpha = c.a;
}
float4 LightingTest(SurfaceOutput s, float3 lighDir, float3 viewDir ,float atten){
float4 final;
float3 H = normalize(lighDir + viewDir);
float spec = saturate(dot(H,s.Normal));
spec = pow(spec, _SpecPow);
final.rgb = s.Albedo * spec;
final.a = s.Alpha;
return final;
}
ENDCG
}
FallBack "Diffuse"
}
-----
스펙큘러에 색깔 넣어보기
-----
알베도 색 넣기
float4 LightingTest(SurfaceOutput s, float3 lighDir, float3 viewDir ,float atten){
float4 final;
//램버트 공식
float ndotl = saturate(dot(s.Normal, lighDir));
//스펙큘러 공식 적용
float3 H = normalize(lighDir + viewDir);
float spec = saturate(dot(H,s.Normal));
spec = pow(spec, _SpecPow);
//스팩큘러 색깔 적용
float3 SpecColor = spec * _SpecCol.rgb;
//알베도 적용
final.rgb = (ndotl * s.Albedo) + SpecColor.rgb;
final.a = s.Alpha;
return final;
}
( 램버트 공식(기본 조명) * 알베도 ) + 스펙큘러 컬러 를 해줘야한다.
내 코드
Shader "Custom/Test"
{
Properties
{
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Normal ("Normal", 2D) = "white" {}
_SpecPow("SpecPow", Range(0,100)) = 0
_SpecCol("SpecColor", Color) = (1,1,1,1)
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
#pragma surface surf Test
#pragma target 3.0
sampler2D _MainTex;
sampler2D _Normal;
float _SpecPow;
float4 _SpecCol;
struct Input
{
float2 uv_MainTex;
float2 uv_Normal;
float3 viewDir;
};
void surf (Input IN, inout SurfaceOutput o)
{
fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
o.Normal = UnpackNormal(tex2D(_Normal, IN.uv_Normal));
o.Albedo = c.rgb;
o.Alpha = c.a;
}
float4 LightingTest(SurfaceOutput s, float3 lighDir, float3 viewDir ,float atten){
float4 final;
//램버트 공식
float ndotl = saturate(dot(s.Normal, lighDir));
//스펙큘러 공식 적용
float3 H = normalize(lighDir + viewDir);
float spec = saturate(dot(H,s.Normal));
spec = pow(spec, _SpecPow);
//스팩큘러 색깔 적용
float3 SpecColor = spec * _SpecCol.rgb;
//알베도 적용
final.rgb = (ndotl * s.Albedo) + SpecColor.rgb;
final.a = s.Alpha;
return final;
}
ENDCG
}
FallBack "Diffuse"
}
선생님 코드
Shader "Custom/Test"
{
Properties
{
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_BumpMap ("NormalMap", 2D) = "bump" {}
_SpecPow ("Specular Power", Float) = 50.0
_SpecCol ("specular Color", Color) = (1,1,1,1)
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
#pragma surface surf _Test noambient
sampler2D _MainTex;
sampler2D _BumpMap;
float _SpecPow;
float4 _SpecCol;
struct Input
{
float2 uv_MainTex;
float2 uv_BumpMap;
};
void surf (Input IN, inout SurfaceOutput o)
{
fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
o.Albedo = c.rgb;
o.Alpha = c.a;
}
float4 Lighting_Test (SurfaceOutput s, float3 lightDir, float viewDir, float atten){
//램버트 공식
float ndotl = dot(s.Normal, lightDir);
//스패큘러 공식 적용
float3 H = normalize(lightDir + viewDir);
float spec = dot(H, s.Normal);
spec = pow(spec, _SpecPow);
//스패큘러 색상 적용 , _SpecColor 내장 변수
float3 specColor;
specColor = spec * _SpecCol.rgb;
//알베도 적용
float4 final;
final.rgb = (ndotl * s.Albedo) + specColor.rgb;
final.a = s.Alpha;
return final;
}
ENDCG
}
FallBack "Diffuse"
}
---
순서
텍스쳐 한장을 받는 쉐이더 작성
범프 넣기
커스텀 램버트 라이트만들기
스펙큘러 적용
스펙큘러 컬러 적용
알베도 적용
여기까지한 과정은 직접 수동으로 블린퐁(+스펙큘러)을 만들어 준 것이다.
반응형
'Unity > 그래픽스프로그래밍' 카테고리의 다른 글
0507_ 외곽선 만들어보기 (0) | 2021.05.07 |
---|---|
0507 _ Lim 라이트를 커스텀 라이트로 옮기기 (0) | 2021.05.07 |
0506_ 홀로그램 만들기 (0) | 2021.05.06 |
0506 _ RIM 라이트 표현하기 (0) | 2021.05.06 |
0506_유니티 그래픽스 라이트 연산에 대하여 (0) | 2021.05.06 |