像素缓冲区,pixel buffer.好几个月以前看书看到这就看得我迷迷糊糊,当时手头没有电脑,书被翻译得好多根本不是人话,我看了两遍也只是知道一个大概意思.大概一个月前,决定把上本书从头带着写代码再学习一遍.一个星期前看到了像素缓冲区这块,起初也是没看懂,示例代码是运动模糊特效,信息量比较大,理解起来很难,对我那时来说.于是我把问题简化,简化到先是渲染一个球,用内置的着色器,之后创建缓冲区对象,绑定到GL_PIXEL_PACK_BUFFER,把像素读取到刚创建的缓冲区中.再将刚创建的缓冲区绑定到GL_PIXEL_UNPACK_BUFFER,把缓冲区中的数据写到纹理中.结果就是刚刚渲染出的图像去到了纹理中,数据的传递在显存之间,也达到了得到渲染出的图像的目的,做一些后期处理什么的.从代码上来看就是渲染好一个白色的球之后,在同一帧对整个屏幕这个四边形进行再次渲染,投影矩阵用到了正投影矩阵,在片段着色器上提取出纹理后将其乘以0.5.最终看到的图像就是灰色的球.这个实现逻辑简单,如果单纯是学习使用缓冲区对象这样的事,还是从这样的例子入手比较好.学习也就是这样,自己动手实践出来,也就掌握得不错了.
最近工作上事情多多,很多时候压得我很累.我也不知道该对谁去说.跟朋友说,平时不怎么联系,见面就喝酒,听听他们的不开心,我也很少说我自己的不开心.毕竟工作上的事情跟他们说我觉得挺无聊的.亲人就更不用说.跟女朋友说,我也不想办她老相好办过的事,整天和她说什么工作的事情,而她似乎也不会主动关心我这些.前几天装个虚拟机,一整好几天,后来发现之前美术愚蠢地组织贴图的方式,又弄了一个问题,昨天又开始弄SVN管理客户端外管理不到的代码.事情都是我给自己找的.我TM也不是程序的头,我有什么事情还得跟一个美术程序员说清楚,很多事必须他明白了我才能通过.很多时候觉得委屈无处去说,也得不到什么温暖.一天天就这么过着,似乎不管到什么时候,还是我自己最能慰藉我自己,给我自己温暖和动力.也可能是,我更习惯这样.不说了,贴出来代码,洗洗睡了.
// PixelBuffers.cpp - 2013/09/23 - 22:40
#include "stdafx.h"
#include <GLTools.h>
#include <GLMatrixStack.h>
#include <GLFrame.h>
#include <GLFrustum.h>
#include <GLGeometryTransform.h>
#include <StopWatch.h>
#define FREEGLUT_STATIC
#include <GL/glut.h>
GLFrame viewFrame;
GLFrustum viewFrustum;
GLTriangleBatch sphereBatch;
GLBatch screenQuad;
GLMatrixStack modelViewMatrix;
GLMatrixStack projectionMatrix;
M3DMatrix44f orthoMatrix;
GLGeometryTransform transformPipeline;
GLShaderManager shaderManager;
CStopWatch timer ;
GLuint textures[1] ;
GLuint pixelBufferObjects[1];
GLuint pixelDataSize ;
void * pixelData ;
GLuint writeScreen;
GLsizei screenWidth ;
GLsizei screenHeight ;
void SetupRC(void)
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f );
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
shaderManager.InitializeStockShaders();
viewFrame.MoveForward(4.0f);
gltMakeSphere(sphereBatch, 1.0f, 26, 13);
gltGenerateOrtho2DMat(screenWidth, screenHeight, orthoMatrix, screenQuad);
writeScreen = gltLoadShaderPairWithAttributes(
"writeScreen.vs", "writeScreen.fs",
2,
GLT_ATTRIBUTE_VERTEX, "vVertex",
GLT_ATTRIBUTE_TEXTURE0, "texCoord0");
glGenTextures(1, textures) ;
GLuint pixelDataSize = screenWidth * screenHeight * sizeof(GL_UNSIGNED_BYTE) ;
void * textureData = (void *)malloc(pixelDataSize) ;
memset(textureData, NULL, pixelDataSize) ;
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textures[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, screenWidth, screenHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData);
pixelData = malloc(pixelDataSize) ;
glGenBuffers(1, pixelBufferObjects) ;
glBindBuffer(GL_PIXEL_PACK_BUFFER, pixelBufferObjects[0]) ;
glBufferData(GL_PIXEL_PACK_BUFFER, screenWidth * screenHeight * sizeof(GL_UNSIGNED_BYTE), NULL, GL_DYNAMIC_COPY) ;
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0) ;
gltGenerateOrtho2DMat(screenWidth, screenHeight, orthoMatrix, screenQuad);
timer.Reset() ;
}
void ShutdownRC(void)
{
glDeleteTextures(1, textures) ;
glDeleteBuffers(1, pixelBufferObjects) ;
}
void RenderScene(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
modelViewMatrix.PushMatrix(viewFrame);
float elapsedSceonds = timer.GetElapsedSeconds() ;
modelViewMatrix.Translate(elapsedSceonds, 0, 0) ;
if (elapsedSceonds > 1.0f)
timer.Reset() ;
GLfloat vAmbientColor[] = { 1.0f, 1.0f, 1.0f, 1.0f };
shaderManager.UseStockShader(GLT_SHADER_FLAT,
transformPipeline.GetModelViewProjectionMatrix(),
vAmbientColor);
sphereBatch.Draw();
modelViewMatrix.PopMatrix();
glBindBuffer(GL_PIXEL_PACK_BUFFER, pixelBufferObjects[0]) ;
glReadPixels(0, 0, screenWidth, screenHeight, GL_RGB, GL_UNSIGNED_BYTE, NULL) ;
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0) ;
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pixelBufferObjects[0]) ;
glActiveTexture(GL_TEXTURE0) ;
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, screenWidth, screenHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL) ;
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0) ;
projectionMatrix.PushMatrix() ;
projectionMatrix.LoadIdentity() ;
projectionMatrix.LoadMatrix(orthoMatrix) ;
modelViewMatrix.PushMatrix() ;
modelViewMatrix.LoadIdentity() ;
glDisable(GL_DEPTH_TEST) ;
glUseProgram(writeScreen) ;
glUniformMatrix4fv(glGetUniformLocation(writeScreen, "mvpMatrix"), 1, GL_FALSE, transformPipeline.GetModelViewProjectionMatrix()) ;
glUniform1i(glGetUniformLocation(writeScreen, "textureUnit0"), 0) ;
screenQuad.Draw() ;
glEnable(GL_DEPTH_TEST) ;
modelViewMatrix.PopMatrix() ;
projectionMatrix.PopMatrix() ;
glutSwapBuffers();
glutPostRedisplay();
}
void ChangeSize(int w, int h)
{
if(h == 0)
h = 1;
screenWidth = w ;
screenHeight = h ;
gltGenerateOrtho2DMat(screenWidth, screenHeight, orthoMatrix, screenQuad);
glViewport(0, 0, w, h);
viewFrustum.SetPerspective(35.0f, float(w)/float(h), 1.0f, 100.0f);
projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
free(pixelData) ;
pixelDataSize = screenWidth * screenHeight * sizeof(GL_UNSIGNED_BYTE) ;
pixelData = (void *)malloc(pixelDataSize) ;
glBindBuffer(GL_PIXEL_PACK_BUFFER, pixelBufferObjects[0]) ;
glBufferData(GL_PIXEL_PACK_BUFFER, pixelDataSize, pixelData, GL_DYNAMIC_DRAW) ;
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0) ;
}
int main(int argc, char* argv[])
{
gltSetWorkingDirectory(argv[0]);
screenWidth = 800 ;
screenHeight = 600 ;
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(screenWidth, screenHeight);
glutCreateWindow("Pixel Buffer");
glutReshapeFunc(ChangeSize);
glutDisplayFunc(RenderScene);
GLenum err = glewInit();
if (err != GLEW_OK)
{
fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
return 1;
}
SetupRC();
glutMainLoop();
ShutdownRC();
return 0;
}