0

我按照这个简短的教程在 XNA 代码中实现了基本的硬件模型实例化方法:http: //www.float4x4.net/index.php/2011/07/hardware-instancing-for-pc-in-xna-4-with -纹理/

我已经创建了所需的着色器(虽然没有纹理图集,只有单个纹理),并且我正在尝试使用这种方法来绘制我使用 3DS Max 2013 生成并通过 FBX 格式导出的简单树。

我看到的结果让我不知道发生了什么。

出于某种原因,没有树干的树。

当我没有使用实例化方法,而只是在网格上调用 Draw 时(对于一个级别上的每棵树),整个树都显示出来了:

正确渲染,但没有实例化(每级数百个对象可能非常慢

我已经确定 Model只包含一个 Mesh 并且 Mesh 只包含一个 MeshPart

我正在使用顶点提取方法,通过使用模型的顶点和索引缓冲区“GetData<>()”方法,以及正确数量的顶点和索引,因此渲染了正确数量的图元。正确的纹理坐标和光照法线也被提取出来,正如正在渲染的树的一部分可见。

树的各个部分也位于正确的位置。

他们只是毫无理由地丢失了大约 1000 个左右的多边形。我在顶点提取和着色器参数生成的每一步都设置了断点,我终其一生都无法弄清楚我做错了什么。

我的 Shader 的顶点变换函数:

VertexShaderOutput VertexShaderFunction2(VertexShaderInput IN, float4x4 instanceTransform : TEXCOORD1)
{
        VertexShaderOutput output;

        float4 worldPosition = mul(IN.Position, transpose(instanceTransform));
        float4 viewPosition = mul(worldPosition, View);
        output.Position = mul(viewPosition, Projection);
        output.texCoord = IN.texCoord;
        output.Normal = IN.Normal;

        return output;
}

顶点绑定和索引缓冲区生成:

instanceBuffer = new VertexBuffer(Game1.graphics.GraphicsDevice, Core.VertexData.InstanceVertex.vertexDeclaration, counter, BufferUsage.WriteOnly);
            instanceVertices = new Core.VertexData.InstanceVertex[counter];

            for (int i = 0; i < counter; i++)
            {
                instanceVertices[i] = new Core.VertexData.InstanceVertex(locations[i]);
            }

            instanceBuffer.SetData(instanceVertices);

            bufferBinding[0] = new VertexBufferBinding(vBuffer, 0, 0);
            bufferBinding[1] = new VertexBufferBinding(instanceBuffer, 0, 1);

用于获取所有顶点信息的顶点提取方法(这部分我确信可以正常工作,因为我之前使用它来将测试几何形状加载到关卡中,如盒子、球体等,以测试各种着色器,并使用它们构建边界框提取的顶点数据,都是正确的):

public void getVertexData(ModelMeshPart part)
        {
            modelVertices = new VertexPositionNormalTexture[part.NumVertices];
            rawData = new Vector3[modelVertices.Length];
            modelIndices32 = new uint[rawData.Length];
            modelIndices16 = new ushort[rawData.Length];

            int stride = part.VertexBuffer.VertexDeclaration.VertexStride;

            VertexPositionNormalTexture[] vertexData = new VertexPositionNormalTexture[part.NumVertices];
            part.VertexBuffer.GetData(part.VertexOffset * stride, vertexData, 0, part.NumVertices, stride);

            if (part.IndexBuffer.IndexElementSize == IndexElementSize.ThirtyTwoBits)
                part.IndexBuffer.GetData<uint>(modelIndices32);
            if (part.IndexBuffer.IndexElementSize == IndexElementSize.SixteenBits)
                part.IndexBuffer.GetData<ushort>(modelIndices16);

            for (int i = 0; i < modelVertices.Length; i++)
            {
                rawData[i] = vertexData[i].Position;
                modelVertices[i].Position = rawData[i];
                modelVertices[i].TextureCoordinate = vertexData[i].TextureCoordinate;
                modelVertices[i].Normal = vertexData[i].Normal;
                counter++;
            }
        }

这是对象批处理的渲染代码(在这种特殊情况下为树):

public void RenderHW()
        {
            Game1.graphics.GraphicsDevice.RasterizerState = rState;

            treeBatchShader.CurrentTechnique.Passes[0].Apply();
            Game1.graphics.GraphicsDevice.SetVertexBuffers(bufferBinding);
            Game1.graphics.GraphicsDevice.Indices = iBuffer;
            Game1.graphics.GraphicsDevice.DrawInstancedPrimitives(PrimitiveType.TriangleList, 0, 0, treeMesh.Length, 0, primitive , counter);

            Game1.graphics.GraphicsDevice.RasterizerState = rState2;
        }

如果有人知道从哪里开始寻找错误,只需发布​​所有想到的想法,因为我完全不知道发生了什么。

这甚至抵消了我之前的所有经验,我在着色器代码或顶点生成中搞砸了一些东西,你会在屏幕上得到一些绝对的混乱 - 大量的图形伪影,例如源自网格应该在哪里的细长三角形,但一个提示向后伸展到(0,0,0),黑色纹理,不正确的定位(通常在天空盒之外或地形下方),不正确的缩放......

这是不同的东西,几乎就像它工作一样 - 树的可见部分在每个方面(位置,旋转,比例,纹理,阴影)都是正确的,除了缺少一部分。对我来说更奇怪的是,丢失的部分似乎在逻辑上被分割:只有树干的图元和树的最低分支的一些叶子丢失,所有其他图元正确渲染而没有伪影。基本上,他们......正确地失踪了

4

1 回答 1

0

解决了。当然,这是我 100% 确定它是正确的部分,而事实并非如此。

        modelIndices32 = new uint[rawData.Length];
        modelIndices16 = new ushort[rawData.Length];

将其更改为:

        modelIndices32 = new uint[part.IndexBuffer.IndexCount];
        modelIndices16 = new ushort[part.IndexBuffer.IndexCount];

现在我必须弄清楚为什么 3 次绘制调用渲染 300 棵树比 300 次绘制调用每棵树渲染 1 棵树慢(即为什么我浪费了整个下午来创建一个新问题)。

于 2014-03-31T15:42:07.650 回答