Custom phong shading vs standard pbr(GGX) shading

내가 만들엇지만 나름 잘만든 것 같다.

(위사진은 왼쪽이 cook-torrance방식이고 가운데가 standard 왼쪽이 내가 만든 custom phong shading이다.)
회사 디자이너 분들에게 물어봤을때 오른쪽에 내가 만든 쉐이더가 제일 이쁘다고 했다 ! 
yeah~~ ! 
비용도 프로파일러로 GPU profiling했을때 standard의 절반정도 비용으로 나온다.

Nice~!

아래는 왼쪽이 standard pbr(GGX) shading 이고 오른쪽이 customize 한 phong shading으로 만든 것이다 퀄리티는 거의 흡사하지만 퍼포먼스는 확실히 많이 개선 됬으며 필요로 하게 되는 texture 의 수는 standard = 5/ custom = 2 로 확연히 줄었다. 


Sample code 계속해서 발전 시켜보고 있다. (UTF-8 이 왜 풀렸는지.. 한글이 날라갔다 ㄷㄷ)

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "Custom/Phong" { Properties { _DiffuseSampler("DiffuseTexture", 2D) = "white"{} _DiffuseColor("DiffuseColor", Color) = (0.5,0.5,0.5,1) _DiffuseStr("Diffuse Strength", Float) = 1 _DiffusePow("Diffuse Power", Float) = 1 _BaseLerp("Base Lerp", 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 _HeightMap("Height Map", 2D) = "white"{} _Parallax("Parallax", Float) = 0 } 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 float _DiffusePow; uniform float _BaseLerp; uniform float4 _ShadeColor; uniform float _ShadeNormalStr; uniform float4 _SpecColor; uniform float _SpecDiffuseStr; uniform float _ReflectionStr; uniform float _Shininess; uniform float _Metallic; uniform float _BumpStr; uniform float _Parallax; 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; float fresnel : TEXCOORD7; // float3 worldRefl; }; sampler2D _DiffuseSampler; float4 _DiffuseSampler_ST; sampler2D _BumpTex; float4 _BumpTex_ST; sampler2D _HeightMap; float4 _HeightMap_ST; float3 customObjSpaceViewDir(float4 v) { float3 objSpaceCameraPos = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos.xyz, 1)).xyz; return objSpaceCameraPos - v.xyz; } vertexOutput vert(vertexInput v) { vertexOutput o; //o.pos = UnityObjectToClipPos(v.vertex); //UNITY_MATRIX_MVP == gWorldViewProjectionMatrix //o.color = v.color; o.pos = UnityObjectToClipPos(v.vertex); o.posWorld = mul(unity_ObjectToWorld, v.vertex); o.lightDir = WorldSpaceLightDir(v.vertex); o.viewDir = 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); //fresnel equation float3 i = normalize(customObjSpaceViewDir(v.vertex)); //o.fresnel = 1 - dot(i, v.normal); o.fresnel = _FresnelBias + _FresnelScale * pow( 1 - dot(i, v.normal), _FresnelPower); 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 } /* 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); } inline float2 customParallaxOffset(half h, half height, half3 viewDir) { h = h * height - height / 2.0; float3 v = normalize(viewDir); v.z += 0.42; return h * (v.xy / v.z); } fixed4 frag(vertexOutput i) : COLOR {... } ENDCG } } Fallback "Diffuse" }














댓글

이 블로그의 인기 게시물

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

UE4 Tarray & Shuffle

Phong Shader equation