我无法让我的 OpenGL 程序渲染三角形

I can't get my OpenGL program to render a triangle

本文关键字:程序 三角形 OpenGL 我的      更新时间:2023-10-16

所以我在OpenGL中编写了一个模型加载器,它确实加载了模型,但由于某种原因,我在屏幕上看不到生成的三角形。自己看看:

#define GLEW_STATIC
#include <GLglew.h>    // Graphics Libraries
#include <GLFWglfw3.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
int main()
{
    std::cout << "Please enter the name of the mesh file: ";
    std::string FileName;
    std::cin >> FileName;
    std::cout << "You entered: " << FileName << std::endl;
    if (!glfwInit())
    {
        std::cout << "Failed to initialize GLFW" << std::endl;
        system("Pause");
        return EXIT_FAILURE;
    }
    std::cout << "GLFW 3.0.4 Initialized" << std::endl;
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    GLFWwindow* Window = glfwCreateWindow(800, 600, "Window", NULL, NULL);
    glfwMakeContextCurrent(Window);
    if (Window == NULL)
    {
        std::cout << "Failed to create an OpenGL 3.3 context" << std::endl;
        system("Pause");
        return EXIT_FAILURE;
    }
    std::cout << "Created an OpenGL 3.3 context" << std::endl;
    glewExperimental = GL_TRUE; 
    if (glewInit() != GLEW_OK)
    {
        std::cout << "Failed to initialize GLEW 1.11.0" << std::endl;
        system("Pause");
        return EXIT_FAILURE;
    }
    std::ifstream FileStream(FileName);
    std::vector <float> Vertices;
    if (!FileStream)
    {
        std::cout << "An error was encountered while opening "<< FileName << std::endl;
        system("Pause");
        return EXIT_FAILURE;
    }
    float coordinateX, coordinateY, coordinateZ;
    std::string Character;
    while (!FileStream.eof())
    {
        FileStream >> Character;
        if (Character == "v")
        {
            FileStream >> coordinateX >> coordinateY >> coordinateZ;
            std::cout << "Loading in " << coordinateX << " " << coordinateY << " " << coordinateZ << std::endl;
            Vertices.push_back(coordinateX);
            Vertices.push_back(coordinateY);
            Vertices.push_back(coordinateZ);
        }
        else
        {
            std::cout << "Skipping " << Character << std::endl;
            continue;
        }
    }
    std::cout << "Loaded " << FileName << std::endl;
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LESS);
    unsigned int VBO;
    glGenBuffers(1, &VBO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(float) * Vertices.size(), &Vertices.front(), GL_STATIC_DRAW);
    unsigned int VAO;
    glGenVertexArrays(1, &VAO);
    glBindVertexArray(VAO);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
    const char* Vertex_Shader =
        "#version 330n"
        "in vec3 vp;"
        "void main () {"
        "  gl_Position = vec4 (vp, 1.0);"
        "}";
    const char* Fragment_Shader =
        "#version 330n"
        "out vec4 frag_colour;"
        "void main () {"
        "  frag_colour = vec4 (0.5, 0.0, 0.5, 1.0);"
        "}";
    unsigned int VertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(VertexShader, 1, &Vertex_Shader, NULL);
    glCompileShader(VertexShader);
    unsigned int FragmentShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(FragmentShader, 1, &Fragment_Shader, NULL);
    glCompileShader(FragmentShader);
    unsigned int Shader_Program = glCreateProgram();
    glAttachShader(Shader_Program, FragmentShader);
    glAttachShader(Shader_Program, VertexShader);
    glLinkProgram(Shader_Program);
    while (!glfwWindowShouldClose(Window))
    {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glUseProgram(Shader_Program);
        glBindVertexArray(VAO);
        glDrawArrays(GL_TRIANGLES, 0, Vertices.size());
        glfwPollEvents();
        glfwSwapBuffers(Window);
    }
    return EXIT_SUCCESS;
}

加载的文件如下:

v 0.0 0.5 0.0
v 0.5 -0.5 0.0
v -0.5 -0.5 0.0
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
const char* Vertex_Shader =
    "#version 330n"
    "in vec3 vp;"
    "void main () {"
    "  gl_Position = vec4 (vp, 1.0);"
    "}";

无法保证将按声明顺序为属性分配属性槽。

你需要告诉OpenGL(通过location限定符或glBindAttribLocation()前链接(把它放在哪里或问(glGetAttribLocation()后链接(它被放在哪里。

此代码中至少有 3 个问题:

  1. 它创建两个顶点着色器对象,并且没有片段着色器对象。取代:

    unsigned int FragmentShader = glCreateShader(GL_VERTEX_SHADER);
    

    由:

    unsigned int FragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    
  2. glDrawArrays()的第三个参数必须是顶点数,而此代码传入坐标总数。由于此处使用每个顶点 3 个坐标,因此将调用更改为:

    glDrawArrays(GL_TRIANGLES, 0, Vertices.size() / 3);
    
  3. 未指定顶点属性的位置。这可能是"偶然"起作用的,特别是只要只有一个属性。但是指定位置要安全得多。执行此操作的最简单方法是将位置添加到vp顶点着色器的声明中:

    "layout(location = 0) in vec3 vp;"
    
  1. 你把你的GL_ARRAY_BUFFER绑错
  2. 着色器创建中存在错误
  3. 您的着色器错误

1(只需在glBindVertexArray调用绑定(并创建(您的GL_ARRAY_BUFFER即可。

2(正如在另一个答案中已经说过的,你的片段着色器创建是错误的,应该读作:unsigned int FragmentShader = glCreateShader(GL_FRAGMENT_SHADER);

3(你理所当然地认为你会在你的着色器中获得正确的属性,这是不好的做法。您应该明确并具有类似于以下内容的布局layout(location = X) in vec3 myVec;


还有几点提示:

无需在循环中重新绑定您的 VAO,只需在while(!glfwWindowShouldClose(Window))之前绑定它即可。着色器程序也是如此。

你应该检查你的着色器是否正确编译,你的程序是否正确链接!看看glGetShaderivglGetProgramiv分别用GL_COMPILE_STATUSGL_LINK_STATUS;如果你没有得到任何一种状态的GL_TRUEglGetShaderInfoLogglGetProgramInfoLog

这将为您提供一条消息,告诉您在编译/链接时遇到的确切问题,以便您可以轻松地调试着色器代码而无需猜测。