热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Unity3DGPUInstancing测试

GPUinstancing很早就支持手机了(Android只支持OpenglES3.0),最近在调研这个就对它测试了一下。如果是不动的物体

GPU instancing 很早就支持手机了(Android只支持Opengl ES 3.0),最近在调研这个就对它测试了一下。

如果是不动的物体勾选static静态合并批次(40-50帧率)

自定义Shader中勾选Enable GPU Instancing

帧率竟然还不如静态合批次(帧率 30-40)

自定义Shader

Shader "SimplestInstancedShader1"

{

Properties

{

_Color ("Color", Color) = (1, 1, 1, 1)

_MainTex ("Texture", 2D) = "white" {}

}

SubShader

{

Tags { "RenderType"="Opaque" }

LOD 100

Pass

{

CGPROGRAM

pragma vertex vert pragma fragment frag pragma multi_compile_instancing include "UnityCG.cginc"

struct appdata

{

float4 vertex : POSITION;

float2 uv : TEXCOORD0;

UNITY_VERTEX_INPUT_INSTANCE_ID

};

struct v2f

{

float2 uv : TEXCOORD0;

float4 vertex : SV_POSITION;

UNITY_VERTEX_INPUT_INSTANCE_ID // necessary only if you want to access instanced properties in fragment Shader.

};

UNITY_INSTANCING_BUFFER_START(Props)

UNITY_DEFINE_INSTANCED_PROP(float4, _Color)

UNITY_INSTANCING_BUFFER_END(Props)

sampler2D _MainTex;

float4 _MainTex_ST;

v2f vert(appdata v)

{

v2f o;

UNITY_SETUP_INSTANCE_ID(v);

UNITY_TRANSFER_INSTANCE_ID(v, o); // necessary only if you want to access instanced properties in the fragment Shader.

o.vertex = UnityObjectToClipPos(v.vertex);

o.uv = TRANSFORM_TEX(v.uv, _MainTex);

return o;

}

fixed4 frag(v2f i) : SV_Target

{

UNITY_SETUP_INSTANCE_ID(i); // necessary only if any instanced properties are going to be accessed in the fragment Shader.

return tex2D (_MainTex, i.uv) * UNITY_ACCESS_INSTANCED_PROP(Props, _Color);

}

ENDCG

}

}

}

所以,静态不动的物体就没必要用上面的方法了,于是我又测试了Graphics.DrawMeshInstanced()方法,终于满意了。(稳定60帧)

Graphics.DrawMeshInstanced()方法不需要游戏对象以及游戏组件的额外开销,在Update()方法中一气呵成,不过它也有限制,最多可以画1023个。

还有个方法是Graphics.DrawMeshInstancedIndirect()它没有画多少的限制,而且更加灵活,我也搞了好一会儿才在游戏中跑起来,后来才知道它不能再手机上用,只有PC上可以.

在shader中接收位置 颜色 矩阵

Shader "Instanced/InstancedIndirectSelection"

{

Properties

{

_MainTex ("Texture", 2D) = "white" {}

}

SubShader

{

Tags{ "RenderType" = "Opaque" }

LOD 100

Pass

{

CGPROGRAM

pragma vertex vert pragma fragment frag pragma target 4.5 include "UnityCG.cginc"

StructuredBuffer positionBuffer;

StructuredBuffer colorBuffer;

StructuredBuffer matrix4x4Buffer;

struct appdata

{

fixed4 color : COLOR;

float4 vertex : POSITION;

float4 texcoord : TEXCOORD0;

};

struct v2f

{

float4 color: COLOR;

float4 vertex : SV_POSITION;

float2 texcoord : TEXCOORD0;

};

sampler2D _MainTex;

float4 _MainTex_ST;

v2f vert(appdata v, uint instanceID : SV_InstanceID)

{

float4 data = positionBuffer[instanceID];

float4x4 materix = matrix4x4Buffer[instanceID / matrix4x4Buffer.Length];

float3 worldPosition = data.xyz + mul(materix,v.vertex.xyz * data.w);

v2f o;

o.vertex = mul(UNITY_MATRIX_VP, float4(worldPosition, 1.0f));

o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);

o.color = colorBuffer[instanceID];

return o;

}

fixed4 frag(v2f i) : SV_Target

{

return tex2D (_MainTex, i.texcoord) * i.color;

}

ENDCG

}

}

}

在代码中将位置 颜色 矩阵传进去就行了

using UnityEngine;

public class InstancedIndirectExample : MonoBehaviour

{

public int instanceCount = 100000;

public Mesh instanceMesh;

public Material instanceMaterial;

private ComputeBuffer positionBuffer;

private ComputeBuffer argsBuffer;

private ComputeBuffer colorBuffer;

private ComputeBuffer matrix4x4Buffer;

private uint[] args = new uint[5] { 0, 0, 0, 0, 0 };

void Start()

{

argsBuffer = new ComputeBuffer(1, args.Length * sizeof(uint), ComputeBufferType.IndirectArguments);

UpdateBuffers();

}

void Update()

{

// instanceMaterial.SetBuffer("positionBuffer", positionBuffer);

Graphics.DrawMeshInstancedIndirect(instanceMesh, 0, instanceMaterial, new Bounds(Vector3.zero, new Vector3(100.0f, 100.0f, 100.0f)), argsBuffer);

}

void UpdateBuffers()

{

if ( instanceCount <1 ) instanceCount &#61; 1;

// Positions & Colors

if (positionBuffer !&#61; null) positionBuffer.Release();

if (colorBuffer !&#61; null) colorBuffer.Release();

if (matrix4x4Buffer !&#61; null) matrix4x4Buffer.Release();

positionBuffer &#61; new ComputeBuffer(instanceCount, 16);

colorBuffer &#61; new ComputeBuffer(instanceCount, 4*4);

matrix4x4Buffer &#61; new ComputeBuffer(instanceCount,16);

Vector4[] positions &#61; new Vector4[instanceCount];

Vector4[] colors &#61; new Vector4[instanceCount];

Matrix4x4[] materix4X4 &#61; new Matrix4x4[instanceCount];

for (int i&#61;0; i

{

positions [i] &#61; new Vector4 (i, 0f, 0f, 1f);

colors[i] &#61; new Vector4( 1f, 1f, 1f, 1f );

materix4X4[i] &#61; Matrix4x4.TRS (positions [i], Quaternion.Euler (0F, 0F, 0F), Vector3.one);

}

positionBuffer.SetData(positions);

colorBuffer.SetData(colors);

matrix4x4Buffer.SetData (materix4X4);

instanceMaterial.SetBuffer("positionBuffer", positionBuffer);

instanceMaterial.SetBuffer("colorBuffer", colorBuffer);

instanceMaterial.SetBuffer("matrix4x4Buffer", matrix4x4Buffer);

// indirect args

uint numIndices &#61; (instanceMesh !&#61; null) ? (uint)instanceMesh.GetIndexCount(0) : 0;

args[0] &#61; numIndices;

args[1] &#61; (uint)instanceCount;

argsBuffer.SetData(args);

}

void OnDisable()

{

if (positionBuffer !&#61; null) positionBuffer.Release();

positionBuffer &#61; null;

if (colorBuffer !&#61; null) colorBuffer.Release();

colorBuffer &#61; null;

if (argsBuffer !&#61; null) argsBuffer.Release();

argsBuffer &#61; null;

if (matrix4x4Buffer !&#61; null) matrix4x4Buffer.Release();

matrix4x4Buffer &#61; null;

}

}

如果是发生移动的物体顶点数量在900以内会动态合并批次&#xff0c;如果需要支持更多的顶点GPU Instaning的优势就更明显了。 目前来看草、石头、植被、比较合适用它。



推荐阅读
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 本文由编程笔记#小编为大家整理,主要介绍了logistic回归(线性和非线性)相关的知识,包括线性logistic回归的代码和数据集的分布情况。希望对你有一定的参考价值。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • 本文介绍了Oracle数据库中tnsnames.ora文件的作用和配置方法。tnsnames.ora文件在数据库启动过程中会被读取,用于解析LOCAL_LISTENER,并且与侦听无关。文章还提供了配置LOCAL_LISTENER和1522端口的示例,并展示了listener.ora文件的内容。 ... [详细]
  • 本文介绍了解决二叉树层序创建问题的方法。通过使用队列结构体和二叉树结构体,实现了入队和出队操作,并提供了判断队列是否为空的函数。详细介绍了解决该问题的步骤和流程。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 本文介绍了机器学习手册中关于日期和时区操作的重要性以及其在实际应用中的作用。文章以一个故事为背景,描述了学童们面对老先生的教导时的反应,以及上官如在这个过程中的表现。同时,文章也提到了顾慎为对上官如的恨意以及他们之间的矛盾源于早年的结局。最后,文章强调了日期和时区操作在机器学习中的重要性,并指出了其在实际应用中的作用和意义。 ... [详细]
  • 海马s5近光灯能否直接更换为H7?
    本文主要介绍了海马s5车型的近光灯是否可以直接更换为H7灯泡,并提供了完整的教程下载地址。此外,还详细讲解了DSP功能函数中的数据拷贝、数据填充和浮点数转换为定点数的相关内容。 ... [详细]
  • 本文介绍了Codeforces Round #321 (Div. 2)比赛中的问题Kefa and Dishes,通过状压和spfa算法解决了这个问题。给定一个有向图,求在不超过m步的情况下,能获得的最大权值和。点不能重复走。文章详细介绍了问题的题意、解题思路和代码实现。 ... [详细]
  • Iamtryingtocreateanarrayofstructinstanceslikethis:我试图创建一个这样的struct实例数组:letinstallers: ... [详细]
  • OpenMap教程4 – 图层概述
    本文介绍了OpenMap教程4中关于地图图层的内容,包括将ShapeLayer添加到MapBean中的方法,OpenMap支持的图层类型以及使用BufferedLayer创建图像的MapBean。此外,还介绍了Layer背景标志的作用和OMGraphicHandlerLayer的基础层类。 ... [详细]
author-avatar
手机用户2502885835
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有