繁体   English   中英

将 2D 和 3D 阴影贴图发送到着色器

[英]Sending 2D and 3D shadowmaps to shaders

我正在尝试为我的简单引擎实现阴影贴图,我发现我应该将全向阴影贴图(点光源的立方体贴图)与二维贴图(方向灯和聚光灯)结合起来。

我的统一块看起来像这样:

#define MAX_LIGHTS 128
//...
struct Light
{
   //light data...
};
//...
layout (std140) uniform Lights
{
    int lightCount; //how many lights were passed into the shader (from 0 to MAX_LIGHTS)
    Light lights[MAX_LIGHTS];
};

我有两个问题要问你。

  1. 采样器对象成本高吗? 以下代码是否适用于多个灯?

     sampler2D shadowMaps2D[MAX_LIGHTS]; samplerCube shadowCubemaps[MAX_LIGHTS]; //... if (lights[index].type == POINT_LIGHT) CalculateShadow(shadowCubemaps[lights[index].shadowMapNr]); else CalculateShadow(shadowMaps2D[lights[index].shadowMapNr]);

    只有lightCount数量的对象会实际填充纹理。 我们遇到了很多未定义的采样器,我认为这会导致一些问题。

  2. 如果我理解正确,我不能在统一块中声明采样器 那么,每次阴影贴图更新时,我真的被迫循环遍历所有着色器并更新采样器吗? 这是浪费时间!

采样器对象成本高吗?

这个问题有点误导,因为 GLSL 中的sampler数据类型只是引用纹理单元的不透明句柄 代价高昂的是实际的采样操作。 此外,特定阴影阶段的纹理单元数量是有限的。 该规范仅保证 16 个。由于您不能为不同的采样器类型重复使用相同的单元,这会将您的MAX_LIGHTS限制为仅 8 个。

然而,很少需要采样器阵列。 相反,您可以使用数组 textures ,这将允许您将所有阴影贴图(每种纹理类型)存储在单个纹理对象中,并且您只需要一个采样器。

说了这么多我还是觉得你的光数是完全不现实的。 即使在最快的 GPU 上,实时应用 128 个阴影贴图也行不通……

如果我理解正确,我不能在统一块中声明采样器

正确的。

那么,每次阴影贴图更新时,我真的被迫循环遍历所有着色器并更新采样器吗? 这是浪费时间!

不。仅当您要从中采样的纹理单元索引发生变化(理想情况下永远不会)时,才需要更新采样器制服。 不是当绑定不同的纹理时,也不是当某些纹理内容更改时。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM