Search code examples
c++algorithmopenglglfwglm-math

Trying to Draw a point cloud, just a single point in the center in opengl


Trying to create a random point cloud in 2D. However, I've got this in the end for now : The background color + 1 single 'grey' point in the center. What might have gone wrong here?

  • I try writing my own simple shader.
  • Trying to compile shader by myself.
  • All are supposed to be baby steps.
  • Also what would be some tips of debugging these issues?
#include <vector>
#include <algorithm>
#include <iostream>

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

GLFWwindow* window;

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/norm.hpp>

/* SHADERS */

/* Vertex Shader */
const char *VertexShaderSource="#version 330 core\n"
"layout(location=0) in vec2 pos;\n"
"//layout(location=1) in vec2 da;//distance and angle \n"
"//layout(location=2) in vec4 color;\n"
"\n"
"out vec4 particle_color\n"
"uniform mat4 mvp;\n"
"int main(){\n"
"gl_Position = mvp*vec4(pos, 0.0,1.0));\n"
"//particle_color =;\n"
"}\n";
/* Fragment Shader*/
const char *FragmentShaderSource="#version 330 core\n"
"//in vec4 particle_color;\n"
"out vec4 color;\n"
"//layout(location=2) in vec4 color;\n"
"void main(){\n"
"color =  vec4(1.0f,0.0f,0.0f,1.0f);\n"
"}\n";
/* SHADERS END */



// Particle
struct Point{
    glm::vec2 pos;
    // Create random color in GPU
    // unsigned char r,g,b,a;
    float distance;
    float angle;
};
static const int max_point_number=1000;
Point PointContainer[max_point_number];

int main()
{
    // Start GLFW
    if(!glfwInit())
    {
        std::cout<<"Failed to start GLWF\n";
        getchar();
        return -1;
    }   

    glfwWindowHint(GLFW_SAMPLES, 4);
    //glfwWindowHint(GLFW_RESIZABLE,GL,FALSE);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR,3);
    glfwWindowHint(GLFW_OPENGL_PROFILE,GLFW_OPENGL_CORE_PROFILE);
    window = glfwCreateWindow(800, 600, "Rotating Points", NULL, NULL);
    if(window == NULL)
    {
        std::cout<<"Initialization of the window failed\n";
        getchar();
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);

    // Start GLEW;
    glewExperimental = true;
    if(glewInit() != GLEW_OK)
    {
        std::cout<<"Failed to start GLEW\n";
        getchar();
        return -1;
    }

    glfwPollEvents();

    glClearColor(.0f,0.5f,0.5f,0.0f); // Black is the new orange


    // Camera
    glm::mat4 Projection = glm::ortho(0.0f,800.0f, 0.0f,600.0f,-5.0f,5.0f); // In world coordinates
    glm::mat4 View = glm::lookAt(
    glm::vec3(0,0,-1), // Camera is at (0,0,-1), in World Space
    glm::vec3(0,0,0), // and looks at the origin
    glm::vec3(0,1,0)  // Head is up (set to 0,-1,0 to look upside-down)
    );
    glm::mat4 Model = glm::mat4(1.0f);
    glm::mat4 mvp = Projection * View * Model; // Remember, matrix multiplication is the other way around
    // No need to have depth test

    GLuint VertexArrayID;
    glGenVertexArrays(1, &VertexArrayID);
    glBindVertexArray(VertexArrayID);

    // Build and compile shaders
    // Vertex Shader
    int vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &VertexShaderSource, NULL);
    glCompileShader(vertexShader);
    // Fragment Shader
    int fragmentShader=glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &FragmentShaderSource, NULL);
    glCompileShader(fragmentShader);
    // Link Shaders
    int shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);
    glUseProgram(shaderProgram);
    // Delete Shaders after Linking
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    for(auto &p:PointContainer)
    {
        p.pos.x =rand() % 800;
        p.pos.y =rand() % 600;
        std::cout<<p.pos.x<<" "<<p.pos.y<<"\n";
    }
    // Vertex Shader
    GLuint tPM = glGetUniformLocation(shaderProgram, "mvp");//mvp
    glUniformMatrix4fv(tPM, 1, GL_FALSE, &mvp[0][0]);


    GLuint pointsVertexBuffer;
    glGenBuffers(1, &pointsVertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, pointsVertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(PointContainer), PointContainer, GL_STREAM_DRAW); // Start with NULL, update with frames;
    do
    {
        // Clear the screen
        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );   
        //glDrawArraysInstanced(GL_POINTS, 0, 2, max_point_number);
        glBindBuffer( GL_ARRAY_BUFFER, pointsVertexBuffer );
        glEnableClientState( GL_VERTEX_ARRAY );
        //glEnableClientState( GL_COLOR_ARRAY );
        glVertexPointer( 4, GL_FLOAT, sizeof( Point ), (void*)offsetof( Point, pos ) );
        //glColorPointer( 4, GL_FLOAT, sizeof( Vertex ), (void*)offsetof( Vertex, color ) );
        glDrawArrays( GL_POINTS, 0, max_point_number);
        glDisableClientState( GL_VERTEX_ARRAY );
        //glDisableClientState( GL_COLOR_ARRAY );
        glBindBuffer( GL_ARRAY_BUFFER, 0 );     // Swap buffers

        glfwSwapBuffers(window);
        glfwPollEvents();

    } // Check if the ESC key was pressed or the window was closed
    while( glfwWindowShouldClose(window) == 0 );
    return 0;
}

enter image description here

Edit:

I edited the code, still gives the same result.

#include <vector>
#include <algorithm>
#include <iostream>`

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

GLFWwindow* window;

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/norm.hpp>

/* SHADERS */

/* Vertex Shader */
const char *VertexShaderSource=R"(
#version 330 core
layout(location=0) in vec2 pos;

uniform mat4 mvp;

int main(){
gl_Position = mvp*vec4(pos, 0.0,1.0);
}
)";
/* Fragment Shader*/
const char *FragmentShaderSource = R"(
#version 330 core
out vec4 color;

void main(){
    color =  vec4(1.0f);
}
)";
/* SHADERS END */

// Particle
struct Point{
    glm::vec2 pos;
    // Create random color in GPU
    // unsigned char r,g,b,a;
    float distance;
    float angle;
};
static const int max_point_number=1000;
Point PointContainer[max_point_number];

int main()
{
    // Start GLFW
    if(!glfwInit())
    {
        std::cout<<"Failed to start GLWF\n";
        getchar();
        return -1;
    }   

    glfwWindowHint(GLFW_SAMPLES, 4);
    //glfwWindowHint(GLFW_RESIZABLE,GL,FALSE);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR,3);
    glfwWindowHint(GLFW_OPENGL_PROFILE,GLFW_OPENGL_CORE_PROFILE);
    window = glfwCreateWindow(800, 600, "Rotating Points", NULL, NULL);
    if(window == NULL)
    {
        std::cout<<"Initialization of the window failed\n";
        getchar();
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);

    // Start GLEW;
    glewExperimental = true;
    if(glewInit() != GLEW_OK)
    {
        std::cout<<"Failed to start GLEW\n";
        getchar();
        return -1;
    }

    glfwPollEvents();

    glClearColor(.0f,0.0f,0.0f,0.0f); // Black is the new orange


    // Camera
    glm::mat4 Projection = glm::ortho(0.0f,800.0f, 0.0f,600.0f,-5.0f,5.0f); // In world coordinates
    glm::mat4 View = glm::lookAt(
    glm::vec3(0,0,1), // Camera is at (0,0,-1), in World Space
    glm::vec3(0,0,0), // and looks at the origin
    glm::vec3(0,1,0)  // Head is up (set to 0,-1,0 to look upside-down)
    );
    glm::mat4 Model = glm::mat4(1.0f);
    glm::mat4 mvp = Projection * View * Model; // Remember, matrix multiplication is the other way around
    // No need to have depth test

    GLuint VertexArrayID;
    glGenVertexArrays(1, &VertexArrayID);
    glBindVertexArray(VertexArrayID);

    // Build and compile shaders
    // Vertex Shader
    int vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &VertexShaderSource, NULL);
    glCompileShader(vertexShader);
    // Fragment Shader
    int fragmentShader=glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &FragmentShaderSource, NULL);
    glCompileShader(fragmentShader);
    // Link Shaders
    int shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);
    glUseProgram(shaderProgram);
    // Delete Shaders after Linking
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    for(auto &p:PointContainer)
    {
        p.pos.x =(rand() % 800)*-1;
        p.pos.y =rand() % 600;
        std::cout<<p.pos.x<<" "<<p.pos.y<<"\n";
    }
    // Vertex Shader
    GLuint tPM = glGetUniformLocation(shaderProgram, "mvp");//mvp
    glUniformMatrix4fv(tPM, 1, GL_FALSE, &mvp[0][0]);


    GLuint pointsVertexBuffer;
    glGenBuffers(1, &pointsVertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, pointsVertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(PointContainer), PointContainer, GL_STREAM_DRAW); // Start with NULL, update with frames;

    GLuint vao;
    glGenVertexArrays( 1, &vao );
    glBindVertexArray( vao );
    glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, 4*sizeof(float), 0 );
    glEnableVertexAttribArray( 0 );

    do
    {
        // Clear the screen
        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );   

        glDrawArrays( GL_POINTS, 0, max_point_number);


        glfwSwapBuffers(window);
        glfwPollEvents();

    } // Check if the ESC key was pressed or the window was closed
    while( glfwWindowShouldClose(window) == 0 );
        return 0;
}

Solution

  • The vertex shader doesn't even compile. A ;is missing affter out vec4 particle_color, the return type of main has to be void and at the end of gl_Position = mvp*vec4(pos, 0.0,1.0)); there is one ) to many.

    I recommend to use a Raw string literal:

    const char *VertexShaderSource = R"(
    #version 330 core
    layout(location=0) in vec2 pos;
    uniform mat4 mvp;
    
    void main(){
        gl_Position = mvp*vec4(pos, 0.0,1.0);
    }
    )";
    

    Since you use a core profile Context you've to use a Vertex Array Object. e.g.:

    GLuint pointsVertexBuffer;
    glGenBuffers(1, &pointsVertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, pointsVertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(PointContainer), PointContainer, GL_STREAM_DRAW); // Start with NULL, update with frames;
    
    GLuint vao;
    glGenVertexArrays( 1, &vao );
    glBindVertexArray( vao );
    glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, 4*sizeof(float), 0 );
    glEnableVertexAttribArray( 0 );
    
    do
    {
        // Clear the screen
        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );   
    
        glDrawArrays( GL_POINTS, 0, max_point_number);
    
    
        glfwSwapBuffers(window);
        glfwPollEvents();
    
    } // Check if the ESC key was pressed or the window was closed
    while( glfwWindowShouldClose(window) == 0 );
    

    You've an orthographic projection from (0, 0) to (600, 800), so the view matrix has to be

    glm::mat4 View = glm::lookAt(
        glm::vec3(0,0,1), // Camera is at (0,0,-1), in World Space
        glm::vec3(0,0,0), // and looks at the origin
        glm::vec3(0,1,0)  // Head is up (set to 0,-1,0 to look upside-down)
    );
    

    Note, with your view matrix the points are drawn at the left of the viewport, so you can't see them. The point would be drawn in in the rectangle from (0, 0) to (-800, 600).


    Change the color of the points in the fragment shader. The red color is hardly to see on the green ground:

    const char *FragmentShaderSource = R"(
    #version 330 core
    out vec4 color;
    
    void main(){
        color =  vec4(1.0f);
    }
    )";
    

    I recommend to verify if the shader succeeded to compile by glGetShaderiv. e.g.:

    glGetShaderiv( vertexShader, GL_COMPILE_STATUS, &status );
    if ( status == GL_FALSE )
    {
        GLint logLen;
        glGetShaderiv( vertexShader, GL_INFO_LOG_LENGTH, &logLen );
        std::vector< char >log( logLen );
        GLsizei written;
        glGetShaderInfoLog( vertexShader, logLen, &written, log.data() );
        std::cout << "compile error:" << std::endl << log.data() << std::endl;
    }
    

    and the program succeeded to link by glGetProgramiv. e.g.:

    glGetProgramiv( shaderProgram, GL_LINK_STATUS, &status );
    if ( status == GL_FALSE )
    {
        GLint logLen;
        glGetProgramiv( shaderProgram, GL_INFO_LOG_LENGTH, &logLen );
        std::vector< char >log( logLen );
        GLsizei written;
        glGetProgramInfoLog( shaderProgram, logLen, &written, log.data() );
        std::cout  << "link error:" << std::endl << log.data() << std::endl;
    }