使用OpenGl核心中的单个像素绘制一条线

时间:2017-03-05 16:47:51

标签: c++ algorithm line opengl-3 bresenham

我正在尝试在OpenGl中实现线条绘制算法。我从learnopengl学到了使用OpenGl的基础知识。在线条绘制算法中,我需要设置单个像素本身。我不明白如何在像素级别使用OpenGl。我尝试在opengl中搜索bresenham的线路算法,在实现中使用OpenGl3.3不支持的函数 glDrawPixels 。我在OpenGl3.3中缺少什么?

2 个答案:

答案 0 :(得分:1)

OpenGL的目的是使用将为您进行光栅化的硬件。如果您自己进行光栅化,只需将像素写入自己分配的内存中,根本不需要OpenGL;无论如何,它不会为你做任何事情。

要显示图像,可以将图像上传到纹理(glTexImage2D / glTexSubImage2D),然后使用映射到它的纹理绘制四边形。或者使用操作系统的窗口/ UI例程在窗口上绘制图像,这可能会更容易。

如果你真的想用OpenGL逐个绘制单个像素,你可以使用GL_POINTS。您仍然需要创建顶点和片段着色器等,这是一项额外的工作。

答案 1 :(得分:0)

最简单的方法是使用旧样式 GL api

const int sz=400;   // window resolution
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
glDisable(GL_TEXTURE_2D);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(-1.0,-1.0,0.0);
glScalef(2.0/float(sz),2.0/float(sz),0.0);

glBegin(GL_POINTS);
glColor3f(1.0,1.0,1.0);
glVertex2i(x0,y0);
glVertex2i(x1,y1);
glVertex2i(x2,y2);
...
glEnd(); 

glFinish();
SwapBuffers(hdc);

但这仅适用于兼容性配置文件或较旧的GL实施。

对于新内容,您需要创建一个点列表以使用它们呈现 VAO / VBOs ,并将glDrawArrays/glDrawElementsGL_POINT一起使用样式和粗糙你需要使用着色器。在这里查看完整的多维数据集示例,以:

开头

为了简化这两个方法的示例(使用注释或取消注释_gl_old定义)只使用一些随机点和非常简单的着色器(期望400x400窗口和以[像素]为单位的点)使用{ {1}}来自上一个链接:

gl_simple.h

OpenGL / VCL / C ++ 所以请忽略VCL(所有定义,编译指示,包括......除//--------------------------------------------------------------------------- #include <vcl.h> #include <math.h> #pragma hdrstop #include "Unit1.h" #include "gl_simple.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //--------------------------------------------------------------------------- // this define determines if old or new stuff is used //#define _gl_old //--------------------------------------------------------------------------- const int sz=400; // window resolution const int n=1024; // points const int n2=n+n; // points*dimensions GLint pnt[n2]; // points x,y ... #ifndef _gl_old GLuint pnt_vbo=-1; GLuint pnt_vao=-1; #endif //--------------------------------------------------------------------------- void pnt_init() { // compute some points (your line algo should do it I use random instead) Randomize(); for (int i=0;i<n2;i++) pnt[i]=Random(sz); // the new stuff need VBO #ifndef _gl_old // create VAO/VBO glGenVertexArrays(1,&pnt_vao); glGenBuffers(1,&pnt_vbo); glBindVertexArray(pnt_vao); // points -> VBO glBindBuffer(GL_ARRAY_BUFFER,pnt_vbo); glBufferData(GL_ARRAY_BUFFER,sizeof(pnt),pnt,GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribIPointer(0,2,GL_INT,0,0); // unbind VAO/VBO glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER,0); glDisableVertexAttribArray(0); #endif } //--------------------------------------------------------------------------- void pnt_exit() { // the new stuff needs to release VBO/VAO #ifndef _gl_old glDeleteVertexArrays(1,&pnt_vao); glDeleteBuffers(1,&pnt_vbo); #endif } //--------------------------------------------------------------------------- void gl_draw() { glClear(GL_COLOR_BUFFER_BIT); glDisable(GL_DEPTH_TEST); glDisable(GL_TEXTURE_2D); // Old GL 1.0 stuff #ifdef _gl_old // set view to 2D in [pixels] glMatrixMode(GL_PROJECTION); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(-1.0,-1.0,0.0); glScalef(2.0/float(sz),2.0/float(sz),0.0); // render points froma list glBegin(GL_POINTS); glColor3f(1.0,1.0,1.0); for (int i=0;i<n2;i+=2) glVertex2iv(pnt+i); glEnd(); #endif // New GL stuff #ifndef _gl_old glUseProgram(prog_id); glBindVertexArray(pnt_vao); glDrawArrays(GL_POINTS,0,sizeof(pnt)/sizeof(pnt[0])); glBindVertexArray(0); glUseProgram(0); #endif // glFlush(); glFinish(); SwapBuffers(hdc); } //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner):TForm(Owner) { // Init of program gl_init(Handle); // init OpenGL pnt_init(); // init pooints and VAO/VBO #ifndef _gl_old // init shaders char vertex[]="#version 330 core\r\nlayout(location=0) in ivec2 pos;\r\nvoid main(void) { vec2 p; p=vec2(pos); p-=200; p/=200.0; gl_Position=vec4(p,0.0,1.0); }"; char fragment[]="#version 330 core\r\nout vec4 col;\r\nvoid main() { col=vec4(1.0,1.0,1.0,1.0); }"; glsl_init(vertex,fragment); int hnd=FileCreate("GLSL.txt"); FileWrite(hnd,glsl_log,glsl_logs); FileClose(hnd); // just write logs into file #endif } //--------------------------------------------------------------------------- void __fastcall TForm1::FormDestroy(TObject *Sender) { // Exit of program gl_exit(); pnt_exit(); #ifndef _gl_old glsl_exit(); #endif } //--------------------------------------------------------------------------- void __fastcall TForm1::FormPaint(TObject *Sender) { // repaint gl_draw(); } //--------------------------------------------------------------------------- void __fastcall TForm1::FormResize(TObject *Sender) { // resize gl_resize(ClientWidth,ClientHeight); } //--------------------------------------------------------------------------- gl_simple.h之外的东西)和模仿事件在您的平台上(重新绘制,初始化/退出,调整大小)。新旧样式之间的区别在于,您需要在渲染之前计算前面渲染的像素,并将它们存储到表/数组中。