我从这个问题中了解到,一旦程序链接,着色器对象就可以被分离和删除。
缓冲区对象的行为是否与 VAO 相似?我可以在初始化 VAO 后删除它们(在Scene::Scene()
下面的末尾),还是应该让我的代码保持原样,每次我想使用它们时绑定它们?
场景.h:
class Scene
{
public:
void render();
Scene();
~Scene();
private:
GLuint vertexArray;
GLuint vertexBuffer;
GLuint indexBuffer;
GLuint program;
};
场景.cpp:
#include <GL/glew.h>
#include <stdio.h>
#include "Scene.h"
namespace
{
void printProgramInfoLog(GLuint program);
void printShaderInfoLog(GLuint shader);
}
void Scene::render()
{
glBindVertexArray(vertexArray);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glUseProgram(program);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
glUseProgram(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
Scene::Scene()
{
const float vertices[] =
{
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f,
};
const unsigned short indices[] =
{
0,
1,
2,
0,
2,
3,
};
const char* vertexShaderSource[] =
{
"#version 330\n",
"\n",
"in vec3 position;\n",
"\n",
"out vec2 fspos;",
"\n",
"void main()\n",
"{\n",
" gl_Position = vec4(position, 1.0);\n",
"fspos = vec2(position.x, position.y);\n",
"}\n",
};
const char* fragmentShaderSource[] =
{
"#version 330\n",
"\n",
"precision highp float;\n",
"\n",
"in vec2 fspos;",
"\n",
"out vec4 color;\n",
"\n",
"void main()\n",
"{\n",
" color = vec4(abs(fspos.x), abs(fspos.y), 0.0, 1.0);\n",
"}\n",
};
//-------------------------------
// Create and bind vertex array.
//-------------------------------
glGenVertexArrays(1, &vertexArray);
glBindVertexArray(vertexArray);
//--------------------------------------
// Create, bind and fill vertex buffer.
//--------------------------------------
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
//-------------------------------------
// Create, bind and fill index buffer.
//-------------------------------------
glGenBuffers(1, &indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
//-----------------
// Create program.
//-----------------
program = glCreateProgram();
//----------------------------------
// Create and attach vertex shader.
//----------------------------------
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, sizeof(vertexShaderSource) / sizeof(vertexShaderSource[0]), vertexShaderSource, 0);
glCompileShader(vertexShader);
printShaderInfoLog(vertexShader);
glAttachShader(program, vertexShader);
//------------------------------------
// Create and attach fragment shader.
//------------------------------------
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, sizeof(fragmentShaderSource) / sizeof(fragmentShaderSource[0]), fragmentShaderSource, 0);
glCompileShader(fragmentShader);
printShaderInfoLog(fragmentShader);
glAttachShader(program, fragmentShader);
//---------------
// Link program.
//---------------
glLinkProgram(program);
printProgramInfoLog(program);
//-----------------------
// Set up shader inputs.
//-----------------------
GLint position = glGetAttribLocation(program, "position");
glEnableVertexAttribArray(position);
glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, 0, 0);
//------------------------------------
// Detach and delete fragment shader.
//------------------------------------
glDetachShader(program, fragmentShader);
glDeleteShader(fragmentShader);
//----------------------------------
// Detach and delete vertex shader.
//----------------------------------
glDetachShader(program, vertexShader);
glDeleteShader(vertexShader);
//----------------------
// Unbind vertex array.
//----------------------
glBindVertexArray(0);
//!!!!!!!!!!!!!!!!!!!
// Unbinding and deleting the buffers here and only binding the VAO in
// render() works just fine, but is it okay to do this or should I leave
// it as is?
//!!!!!!!!!!!!!!!!!!!
}
Scene::~Scene()
{
glDeleteProgram(program);
glDeleteBuffers(1, &indexBuffer);
glDeleteBuffers(1, &vertexBuffer);
glDeleteVertexArrays(1, &vertexArray);
}
namespace
{
void printProgramInfoLog(GLuint program)
{
int logLength;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0)
{
char* log = new char[logLength];
glGetProgramInfoLog(program, logLength, 0, log);
fprintf(stderr, "%s", log);
delete[] log;
}
}
void printShaderInfoLog(GLuint shader)
{
int logLength;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0)
{
char* log = new char[logLength];
glGetShaderInfoLog(shader, logLength, 0, log);
fprintf(stderr, "%s", log);
delete[] log;
}
}
}