从带有GLSL 1.2的OpenGL 2.1切换到带有GLSL版本1.5的OpenGL 3.3会破坏我的代码

时间:2018-04-04 17:22:32

标签: c++ opengl sdl sdl-2

我正在尝试将OpenGL版本从OpenGL 2.1切换到OpenGL 3.3。最小可重现的OpenGL 3.3代码如下:

#include <stdio.h>

#include <SDL2/SDL.h>
#include <GL/glew.h>

static const GLuint WIDTH = 512;
static const GLuint HEIGHT = 512;
static const GLchar* vertex_shader_source =
"#version 330\n"
"in vec2 coord2d;\n"
"void main() {\n"
"    gl_Position = vec4(coord2d, 0.0, 1.0);\n"
"}\n";
static const GLchar* fragment_shader_source =
"#version 330\n"
"out vec4 color;\n"
"void main() {\n"
"    color = vec4(1.0, 0.0, 0.0, 1.0);\n"
"}\n";
static GLfloat vertices[] = {
    0.0,  0.8,
    -0.8, -0.8,
    0.8, -0.8,
};

GLuint common_get_shader_program(
                                 const char *vertex_shader_source,
                                 const char *fragment_shader_source
                                 ) {
    GLchar *log = NULL;
    GLint log_length, success;
    GLuint fragment_shader, program, vertex_shader;

    /* Vertex shader */
    vertex_shader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertex_shader, 1, &vertex_shader_source, NULL);
    glCompileShader(vertex_shader);
    glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success);
    glGetShaderiv(vertex_shader, GL_INFO_LOG_LENGTH, &log_length);
    log = (char*) malloc(log_length);
    if (log_length > 0) {
        glGetShaderInfoLog(vertex_shader, log_length, NULL, log);
        printf("vertex shader log:\n\n%s\n", log);
    }
    if (!success) {
        printf("vertex shader compile error\n");
        exit(EXIT_FAILURE);
    }

    /* Fragment shader */
    fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragment_shader, 1, &fragment_shader_source, NULL);
    glCompileShader(fragment_shader);
    glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success);
    glGetShaderiv(fragment_shader, GL_INFO_LOG_LENGTH, &log_length);
    if (log_length > 0) {
        log = (char*)realloc(log, log_length);
        glGetShaderInfoLog(fragment_shader, log_length, NULL, log);
        printf("fragment shader log:\n\n%s\n", log);
    }
    if (!success) {
        printf("fragment shader compile error\n");
        exit(EXIT_FAILURE);
    }

    /* Link shaders */
    program = glCreateProgram();
    glAttachShader(program, vertex_shader);
    glAttachShader(program, fragment_shader);
    glLinkProgram(program);
    glGetProgramiv(program, GL_LINK_STATUS, &success);
    glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length);
    if (log_length > 0) {
        log = (char*)realloc(log, log_length);
        glGetProgramInfoLog(program, log_length, NULL, log);
        printf("shader link log:\n\n%s\n", log);
    }
    if (!success) {
        printf("shader link error");
        exit(EXIT_FAILURE);
    }

    /* Cleanup. */
    free(log);
    glDeleteShader(vertex_shader);
    glDeleteShader(fragment_shader);
    return program;
}

int main(void) {
    GLint attribute_coord2d;
    GLuint program, vbo;
    SDL_Event event;

    SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO);
    SDL_GL_SetAttribute (SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute (SDL_GL_CONTEXT_MINOR_VERSION, 3);
    SDL_GL_SetAttribute (SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);

    SDL_Window *window;
    SDL_GLContext gl_context;
    window = SDL_CreateWindow(__FILE__, 0, 0,
                              WIDTH, HEIGHT, SDL_WINDOW_OPENGL);
    gl_context = SDL_GL_CreateContext(window);
    glewInit();

    /* Shader setup. */
    program = common_get_shader_program(vertex_shader_source, fragment_shader_source);
    attribute_coord2d = glGetAttribLocation(program, "coord2d");

    /* Buffer setup. */
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    glVertexAttribPointer(attribute_coord2d, 2, GL_FLOAT, GL_FALSE, 0, 0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    /* Global draw state */
    glUseProgram(program);
    glViewport(0, 0, WIDTH, HEIGHT);
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

    /* Main loop. */
    while (1) {
        glClear(GL_COLOR_BUFFER_BIT);
        glEnableVertexAttribArray(attribute_coord2d);
        glDrawArrays(GL_TRIANGLES, 0, 3);
        glDisableVertexAttribArray(attribute_coord2d);
        SDL_GL_SwapWindow(window);
        if (SDL_PollEvent(&event) && event.type == SDL_QUIT)
            break;
    }

    /* Cleanup. */
    glDeleteBuffers(1, &vbo);
    glDeleteProgram(program);
    SDL_GL_DeleteContext(gl_context);
    SDL_DestroyWindow(window);
    SDL_Quit();
    return EXIT_SUCCESS;
}

没有编译时错误,也没有运行时错误,但它只呈现一个空白屏幕。但是,当我将vertex_shader_source更改为

"#version 120\n"
"attribute vec2 coord2d;\n"
"void main() {\n"
"    gl_Position = vec4(coord2d, 0.0, 1.0);\n"
"}\n";

fragment_shader_source

"#version 120\n"
"void main() {\n"
"    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
"}\n";

并注释掉

SDL_GL_SetAttribute (SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute (SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_GL_SetAttribute (SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);

代码有效,我得到了预期的输出。

enter image description here

感觉OpenGL 3.3版本的代码应该可行,特别是考虑到两个代码片段之间的差异很小。我还检查过以确保使用glGetBufferSubData正确设置了顶点缓冲区。据我所知,它设置正确。

我能想到的唯一两种可能性是

  1. 我不了解顶点着色器和/或片段着色器源代码。
  2. 我的构建过程有问题。即库缺失或未链接。
  3. 关于第二种可能性,我在Mac OSX上使用XCode,这些是我链接的库。

    enter image description here

    有谁可以帮我弄清楚出了什么问题?

1 个答案:

答案 0 :(得分:3)

  

没有编译时错误,也没有运行时错误,但它只呈现一个空白屏幕。但是,当我改变......

在核心模式下,您必须有一个名为Vertex Array Object,因为默认的顶点数组对象“0”无效。

  

那么你的意思是我需要添加glGenVertexArrays(1, &vao); glBindVertexArray(vao);之类的内容吗?我刚试过,我得到“EXC_BAD_ACCESS(code = 1,address = 0x0)”

自从OpenGL 3.0版开始,

glGenVertexArrays可用。如果支持顶点数组对象,则可以glewGetExtension("GL_ARB_vertex_array_object")检查。

Glew可以通过以下方式启用其他扩展程序:

glewExperimental = GL_TRUE;
glewInit();

请参阅GLEW documentation

  

GLEW从图形驱动程序获取有关受支持的扩展的信息。但是,实验或预发布驱动程序可能不会通过标准机制报告每个可用的扩展,在这种情况下,GLEW将报告它不受支持。为了避免这种情况,可以在调用glewExperimental之前将GL_TRUE全局开关设置为glewInit(),从而确保所有具有有效入口点的扩展都会被公开。