Unity Shader学习:CPU/GPU boid

参考:https://github.com/chenjd/Unity-Boids-Behavior-on-GPGPU
https://www.youtube.com/watch?v=bqtqltqcQhw

CPU:加入了射线碰撞

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class CPUBoid : MonoBehaviour {public Transform[] centers;public Transform[] boids;public float speed = 1f;public float nearbyDis = 1f;private float tempDis;private Vector3 separation;private Vector3 alignment;private Vector3 cohesion;private Vector3 tempCohesion;private Vector3 direction;private int nearbyCount;private Vector3 toCenter;private Quaternion tempRotation;private RaycastHit hit;private Ray ray;private Vector3 tempDir;private bool isHit=false;private Transform center;void Start () {getColliderDirections();center = centers[0];}void LateUpdate () {for (int i = 0; i < boids.Length; i++){separation = Vector3.zero;alignment = Vector3.zero;cohesion = Vector3.zero;tempCohesion = Vector3.zero;nearbyCount = 0;toCenter = Vector3.Normalize(center.position - boids[i].position);for (int j = 0; j < boids.Length; j++){if (i!=j){tempDis = Vector3.Distance(boids[i].position, boids[j].position);if (tempDis<nearbyDis&&Vector3.Dot(Vector3.Normalize( boids[j].position- boids[i].position), boids[i].forward)>-0.5f){separation += boids[i].position - boids[j].position;alignment += boids[j].forward;tempCohesion+= boids[j].position;nearbyCount++;}}}if (nearbyCount>0){alignment *= 1 / nearbyCount;tempCohesion *= 1 / nearbyCount;}cohesion += tempCohesion;direction = alignment + separation + Vector3.Normalize(cohesion - boids[i].position);Vector3 t = toCenter;Vector3 tt= Vector3.Lerp(boids[i].forward, direction, Time.deltaTime);t = Vector3.Lerp(t, tt, 0.95f);ray = new Ray(boids[i].position, t);if (Physics.SphereCast(ray, 1f, 1f)){isHit = true;for (int k = 0; k < directions.Length; k++){tempDir = boids[i].TransformDirection(directions[k]);ray = new Ray(boids[i].position, tempDir);if (!Physics.SphereCast(ray, 1f, 3f)){tempDir = boids[i].TransformDirection(directions[k]);break;}}}if (isHit){isHit = false;t = Vector3.Lerp(t,tempDir,1f);}boids[i].rotation = Quaternion.LookRotation(t,boids[i].up);boids[i].position += speed * t * Time.deltaTime;}}private int numViewDirections = 300;private Vector3[] directions;void getColliderDirections(){directions = new Vector3[numViewDirections];float goldenRatio = (1 + Mathf.Sqrt(5)) / 2;float angleIncrement = Mathf.PI * 2 * goldenRatio;for (int i = 0; i < numViewDirections; i++){float t = (float)i / numViewDirections;float inclination = Mathf.Acos(1 - 2 * t);float azimuth = angleIncrement * i;float x = Mathf.Sin(inclination) * Mathf.Cos(azimuth);float y = Mathf.Sin(inclination) * Mathf.Sin(azimuth);float z = Mathf.Cos(inclination);directions[i] = new Vector3(x, y, z);}}
}

GPU:没有碰撞,基于compute shader,需要构建旋转矩阵
c#部分:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public struct BoidData
{public Vector3 pos;public Vector3 rot;
}public class ZzcGPUBoid : MonoBehaviour {public ComputeShader computeShader;public int boidsCount;public float nearbyDis;public float flockSpeed;public Material boidMat;public Mesh boidMesh;public Transform target;private int kernelIndex;private BoidData[] boidData;private ComputeBuffer Buffer;private int stride;private ComputeBuffer positionBuffer;private ComputeBuffer argsBuffer;private uint[] args = new uint[5] { 0, 0, 0, 0, 0 };private int subMeshIndex = 0;private int cachedInstanceCount = -1;private int cachedSubMeshIndex = -1;private Bounds bounds = new Bounds(Vector3.zero, Vector3.one * 100f);// Use this for initializationvoid Start () {int vector3Stride= sizeof(float) * 3;stride = vector3Stride * 2;Buffer = new ComputeBuffer(boidsCount, stride);kernelIndex = computeShader.FindKernel("CSMain");boidData = new BoidData[boidsCount];for (int i = 0; i < boidData.Length; i++){boidData[i] = new BoidData();boidData[i].pos = Vector3.right * i;boidData[i].rot = Vector3.Normalize( new Vector3(Random.Range(0f,1f), Random.Range(0f, 1f), Random.Range(0f, 1f)));}computeShader.SetFloat("nearbyDis", nearbyDis);computeShader.SetFloat("speed", flockSpeed);computeShader.SetInt("boidsCount", boidsCount);Buffer.SetData(boidData);computeShader.SetBuffer(kernelIndex, "boidBuffer", Buffer);boidMat.SetBuffer("positionBuffer", Buffer);argsBuffer = new ComputeBuffer(1, args.Length * sizeof(uint), ComputeBufferType.IndirectArguments);UpdateBuffers();}void Update () {if (cachedInstanceCount != boidsCount || cachedSubMeshIndex != subMeshIndex)UpdateBuffers();computeShader.SetFloat("deltaTime", Time.deltaTime);computeShader.SetVector("flockPos", target.position);computeShader.Dispatch(kernelIndex, boidsCount, 1, 1);Graphics.DrawMeshInstancedIndirect(boidMesh, subMeshIndex, boidMat, bounds, argsBuffer);}void UpdateBuffers(){if (boidMesh!=null){subMeshIndex = Mathf.Clamp(subMeshIndex, 0, boidMesh.subMeshCount - 1);}if (boidMesh!=null){args[0] = (uint)boidMesh.GetIndexCount(subMeshIndex);args[1] = (uint)boidsCount;args[2] = (uint)boidMesh.GetIndexStart(subMeshIndex);args[3] = (uint)boidMesh.GetBaseVertex(subMeshIndex);}else{args[0] = 0;args[1] = 0;args[2] = 0;args[3] = 0;}argsBuffer.SetData(args);cachedInstanceCount = boidsCount;cachedSubMeshIndex = subMeshIndex;}private void OnDisable(){if (positionBuffer!=null){positionBuffer.Release();}positionBuffer = null;if (argsBuffer!=null){argsBuffer.Release();}argsBuffer = null;Buffer.Release();}
}

compute shader部分:

#pragma kernel CSMainstruct Boid {float3 pos;float3 rot;
};RWStructuredBuffer<Boid> boidBuffer;
float deltaTime;
float speed;
float nearbyDis;
int boidsCount;
float3 flockPos;[numthreads(128,1,1)]
void CSMain (uint3 id : SV_DispatchThreadID)
{Boid boid = boidBuffer[id.x];float3 pos = boid.pos;float3 rot = boid.rot;float3 separation = float3(0, 0, 0);float3 alignment = float3(0, 0, 0);float3 cohesion = flockPos;float3 tempCohesion = float3(0, 0, 0);float tempSpeed = 0;int nearbyCount = 0;[loop]for (int i = 0; i < int(boidsCount); i++){if (i!=int(id.x)){Boid tempBoid = boidBuffer[i];if (length(boid.pos-tempBoid.pos)<nearbyDis){separation += boid.pos - tempBoid.pos;alignment += tempBoid.rot;tempCohesion += tempBoid.pos;nearbyCount++;              }       }}if (nearbyCount>0){alignment *= 1 / nearbyCount;tempCohesion *= 1 / nearbyCount;}cohesion += tempCohesion;float3 direction = alignment + separation + normalize(cohesion - boid.pos);boid.rot = lerp(boid.rot, normalize(direction), deltaTime*4);boid.rot = normalize(boid.rot);boid.pos += boid.rot*speed*deltaTime;boidBuffer[id.x] = boid;
}

着色shader:

Shader "Instanced/InstancedShader" {Properties{_MainTex("Albedo (RGB)", 2D) = "white" {}}SubShader{Pass {Tags {"LightMode" = "ForwardBase"}CGPROGRAM#pragma vertex vert#pragma fragment frag#pragma target 4.5#include "UnityCG.cginc"#include "UnityLightingCommon.cginc"#include "AutoLight.cginc"sampler2D _MainTex;struct Boid {float3 pos;float3 rot;};#if SHADER_TARGET >= 45StructuredBuffer<Boid> positionBuffer;#endifstruct v2f{float4 pos : SV_POSITION;float2 uv_MainTex : TEXCOORD0;float3 normal:NORMAL;};float3x3 rotateMatrix(float angle, float3 axis) {float u0 = axis.x;float u1 = axis.y;float u2 = axis.z;float3x3 r = float3x3(cos(angle) + u0 * u0*(1 - cos(angle)),u0*u1*(1 - cos(angle) - u2 * sin(angle)),u1*sin(angle) + u0 * u2*(1 - cos(angle)),u2*sin(angle) + u0 * u1*(1 - cos(angle)),cos(angle) + u1 * u1*(1 - cos(angle)),-u0 * sin(angle) + u1 * u2*(1 - cos(angle)),-u1 * sin(angle) + u0 * u2*(1 - cos(angle)),u0*sin(angle) + u1 * u2*(1 - cos(angle)),cos(angle) + u2 * u2*(1 - cos(angle)));return r;}float3x3 calculationRotateMatrix(float3 vectorBefore, float3 vectorAfter) {float3 rotationAxis = cross(vectorBefore, vectorAfter);float rotationAngle=acos(dot(vectorBefore,vectorAfter)) ;return rotateMatrix(rotationAngle,rotationAxis);}             v2f vert(appdata_full v, uint instanceID : SV_InstanceID){#if SHADER_TARGET >= 45float3 data = positionBuffer[instanceID].pos.xyz;#elsefloat3 data = 0;#endiffloat3x3 rotMatrix = calculationRotateMatrix(float3(0, 0, 1), positionBuffer[instanceID].rot.xyz);v.vertex.xyz = mul(rotMatrix,v.vertex.xyz);float3 worldPosition = data.xyz+ v.vertex.xyz;v2f o;o.pos = mul(UNITY_MATRIX_VP, float4(worldPosition, 1.0f));o.uv_MainTex = v.texcoord;o.normal = v.normal;return o;}fixed4 frag(v2f i) : SV_Target{return saturate(dot( i.normal , _WorldSpaceLightPos0.xyz ))*0.5+0.5 ;}ENDCG}}
}

Unity Shader学习:CPU/GPU boid相关推荐

  1. 《Unity Shader入门精要》学习笔记第5章 开始Unity Shader学习之旅

    本文章用于帮助自己学习,因此只记录一些个人认为比较重要或者还不够熟悉的内容. 原作者:http://blog.csdn.net/candycat1992/article/ 第五章 开始Unity Sh ...

  2. Unity Shader 学习笔记(33) 全局光照(GI)、反射探针、线性空间和伽马空间、高动态范围(HDR)

    Unity Shader 学习笔记(33) 全局光照(GI).反射探针.线性空间和伽马空间.高动态范围(HDR) 参考书籍:<Unity Shader 入门精要> [<Real-Ti ...

  3. Unity Shader学习-高光反射

    Unity Shader学习-高光反射 高光反射计算公式 高光反射 = 光源的色彩和强度 * 材质的高光反射系数 * pow(max(0,视角方向 · 反射方向),_Gloss) 视角方向 = ref ...

  4. Unity Shader学习:SSAO屏幕环境光遮蔽

    Unity Shader学习:SSAO屏幕环境光遮蔽 主要思路:1.随机采样像素法线半球周围的像素,平均对比与该像素深度是否处在暗处.2.双边滤波去噪点.3.后期AO图与原图混合. 原文链接:http ...

  5. Unity Shader学习:动态模糊(shutter angle方式)

    Unity Shader学习:动态模糊 动态模糊一般有帧混合和motion vector两种,这里主要介绍motion vector的方法. Keijiro源码:https://github.com/ ...

  6. Unity Shader学习:水墨效果

    Unity Shader学习:水墨效果 偶然在网上看到9级铁甲蛹大神的水墨风格后处理觉得挺有意思,参照着实现一下,还是涉及到之前油画效果的算法,叫什么滤波暂时不清楚,应该用来处理手绘效果挺多的. 水墨 ...

  7. Unity Shader学习:体积光/体积阴影

    Unity Shader学习:体积光/体积阴影 在前向渲染下实现平行光的体积光影效果,需要全屏深度图,延迟渲染会更划算. 思路:通过ray marching的步进点位置计算该点是否在阴影中,采样阴影贴 ...

  8. Unity Shader学习:SSR屏幕空间反射

    Unity Shader学习:SSR屏幕空间反射 本文在前向渲染模式下实现,延迟渲染更适合SSR,这里只简单的实现下,未作更深入的优化. 思路:沿视线和法线的反射向量步进光线,判断打到物体(这里用的是 ...

  9. Unity Shader学习:Dissolve消融效果

    Unity Shader学习:Dissolve消融效果 消融效果在游戏里非常常用,这里简单的实现下,代码里用到了if分支在shader里可能会费一点,如果想直接用puppet_master大佬版本的话 ...

最新文章

  1. mysql association_mybatis association 一对一
  2. python中使用zip函数基于两个列表数据list创建字典dict数据(Create a dictionary by passing the output of zip to dict)
  3. python爬网页数据用什么_初学者如何用“python爬虫”技术抓取网页数据?
  4. document.getElementById 学习总结
  5. P1020 导弹拦截(n*log n时间的最长上升子序列思想)
  6. 《信息通信技术与政策》丨盖国强:中国数据库服务生态与体系
  7. python判断字符串,str函数isdigit、isdecimal、isnumeric的区别
  8. 详实!DevOps 最新现状研究报告解读 | 原力计划
  9. ARM处理器的9种模式详解
  10. 英文论文写作LaTeX模板
  11. 程序员亲试,人体工学椅真的有用吗?
  12. 神舟Z7-KP7SC笔记本电脑-游戏实机帧数截图与鲁大师跑分
  13. Tomcat无法启动,报错java.lang.NoClassDefFoundError: or...
  14. 一位小公司CTO的成长历程
  15. 关于《机器学习决策树导出图片、PDF支持中文》解决办法
  16. 【2019蓝桥杯国赛B组】排列数
  17. 各种机械键盘轴的差别,究竟什么轴好
  18. Openlayers各种下载方法
  19. Kernel Trick
  20. 冯唐和蔡康永给新养医美做广告

热门文章

  1. 华云数据参与由信标委归口的4项云计算国家标准立项工作
  2. 汽车零配件行业MES方案,打造全面透明化管理模式
  3. 某种产品中,合格品率为85%,一个合格品被检查成次品的概率是10%,一个次品被检查成合格品的概率为5%,问题:求一个被检查成合格品的产品确实为合格品的概率()?
  4. [Xmind]关于Xmind的使用方法
  5. 网红赚钱主要靠道具系统,直播会沦为在线秀场吗?
  6. c/c++中字符串的基本操作API
  7. 如何高效阅读芯片英文datasheet
  8. 初学者之路——————水下通信
  9. 2010软件收入百强企业出炉:华为居首
  10. 校园网络整体解决方案