【发布时间】:2014-10-30 23:50:21
【问题描述】:
我对 OpenGL 还是很陌生,目前我正在处理一个简单的程序。
我遇到的问题是当我传递一个数组来表示点的颜色时,颜色最终变成了黑色。如果我只是在片段着色器中明确定义一种颜色,并且如果我在 VAO 中切换数据的索引,则三角形会移动到作为颜色的点。
我尝试使用 API 跟踪并得到以下结果:
6872: message: major api error 1282: GL_INVALID_OPERATION error generated. <program> is not a program object, or <shader> is not a shader object.
6872 @0 glAttachShader(program = 1, shader = 1)
6872: warning: glGetError(glAttachShader) = GL_INVALID_OPERATION
6876: message: major api error 1282: GL_INVALID_OPERATION error generated. Handle does not refer to the expected type of object (GL_SHADER_OBJECT_ARB).
6876 @0 glDeleteShader(shader = 1)
6876: warning: glGetError(glDeleteShader) = GL_INVALID_OPERATION
6878: message: major api error 1282: GL_INVALID_OPERATION error generated. Handle does not refer to the expected type of object (GL_SHADER_OBJECT_ARB).
6878 @0 glDeleteShader(shader = 1)
6878: warning: glGetError(glDeleteShader) = GL_INVALID_OPERATION
Rendered 507 frames in 8.52598 secs, average of 59.4653 fps
我所有的代码都是here,但它正在大量进行中。可能导致某种类型问题的位是下面的绘图段:
// TODO: Use this code once per mesh
// Make a VBO to hold points
GLuint vbo = 0;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, points.size() * sizeof(GLfloat), &points[0], drawType);
// VBO TO hold colors
GLuint colorVbo = 0;
glGenBuffers(1, &colorVbo);
glBindBuffer(GL_ARRAY_BUFFER, colorVbo);
float colors[] = {
0.5, 0.0, 0.0,
0.0, 0.5, 0.0,
0.0, 0.0, 0.5
};
glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), colors, GL_STATIC_DRAW);
// Make a VAO for the points VBO
GLuint vao = 0;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// Points
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
// Colors
glBindBuffer(GL_ARRAY_BUFFER, colorVbo);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, NULL);
GLint colorpos = glGetAttribLocation(Program::getCurrentProgram(), "vertColor");
glEnableVertexAttribArray(0); // Points
glEnableVertexAttribArray(1); // Colors
glLinkProgram(Program::getCurrentProgram());
// Draw Mesh
glDrawArrays(drawShape, 0, points.size()/2);
}
您可能需要知道的一些事情是points 是Vector<float>,Program::getCurrentProgram() 是返回当前正在使用的程序的静态函数,而drawShape 在这种情况下是GL_TRIANGLES .
顶点着色器:
#version 400 core
layout(location=0) in vec3 vert;
layout(location=1) in vec3 vertColor;
out vec3 color;
void main()
{
color = vertColor;
gl_Position = vec4(vert, 1);
}
片段着色器:
#version 400 core
in vec3 color;
out vec4 finalColor;
void main()
{
finalColor = vec4(color, 1.0);
}
如果这是一个需要花点时间研究的问题,我深表歉意。过去一天左右我环顾四周,尝试了几种不同的方法,但都没有奏效。如果需要任何其他信息以便有人不必对我的所有代码进行排序,请告诉我。
我从 apitrace 得到的信息似乎表明我可能在着色器 ID 上做错了,尽管如果我将颜色编码到片段着色器中并且颜色随后会起作用,该错误仍然会发生。
我正在使用 GLFW 来创建我的 OpenGL 上下文。我设置了一个错误回调,但我没有从中得到任何东西,我的印象是它也应该通过 OpenGL 错误,尽管我没有在他们的常见问题解答中看到任何明确说明的内容。
我也在编译着色器和链接程序时检查错误,那里也没有发生任何事情。
另外,我想知道,一旦对象超出范围并调用 delete,使用 C++ 是否可能会丢失 OpenGL 状态。
编辑:以下是我没有展示的几件事:
着色器初始化:
// Create OpenGL Shader
shaderID = glCreateShader(shaderType);
glShaderSource(shaderID, 1, &cShaderString, NULL);
// Compile
glCompileShader(shaderID);
着色器析构函数只调用glDeleteShader(shaderID);
这是相当标准的。这是在着色器类的构造函数中,shaderID 是Shader 的成员变量。 shaderType 是 GLenum,在这种情况下是 GL_VERTEX_SHADER 或 GL_FRAGMENT_SHADER。
程序初始化: // 创建程序 程序ID = glCreateProgram();
// Iterate through Shaders
for(std::vector<Shader>::iterator shader = shaders.begin(); shader != shaders.end(); shader++)
{
// Attach Shader
glAttachShader(programID, shader->getShaderID());
}
// Link program
glLinkProgram(programID);
程序析构函数:
// Iterate through attached shaders
for(std::vector<Shader>::iterator shader = shaders.begin(); shader != shaders.end(); shader++)
{
// Detach Shader
glDetachShader(programID, shader->getShaderID());
}
// Delete program
glDeleteProgram(programID);
再一次,这看起来很标准,并且在 Program 类的构造函数中。
编辑 2: 搞砸了一些代码后,我发现了一个相当奇怪的东西。如果我移动创建和绑定缓冲区的代码并将三角形绘制到我用作表示三角形的类的构造函数中,我将位置作为颜色而不是位置。这与我切换数据上的索引(位置为 1,颜色为 0)时发生的情况相同。
编辑 3: 实际上,再看多一点后,它似乎绘制了一个与颜色完全不同的三角形。为 Triangle 类创建一个 vao 成员并将其绑定到 draw 似乎可以解决此问题。
编辑 4: 似乎 glValidateProgram() 确实产生了成功的结果,这让我怀疑它的着色器是否存在问题。
【问题讨论】:
-
嗯,来自跟踪的错误消息暗示着色器初始化存在问题。您尚未为此粘贴相关代码。 “glAttachShader(program = 1, shader = 1)” 看起来您尝试将程序附加到程序,而不是着色器。以及为什么在你的属性设置完全超出我的能力之后你称之为
glLinkProgram()。 -
@derhass 我已经更新了帖子以对着色器和程序进行初始化。在我看来,他们俩都很标准。至于程序和着色器的索引都为 1,我认为这可能只是巧合,但我会稍微研究一下。再次调用
glLinkProgram()是我在某处测试过的事情之一,在我读到的某处提到该程序应在设置属性后链接,或者应在设置属性后再次链接。我只是在看到它没有效果后忘记删除该行。 -
@derhass 经过更多调试,似乎着色器的 ID 为 1 和 2。从我帖子中的错误来看,看起来程序的 ID 为 1好吧。
-
一些平台为不同类型的对象提供不同的 ID,而另一些则没有。对于着色器和程序,您完全有可能获得 1 的 id。也就是说,该错误肯定表明 id 存在问题。
-
@RetoKoradi 我会再看一下,但看起来这些是从
glCreateShader()和glCreateProgram()返回的 ID 我也有点奇怪当我编译两个着色器时,只有一个着色器出现这些错误。调用glCompileShader时,我也没有收到任何类型的错误。用 C++ 类表示的所有东西是否有可能以某种方式破坏 OpenGL 状态?