首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Unity项目中的单通道实例渲染DrawMeshInstancedProcedural

Unity项目中的单通道实例渲染DrawMeshInstancedProcedural
EN

Stack Overflow用户
提问于 2022-01-27 02:46:09
回答 2查看 1.8K关注 0票数 1

在程序上,我使用DrawMeshInstancedProcedural和自定义着色器( https://docs.unity3d.com/Manual/GPUInstancing.html )绘制了一整组网格,这在PC上运行得很好。我现在正尝试在一个Hololen2项目中使用它。如果我是正确的,更有效的XR渲染方法的“单通过实例”也是利用这个GPU实例的能力,以绘制场景的几何图形为每个眼睛。这是否意味着我不能同时做这两件事,或者我是否需要在着色器或DrawMeshInstancedProcedural代码中正确地处理这个组合(即。每个眼实例与每个DrawMeshInstancedProcedural实例)?

使用“多通”设置,我的场景渲染正确,但使用“单次传递实例”,转换为我的实例在一只眼睛(即。似乎基于实例ID的每个实例转换的查找已经关闭)。

我认为问题是顶点着色器中的实例ID与立体声渲染之间的冲突。

我确实想知道统一Hololens立体渲染文档底部的语句是否是一条线索--“Graphics.DrawProceduralIndirect()和CommandBuffer.DrawProceduralIndirect()从计算缓冲区中获取它们的所有参数,因此我们不能轻松地增加实例计数。因此,您必须手动加倍计算缓冲区中包含的实例计数。“

任何帮助或建议都会很好。

代码语言:javascript
复制
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);
代码语言:javascript
复制
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
        }
    }
}
EN

回答 2

Stack Overflow用户

发布于 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,因此您需要

代码语言:javascript
复制
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*在场景中呈现的实例数。

票数 1
EN

Stack Overflow用户

发布于 2022-01-27 09:06:17

如果你的非内置着色器不是为实例而写的。在启用单次传递实例呈现之后,一些GameObjects只能在一只眼睛内呈现。这是因为关联的自定义着色器没有适合实例的属性。有关如何解决此问题,请参见基于统一的HoloLens单程立体渲染

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70872714

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档