Home > Enterprise >  Why is my OpenGL code producing a black screen?
Why is my OpenGL code producing a black screen?

Time:10-25

This is my code written in C that is supposed to produce 2 triangles, however I am getting a blank screen. Is there something I am missing?

#include <GL/glew.h>
#include <GLFW/glfw3.h>

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>

#include <glm/vec3.hpp> // glm::vec3
#include <glm/vec4.hpp> // glm::vec4
#include <glm/mat4x4.hpp> // glm::mat4
#include <glm/gtc/matrix_transform.hpp> // glm::translate, glm::rotate, glm::scale, glm::perspective

using namespace std;

static string ParseShader(string filepath) {
    ifstream stream(filepath);
    string line;
    stringstream stringStream;

    while (getline(stream, line))
    {
        stringStream << line << '\n';
    }

    return stringStream.str();
}

static unsigned int CompileShader(unsigned int type, const string& source) {
    unsigned int id = glCreateShader(type);
    const char* src = source.c_str(); // this returns a pointer to data inside the string, the first character
    glShaderSource(id, 1, &src, nullptr); // shader id, count of source codes, a pointer to the array that holds the strings
    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);
        cout << type << endl;
        cout << message << endl;
        glDeleteShader(id);
        return 0;
    }
    return id;
}

// takes the shader codes as a string parameters 
static unsigned int CreateShader(const string& vertexShader, const string& fragmentShader)
{
    GLuint program = glCreateProgram();
    unsigned int vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
    unsigned int fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);


    glAttachShader(program, vs);
    glAttachShader(program, fs);
    glLinkProgram(program);
    glValidateProgram(program); // validate if the program is valid and can be run in the current state of opengl

    glDeleteShader(vs);
    glDeleteShader(fs);

    return program;
}

int main(void)
{
    GLFWwindow* window;

    float Angle = 0;

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

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

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

    // call glewInit after creating the context...
    GLenum err = glewInit();
    if (GLEW_OK != err)
    {
        /* Problem: glewInit failed, something is seriously wrong. */
        fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
    }


    GLfloat coordinates[12] = {
        -0.5f,  0.5f,
         0.0f,  0.5f, 
         0.5f,  0.5f, 

        -0.5f,  -0.5f,
         0.0f,  -0.5f,
         0.5f,  -0.5f
    };

    GLuint indices[6] = { 0, 3, 1, 4, 2, 5 };

    GLuint position_buffer;
    glGenBuffers(1, &position_buffer);
    glBindBuffer(GL_ARRAY_BUFFER, position_buffer);
    glBufferData(GL_ARRAY_BUFFER, 6 * 2 * sizeof(float), coordinates, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0); //vertex positions
    glEnableVertexAttribArray(0);


    GLuint index_buffer;
    glGenBuffers(1, &index_buffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(GLuint), indices, GL_STATIC_DRAW);


    string vertexSource = ParseShader("vertex.shader");
    string fragmentSource = ParseShader("fragment.shader");

    unsigned int program = CreateShader(vertexSource, fragmentSource);
    glUseProgram(program);

    /* Loop until the user closes the window */
    while (!glfwWindowShouldClose(window))
    {
        // Render here 
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glDrawElements(GL_TRIANGLE_STRIP, 6, GL_UNSIGNED_INT, nullptr);

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

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

    glDeleteProgram(program);

    glfwTerminate();
    return 0;
}

This is my vertex shader.

#version 330 core 

layout(location = 0) in vec4 position;
layout(location = 1) in vec4 color;

out vec4 var_color;

void main()
{
    var_color = color;
    gl_Position =  position;
};

And here is my fragment shader.

#version 330 core 

out vec4 color;
in vec4 var_color;


void main()
{
    //color = vec4(1.0f, 0.0f, 0.0f, 1.0f);
    color = var_color;
    //discard;
};

I get a black screen as a result, I doubt this is an issue with my machine as other code snippets worked on it.

CodePudding user response:

Colors are not specified in the provided code. The shader are most probably drawing black squares because of the value already in memory when you execute the program. To add colors, use this code:

GLfloat colors[24] = { // Random colors
    1.0f,  1.0f, 1.0f, 1.0f,
    1.0f,  0.0f, 1.0f, 1.0f,
    1.0f,  1.0f, 0.0f, 1.0f,
    0.0f,  1.0f, 0.0f, 1.0f,
    1.0f,  1.0f, 1.0f, 1.0f,
    0.0f,  0.0f, 1.0f, 1.0f,
};

GLuint color_buffer;
glGenBuffers(1, &color_buffer);
glBindBuffer(GL_ARRAY_BUFFER, color_buffer);
glBufferData(GL_ARRAY_BUFFER, 6 * 4 * sizeof(float), colors, GL_STATIC_DRAW);

glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 4, 0); //vertex colors
glEnableVertexAttribArray(1);

CodePudding user response:

The code shouldn't produce two triangles, as it is asked to render a triangle strip. The first three vertices define one triangle and each subsequent vertex adds another triangle for a total of 4 triangles.

The blank screen you're getting is the result of the vertex shader being sent 2D positions and interpreting them as 4D positions, as well as no color information being present.

To resolve these issues:

  1. The vertex shader should receive a vec2 for the positions, since these are given in 2D:

    layout(location = 0) in vec2 position;
    

    Then convert these to 4D for gl_Position:

    gl_Position = vec4(position, 0.0f, 1.0f);
    
  2. The definition of the colors, setting up the corresponding buffer and uploading of the color data was missing. For example, add:

    GLfloat colors[24] = {
         1.0f,  0.0f, 0.0f, 1.0f,
         0.0f,  1.0f, 0.0f, 1.0f,
         0.0f,  0.0f, 1.0f, 1.0f,
         1.0f,  1.0f, 0.0f, 1.0f,
         0.0f,  1.0f, 1.0f, 1.0f,
         1.0f,  1.0f, 1.0f, 1.0f,
    };
    
    GLuint color_buffer;
    glGenBuffers(1, &color_buffer);
    glBindBuffer(GL_ARRAY_BUFFER, color_buffer);
    glBufferData(GL_ARRAY_BUFFER, 6 * 4 * sizeof(float), colors, GL_STATIC_DRAW);
    
    glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 4, 0);
    glEnableVertexAttribArray(1);
    

The result:

corresponding_output

  • Related