我有一个C ++ DirectX 11渲染器,我一直在写。
我编写了一个COLLADA 1.4.1加载程序来导入COLLADA数据,用于支持骨骼动画。
此时我正在验证加载程序(我之前在另一个使用不同技术编写的渲染器中支持COLLADA)我遇到了将COLLADA与DX10 / 11匹配的问题。
我有3个独立的数据顶点缓冲区:
唯一顶点位置的顶点缓冲区。 唯一法线的顶点缓冲区。 唯一纹理坐标的顶点缓冲区。
这些顶点缓冲区包含不同的数组长度(位置有2910个元素,法线有9000多个,纹理坐标大约有3200个。)
COLLADA提供了一个三角形列表,它给出了给定三角形的每个数组的索引(一开始是冗长而奇怪的,但最终一旦你使用它就变得简单了。)
知道DX10 / 11支持多个顶点缓冲区我认为我将填充带有索引的DX10 / 11索引缓冲区到每个缓冲区 *和* (这是重要的部分),这些对于三角形的给定点,指数可能不同。
换句话说,我可以设置三个顶点缓冲区,设置正确的输入布局,然后在索引缓冲区中我将相当于:
l_aIndexBuffer[ NumberOfTriangles * 3 ]
for( i = 0; i < NumberOfTriangles; i++ )
{
l_aIndexBufferData.add( triangle[i].Point1.PositionIndex )
l_aIndexBufferData.add( triangle[i].Point1.NormalIndex )
l_aIndexBufferData.add( triangle[i].Point1.TextureCoordinateIndex )
}
有关在DirectX中使用多个顶点缓冲区的文档似乎没有提供有关它如何影响索引缓冲区的任何信息(稍后会详细介绍。)
运行代码会产生奇怪的渲染结果,我可以看到网格间歇性地正确绘制(奇怪的多边形,但大约三分之一的点位于正确的位置 - 提示 - 提示)
我认为此时(昨天)我搞砸了我的数据或索引,所以我煞费苦心地验证了这一切,所以我认为我正在搞砸我的输入或其他东西。我通过使用普通和纹理缓冲区中的值来消除这一点,或者设置像素着色器使用的颜色值,颜色是正确的,所以我没有遇到填充问题。
最后我得出结论,DX10 / 11必须期望以不同的方式订购数据,所以我尝试以这种方式存储索引:
indices.add( Point1Position index )
indices.add( Point2Position index )
indices.add( Point3Position index )
indices.add( Point1Normal index )
indices.add( Point2Normal index )
indices.add( Point3Normal index )
indices.add( Point1TexCoord index )
indices.add( Point2TexCoord index )
indices.add( Point3TexCoord index )
奇怪的是,这产生了一个渲染的网格看起来正好1/3 - 提示 - 提示。
我猜测DX10 / DX11可能想要通过'顶点缓冲区'存储索引,这意味着我将首先添加所有三角形的所有位置索引,然后是所有三角形的所有正常索引,然后是所有纹理坐标所有三角形的索引。
这产生了另外1/3正确(看起来)的网格。
这让我觉得 - 好吧,DX10 / 11肯定不会为你提供从多个顶点缓冲区流式传输的能力,然后实际上只期望每个三角形点有一个索引?
仅在位置的顶点缓冲区中包含索引会产生正确渲染的网格,遗憾的是它使用了错误的法线和纹理坐标。
看起来将法线和纹理坐标索引放入索引缓冲区会导致错误地绘制正确渲染的网格。
这是预期的行为吗?
多个顶点缓冲区 - 一个索引缓冲区和索引缓冲区只能有一个三角形点的索引?
这对我来说真的没有意义。
帮助!
答案 0 :(得分:2)
首先出现在我脑海中:
支持计算着色器的所有硬件(几乎等于所有DirectX 10及更高版本)也支持ByteAddressBuffer,并且大多数支持StructuredBuffer。因此,您可以将数组绑定为SRV
,并可以随机访问着色器中的任何元素。
像这样的东西(未测试,只是伪代码):
// Indices passed as vertex buffer to shader
// Think of them as of "references" to real data
struct VS_INPUT
{
uint posidx;
uint noridx;
uint texidx;
}
// The real vertex data
// You pass it as structured buffers (similar to textures)
StructuredBuffer<float3> pos : register (t0);
StructuredBuffer<float3> nor : register (t1);
StructuredBuffer<float2> tex : register (t2);
VS_OUTPUT main(VS_INPUT indices)
{
// in shader you read data for current vertex
float3 pos = pos[indices.posidx];
float3 nor = nor[indices.noridx];
float2 tex = tex[indices.texidx];
// here you do something
}
我们称之为“计算着色器方法”。您必须使用DirectX 11 API。
此外,您可以以相同的方式绑定索引并在着色器中执行一些魔术。在这种情况下,您需要找出当前的索引ID。可能你可以从SV_VertexId获取它。
可能你可以解决这些缓冲区并以其他方式绑定数据(DirectX 9兼容纹理采样!O_o)。
希望它有所帮助!