2015-12-24 37 views
2

我正在研究C++和Direct3D11中的游戏引擎,现在我想在场景中添加一个可变数量的灯。到目前为止,我设法在着色器程序中添加并渲染已知和编码的计数的简单灯光。D3D11:HLSL中可变灯号数

在shader.fx:

static const int LightsCount= 4; 

struct NF3D_LIGHT 
{ 
    // Members... 
}; 

cbuffer Light : register(b5) 
{ 
    NF3D_LIGHT light[LightsCount]; 
}; 

... 

// And the pixel shader function: 
float4 PS(PS_INPUT input) : SV_Target 
{ 
    for(int i = 0; i < LightsCount; i++) 
    { 
     // Process each light and return the final pixel colour 
    } 
} 

这工作得很好。但如果我尝试:

cbuffer LIGHTS_COUNT : register(b13) 
{ 
    int LightsCount; 
} 

使灯的数量根据游戏中发生的情况而变化,这是行不通的。我知道我可以在应用程序开始时给LightsCount一个很大的价值,并为数组添加灯光,但我发现这种方法复杂,固定且效率不高。

有谁知道如何解决这个问题?先谢谢你。

回答

2

从着色器访问可变大小数组(带运行时定义的大小)的一般问题可能会有所不同,具体取决于数组大小,数据更改的频率以及目标硬件。

有想到的几种技术:

  1. 如果阵列是小,最简单的方法是只传递一个常数缓冲带固定大小的数组电流的大小你有人建议。

  2. ,将工作在几乎任何硬件的方式是写数据到纹理Sample或着色Load它。您只能读取原始类型(float,float4等),因此您需要在纹理中实现正确的索引以读取复杂的对象(struct s)。

  3. 在着色器模型5硬件上(以及在某些SM 4上),可以使用UAV s和StructuredBuffer s从缓冲区中读取结构化数据。

  4. 如果您的复杂计算涉及数组,并且目标硬件允许您这样做,那么您可能需要将处理移至计算着色器或甚至是OpenCL或CUDA内核。

考虑到给定的问题,这是经典的灯光,我要说的是什么,我已经看到了使用方法1。99%,你真的没有比灯的十几个场景中的大多数无论如何。

+0

嗯......我并不期待这些答案,但他们正是我最需要的。非常感谢您的帮助。 –

+0

通常情况下,给定的对象用'n'最近/最强的灯光呈现。通常情况下,只有少量灯光(3-4个)通过光照贴图或其他预先计算的照明模型点亮了实时灯光。你可以使用很多灯光进行前向渲染,但通常没有必要。或者,您使用延迟渲染器并绘制数十或数百遍。 –

+0

谢谢你的回复。 –