仅在错误的着色器程序中设置属性会影响属性值
Only setting the attribute in wrong shader program affects attribute value
我尝试在 OpenGL 中使用多个着色器程序,我总是会遇到问题。出于某种原因,设置正在使用的 shader2 程序的属性根本没有反映 - 但在当前未使用的 shader1 中设置属性会影响 shader2 中的渲染。我确定,使用了我的 shader2(将着色器中的属性设置为常量值会反映在使用 shader2 绘制的对象上),并且我正在 shader2 中设置属性值。
我将ShaderPrograms封装到一个类中,如下所示:
class ShaderProgram{
public:
ShaderProgram(const std::string& vertexSource, const std::string& fragmentSource){
vertexShader = glCreateShader(GL_VERTEX_SHADER);
const GLchar *source = (const GLchar *)vertexSource.c_str();
glShaderSource(vertexShader, 1, &source, 0);
glCompileShader(vertexShader);
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
source = (const GLchar *)fragmentSource.c_str();
glShaderSource(fragmentShader, 1, &source, 0);
glCompileShader(fragmentShader);
program = glCreateProgram();
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glLinkProgram(program);
}
void use(){
glUseProgram(program);
}
void setAttribPointer(const char* name, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* pointer) {
GLuint pos = glGetAttribLocation(program, name);
glEnableVertexAttribArray(pos);
glVertexAttribPointer(pos, size, type, normalized, stride, pointer);
}
void setAttribValue4f(const char* name, float x, float y, float z, float w) {
GLuint pos = glGetAttribLocation(program, name);
glDisableVertexAttribArray(pos);
const GLfloat pointer[] = { x, y, z, w };
glVertexAttrib4fv(program, pointer);
}
~ShaderProgram() {
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glDeleteProgram(program);
}
private:
GLuint vertexShader, fragmentShader, program;
};
我的应用程序中的渲染循环如下所示:
program1.use();
program1.setAttribValue4f("color", 1.0f, 0.0f, 0.0f, 1.0f);
program1.setAttribPointer("positions", 3, GL_FLOAT, GL_FALSE, 0, vertices.data());
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, indices.data());
program2.use();
program2.setAttribValue4f("color", 0.0f, 0.0f, 1.0f, 1.0f);
program2.setAttribPointer("positions", 3, GL_FLOAT, GL_FALSE, 0, vertices.data());
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, indices.data());
在这种情况下,两个对象都以红色绘制 - 而第二个对象应该是蓝色(在第二个着色器程序中,颜色属性设置为蓝色)。我可以使用任何简单的 GLSL 着色器重现此问题。但是,如果我将上面的代码更改为:
program1.use();
program1.setAttribValue4f("color", 1.0f, 0.0f, 0.0f, 1.0f);
program1.setAttribPointer("positions", 3, GL_FLOAT, GL_FALSE, 0, vertices.data());
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, indices.data());
program2.use();
program1.setAttribValue4f("color", 0.0f, 0.0f, 1.0f, 1.0f);
program2.setAttribPointer("positions", 3, GL_FLOAT, GL_FALSE, 0, vertices.data());
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, indices.data());
第二个对象以蓝色绘制(这就是我想要完成的)。但令人困惑的是,glVertexAttrib4fv(program, pointer);
被调用在错误的程序对象(未使用),但颜色被更改 - 虽然它没有改变,如果我使用正确的程序对象 (program2)。我在 glUseProgram()
后和 glGetAttribLocation()
/glVertexAttrib4fv()
之后检查了glGetError()
- 总是返回 0。glGetAttribLocation()
返回的位置也正确。GLSL是#version 330
知道什么可能导致此问题吗?
如果您不想设置每个顶点的颜色,请使用统一来传递该值。
另外,为什么要在setAttribValue4f中调用glDisableVertexAttribArray(pos)?
我在一个简单的打字错误中发现了我的问题。作为第一个参数,我将程序对象传递给glVertexAttrib4fv()
而不是位置:
glVertexAttrib4fv(program, pointer);
应该是:
glVertexAttrib4fv(pos, pointer);
OpenGL使用弱类型(完全相同的类型GLuint
用于完全不同的对象)这一事实使得很难找到这个错误。巧合的是,我的属性的位置是第一个程序的值(值为 1 的GLuint
),这导致始终使用我在第一个程序中设置的属性(因为 eprogram 等于我想要设置的位置)。解决这个问题,为我解决了问题。
重要的是要记住,即顶点属性和着色器程序之间没有直接关系 - 规范说:
通用顶点属性索引与 顶点着色器中的用户定义属性变量是 程序对象的状态,但泛型顶点的当前值 属性不是。每个通用顶点属性的值是一部分 当前状态,即使不同的程序也会保持 对象被使用。
- C++ 命名参数习惯用语 - 未设置字符串属性
- 如何将字符串属性设置为 QTreeWidgetItem?
- 由 JOB 中的进程启动的子进程是否可以将 JOB 属性设置为脱离作业?
- 是否可以在单独的线程中将 QObject 设置为 QML 上下文属性?
- CMake 设置使用不正确的参数数调用的目标属性
- 如何使用C++获取/设置OBS中的垂直滚动过滤器属性?
- 设置使用 Cereal 序列化库时可以在序列化函数中访问的属性
- 设置类的 char* 属性
- 创建新对象并立即为其设置属性时出现编译器错误
- boost::log 设置"Channel"通道记录器中的属性
- property_tree:无法设置默认属性值
- 将 QObject* 设置为 QMLEngine 根上下文属性
- 设置文件属性成功,但检索其失败
- 如何将项目属性设置为删除警告MSB8004:中间目录不会以落后的斜线结束
- 如何根据道具名称动态设置对象的属性?
- 重载>>运算符未在输入上设置属性
- 如何将按钮的属性设置为从Qt中的小部件可见
- 将公共属性设置为私有属性
- 使用 boost.accumulators 对将特定属性设置为值的对象进行计数
- 如何将成员属性设置为QGraphicsItem的工具提示?