glfw 和 glew 不渲染(glDrawElements 与 VAO)
glfw and glew not rendering (glDrawElements with VAO)
我会转储所有信息。我正在使用 C++。无论我尝试什么,glClear()
都有效,而渲染网格则无效。没有错误。
我已经从 freeglut 切换到 glfw。我以前没有问题。我有 glfw3 dll 和 lib,glew 也有。由于未解决的外部问题,我还链接了 OpenGL32 库。
我使用的是 Visual Studio 2017 并且库是最新的。
我从主 glfw 站点获取 glfw 并下载了 64 位二进制文件。我从 http://glew.sourceforge.net/ 得到了 glew 32 位和 64 位二进制文件。我编译为 64 位和 运行 它在 windows 10 64 位上。
目前可以编译并且 运行s 没有代码错误。
编辑:
我听取了一些建议,但仍然看不到四边形。感谢您的输入。
新代码:
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <stdlib.h>
#include <stdio.h>
#include <fstream>
#include <string>
#include <iostream>
#include <vector>
GLFWwindow * window;
int width;
int height;
unsigned int vertex_array_buffer;
unsigned int vertex_buffer;
unsigned int index_buffer;
float vertex_model[24] = {
-0.5f, -0.5f, 0.0f,
0.0f, 0.0f, 1.0f,
-0.5f, 0.5f, 0.0f,
0.0f, 1.0f, 1.0f,
0.5f, 0.5f, 0.0f,
1.0f, 1.0f, 1.0f,
0.5f, -0.5f, 0.0f,
1.0f, 0.0f, 1.0f
};
unsigned int index_model[6] = {
0, 1, 2,
0, 2, 3
};
unsigned int program;
float ratio;
int main() {
if (!glfwInit()) {
exit(-1);
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
window = glfwCreateWindow(640, 480, "RenderEngine v0.0.0", NULL, NULL);
if (!window)
{
exit(-1);
}
glfwMakeContextCurrent(window);
if (glewInit()) {
exit(-1);
}
glfwSwapInterval(1);
unsigned int vert_shader;
unsigned int frag_shader;
const char * vert_shader_text;
const char * frag_shader_text;
std::ifstream file;
std::string buffer;
size_t f_size;
file.open("shader.vert", std::ifstream::in | std::ifstream::binary);
file.seekg(0, std::ios::end);
f_size = file.tellg();
buffer.resize(f_size);
file.seekg(0);
file.read(&buffer[0], f_size);
file.close();
vert_shader_text = buffer.c_str();
buffer.clear();
file.open("shader.frag", std::ifstream::in | std::ifstream::binary);
file.seekg(0, std::ios::end);
f_size = file.tellg();
buffer.resize(f_size);
file.seekg(0);
file.read(&buffer[0], f_size);
file.close();
frag_shader_text = buffer.c_str();
vert_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vert_shader, 1, &vert_shader_text, NULL);
glCompileShader(vert_shader);
int result = GL_FALSE;
int log_length;
glGetShaderiv(vert_shader, GL_COMPILE_STATUS, &result);
glGetShaderiv(vert_shader, GL_INFO_LOG_LENGTH, &log_length);
std::vector<char> vert_shader_error((log_length > 1) ? log_length : 1);
glGetShaderInfoLog(vert_shader, log_length, NULL, &vert_shader_error[0]);
std::cout << &vert_shader_error[0] << '\n';
result = GL_FALSE;
frag_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(frag_shader, 1, &frag_shader_text, NULL);
glCompileShader(frag_shader);
glGetShaderiv(frag_shader, GL_COMPILE_STATUS, &result);
glGetShaderiv(frag_shader, GL_INFO_LOG_LENGTH, &log_length);
std::vector<char> frag_shader_error((log_length > 1) ? log_length : 1);
glGetShaderInfoLog(frag_shader, log_length, NULL, &frag_shader_error[0]);
std::cout << &frag_shader_error[0] << '\n';
program = glCreateProgram();
glAttachShader(program, vert_shader);
glAttachShader(program, frag_shader);
glBindAttribLocation(program, 0, "pos");
glBindAttribLocation(program, 1, "color");
glLinkProgram(program);
glDeleteShader(vert_shader);
glDeleteShader(frag_shader);
glGetProgramiv(program, GL_LINK_STATUS, &result);
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length);
std::vector<char> program_error((log_length > 1) ? log_length : 1);
glGetProgramInfoLog(program, log_length, NULL, &program_error[0]);
std::cout << &program_error[0] << '\n';
glUseProgram(program);
glGenVertexArrays(1, &vertex_array_buffer);
glBindVertexArray(vertex_array_buffer);
glGenBuffers(1, &vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_model), vertex_model, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 6, (void*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 6, (void*)(sizeof(float) * 3));
glGenBuffers(1, &index_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(index_model), index_model, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
if (glGetError()) {
exit(-1);
}
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
while (!glfwWindowShouldClose(window))
{
glfwGetFramebufferSize(window, &width, &height);
ratio = width / (float)height;
glViewport(0, 0, width, height);
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(vertex_array_buffer);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
glBindVertexArray(0);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
如果需要,还有着色器文件。顶点着色器:
#version 330
in layout(location = 0) vec3 pos;
in layout(location = 1) vec3 color;
out vec3 out_color;
void main() {
gl_Position = vec4(pos, 1.0f);
out_color = color;
}
片段着色器:
#version 330
in vec3 out_color;
out vec4 final_color;
void main() {
final_color = vec4(out_color, 1.0f);
}
几个问题:
现在甚至 Intel 也支持 OpenGL 3.3 Core 上下文。请求一:
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
实际验证您的着色器 compile/link。在我的系统上,顶点着色器失败并显示:
Vertex shader failed to compile with the following errors:
ERROR: 0:3: error(#12) Unexpected qualifier
ERROR: 0:4: error(#12) Unexpected qualifier
ERROR: error(#273) 2 compilation errors. No code generated
layout()
应该放在in
之前:
layout(location = 0) in vec3 pos;
layout(location = 1) in vec3 color;
在解除绑定 VAO 后GL_ELEMENT_ARRAY_BUFFER
解除绑定。
index_model
正在索引 vertex_model
的末尾。不要那样做,除非你喜欢 OpenGL 驱动程序内部的访问冲突:)
截图:
总计:
#include <GL/glew.h>
#include <glfw/glfw3.h>
#include <iostream>
#include <cstdarg>
struct Program
{
static GLuint Load( const char* shader, ... )
{
GLuint prog = glCreateProgram();
va_list args;
va_start( args, shader );
while( shader )
{
const GLenum type = va_arg( args, GLenum );
AttachShader( prog, type, shader );
shader = va_arg( args, const char* );
}
va_end( args );
glLinkProgram( prog );
CheckStatus( prog );
return prog;
}
private:
static void CheckStatus( GLuint obj )
{
GLint status = GL_FALSE;
if( glIsShader( obj ) ) glGetShaderiv( obj, GL_COMPILE_STATUS, &status );
if( glIsProgram( obj ) ) glGetProgramiv( obj, GL_LINK_STATUS, &status );
if( status == GL_TRUE ) return;
GLchar log[ 1 << 15 ] = { 0 };
if( glIsShader( obj ) ) glGetShaderInfoLog( obj, sizeof( log ), NULL, log );
if( glIsProgram( obj ) ) glGetProgramInfoLog( obj, sizeof( log ), NULL, log );
std::cerr << log << std::endl;
std::exit( EXIT_FAILURE );
}
static void AttachShader( GLuint program, GLenum type, const char* src )
{
GLuint shader = glCreateShader( type );
glShaderSource( shader, 1, &src, NULL );
glCompileShader( shader );
CheckStatus( shader );
glAttachShader( program, shader );
glDeleteShader( shader );
}
};
const char* vert = 1 + R"GLSL(
#version 330 core
layout(location = 0) in vec3 pos;
layout(location = 1) in vec3 color;
out vec3 out_color;
void main() {
gl_Position = vec4(pos, 1.0f);
out_color = color;
}
)GLSL";
const char* frag = 1 + R"GLSL(
#version 330 core
in vec3 out_color;
out vec4 final_color;
void main() {
final_color = vec4(out_color, 1.0f);
}
)GLSL";
GLFWwindow * window;
int width;
int height;
unsigned int vertex_array_buffer;
unsigned int vertex_buffer;
unsigned int index_buffer;
float vertex_model[] =
{
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f,
-0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f,
0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 1.0f,
0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f,
};
unsigned int index_model[] =
{
0, 1, 2,
};
unsigned int program;
float ratio;
int main()
{
if( !glfwInit() )
{
exit( -1 );
}
glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, 3 );
glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 3 );
glfwWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE );
window = glfwCreateWindow( 640, 480, "RenderEngine v0.0.0", NULL, NULL );
if( !window )
{
exit( -1 );
}
glfwMakeContextCurrent( window );
if( glewInit() )
{
exit( -1 );
}
glfwSwapInterval( 1 );
GLuint program = Program::Load( vert, GL_VERTEX_SHADER, frag, GL_FRAGMENT_SHADER, NULL );
glUseProgram( program );
glGenVertexArrays( 1, &vertex_array_buffer );
glBindVertexArray( vertex_array_buffer );
glGenBuffers( 1, &vertex_buffer );
glBindBuffer( GL_ARRAY_BUFFER, vertex_buffer );
glBufferData( GL_ARRAY_BUFFER, sizeof( vertex_model ), vertex_model, GL_STATIC_DRAW );
glEnableVertexAttribArray( 0 );
glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, sizeof( float ) * 6, (void*)0 );
glEnableVertexAttribArray( 1 );
glVertexAttribPointer( 1, 3, GL_FLOAT, GL_FALSE, sizeof( float ) * 6, (void*)( sizeof( float ) * 3 ) );
glBindBuffer( GL_ARRAY_BUFFER, 0 );
glGenBuffers( 1, &index_buffer );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, index_buffer );
glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof( index_model ), index_model, GL_STATIC_DRAW );
glBindVertexArray( 0 );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
while( !glfwWindowShouldClose( window ) )
{
glfwGetFramebufferSize( window, &width, &height );
ratio = width / (float)height;
glViewport( 0, 0, width, height );
glClear( GL_COLOR_BUFFER_BIT );
glBindVertexArray( vertex_array_buffer );
glDrawElements( GL_TRIANGLES, 3, GL_UNSIGNED_INT, nullptr );
glBindVertexArray( 0 );
glfwSwapBuffers( window );
glfwPollEvents();
}
glfwDestroyWindow( window );
glfwTerminate();
return 0;
}
glVertexAttribPointer
获取传递的参数和当前绑定的 VBO 并将该信息保存在 当前 绑定的 VAO 的状态中。
glEnableVertexAttribArray
也仅在 当前 绑定的 VAO 中启用一个属性。你太早启用它们了。
所以,正确的做事顺序是:
- 绑定 VAO
- 绑定 VBO
- 调用
glVertexAttribPointer
和 glEnableVertexAttribArray
- 现在你可以解绑VBO或者重复2-3因为3.保存了状态到VAO
- 解绑 VAO
索引缓冲区应放置在 1-5 之间的任何位置。请注意不要意外地过早解除索引缓冲区的绑定——此时 VAO 仍处于绑定状态。因为 VAO 只记住一个索引缓冲区。
除了早期的调用,我没有发现任何错误。
通过将 glVertexAttribPointer
的功能拆分为 glVertexArrayAttribBinding
、glVertexArrayAttribFormat
和 [=17],此 "hidden" VBO 捕获已在 OpenGL 4.5 中 "revealed" =].
名为 index buffer object is a state of the vertex array objects 的状态向量。
如果你这样做glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)
,当顶点数组对象被绑定时,那么对元素缓冲区的引用就被破坏了。
删除glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
,解决问题:
glGenVertexArrays(1, &vertex_array_buffer);
glBindVertexArray(vertex_array_buffer);
// [...]
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
// [...]
//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); // <---- skip this
glBindVertexArray(0);
顶点数组中有4个坐标和颜色属性,所以索引必须在[0, 3]范围内。坐标排列成四边形,四边形可以由2个三角形绘制如下:
1 2
+-------+
| / |
| / |
| / |
+-------+
0 3
unsigned int index_model[6] = {
0, 1, 2,
0, 2, 3
};
我会转储所有信息。我正在使用 C++。无论我尝试什么,glClear()
都有效,而渲染网格则无效。没有错误。
我已经从 freeglut 切换到 glfw。我以前没有问题。我有 glfw3 dll 和 lib,glew 也有。由于未解决的外部问题,我还链接了 OpenGL32 库。
我使用的是 Visual Studio 2017 并且库是最新的。
我从主 glfw 站点获取 glfw 并下载了 64 位二进制文件。我从 http://glew.sourceforge.net/ 得到了 glew 32 位和 64 位二进制文件。我编译为 64 位和 运行 它在 windows 10 64 位上。
目前可以编译并且 运行s 没有代码错误。
编辑: 我听取了一些建议,但仍然看不到四边形。感谢您的输入。
新代码:
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <stdlib.h>
#include <stdio.h>
#include <fstream>
#include <string>
#include <iostream>
#include <vector>
GLFWwindow * window;
int width;
int height;
unsigned int vertex_array_buffer;
unsigned int vertex_buffer;
unsigned int index_buffer;
float vertex_model[24] = {
-0.5f, -0.5f, 0.0f,
0.0f, 0.0f, 1.0f,
-0.5f, 0.5f, 0.0f,
0.0f, 1.0f, 1.0f,
0.5f, 0.5f, 0.0f,
1.0f, 1.0f, 1.0f,
0.5f, -0.5f, 0.0f,
1.0f, 0.0f, 1.0f
};
unsigned int index_model[6] = {
0, 1, 2,
0, 2, 3
};
unsigned int program;
float ratio;
int main() {
if (!glfwInit()) {
exit(-1);
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
window = glfwCreateWindow(640, 480, "RenderEngine v0.0.0", NULL, NULL);
if (!window)
{
exit(-1);
}
glfwMakeContextCurrent(window);
if (glewInit()) {
exit(-1);
}
glfwSwapInterval(1);
unsigned int vert_shader;
unsigned int frag_shader;
const char * vert_shader_text;
const char * frag_shader_text;
std::ifstream file;
std::string buffer;
size_t f_size;
file.open("shader.vert", std::ifstream::in | std::ifstream::binary);
file.seekg(0, std::ios::end);
f_size = file.tellg();
buffer.resize(f_size);
file.seekg(0);
file.read(&buffer[0], f_size);
file.close();
vert_shader_text = buffer.c_str();
buffer.clear();
file.open("shader.frag", std::ifstream::in | std::ifstream::binary);
file.seekg(0, std::ios::end);
f_size = file.tellg();
buffer.resize(f_size);
file.seekg(0);
file.read(&buffer[0], f_size);
file.close();
frag_shader_text = buffer.c_str();
vert_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vert_shader, 1, &vert_shader_text, NULL);
glCompileShader(vert_shader);
int result = GL_FALSE;
int log_length;
glGetShaderiv(vert_shader, GL_COMPILE_STATUS, &result);
glGetShaderiv(vert_shader, GL_INFO_LOG_LENGTH, &log_length);
std::vector<char> vert_shader_error((log_length > 1) ? log_length : 1);
glGetShaderInfoLog(vert_shader, log_length, NULL, &vert_shader_error[0]);
std::cout << &vert_shader_error[0] << '\n';
result = GL_FALSE;
frag_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(frag_shader, 1, &frag_shader_text, NULL);
glCompileShader(frag_shader);
glGetShaderiv(frag_shader, GL_COMPILE_STATUS, &result);
glGetShaderiv(frag_shader, GL_INFO_LOG_LENGTH, &log_length);
std::vector<char> frag_shader_error((log_length > 1) ? log_length : 1);
glGetShaderInfoLog(frag_shader, log_length, NULL, &frag_shader_error[0]);
std::cout << &frag_shader_error[0] << '\n';
program = glCreateProgram();
glAttachShader(program, vert_shader);
glAttachShader(program, frag_shader);
glBindAttribLocation(program, 0, "pos");
glBindAttribLocation(program, 1, "color");
glLinkProgram(program);
glDeleteShader(vert_shader);
glDeleteShader(frag_shader);
glGetProgramiv(program, GL_LINK_STATUS, &result);
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length);
std::vector<char> program_error((log_length > 1) ? log_length : 1);
glGetProgramInfoLog(program, log_length, NULL, &program_error[0]);
std::cout << &program_error[0] << '\n';
glUseProgram(program);
glGenVertexArrays(1, &vertex_array_buffer);
glBindVertexArray(vertex_array_buffer);
glGenBuffers(1, &vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_model), vertex_model, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 6, (void*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 6, (void*)(sizeof(float) * 3));
glGenBuffers(1, &index_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(index_model), index_model, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
if (glGetError()) {
exit(-1);
}
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
while (!glfwWindowShouldClose(window))
{
glfwGetFramebufferSize(window, &width, &height);
ratio = width / (float)height;
glViewport(0, 0, width, height);
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(vertex_array_buffer);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
glBindVertexArray(0);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
如果需要,还有着色器文件。顶点着色器:
#version 330
in layout(location = 0) vec3 pos;
in layout(location = 1) vec3 color;
out vec3 out_color;
void main() {
gl_Position = vec4(pos, 1.0f);
out_color = color;
}
片段着色器:
#version 330
in vec3 out_color;
out vec4 final_color;
void main() {
final_color = vec4(out_color, 1.0f);
}
几个问题:
现在甚至 Intel 也支持 OpenGL 3.3 Core 上下文。请求一:
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
实际验证您的着色器 compile/link。在我的系统上,顶点着色器失败并显示:
Vertex shader failed to compile with the following errors: ERROR: 0:3: error(#12) Unexpected qualifier ERROR: 0:4: error(#12) Unexpected qualifier ERROR: error(#273) 2 compilation errors. No code generated
layout()
应该放在in
之前:layout(location = 0) in vec3 pos; layout(location = 1) in vec3 color;
在解除绑定 VAO 后
GL_ELEMENT_ARRAY_BUFFER
解除绑定。index_model
正在索引vertex_model
的末尾。不要那样做,除非你喜欢 OpenGL 驱动程序内部的访问冲突:)
截图:
总计:
#include <GL/glew.h>
#include <glfw/glfw3.h>
#include <iostream>
#include <cstdarg>
struct Program
{
static GLuint Load( const char* shader, ... )
{
GLuint prog = glCreateProgram();
va_list args;
va_start( args, shader );
while( shader )
{
const GLenum type = va_arg( args, GLenum );
AttachShader( prog, type, shader );
shader = va_arg( args, const char* );
}
va_end( args );
glLinkProgram( prog );
CheckStatus( prog );
return prog;
}
private:
static void CheckStatus( GLuint obj )
{
GLint status = GL_FALSE;
if( glIsShader( obj ) ) glGetShaderiv( obj, GL_COMPILE_STATUS, &status );
if( glIsProgram( obj ) ) glGetProgramiv( obj, GL_LINK_STATUS, &status );
if( status == GL_TRUE ) return;
GLchar log[ 1 << 15 ] = { 0 };
if( glIsShader( obj ) ) glGetShaderInfoLog( obj, sizeof( log ), NULL, log );
if( glIsProgram( obj ) ) glGetProgramInfoLog( obj, sizeof( log ), NULL, log );
std::cerr << log << std::endl;
std::exit( EXIT_FAILURE );
}
static void AttachShader( GLuint program, GLenum type, const char* src )
{
GLuint shader = glCreateShader( type );
glShaderSource( shader, 1, &src, NULL );
glCompileShader( shader );
CheckStatus( shader );
glAttachShader( program, shader );
glDeleteShader( shader );
}
};
const char* vert = 1 + R"GLSL(
#version 330 core
layout(location = 0) in vec3 pos;
layout(location = 1) in vec3 color;
out vec3 out_color;
void main() {
gl_Position = vec4(pos, 1.0f);
out_color = color;
}
)GLSL";
const char* frag = 1 + R"GLSL(
#version 330 core
in vec3 out_color;
out vec4 final_color;
void main() {
final_color = vec4(out_color, 1.0f);
}
)GLSL";
GLFWwindow * window;
int width;
int height;
unsigned int vertex_array_buffer;
unsigned int vertex_buffer;
unsigned int index_buffer;
float vertex_model[] =
{
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f,
-0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f,
0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 1.0f,
0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f,
};
unsigned int index_model[] =
{
0, 1, 2,
};
unsigned int program;
float ratio;
int main()
{
if( !glfwInit() )
{
exit( -1 );
}
glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, 3 );
glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 3 );
glfwWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE );
window = glfwCreateWindow( 640, 480, "RenderEngine v0.0.0", NULL, NULL );
if( !window )
{
exit( -1 );
}
glfwMakeContextCurrent( window );
if( glewInit() )
{
exit( -1 );
}
glfwSwapInterval( 1 );
GLuint program = Program::Load( vert, GL_VERTEX_SHADER, frag, GL_FRAGMENT_SHADER, NULL );
glUseProgram( program );
glGenVertexArrays( 1, &vertex_array_buffer );
glBindVertexArray( vertex_array_buffer );
glGenBuffers( 1, &vertex_buffer );
glBindBuffer( GL_ARRAY_BUFFER, vertex_buffer );
glBufferData( GL_ARRAY_BUFFER, sizeof( vertex_model ), vertex_model, GL_STATIC_DRAW );
glEnableVertexAttribArray( 0 );
glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, sizeof( float ) * 6, (void*)0 );
glEnableVertexAttribArray( 1 );
glVertexAttribPointer( 1, 3, GL_FLOAT, GL_FALSE, sizeof( float ) * 6, (void*)( sizeof( float ) * 3 ) );
glBindBuffer( GL_ARRAY_BUFFER, 0 );
glGenBuffers( 1, &index_buffer );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, index_buffer );
glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof( index_model ), index_model, GL_STATIC_DRAW );
glBindVertexArray( 0 );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
while( !glfwWindowShouldClose( window ) )
{
glfwGetFramebufferSize( window, &width, &height );
ratio = width / (float)height;
glViewport( 0, 0, width, height );
glClear( GL_COLOR_BUFFER_BIT );
glBindVertexArray( vertex_array_buffer );
glDrawElements( GL_TRIANGLES, 3, GL_UNSIGNED_INT, nullptr );
glBindVertexArray( 0 );
glfwSwapBuffers( window );
glfwPollEvents();
}
glfwDestroyWindow( window );
glfwTerminate();
return 0;
}
glVertexAttribPointer
获取传递的参数和当前绑定的 VBO 并将该信息保存在 当前 绑定的 VAO 的状态中。
glEnableVertexAttribArray
也仅在 当前 绑定的 VAO 中启用一个属性。你太早启用它们了。
所以,正确的做事顺序是:
- 绑定 VAO
- 绑定 VBO
- 调用
glVertexAttribPointer
和glEnableVertexAttribArray
- 现在你可以解绑VBO或者重复2-3因为3.保存了状态到VAO
- 解绑 VAO
索引缓冲区应放置在 1-5 之间的任何位置。请注意不要意外地过早解除索引缓冲区的绑定——此时 VAO 仍处于绑定状态。因为 VAO 只记住一个索引缓冲区。
除了早期的调用,我没有发现任何错误。
通过将 glVertexAttribPointer
的功能拆分为 glVertexArrayAttribBinding
、glVertexArrayAttribFormat
和 [=17],此 "hidden" VBO 捕获已在 OpenGL 4.5 中 "revealed" =].
名为 index buffer object is a state of the vertex array objects 的状态向量。
如果你这样做glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)
,当顶点数组对象被绑定时,那么对元素缓冲区的引用就被破坏了。
删除glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
,解决问题:
glGenVertexArrays(1, &vertex_array_buffer);
glBindVertexArray(vertex_array_buffer);
// [...]
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
// [...]
//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); // <---- skip this
glBindVertexArray(0);
顶点数组中有4个坐标和颜色属性,所以索引必须在[0, 3]范围内。坐标排列成四边形,四边形可以由2个三角形绘制如下:
1 2
+-------+
| / |
| / |
| / |
+-------+
0 3
unsigned int index_model[6] = {
0, 1, 2,
0, 2, 3
};