CUSTOM shader : Phong shader base (light count : 1)


custom shader practice for light & good quality shaing

unpacking method and traspose of TBN edited in order to get better look

Shader "Custom/Phong" { Properties { _DiffuseSampler("DiffuseTexture", 2D) = "white"{} _DiffuseColor("DiffuseColor", Color) = (0.5,0.5,0.5,1) _DiffuseStr("Diffuse Strength", Float) = 1 _ShadeColor("ShadeColor", Color) = (0.5,0.5,0.5,1) _ShadeNormalStr("Shade Normal Strength", Float) = 0.2 _SpecColor("SpecColor", Color) = (1,1,1,1) _SpecDiffuseStr("Specular Diffuse Strength", Range(0,1)) = 0.5 _ReflectionStr("Refeflection strength", Float) = 0.2 _Shininess("Shininess", Float) = 0.5 _Metallic("Metallic", Range(0, 2)) = 0.5 _BumpTex("Bump Texture", 2D) = "bump"{} _BumpStr("Bump Strength", Float) = 1 _FresnelBias("Fresnel Bias", Float) = 0 _FresnelScale("Fresnel Scale", Float) = 1 _FresnelPower("Fresnel Power", Float) = 1 } SubShader { Tags {"Queue" = "Geometry" "RenderType" = "Opaque" } Pass { CGPROGRAM // Physically based Standard lighting model, and enable shadows on all light types #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" uniform float4 _LightColor0; //uniform float4 _Color; uniform float4 _DiffuseColor; uniform float _DiffuseStr; uniform float4 _ShadeColor; uniform float _ShadeNormalStr; uniform float4 _SpecColor; uniform float _SpecDiffuseStr; uniform float _ReflectionStr; uniform float _Shininess; uniform float _Metallic; uniform float _BumpStr; fixed _FresnelBias; fixed _FresnelScale; fixed _FresnelPower; //float4x4 gWorldMatrix; //World space //float4x4 gWorldViewProjectionMatrix; //float4x4 gWorldLightPosition; //float4x4 gWorldCameraPosition; //float4x4 gViewMatrix; // View space //float4x4 gProjectionMatrix; // resterize // 입출력 과정 // Object space -> world space -> view space -> resterize // 전역 변수 , 정점 데이터 // 전역 변수 -> 카메라 위치, world 좌표 ... // 정점 데이터 -> vertex position ... struct vertexInput // 정점 데이터 입력 { float4 vertex : POSITION; //각 정점의 위치 (sementic)을 통해서 가져옴 float3 normal : NORMAL; float4 tangent : TANGENT; float4 texcoord :TEXCOORD0; //float3 worldRefl; // Surface shader automatically calculate V2N world reflect vector }; struct vertexOutput // 정점 데이터의 출력값 { float4 pos : SV_POSITION; float4 uv : TEXCOORD0; float4 posWorld :TEXCOORD1; float3 N :TEXCOORD2; float3 T : TEXCOORD3; float3 B : TEXCOORD4; float3 lightDir : TEXCOORD5; half3 viewDir : TEXCOORD6; // float3 worldRefl; }; sampler2D _DiffuseSampler; float4 _DiffuseSampler_ST; sampler2D _BumpTex; float4 _BumpTex_ST; vertexOutput vert(vertexInput v) { vertexOutput o; //o.pos = UnityObjectToClipPos(v.vertex); //UNITY_MATRIX_MVP == gWorldViewProjectionMatrix //o.color = v.color; o.posWorld = mul(unity_ObjectToWorld, v.vertex); o.pos = UnityObjectToClipPos(v.vertex); o.lightDir = WorldSpaceLightDir(v.vertex); o.viewDir = normalize(WorldSpaceViewDir(v.vertex)); half fTangentSign = v.tangent.w * unity_WorldTransformParams.w; o.N = normalize(mul(float4(v.normal, 0.0), unity_WorldToObject).xyz); //normal direction converting o.T = normalize(UnityObjectToWorldDir(v.tangent.xyz));//normalize(mul(float4(v.tangent, 0.0), modelMatrixInverse).xyz); o.B = normalize(cross(o.N, o.T) * fTangentSign); //o.worldRefl = v.worldRefl; o.uv = float4(v.texcoord.xy, 0, 0); return o; } fixed3 CustomUnpackNormal(fixed4 packednormal) { // convert [0~1] to [-1 ~ 1] //xyzw #if defined(UNITY_NO_DXT5nm) // !!!! re calculation of this format needed !!!! //fixed3 normal; //normal.xy = packednormal.yw; //normal.z = sqrt(1 - normal.x * normal.x - normal.y * normal.y); return packednormal.xyz * 2 - 1; #else fixed3 normal; normal.xy = packednormal.wy * 2 - 1; normal.z = sqrt(1 - normal.x * normal.x - normal.y * normal.y); return normal.xyz; #endif //#if defined(SHADER_API_GLES) defined(SHADER_API_MOBILE) //#else // fixed3 normal; // normal.xy = packednormal.wy * 2 - 1; // normal.z = sqrt(1 - normal.x * normal.x - normal.y * normal.y); // // // return normal; // #endif } /* transpose : [ 1, 2, 3 ] [ 1, 4, 7 ] [ 4, 5 6 ] [ 2, 5, 8 ] [ 7, 8, 9 ] [ 3, 6, 9 ] */ void CustomLocalNormal2TBN(half3 localnormal, float4 tangent, inout half3 T, inout half3 B, inout half3 N) { half fTangentSign = tangent.w * unity_WorldTransformParams.w; N = normalize(UnityObjectToWorldNormal(localnormal)); T = normalize(UnityObjectToWorldDir(tangent.xyz)); B = normalize(cross(N, T) * fTangentSign); } half3 CustomTangentNormal2WorldNormal(half3 fTangentNormal, half3 T, half3 B, half3 N) { float3x3 TBN = float3x3(T, B, N); TBN = transpose(TBN); // transpose(전치행렬) : MVP 좌표변환의 이동행렬(Translation)과 동일 return mul(TBN, fTangentNormal); } half3 CustomTangentNormal2TNB(half3 fTangentNormal, half3 T, half3 B, half3 N) { float3x3 TNB = float3x3(T, N, B); TNB = transpose(TNB); // transpose(전치행렬) : MVP 좌표변환의 이동행렬(Translation)과 동일 return mul(TNB, fTangentNormal); } fixed4 frag(vertexOutput i) : COLOR { fixed4 o; fixed4 diffuse = tex2D(_DiffuseSampler, i.uv * _DiffuseSampler_ST.xy) * _DiffuseColor * _DiffuseStr; float3 viewDirection = normalize(_WorldSpaceCameraPos - i.posWorld.xyz); //view normal vector float3 lightDirection; float attenuation; float4 ref_val = UNITY_SAMPLE_TEXCUBE(unity_SpecCube0, i.N);//texCUBE(_CubeMap, reflectDirection);//UNITY_SAMPLE_TEXCUBE(_CubeMap, i.worldRefl);//tex2D(_CubeMap, i.worlRefl.uv); float3 ref_col = DecodeHDR(ref_val, unity_SpecCube0_HDR); //Bump half3 fTangentNormal = CustomUnpackNormal(tex2D(_BumpTex, i.uv * _BumpTex_ST.rg)); fTangentNormal.xy *= _BumpStr; float3 worldNormal = CustomTangentNormal2WorldNormal(fTangentNormal, i.T, i.B, i.N); float3 TNBNormal = CustomTangentNormal2TNB(fTangentNormal, i.T, i.B, i.N); fixed fNdotL = dot(i.lightDir, worldNormal); float3 fReflection = reflect(i.lightDir, worldNormal); float3 fTNBRef = reflect(i.lightDir, TNBNormal); if (0.0 == _WorldSpaceLightPos0.w) { // directional light attenuation = 1.0; lightDirection = normalize(_WorldSpaceLightPos0.xyz); } else { float3 vertexToLightSource = _WorldSpaceLightPos0.xyz - i.posWorld.xyz; float distance = length(vertexToLightSource); attenuation = 1.0 / distance; lightDirection = normalize(vertexToLightSource); } float3 lightInverseDir = -lightDirection; float3 ambientLighting = UNITY_LIGHTMODEL_AMBIENT.rgb * diffuse.rgb; //get diffuse reflection on bright side float3 diffuseReflection = attenuation * _LightColor0.rgb * diffuse.rgb * max(0.0, dot(i.N, lightDirection)); float3 diffuseShadeRef = attenuation * _ShadeColor.rgb * diffuse.rgb * max(0.0, dot(i.N, -lightDirection)) * 0.5; // +(ref_col - 0.4); float3 specularReflection; //if (dot(worldNormal, lightDirection) < 0.0) //{ // specularReflection = float3(0.0, 0.0, 0.0); //} //else //{ specularReflection = attenuation * _LightColor0.rgb * _SpecColor.rgb * pow(max(0.0, dot(fReflection, -normalize(i.viewDir)) * _Metallic), _Shininess) * ((1 - _SpecDiffuseStr) + diffuse.rgb * _SpecDiffuseStr) *ref_col + max(0, dot(fTNBRef, -normalize(i.viewDir) * _ShadeNormalStr)); // // //attenuation * _LightColor0.rgb * _SpecColor.rgb * // //pow(max(0.0, dot(-fReflection, normalize(i.viewDir)) * _Metallic), _Shininess) // //* dot(i.lightDir, worldNormal); //*ref_col * ((1- _SpecDiffuseStr) + diffuse.rgb* _SpecDiffuseStr); //} float4 final = float4( ambientLighting +(diffuseReflection + diffuseShadeRef) + specularReflection, 1); //= float4(ambientLighting + diffuseReflection + specularReflection, 1.0); //float4 final = float4(specularReflection, 1); //= float4(ambientLighting + diffuseReflection + specularReflection, 1.0); return final; } ENDCG } } Fallback "Diffuse" }

.cs 

CatDarkGame's Game Dev Story :: Unity Custom Light 5강 - Reflection (tistory.com)

CatDarkGame's Game Dev Story :: Unity Normal Map 구현 & 분석 (tistory.com)

Normal(법선)버텍스의 수직을 향하는 방향
Tangent(접선)버텍스의 수평을 향하는 방향
BiNormal(종법선)Normal과 Tangent를 외적(Cross)하여 나온 방향






댓글

이 블로그의 인기 게시물

About AActor!!! "UObject" has no member "BeginPlay"

Phong Shader equation