图像粒子化
作者:追风剑情 发布于:2021-8-9 16:31 分类:Unity3d
关键技术:GPU实例、Graphics.DrawMeshInstancedIndirect()
工程截图
处理粒子化的Shader(仅支持DX11)
//图像粒子化Shader Shader "Custom/ImageParticleShader" { Properties{ //要显示的图像 _MainTex("Albedo (RGB)", 2D) = "white" {} //粒子遮罩 _MaskTex("Mask", 2D) = "white" {} _Glossiness("Smoothness", Range(0,1)) = 0.5 _Metallic("Metallic", Range(0,1)) = 0.0 } SubShader{ Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" "PreviewType" = "Plane" } LOD 200 Blend SrcAlpha OneMinusSrcAlpha ColorMask RGB Cull Off Lighting Off ZWrite Off CGPROGRAM // Physically based Standard lighting model #pragma surface surf Standard addshadow fullforwardshadows alpha:fade #pragma multi_compile_instancing //指定为每个顶点调用一次配置函数setup #pragma instancing_options procedural:setup sampler2D _MainTex; sampler2D _MaskTex; struct Input { float2 uv_MainTex; }; #ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED StructuredBuffer<float4> positionBuffer; StructuredBuffer<float4> blockBuffer; #endif void setup() { //仅应针对专为程序绘制而编译的着色器变体执行此操作 //https://cloud.tencent.com/developer/article/1799606 #ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED float4 data = positionBuffer[unity_InstanceID]; //设置转换矩阵,将顶点从对象空间转到世界空间 //设置缩放 unity_ObjectToWorld._11_21_31_41 = float4(data.w, 0, 0, 0); unity_ObjectToWorld._12_22_32_42 = float4(0, data.w, 0, 0); unity_ObjectToWorld._13_23_33_43 = float4(0, 0, data.w, 0); //设置坐标 unity_ObjectToWorld._14_24_34_44 = float4(data.xyz, 1); //还有一个unity_WorldToObject矩阵,其中包含逆变换,用于变换法向量。当应用非均匀变形时,需要正确地变换方向矢量。 //unity_WorldToObject与unity_ObjectToWorld互为逆变换 unity_WorldToObject = unity_ObjectToWorld; //可以通过简单地使用负位置和缩放的倒数来构造它。 unity_WorldToObject._14_24_34 *= -1; unity_WorldToObject._11_22_33 = 1.0f / unity_WorldToObject._11_22_33; #endif } half _Glossiness; half _Metallic; void surf(Input IN, inout SurfaceOutputStandard o) { #ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED float2 uv = IN.uv_MainTex; fixed4 mask = tex2D(_MaskTex, uv); //映射uv到一个像素块区域 float4 block = blockBuffer[unity_InstanceID]; uv.x = block.x + uv.x * block.z; uv.y = block.y + uv.y * block.w; fixed4 c = tex2D(_MainTex, uv); o.Albedo = c.rgb; o.Metallic = _Metallic; o.Smoothness = _Glossiness; o.Alpha = c.a * mask.a; #else fixed4 col = tex2D(_MainTex, IN.uv_MainTex); o.Albedo = col.rgb; o.Metallic = _Metallic; o.Smoothness = _Glossiness; o.Alpha = col.a; #endif } ENDCG } FallBack "Diffuse" }
创建材质球
创建C#脚本
using UnityEngine; /// <summary> /// 图片粒子化 /// </summary> public class ImageParticle : MonoBehaviour { public Texture2D mainTexture; [Range(0.001f, 1)] public float particleScale = 0.01f; [Range(0f, 0.05f)] public float gap = 0f; public Mesh instanceMesh; public Material instanceMaterial; public int subMeshIndex = 0; public int instanceCount; private ComputeBuffer positionBuffer; private ComputeBuffer argsBuffer; private ComputeBuffer blockBuffer; //每个实例的索引数、实例数、起始索引位置、基顶点位置、起始实例位置 private uint[] args = new uint[5] { 0, 0, 0, 0, 0 }; private float gap_t = 1.87f; //创建粒子Mesh private Mesh CreateMesh() { //矩形的四个顶点坐标 Vector3[] vertices = new Vector3[4]; vertices[0] = new Vector3(0, 0, 0); vertices[1] = new Vector3(1f, 0, 0); vertices[2] = new Vector3(1f, 1f, 0); vertices[3] = new Vector3(0, 1f, 0); //三角形顶点索引 int[] triangles = new int[6] { 0, 1, 2, 2, 3, 0 }; //每个顶点的法线 Vector3[] normals = new Vector3[4]; normals[0] = new Vector3(0, 0, -5); normals[1] = new Vector3(0, 0, -5); normals[2] = new Vector3(0, 0, -5); normals[3] = new Vector3(0, 0, -5); //UV贴图坐标 Vector2[] uvs = new Vector2[4]; uvs[0] = new Vector2(0, 0); uvs[1] = new Vector2(1, 0); uvs[2] = new Vector2(1, 1); uvs[3] = new Vector2(0, 1); //顶点颜色 Color32[] colors32 = new Color32[4]; byte r = (byte)Random.Range(0, 255); Color32 color = new Color32(r, r, r, 255); colors32[3] = colors32[2] = colors32[1] = colors32[0] = color; //colors32[0] = new Color32(255, 0, 0, 255); //colors32[1] = new Color32(255, 0, 0, 255); //colors32[2] = new Color32(255, 0, 0, 255); //colors32[3] = new Color32(255, 0, 0, 255); Mesh mesh = new Mesh(); mesh.hideFlags = HideFlags.DontSave; mesh.vertices = vertices; mesh.triangles = triangles; mesh.colors32 = colors32; mesh.uv = uvs; mesh.normals = normals; return mesh; } void Start() { if (instanceMesh == null) instanceMesh = CreateMesh(); argsBuffer = new ComputeBuffer(1, args.Length * sizeof(uint), ComputeBufferType.IndirectArguments); UpdateBuffers(); } void Update() { if (!Mathf.Approximately(gap, gap_t)) UpdateBuffers(); // GPU绘制实例 Graphics.DrawMeshInstancedIndirect(instanceMesh, subMeshIndex, instanceMaterial, new Bounds(Vector3.zero, new Vector3(200.0f, 200.0f, 200.0f)), argsBuffer); } void UpdateBuffers() { // Ensure submesh index is in range if (instanceMesh != null) subMeshIndex = Mathf.Clamp(subMeshIndex, 0, instanceMesh.subMeshCount - 1); // Positions if (positionBuffer != null) positionBuffer.Release(); // Pixel Block if (blockBuffer != null) blockBuffer.Release(); // Pixel Block (每个粒子就是一个像素块) int blockWidth = 16; int blockHeight = 16; int blockXCount = mainTexture.width / blockWidth; int blockYCount = mainTexture.height / blockHeight; int blockCount = blockXCount * blockYCount; instanceCount = blockCount; int texWidth = blockXCount * blockWidth; int texHeight = blockYCount * blockHeight; float widthScale = (float)blockWidth / (float)texWidth; float heightScale = (float)blockHeight / (float)texHeight; blockBuffer = new ComputeBuffer(blockCount, 16); positionBuffer = new ComputeBuffer(blockCount, 16); Vector4[] blocks = new Vector4[blockCount]; Vector4[] positions = new Vector4[blockCount]; for (int y = 0; y < blockYCount; y++) { float v = (float)y / (float)blockYCount; for (int x = 0; x < blockXCount; x++) { float u = (float)x / (float)blockXCount; Vector4 block = new Vector4(u, v, widthScale, heightScale); int index = y * blockXCount + x; blocks[index] = block; positions[index] = new Vector4((particleScale + gap) * x, (particleScale + gap) * y, 0, particleScale); } } positionBuffer.SetData(positions); instanceMaterial.SetBuffer("positionBuffer", positionBuffer); blockBuffer.SetData(blocks); instanceMaterial.SetBuffer("blockBuffer", blockBuffer); gap_t = gap; // Indirect args if (instanceMesh != null) { args[0] = (uint)instanceMesh.GetIndexCount(subMeshIndex); args[1] = (uint)instanceCount; args[2] = (uint)instanceMesh.GetIndexStart(subMeshIndex); args[3] = (uint)instanceMesh.GetBaseVertex(subMeshIndex); } else { args[0] = args[1] = args[2] = args[3] = 0; } argsBuffer.SetData(args); instanceMaterial.SetTexture("_MainTex", mainTexture); } void OnDisable() { if (positionBuffer != null) positionBuffer.Release(); positionBuffer = null; if (blockBuffer != null) blockBuffer.Release(); blockBuffer = null; if (argsBuffer != null) argsBuffer.Release(); argsBuffer = null; } }
运行测试
Scene窗口截图
Game窗口截图
动态调整粒子间距
标签: Unity3d
日历
最新文章
随机文章
热门文章
分类
存档
- 2024年11月(3)
- 2024年10月(5)
- 2024年9月(3)
- 2024年8月(3)
- 2024年7月(11)
- 2024年6月(3)
- 2024年5月(9)
- 2024年4月(10)
- 2024年3月(11)
- 2024年2月(24)
- 2024年1月(12)
- 2023年12月(3)
- 2023年11月(9)
- 2023年10月(7)
- 2023年9月(2)
- 2023年8月(7)
- 2023年7月(9)
- 2023年6月(6)
- 2023年5月(7)
- 2023年4月(11)
- 2023年3月(6)
- 2023年2月(11)
- 2023年1月(8)
- 2022年12月(2)
- 2022年11月(4)
- 2022年10月(10)
- 2022年9月(2)
- 2022年8月(13)
- 2022年7月(7)
- 2022年6月(11)
- 2022年5月(18)
- 2022年4月(29)
- 2022年3月(5)
- 2022年2月(6)
- 2022年1月(8)
- 2021年12月(5)
- 2021年11月(3)
- 2021年10月(4)
- 2021年9月(9)
- 2021年8月(14)
- 2021年7月(8)
- 2021年6月(5)
- 2021年5月(2)
- 2021年4月(3)
- 2021年3月(7)
- 2021年2月(2)
- 2021年1月(8)
- 2020年12月(7)
- 2020年11月(2)
- 2020年10月(6)
- 2020年9月(9)
- 2020年8月(10)
- 2020年7月(9)
- 2020年6月(18)
- 2020年5月(4)
- 2020年4月(25)
- 2020年3月(38)
- 2020年1月(21)
- 2019年12月(13)
- 2019年11月(29)
- 2019年10月(44)
- 2019年9月(17)
- 2019年8月(18)
- 2019年7月(25)
- 2019年6月(25)
- 2019年5月(17)
- 2019年4月(10)
- 2019年3月(36)
- 2019年2月(35)
- 2019年1月(28)
- 2018年12月(30)
- 2018年11月(22)
- 2018年10月(4)
- 2018年9月(7)
- 2018年8月(13)
- 2018年7月(13)
- 2018年6月(6)
- 2018年5月(5)
- 2018年4月(13)
- 2018年3月(5)
- 2018年2月(3)
- 2018年1月(8)
- 2017年12月(35)
- 2017年11月(17)
- 2017年10月(16)
- 2017年9月(17)
- 2017年8月(20)
- 2017年7月(34)
- 2017年6月(17)
- 2017年5月(15)
- 2017年4月(32)
- 2017年3月(8)
- 2017年2月(2)
- 2017年1月(5)
- 2016年12月(14)
- 2016年11月(26)
- 2016年10月(12)
- 2016年9月(25)
- 2016年8月(32)
- 2016年7月(14)
- 2016年6月(21)
- 2016年5月(17)
- 2016年4月(13)
- 2016年3月(8)
- 2016年2月(8)
- 2016年1月(18)
- 2015年12月(13)
- 2015年11月(15)
- 2015年10月(12)
- 2015年9月(18)
- 2015年8月(21)
- 2015年7月(35)
- 2015年6月(13)
- 2015年5月(9)
- 2015年4月(4)
- 2015年3月(5)
- 2015年2月(4)
- 2015年1月(13)
- 2014年12月(7)
- 2014年11月(5)
- 2014年10月(4)
- 2014年9月(8)
- 2014年8月(16)
- 2014年7月(26)
- 2014年6月(22)
- 2014年5月(28)
- 2014年4月(15)
友情链接
- Unity官网
- Unity圣典
- Unity在线手册
- Unity中文手册(圣典)
- Unity官方中文论坛
- Unity游戏蛮牛用户文档
- Unity下载存档
- Unity引擎源码下载
- Unity服务
- Unity Ads
- wiki.unity3d
- Visual Studio Code官网
- SenseAR开发文档
- MSDN
- C# 参考
- C# 编程指南
- .NET Framework类库
- .NET 文档
- .NET 开发
- WPF官方文档
- uLua
- xLua
- SharpZipLib
- Protobuf-net
- Protobuf.js
- OpenSSL
- OPEN CASCADE
- JSON
- MessagePack
- C在线工具
- 游戏蛮牛
- GreenVPN
- 聚合数据
- 热云
- 融云
- 腾讯云
- 腾讯开放平台
- 腾讯游戏服务
- 腾讯游戏开发者平台
- 腾讯课堂
- 微信开放平台
- 腾讯实时音视频
- 腾讯即时通信IM
- 微信公众平台技术文档
- 白鹭引擎官网
- 白鹭引擎开放平台
- 白鹭引擎开发文档
- FairyGUI编辑器
- PureMVC-TypeScript
- 讯飞开放平台
- 亲加通讯云
- Cygwin
- Mono开发者联盟
- Scut游戏服务器引擎
- KBEngine游戏服务器引擎
- Photon游戏服务器引擎
- 码云
- SharpSvn
- 腾讯bugly
- 4399原创平台
- 开源中国
- Firebase
- Firebase-Admob-Unity
- google-services-unity
- Firebase SDK for Unity
- Google-Firebase-SDK
- AppsFlyer SDK
- android-repository
- CQASO
- Facebook开发者平台
- gradle下载
- GradleBuildTool下载
- Android Developers
- Google中国开发者
- AndroidDevTools
- Android社区
- Android开发工具
- Google Play Games Services
- Google商店
- Google APIs for Android
- 金钱豹VPN
- TouchSense SDK
- MakeHuman
- Online RSA Key Converter
- Windows UWP应用
- Visual Studio For Unity
- Open CASCADE Technology
- 慕课网
- 阿里云服务器ECS
- 在线免费文字转语音系统
- AI Studio
- 网云穿
- 百度网盘开放平台
- 迅捷画图
- 菜鸟工具
- [CSDN] 程序员研修院
- 华为人脸识别
- 百度AR导航导览SDK
- 海康威视官网
- 海康开放平台
- 海康SDK下载
- git download
交流QQ群
-
Flash游戏设计: 86184192
Unity游戏设计: 171855449
游戏设计订阅号