使用OpenGL/GLSL时,统一缓冲区对象(UBO)无法正常工作
我目前正在开发一个小型3D引擎。在此之前,我一直使用glUniformXXX等方法将统一变量(一个接一个)发送到着色器程序。所以我不得不为每一帧发送它们(这不是很优化)。所以我决定在程序初始化时使用统一缓冲区对象发送所有这些统一变量一次。因此,将使用VBO、IBO或PBO按状态更改以相同的方式在缓冲区中加载一次物料数据。当然,如果出于某种原因需要修改缓存中的数据,我总是可以使用glMapBuffer和glUnmapBuffer之类的方法来更新数据 例如,我加载了一个简单的ADS着色器程序(环境光、漫反射光和镜面反射光)。现在,为了简单起见,将光泽度组件(用于计算镜面反射光)放置在片段着色器中的统一块中,如下所示(我们需要计算ADS着色的所有剩余统一变量都用作简单统一变量): 现在,我将向您展示加载我们的UBO的客户端代码:使用OpenGL/GLSL时,统一缓冲区对象(UBO)无法正常工作,opengl,glsl,fragment-shader,vertex-shader,Opengl,Glsl,Fragment Shader,Vertex Shader,我目前正在开发一个小型3D引擎。在此之前,我一直使用glUniformXXX等方法将统一变量(一个接一个)发送到着色器程序。所以我不得不为每一帧发送它们(这不是很优化)。所以我决定在程序初始化时使用统一缓冲区对象发送所有这些统一变量一次。因此,将使用VBO、IBO或PBO按状态更改以相同的方式在缓冲区中加载一次物料数据。当然,如果出于某种原因需要修改缓存中的数据,我总是可以使用glMapBuffer和glUnmapBuffer之类的方法来更新数据 例如,我加载了一个简单的ADS着色器程序(环境光
void video::SpecularEffect::SetupMaterials(std::string const &name)
{
GLuint blockIndex = 0, bindingPoint = 0, bufferIndex = 0;
float shininess = 96.0f;
{
blockIndex = glGetUniformBlockIndex(this->m_Handle, "MaterialBlock");
glUniformBlockBinding(this->m_Handle, blockIndex, bindingPoint);
{
glGenBuffers(1, &bufferIndex);
glBindBuffer(GL_UNIFORM_BUFFER, bufferIndex);
{
glBufferData(GL_UNIFORM_BUFFER, sizeof(float), &shininess, GL_DYNAMIC_DRAW);
}
glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
glBindBufferBase(GL_UNIFORM_BUFFER, bindingPoint, bufferIndex);
[...]
}
如您所见,上面的代码描述了以下示意图:
[*.frag] BlockIndex BindingPoint *pBuffer
uniform MaterialBlock [0] ----------> [1] <----------- [96.0f] //The shininess value = 96.0f
{
float Shininess;
};
如您所见,我直接在循环中调用方法“SetupMaterials”。但这是不正确的,因为我对每个帧重新分配缓冲区,而且像这样使用UBO是无用的。目标是在缓存中加载一次材质数据。但是渲染是正确的(因此统一块似乎已正确初始化,着色器程序可以访问缓冲区):
但是现在,如果我在初始化时只加载并填充一次缓冲区,那么在主循环之前,我有以下显示:
但是,我没有OpenGL错误(使用“glGetError”)
另外,我尝试在上面的渲染方法中使用“glBindBuffer(GL_UNIFORM_BUFFER,bufferIndex)”绑定UBO,但我仍然有相同的显示
那么,如果我在主循环中直接调用加载方法,为什么显示是正确的呢?如果我在初始化时调用它一次,为什么它不起作用?我怎样才能解决我的问题
非常感谢您的帮助 在gdebugger中启动它,在两种方法中停止drawcall并查找状态差异。您好。我试图找到一个链接来下载NVIDIA的gdebugger,但我只找到了以下链接:但是下载链接不起作用!我试图安装AMD gdebugger并使用它,但软件说我没有安装AMD GPU(这是正常的,我有一个NVDIA图形卡)。那么,有没有一种方法可以将AMD gdebugger与NVDIA卡一起使用呢?如果这是不可能的,你知道另一个链接下载NVIDIA的gdebugger吗?非常感谢您的帮助!你应该能够使用AMD的调试器与nvidia卡。不幸的是,原来的gRemedy网站已经关闭,但是你应该可以在互联网上找到旧的安装程序。它不包括GL 4+功能,但应适用于您的情况。另一个不错的调试器是NVIDIAnsight,它最近得到了更新;也许试试这个。如果您还没有NVidia开发者帐户,您需要申请该帐户。谢谢您的帮助!
[*.frag] BlockIndex BindingPoint *pBuffer
uniform MaterialBlock [0] ----------> [1] <----------- [96.0f] //The shininess value = 96.0f
{
float Shininess;
};
void video::RenderBatch::Render(void)
{
type::EffectPtr pShaderEffect = EffectManager::GetSingleton()
.FindEffectByName(this->m_pMaterial->GetAssocEffectName());
pShaderEffect->Bind();
{
///VERTEX ATTRIBUTES LOCATIONS.
{
pShaderEffect->BindAttribLocation(scene::VERTEX_POSITION, "VertexPosition");
pShaderEffect->BindAttribLocation(scene::VERTEX_TEXTURE, "VertexTexture");
pShaderEffect->BindAttribLocation(scene::VERTEX_NORMAL, "VertexNormal");
}
//SEND MATRIX UNIFORMS.
{
glm::mat3 normalMatrix = glm::mat3(glm::vec3(this->m_ModelViewMatrix[0]),
glm::vec3(this->m_ModelViewMatrix[1]), glm::vec3(this->m_ModelViewMatrix[2]));
pShaderEffect->SetUniform("ModelViewProjMatrix", this->m_ModelViewProjMatrix);
pShaderEffect->SetUniform("ModelViewMatrix", this->m_ModelViewMatrix);
pShaderEffect->SetUniform("NormalMatrix", normalMatrix);
}
this->SendLightUniforms(pShaderEffect);
pShaderEffect->SetupMaterials(this->m_pMaterial->GetName());
{
this->m_pVertexArray->Lock(); //VAO binding
{
this->m_pIndexBuffer->Lock(); //IBO binding
{
//Draw call here
}
this->m_pIndexBuffer->Unlock();
}
this->m_pVertexArray->Unlock();
}
}
pShaderEffect->Release();
}