简体   繁体   中英

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

So I've coded a model loader in OpenGL, and, it does in fact loads models, but for some reason, I can't see the resulting triangle on the screen. Take a look for yourself:

#define GLEW_STATIC

#include <GL\glew.h>    // Graphics Libraries
#include <GLFW\glfw3.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 330\n"
        "in vec3 vp;"
        "void main () {"
        "  gl_Position = vec4 (vp, 1.0);"
        "}";

    const char* Fragment_Shader =
        "#version 330\n"
        "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;
}

And the loaded file is as follows:

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 330\n"
    "in vec3 vp;"
    "void main () {"
    "  gl_Position = vec4 (vp, 1.0);"
    "}";

There's no guarantee that attributes will be allocated attribute slots in declaration order.

You need to tell OpenGL (via a location qualifier or glBindAttribLocation() pre-link ) where to put it or ask ( glGetAttribLocation() post-link ) where it was put.

There are at least 3 problems in this code:

  1. It creates two vertex shader objects, and no fragment shader object. Replace:

     unsigned int FragmentShader = glCreateShader(GL_VERTEX_SHADER); 

    by:

     unsigned int FragmentShader = glCreateShader(GL_FRAGMENT_SHADER); 
  2. The third argument to glDrawArrays() must be the number of vertices, while this code passes in the total number of coordinates. Since 3 coordinates per vertex are used here, change the call to:

     glDrawArrays(GL_TRIANGLES, 0, Vertices.size() / 3); 
  3. The location of the vertex attribute is not specified. This might work by "accident", particularly as long as there is only one attribute. But it's much safer to specify the location. The easiest way to do this is to add the location to the declaration of vp the vertex shader:

     "layout(location = 0) in vec3 vp;" 
  1. You are binding your GL_ARRAY_BUFFER wrong
  2. You have a bug in your shader creation
  3. Your shaders are wrong

1) Simply bind (and create) your GL_ARRAY_BUFFER after your glBindVertexArray call.

2) As already said in another answer, your fragment shader creation is wrong and should read: unsigned int FragmentShader = glCreateShader(GL_FRAGMENT_SHADER);

3) You are taking for granted that you will get the right attributes in your shaders, this is bad practice. You should be explicit and have a layout similar to this: layout(location = X) in vec3 myVec;


also as a few tips:

There's no need to re-bind your VAO within the loop, just bind it before while(!glfwWindowShouldClose(Window)) . Same goes for your shader program.

You should be checking that your shaders compiled correctly and that your program linked correctly! have a look at glGetShaderiv , glGetProgramiv with GL_COMPILE_STATUS and GL_LINK_STATUS respectively; and glGetShaderInfoLog and glGetProgramInfoLog if you don't get GL_TRUE for either status.

This will give you a message telling you the exact problem you get when compiling/linking so you can debug your shader code easily without having to guess.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM