Hi
I am drawing a 3D point cloud in OpenGL4.5. running on Ubuntu Linux 23.04, code is C++.
I read in a file with the point cloud data in *.ply format. Please see my ply files here:
I am very new to OpenGL and trying to debug it. I just learnt today about RenderDoc for debugging. I captured a log but can’t yet figure out how to find anomalies related to the below error I describe. If it helps here’s the RenderDoc log capture: RenderDoc Log Capture
I am using glDrawElements() to draw the point cloud. The problem is that while I can successfully draw a point cloud with glDrawElements(GL_POINTS,…) (right hand side of below screenshot)…
I cannot draw (the screen is blank) when I use glDrawElements(GL_TRIANGLES,…) or glDrawElements(GL_TRIANGLE_STRIP,…).
I define one Vertex Array Object (VAO) and Vertex Buffer Object (VBO) which I set up with position(xyzw) data first, then color(rgba) data, then point size.
Here is the code to set up the VAO and VBO.
void setup_VAO_VBO(void)
{
// configure global opengl state
// -----------------------------
glEnable(GL_DEPTH_TEST);
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
// glEnable(GL_MULTISAMPLE); // enabled by default on some drivers, but not all so always enable to make sure
glDepthFunc(GL_LESS); // Accept fragment if it closer to the camera than the former one
glEnable(GL_PROGRAM_POINT_SIZE);
glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
//glEnable(GL_POINT_SPRITE);
//glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
//glEnable(GL_BLEND); // to recognise/implement a varying alpha value for r,g,b,alpha vertex colour attribute
//glBlendFunc(GL_SRC_ALPHA, GL_SRC_ALPHA);
//glFrontFace(GL_CW);
//glEnable(GL_CULL_FACE); // https://learnopengl.com/Advanced-OpenGL/Face-culling
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); //When drawing faces: draw wireframe rather than fill triangle with colour
// create a Vertex Array Object and set it as the current one.
// Do this once your window is created (= after the OpenGL Context creation) and before any other OpenGL call.
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glGenBuffers(1, &VBO1);
glBindBuffer(GL_ARRAY_BUFFER, VBO1);
// Allocate memory for both vertex_buffer_data1 and vertex_buffer_data2
glBufferData(GL_ARRAY_BUFFER,
vertex_buffer_data1.size() * sizeof(decltype(vertex_buffer_data1)::value_type),
&vertex_buffer_data1[0],
GL_STATIC_DRAW); // mem is allocated here for the buffer size specified
/*
glBufferSubData(GL_ARRAY_BUFFER,
0,
sizeof(decltype(vertex_buffer_data1)::value_type) * vertex_buffer_data1.size(),
&vertex_buffer_data1[0]);
*/
glBufferSubData(GL_ARRAY_BUFFER,
0,
sizeof(decltype(vertex_buffer_data2)::value_type) * vertex_buffer_data2.size(),
&vertex_buffer_data2[0]);
// Create an Element Buffer Object that will store the indices array:
glGenBuffers(1, &EBO);
// Transfer the data from indices to EBO
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
indices_buffer_data.size() * sizeof(unsigned int),
&indices_buffer_data[0],
GL_STATIC_DRAW);
// Attribute binding
glVertexAttribPointer(0, // attribute - must match the layout in the shader.
VERTEX_SIZE, // size = 3 for rgb, = 4 for rgba
GL_FLOAT, // vertex data type
GL_FALSE, // normalized?
0, // stride
(void *)0); // array buffer offset
glEnableVertexAttribArray(0);
//std::cout << "sizeof(decltype(color_buffer_data)::value_type) = " << sizeof(decltype(color_buffer_data)::value_type) << std::endl;
glGenBuffers(1, &VBO2); // color buffer
glBindBuffer(GL_ARRAY_BUFFER, VBO2);
glBufferData(GL_ARRAY_BUFFER, sizeof(decltype(color_buffer_data)::value_type) * color_buffer_data.size(), &color_buffer_data[0], GL_STATIC_DRAW); // mem is allocated here for the buffer size specified // VBO2 is used for a color attribute per vertex
glVertexAttribPointer(1, // attribute - must match the layout in the shader.
4, // size = 3 for rgb, = 4 for rgba
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void *)0); // array buffer offset
glEnableVertexAttribArray(1);
glGenBuffers(1, &VBO3); // point size buffer
glBindBuffer(GL_ARRAY_BUFFER, VBO3);
glBufferData(GL_ARRAY_BUFFER, sizeof(decltype(pointsize_buffer_data)::value_type) * pointsize_buffer_data.size(), &pointsize_buffer_data[0], GL_STATIC_DRAW); // mem is allocated here for the buffer size specified
// VBO3 is used for a point size attribute per vertex
glVertexAttribPointer(2, // attribute - must match the "layout" in the shader.
1, // size = 1 float (depicting a point size)
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void *)0); // array buffer offset
glEnableVertexAttribArray(2);
glBindVertexArray(0);
}
The draw part of the code looks like this:
main()
{
some_code_to_load_the_point_cloud_and_populate_the_buffer_data_structures();
// Loop until the user closes the window
while (!glfwWindowShouldClose(window1))
{
//Note the Vertex Array Object (VAO) is bound in the initialise() function and never unbound so
//I don't bind it again in this while loop. Could that be a source of the error? Am I missing
//something?
//some_code_to_set_viewport_to_left_side_of_screen();
//some_code_to_set_viewport_to_right_side_of_screen();
//some_code_to_update_color_buffer_data(); //do some processing and update
//'std::vector<glm::vec4> color_buffer_data'
//which holds r,g,b,a values per vertex
// Update the (vertex) color buffer on the GPU.
glNamedBufferSubData(VBO,
vertex_buffer_data1.size() * sizeof(decltype(vertex_buffer_data1)::value_type),
color_buffer_data.size() * sizeof(decltype(color_buffer_data)::value_type),
&color_buffer_data[0]);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear the screen
glDrawElements(GL_POINTS, (GLsizei)indices_buffer_data.size(), GL_UNSIGNED_INT, NULL);
//do some processing and update 'std::vector<float> pointsize_buffer_data'
//which holds a float per vertex.
some_code_to_update_point_size_buffer_data();
// Update the (vertex) point sizes on the GPU.
glNamedBufferSubData(VBO,
(vertex_buffer_data1.size() * sizeof(decltype(vertex_buffer_data1)::value_type))
+ (color_buffer_data.size()) * sizeof(decltype(color_buffer_data)::value_type),
pointsize_buffer_data.size() * sizeof(decltype(pointsize_buffer_data)::value_type),
&pointsize_buffer_data[0]);
//do some processing and update 'std::vector<glm::vec4> vertex_buffer_data1'
//which holds x,y,z,w values
some_code_to_update_position_vertex_buffer_data();
// Update the (vertex) positions on the GPU.
glNamedBufferSubData(VBO,
0,
vertex_buffer_data1.size() * sizeof(decltype(vertex_buffer_data1)::value_type),
&vertex_buffer_data1[0]);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear the screen
if(drawTriangleFaces == false) //a flag which the user can toggle from keyboard input
//this draw call works for GL_POINTS but not for GL_TRIANGLES
glDrawElements(GL_POINTS, (GLsizei)indices_buffer_data.size(),
GL_UNSIGNED_INT, nullptr);
else
{//*************this doesn't draw anything - screen is blank*************
//this draw call works for GL_POINTS but not for GL_TRIANGLES nor GL_TRIANGLE_STRIP
glDrawElements(GL_TRIANGLES, (GLsizei)indices_buffer_data.size(),
GL_UNSIGNED_INT, nullptr);
}
}
}
This is my vertex and Fragment shader code (I have them in one file).
#shader vertex
#version 450 core
in vec4 vertexPosition_modelspace;
in vec4 vertColor;
in float vertexPointSize;
uniform mat4 mvpMatrix;
out vec4 fragColor;
void main()
{
gl_Position = mvpMatrix * vertexPosition_modelspace;
gl_PointSize = vertexPointSize;
fragColor = vertColor;
};
#shader fragment
#version 450 core
in vec4 fragColor;
out vec4 color;
void main()
{
// shape the vertices to be round
vec2 round = 2.0 * gl_PointCoord - 1.0;
if (dot(round, round) > 1.0)
{
discard;
}
color = fragColor;
};
I need to draw the point cloud both with and without the mesh (triangle faces).
Any suggestions?
Note:
- The triangle faces are read in from file. I have checked that they are read in correctly. I can view the triangle faces (mesh) if I load the point cloud into an app like Meshlab.
I am using a a few libraries: VCG Lib to read in the Point Cloud, OpenGL to Render and OpenCV to do some image processing.
I am new to graphics and OpenGL. I’m using it to demonstrate a thesis. Any help appreciated. Thanks.