unity冰视差

首先要知道,视差要采样一张视差图,通过这张视差图,才能判断这个像素在这个点应该偏移多少

本文使用陡峭视差映射

底下有全部代码

unity一开,优哉游哉,无需多言,我们直接开始

1.首先viewdir是要从世界空间转到切线空间去计算的,

这是因为如果用世界空间viewdir,随视角转动,凹凸效果也会随之改变

肯定要用切线空间,切线空间的Z轴(法线)​决定了表面的“陡峭程度” ,​只有在切线空间中,视角方向才能正确反映表面局部倾斜。

想想看我们的uv偏移,其实算的就是在这个t0点,向下偏移了多少

    
    float3 binormal = cross(v.normal, v.tangent.xyz) * v.tangent.w;
    
    float3 cammearDir = o.worldPos.xyz - _WorldSpaceCameraPos;
    
    
    o.viewDir = float3(
                        dot(cammearDir, v.tangent.xyz),
                        dot(cammearDir, binormal),
                        dot(cammearDir, v.normal)
                        );
 
      

2.准备一个视差函数

接下来,我们的视角层层递进(写循环),直到探查到视差图的深度

需要的食材:

currentTexCoords;指当前uv,开始是正常的uv,每一次步进,都会让当前uv,增加一层视差uv

deltaDepthever =height / _maxstep 每一步走的深度是多少;

 deltaTexCoords = viewdir.xy / (viewdir.z * ) 偏移uv,viewdir.xy/view.z是因为,离摄像机越近,那么偏移的程度就越大,离摄像机越远,偏移的程度就越小

currentLayerDepth;当前前进的深度

currentDepthMapValue;视差图采样的深度

想想看如果currentLayerDepth<currentDepthMapValue,是不是就可以结束循环了

接下来我们开始循环

while (currentLayerDepth < currentDepthMapValue && xxx < 100)
    {
       
        
        outuv = currentTexCoords;
        currentTexCoords += deltaTexCoords;
        
       
        
        currentDepthMapValue = tex2D(_DispTex, currentTexCoords);
        
        currentLayerDepth += deltaDepth;

      
        xxx += 1;
    }
    

outuv;记录循环后偏移的uv,并作为函数的返回值;

currentTexcoords +=deltatexcoords;currentTexcoords 其实也就是最终的uv,也就是outuv,为什么uv要累计深度偏移

这是因为视差贴图通过“欺骗性”的UV偏移模拟表面高度差。例如:

高处(高度值大)的像素需要更大的UV偏移量(看起来更“远”)

低处(高度值小)的像素需要更小的UV偏移量(看起来更“近”)

用累计好的深度去采样贴图,哪里深哪里浅,视差就成功了

currentDepthMapValue = tex2D(_DispTex, currentTexCoords);用偏移后的uv去采样深度图,再去与当前步进累计的深度currentLayerDepth做判断,是不是当前深度已经抵达视差贴图深度,我们就可以停止循环了,这个就是循环的条件

好了现在给出全部代码,有些地方看着有点奇怪,问就是这样效果好,有什么问题可以留言,其实本来就比较简单,难得我也不会,哈哈

Shader"Unlit/csdnshicha"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _maxstep("MaxStep", Int) = 1
        _height_scale("height-scale",range(0,5))=3
        _DispTex("displace",2D)= "white"{}
        _scale("scale",range(0,255))=1
        _Heightl("height",range(-1,1)) = 0.01
        _LayerStep("cengshu",Range(1,256)) = 16
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                float3 normal : NORMAL;
                float4 tangent : TANGENT;
};

            struct v2f
            {
                float2 uv : TEXCOORD0;
           
                float4 vertex : SV_POSITION;
                float3 worldPos : TEXCOORD1;
   
                float3 viewDir : TEXCOORD2;
};

            sampler2D _MainTex;
            sampler2D _DispTex;
            float4 _MainTex_ST;
            int _maxstep;


float _height_scale;
float _scale;
float _Heightl;
float _LayerStep;

            v2f vert (appdata v)
            {
    
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;

                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    
  
    
    float3 binormal = cross(v.normal, v.tangent.xyz) * v.tangent.w;
    
    float3 cammearDir = o.worldPos.xyz - _WorldSpaceCameraPos;
    
    
    o.viewDir = float3(
                        dot(cammearDir, v.tangent.xyz),
                        dot(cammearDir, binormal),
                        dot(cammearDir, v.normal)
                        );
 
                return o;
            }

float2 par(float3 viewdir, float2 uv)
{




 float deltaDepth = _height_scale / _maxstep;//每一步前进的深度
    

    
    
    
    
float3 viewDir = normalize(viewdir);

                            //获得深度距离的绝对值
   viewdir.z = abs(viewdir.z);

                        //增加视角方向UV,增加距离感觉
    viewdir.xy *= _Heightl;
    float2 deltaTexCoords = viewdir.xy / (viewdir.z * _LayerStep); //
    float2 currentTexCoords = uv * _scale;
    

    float2 outuv = currentTexCoords;

    float currentDepthMapValue = tex2D(_DispTex, currentTexCoords);
    float currentLayerDepth = 0;
    float xxx = 0; //防止循环次数过大

    

        
    while (currentLayerDepth < currentDepthMapValue && xxx < 100)
    {
       
        
        outuv = currentTexCoords;
        currentTexCoords += deltaTexCoords;
        
       
        
        currentDepthMapValue = tex2D(_DispTex, currentTexCoords);
        
        currentLayerDepth += deltaDepth;

      
        xxx += 1;
    }
    

    return outuv;
}


fixed4 frag (v2f i) : SV_Target
            {
 
                // sample the texture
                
                // apply fog
                float3 viewdir = i.viewDir;
                float2 uv = i.uv;
                float2 outuv = par(viewdir,uv );
                float4 col = tex2D(_MainTex, outuv);
                return col; 
            }
            ENDCG
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值