C++ 在OpenGl core中使用单个像素绘制直线

C++ 在OpenGl core中使用单个像素绘制直线,c++,algorithm,line,opengl-3,bresenham,C++,Algorithm,Line,Opengl 3,Bresenham,我正在尝试在OpenGl中实现一个线条绘制算法。我从中学到了使用OpenGl的基本知识。在线条绘制算法中,我需要设置单个像素本身。我不明白如何在像素级使用OpenGl。我尝试在opengl中搜索bresenham的直线算法实现,该实现在任何地方都使用OpenGl3.3不支持的函数glDrawPixels。OpenGl3.3中有什么我没有的吗?OpenGL的重点是使用硬件来为您进行光栅化。如果你自己做光栅化,只需将像素写入分配给你自己的内存,你根本不需要OpenGL;不管怎样,这对你没有任何帮助

我正在尝试在OpenGl中实现一个线条绘制算法。我从中学到了使用OpenGl的基本知识。在线条绘制算法中,我需要设置单个像素本身。我不明白如何在像素级使用OpenGl。我尝试在opengl中搜索bresenham的直线算法实现,该实现在任何地方都使用OpenGl3.3不支持的函数glDrawPixels。OpenGl3.3中有什么我没有的吗?

OpenGL的重点是使用硬件来为您进行光栅化。如果你自己做光栅化,只需将像素写入分配给你自己的内存,你根本不需要OpenGL;不管怎样,这对你没有任何帮助

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


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

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

但这只适用于兼容性配置文件或较旧的GL实现

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

要使这两种方法的示例更简单,请选择注释或取消注释的_gl_old define,仅使用一些随机点和非常简单的着色器,使用上一链接中的gl_simple.h,以[pixels]单位显示400x400个窗口和点:

//---------------------------------------------------------------------------
#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);
    }
//---------------------------------------------------------------------------

它是OpenGL/VCL/C++的,所以只需忽略VCL所有的定义,pragmas,包括。。。除了gl_simple.h和_gl_平台上的旧东西和模拟事件,请重新绘制、初始化/退出、调整大小。新旧样式之间的区别在于,在渲染之前需要提前计算渲染像素并将其存储到表/数组中。

我可以使用什么来代替OpenGl?操作系统的窗口/用户界面例程用于在窗口上绘制图像,您在谈论什么例程?无论您使用什么框架在Windows上创建和管理窗口Win32或MFC,Linux上的Xlib/Gtk/Qt/等都有用于绘制该窗口内容的例程。这些通常会设置一个像素函数,以及将图像数据从应用程序内存复制到窗口函数。如果您坚持核心配置文件,我添加了两种使用GL的方法,而不仅仅是第二种方法。
//---------------------------------------------------------------------------
#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);
    }
//---------------------------------------------------------------------------