OpenGL 3.0 到 3.2
Posted
技术标签:
【中文标题】OpenGL 3.0 到 3.2【英文标题】:OpenGL 3.0 to 3.2 【发布时间】: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
。
***.com/questions/25595368/… 的子集。
也与此非常相似:***.com/questions/24643027/….
【参考方案1】:
您需要使用 VAO
用glGenVertexArrays(1, &vao);
创建一个并用glBindVertexArray(vao);
绑定
将绑定代码移动到设置代码中,像这样移动
glBindVertexArray(vao);
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);
//etc.
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[INDEX_BUFFER]);
glBindVertexArray(0);
然后在渲染过程中它只是
glBindeVertexArray(vao);
glDrawElements(GL_TRIANGLES, faces.size() * 3, GL_UNSIGNED_INT, 0);
glBindeVertexArray(0);
最好在链接程序之前bind the attribute locations,因此位置始终为 1,法线始终为 2,依此类推。
【讨论】:
感谢您的提示,真正解决了我的问题的是:***.com/questions/20766864/… 由于 glew 没有加载 glGenVertexArrays,我认为它不属于核心...以上是关于OpenGL 3.0 到 3.2的主要内容,如果未能解决你的问题,请参考以下文章
我的OpenGL学习进阶之旅学习OpenGL ES 3.0 的实战 Awsome Demo (中)