glsl multi light,传递数据的最佳实践(结构数组?)

时间:2014-03-20 16:42:35

标签: arrays opengl struct glsl

从一步到另一步工作我现在正试图弄清楚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并通过一些统一的数组传递其他信息?虽然这对我来说似乎没有任何意义。

1 个答案:

答案 0 :(得分:4)

轻型结构的想法很好。对于正向渲染 - 将所有光源传递到处理实际几何体的一个着色器中 - 数组就可以了。

  1. 你可能有一个结构数组作为制服(uniform LightInfo gLight[NumLights],其中NumLights是编译时constatnt),但是数组与仅仅声明{{1}不同}}

    您可以通过全名获得统一的位置,例如:

    glGetUniformLocation(program," gLight 3。spotExponent")

    请注意,uniform LightInfo gLight0, gLight1...将只返回元素为零的字符串,但大小将给出元素数。

  2. 统一缓冲区对于大量灯光和属性非常重要。您可以在GPU上存储结构的所有数据,因此每次单独调用glGetActiveUniform时都不会发送它。如果其余部分不需要更改,您可以使用glUniform*修改部分缓冲区。

    非常了解结构和数组是如何打包的it's not always intuitive)!相关问题也出现在非均匀/统一的块情况下。

    请参阅:Sub-section 2.15.3.1.2 - Standard Uniform Block Layout

      

    要从块的开头获取字节偏移量,请使用GL_UNIFORM_OFFSET枚举

    请参阅:Uniform Buffer Object

  3. 元素与高大的 16字节边界(vec4大小)对齐。为了提高结构效率,您应该将glMapBuffervec3配对。

  4. 你是对的,如果你的灯光比着色器中的光线多,你就必须砍掉并选择。近距离的灯很重要,但您可能还希望按照您所面对的方向(那些影响区域接触投影矩阵形成的观看体积的那些)以及更大/更亮的灯光(例如太阳/定向)。

    最终,如果你有太多的灯,这种方法就不再起作用了。您的下一步是交换到延迟着色,这会带来更多问题(例如,混合/透明度)。