Попытка нарисовать облако точек, просто одну точку в центре в OpenGL - PullRequest
1 голос
/ 12 октября 2019

Попытка создать случайное облако точек в 2D. Тем не менее, я получил это в конце: цвет фона + 1 единичная «серая» точка в центре. Что могло пойти не так?

  • Я пытаюсь написать свой собственный простой шейдер.
  • Пытаюсь скомпилировать шейдер самостоятельно.
  • Все должны быть шагами ребенка.
  • Также, каковы некоторые советы по устранению этих проблем?
#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

Редактировать:

Я редактировал код, все еще дает тот же результат.

#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;
}

1 Ответ

1 голос
/ 12 октября 2019

Вершинный шейдер даже не компилируется. ; отсутствует после out vec4 particle_color, тип возврата main должен быть void, а в конце gl_Position = mvp*vec4(pos, 0.0,1.0)); есть один ) для многих.

Рекомендуюиспользуйте необработанный строковый литерал :

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);
}
)";

Поскольку вы используете базовый профиль Context , вы должны использовать Vertex Array Object . Например:

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 );

Вы имеете ортографическую проекцию от (0, 0) до (600, 800), поэтому матрица вида должна быть

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)
);

Примечание, с вашей матрицей вида точки нарисованы слева от окна просмотра, поэтому вы не можете их видеть. Точка будет нарисована в прямоугольнике от (0, 0) до (-800, 600).


Изменение цвета точек в фрагментном шейдере. Красный цвет вряд ли можно увидеть на зеленом фоне:

const char *FragmentShaderSource = R"(
#version 330 core
out vec4 color;

void main(){
    color =  vec4(1.0f);
}
)";

Я рекомендую проверить, удалось ли скомпилировать шейдер по glGetShaderiv. Например:

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;
}

и программе удалось установить связь по glGetProgramiv. Например:

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;
}
...