shader之——rain

1.地面shader

Shader "baicai/me02" {
    Properties {
        _MainTex ("MainTex", 2D) = "white" {}
        _Bump ("Bump", 2D) = "bump" {}
        _Bump02("Bump02",2D) = "Bump"{}
        _DirectionUv("Wet scroll direction (2 samples)", Vector) = (1.0,1.0, -0.2,-0.2)
        _TexAtlasTiling("Tex atlas tiling", Vector) = (8.0,8.0, 4.0,4.0)
        _water ("water",Range(0.01,5)) = 0.2
        _ref("ref",Range(0,1)) = 0.5
        _ReflectionTex("reflectiontex",2D ) = "black"{}

    }
    SubShader {
        Tags {
            "RenderType"="Opaque"
        }
        Pass {
            Tags {
                "LightMode"="ForwardBase"
            }

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #define UNITY_PASS_FORWARDBASE
            #include "UnityCG.cginc"
            #include "AutoLight.cginc"
            #pragma multi_compile_fwdbase_fullshadows
            #pragma target 3.0

             float4 _LightColor0;
             sampler2D _MainTex;
             float4 _MainTex_ST;
             sampler2D _Bump;
             sampler2D _Bump02;
             sampler2D _ReflectionTex;
             float4 _DirectionUv;
             float4 _TexAtlasTiling;
             float _water;
             float _ref;

            struct VertexInput {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
                float4 tangent : TANGENT;
                float2 uv : TEXCOORD0;
            };
            struct v2f {
                float4 pos : SV_POSITION;
                float2 uv : TEXCOORD0;
                float3x3 tangentTransform:COLOR;
                float4 normalScrollUv:TEXCOORD1;
                float4 screen : TEXCOORD2;
                LIGHTING_COORDS(3,4)

            };
            ///需要把顶点着色器中的切线空间转化为世界空间
            ///或者把世界空间的所有向量转化为切线空间
            v2f vert (VertexInput v) {
                v2f o ;
                o.pos = UnityObjectToClipPos(v.vertex );
                o.uv =TRANSFORM_TEX(v.uv, _MainTex);
                //求世界法线三件套
                float3 normal =normalize( UnityObjectToWorldNormal(v.normal));
                float3 tangentDir = normalize( mul( unity_ObjectToWorld, float4( v.tangent.xyz, 0.0 ) ).xyz );//切线空间转化为世界空间
                float3 bitangentDir = normalize(cross(normal, tangentDir) * v.tangent.w);//切线 法线 计算副切线

                //得出结合切线的世界法线
                o.tangentTransform = float3x3( tangentDir, bitangentDir, normal);
                //物体世界坐标

                o.normalScrollUv = v.uv.xyxy * _TexAtlasTiling + _Time.xxxx * _DirectionUv;
                o.screen = ComputeScreenPos(o.pos);

                TRANSFER_VERTEX_TO_FRAGMENT(o)
                return o;
            }

                float4 frag(v2f i) : COLOR {
                half3 nrml = UnpackNormal(tex2D(_Bump02, i.normalScrollUv.xy));
                nrml += UnpackNormal(tex2D(_Bump02, i.normalScrollUv.zw));
                nrml.xy *= 0.025;

                float2 uvRef = i.screen.xy / (i.screen.w+0001);
                uvRef.y = 1-uvRef.y;
                fixed4 rtRefl = tex2D (_ReflectionTex, uvRef + nrml.xy *_water);

                float3 BumpMap = UnpackNormal(tex2D(_Bump,i.uv));
                float3 N = normalize(mul( BumpMap, i.tangentTransform )); //根据模型的世界法线 将法线贴图转换为世界空间

                float3 L = normalize(_WorldSpaceLightPos0.xyz);
                float atten = LIGHT_ATTENUATION(i);

                float4 col = tex2D(_MainTex,i.uv+nrml.xy *_water);
                float NdotL = saturate(dot( N, L )); //漫反射强
                col.rgb= col.rgb * (NdotL *_LightColor0.xyz * atten + UNITY_LIGHTMODEL_AMBIENT.rgb) +rtRefl *_ref ;

                return col;
            }
            ENDCG
        }
   }
   FallBack "Diffuse"
}

2.反射脚本 跟河流倒影的脚本相同

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

public class ReflectionSelf : MonoBehaviour {

    private Transform refObject;
    private Camera m_camera;
    public LayerMask reflectionMask;
    private RenderTexture m_texture;

    void Start () {
        refObject = this.GetComponent<Transform>();
        GameObject refCramera = new GameObject("refCramera");
        m_camera = refCramera.AddComponent<Camera>();
        m_texture = new RenderTexture(Screen.width,Screen.height,24);
        refCameraSet();
    }

    /// <summary>
    /// 相机位置及方向
    /// </summary>
        void cameraTrasform()
    {
        //Position  x z 与mainCamera相同  y 到平面的距离与 mainCamera到平面的距离相等
        Vector3 p_ref;
        Vector3 p_main = Camera.main.transform.position;
        Vector3 p_plan = this.transform.position;
        float y = p_main.y - p_plan.y;

        p_ref.x = p_main.x;
        p_ref.y = p_plan.y - y;
        p_ref.z = p_main.z;
        m_camera.transform.position = p_ref;

        //Rotation
        Vector3 R_ref;
        Vector3 R_main = Camera.main.transform.localEulerAngles;

        R_ref.x = -R_main.x;
        R_ref.y = R_main.y;
        R_ref.z = R_main.z;
        m_camera.transform.localEulerAngles = R_ref;
    }

    /// <summary>
    /// 反射相机的设置
    /// </summary>

        void refCameraSet()
    {
        m_camera.backgroundColor = Color.black;
        m_camera.clearFlags = CameraClearFlags.Skybox;
        m_camera.cullingMask = reflectionMask; //图层
        m_camera.targetTexture = m_texture;
        this.GetComponent<Renderer>().sharedMaterial.SetTexture("_ReflectionTex", m_camera.targetTexture);
    }

    void Update () {
        //相机位置要放在这里,因为要随着主相机一直运动
        cameraTrasform();

    }
}

3.下雨脚本1

using System.Collections;
using System.Collections.Generic;
#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;

public class RainManager : MonoBehaviour {
    public float minYPosition = 0;
    public int numberOfParticles = 400;
    public float areaSize = 40;
    public float areaHeight = 15;
    public float fallingSpeed = 23;
    public float particleSize =10f;
    public float flakeRandom = 0.1f;

    public Mesh[] preGennedMeshes;
    private int preGennedIndex = 0;

    public bool generateNewAssetsOnStart = false;

    void Start () {
#if UNITY_EDITOR
        if (generateNewAssetsOnStart)
        {
            // create & save 3 meshes
            Mesh m1 = CreateMesh();
            Mesh m2  = CreateMesh();
            Mesh m3  = CreateMesh();

            AssetDatabase.CreateAsset(m1, "Assets/resourcex/" + gameObject.name + "_LQ0.asset");
            AssetDatabase.CreateAsset(m2, "Assets/resourcex/" + gameObject.name + "_LQ1.asset");
            AssetDatabase.CreateAsset(m3, "Assets/resourcex/" + gameObject.name + "_LQ2.asset");
            //Debug.Log("Created new rain meshes in Assets/Objects/RainFx/");
        }
#endif

    }

    public Mesh GetPreGennedMesh()
    {

        return preGennedMeshes[(preGennedIndex++) % preGennedMeshes.Length];

    }
    void Update () {

    }
    private Mesh CreateMesh() {
        Mesh mesh = new Mesh();

        Vector3 cameraRight = Camera.main.transform.right;
        Vector3 cameraUp  = (Vector3.up);

        int particleNum  = numberOfParticles / 2;

        Vector3[] verts  = new Vector3[4 * particleNum];
        Vector2[] uvs  = new Vector2[4 * particleNum];
        Vector2[]  uvs2  = new Vector2[4 * particleNum];
        Vector3[] normals = new Vector3[4 * particleNum];

        int[] tris  = new int[2 * 3 * particleNum];

        Vector3 position ;
        for (int i  = 0; i<particleNum; i++)
        {
            int i4  = i* 4;
            int i6  = i* 6;

            position.x = areaSize* (Random.value - 0.5f);
            position.y = areaHeight* Random.value;
    position.z = areaSize* (Random.value - 0.5f);

            float rand = Random.value;
            float widthWithRandom  = particleSize* 0.215f;// + rand * flakeRandom;
            float heightWithRandom  = particleSize + rand* flakeRandom;

    verts[i4 + 0] = position - cameraRight* widthWithRandom - cameraUp* heightWithRandom;
    verts[i4 + 1] = position + cameraRight* widthWithRandom - cameraUp* heightWithRandom;
    verts[i4 + 2] = position + cameraRight* widthWithRandom + cameraUp* heightWithRandom;
    verts[i4 + 3] = position - cameraRight* widthWithRandom + cameraUp* heightWithRandom;

    normals[i4 + 0] = -Camera.main.transform.forward;
            normals[i4 + 1] = -Camera.main.transform.forward;
            normals[i4 + 2] = -Camera.main.transform.forward;
            normals[i4 + 3] = -Camera.main.transform.forward;

            uvs[i4 + 0] = new Vector2(0.0f, 0.0f);
    uvs[i4 + 1] = new Vector2(1.0f, 0.0f);
    uvs[i4 + 2] = new Vector2(1.0f, 1.0f);
    uvs[i4 + 3] = new Vector2(0.0f, 1.0f);

    uvs2[i4 + 0] = new Vector2( Random.Range(-2f,2f)*4.0f, Random.Range(-1f,1f)*1.0f);
            uvs2[i4 + 1] = new Vector2(uvs2[i4 + 0].x, uvs2[i4 + 0].y);
    uvs2[i4 + 2] = new Vector2(uvs2[i4 + 0].x, uvs2[i4 + 0].y);
    uvs2[i4 + 3] = new Vector2(uvs2[i4 + 0].x, uvs2[i4 + 0].y);

    tris[i6 + 0] = i4 + 0;
            tris[i6 + 1] = i4 + 1;
            tris[i6 + 2] = i4 + 2;
            tris[i6 + 3] = i4 + 0;
            tris[i6 + 4] = i4 + 2;
            tris[i6 + 5] = i4 + 3;
        }

mesh.vertices = verts;
        mesh.triangles = tris;
        mesh.normals = normals;
        mesh.uv = uvs;
        mesh.uv2 = uvs2;
        mesh.RecalculateBounds ();

        return mesh;
    }    

}

4.下雨脚本2

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

public class RainBox : MonoBehaviour {
    private MeshFilter mf;
    private Vector3 defaultPosition;
    private Bounds bounds;
    private RainManager manager;
    private Transform cachedTransform;
    private float cachedMinY;
    private float cachedAreaHeight;
    private float cachedFallingSpeed;

    void Start () {
        manager = transform.parent.GetComponent< RainManager > ();

        bounds = new Bounds(new Vector3(transform.position.x, manager.minYPosition, transform.position.z),
                           new  Vector3(manager.areaSize * 1.35f, Mathf.Max(manager.areaSize, manager.areaHeight) * 1.35f, manager.areaSize * 1.35f));

        mf = GetComponent< MeshFilter > ();
        mf.sharedMesh = manager.GetPreGennedMesh();

        cachedTransform = transform;
        cachedMinY = manager.minYPosition;
        cachedAreaHeight = manager.areaHeight;
        cachedFallingSpeed = manager.fallingSpeed;

        enabled = false;
    }

    private void OnBecameVisible()
    {
        enabled = true;
    }
    private void OnBecameInvisible()
    {
        enabled = false;
    }

    void Update () {

        cachedTransform.position -= Vector3.up * Time.deltaTime * cachedFallingSpeed;

        if (cachedTransform.position.y + cachedAreaHeight < cachedMinY)
        {
            cachedTransform.position = cachedTransform.position + Vector3.up * cachedAreaHeight * 2.0f;
        }
    }

    private void OnDrawGizmos()
    {
#if UNITY_EDITOR
        // do not display a weird mesh in edit mode
        if (!Application.isPlaying)
        {
            mf = GetComponent< MeshFilter > ();
            mf.sharedMesh = null;
        }
#endif

        if (transform.parent)
        {
            Gizmos.color =new  Color(0.2f, 0.3f, 3.0f, 0.35f);
            RainManager manager  = transform.parent.GetComponent<RainManager>() as RainManager;
            if (manager)
                Gizmos.DrawWireCube(transform.position + transform.up * manager.areaHeight * 0.5f,
                                        new Vector3(manager.areaSize, manager.areaHeight, manager.areaSize));
        }
    }

}

5.地面涟漪shader1

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

public class RainsplashManager : MonoBehaviour {
    public int numberOfParticles  = 700;
    public float areaSize = 40.0f;
    public float areaHeight = 15.0f;
    public float fallingSpeed = 23.0f;
    public float flakeWidth   = 0.4f;
    public float flakeHeight = 0.4f;
    public float flakeRandom   = 0.1f;

    public Mesh[] preGennedMeshes  ;
    private int preGennedIndex  = 0;

    public bool generateNewAssetsOnStart  = false;    

    public void Start () {
    #if UNITY_EDITOR
        if (generateNewAssetsOnStart) {
            // create & save 3 meshes
            Mesh m1  = CreateMesh ();
            Mesh m2  = CreateMesh ();
            Mesh m3  = CreateMesh ();
            UnityEditor.AssetDatabase.CreateAsset(m1, "Assets/Objects/RainFx/" + gameObject.name + "_LQ0.asset");
            UnityEditor.AssetDatabase.CreateAsset(m2, "Assets/Objects/RainFx/" + gameObject.name + "_LQ1.asset");
            UnityEditor.AssetDatabase.CreateAsset(m3, "Assets/Objects/RainFx/" + gameObject.name + "_LQ2.asset");
            //DebugUtility.Log ("Created new rainsplash meshes in Assets/Objects/RainFx/");
        }
    #endif
    }

    public Mesh GetPreGennedMesh ()  {
        return preGennedMeshes[(preGennedIndex++) % preGennedMeshes.Length];
    }

    Mesh CreateMesh () {
        Mesh mesh = new Mesh ();
        // we use world space aligned and not camera aligned planes this time
        Vector3 cameraRight = transform.right * UnityEngine.Random.Range(0.1f,2.0f) + transform.forward * UnityEngine.Random.Range(0.1f,2.0f);// Vector3.forward;//Camera.main.transform.right;
        cameraRight = Vector3.Normalize(cameraRight);
        Vector3 cameraUp = Vector3.Cross(cameraRight, Vector3.up);
        cameraUp = Vector3.Normalize(cameraUp);

        int particleNum = numberOfParticles / 2;

        Vector3[] verts = new Vector3[4 * particleNum];
        Vector2[] uvs  = new Vector2[4 * particleNum];
        Vector2[] uvs2 = new Vector2[4 * particleNum];
        Vector3[] normals = new Vector3[4 * particleNum];

        int[] tris  = new int[2 * 3 * particleNum];

        Vector3 position;
        for (int i  = 0; i < particleNum; i++) {
            int i4  = i * 4;
            int i6  = i * 6;

            position.x = areaSize * (UnityEngine.Random.value - 0.5f);
            position.y = 0.0f;
            position.z = areaSize * (UnityEngine.Random.value - 0.5f);

            float rand   = UnityEngine.Random.value;
            float widthWithRandom  = flakeWidth + rand * flakeRandom;
            float heightWithRandom  = widthWithRandom;

            verts[i4 + 0] = position - cameraRight * widthWithRandom;// - 0.0 * heightWithRandom;
            verts[i4 + 1] = position + cameraRight * widthWithRandom;// - 0.0 * heightWithRandom;
            verts[i4 + 2] = position + cameraRight * widthWithRandom + cameraUp * 2.0f * heightWithRandom;
            verts[i4 + 3] = position - cameraRight * widthWithRandom + cameraUp * 2.0f * heightWithRandom;

            normals[i4 + 0] = -Camera.main.transform.forward;
            normals[i4 + 1] = -Camera.main.transform.forward;
            normals[i4 + 2] = -Camera.main.transform.forward;
            normals[i4 + 3] = -Camera.main.transform.forward;

            uvs[i4 + 0] = new Vector2(0.0f, 0.0f);
            uvs[i4 + 1] = new Vector2(1.0f, 0.0f);
            uvs[i4 + 2] = new Vector2(1.0f, 1.0f);
            uvs[i4 + 3] = new Vector2(0.0f, 1.0f);

            Vector2 tc1  = new Vector2(UnityEngine.Random.Range(0.0f, 1.0f), UnityEngine.Random.Range(0.0f, 1.0f));
            uvs2[i4 + 0] = new Vector2(tc1.x,tc1.y);
            uvs2[i4 + 1] = new Vector2(tc1.x,tc1.y);;
            uvs2[i4 + 2] = new Vector2(tc1.x,tc1.y);;
            uvs2[i4 + 3] = new Vector2(tc1.x,tc1.y);;

            tris[i6 + 0] = i4 + 0;
            tris[i6 + 1] = i4 + 1;
            tris[i6 + 2] = i4 + 2;
            tris[i6 + 3] = i4 + 0;
            tris[i6 + 4] = i4 + 2;
            tris[i6 + 5] = i4 + 3;
        }

        mesh.vertices = verts;
        mesh.triangles = tris;
        mesh.normals = normals;
        mesh.uv = uvs;
        mesh.uv2 = uvs2;
        mesh.RecalculateBounds ();

        return mesh;
    }
}

6.地面涟漪脚本2

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

public class RainsplashBox : MonoBehaviour
{
    private MeshFilter _mf ;
    private Bounds bounds; 

    private RainsplashManager manager ;

    public void Start () {
        transform.localRotation = Quaternion.identity;

        manager = transform.parent.GetComponent<RainsplashManager> ();
        bounds = new Bounds (new Vector3 (transform.position.x,0.0f,transform.position.z),
                             new Vector3 (manager.areaSize,Mathf.Max(manager.areaSize,manager.areaHeight),manager.areaSize));    

        _mf = GetComponent<MeshFilter> ();
        _mf.sharedMesh = manager.GetPreGennedMesh ();        

        enabled = false;
    }

    void OnBecameVisible () {
        enabled = true;
    }

    void OnBecameInvisible () {
        enabled = false;
    }

    void OnDrawGizmos () {
        if (transform.parent) {
            manager = transform.parent.GetComponent<RainsplashManager> ();
            Gizmos.color =new Color(0.5f,0.5f,0.65f,0.5f);
            if(manager)
                Gizmos.DrawWireCube (    transform.position + transform.up * manager.areaHeight * 0.5f,
                                        new Vector3 (manager.areaSize,manager.areaHeight, manager.areaSize) );
        }
    }
}
时间: 2024-10-19 00:18:02

shader之——rain的相关文章

(转)简述47种Shader Map的渲染原理与制作方法

在Shader中会使用各种不同图参与渲染,所以简单地总结下各种图的渲染原理.制作方法,最后面几种是程序生成图. 1. Albedo 2. Diffuse(Photographic) 从上图可以看出来,Albedo是去掉Diffuse的光照和阴影生成的,而在pbr工作流下必须要用Albedo. 转换方法:How to Make an Albedo Texture from a Diffuse Texture 3. Alpha Map 注意:jpg没有alpha通道,png也没有alpha通道,显示

unity shader笔记

clip函数可以用来切割mesh clip(var); var 的值小于0时就会被切割 表面着色器 其实就是生成了定点片元着色器,相当于一种包装和简化吧 标准的填充结构 struct SurfaceOutput { fixed3 Albedo; // diffuse color fixed3 Normal; // tangent space normal, if written fixed3 Emission; half Specular; // specular power in 0..1 r

火云开发课堂 - 《Shader从入门到精通》系列 第一节:Shader介绍与工程搭建

<Shader从入门到精通>系列在线课程 第一节:Shader介绍与工程搭建 视频地址:http://edu.csdn.net/course/detail/1441/22665?auto_start=1 交流论坛:http://www.firestonegames.com/bbs/forum.php 工程下载地址:请成为正式学员获取工程 课程截图: 项目实例: 版权声明:本文为博主原创文章,未经博主允许不得转载.

Qt 3D的研究(五):Gooch Shader

Qt 3D的研究(五):Gooch Shader Qt 3D的一个很大的优势就是采用数据驱动的方式,将C++和GLSL使用QML来表示,动态语言的优势尽显.在上一次的研究中,我实现了一个非常简单的着色器,接下来,我们可以在此基础上,通过设定着色器的数据,制作出更加绚丽的着色效果.作为开始,我们先从几个非真实渲染(Non-Photorealistic Rendering,NPR)开始吧. 蒋彩阳原创文章,首发地址:http://blog.csdn.net/gamesdev/article/deta

游戏框架其九:网和着色器( Mesh and Shader )

网的重要作用可以导入3DMAX等创建的模型,到游戏中:着色器可以实现特定绚丽的效果.它们的实现如下 1. 网 Mesh的实现: #pragma once //======================================================================== // File: Mesh.h - classes to render meshes in D3D9 and D3D11 // 主要是导入3DMAX等软件生成的模型文件 基于Windows Dir

unity3d关于怎样动态改变物体 shader

material = new Material(Shader.Find("Custom/Alpha")); material.SetFloat("_Shininess", materialAlpha); void OnRenderImage(RenderTexture source, RenderTexture destination){Graphics.Blit(source, destination, material);} unity3d关于怎样动态改变物体

HDU 2389 Rain on your Parade

http://acm.hdu.edu.cn/showproblem.php?pid=2389 题意:给暴风雨到来的时刻,m个人的坐标和单位速度,和n个救生衣的坐标.每个救生衣只能匹配一个人,求最多有多少人可以得到救生衣. 题解:典型二分图最大匹配题型.因为点比较多,使用Hopcroft-Karp算法.讲解:http://blog.csdn.net/wall_f/article/details/8248373 http://www.cnblogs.com/-sunshine/archive/201

【Unity Shader】Shader纹理映射的例子

将漫反射的颜色改为从纹理贴图中获取,逐像素计算. Shader "Custom/11-Texture" { // BlinnPhong光照模型 Properties{ //_Diffuse("Diffuse Color", Color) = (1,1,1,1) // 可在编辑器面板定义材质自身色彩 _MainTex("Main Tex",2D) = "white"{} // 纹理贴图,默认是一张白色贴图 _Color(&quo

【译】Unity3D Shader 新手教程(2/6) &mdash;&mdash; 积雪Shader

如果你是一个shader编程的新手,并且你想学到下面这些酷炫的技术,我觉得你可以看看这篇教程: 实现一个积雪效果的shader 创建一个具有凹凸纹理的shader 为每个像素修改其对应纹理值 在表面着色器中修改模型的顶点数据 引论 这是我们系列教程的第二部分,我们将在此部分实现些有用的技术.在学习完第一部分的所有背景知识后,我们将利用所学的知识实现一个简单的积雪效果的shader.效果如下: 准备工作 我们想做的其实很简单,简单介绍一下: 随着Snow Level(表示积雪的程度,该值越大,积雪