UnityShader学习10 纹理采样相关

//图像波浪效果
Shader "ShaderLearn/my_test_05" { Properties{ _MainTex("MainTex", 2D) = ""{} _F("F",range(1, 30)) = 10 _A ("A", range(0, 0.1)) = 0.01 _R ("R", range(0, 1)) = 0 } SubShader{ pass{ CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" sampler2D _MainTex; float4 _MainTex_ST; float _F; float _A;//幅度 float _R;//影响半径 struct v2f{ float4 pos : POSITION; float2 uv :TEXCOORD0; }; v2f vert(appdata_full v){ v2f o; o.pos = UnityObjectToClipPos(v.vertex); o.uv = v.texcoord.xy * _MainTex_ST.xy/*缩放*/ + _MainTex_ST.zw/*偏移*/;//给主纹理的uv坐标赋值 return o; } fixed4 frag(v2f IN) : COLOR{ /* y=Asin(ωx+φ)+k φ表示函数的所有点平行移动|φ|个单位 A表示纵坐标的伸缩 ω表示横坐标的伸缩 */ float2 uv = IN.uv; uv += 0.005 * sin(IN.uv *3.14 * _F + _Time.y);//普通波浪 //圆形波浪,以(0.5,0.5)为中心开始向四周扩散 float dis = distance(uv, float2(0.5,0.5)); _A *= saturate(1 - dis / _R); float scale = _A * sin(-dis * 3.14 * _F + _Time.y); uv = uv + uv * scale; ////根据z值图像模糊 //float2 dsdx = ddx(IN.z) * 10; //float2 dsdy = ddy(IN.z) * 10; //float4 color = tex2D(_MainTex, uv, dsdx, dsdy); fixed4 color = tex2D(_MainTex, uv); return color; } ENDCG } } FallBack "Diffuse" }

 

 

2.鼠标点击形成水波

cs脚本:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class WaveTexture : MonoBehaviour
{
    public int waveWidth;
    public int waveHeight;

    public int radius = 8;
    public float coutDownSpeed = 0.03f;

    float[,] waveA;//
    float[,] waveB;//


    Texture2D tex_uv;


    // Use this for initialization
    void Start()
    {
        waveA = new float[waveWidth, waveHeight];
        waveB = new float[waveWidth, waveHeight];

        tex_uv = new Texture2D(waveWidth, waveHeight);

        GetComponent<MeshRenderer>().material.SetTexture("_WaveTex", tex_uv);
    
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            RaycastHit hit;
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(ray, out hit))
            {
                Vector3 pos = hit.point;
                pos = transform.worldToLocalMatrix.MultiplyVector(pos);
                Debug.Log(pos);
                //因为立方体的uv范围是-0.5到0.5,所以这里要映射到0到1。
                int w = (int)((-pos.x + 0.5f) * waveWidth);
                int h = (int)((-pos.y + 0.5f) * waveHeight);

                PutDrop(w, h);
            }
        }
        ComputeWave();

    }

    private void PutDrop(int x, int y)
    {
        float dist;

        for (int i = -radius; i <= radius; i++)
        {
            for (int j = -radius; j <= radius; j++)
            {
                if (((x + i > 0) && (x + i < waveWidth - 1)) && ((y + j >= 0) && (y + j < waveHeight - 1)))
                {
                    dist = Mathf.Sqrt(i * i + j * j);//距离
                    if (dist < radius)
                    {
                        waveA[x + i, y + j] = Mathf.Cos(dist * Mathf.PI / radius);
                    }
                }
            }
        }

    }

    //以某个点测试用
    void Putpop()
    {
        waveA[waveWidth / 2, waveHeight / 2] = 1;
        waveA[waveWidth / 2 - 1, waveHeight / 2] = 1;
        waveA[waveWidth / 2 + 1, waveHeight / 2] = 1;
        waveA[waveWidth / 2, waveHeight / 2 - 1] = 1;
        waveA[waveWidth / 2, waveHeight / 2 + 1] = 1;
        waveA[waveWidth / 2 - 1, waveHeight / 2 + 1] = 1;
        waveA[waveWidth / 2 - 1, waveHeight / 2 - 1] = 1;
        waveA[waveWidth / 2 + 1, waveHeight / 2 + 1] = 1;
        waveA[waveWidth / 2 + 1, waveHeight / 2 - 1] = 1;

    }

    void ComputeWave()
    {
        for (int w = 1; w < waveWidth - 1; w++)
        {
            for (int h = 1; h < waveHeight - 1; h++)
            {
                waveB[w, h] = (waveA[w - 1, h] +
                    waveA[w + 1, h] +
                    waveA[w, h - 1] +
                    waveA[w, h + 1] +
                    waveA[w - 1, h - 1] +
                    waveA[w + 1, h - 1] +
                    waveA[w - 1, h + 1] +
                    waveA[w + 1, h + 1]) / 4 - waveB[w, h];

                //限定在-1到1范围
                float value = waveB[w, h];
                if (value > 1)
                {
                    waveB[w, h] = 1;

                }
                if (value < -1)
                {
                    waveB[w, h] = -1;
                }

                float offset_u = (waveB[w - 1, h] - waveB[w + 1, h]) / 2;
                float offset_v = (waveB[w, h - 1] - waveB[w, h + 1]) / 2;

                //颜色只有0到1,所以要映射到0到1
                float r = offset_u / 2 + 0.5f;
                float g = offset_v / 2 + 0.5f;

                tex_uv.SetPixel(w, h, new Color(r, g, 0));
                waveB[w, h] -= waveB[w, h] * coutDownSpeed;//衰减,每次减一个很小的数,一直到很接近0


            }
        }


        tex_uv.Apply();

        float[,] temp = waveA;
        waveA = waveB;
        waveB = temp;
    }
}

 

shader脚本:

Shader "ShaderLearn/my_test_06" {
    Properties{
        _MainTex("MainTex", 2D) = ""{}
    }

    SubShader{

        pass{
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            sampler2D _MainTex;
            sampler2D _WaveTex;

            struct v2f{
                float4 pos : POSITION;
                float2 uv :TEXCOORD0;
            };

                

            v2f vert(appdata_full v){
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv = v.texcoord.xy;

                return o;
            }

            fixed4 frag(v2f IN) : COLOR{

                float2 uv = tex2D(_WaveTex, IN.uv).xy;//对应脚本的rg分量

                uv = uv * 2 - 1;//将0到1 还原到1到 -1;
                uv *= 0.05;

                IN.uv += uv;

                fixed4 color = tex2D(_MainTex, IN.uv);
                
                return color;
            }


            ENDCG
        }
    }
        FallBack "Diffuse"
}

 

posted on 2019-06-17 23:08  炼金师  阅读(780)  评论(0)    收藏  举报

导航