Opengl 3.3 不绘制任何东西。使用 GLSL 330 核心

Posted

技术标签:

【中文标题】Opengl 3.3 不绘制任何东西。使用 GLSL 330 核心【英文标题】:Opengl 3.3 doesn't draw anything. Using GLSL 330 Core 【发布时间】:2015-03-29 23:31:07 【问题描述】:

我正在遵循this site 的指南并停止学习第 2 课。起初我尝试编写自己的代码,但在它不起作用后,我只是从网站上获取了代码。除了glClearColor,它仍然没有绘制任何东西。

我做了什么:

    检查编译和链接。工作正常 检查错误。不确定我是否做得对,但似乎一切正常(我收到 1280 错误,但我读过 GLEW 会导致它,可以忽略)。 将glUseProgram 移动到主循环中,但没有得到任何结果。 更改了颜色并尝试修改着色器。还是什么都没有

我将发布我目前拥有的代码(来自网站的原始代码):

main.cpp

#include <stdio.h>
#include <stdlib.h>
#include <glew.h>
#include <glfw3.h>
#include <glm/glm.hpp>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>


int max(int i, int j)

    if (i > j) return i;
    return j;



GLuint LoadShaders(const char * vertex_file_path, const char * fragment_file_path)

    // Create the shaders
    GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
    GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);

    // Read the Vertex Shader code from the file
    std::string VertexShaderCode;
    std::ifstream VertexShaderStream(vertex_file_path, std::ios::in);
    if (VertexShaderStream.is_open())
    
        std::string Line = "";
        while (getline(VertexShaderStream, Line))
            VertexShaderCode += "\n" + Line;
        VertexShaderStream.close();
    

    // Read the Fragment Shader code from the file
    std::string FragmentShaderCode;
    std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in);
    if (FragmentShaderStream.is_open())
        std::string Line = "";
        while (getline(FragmentShaderStream, Line))
            FragmentShaderCode += "\n" + Line;
        FragmentShaderStream.close();
    

    GLint Result = GL_FALSE;
    int InfoLogLength;

    // Compile Vertex Shader
    printf("Compiling shader : %s\n", vertex_file_path);
    char const * VertexSourcePointer = VertexShaderCode.c_str();
    glShaderSource(VertexShaderID, 1, &VertexSourcePointer, NULL);
    glCompileShader(VertexShaderID);

    // Check Vertex Shader
    glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
    glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    std::vector<char> VertexShaderErrorMessage(InfoLogLength);
    glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
    fprintf(stdout, "%s\n", &VertexShaderErrorMessage[0]);

    // Compile Fragment Shader
    printf("Compiling shader : %s\n", fragment_file_path);
    char const * FragmentSourcePointer = FragmentShaderCode.c_str();
    glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer, NULL);
    glCompileShader(FragmentShaderID);

    // Check Fragment Shader
    glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
    glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    std::vector<char> FragmentShaderErrorMessage(InfoLogLength);
    glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
    fprintf(stdout, "%s\n", &FragmentShaderErrorMessage[0]);

    // Link the program
    fprintf(stdout, "Linking program\n\n");
    GLuint ProgramID = glCreateProgram();
    glAttachShader(ProgramID, VertexShaderID);
    glAttachShader(ProgramID, FragmentShaderID);
    glLinkProgram(ProgramID);


    // Check the program
    glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
    glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    std::vector<char> ProgramErrorMessage(max(InfoLogLength, int(1)));
    std::cout << "Checking program\n";

    glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
    fprintf(stdout, "%s\n", &ProgramErrorMessage[0]);
    glDeleteShader(VertexShaderID);
    glDeleteShader(FragmentShaderID);
    std::cout << "END";

    return ProgramID;



int main(void)

    if (!glfwInit())
    
        std::cout << "Cannot init glfw";
        return -1;
    

    //glfwWindowHint(GLFW_SAMPLES, 4); // 4x antialiasing
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // We want OpenGL 3.3
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // To make MacOS happy; should not be needed
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); //We don't want the old OpenGL 



    // Open a window and create its OpenGL context 
    GLFWwindow* window; // (In the accompanying source code, this variable is global) 
    window = glfwCreateWindow(1024, 768, "Tutorial 01", NULL, NULL);
    if (window == NULL)
        fprintf(stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n");
        glfwTerminate();
        return -1;
    
    glfwMakeContextCurrent(window); // Initialize GLEW 
    glewExperimental = GL_TRUE; // Needed in core profile 
    if (glewInit() != GLEW_OK) 
        fprintf(stderr, "Failed to initialize GLEW\n");
        return -1;
    

    // Ensure we can capture the escape key being pressed below
    glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);


    // This will identify our vertex buffer
    GLuint vertexbuffer;

    // Generate 1 buffer, put the resulting identifier in vertexbuffer
    glGenBuffers(1, &vertexbuffer);

    // The following commands will talk about our 'vertexbuffer' buffer
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);

    // Give our vertices to OpenGL.
    static const GLfloat g_vertex_buffer_data[] = 
        -1.0f, -1.0f, 0.0f,
        1.0f, -1.0f, 0.0f,
        0.0f, 1.0f, 0.0f
    ;
    glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);

    glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
    GLuint programID = LoadShaders("res\\vertex.glsl", "res\\fragment.glsl");

    do

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glUseProgram(programID);

        glEnableVertexAttribArray(0);
        glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
        glVertexAttribPointer(
            0,                  // attribute 0. No particular reason for 0, but must match the layout in the shader.
            3,                  // size
            GL_FLOAT,           // type
            GL_FALSE,           // normalized?
            0,                  // stride
            (void*)0            // array buffer offset
            );

        // Draw the triangle !
        glDrawArrays(GL_TRIANGLES, 0, 3); // Starting from vertex 0; 3 vertices total -> 1 triangle

        glDisableVertexAttribArray(0);

        // Swap buffers
        glfwSwapBuffers(window);
        glfwPollEvents();


     // Check if the ESC key was pressed or the window was closed
    while (glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS &&
    glfwWindowShouldClose(window) == 0);

    return 0;

fragment.glsl

#version 330 core
out vec3 color;

void main()
    color = vec3(1,1,0);

vertex.glsl

#version 330 core

layout(location = 0) in vec3 vertexPosition_modelspace;
void main()
gl_Position.xyz = vertexPosition_modelspace;
    gl_Position.w = 1.0;
 

【问题讨论】:

此代码与核心配置文件不兼容。在核心配置文件中需要使用顶点数组对象 (VAO)。 @RetoKoradi 感谢您的评论。它解决了这种情况。您介意将其作为答案,以便我将其标记为正确吗? 你是如何解决这个问题的?我和你的处境一样,希望得到一些帮助 @RakshithRavi 我建议你看看我接受的答案。已经一年多了,我不确定我是如何解决的,但答案确实有帮助。 【参考方案1】:

OpenGL 核心配置文件需要使用顶点数组对象 (VAO)。这在规范的“已弃用和删除的功能”中:

客户端顶点和索引数组 - 所有顶点数组属性和元素数组索引指针必须引用缓冲区对象。默认的顶点数组对象(名称为零)也已弃用。在未绑定缓冲区对象或未绑定顶点数组对象时调用 VertexAttribPointer 会产生 INVALID_OPERATION 错误,当未绑定顶点数组对象时调用任何数组绘制命令也会产生错误。

您使用的教程建议将此代码用作初始化的一部分:

GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);

这足以让教程代码正常工作。为了在更复杂的应用程序中有效地使用 VAO,您可能希望为每个对象创建一个 VAO。然后,这将跟踪对象的完整顶点设置状态,并允许您在绘制之前通过单个 glBindVertexArray() 调用来设置状态。

【讨论】:

以上是关于Opengl 3.3 不绘制任何东西。使用 GLSL 330 核心的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL不绘制任何东西

为啥我的 OpenGL 不绘制任何东西?

OpenGL + SDL + glew 初始化成功后不绘制任何东西

在渲染纹理上绘制时出现问题。 (OpengL 3.3)

OpenGL:glDrawElements 不绘制

无法使用 GLEW (mac,c++) 在 openGL 中绘制任何内容