PART ONE
codes.cpp
#include <stdio.h>
#include <GL/glew.h>
#include <GL/freeglut.h>
#define width 222
#define height 207
#define widthPBO width/2
#define heightPBO height/2
GLuint PBO;
void initPBO()
{
GLubyte image[widthPBO][heightPBO][4];
for (int y = 0; y < widthPBO; y++) {
for (int x = 0; x < heightPBO; x++)
{
image[y][x][0] = 255; //red
image[y][x][1] = 255; //green
image[y][x][2] = 255; //blue
image[y][x][3] = 255; //alpya
}
}
glGenBuffers(1, &PBO);
glBindBuffer(GL_PIXEL_PACK_BUFFER, PBO);
glBufferData(GL_PIXEL_PACK_BUFFER, widthPBO * heightPBO * 4 * sizeof(GLubyte), image, GL_DYNAMIC_COPY);
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
}
void render()
{
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, PBO);
glDrawPixels(widthPBO, heightPBO, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
glutSwapBuffers();
}
int main(int argc, char** argv)
{
// init GLUT
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowSize(width, height);
glutInitWindowPosition(200, 100);
int id = glutCreateWindow("PBO");
// init GLEW after GLUT
GLenum err = glewInit();
if (err != GLEW_OK) {
fprintf(stderr, "Error: '%s'\n", glewGetErrorString(err));
return 1;
}
initPBO();
glutDisplayFunc(render);
glutMainLoop();
return 0;
}
部分二
代码分析
1、在initPBO()函数中,根据PBO的宽widthPBO和高heightPBO定义image[][][4],通过for嵌套循环将白色像素{255, 255, 255, 255}写入Image。
glGenBuffers(1, &PBO)在屏幕帧缓冲区中生成一个大小为16384*16384的缓存,用PBO命名。
glBindBuffer(GL_PIXEL_PACK_BUFFER, )使用屏幕帧缓冲区中用户自定义的PBO缓存,使用方式为“PACK”。"PACK"模式下,PBO缓存作“可写”使用,可将数据“写入”PBO缓存空间。
glBufferData( , , , )将大小为widthPBO * heightPBO的四通道"GL_RGBA"的"GLubyte"型的image[][][]数据写入PBO缓存空间。
glBindBuffer( , 0)使用屏幕帧缓冲区自带的GL_BACK缓存区和GL_FRONT缓存区。
此时屏幕帧缓冲区,除自带的GL_BACK和GL_FRONT缓存外,还有定义的GL_PBO缓存。
2、在render()函数中,glClear()启用屏幕帧缓冲区,并将自带的GL_BACK缓存和GL_FRONT缓存初始化为黑色。
glClearColor(1.0f, 0.0f, 0.0f, 1.0f)将GL_BACK缓存和GL_FRONT缓存后始化为红色。
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, )激活GL_PBO缓存的”UNPACK“模式,此时PBO缓存空间作“可读”使用,可以将PBO缓存空间中的数据“读出”。
glDrawPixels(, , , , )中,因为最后一个参数为“NULL”,使用当前活动的PBO缓存。在PBO缓存中,读取大小为widthPBO*heightPBO的四通道”GL_RGBA“的“GL_UNSIGNED_BYTE”数据,绘制到屏幕帧缓冲区自带的GL_BACK缓存中。
glutSwapBuffers()将屏幕帧缓冲区自带的GL_BACK缓存数据写入GL_FRONT缓存。
3、在main()函数中,glutDisplayFunc(render)对屏幕帧缓冲区自带的GL_FRONT缓存数据处理成”电信号“。通过GL_FRONT生成的"电信号"激活控制屏幕的电路,实现屏幕上像素的点亮。glutMainLoop()保持一直有”电信号“输入到屏幕,使屏幕上的像素处于工作状态。