将 2D 和 3D 阴影贴图发送到着色器
Sending 2D and 3D shadowmaps to shaders
我正在尝试为我的简单引擎实现阴影贴图,我发现我应该将全向阴影贴图(用于点光源的立方体贴图)与 2d 贴图(用于平行光和聚光灯)结合起来。
我的制服块是这样的:
#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];
};
我有两个问题要问你。
sampler 对象昂贵吗?以下代码是否适用于多灯?
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 个对象会实际填充纹理。我们遇到了很多未定义的 采样器 ,我认为这可能会导致一些问题。
如果我没理解错的话,我不能在uniform块中声明sampler。那么每次阴影贴图更新时,我真的被迫循环遍历所有着色器并更新采样器吗?这是浪费时间!
Are sampler objects costly?
这个问题有点误导,因为 GLSL 中的 sampler
数据类型只是 不透明句柄 ,它引用 纹理单元 .代价高昂的是实际的采样操作。此外,特定着色阶段的纹理单元数量是有限的。该规范仅保证 16。由于您不能为不同的采样器类型重复使用相同的单元,因此这会将您的 MAX_LIGHTS
限制为 8.
然而,人们很少需要采样器阵列。相反,您可以使用 array textures,这将允许您将所有阴影贴图(每个纹理类型)存储在一个纹理对象中,并且您只需要一个采样器。
说了这么多我还是觉得你的光数是完全不现实的。即使在目前最快的 GPU 上,实时应用 128 个阴影贴图也行不通...
If I understand correctly, I mustn't declare sampler in uniform blocks.
正确。
So am I really forced to cycle through all of my shaders and update samplers each time the shadow maps get updated? It's a waste of time!
没有。如果要从 采样的纹理单元的 索引发生变化(理想情况下永远不会发生变化),则采样器统一只需要更新。绑定不同的纹理时不会,某些纹理内容发生变化时不会。
我正在尝试为我的简单引擎实现阴影贴图,我发现我应该将全向阴影贴图(用于点光源的立方体贴图)与 2d 贴图(用于平行光和聚光灯)结合起来。
我的制服块是这样的:
#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];
};
我有两个问题要问你。
sampler 对象昂贵吗?以下代码是否适用于多灯?
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 个对象会实际填充纹理。我们遇到了很多未定义的 采样器 ,我认为这可能会导致一些问题。
如果我没理解错的话,我不能在uniform块中声明sampler。那么每次阴影贴图更新时,我真的被迫循环遍历所有着色器并更新采样器吗?这是浪费时间!
Are sampler objects costly?
这个问题有点误导,因为 GLSL 中的 sampler
数据类型只是 不透明句柄 ,它引用 纹理单元 .代价高昂的是实际的采样操作。此外,特定着色阶段的纹理单元数量是有限的。该规范仅保证 16。由于您不能为不同的采样器类型重复使用相同的单元,因此这会将您的 MAX_LIGHTS
限制为 8.
然而,人们很少需要采样器阵列。相反,您可以使用 array textures,这将允许您将所有阴影贴图(每个纹理类型)存储在一个纹理对象中,并且您只需要一个采样器。
说了这么多我还是觉得你的光数是完全不现实的。即使在目前最快的 GPU 上,实时应用 128 个阴影贴图也行不通...
If I understand correctly, I mustn't declare sampler in uniform blocks.
正确。
So am I really forced to cycle through all of my shaders and update samplers each time the shadow maps get updated? It's a waste of time!
没有。如果要从 采样的纹理单元的 索引发生变化(理想情况下永远不会发生变化),则采样器统一只需要更新。绑定不同的纹理时不会,某些纹理内容发生变化时不会。