【unity shader】定向光版视差贴图实现

公式相关,点光源版本的实现请看上一节
添加链接描述
趁着春节做一点点小工作,把定向光版本也补全了

效果

定向光版
在这里插入图片描述
点光源版
在这里插入图片描述

源码

点光源:fwadd
节点着色器阶段求解切线空间下的光源坐标,传入片元着色器阶段计算
定向光:fwbase
节点着色器阶段直接算切线空间下的光照方向
两个计算texcoord偏移的函数没有单独拿出来,请讲究着看看

Shader "Unlit/parrallax_Map"
{
    
    
    Properties
    {
    
    
        _Color ("Color Tint", Color) = (1, 1, 1, 1)
        _MainTex ("Texture", 2D) = "white" {
    
    }
        _NormalTex("Normal Map", 2D) = "white"{
    
    }
        _BumpScale ("bump scale", float) = 1.0
        _DispTex("Disp Map", 2D) = "white"{
    
    }
        _Specular ("Specular", Color) = (1, 1, 1, 1)
		_Gloss ("Gloss", Range(8.0, 256)) = 20
        _height_scale("Height_scale", Range(0, 2)) = 1.0
    }
    SubShader
    {
    
    
        Tags {
    
     "RenderType"="Opaque" }
        LOD 100

        Pass
        {
    
    
            Tags {
    
     "LightMode"="ForwardBase" }
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_fwbase

            #include "UnityCG.cginc"
            #include "Lighting.cginc"

            struct v2f
            {
    
    
                float4 pos : SV_POSITION;
                half2 uv : TEXCOORD0;
                float3 TanLightDir : TEXCOORD1;
                float3 TanViewPos : TEXCOORD2;
                float3 TanFragPos : TEXCOORD3;
                //float3 T : TEXCOORD4;
                //float3 B : TEXCOORD5;
                //float3 N : TEXCOORD6;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            sampler2D _NormalTex;
            sampler2D _DispTex;
            float _BumpScale;
            fixed4 _Color;
            fixed4 _Specular;
            float _Gloss;
            float _height_scale;

            v2f vert (appdata_tan v)
            {
    
    
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);

                float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;  
                float3 FragPos = mul(UNITY_MATRIX_M, v.vertex).xyz;
				fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);  
				fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);  
				fixed3 worldBinormal = cross(worldNormal, worldTangent) * v.tangent.w;

                float3x3 TBN = transpose(float3x3(worldTangent, worldBinormal, worldNormal));

                o.TanLightDir = mul(TBN , UnityWorldSpaceLightDir(worldPos)) ;
                o.TanViewPos = mul(TBN , _WorldSpaceCameraPos) ;
                o.TanFragPos = mul(TBN , FragPos);

                return o;
            }

            float2 steep_ParallaxMapping(float2 texCoords, fixed3 viewDir)
            {
    
    
                float minLayers = 10;
                float maxLayers = 20;
                float numLayers = lerp(maxLayers, minLayers, abs(dot(float3(0.0, 0.0, 1.0), viewDir)));
                float LayerDepth = 1.0 / numLayers;
                float currentLayerDepth = 0.0;
                float2 P = viewDir.xy / viewDir.z * _height_scale;
                float2 deltaTexCoords = P / numLayers;

                float2 currentTexCoords = texCoords;
                float currentDepthMapValue = tex2D(_DispTex, currentTexCoords).r;

                while(currentLayerDepth < currentDepthMapValue)
                {
    
    
                    currentTexCoords -= deltaTexCoords;
                    currentDepthMapValue = tex2Dlod(_DispTex, float4(currentTexCoords, 0.0, 0.0)).r;
                    currentLayerDepth += LayerDepth;
                }

                return currentTexCoords;
            }

            float2 ParallaxOcclusionMapping(float2 texCoords, fixed3 viewDir)
            {
    
    
                float minLayers = 10;
                float maxLayers = 20;
                float numLayers = lerp(maxLayers, minLayers, abs(dot(float3(0.0, 0.0, 1.0), viewDir)));
                float LayerDepth = 1.0 / numLayers;
                float currentLayerDepth = 0.0;
                float2 P = viewDir.xy / viewDir.z * _height_scale;
                float2 deltaTexCoords = P / numLayers;

                float2 currentTexCoords = texCoords;
                float currentDepthMapValue = tex2D(_DispTex, currentTexCoords).r;

                while(currentLayerDepth < currentDepthMapValue)
                {
    
    
                    currentTexCoords -= deltaTexCoords;
                    currentDepthMapValue = tex2Dlod(_DispTex, float4(currentTexCoords, 0.0, 0.0)).r;
                    currentLayerDepth += LayerDepth;
                }

                float2 prevTexCoords = currentTexCoords + deltaTexCoords;
                float afterDepth = currentDepthMapValue - currentLayerDepth;
                float beforeDepth = tex2D(_DispTex, prevTexCoords).r - currentLayerDepth + LayerDepth;

                float weight = afterDepth / (afterDepth - beforeDepth);
                float2 finalTexCoords = prevTexCoords * weight + currentTexCoords * (1.0 - weight);

                return finalTexCoords;
            }
            
            fixed4 frag (v2f i) : SV_Target
            {
    
    
				// Compute the light and view dir in world space
				fixed3 lightDir = normalize(i.TanLightDir);
				fixed3 viewDir = normalize(i.TanViewPos - i.TanFragPos);
                float2 texcoords = i.uv;
                texcoords = ParallaxOcclusionMapping(i.uv, viewDir);
                //texcoords = steep_ParallaxMapping(i.uv, viewDir);

                if(texcoords.x > 1.0 || texcoords.y > 1.0 || texcoords.x < 0.0 || texcoords.y < 0.0)
                    discard;
                
                fixed3 bump = tex2D(_NormalTex, texcoords).rgb;
                bump = normalize(bump * 2.0 - 1.0);

                fixed3 albedo = tex2D(_MainTex, texcoords).rgb * _Color.rgb;
				
				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
				
				fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(bump, lightDir));

				fixed3 halfDir = normalize(lightDir + viewDir);
				fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(bump, halfDir)), _Gloss);
				
				return fixed4(ambient + diffuse + specular, 1.0);
            }
            ENDCG
        }

        Pass
        {
    
    
            Tags {
    
     "LightMode"="ForwardAdd" }
            Blend One One
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_fwadd

            #include "UnityCG.cginc"
            #include "Lighting.cginc"

            struct v2f
            {
    
    
                float4 pos : SV_POSITION;
                half2 uv : TEXCOORD0;
                float3 TanLightPos : TEXCOORD1;
                float3 TanViewPos : TEXCOORD2;
                float3 TanFragPos : TEXCOORD3;
                //float3 T : TEXCOORD4;
                //float3 B : TEXCOORD5;
                //float3 N : TEXCOORD6;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            sampler2D _NormalTex;
            sampler2D _DispTex;
            float _BumpScale;
            fixed4 _Color;
            fixed4 _Specular;
            float _Gloss;
            float _height_scale;

            v2f vert (appdata_tan v)
            {
    
    
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);

                float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;  
                float3 FragPos = mul(UNITY_MATRIX_M, v.vertex).xyz;
				fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);  
				fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);  
				fixed3 worldBinormal = cross(worldNormal, worldTangent) * v.tangent.w;

                float3x3 TBN = transpose(float3x3(worldTangent, worldBinormal, worldNormal));

                o.TanLightPos = mul(TBN , _WorldSpaceLightPos0) ;
                o.TanViewPos = mul(TBN , _WorldSpaceCameraPos) ;
                o.TanFragPos = mul(TBN , FragPos);

                return o;
            }

            float2 steep_ParallaxMapping(float2 texCoords, fixed3 viewDir)
            {
    
    
                float minLayers = 10;
                float maxLayers = 20;
                float numLayers = lerp(maxLayers, minLayers, abs(dot(float3(0.0, 0.0, 1.0), viewDir)));
                float LayerDepth = 1.0 / numLayers;
                float currentLayerDepth = 0.0;
                float2 P = viewDir.xy / viewDir.z * _height_scale;
                float2 deltaTexCoords = P / numLayers;

                float2 currentTexCoords = texCoords;
                float currentDepthMapValue = tex2D(_DispTex, currentTexCoords).r;

                while(currentLayerDepth < currentDepthMapValue)
                {
    
    
                    currentTexCoords -= deltaTexCoords;
                    currentDepthMapValue = tex2Dlod(_DispTex, float4(currentTexCoords, 0.0, 0.0)).r;
                    currentLayerDepth += LayerDepth;
                }

                return currentTexCoords;
            }

            float2 ParallaxOcclusionMapping(float2 texCoords, fixed3 viewDir)
            {
    
    
                float minLayers = 10;
                float maxLayers = 20;
                float numLayers = lerp(maxLayers, minLayers, abs(dot(float3(0.0, 0.0, 1.0), viewDir)));
                float LayerDepth = 1.0 / numLayers;
                float currentLayerDepth = 0.0;
                float2 P = viewDir.xy / viewDir.z * _height_scale;
                float2 deltaTexCoords = P / numLayers;

                float2 currentTexCoords = texCoords;
                float currentDepthMapValue = tex2D(_DispTex, currentTexCoords).r;

                while(currentLayerDepth < currentDepthMapValue)
                {
    
    
                    currentTexCoords -= deltaTexCoords;
                    currentDepthMapValue = tex2Dlod(_DispTex, float4(currentTexCoords, 0.0, 0.0)).r;
                    currentLayerDepth += LayerDepth;
                }

                float2 prevTexCoords = currentTexCoords + deltaTexCoords;
                float afterDepth = currentDepthMapValue - currentLayerDepth;
                float beforeDepth = tex2D(_DispTex, prevTexCoords).r - currentLayerDepth + LayerDepth;

                float weight = afterDepth / (afterDepth - beforeDepth);
                float2 finalTexCoords = prevTexCoords * weight + currentTexCoords * (1.0 - weight);

                return finalTexCoords;
            }
            
            fixed4 frag (v2f i) : SV_Target
            {
    
    
				// Compute the light and view dir in world space
				fixed3 lightDir = normalize(i.TanLightPos - i.TanFragPos);
				fixed3 viewDir = normalize(i.TanViewPos - i.TanFragPos);
                float2 texcoords = i.uv;
                texcoords = ParallaxOcclusionMapping(i.uv, viewDir);
                //texcoords = steep_ParallaxMapping(i.uv, viewDir);

                if(texcoords.x > 1.0 || texcoords.y > 1.0 || texcoords.x < 0.0 || texcoords.y < 0.0)
                    discard;
                
                fixed3 bump = tex2D(_NormalTex, texcoords).rgb;
                bump = normalize(bump * 2.0 - 1.0);

                fixed3 albedo = tex2D(_MainTex, texcoords).rgb * _Color.rgb;
				
				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
				
				fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(bump, lightDir));

				fixed3 halfDir = normalize(lightDir + viewDir);
				fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(bump, halfDir)), _Gloss);
				
				return fixed4(ambient + diffuse + specular, 1.0);
            }
            ENDCG
        }
    }
    FallBack "Specular"
}

猜你喜欢

转载自blog.csdn.net/misaka12807/article/details/128760368