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 3.0 制服的问题

OpenCV-3.0 的 OpenGL 支持

如何在 OpenGL 3.0 中编程? (没有更高)

我的OpenGL学习进阶之旅学习OpenGL ES 3.0 的实战 Awsome Demo (中)

我的OpenGL学习进阶之旅学习OpenGL ES 3.0 的实战 Awsome Demo (中)

我的OpenGL学习进阶之旅学习OpenGL ES 3.0 的实战 Awsome Demo (上)