用于在大满贯中绘制特征点的opengl着色器[关闭]
Posted
技术标签:
【中文标题】用于在大满贯中绘制特征点的opengl着色器[关闭]【英文标题】:opengl shader for drawing feature point in slam [closed] 【发布时间】:2020-02-26 05:14:19 【问题描述】:我想使用 opengl 着色器绘制点。 现在我的代码使用 glvertex3f(pos.x, pos.y, pos.z) 但是当使用它绘制的点太多时,它会变慢。所以我想使用着色器和 glDrawarrays。但它不起作用。请检查我的代码。
原代码:
for (const auto lm : landmarks)
const openvslam::Vec3_t pos_w = lm->get_pos_in_world();
glColor3ub(lm->color_[0], lm->color_[1], lm->color_[2]);
glVertex3f(pos_w.cast<float>().eval().x(),pos_w.cast<float>().eval().y(), pos_w.cast<float>().eval().z());
我的代码:
for (const auto lm : landmarks)
const openvslam::Vec3_t pos_w = lm->get_pos_in_world();
int buffer_size = local_landmarks.size();
glGenBuffers(2, buffers_);
glBindBuffer(GL_ARRAY_BUFFER, buffers_[0]);
glm::vec3 pos_pt = glm::vec3(pos_w.cast<float>().eval().x(),pos_w.cast<float>().eval().y(), pos_w.cast<float>().eval().z());
glBufferData(GL_ARRAY_BUFFER, 3*buffer_size*sizeof(float), &pos_pt , GL_DYNAMIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, buffers_[1]);
glm::vec3 color_pt = glm::vec3(lm->color_[0], lm->color_[1], lm->color_[2]);
glBufferData(GL_ARRAY_BUFFER, buffer_size*3*sizeof(float), &color_pt, GL_DYNAMIC_DRAW);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);
Eigen::Matrix4f mvp = s_cam_shader_opengl->GetProjectionModelViewMatrix();
//Eigen::Matrix4f mvp = s_cam_shader_opengl->GetProjectionMatrix() * s_cam_shader_opengl->GetModelViewMatrix();
glUniformMatrix4fv(mvp_location, 1, GL_FALSE, mvp.data());
glPointSize(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawArrays(GL_POINTS, 0, 3*num);
顶点着色器
#version 460
uniform mat4 mvpMat;
layout (location = 0) in vec3 test_position;
layout (location = 1) in vec3 test_color;
out vec3 colorr;
void main(void)
colorr = test_color;
gl_Position = vec4(test_position,1.0);
片段着色器
#version 460
uniform mat4 mvpMat;
in vec3 colorr;
out vec4 frag_color;
void main(void)
frag_color = vec4(colorr, 1.0);
/////////////////////////////////////// //////////////////////
+编辑
我更新了代码,但它说分段错误。 有什么问题?
struct TLandmarkData
glm::vec3 pos;
glm::vec3 color;
;
using TLandmarks = std::vector<TLandmarkData>;
TLandmarks landmarks_;
...
code
...
glUseProgram(points_program_);
while()
...
for (const auto lm : landmarks)
TLandmarkData aaa;
glm::vec3 pos_pt = glm::vec3(pos_w.cast<float>().eval().x(),pos_w.cast<float>().eval().y(), pos_w.cast<float>().eval().z());
glm::vec3 color_pt = glm::vec3(lm->color_[0], lm->color_[1], lm->color_[2]);
aaa.pos = pos_pt;
aaa.color = color_pt;
landmarks_.push_back(aaa);
...
GLuint vbo_;
GLuint vao_;
glGenBuffers(1, &vbo_);
glBindBuffer(GL_ARRAY_BUFFER, vbo_);
glBufferData(GL_ARRAY_BUFFER, landmarks_.size()*sizeof(*landmarks_.data()), landmarks_.data(), GL_STATIC_DRAW);
glGenVertexArrays(1, &vao_);
glBindVertexArray(vao_);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(TLandmarkData), 0);
glEnableVertexAttribArray( 0 );
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(TLandmarkData), (void*)(sizeof(glm::vec3)));
glEnableVertexAttribArray(1);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDrawArrays(GL_POINTS, 0, landmarks_.size());
顶点着色器
#version 460
layout (location = 0) in vec3 test_position;
layout (location = 1) in vec3 test_color;
out vec3 colorr;
void main(void)
colorr = test_color;
gl_Position = vec4(test_position,1.0);
片段着色器
#version 460
in vec3 colorr;
out vec4 frag_color;
void main(void)
frag_color = vec4(colorr, 1.0);
+
【问题讨论】:
【参考方案1】:您实际上要做的是创建landmarks.size()
缓冲区而不是1 个缓冲区。您必须创建一个缓冲区。为了获得最佳性能增益,您必须创建一次缓冲区(分别在仅更改时)并在着色器中进行世界变换。
使用以下数据结构来表示一个点(或类似的aggregate):
struct TLandmarkData
glm::vec3 pos;
glm::vec3 color;
;
using TLandmarks = std::vector<TLandmarkData>;
创建一个顶点数组对象和一个顶点缓冲区对象(在初始化时): (另见Vertex Specification)
TLandmarks landmarks;
GLuint vbo_;
GLuint vao_;
glGenBuffers(1, &vbo_);
glBindBuffer(GL_ARRAY_BUFFER, vbo_);
glBufferData(GL_ARRAY_BUFFER, landmarks.size()*sizeof(*landmarks.data()), landmarks.data(), GL_STATIC_DRAW);
glGenVertexArrays(1, &vao_);
glBindVertexArray(vao_);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(TLandmarkData), 0);
glEnableVertexAttribArray( 0 );
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(TLandmarkData), (void*)(sizeof(glm::vec3)));
glEnableVertexAttribArray(1);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
如您所见,您不需要任何循环。如果数据发生变化,可以更新缓冲区(vbo_
)(例如glBufferSubData
)。
当你想绘制点时,绑定顶点数组对象就足够了。 glDrawArrays
的 count 参数必须是顶点数:
glBindVertexArray(vao_);
glDrawArrays(GL_POINTS, 0, landmarks.size());
使用mat4
类型的Uniform,将点转换为顶点着色器中的世界坐标:
#version 460
uniform mat4 mvpMat;
layout (location = 0) in vec3 test_position;
layout (location = 1) in vec3 test_color;
layout (location=0) uniform mat4 worldtransform;
out vec3 colorr;
void main(void)
colorr = test_color;
gl_Position = worldtransform * vec4(test_position,1.0);
在glUseProgram
安装程序后,通过glUniformMatrix4fv
设置统一(每帧更新):
glm::mat4 toworld(1.0f);
// set toworld
// [...]
glUseProgram(myProgram);
glUniformMatrix4fv(0, 1, GL_FALSE, glm::value_ptr(toworld));
【讨论】:
感谢您的回答。在我的算法中,地标(大小和位置)非常快速地更改和更新新数据,所以我使用 for 循环。如何实时更新和绘制点? @2255jj 您也可以更新缓冲区并在每个帧中指定 vao。 (在这种情况下,您不需要矩阵转换)。动态生成std::vector<TLandmarkData>;
并使用我的答案代码。注意如果点数没有变化,将vbo_
的内容更改为glBufferSubData
(每帧)就足够了。
更新代码但显示分段错误。什么问题?请检查。
@2255jj 你在glDrawArrays
之前错过了glBindVertexArray(vao_);
。如果vao_
和vbo_
只是临时的,那么你必须通过glDeleteBuffers(1, &vbo_);
删除它们glDeleteVertexArrays(1, &vao_);
谢谢,它可以工作,但有些问题。它绘制了未知的大红色方块,并且点的颜色全是白色。还有一个问题,我可以在同一个窗口中将 glDrawarrays 与 glbegin()~ glvertex() ~ glend() 一起使用吗?以上是关于用于在大满贯中绘制特征点的opengl着色器[关闭]的主要内容,如果未能解决你的问题,请参考以下文章