OpenGL 3.0到3.2

rio*_*oki -1 c++ opengl

我正在将我的代码从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.)

rat*_*eak 6

您需要使用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等.