HLSL:使用实例浮点input来select纹理索引,可能吗?

我正在使用XNA为xbox360编写游戏。 我想用一个DrawInstancedPrimitives调用画几个模型。 每个模型将使用不同的纹理。

为了做到这一点,我想创建一个采样器数组,并从实例顶点缓冲区传入着色器的值中select数组中使用哪个采样器。

所以着色器代码可能如下所示:

void InstancingVertexShader(..., in float4x4 data : TEXCOORD0) { output.TextureIndex = data._m00 } void InstancingPixelShader(...) { color = tex2Dlod(samplers[input.TextureIndex]); } 

在我开始尝试实现之前,我的问题是:

有可能这样做,还是HLSL会抱怨?

我应该知道这个方法有什么缺点吗?

实际答案: (在SM 3.0中;显然你可以在SM 4.0中,但是我没有检查过。)

技术上答案是肯定的,因为这是合法的HLSL。 但是如果在编译时无法确定采样器索引,那么编译将失败,因为无法将其表示为GPU指令。

所以, 如果索引在编译时是不变的那么只能通过索引select一个采样器

当然你可以通过使用dynamic分支或者简单地做多个读取和select一个来实现类似于索引的效果。 但是如果你有足够的纹理带宽,这只是一个好主意。

最好的解决scheme可能是纹理地图集。 如果这是一个问题,你可以创建自己的mipmap。

( 这是GameDev.net上的一个线程,与您的问题相同 。)

使用3D纹理,可以使用3D纹理坐标的“w”分量来select不同的纹理进行采样。

你想达到什么目的? 通过一个通话渲染所有3,你能节省很多钱吗? 你也可以使用一个纹理页面/图集,将所有3个纹理放在一个较大的纹理中(可能会有一点点的浪费),然后让这3个UV的纹理从图像的右边部分选取正确的纹理。

这张贴作为答复,因为我没有足够的声誉写评论。

你提到你不能使用纹理图集,因为那样你就不能使用mipmapping。 这不是真的。 只需为纹理图集生成mipmap链(例如,先为各个纹理生成mipmap,然后将它们dynamic组合成一个大纹理;这比较容易,因为Texture2D会自动生成mipmap)。 在着色器中,可以使用tex2Dlod,tex2Dgrad,ddx和ddy函数来计算首选的mipmap级别。

此外,你可以看看硬件实例,这在Xbox上显然是可用的( http://dotnetkicks.com/csharp/Hardware_Instancing_in_XNA_on_the_XBOX_360

我没有时间去阅读整个事情,但从大纲来看,这可能适合你:

在nVidia Direct3D SDK 10.5中有一个示例,描述如下:

这个例子是一个在DX10中使用Texture Arrays的简单例子。 它使用纹理数组作为地形纹理的调色板,在单个绘图调用中渲染具有许多纹理的地形网格。 以前的API中的类似效果将需要纹理图集或多个绘制调用。

nVidia D3D SDK 10.5示例页面 (位于页面的底部)

nVidia白皮书纹理数组和地形渲染

nVidia演示项目下载

我知道这是一个)不直接关于XNA和b)可能不是你想要的,但也许你可以获得进一步的领先在那里。