在程序上,我使用DrawMeshInstancedProcedural和自定义着色器( https://docs.unity3d.com/Manual/GPUInstancing.html )绘制了一整组网格,这在PC上运行得很好。我现在正尝试在一个Hololen2项目中使用它。如果我是正确的,更有效的XR渲染方法的“单通过实例”也是利用这个GPU实例的能力,以绘制场景的几何图形为每个眼睛。这是否意味着我不能同时做这两件事,或者我是否需要在着色器或DrawMeshInstancedProcedural代码中正确地处理这个组合(即。每个眼实例与每个DrawMeshInstancedProcedural实例)?
使用“多通”设置,我的场景渲染正确,但使用“单次传递实例”,转换为我的实例在一只眼睛(即。似乎基于实例ID的每个实例转换的查找已经关闭)。
我认为问题是顶点着色器中的实例ID与立体声渲染之间的冲突。
我确实想知道统一Hololens立体渲染文档底部的语句是否是一条线索--“Graphics.DrawProceduralIndirect()和CommandBuffer.DrawProceduralIndirect()从计算缓冲区中获取它们的所有参数,因此我们不能轻松地增加实例计数。因此,您必须手动加倍计算缓冲区中包含的实例计数。“
任何帮助或建议都会很好。
private struct MeshProperties
{
public Matrix4x4 mat;
public Color color;
public static int Size()
{
//Size for buffer
return
sizeof(float) * 4 * 4 + // matrix;
sizeof(float) * 4; // colour;
}
}
...
MeshProperties[] meshProperties = new MeshProperties[vertCount];
for (int i = 0; i < vertCount; i++)
{
MeshProperties meshProps = new MeshProperties();
// populate transform and color of each point (instance)
meshProperties[i] = meshProps;
}
ComputeBuffer computeBuffer = new ComputeBuffer(vertCount, MeshProperties.Size());
computeBuffer.SetData(meshProperties);
material.SetBuffer("_Properties", computeBuffer);
...
Graphics.DrawMeshInstancedProcedural(
instanceMesh, // the mesh to draw at each location
0,
material,
bounds,
vertexCount);Shader "RBGA Glyphs"
{
Properties
{
_Ambient("Ambient", Color) = (0.25, 0.25, 0.25, 1)
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
Tags {"LightMode"="ForwardBase"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct VertInput
{
float4 pos : POSITION;
float3 normal : NORMAL;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct VertOutput
{
float4 pos : SV_POSITION;
half4 color : COLOR;
UNITY_VERTEX_OUTPUT_STEREO
};
half4 _Ambient;
float4x4 _WorldTrans;
struct MeshProperties
{
float4x4 mat; //matrix
float4 color; //vertex colour
};
StructuredBuffer<MeshProperties> _Properties;
VertOutput vert(VertInput vin, uint instanceID: SV_InstanceID)
{
VertOutput vout;
UNITY_SETUP_INSTANCE_ID(vin);
UNITY_INITIALIZE_OUTPUT(VertOutput, vout);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(vout);
float3 norm = mul(_Properties[instanceID].mat, vin.normal);
norm = mul(_WorldTrans, norm);
float3 worldNormal = UnityObjectToWorldNormal(norm);
// dot product between normal and light direction for standard diffuse (Lambert) lighting
half nl = saturate(dot(worldNormal, normalize(_WorldSpaceLightPos0.xyz)));
// add ambient
nl = clamp(nl + _Ambient, 0, 1);
float4 pos = mul(_Properties[instanceID].mat, vin.pos);
pos = mul(_WorldTrans, pos);
vout.pos = UnityObjectToClipPos(pos);
vout.color = _Properties[instanceID].color * nl;
return vout;
}
half4 frag(VertOutput vin) : SV_Target
{
return vin.color;
}
ENDCG
}
}
}发布于 2022-03-09 10:51:38
在深入研究了UNITY_SETUP_INSTANCE_ID (https://github.com/TwoTailsGames/Unity-Built-in-Shaders/blob/master/CGIncludes/UnityInstancing.cginc)所做的工作和许多痛苦的实验之后,我发现我是正确的,文档中的注释“因此,您必须手动加倍计算缓冲区中包含的实例计数”。确实是一条线索(也就是答案)。在立体声实例渲染的情况下,每个实例的缓冲区需要两倍长,并且重复(交错)为每个眼睛渲染(对于每个几何图形被渲染的实例)。unity_StereoEyeIndex计算为inputInstanceID & 0x01,因此您需要
Computebuffer[0] // matrix for instance 0 left eye
Computebuffer[1] // matrix for instance 0 right eye (ie. Duplicate of Computebuffer[0])
Computebuffer[2] // matrix for instance 1 left eye
Computebuffer[3] // matrix for instance 1 right eye (ie. Duplicate of Computebuffer[2])
…
Computebuffer[instanceCount *2]对DrawMeshInstancedProcedural的调用或对DrawMeshInstancedIndirect的计数缓冲区参数也应该使用count 2*在场景中呈现的实例数。
发布于 2022-01-27 09:06:17
如果你的非内置着色器不是为实例而写的。在启用单次传递实例呈现之后,一些GameObjects只能在一只眼睛内呈现。这是因为关联的自定义着色器没有适合实例的属性。有关如何解决此问题,请参见基于统一的HoloLens单程立体渲染。
https://stackoverflow.com/questions/70872714
复制相似问题