像素缓冲区,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; }