无法使用 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);
我正在尝试编辑 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);