Рисование линии с использованием отдельных пикселей в ядре OpenGl

Я пытаюсь реализовать алгоритм рисования линий в OpenGl. Я изучил основы использования OpenGl из learnopengl. В алгоритме рисования линий мне нужно установить сам отдельный пиксель. Я не понимаю, как использовать OpenGl на уровне пикселей. Я пытался найти реализацию алгоритма строки Брезенхэма в opengl, везде реализация использует функцию glDrawPixels который не поддерживается в OpenGl3.3. Есть ли что-то, чего мне не хватает в OpenGl3.3?

0

Решение

Смысл OpenGL в том, чтобы использовать оборудование, которое сделает растеризацию за вас. Если вы делаете растеризацию самостоятельно, просто записывайте пиксели в память, которую вы выделяете сами, вам вообще не нужен OpenGL; это все равно ничего не сделает для вас.

Чтобы отобразить ваше изображение, вы можете загрузить свое изображение в текстуру (glTexImage2D / glTexSubImage2D), а затем нарисовать четырехугольник с сопоставленной ему текстурой. Или используйте процедуры окна / пользовательского интерфейса вашей ОС, чтобы нарисовать изображение в окне, что, вероятно, будет проще.

Если вы действительно хотите рисовать отдельные пиксели один за другим с помощью OpenGL, вы можете использовать GL_POINTS. Вам все равно придется создавать вершинные и фрагментные шейдеры и т. Д., Что требует много дополнительной работы.

1

Другие решения

Самый простой способ — использовать старый стиль GL апи

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.

Для Новый вещи вам нужно создать список точек для рендеринга множества ВАО / О с ними и использовать glDrawArrays/glDrawElements с GL_POINT стиль и грубо нужно использовать шейдеры. Посмотрите здесь полный пример куба, чтобы начать с:

Чтобы упростить этот пример, приведем здесь пример обоих подходов (выберите с комментариями или комментариями _gl_old определить) только с некоторыми случайными точками и очень простыми шейдерами (ожидая окна 400×400 и точек в [пикселях]), используя gl_simple.h из предыдущей ссылки:

//---------------------------------------------------------------------------
#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 (все определения, прагмы, включают … кроме gl_simple.h а также _gl_old) вещи и имитировать события на вашей платформе (перекрасить, инициализировать / выйти, изменить размер). Разница между новым и старым стилем заключается в том, что вам нужно вычислить визуализированные пиксели заранее перед рендерингом и сохранить их в таблицу / массив.

0