【发布时间】:2014-12-01 22:09:32
【问题描述】:
我正在将我的代码从 OpenGL 3.0 升级到 3.3(甚至可能是 4.x),但我缺少一些东西,因为屏幕是黑色的。
最接近这个问题的答案是triangle in openGL 3.1 but nothing in 3.2。这里的解决方案是使用兼容性配置文件。实现正确使用核心配置文件的唯一提示是“实际上使用具有完整顶点和片段着色器的正确核心配置文件 GL 命令序列。”
我遇到的问题是,在阅读规范、教程和示例一整个下午后,我看不出我的代码做错了什么。我目前正在做一个回收我使用的一些代码的演示,你可以找到整个演示,目前只是在gitub 处渲染一个三角形。
多汁的部分如下:
顶点代码为:
#version 150
in vec3 aVertex;
void main()
{
gl_Position = aVertex;
}
片段代码为:
#version 330 core
out vec4 oFragColor;
void main()
{
oFragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
编译着色器以follows:
int status = 0;
char logstr[256];
const GLchar* vbuff[1] = {vertex_code.c_str()};
unsigned int vertex_id = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_id, 1, vbuff, NULL);
glCompileShader(vertex_id);
glGetShaderInfoLog(vertex_id, 256, NULL, logstr);
glGetShaderiv(vertex_id, GL_COMPILE_STATUS, &status);
if(! status)
{
glDeleteShader(vertex_id);
throw std::runtime_error(logstr);
}
const GLchar* fbuff[1] = {fragment_code.c_str()};
unsigned int fragment_id = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_id, 1, fbuff, NULL);
glCompileShader(fragment_id);
glGetShaderInfoLog(fragment_id, 256, NULL, logstr);
glGetShaderiv(fragment_id, GL_COMPILE_STATUS, &status);
if(! status)
{
glDeleteShader(vertex_id);
glDeleteShader(fragment_id);
throw std::runtime_error(logstr);
}
program_id = glCreateProgram();
glAttachShader(program_id, vertex_id);
glAttachShader(program_id, fragment_id);
glLinkProgram(program_id);
glGetShaderInfoLog(program_id, 256, NULL, logstr);
glGetShaderiv(program_id, GL_LINK_STATUS, &status);
if(! status)
{
glDeleteShader(vertex_id);
glDeleteShader(fragment_id);
glDeleteProgram(program_id);
throw std::runtime_error(logstr);
}
glDeleteShader(vertex_id);
glDeleteShader(fragment_id);
着色器绑定了一个简单的:
glUseProgram(program_id);
顶点缓冲区被创建为follows:
glGenBuffers(5, buffers);
size_t vcount = vertexes.size();
size_t fcount = faces.size();
glBindBuffer(GL_ARRAY_BUFFER, buffers[VERTEX_BUFFER]);
glBufferData(GL_ARRAY_BUFFER, vcount * 3 * sizeof(float), &vertexes[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, buffers[NORMAL_BUFFER]);
glBufferData(GL_ARRAY_BUFFER, vcount * 3 * sizeof(float), &normals[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, buffers[TEXCOORD_BUFFER]);
glBufferData(GL_ARRAY_BUFFER, vcount * 2 * sizeof(float), &texcoords[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, buffers[TANGENT_BUFFER]);
glBufferData(GL_ARRAY_BUFFER, vcount * 3 * sizeof(float), &tangents[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[INDEX_BUFFER]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, fcount * 3 * sizeof(unsigned int), &faces[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
然后使用following sequence 渲染顶点缓冲区:
int vertex_location = shader.get_attribute_location("aVertex");
int normal_location = shader.get_attribute_location("aNormal");
int texcoord_location = shader.get_attribute_location("aTexCoord");
int tangent_location = shader.get_attribute_location("aTangent");
if (vertex_location != -1)
{
glBindBuffer(GL_ARRAY_BUFFER, buffers[VERTEX_BUFFER]);
glVertexAttribPointer(vertex_location, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(vertex_location);
}
if (normal_location != -1)
{
glBindBuffer(GL_ARRAY_BUFFER, buffers[NORMAL_BUFFER]);
glVertexAttribPointer(normal_location, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(normal_location);
}
if (texcoord_location != -1)
{
glBindBuffer(GL_ARRAY_BUFFER, buffers[TEXCOORD_BUFFER]);
glVertexAttribPointer(texcoord_location, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(texcoord_location);
}
if (tangent_location != -1)
{
glBindBuffer(GL_ARRAY_BUFFER, buffers[TANGENT_BUFFER]);
glVertexAttribPointer(tangent_location, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(tangent_location);
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[INDEX_BUFFER]);
glDrawElements(GL_TRIANGLES, faces.size() * 3, GL_UNSIGNED_INT, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
属性位置通过以下方式确定:
return glGetAttribLocation(program_id, name.c_str());
此代码适用于 3.0 和 3.1。我错过了哪些细节,以至于它从 OpenGL 3.2 核心开始就中断了。 (它显然也适用于 3.2 兼容。)
【问题讨论】:
-
从到目前为止粘贴的代码来看,我想说你的代码缺少核心中强制的 VAO。
-
您可以在整个应用程序期间生成并绑定一个 VAO。兼容性和核心的区别在于,在核心中,如果你没有非零的 VAO 界限,那么像
glVertexAttribPointer (...)这样的所有命令都是无效操作。 你真的检查过glGetError ()吗?如果是这种情况,它将显示GL_INVALID_OPERATION。