如果设置了显式版本,OpenGL程序将无法正确执行

时间:2016-05-08 15:48:39

标签: opengl glfw

我的电脑运行Ubuntu 16.04并配备了Nvidia GeForce GT 630M显卡,并安装了专有驱动程序。 glGetString(GL_VERSION)函数显示,默认情况下,我的图形卡支持OpenGL 4.5。

我一直在关注Learn OpenGL教程系列,我遇到以下困难:我只能获得教程" Hello Triangle"程序如果我注释掉行

就能正常运行
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

将这些线保持原样会阻止三角形出现。

我无法理解为什么设置所需的OpenGL版本更低比我的卡可以支持的OpenGL版本会使程序失败。

编辑:命令

std::cout << "Renderer: " << glGetString(GL_RENDERER) << std::endl;
std::cout << "Version: " << glGetString(GL_VERSION) << std::endl;
std::cout << "Shading Language: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << std::endl;

输出

Renderer: GeForce GT 630M/PCIe/SSE2
Version: 4.5.0 NVIDIA 361.42
Shading Language: 4.50 NVIDIA

如果这些行被注释掉,

Renderer: GeForce GT 630M/PCIe/SSE2
Version: 3.3.0 NVIDIA 361.42
Shading Language: 3.30 NVIDIA via Cg compiler

如果这些线留在原位。

EDIT2:这是实际的源代码:

#include <array>
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <GL/glew.h>
#include <GLFW/glfw3.h>

constexpr char FRAGMENT_SHADER_SOURCE_FILE[] = "simple_fragment.shader";
constexpr char VERTEX_SHADER_SOURCE_FILE[]   = "simple_vertex.shader";

constexpr int  WINDOW_WIDTH   = 800;
constexpr int  WINDOW_HEIGHT  = 800;
constexpr char WINDOW_TITLE[] = "Triangle";

constexpr std::array<GLfloat, 4> bgColour { 0.3f, 0.1f, 0.3f, 1.0f };

/*
 * Instructs GLFW to close window if escape key is pressed.
 */
void keyCallback(GLFWwindow *window, int key, int scancode, int action, int mode);

int main() {
    // Start GLFW.
    if (not glfwInit()) {
        std::cerr << "ERROR: Failed to start GLFW.\n";
        return 1;
    }

    // Set OpenGL version.
    //glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    //glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    //glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    // Create window and bind to current contex.
    GLFWwindow *window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE, nullptr,
                                          nullptr);
    if (not window) {
        std::cerr << "ERROR: Failed to create GLFW window.\n";
        glfwTerminate();
        return 1;
    }
    glfwMakeContextCurrent(window);

    // Set keyboard callback functions.
    glfwSetKeyCallback(window, keyCallback);

    // Initialize GLEW with experimental features turned on.
    glewExperimental = GL_TRUE;
    if (glewInit() != GLEW_OK) {
        std::cerr << "ERROR: Failed to start GLEW.\n";
        glfwTerminate();
        return 1;
    }

    // Create viewport coordinate system.
    int width, height;
    glfwGetFramebufferSize(window, &width, &height);
    glViewport(0, 0, static_cast<GLsizei>(width), static_cast<GLsizei>(height));

    // Create a vertex shader object.
    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);

    // Load the vertex shader source code.
    std::string vertexShaderSource;
    std::ifstream vsfs(VERTEX_SHADER_SOURCE_FILE);
    if (vsfs.is_open()) {
        std::stringstream ss;
        ss << vsfs.rdbuf();
        vertexShaderSource = ss.str();
    }
    else {
        std::cerr << "ERROR: File " << VERTEX_SHADER_SOURCE_FILE << " could not be found.\n";
        glfwTerminate();
        return 1;
    }

    // Attach the shader source code to the vertex shader object and compile.
    const char *vertexShaderSource_cstr = vertexShaderSource.c_str();
    glShaderSource(vertexShader, 1, &vertexShaderSource_cstr, nullptr);
    glCompileShader(vertexShader);

    // Check if compilation was successful.
    GLint success;
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if (not success) {
        std::cerr << "ERROR: Vertex shader compilation failed.\n";
        glfwTerminate();
        return 1;
    }

    // Create a fragment shader object.
    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);

    // Load the fragment shader source code.
    std::string fragmentShaderSource;
    std::ifstream fsfs(FRAGMENT_SHADER_SOURCE_FILE);
    if (fsfs.is_open()) {
        std::stringstream ss;
        ss << fsfs.rdbuf();
        fragmentShaderSource = ss.str();
    }
    else {
        std::cerr << "ERROR: File " << FRAGMENT_SHADER_SOURCE_FILE << " could not be found.\n";
        glfwTerminate();
        return 1;
    }

    // Attach the shader source code to the fragment shader object and compile.
    const char *fragmentShaderSource_cstr = fragmentShaderSource.c_str();
    glShaderSource(fragmentShader, 1, &fragmentShaderSource_cstr, nullptr);
    glCompileShader(fragmentShader);

    // Check if compilation was successful.
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if (not success) {
        std::cerr << "ERROR: Fragment shader compilation failed.\n";
        glfwTerminate();
        return 1;
    }

    // Create a shader program by linking the vertex and fragment shaders.
    GLuint shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);   

    // Check that shader program was successfully linked.
    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
    if (not success) {
        std::cerr << "ERROR: Shader program linking failed.\n";
        glfwTerminate();
        return 1;
    }

    // Delete shader objects.
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    // Coordinates of triangle vertices in Normalized Device Coordinates (NDC).
    std::array<GLfloat, 9> vertices {
        -0.5f, -0.5f,  0.0f,
         0.5f, -0.5f,  0.0f,
         0.0f,  0.5f,  0.0f
    };

    // Create a vertex array object.
    GLuint vao;
    glGenBuffers(1, &vao);
    glBindVertexArray(vao);

    // Create a vertex buffer object.
    GLuint vbo;
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);

    // Pass vertex data into currently bound vertex buffer object.
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices.data(), GL_STATIC_DRAW);

    // Create vertex attribute.
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), static_cast<GLvoid*>(0));
    glEnableVertexAttribArray(0);

    // Unbind the vertex array object and vertex buffer object.
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

    glClearColor(bgColour[0], bgColour[1], bgColour[2], bgColour[3]);

    while (not glfwWindowShouldClose(window)) {
        glClear(GL_COLOR_BUFFER_BIT);
        glfwPollEvents();

        // Inform OpenGL to use the shader program created above.
        glUseProgram(shaderProgram);

        // Bind the vertex array object.
        glBindVertexArray(vao);

        // Draw the triangle.
        glDrawArrays(GL_TRIANGLES, 0, 3);

        // Unbind the vertex array object.
        glBindVertexArray(0);

        glfwSwapBuffers(window);
    }

    // Delete vertex array object.
    glDeleteVertexArrays(1, &vao);

    // Delete vertex buffer object.
    glDeleteBuffers(1, &vbo);

    // Delete shader program.
    glDeleteProgram(shaderProgram);

    glfwDestroyWindow(window);
    glfwTerminate();
    return 0;
}

void keyCallback(GLFWwindow *window, int key, int scancode, int action, int mode) {
    if (key == GLFW_KEY_ESCAPE and action == GLFW_PRESS) {
        glfwSetWindowShouldClose(window, GL_TRUE);
    }
}

以下是simple_vertex.shadersimple_fragment.shader的内容:

#version 330 core

layout (location = 0) in vec3 position;

void main() {
    gl_Position = vec4(position.x, position.y, position.z, 1.0);
}

#version 330 core

out vec4 color;

void main() {
    color = vec4(1.0f, 0.5f, 0.2f, 1.0f);
}

1 个答案:

答案 0 :(得分:3)

我在代码中输错了。

我使用函数glGenBuffers而不是glGenVertexArrays来创建我的顶点数组对象。显然Nvidia接受这个,除非我指定一个OpenGL版本。我仍然感到困惑,但至少问题是解决的。