Caustic Effect

作者: 万里_aa3f | 来源:发表于2019-02-23 22:43 被阅读0次

    1.caustic 效果实现
    2.后期处理,在投射caustic的dirLight空间投射
    3.消除阴影部分的投射
    4.添加投射角度的衰减
    5.添加距离衰减控制

    1.caustic效果实现

    将shadertoy上的uv限制进行修改,取消投射时的重复
    https://www.shadertoy.com/view/MdlXz8

                float3 CausticTriTwist(float2 uv,float time )
                {
                    const int MAX_ITER = 5;
                    float2 p = uv-250;
    
                    float2 i = float2(p);
                    float c = 1.0;
                    float inten = .005;
    
                    for (int n = 0; n < MAX_ITER; n++) //3.多层叠加
                    {
                        float t = time * (1.0 - (3.5 / float(n+1)));
                        i = p + float2(cos(t - i.x) + sin(t + i.y), sin(t - i.y) + cos(t + i.x));//2.空间扭曲
                        c += 1.0/length(float2(p.x / (sin(i.x+t)/inten),p.y / (cos(i.y+t)/inten)));//集合操作avg
                    }
                    
                    c /= float(MAX_ITER);
                    c = 1.17-pow(c, 1.4);//4.亮度调整
                    float val = pow(abs(c), 8.0);
                    return val;
                }
    

    2.在dirLight空间进行投射

    ①深度图求出worldPos;
    ②脚本传入world to light matrix: _Matrix_W2L, 并将worldPos变换到LightPos;
    ③用lightPos的xy值进行采样,因为z是光线投射方向,下文也会用到

    //worldPos+normal
    float3 viewNormal;
    float depth01;
    DecodeDepthNormal(tex2D(_CameraDepthNormalsTexture,i.uv),depth01,viewNormal);
    float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv);
    float4 pos = float4(i.uv.x*2-1,i.uv.y*2-1,(1-depth)*2-1,1);
    pos = mul(_Matrix_P2W , pos);
    float3 worldPos = pos.xyz/pos.w;
    float4 lightPos = mul(_Matrix_W2L,float4(worldPos,1.0));
                    
    float2 CausticUV = float3(lightPos.xyz).xy;
    float causstic = CausticTriTwist(CausticUV/_Repeat, _Time.y);
    
    _repeat 控制重复

    3.消除阴影投射

    思路,主要拿到collectShadows就好办了



    用commandBuffer,配合的C# ,unityAPI手册里CommandBuffer里有提到

    RenderTargetIdentifier shadowmap = BuiltinRenderTextureType.CurrentActive;
    m_ShadowmapCopy = new RenderTexture(myCamera.pixelWidth,myCamera.pixelHeight,0);
    CommandBuffer cb = new CommandBuffer();
    cb.Blit(shadowmap, new RenderTargetIdentifier(m_ShadowmapCopy));
    dirctLight.AddCommandBuffer(LightEvent.AfterScreenspaceMask, cb);
    
    shader
    //消除阴影光强
    float shadow = tex2D(_dirShadowMap,i.uv).r;
    shadow = smoothstep(0.6,1.0,shadow);
    causstic *= shadow;
    

    4.添加角度的衰减

    无衰减
    比较假的原因
    修正效果
    //倾斜衰减
    float3 worldNormal = mul(_Matrix_IV,viewNormal);
    float3 lightNormal = mul(_Matrix_W2L,worldNormal);
    float attenNormal = max(0,dot(lightNormal,float3(0,0,-1))) ;
    float3 caussticCol=_Color * causstic * attenDistance * attenNormal;
    

    5.添加距离衰减控制

    _attenDistance 投射的距离
    _attenLenght 效果过度融合的长度
    还可以自己添加很多方面的控制
    比如模拟深度对光强的影响等

    //距离衰减
    float attenDistance = smoothstep(_attenDistance+_attenLength,_attenDistance-_attenLength,length(_WorldSpaceCameraPos-worldPos));
    

    C#脚本

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.Rendering;
    
    [ExecuteInEditMode]
    [RequireComponent(typeof(Camera))]
    public class CausticEffect : MonoBehaviour
    {
        private Camera myCamera=null;
        public Shader effectShader=null;
        private Material effectMaterial=null;
        private RenderTexture m_ShadowmapCopy;
    
        public Light dirctLight=null;
        public Color causticColor = Color.yellow;
        public float attenDistance = 200;
        public float attenLength=50;
        public float repeat=10;
    
    
        private void OnEnable() {
            myCamera = this.GetComponent<Camera>();
            if(myCamera!=null&&effectShader!=null&&effectShader.isSupported==true&&dirctLight.type==LightType.Directional){
                effectMaterial = new Material(effectShader);
                myCamera.depthTextureMode|=DepthTextureMode.Depth;
                myCamera.depthTextureMode=DepthTextureMode.DepthNormals;
    
                //get shadow map
                RenderTargetIdentifier shadowmap = BuiltinRenderTextureType.CurrentActive;
                m_ShadowmapCopy = new RenderTexture(myCamera.pixelWidth,myCamera.pixelHeight,0);
                CommandBuffer cb = new CommandBuffer();
                cb.Blit(shadowmap, new RenderTargetIdentifier(m_ShadowmapCopy));
                dirctLight.AddCommandBuffer(LightEvent.AfterScreenspaceMask, cb);
                
            }else
            {
                enabled=false;
                Debug.LogWarning("please check your C# value!");
            }
        }
    
        private void OnDisable() {
            if(effectMaterial!=null){
                effectMaterial=null;
            }
            
        }
    
        private void OnRenderImage(RenderTexture src, RenderTexture dest) {
            if(effectMaterial!=null){
                Matrix4x4 viewMatrix = myCamera.worldToCameraMatrix;
                Matrix4x4 projectMatrix = myCamera.projectionMatrix;
                Matrix4x4 _Matrix_P2W = (projectMatrix*viewMatrix).inverse;
                effectMaterial.SetMatrix("_Matrix_P2W",_Matrix_P2W);
                effectMaterial.SetMatrix("_Matrix_IV",viewMatrix.inverse);
                Matrix4x4 lightMatrix =  dirctLight.transform.worldToLocalMatrix;
                effectMaterial.SetMatrix("_Matrix_W2L",lightMatrix);
                effectMaterial.SetColor("_Color", causticColor);
                effectMaterial.SetFloat("_attenDistance",attenDistance);
                effectMaterial.SetFloat("_attenLength",attenLength);
                effectMaterial.SetFloat("_Repeat",repeat);
    
                effectMaterial.SetTexture("_dirShadowMap",m_ShadowmapCopy);
                
                Graphics.Blit(src,dest,effectMaterial);
            }else
            {
                Graphics.Blit(src,dest);
            }
        }
    
    }
    
    

    Shader

    Shader "Unlit/caustic"
    {
        Properties
        {
            _MainTex ("Texture", 2D) = "white" {}
            _Color("Color",Color)=(1,1,0,1)
            _attenDistance("attenDistance",float)=200
            _attenLength("attenLength",float)=50
            _Repeat("Repeat",float)=10
            _dirShadowMap("dirShadowMap",2D)="white"{}
    
        }
        SubShader
        {
            ZTest Always
            Cull Off
            ZWrite off 
    
            Pass
            {
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
    
                #include "UnityCG.cginc"
    
                struct appdata
                {
                    float4 vertex : POSITION;
                    float2 texcoord:TEXCOORD;
                };
    
                struct v2f
                {
                    float4 vertex : SV_POSITION;
                    float2 uv:TEXCOORD0;
                };
    
                sampler2D _MainTex;
                float3 _Color;
                float _attenDistance;
                float _attenLength;
                float _Repeat;
                sampler2D _CameraDepthTexture;
                sampler2D _CameraDepthNormalsTexture;
                float4x4 _Matrix_P2W;
                float4x4 _Matrix_W2L;
                float4x4 _Matrix_IV;
                sampler2D _dirShadowMap;
    
    
                v2f vert (appdata v)
                {
                    v2f o;
                    o.vertex = UnityObjectToClipPos(v.vertex);
                    o.uv= v.texcoord;
                    return o;
                }
    
                float3 CausticTriTwist(float2 uv,float time )
                {
                    const int MAX_ITER = 5;
                    float2 p = uv-250;
    
                    float2 i = float2(p);
                    float c = 1.0;
                    float inten = .005;
    
                    for (int n = 0; n < MAX_ITER; n++) //3.多层叠加
                    {
                        float t = time * (1.0 - (3.5 / float(n+1)));
                        i = p + float2(cos(t - i.x) + sin(t + i.y), sin(t - i.y) + cos(t + i.x));//2.空间扭曲
                        c += 1.0/length(float2(p.x / (sin(i.x+t)/inten),p.y / (cos(i.y+t)/inten)));//集合操作avg
                    }
                    
                    c /= float(MAX_ITER);
                    c = 1.17-pow(c, 1.4);//4.亮度调整
                    float val = pow(abs(c), 8.0);
                    return val;
                }
    
                fixed4 frag (v2f i) : SV_Target
                {
                    //场景颜色
                    fixed4 col = tex2D(_MainTex,i.uv);
    
                    //worldPos+normal
                    float3 viewNormal;
                    float depth01;
                    DecodeDepthNormal(tex2D(_CameraDepthNormalsTexture,i.uv),depth01,viewNormal);
                    float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv);
                    float4 pos = float4(i.uv.x*2-1,i.uv.y*2-1,(1-depth)*2-1,1);
                    pos = mul(_Matrix_P2W , pos);
                    float3 worldPos = pos.xyz/pos.w;
                    float4 lightPos = mul(_Matrix_W2L,float4(worldPos,1.0));
                    
                    float2 CausticUV = float3(lightPos.xyz).xy;
                    float causstic = CausticTriTwist(CausticUV/_Repeat, _Time.y);
    
                    //距离衰减
                    float attenDistance = smoothstep(_attenDistance+_attenLength,_attenDistance-_attenLength,length(_WorldSpaceCameraPos-worldPos));
    
                    //消除阴影光强
                    float shadow = tex2D(_dirShadowMap,i.uv).r;
                    shadow = smoothstep(0.6,1.0,shadow);
                    causstic *= shadow;
    
                    //倾斜衰减
                    float3 worldNormal = mul(_Matrix_IV,viewNormal);
                    float3 lightNormal = mul(_Matrix_W2L,worldNormal);
                    float attenNormal = max(0,dot(lightNormal,float3(0,0,-1))) ;
                    float3 caussticCol=_Color * causstic * attenDistance * attenNormal;
    
                    float3 finalCol = col + 0.2 * caussticCol;
                    return float4(finalCol,1.0);
                }
                ENDCG
            }
        }
    }
    
    

    相关文章

      网友评论

        本文标题:Caustic Effect

        本文链接:https://www.haomeiwen.com/subject/rasmyqtx.html