我的需求是: 需要向shader中传递一个比较大的float数组. 该数组的内容(和大小)可能会偶尔更新.
当前的做法是: 使用TBO, 每帧都会传递一次该数组. 相关代码如下:
片元着色器中:
#version 450 compatibility
uniform samplerbuffer electrodePos;
...
客户端代码:
...
glBindBuffer(GL_TEXTURE_BUFFER, m_pointTboID);
glBufferData(GL_TEXTURE_BUFFER, m_electrodesPos.size() * sizeof(GLfloat), m_electrodesPos.data(), GL_STREAM_DRAW);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_BUFFER, m_pointTexID);
glTexBuffer(GL_TEXTURE_BUFFER, GL_RGB32F, m_pointTboID);
shader->setInt("electrodePos", 1);
...
上面的客户端代码每帧绘制的时候都会被执行一次, 当数组内容较大时效率就会很低.
为了提高效率, 我有以下两种改进的思路:
1. 仅仅在数组内容有更新时才会传递一次数据(使用glBufferData), 而非每帧都传输,
2. 使用无绑定纹理bindless texture;
基于以上两种想法, 对代码做以下修改:
片元着色器中:
#version 450 compatibility
#extension GL_ARB_bindless_texture : require
...
layout (std140, binding = 2) uniform electrodePos {
samplerBuffer position;
};
...
下面一段代码, 在数组内容有更新时执行一次, 用于向shader中传输数据:
glBindBuffer(GL_TEXTURE_BUFFER, m_pointTboID);
glBufferData(GL_TEXTURE_BUFFER, m_electrodesPos.size() * sizeof(GLfloat), m_electrodesPos.data(), GL_STREAM_DRAW);
glBindTexture(GL_TEXTURE_BUFFER, m_pointTexID);
glTexBuffer(GL_TEXTURE_BUFFER, GL_RGB32F, m_pointTboID);
m_pointHandle = glGetTextureHandleARB(m_pointTexID);
glMakeTextureHandleResidentARB(m_pointHandle);
下面一段代码, 依旧逐帧执行:
// glGenBuffers(1, &m_pointUBO);
glBindBuffer(GL_UNIFORM_BUFFER, m_pointUBO);
glBindBufferRange(GL_UNIFORM_BUFFER, 0, m_pointUBO, 0, sizeof(GLuint64));
unsigned int ubid = glGetUniformBlockIndex(m_shaderID, "electrodePos");
glUniformBlockBinding(m_shaderID, ubid, 2);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(GLuint64), &(m_pointHandle));
glBindBuffer(GL_UNIFORM_BUFFER, 0);
改动后, 经测试shader端接收不到数据了.
我现在的问题是:
1. 我用于提升效率的两个想法是否是可行的?
2. 如果不可行, 有没有其他适用于我的使用场景的传输方法. 如果可行, 我修改后的代码问题出现在哪里.
谢谢~
相似问题