【问题标题】:D3D11: variable number of lights in HLSLD3D11:HLSL 中可变数量的灯光
【发布时间】:2015-12-25 02:16:22
【问题描述】:

我正在使用 C++ 和 Direct3D11 开发游戏引擎,现在我想向场景中添加可变数量的灯光。迄今为止,我设法添加和渲染了一些简单的灯光,这些灯光在着色器程序中已经知道和编码。

在 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 一个很大的值并向数组添加灯光,但我发现这种方法复杂、固定且效率不高。

有人知道如何解决这个问题吗?提前谢谢你。

【问题讨论】:

    标签: c++ shader hlsl lighting direct3d11


    【解决方案1】:

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

    我想到了几种技术:

    1. 如果您的数组很小,最简单的方法是按照您的建议传递一个带有固定大小数组当前大小 的常量缓冲区。

    2. 几乎可以在任何硬件上工作的方式是将数据写入纹理,然后从着色器中将数据写入SampleLoad。您只能读取原始类型(floatfloat4 等),因此您需要对纹理进行适当的索引以读取复杂对象(structs)。

    3. 在 Shader Model 5 硬件(以及一些 SM 4 上)您可以使用 UAVs 和 StructuredBuffers 从缓冲区读取结构化数据。

    4. 如果您有涉及数组的非常复杂的计算,并且如果目标硬件允许您这样做,您可能希望将处理转移到 Compute Shader 甚至 OpenCL 或 CUDA 内核。

      李>

    考虑到给定的问题,即经典照明,我会说我所见过的 99% 都使用方法 1。无论如何,在大多数情况下,一个场景中的灯光实际上不会超过一打。

    【讨论】:

    • 嗯...我没想到会有这些答案,但它们正是我最需要的。非常感谢您提供急需的帮助。
    • 通常情况下,给定对象使用“n”个最近/最强的灯光进行渲染。通常只有少数几个灯(3-4 个)实时照亮角色,房间由光照贴图或其他预先计算的照明模型照亮。您当然可以在前向渲染中使用大量灯光并进行多次传递,但这通常不是必需的。或者,您使用延迟渲染器并绘制数十或数百个通道。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多