glDrawPixels:绘制一些像素。当前可以简单理解为“把内存中一些数据作为像素数据,进行绘制”。
glDrawPixels函数是OpenGL中的一个绘图函数,它用于在窗口中绘制像素数据。这个函数可以将一组像素数据直接绘制在窗口的指定位置,不需要通过顶点和图元来定义几何图形。glDrawPixels适用于简单的像素级绘制,但在实际应用中较少使用,因为它相对较慢且不支持硬件加速。
void glDrawPixels(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels);
/*width和height:绘制区域的宽度和高度,以像素为单位。
format:指定像素数据的颜色格式,常见的有 GL_RGB(红绿蓝颜色)和 GL_RGBA(红绿蓝透明颜色)等。
type:指定像素数据的数据类型,常见的有 GL_UNSIGNED_BYTE(无符号字节)等。
pixels:指向存储像素数据的指针。*/
注意,glDrawPixels函数绘制的像素数据会覆盖在当前绘制区域的位置,所以确保你在适当的位置调用该函数
#include
void display() {
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Clear color to black
glClear(GL_COLOR_BUFFER_BIT); // Clear the color buffer
GLsizei width = 300;
GLsizei height = 300;
GLubyte* pixels = new GLubyte[width * height * 3];
// Fill the pixel array with colors (e.g., red and green stripes)
//这段代码会在绘制区域的左半部分创建红色的条纹,右半部分创建绿色的条纹。
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int index = (y * width + x) * 3;
if (x < width / 2) {
// Red color
pixels[index] = 255;
pixels[index + 1] = 0;
pixels[index + 2] = 0;
}
else {
// Green color
pixels[index] = 0;
pixels[index + 1] = 255;
pixels[index + 2] = 0;
}
}
}
glDrawPixels(width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels);
glFlush(); // Ensure all drawing commands are executed
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(800, 600);
glutCreateWindow("glDrawPixels Example");
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
glDrawPixels 函数与 glReadPixels 函数相比,参数内容大致相同。它的第一、二、三、四个参数分别对应于 glReadPixels 函数的第三、四、五、六个参数,依次表示图象宽度、图象高度、像素数据内容、像素数据在内存中的格式。两个函数的最后一个参数也是对应的,glReadPixels 中表示像素读取后存放在内存中的位置,glDrawPixels 则表示用于绘制的像素数据在内存中的位置。
注意到 glDrawPixels 函数比 glReadPixels 函数少了两个参数,这两个参数在glReadPixels 中分别是表示图象的起始位置。在 glDrawPixels 中,不必显式的指定绘制的位置,这是因为绘制的位置是由另一个函数 glRasterPos来指定的。glRasterPos函数的参数与 glVertex*类似,通过指定一个二维/三维/四维坐标,OpenGL 将自动计算出该坐标对应的屏幕位置,并把该位置作为绘制像素的起始位置。
自己画一个dummy.bmp文件,程序如下
// glDrawPixels举例.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
#include "pch.h"
#include
#include
#define FileName "dummy.bmp"
static GLint ImageWidth;
static GLint ImageHeight;
static GLint PixelLength;
static GLubyte* PixelData;
#include
#include
void display(void)
{
// 清除屏幕并不必要
// 每次绘制时,画面都覆盖整个屏幕
// 因此无论是否清除屏幕,结果都一样
// glClear(GL_COLOR_BUFFER_BIT);
// 绘制像素
glDrawPixels(ImageWidth, ImageHeight,GL_BGR_EXT, GL_UNSIGNED_BYTE, PixelData);
// 完成绘制
glutSwapBuffers();
}
int main(int argc, char* argv[])
{
// 打开文件
FILE* pFile;
errno_t err;
err= fopen_s(&pFile,"C:\\*********\\dummy.bmp", "rb");
if (pFile == 0)
exit(0);
// 读取图象的大小信息
fseek(pFile, 0x0012, SEEK_SET);
fread(&ImageWidth, sizeof(ImageWidth), 1, pFile);
fread(&ImageHeight, sizeof(ImageHeight), 1, pFile);
// 计算像素数据长度
PixelLength = ImageWidth * 3;
while (PixelLength % 4 != 0)
++PixelLength;
PixelLength *= ImageHeight;
// 读取像素数据
PixelData = (GLubyte*)malloc(PixelLength);
if (PixelData == 0)
exit(0);
fseek(pFile, 54, SEEK_SET);
fread(PixelData, PixelLength, 1, pFile);
// 关闭文件
fclose(pFile);
// 初始化 GLUT 并运行
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100, 100);
glutInitWindowSize(ImageWidth, ImageHeight);
glutCreateWindow(FileName);
glutDisplayFunc(&display);
glutMainLoop();
// 释放内存
// 实际上,glutMainLoop 函数永远不会返回,这里也永远不会到达
// 这里写释放内存只是出于一种个人习惯
// 不用担心内存无法释放。在程序结束时操作系统会自动回收所有内存
free(PixelData);
return 0;
}
运行结果
OpenGL 在绘制像素之前,可以对像素进行若干处理。最常用的可能就是对整个像素图象进行放大/缩小。使用 glPixelZoom来设置放大/缩小的系数,该函数有两个参数,分别是水平方向系数和垂直方向系数。例如设置 glPixelZoom(0.5f, 0.8f);则表示水平方向变为原来的 50%大小,而垂直方向变为原来的 80%大小。我们甚至可以使用负的系数,使得整个图象进行水平方向或垂直方向的翻转(默认像素从左绘制到右,但翻转后将从右绘制到左。默认像素从下绘制到上,但翻转后将从上绘制到下。因此,glRasterPos*函数设置的“开始位置”不一定就是矩形的左下角)。