我正在尝试在OpenGl中实现线条绘制算法。我从learnopengl学到了使用OpenGl的基础知识。在线条绘制算法中,我需要设置单个像素本身。我不明白如何在像素级别使用OpenGl。我尝试在opengl中搜索bresenham的线路算法,在实现中使用OpenGl3.3不支持的函数 glDrawPixels 。我在OpenGl3.3中缺少什么?
答案 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/glDrawElements
与GL_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
之外的东西)和模仿事件在您的平台上(重新绘制,初始化/退出,调整大小)。新旧样式之间的区别在于,您需要在渲染之前计算前面渲染的像素,并将它们存储到表/数组中。