Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ GLSL-无法访问多个灯光的SSBO阵列的第二个索引_C++_Opengl_Glsl_Nsight_Opengl 4 - Fatal编程技术网

C++ GLSL-无法访问多个灯光的SSBO阵列的第二个索引

C++ GLSL-无法访问多个灯光的SSBO阵列的第二个索引,c++,opengl,glsl,nsight,opengl-4,C++,Opengl,Glsl,Nsight,Opengl 4,在我的应用程序中,我添加了两个灯光。一个在(0,0,2)处,第二个在(2,0,0)处。以下是我得到的结果(x、y、z轴分别由红色、绿色和蓝色线表示): 请注意,只有第一个灯光工作,而第二个灯光不工作。我使我的应用程序核心配置文件兼容,以使用各种工具(如RenderDoc和NSight)检查缓冲区,这两种工具都向我显示第二个灯光的数据存在于缓冲区中(运行NSight时拍摄的图片): 这些位置似乎被正确地转移到gpu内存缓冲区。下面是我的片段着色器的实现,它使用SSBO处理我的应用程序中的多个灯

在我的应用程序中,我添加了两个灯光。一个在(0,0,2)处,第二个在(2,0,0)处。以下是我得到的结果(x、y、z轴分别由红色、绿色和蓝色线表示):

请注意,只有第一个灯光工作,而第二个灯光不工作。我使我的应用程序核心配置文件兼容,以使用各种工具(如RenderDoc和NSight)检查缓冲区,这两种工具都向我显示第二个灯光的数据存在于缓冲区中(运行NSight时拍摄的图片):

这些位置似乎被正确地转移到gpu内存缓冲区。下面是我的片段着色器的实现,它使用SSBO处理我的应用程序中的多个灯光:

#version 430

struct Light {
  vec3  position;
  vec3  color;
  float intensity;
  float attenuation;
  float radius;
};

layout (std140, binding = 0) uniform CameraInfo {
  mat4  ProjectionView; 
  vec3  eye;
};

layout (std430, binding = 1) readonly buffer LightsData {
    Light lights[];
};

uniform vec3  ambient_light_color;
uniform float ambient_light_intensity;

in  vec3 ex_FragPos;
in  vec4 ex_Color;
in  vec3 ex_Normal;
out vec4 out_Color;

void main(void)
{
    // Basic ambient light
    vec3 ambient_light = ambient_light_color * ambient_light_intensity;

    int i;
    vec3 diffuse = vec3(0.0,0.0,0.0);
    vec3 specular = vec3(0.0,0.0,0.0);
    for (i = 0; i < lights.length(); ++i) {
        Light wLight = lights[i];
        // Basic diffuse light
        vec3 norm = normalize(ex_Normal); // in this project the normals are all normalized anyway...
        vec3 lightDir = normalize(wLight.position - ex_FragPos);
        float diff = max(dot(norm, lightDir), 0.0);
        diffuse += diff * wLight.color;

        // Basic specular light
        vec3 viewDir = normalize(eye - ex_FragPos);
        vec3 reflectDir = reflect(-lightDir, norm);  
        float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);
        specular += wLight.intensity * spec * wLight.color;  
    }

    out_Color = ex_Color * vec4(specular + diffuse + ambient_light,1.0); 
}
第50行和第56行表示
diffuse+=diff*wLight.color
镜面反射+=wLight.intensity*spec*wLight.color分别为。即使我在第一次抽签前添加灯光,是否真的存在越界访问?为什么在我使用
lights.length()而不是2时着色器编译正确


最后,我在for循环中添加了一个简单的
if(I==1)
,以查看lights.length()是否等于2,但它不在其中但是我的缓冲区的初始大小是0,然后我添加了一个灯光,将缓冲区大小设置为36字节,我们可以看到第一个灯光工作正常。为什么更新/重新分配不在第二次工作?< /强>

,所以我做的是在C++结构的声明结束时添加一些填充,仅在C++边> < /强>。所需的填充是float[3]或12个字节,总计48个字节。我仍然不确定为什么需要这样做,因为规范说明(如中突出显示的)

  • 如果构件是结构,则结构的基准对齐为N,其中N是其任何构件的最大基准对齐值 成员,并四舍五入到vec4的基本对齐方式。这个 然后,此子结构的各个构件将按偏移指定 递归地应用这组规则,其中 子结构的第一个构件等于 结构。该结构的末端可能有衬垫;基地 子结构后面的杆件偏移向上舍入到 结构的基础对齐的下一个倍数。 [……]
  • 使用std430存储布局时,着色器存储块将 在缓冲存储器中的布局与均匀和着色存储器相同 块使用std140布局,但基础对齐和 规则4中标量和向量数组的步长和规则4中结构的步长 规则9不向上舍入vec4的基本对齐倍数

    我的猜测是,glm定义的vec3和glm::f32vec3等结构在使用std430时会递归地向上取整为vec4,因此我的结构必须遵循vec4的对齐方式。如果有人能证实这一点,这将是有趣的,因为上面的链接帖子直接涉及vec4而不是vec3

    两个灯都亮的图片:

    编辑:

    经过进一步调查,结果表明,光结构的最后3个场(强度、衰减和半径)不可用。我通过将位置和颜色从glm::f32vec3改为glm::vec4来修复此问题。有关更多信息,请参阅。由于前面提到的对齐方式,我还留下了一个用于填充的浮动

    struct Light {
      glm::f32vec3  position;
      glm::f32vec3  color;
      float         intensity;
      float         attenuation;
      float         radius;
    };
    ...
    constexpr GLuint        LIGHTS_SSBO_BINDING_POINT = 1U;
    std::vector<Light>      _Lights;
    ...
    void AddLight(const Light &light) {
      // Add to _Lights
      _Lights.push_back(light);
    UpdateSSBOBlockData(
      LIGHTS_SSBO_BINDING_POINT, _Lights.size()* sizeof(Light),
      static_cast<void*>(_Lights.data()), GL_DYNAMIC_DRAW);
    }
    
    using SSBOCapacity = GLuint;
    using BindingPoint = GLuint;
    using ID = GLuint;
    std::map<BindingPoint, std::pair<ID, SSBOCapacity> >  SSBO_list;
    ...
    void UpdateSSBOBlockData(GLuint a_unBindingPoint,
      GLuint a_unSSBOSize, void* a_pData, GLenum a_eUsage) {
      auto SSBO = SSBO_list.find(a_unBindingPoint);
      if (SSBO != SSBO_list.end()) {
        GLuint unSSBOID = SSBO->second.first;
        glBindBuffer(GL_SHADER_STORAGE_BUFFER, unSSBOID);
        glBufferData(GL_SHADER_STORAGE_BUFFER, a_unSSBOSize, a_pData, a_eUsage);
        glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); //unbind
      }
      else 
        // error handling...
    }
    
    (50) : error C1068: ... or possible array index out of bounds
    (50) : error C5025: lvalue in field access too complex
    (56) : error C1068: ... or possible array index out of bounds
    (56) : error C5025: lvalue in field access too complex