(笔记)中级Shader教程02 2D海洋 2D火焰

 

原作者  FishMan的技术专栏

以下是代码以及自己学习笔记:

1. grid 空间划分 
2. 2D模拟3D中”分层”的概念 
3. 透视模拟

5.grid 格子交错

 

1.空间划分

uv *=10;//将uv放大后frac
uv = frac(uv);
uv-=0.5;

(笔记)中级Shader教程02 2D海洋 2D火焰_第1张图片

2.添加随机值

fixed2 Rand22(fixed2 co){
    fixed x = frac(sin(dot(co.xy ,fixed2(122.9898,783.233))) * 43758.5453);
    fixed y = frac(sin(dot(co.xy ,fixed2(457.6537,537.2793))) * 37573.5913);
    return fixed2(x,y);
}
fixed2 r = Rand22(floor(uv));
col = fixed3(r,0.0);

(笔记)中级Shader教程02 2D海洋 2D火焰_第2张图片

3.uv偏移

float2 rgrid = Rand22(floor(uv));//0~1.0
uv = frac(uv);
uv -= (rgrid*2.0-1.0) * 0.35;
uv -=0.5;

(笔记)中级Shader教程02 2D海洋 2D火焰_第3张图片

4.绘制基本图形

float r = length(uv);
float circleSize = 0.3;
float val = smoothstep(circleSize,-circleSize,r);
float3 col = float3(val,val,val)* rgrid.x ;

(笔记)中级Shader教程02 2D海洋 2D火焰_第4张图片

5.交错grid

 if (abs(fmod(coord.y,2.0))<1.0) //让格子交错
        coord.x += 0.5;

6.生命值随机

float2 coord = uv*_GridSize - float2(0.,yOffset);//整体沿y轴上升
float tempY = gridIndex.y + yOffset ;
float life = min(   10.0*(1.0-min((tempY)/(24.0-20.0*rnd)//生命值随机
                                    ,1.0)),1.0);

 



Shader "FishManShaderTutorial/2DSnow"
{
    Properties
    {
        _MainTex ("MainTex", 2D) = "white" { }
        SIZE_RATE ("SIZE_RATE", float) = 0.1
        XSPEED ("XSPEED", float) = 0.2
        YSPEED ("YSPEED", float) = 0.5
        LAYERS ("LAYERS", float) = 10
    }

    SubShader
    {
        Tags { "RenderType" = "Transparent" "Queue" = "Transparent" }

        Pass
        {
            ZWrite Off
            Blend SrcAlpha OneMinusSrcAlpha
            
            CGPROGRAM
            
            #pragma vertex vert
            #pragma fragment frag
            #include "ShaderLibs/Framework2D.cginc"

            float SIZE_RATE;
            float XSPEED;
            float YSPEED;
            float LAYERS;

            float3 SnowSingleLayer(float2 uv, float layer)
            {
                fixed3 acc = fixed3(0.0, 0.0, 0.0);
                uv *= layer;  //将uv按照层数放大
                
                //UV的偏移 实现下雪的效果
                float xOffset = uv.y * (((Hash11(layer) * 2 - 1.) * 0.5 + 1.) * XSPEED);
                float yOffset = (YSPEED * _Time.y);
                uv += fixed2(xOffset, yOffset);
                
                //Hash22 主要是输入float2 随机生成噪波 并输出float2  实现随机效果
                float2 rgrid = Hash22(floor(uv));
                uv = frac(uv); //取小数
                uv -= (rgrid * 2.0 - 1.0) * 0.4;
                uv -= 0.5;
                
                
                float r = length(uv);
                float circleSize = 0.05 * (1.0 + 0.3 * sin(_Time.y * SIZE_RATE));
                // float circleSize = 0.04;
                float val = smoothstep(circleSize, -circleSize, r);
                float3 col = float3(val, val, val) * rgrid.x ;
                return col;
            }
            float3 Snow(float2 uv)   //多层绘制  主要是绘制出2D立体效果
            {
                float3 acc = float3(0, 0, 0);
                for (fixed i = 0.; i < LAYERS; i ++)
                {
                    acc += SnowSingleLayer(uv, i);
                }
                return acc;
            }
            float3 ProcessFrag(float2 uv)
            {
                uv += float2(_ScreenParams.x / _ScreenParams.y, 1.0);
                return Snow(uv);
            }
            ENDCG
            
        }
    }
}

2D火焰

float3 _Color;
float _GridSize;
float _RotSpd;
float _YSpd;
float3 ProcessFrag(float2 uv){
    float3 acc = float3(0.0,0.0,0.0);

    float rotDeg = 3.*_RotSpd * ftime;
    float yOffset = 4.*_YSpd* ftime;

    float2 coord = uv*_GridSize - float2(0.,yOffset);//整体沿y轴上升
    if (abs(fmod(coord.y,2.0))<1.0) //让格子交错
        coord.x += 0.5;
    float2 gridIndex = float2(floor(coord));
    float rnd = Hash12(gridIndex);//根据ID 获取hash值
    // 弥补y轴上升的逆差 获取原来的y值 
    // 同时因为gridIndex = floor(coord) 的原因  会让tempY值在锁定固定的grid的同时越来越大;
    float tempY = gridIndex.y + yOffset ;
    float life = min(   10.0*(1.0-min((tempY)/(24.0-20.0*rnd)//生命值随机
                                        ,1.0)),1.0);
    if (life>0.0 ) {
        float size = 0.08*rnd;//让大小随机化
        float deg = 999.0*rnd*2.0*PI + rotDeg*(0.5+0.5*rnd);//添加旋转随机化
        float2 rotate = float2(sin(deg),cos(deg));//单位圆旋转偏移
        float radius =  0.5-size*0.2;
        float2 cirOffset = radius*rotate;//
        float2 part = frac(coord-cirOffset) - 0.5 ;//让格子自己旋转起来 位置变 方向不变
        float len = length(part);
        float sparksGray = max(0.0,1.0 -len/size);//画圆
        float sinval = sin(PI*1.*(0.3+0.7*rnd)*ftime+rnd*10.);//加点亮度的变化实现闪烁 
        float period = clamp(pow(pow(sinval,5.),5.),0.,1.);
        float blink =(0.8+0.8*abs(period));
        acc = life*sparksGray*_Color*blink;
    }
    return acc;
}

 

你可能感兴趣的:(UnityShader姿势)