我已经通过以下简短的教程在XNA代码中实现了基本的硬件模型实例化方法: http://www.float4x4.net/index.php/2011/07/hardware-instancing-for-pc-in-xna-4-with-textures/
我已经创建了所需的着色器(没有纹理图集,只有单个纹理),我正在尝试使用此方法绘制一个我使用3DS Max 2013生成并通过FBX格式导出的简单树。
我看到的结果让我不知道发生了什么。
当我不使用实例化方法,但只是在网格上调用Draw时(对于某个级别上的每个树),显示整个树:
我已经确定模型只包含一个Mesh,而Mesh只包含一个MeshPart 。
我正在使用顶点提取方法,使用模型的顶点和索引缓冲区" GetData<>()"方法,以及正确数量的顶点和索引,因此,呈现正确的基元数量。还会提取正确的纹理坐标和光照法线,正如正在渲染的树部分所见。
树的部分也在正确的位置。
他们只是错过了大约1000个左右的多边形,完全没有理由这么做。我已经突破了顶点提取和着色器参数生成的每一步,我不能为我的生活弄清楚我做错了什么。
My 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),黑色纹理,不正确的定位(通常在天空盒外或地形下方),不正确的缩放......
这是不同的,几乎就像它的工作原理一样 - 可见树的部分在每个方面(位置,旋转,比例,纹理,阴影)都是正确的,除了缺少一个部分。让我更奇怪的是,缺少的部分看似逻辑上是分段的:只有树干的原语,以及树的最低分支的一些叶子丢失,留下所有其他原语正确渲染而没有伪影。基本上,他们正在<正确缺失。
答案 0 :(得分: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个树(即为什么我浪费整个下午创建一个新问题)。