Search code examples
c++openglglutglew

Different fragment shader colors


I want to draw different figures with different colors using shaders.

I tried using uniform variables and using vertex attributes of the meshes to separate Vertex Buffer Objects but when I run the program only the second color is used and the first figure isn't shown at all. Im not sure if it's an issue with how I bind the shaders or with the way I use uniform variables. Thanks in advance.

Here is the code:

#include <GL/glew.h>
#include <GL/glut.h>
#include <stdio.h>

const char* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
"   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";

const char* fragmentShaderSource = "#version 330 core\n"
"in vec4 color;\n"
"out vec4 FragColor;\n"
"uniform vec3 figColor;\n"
"void main()\n"
"{\n"
"   FragColor = vec4(figColor, 0.0f);\n"
"}\n\0";

// Set of vertices that draw the different figures:
float vertices1[] = { 
    -0.8f, 0.6f, 0.0f, 
    -0.8f, 0.4f, 0.0f,
    -0.83f, 0.44f, 0.0f,
    -0.87f, 0.51f, 0.0f,
    -0.9f, 0.57f, 0.0f,
    -0.93f, 0.63f, 0.0f,
    -0.95f, 0.69f, 0.0f,
    -0.97f, 0.75f, 0.0f,
    -0.98f, 0.8f, 0.0f,
    -0.91f, 0.8f, 0.0f,
    -0.85f, 0.79f, 0.0f,
    -0.8f, 0.77f, 0.0f,
};

float vertices2[] = {
    -0.8f, -0.15f, 0.0f, 
    -1.0f, 0.0f, 0.0f,
    -0.95f, 0.0f, 0.0f,
    -0.86f, -0.01f, 0.0f,
    -0.81f, -0.02f, 0.0f,
    -0.75f, -0.03f, 0.0f,
};

GLuint vertexShader;
GLuint fragmentShader;
GLuint shaderProgram;

void display(void) {
    // Background color.
    glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    glUseProgram(shaderProgram);
    GLint uniform = glGetUniformLocation(shaderProgram, "figColor");
    glUniform3f(uniform, 1.0f, 0.0f, 0.0f);
    glDrawArrays(GL_TRIANGLE_FAN, 0, 12);
    glUniform3f(uniform, 0.0f, 0.749f, 1.0f);
    glDrawArrays(GL_TRIANGLE_FAN, 0, 6);
    glUseProgram(0);

    glFlush();
}

// Main.
int main(int argc, char** argv) {
    glutInit(&argc, argv);
    // Color mode.
    glutInitDisplayMode(GLUT_RGBA);
    // Window size.
    glutInitWindowSize(500, 500);
    // Title.
    glutCreateWindow("Tarea 3: Figura con curvas");
    GLenum err = glewInit();
    if (err != GLEW_OK) {
        printf("glewInit failed: %s", glewGetErrorString(err));
        exit(1);
    }

    // Compile vertex shader.
    vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
    glCompileShader(vertexShader);

    // Check for vertex shader compilation errors.   
    int success;
    char infoLog[512];
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if (!success) {
        glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
        printf("ERROR::SHADER::VERTEX::COMPILATION_FAILED\n");
    }

    // Compile fragment shader.
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
    glCompileShader(fragmentShader);

    // Check for fragment shader compile errors.  
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if (!success) {
        glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
        printf("ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n");
    }

    // Link and delete shaders.
    shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    //Separating the Vertex Buffer Objects.
    GLuint VBOs[2];
    glBindBuffer(GL_ARRAY_BUFFER, VBOs[0]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices1), vertices1, GL_STATIC_DRAW);

    glBindBuffer(GL_ARRAY_BUFFER, VBOs[1]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices2), vertices2, GL_STATIC_DRAW);

    // Specify a VertexArrayObject for each mesh.
    GLuint VAOs[2];
    glGenVertexArrays(2, VAOs);

    glBindVertexArray(VAOs[0]);
    glBindBuffer(GL_ARRAY_BUFFER, VBOs[0]);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    glBindVertexArray(VAOs[1]);
    glBindBuffer(GL_ARRAY_BUFFER, VBOs[1]);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    // Bind the VAO before the draw call.
    glBindVertexArray(VAOs[0]);
    glDrawArrays(GL_TRIANGLE_FAN, 0, 12);

    glBindVertexArray(VAOs[1]);
    glDrawArrays(GL_TRIANGLE_FAN, 0, 24);

    // Displaying the figures.
    glutDisplayFunc(display);
    glutMainLoop();
} 

Solution

  • You missed to generate the vertex buffer object names:

    //Separating the Vertex Buffer Objects.
    GLuint VBOs[2];
    glGenBuffers(2, VBOs); <----
    

    You have to bind the vertex array before drawing the mesh in the main loop:

    GLuint VAOs[2];
    
    void display(void) {
        // Background color.
        glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
        glClear(GL_COLOR_BUFFER_BIT);
        glUseProgram(shaderProgram);
        GLint uniform = glGetUniformLocation(shaderProgram, "figColor");
        
        glUniform3f(uniform, 1.0f, 0.0f, 0.0f);
        glBindVertexArray(VAOs[0]);                     // <---
        glDrawArrays(GL_TRIANGLE_FAN, 0, 12);
        
        glUniform3f(uniform, 0.0f, 0.749f, 1.0f);
        glBindVertexArray(VAOs[1]);                     // <----
        glDrawArrays(GL_TRIANGLE_FAN, 0, 6);
        glUseProgram(0);
    
        glFlush();
    }
    
    int main(int argc, char** argv) {
        // [...]
    
        // Specify a VertexArrayObject for each mesh.
        // GLuint VAOs[2]; <---- DELETE
        glGenVertexArrays(2, VAOs);
    
        // [...]
    
        // DELETE
        /*
        // Bind the VAO before the draw call.
        glBindVertexArray(VAOs[0]);
        glDrawArrays(GL_TRIANGLE_FAN, 0, 12);
    
        glBindVertexArray(VAOs[1]);
        glDrawArrays(GL_TRIANGLE_FAN, 0, 24);
        */
    
        // [...]