我按照这个简短的教程在 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),黑色纹理,不正确的定位(通常在天空盒之外或地形下方),不正确的缩放......
这是不同的东西,几乎就像它工作一样 - 树的可见部分在每个方面(位置,旋转,比例,纹理,阴影)都是正确的,除了缺少一部分。对我来说更奇怪的是,丢失的部分似乎在逻辑上被分割:只有树干的图元和树的最低分支的一些叶子丢失,所有其他图元正确渲染而没有伪影。基本上,他们......正确地失踪了。