在OpenGL 4.5中迭代自定义结构unifrom数组

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在OpenGL 4.5中迭代自定义结构unifrom数组相关的知识,希望对你有一定的参考价值。

我试图在OpenGL 4.5中迭代一系列自定义结构的统一数组,但我的应用程序崩溃了一个无效的操作枚举器。

我的片段着色器看起来像:

#version 450

struct Light
{
  vec4 position;//intensity here as well
  vec4 color;
};

in vec3 normal;//Normal to the vertex
in vec3 vertexPos;//True position of the vertex (i.e it's location in space)
in vec2 texture_coord;

out vec4 outColor;//Final color of the pixel

uniform sampler2D text;
uniform samplerCubeArray depth_maps;
uniform Light lights[];

uniform vec4 color = vec4(1);//Default color
//TODO: make this an array
//uniform vec3 lum = vec3(100,90,15); vec3(80,70,10);//A unique light position

uniform vec3 lums[2] = {vec3(80,70,10), vec3(100,90,15)};
uniform vec3 cameraPos = vec3(0);//The position of the camera in the world
uniform vec3 cameraDir = vec3(0);

void main()
{
    outColor = vec4(0);
    for(uint i=0 ; i<2; i++)
    {
        vec4 color = vec4(0);
        vec3 lum = lights[i].position.xyz;
        vec3 l = vec3(lum-vertexPos);
        if(length(l)>0)
            l = normalize(l);
        vec3 c = vec3(texture(text,abs(texture_coord)));
        vec3 n = normalize(normal);
        vec3 e = cameraPos-vertexPos;
        e = normalize(e);
        vec3 h = normalize(e+l);

        color = vec4(c*(vec3(0.5)+0.5*max(0,dot(n,l))) + 
            vec3(0.1)*max(0,pow(dot(h,n), 100)), 1);

        vec3 temp = vertexPos-lum; 

        float test = texture(depth_maps, vec4(temp, 1)).r;
        double d = length(temp);

        if(d>test*256 + 0.5)
            color = vec4(test/2);

        outColor += color;
    }

    outColor = outColor/2.f;
}

如果将赋值运算符中的索引替换为常量,即编写vec3 lum = lights[0].position.xyz;vec3 lum = lights[1].position.xyz;

没有错误(但当然最终的图像是错误的)。

但是,如果相反,我尝试将其动态设置为vec3数组,即我写:

vec3 lum = lums[i];

事情按预期工作。

为什么我不能遍历我的Light数组?是因为它是一个自定义结构?

编辑:

添加cpp代码,根据请求设置阴影贴图

绘制阴影贴图

void Renderer::draw_shadow_maps(vector<Light> &lights)
{
    current_program = shading_programs[SHADER_DEPTH].programID;
    glUseProgram(current_program);

    //shadow_maps.resize(lights.size());

    glViewport(0, 0, 2048, 2048);
    glBindFramebuffer(GL_FRAMEBUFFER, FBOs[FBO_SHADOW_MAP]);

    for(uint i=0; i<lights.size(); i++)
    {
        glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, shadow_maps[0].textureID, 0);

        load_uniform((int)i, "map_index");

        glDrawBuffer(GL_NONE); 
        glReadBuffer(GL_NONE);

        if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
        {
            if(glCheckFramebufferStatus(GL_FRAMEBUFFER)==GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)
                cerr << "shadow map was not initialized properly" << endl;
            exit(0);
        }

        glClear(GL_DEPTH_BUFFER_BIT);

        setup_light_perspectives(current_program, lights[i]);
        draw();
    }
}

创建阴影贴图:

Shadow_Map::Shadow_Map()
{
    glGenTextures(1, &textureID);

    glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textureID);
    glTexStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY,1, GL_DEPTH_COMPONENT32F, 2048, 2048, 6*10);

    glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);  

    glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
    openGLerror();
}

将信息传递给GPU:

void Shadow_Map::load_to_GPU(GLuint program)
{   
    glUseProgram(program);
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textureID);

    string name = "depth_maps";

    GLint loc = glGetUniformLocation(program, name.c_str());
    if(loc == GL_INVALID_VALUE || loc==GL_INVALID_OPERATION)
    {
        cerr << "Error returned when trying to find depth_map uniform."
            << "
uniform: " << name 
            << "
Error num: " << loc
            << endl;
        return;
    }

    glUniform1i(loc,1);
}
答案
uniform Light lights[];

Arrays in GLSL几乎总是必须有一个静态定义的大小。以下是例外情况:

  1. 您可以转发声明没有大小的数组,但前提是您稍后使用大小重新声明它。
  2. 变量是last member of a shader storage block
  3. 变量(或接口块)是着色器阶段输入/输出限定变量/块,并且该阶段的输入/输出被排列。

以上是关于在OpenGL 4.5中迭代自定义结构unifrom数组的主要内容,如果未能解决你的问题,请参考以下文章

Windows 上没有 GLUT 的 OpenGL 4.5 简单教程 [关闭]

OpenGL 统一的结构数组

通过Lua迭代器自定义实现对c#集合的遍历

如何提高自定义 OpenGL ES 2.0 深度纹理生成的性能?

lua自定义迭代器

ASP.NET 4.5 自定义验证属性。 IsValid() 调用太晚了