Home > database >  OpenGL square does not render at all (or renders black if I add an error to shader)
OpenGL square does not render at all (or renders black if I add an error to shader)

Time:09-21

I am struggling to figure out why my GLEW/GLFW application won't render a simple square, so I have dismantled it into a single file to try to figure out what's missing.

The code below successfully opens a window, clears to the off green/blue colour I set, but does not render the square. If I add a mistake to the frag shader, it renders the pixels black where the square should be drawn (but surprisingly doesn't crash the program).

I get no errors returned from the glGetError() calls in render_func().

Here is the code I am running with everything except the shader compilation code (which I lifted straight from another project that works fine) to cut down on the example code I'm sharing.

#ifndef GLEW_STATIC
#define GLEW_STATIC
#endif
#include "GL/glew.h"
#ifndef GLFW_INCLUDE_NONE
#define GLFW_INCLUDE_NONE
#endif
#include "GLFW/glfw3.h"
#ifndef GLM_FORCE_CTOR_INIT
#define GLM_FORCE_CTOR_INIT
#endif
#include "glm/glm.hpp"

#include <array>
#include <memory>


constexpr static std::array<glm::vec3, 4> vertices {{ {-0.5, -0.5, 0.0}, {-0.5, 0.5, 0.0}, {0.5, 0.5, 0.0}, {0.5, -0.5, 0.0} }};
constexpr static std::array<uint32_t , 6> indices {{  0, 1, 2,  2, 3, 0  }};


const std::string vertex_shader_source = R"(
    #version 460 core
    layout (location = 0) in vec3 attrib_pos;

    out vec3 frag_pos;

    void main()
    {
        frag_pos = attrib_pos;
    }
)";

const std::string fragment_shader_source = R"(
    #version 460 core

    in vec3 frag_pos;
    out vec4 o_frag_colour;

    void main()
    {
        o_frag_colour = vec4(1.0, 0.5, 0.0, 1.0);
    }
)";


GLFWwindow* init_window()
{
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
//    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);
    GLFWwindow* window = glfwCreateWindow(800, 600, "GLFW Window", nullptr, nullptr);
    glfwMakeContextCurrent(window);
    glfwSetFramebufferSizeCallback(window, [](GLFWwindow* window, int width, int height){ glViewport(0, 0, width, height); });

    glfwSetErrorCallback([](int error, const char* description){
        std::cout << "nodget::App::init_glfw() - ERROR - " << std::to_string(error) << ":\n" << description << std::endl;
        throw;
    });

    glewExperimental = GL_TRUE;
    glewInit();
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glFrontFace(GL_CW);
    glEnable(GL_DEPTH_TEST);
    glDisable(GL_CULL_FACE);

    return window;
}

uint32_t init_vertex_array()
{
    using VERTEX_ELEMENT_TYPE = decltype(vertices)::value_type;
    using INDEX_ELEMENT_TYPE = decltype(indices)::value_type;

    uint32_t VAO, VBO, EBO;

    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glGenBuffers(1, &EBO);

    glBindVertexArray(VAO);

    std::cout << "vertices.size() * sizeof(Vertex) " << vertices.size() * sizeof(VERTEX_ELEMENT_TYPE) << std::endl;
    std::cout << "indices.size() * sizeof(uint32_t) " << indices.size() * sizeof(INDEX_ELEMENT_TYPE) << std::endl;

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(VERTEX_ELEMENT_TYPE), vertices.data(), GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(INDEX_ELEMENT_TYPE), indices.data(), GL_STATIC_DRAW);

    enum {
        VERTEX_POSITION_ATTRIB_INDEX = 0
    };

    glEnableVertexAttribArray(VERTEX_POSITION_ATTRIB_INDEX);
    glVertexAttribPointer(VERTEX_POSITION_ATTRIB_INDEX, 3, GL_FLOAT, false, sizeof(glm::vec3), (void*)0);

    glBindVertexArray(0);

    return VAO;
}

void render_func(GLFWwindow* window, uint32_t vao_id, uint32_t shader_id)
{
    auto error = glGetError();
    if (error != GL_NO_ERROR) {
        std::cout << "Pre Loop Error: " << error << std::endl;
    }

    while(true) {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glUseProgram(shader_id);

        glBindVertexArray(vao_id);
        glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, nullptr);
        glBindVertexArray(0);

        glfwSwapBuffers(window);
        glfwPollEvents();

        error = glGetError();
        if (error != GL_NO_ERROR) {
            std::cout << "Mid Loop Error: " << error << std::endl;
        }
    }
}

int main()
{
    auto window = init_window();
    auto vao_id = init_vertex_array();

    const std::shared_ptr<nodget::Shader> shader = std::make_shared<nodget::Shader>(std::move(vertex_shader_source), std::move(fragment_shader_source));
    shader->init_func();

    render_func(window, vao_id, shader->id);
}

CodePudding user response:

You must write the clip space coordinate to gl_Position. gl_Position is used for primitive assembly:

#version 460 core
layout (location = 0) in vec3 attrib_pos;

out vec3 frag_pos;

void main()
{
    frag_pos = attrib_pos;
    gl_Position = vec4(attrib_pos, 1.0);
}
  • Related