我正在将我的代码从OpenGL 3.0升级到3.3(或者甚至可能是4.x),但我遗漏了一些东西,因为屏幕是黑色的.
这个问题最接近的答案是openGL 3.1中的三角形,但3.2中没有.这里的解决方案是使用兼容性配置文件.使用核心配置文件实现正确的唯一提示是"实际使用具有完整顶点和片段着色器的适当核心配置文件GL命令序列".
我遇到的问题是,在整个下午阅读规范,教程和示例后,我看不出我的代码出错了.我目前正在开发一个演示程序来回收我使用的一些代码,你可以找到整个演示,目前只是在gitub渲染一个三角形.
多汁的比特如下:
顶点代码是:
#version 150
in vec3 aVertex;
void main()
{
gl_Position = aVertex;
}
Run Code Online (Sandbox Code Playgroud)
片段代码是:
#version 330 core
out vec4 oFragColor;
void main()
{
oFragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
Run Code Online (Sandbox Code Playgroud)
编译着色器的过程如下:
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);
Run Code Online (Sandbox Code Playgroud)
着色器绑定简单:
glUseProgram(program_id);
Run Code Online (Sandbox Code Playgroud)
顶点缓冲区创建如下:
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);
Run Code Online (Sandbox Code Playgroud)
然后使用以下序列呈现顶点缓冲区:
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);
Run Code Online (Sandbox Code Playgroud)
属性位置由以下内容确定:
return glGetAttribLocation(program_id, name.c_str());
Run Code Online (Sandbox Code Playgroud)
此代码适用于3.0和3.1.我错过了什么细节,以便从OpenGL 3.2核心开始.(它显然也适用于3.2 compat.)
您需要使用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);
Run Code Online (Sandbox Code Playgroud)
然后在渲染过程中它就是
glBindeVertexArray(vao);
glDrawElements(GL_TRIANGLES, faces.size() * 3, GL_UNSIGNED_INT, 0);
glBindeVertexArray(0);
Run Code Online (Sandbox Code Playgroud)
在链接程序之前绑定属性位置可能最好,因此位置始终为1,而法线始终为2等.