glfw和glew无法呈现(带有VAO的glDrawElements)

时间:2018-12-26 18:29:48

标签: c++ opengl glfw glew

我将转储所有信息。我正在使用c ++。不管我尝试什么,glClear()都有效,渲染网格无效。没有错误。

我已经从freeglut切换到glfw。我以前没问题。我有glfw3 dll和lib,也有问题。由于外部问题未解决,我也链接了OpenGL32 lib。

我正在使用Visual Studio 2017,并且库是最新的。

我从glfw主站点获得了glfw,并下载了64位二进制文​​件。我从http://glew.sourceforge.net/获得了32位和64位二进制文​​件。我编译为64位,并在Windows 10 64位上运行。

它当前可以编译并运行,没有代码错误。

编辑: 我接受了一些建议,但仍然看不到四边形。感谢您的输入。

新代码:

#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);
}

3 个答案:

答案 0 :(得分:2)

一些问题:

  • 如今,甚至 Intel 也支持OpenGL 3.3 Core上下文。请求一个:

    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    
  • 验证您的着色器是否实际编译/链接。在我的系统上,顶点着色器失败,并显示以下信息:

    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驱动程序内部降低访问冲突,否则不要这样做:)

屏幕截图:

screenshot

一起:

#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;
}

答案 1 :(得分:1)

glVertexAttribPointer接受传递的参数和当前绑定的VBO ,并将该信息保存在当前绑定的VAO状态内。

glEnableVertexAttribArray也会在当前绑定的VAO中启用属性。您启用它们为时过早。

因此,正确的处理顺序是:

  1. 绑定VAO
  2. 绑定VBO
  3. 致电glVertexAttribPointerglEnableVertexAttribArray
  4. 现在您可以取消绑定VBO或重复2-3,因为3.将状态保存到VAO中。
  5. 解除绑定VAO

索引缓冲区应放置在1-5之间的任何位置。请注意不要在VAO仍绑定的情况下意外地解除索引缓冲区的绑定。因为VAO只记住一个索引缓冲区。

除了那些早期的电话,我再也没有发现错误。

通过将glVertexAttribPointer的功能分为glVertexArrayAttribBindingglVertexArrayAttribFormatglBindVertexBuffer,在OpenGL 4.5中“揭示了”对VBO的这种“隐藏”捕获。

答案 2 :(得分:1)

命名的index buffer对象是vertex array object状态向量的状态。 如果执行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
};