无法使用 FBO 绘制多个元素

Unable to plot multiple elements using FBO

我正在尝试编辑 this tutorial so to render multiple circles within the FBO. I simplified the tutorial so to save memory that I'm sending through the FBO: I'm only sending the x and y coordinates, alongside with a float that will determine the colour of the node. This information is read from this 文本文件。即使我试图绘制 ~660 个节点,我的代码也不会显示所有节点。我的应用程序应该按比例放大并可能绘制输入中读取的任何可能大小的节点。

我提供了一个图形说明,说明我希望通过 R 中的绘图获得什么:

library(ggplot2)
t <-read.table("pastebin_file.txt", header = T)
ggplot(t, aes(x, y)) + geom_point(aes(colour = factor(col)))

在 OpenGL 中,我得到的顶点数量较少(我知道,颜色是颠倒的,但这不是我关心的问题):

我猜可能是VBO的问题,或者我忘记正确设置所有参数。在这个阶段,我不知道问题是什么。我该如何解决这个问题以便在 OpenGL 上复制 R 的输出?我在问题的最后部分提供了一个包含所有着色器的 MWE:

main.cpp

#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include <GL/glut.h>
#include "utils/shaders.h"


size_t n = 0;
void render(void)
{
    // Clear the screen to black
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    // I want to render exactly all the vertices that were loaded on the VBO.
    glDrawArrays(GL_POINTS, 0, n); 
    glutSwapBuffers();  // Update the rendering
}

program programma;

void set_shader()
{
    // Loading the shaders using a custom class. Nevertheless, the code is exactly the same as the one in https://open.gl/content/code/c7_final.txt, that is loading and compiling the three shaders, and then linking them together in one single program
    programma.add_shader(shader_t::vertex,   "shaders/vertexShader3.txt");
    programma.add_shader(shader_t::fragment, "shaders/fragmentShader3.txt");
    programma.add_shader(shader_t::geometry, "shaders/geometryShader3.txt");
    programma.compile();
}


GLuint vbo;
GLuint vao;

#include <regex>
#include <iostream>

size_t fbo(const std::string& filename) {
    // Create VBO with point coordinates
    glGenBuffers(1, &vbo);
    std::fstream name{filename};
    std::string line;
    std::getline(name, line); // Skipping the first line, that just contains the header
    std::vector<GLfloat> points; // Storage for all the coordinates
    n = 0;

    std::regex rgx ("\s+");
    while (std::getline(name, line)) {
        std::sregex_token_iterator iter(line.begin(), line.end(), rgx, -1);
        std::sregex_token_iterator end;
        points.emplace_back(std::stof(*iter++)/20); // x, rescaled, so it can fit into screen
        points.emplace_back(std::stof(*iter++)/20); // y, rescaled, so it can fit into screen
        int i = std::stoi(*iter++);
        points.emplace_back(i);                         // determining the color
        n++;
    }
    std::cout << n << std::endl;                        // number of vertices
    std::cout << sizeof(float) * 3 * n << std::endl;    // expected size in B = 7992

    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, points.size(), points.data(), GL_STATIC_DRAW);

    // Create VAO
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);

    // Specify the layout of the node data: just two floats for the (x,y) pairs
    GLint posAttrib = glGetAttribLocation(programma.id, "pos");
    glEnableVertexAttribArray(posAttrib);
    glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 0);

    // Determining the color of the circle with one single float parameter
    GLint sidesAttrib = glGetAttribLocation(programma.id, "sides");
    glEnableVertexAttribArray(sidesAttrib);
    glVertexAttribPointer(sidesAttrib, 1, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (void*) (2 * sizeof(GLfloat)));

    return points.size()/3;
}



int main(int argc, char **argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
    glutInitWindowSize(200, 200);
    glutCreateWindow("Stuff");
    glutIdleFunc(render);

    glewInit();
    if (!glewIsSupported("GL_VERSION_2_0")) {
        fprintf(stderr, "GL 2.0 unsupported\n");
        return 1;
    }

    set_shader();
    fbo("pastebin_file.txt");
    glutMainLoop();
    glDeleteBuffers(1, &vbo);
    glDeleteVertexArrays(1, &vao);

    return 0;
}
#endif

shaders/vertexShader3.txt

#version 150 core

in vec2 pos;     // input vertex position
in float sides;  // determines the output color
out vec3 vColor;

void main() {
        gl_Position = vec4(pos, 0.0, 1.0);
        if (sides == 1.0) { // determining the color
            vColor = vec3(1.0,0.0,0.0);
        } else {
            vColor = vec3(0.0,1.0,0.0);
        }
}

shaders/geometryShader3.txt

#version 150 core

layout(points) in;
layout(line_strip, max_vertices = 640) out;

in vec3 vColor[];
out vec3 fColor;

const float PI = 3.1415926;
const float lati = 10;

void main() {
        fColor = vColor[0];

        // Safe, GLfloats can represent small integers exactly
        for (int i = 0; i <= lati; i++) {
            // Angle between each side in radians
            float ang = PI * 2.0 / lati * i;

            // Offset from center of point
            vec4 offset = vec4(cos(ang) * 0.3/20, -sin(ang) * 0.4/20, 0.0, 0.0);
            gl_Position = gl_in[0].gl_Position + offset;

            EmitVertex();

        }

        EndPrimitive();
}

shaders/fragmentShader3.txt

#version 150 core
in vec3 fColor;
out vec4 outColor;

void main() {
        outColor = vec4(fColor, 1.0); // Simply returning the color
}

glBufferData 的第二个参数必须是以 字节为单位的缓冲区大小:

glBufferData(GL_ARRAY_BUFFER, points.size(), points.data(), GL_STATIC_DRAW);

glBufferData(GL_ARRAY_BUFFER, 
    points.size() * sizeof(points[0]), points.data(), GL_STATIC_DRAW);