Search code examples
c++openglglfw

Multiple objects fail to render?


My should display two squares on the screen but when I run it all I see is a screen of nothingness.

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




struct Shaderprogramsource
{
std::string VertexSouce;
std::string FragmentSource;
};

static Shaderprogramsource Parseshader(const std::string& filepath)
{
std::ifstream stream(filepath);

enum class Shadertype
{
    VERTEX = 0,
    FRAGMENT = 1,
    NONE = 5
};

std::string line;
std::stringstream ss[3];

Shadertype type = Shadertype::NONE;

while (getline(stream, line))
{
    if (line.find("#shader") != std::string::npos)
    {
        if (line.find("vertex") != std::string::npos)
            type = Shadertype::VERTEX;

        else if (line.find("fragment") != std::string::npos)
            type = Shadertype::FRAGMENT;
    }
    else
    {
        ss[(int)type] << line << "\n";
    }
}

return Shaderprogramsource{ ss[0].str(), ss[1].str() };
}

static int CompileShader(unsigned int type, const std::string& Source)
{
unsigned int id = glCreateShader(type);
const char* src = Source.c_str();
glShaderSource(id, 1, &src, nullptr);
glCompileShader(id);

int result;
glGetShaderiv(id, GL_COMPILE_STATUS, &result);

if (result == GL_FALSE)
{
    int length;
    glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);

    char* message = (char*)alloca(length * sizeof(char));
    glGetShaderInfoLog(id, length, &length, message);

    std::cout << message;

    return 0;
}

return id;
}

static unsigned int CreateShader(
const std::string& Vertexshader,
const std::string& Fragmentshader)
{
unsigned int program = glCreateProgram();
unsigned int vertex = CompileShader(GL_VERTEX_SHADER, Vertexshader);
unsigned int fragment = CompileShader(GL_FRAGMENT_SHADER, Fragmentshader);

glAttachShader(program, vertex);
glAttachShader(program, fragment);

glLinkProgram(program);
glValidateProgram(program);

return program;
}

int main(void)
{
GLFWwindow* window;

/* Initialize the library */
if (!glfwInit())
    return -1;

glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);






/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(800, 800, "Hello World", NULL, NULL);
if (!window)
{
    glfwTerminate();
    return -1;
}

/* Make the window's context current */
glfwMakeContextCurrent(window);

if (GLEW_OK == glewInit())
{
}

float vertices[] = { -0.1, -0.1,
                      0.1, -0.1, 
                      0.1, 0.1, 
                     -0.1, 0.1 };



float vertices2[] = { -0.1,0.1,
                      0.1, 0.1,
                      0.1, 0.3,
                     -0.1, 0.3 };


unsigned int indices[] = {

    0, 1, 2,
    2, 3, 0


};

unsigned int vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);

unsigned int vao2;
glGenVertexArrays(1, &vao2);
glBindVertexArray(vao2);


unsigned int buffer1;

unsigned int vbo;

glGenBuffers(1, &buffer1);
glBindBuffer(GL_ARRAY_BUFFER, buffer1);
glBufferData(GL_ARRAY_BUFFER, 4 * 2 * sizeof(float), vertices, GL_STATIC_DRAW);

glEnableVertexAttribArray(0);

glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);

glEnableVertexAttribArray(1);

glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);



glGenBuffers(1, &vbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(unsigned int), indices, GL_STATIC_DRAW);





Shaderprogramsource source = Parseshader("res/shaders/Basic.Shader");

unsigned int shader =
    CreateShader(source.VertexSouce, source.FragmentSource);




glUseProgram(shader);


int location = glGetUniformLocation(shader, "Color_u");
if (location > -1) {
    glUniform4f(location, 0.8f, 0.0f, 0.0f, 1.0f);

}



std::cout << source.VertexSouce;

glUseProgram(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
    /* Render here */

    glClear(GL_COLOR_BUFFER_BIT);

    glUseProgram(shader);
    glBindBuffer(GL_ARRAY_BUFFER, vao);
    glBindBuffer(GL_ARRAY_BUFFER, vao2);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo);


    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);

    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);

    glEnableVertexAttribArray(0);

    glEnableVertexAttribArray(1);

    glUseProgram(shader);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);

    /* Swap front and back buffers */
    glfwSwapBuffers(window);

    /* Poll for and process events */
    glfwPollEvents();
}

glDeleteProgram(shader);

glfwTerminate();
return 0;
}

Shaders:

#shader vertex
#version 330 core

layout(location = 0) in vec3 position;



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

#shader fragment
#version 330 core

layout(location = 0) out vec4 color;

uniform vec4 Color_u;

void main()
{
color = Color_u;
};

Solution

  • All sorts of wonk-a-donk:

    • Parseshader() is broken if the first line starts with anything other than the magic #shader directive, since NONE is set to 5 and the ss[(int)type] index + assignment will walk right off the end of the 3-element ss array. Drop NONE down to 2.
    • You only have a single vertex attribute in your shader (0) yet you're trying to set up 1.
    • That's not how VAOs work at all. A VAO has never been a valid argument to glBindBuffer(). Intead, bind a VAO & then set up your vertex attribute bindings/layouts:

      unsigned int vao1 = 0;
      glGenVertexArrays(1, &vao1);
      glBindVertexArray(vao1);
      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
      glBindBuffer(GL_ARRAY_BUFFER, buffer1);
      glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);
      glEnableVertexAttribArray(0);
      

      Then later when you want to draw you can re-bind the VAO and immediately draw, skipping all the glBindBuffer()/glVertexAttribPointer()/glEnableVertexAttribArray() setup.

    All together:

    screenshot

    // g++ -g main.cpp `pkg-config --cflags --libs glfw3 glew`
    #include <GL/glew.h>
    #include <GLFW/glfw3.h>
    #include <iostream>
    #include <sstream>
    #include <string>
    
    const char* const shaderSource = R"GLSL(
    #shader vertex
    #version 330 core
    layout(location = 0) in vec3 position;
    void main()
    {
        gl_Position = vec4(position.x, position.y, position.z, 1.0);
    };
    
    #shader fragment
    #version 330 core
    layout(location = 0) out vec4 color;
    uniform vec4 Color_u;
    void main()
    {
        color = Color_u;
    };
    )GLSL";
    
    struct Shaderprogramsource
    {
        std::string VertexSouce;
        std::string FragmentSource;
    };
    
    static Shaderprogramsource Parseshader(const std::string& shaderString)
    {
        std::stringstream stream( shaderString );
    
        enum class Shadertype
        {
            VERTEX = 0,
            FRAGMENT = 1,
            NONE = 2
        };
    
        std::string line;
        std::stringstream ss[3];
    
        Shadertype type = Shadertype::NONE;
    
        while( std::getline(stream, line) )
        {
            if (line.find("#shader") != std::string::npos)
            {
                if (line.find("vertex") != std::string::npos)
                    type = Shadertype::VERTEX;
    
                else if (line.find("fragment") != std::string::npos)
                    type = Shadertype::FRAGMENT;
            }
            else
            {
                ss[(int)type] << line << '\n';
            }
        }
    
        return Shaderprogramsource{ ss[0].str(), ss[1].str() };
        }
    
    static int CompileShader(unsigned int type, const std::string& Source)
    {
        unsigned int id = glCreateShader(type);
        const char* src = Source.c_str();
        glShaderSource(id, 1, &src, nullptr);
        glCompileShader(id);
    
        int result;
        glGetShaderiv(id, GL_COMPILE_STATUS, &result);
    
        if (result == GL_FALSE)
        {
            int length;
            glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);
    
            char* message = (char*)alloca(length * sizeof(char));
            glGetShaderInfoLog(id, length, &length, message);
    
            std::cout << message;
    
            return 0;
        }
    
        return id;
    }
    
    static unsigned int CreateShader( const std::string& Vertexshader, const std::string& Fragmentshader )
    {
        unsigned int program = glCreateProgram();
        unsigned int vertex = CompileShader(GL_VERTEX_SHADER, Vertexshader);
        unsigned int fragment = CompileShader(GL_FRAGMENT_SHADER, Fragmentshader);
    
        glAttachShader(program, vertex);
        glAttachShader(program, fragment);
    
        glLinkProgram(program);
        glValidateProgram(program);
    
        return program;
    }
    
    int main( int argc, char** argv )
    {
        if (!glfwInit())
            return -1;
    
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
        GLFWwindow* window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
        if (!window)
        {
            glfwTerminate();
            return -1;
        }
    
        /* Make the window's context current */
        glfwMakeContextCurrent(window);
    
        if (GLEW_OK == glewInit())
        {
        }
    
        unsigned int buffer1;
        glGenBuffers(1, &buffer1);
        glBindBuffer(GL_ARRAY_BUFFER, buffer1);
        float vertices1[] =
        {
            -0.1, -0.1,
            0.1, -0.1, 
            0.1, 0.1, 
            -0.1, 0.1,
        };
        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices1), vertices1, GL_STATIC_DRAW);
    
        unsigned int buffer2;
        glGenBuffers(1, &buffer2);
        glBindBuffer(GL_ARRAY_BUFFER, buffer2);
        float vertices2[] =
        {
            -0.1, 0.1,
            0.1, 0.1,
            0.1, 0.3,
            -0.1, 0.3,
        };
        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices2), vertices2, GL_STATIC_DRAW);
    
        unsigned int ebo;
        glGenBuffers(1, &ebo);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
        unsigned int indices[] =
        {
            0, 1, 2,
            2, 3, 0,
        };
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
    
        unsigned int vao1 = 0;
        glGenVertexArrays(1, &vao1);
        glBindVertexArray(vao1);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
        glBindBuffer(GL_ARRAY_BUFFER, buffer1);
        glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);
        glEnableVertexAttribArray(0);
    
        unsigned int vao2 = 0;
        glGenVertexArrays(1, &vao2);
        glBindVertexArray(vao2);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
        glBindBuffer(GL_ARRAY_BUFFER, buffer2);
        glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);
        glEnableVertexAttribArray(0);
    
        Shaderprogramsource source = Parseshader( shaderSource );
        unsigned int shader = CreateShader(source.VertexSouce, source.FragmentSource);
        glUseProgram(shader);
        int location = glGetUniformLocation(shader, "Color_u");
    
        /* Loop until the user closes the window */
        while (!glfwWindowShouldClose(window))
        {
            glfwPollEvents();
    
            glClear(GL_COLOR_BUFFER_BIT);
    
            glUseProgram(shader);
    
            if (location > -1)
            {
                glUniform4f(location, 0.8f, 0.0f, 0.0f, 1.0f);
            }
            glBindVertexArray(vao1);
            glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
    
            if (location > -1)
            {
                glUniform4f(location, 0.0f, 0.8f, 0.0f, 1.0f);
            }
            glBindVertexArray(vao2);
            glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
    
            glfwSwapBuffers(window);
        }
    
        glDeleteProgram(shader);
    
        glfwTerminate();
        return 0;
    }