从一步到另一步工作我现在正试图弄清楚glsl中多灯的更多信息。到目前为止,我阅读了一些教程,但似乎没有人能够得到答案。
让我说我的灯光有这样的结构:
struct LightInfo
{
vec4 LightLocation;
vec3 DiffuseLightColor;
vec3 AmbientLightColor;
vec3 SpecularLightColor;
vec3 spotDirection;
float AmbientLightIntensity;
float SpecularLightIntensity;
float constantAttenuation;
float linearAttenuation;
float quadraticAttenuation;
float spotCutoff;
float spotExponent;
};
uniform LightInfo gLight;
我的第一个想法是让它像
uniform LightInfo gLight[NumLights];
但后来我读了很多关于将那些传递给着色器的数据无法正常工作,因为它无法获得该位置。现在我不得不承认我自己还没有尝试过,但我发现有几页提到这一点,所以它可能没那么错 - 或者这可能只是过时的信息?
另一个想法就是让它成为:
uniform[NumOfArgs]
并再次在着色器中拆分它,但是如果我把我的示例结构上面很快,我很快就会有一个巨大的数组,并且用一个for循环取出它的信息可能也会非常昂贵 - 而且只有当我想在使用gl_LightSource时使用类似数量的灯,例如最大值为8 - 而我想避免使用它,因为有一个自己的结构,同时需要所有信息的优势。
当然,没有任何问题需要许多参数,但任何光线都需要它们(即使剥离它很多,它也会很快生长)。 然而,我可以先使用一些qsort来确定最近的灯光,然后将maxlights限制为类似于3的东西(这也是许多地方也建议的东西),但在这里我再次说我希望从现在的glsl和现代硬件尽管使用它也没有矛盾,与所选择的解决方案无关。
现在我的问题是,这里最好的做法是什么,真的很快?或者我应该继续使用gl_LightSource并通过一些统一的数组传递其他信息?虽然这对我来说似乎没有任何意义。
答案 0 :(得分:4)
轻型结构的想法很好。对于正向渲染 - 将所有光源传递到处理实际几何体的一个着色器中 - 数组就可以了。
你可能有一个结构数组作为制服(uniform LightInfo gLight[NumLights]
,其中NumLights是编译时constatnt),但是数组与仅仅声明{{1}不同}}
您可以通过全名获得统一的位置,例如:
glGetUniformLocation(program," gLight 3。spotExponent")
请注意,uniform LightInfo gLight0, gLight1...
将只返回元素为零的字符串,但大小将给出元素数。
统一缓冲区对于大量灯光和属性非常重要。您可以在GPU上存储结构的所有数据,因此每次单独调用glGetActiveUniform
时都不会发送它。如果其余部分不需要更改,您可以使用glUniform*
修改部分缓冲区。
非常了解结构和数组是如何打包的(it's not always intuitive)!相关问题也出现在非均匀/统一的块情况下。
请参阅:Sub-section 2.15.3.1.2 - Standard Uniform Block Layout
要从块的开头获取字节偏移量,请使用GL_UNIFORM_OFFSET枚举
元素与高大的 16字节边界(vec4大小)对齐。为了提高结构效率,您应该将glMapBuffer
与vec3
配对。
你是对的,如果你的灯光比着色器中的光线多,你就必须砍掉并选择。近距离的灯很重要,但您可能还希望按照您所面对的方向(那些影响区域接触投影矩阵形成的观看体积的那些)以及更大/更亮的灯光(例如太阳/定向)。
最终,如果你有太多的灯,这种方法就不再起作用了。您的下一步是交换到延迟着色,这会带来更多问题(例如,混合/透明度)。