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 有什么表达方式?
- compute shader 粒子?
- compute shader 粒子!
3.compute shader 粒粒子??!!
好一个Compute Shader!!!
微软官网经典图解
微软官网经典图解
- Use the “Dispatch” in C#
我调用“ComputeShader.Dispatch(int kernelID,int x,int y,int z)” 分配了32x32个组线程给computeshader,所以组的ID(SV_GroupID)范围在(32,32,1)内,当然你也可以把它看成一种坐标。
每组里包含了许多线程,所以这个Dispatch 分配的是线程组数
由图所示,很明显我画了3x3个组,每个格子包含了线程,基本意思就是这样,当然z轴方向也是可以划分的。(当然并不完全是图中完全那么个意思,看你怎么分配和规划)
- Use the “[numthreads(x,y,z)]” in compute shader
分配完组,就需要说明组里有多少个线程数。所以我用numthreads(x,y,z)分配了4x4,当然z方向也是可以分配的。
一共线程数为Dispatch*numthreads = (32x32x1) x (4x4x1)= 16384(线程/个)
很明显一个点代表一个线程,如果你想让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<float3> 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<float3> 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.点版效果
2.线条版效果
3.连线版效果
效果增强
由于unity sampler2D 的stat默认模式
你可以移动uv,
变换点坐标
最终效果图
特效中的特效