Unity3D Compute shader 新解-图片粒子矩阵【一】

Unity3D Compute shader 新解-图片粒子矩阵【一】

1.unity3D scripts 给了许多的方便,本地API也方便阅读。
2.unity shader写起来不算很棘手,官方也是很支持CG。
3.至于Compute shader,微软出了DirectCompute d3d11 API,unity也相当要提供了。


  • 转载复制请尊重原作者
    转载请 出处博客http://blog.csdn.net/baidu_26153715/article/details/45567885 恬纳微晰

Compute shader 有什么表达方式?

  1. compute shader 粒子?

    Unity3D Compute shader 新解-图片粒子矩阵【一】_第1张图片
  2. compute shader 粒子!
    Unity3D Compute shader 新解-图片粒子矩阵【一】_第2张图片
    3.compute shader 粒粒子??!!
    Unity3D Compute shader 新解-图片粒子矩阵【一】_第3张图片

好一个Compute Shader!!!


微软官网经典图解
Unity3D Compute shader 新解-图片粒子矩阵【一】_第4张图片

微软官网经典图解


  • Use the “Dispatch” in C#
    这里写图片描述
    我调用“ComputeShader.Dispatch(int kernelID,int x,int y,int z)” 分配了32x32个组线程给computeshaderUnity3D Compute shader 新解-图片粒子矩阵【一】_第5张图片,所以组的ID(SV_GroupID)范围在(32,32,1)内,当然你也可以把它看成一种坐标。

每组里包含了许多线程,所以这个Dispatch 分配的是线程组数
Unity3D Compute shader 新解-图片粒子矩阵【一】_第6张图片
由图所示,很明显我画了3x3个组,每个格子包含了线程,基本意思就是这样,当然z轴方向也是可以划分的。(当然并不完全是图中完全那么个意思,看你怎么分配和规划)

  • Use the “[numthreads(x,y,z)]” in compute shader
    这里写图片描述
    分配完组,就需要说明组里有多少个线程数。所以我用numthreads(x,y,z)分配了4x4,当然z方向也是可以分配的。

一共线程数为Dispatch*numthreads = (32x32x1) x (4x4x1)= 16384(线程/个)
Unity3D Compute shader 新解-图片粒子矩阵【一】_第7张图片
很明显一个点代表一个线程,如果你想让GPU上的每个 管线 代表一个线程,那么你就要分配的线程数与管线数相当。

C#

using UnityEngine;
using System.Collections;

public class cs : MonoBehaviour {

    public ComputeShader comshader;   //代码一切归 恬纳微晰
    public Shader shader;             //代码一切归 恬纳微晰
    private ComputeBuffer P;          //代码一切归 恬纳微晰
    public Material mat;              //代码一切归 恬纳微晰
    int kernel;


    // Use this for initialization
    void Start () {
        P = new ComputeBuffer(16384,12); //设置P Buffer的大小,12为字节大小(float3),
        kernel = comshader.FindKernel("Main");//找到Main的id号
    }


    // Update is called once per frame

    private void OnRenderObject(){
        comshader.SetBuffer(kernel, "P",P);//给compute shader设置P


        comshader.Dispatch(kernel,32 , 32, 1);

        mat.SetBuffer("P", P); //给shader设置P
        mat.SetPass(0);//指定shader的pass渲染
        Graphics.DrawProcedural(MeshTopology.Points, 16384);//在屏幕绘制点
    }

    private void OnDestroy(){
        P.Release();//释放buffer
    }



}

Compute Shader

// Each #kernel tells which function to compile; you can have many kernels
#pragma kernel Main

// Create a RenderTexture with enableRandomWrite flag and set it
struct pp{                //代码一切归 恬纳微晰
    float3 position;      //代码一切归 恬纳微晰
};                        //代码一切归 恬纳微晰

RWStructuredBuffer P;//float3 可以是上面的PP,那么P[id].position这么调用了,不过我这儿用不着。

[numthreads(4,4,1)]
void Main (uint3 id : SV_DispatchThreadID)
{
    uint f = id.x + id.y*4*32 ;//0~16384,如果不怎么理解,你可以用for()结合P[]

    P[f] = float3(id.x,id.y,id.z)/1.7 + float3(0,0,0);//缩放了粒子间的间距

}

Shader

Shader "Custom/c_s" {
    Properties {
        _MainTex ("Base (RGB)", 2D) = "white" {} //代码一切归 恬纳微晰
    }                                            //代码一切归 恬纳微晰
                                                 //代码一切归 恬纳微晰

    SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 200

        Pass{
            Blend Off Lighting Off Cull Off ZWrite Off ZTest Off AlphaTest Off//废话留着
            CGPROGRAM
            #pragma target 5.0
            #pragma vertex vert 
            #pragma fragment frag 
            #include "UnityCG.cginc"

            StructuredBuffer P;//存有点位置

            sampler2D _MainTex;

            struct vertIN{
                uint id : SV_VertexID;
            };

            struct vertOUT{
                float4 pos : SV_POSITION;
                float3 uv : TEXCOORD0;
            };

            vertOUT vert(vertIN i){
                vertOUT o;
                    float3 pos= P [i.id]; //存储点的位置,P buffer中在compute shader以放置了点位置

                    o.pos = mul(UNITY_MATRIX_VP,float4(pos ,1)); //从世界坐标变换到视平空间

                    o.uv = P[i.id]/128; //128=32x4,32为组的x方向组数量,4为每组x方向的线程数
                    //把uv值确定在(0,1)的区间内
                return o;
            }

            fixed4 frag(vertOUT ou):COLOR{

                fixed4 c = tex2D(_MainTex,ou.uv*1.7);//1.7是因为compute shader中我缩放了点的位置除以了1.7,为了是让点之间密集些,当然uv也就对齐不到点上了
                不过uv其实是世界坐标上的xy,就不像模型表面切线空间的uv了就随着模型表面绑着。
                return c;

            }
            ENDCG
        }
    } 
    FallBack "代码归 恬纳微晰 所有!!!"
}
  • 效果一览
    1.点版效果
    Unity3D Compute shader 新解-图片粒子矩阵【一】_第8张图片
    2.线条版效果
    Unity3D Compute shader 新解-图片粒子矩阵【一】_第9张图片
    3.连线版效果
    Unity3D Compute shader 新解-图片粒子矩阵【一】_第10张图片

效果增强

由于unity sampler2D 的stat默认模式

你可以移动uv,
这里写图片描述
变换点坐标
这里写图片描述
最终效果图

特效中的特效

你可能感兴趣的:(Unity,unity特效,shader,Unity-DX11,Unity,Shader,in,my,life)