将数据正确传递到OpenGL的SSBO(C ++和GLSL)

问题描述 投票:0回答:1

我正在OpenGL中开发自己的引擎照明系统。

引擎使用着色器进行渲染,而我有一个主要的角色负责渲染所有内容,还包括照明。到现在为止,所有这些都通过制服传递,一切都很好,但是,我想实现着色器存储缓冲区(我已经实现了UBO,现在我想尝试使用SSBO),但是我遇到了一些问题。

我认为这与如何将数据传递到缓冲区有关。首先,我在用于保持SSBO功能的类中拥有下一个功能(称为着色器存储缓冲区):

  void ShaderStorageBuffer::PassData(uint dataSize, uint dataOffset, const void* data)
  {
      glBufferSubData(GL_SHADER_STORAGE_BUFFER, dataOffset, dataSize, data);
  }

这应该为缓冲区提供所需的数据,该数据具有偏移量和大小。然后,在着色器中,我有下一个SSBO:

  layout(std430, binding = 0) buffer SSBOData
  {
      int u_CurrentLightsNum[3];

      PointLight u_PointLightsArray[MAX_POINTLIGHTS];
      DirLight u_DirLightsArray[MAX_DIRLIGHTS]; 
      SpotLight u_SPLightsArray[MAX_SPOTLIGHTS];
  };

在这里,我用一个整数数组指定当前的灯光量(每种类型-聚光灯,方向灯和点光源),然后再指定一个灯光数组(也每种类型)。出于测试目的,我仅使用第一个点光源阵列,其余的为空。

现在,在渲染器中,我对每种类型的光源都有一个向量。从现在开始,我只使用聚光灯,所以我只传递聚光灯矢量,然后执行下一个:

  m_SSBO->Bind();

  int arr[3] = { currentDLights, currentPLights, currentSPLights };
  memcpy(lightsNum, &arr, sizeof(arr));
  m_SSBO->PassData(sizeof(int) * 3, 0, lightsNum);

  if (PLightVec.size() > 0)
      m_SSBO->PassData(sizeof(PointLight) * PLightVec.size(), sizeof(int) * 4, PLightVec.data());   

  m_SSBO->UnBind();

成为lightsNum一个void *,并且Bind()函数在缓冲区的对应ID(以及Unbind()相同,但ID = 0)中调用glBindBuffer(GL_SHADER_STORAGE_BUFFER,ID)的调用者。

因此,当我执行时,数据似乎传递正确,但是,似乎传递的值不正确(因为看下面的gif,其中的颜色是错误的)的光就像“移动”一样,如果我修改“绿色”值,它会修改“红色”,而实际上红色没有任何作用。]

https://gfycat.com/queasyexemplarybassethound

正如我所说,我怀疑这一定是关于如何传递数据,其顺序或对齐方式,因为我已传递给PassData()函数'sizeof(int)* 4',因为它是最接近的我设法使其正常运行,但是,例如,如果我传递了'sizeof(int)* 3'或'sizeof(int)* 3 + 1',那么它也不起作用。但是,我对这里发生的事情不太了解,我很茫然。

作为附加信息,在Shader和C ++代码中,我具有下一个PointLight结构:

Shader Light StructC++ Light Structure

c++ opengl glsl
1个回答
© www.soinside.com 2019 - 2024. All rights reserved.