《OpenGL 超级宝典(Super Bible)第五版》 有关 PBO 的 Example
【摘要】
代码即关键注释如下:
static GLfloat vGreen[] = { 0.0f, 1.0f, 0.0f, 1.0f };static GLfloat vWhite[] = { 1.0f, 1.0f, 1.0f, 1.0f };static GLfloat vLightPos[] = { 0.0f, 3.0f, 0.0f, 1...
代码即关键注释如下:
-
static GLfloat vGreen[] = { 0.0f, 1.0f, 0.0f, 1.0f };
-
static GLfloat vWhite[] = { 1.0f, 1.0f, 1.0f, 1.0f };
-
static GLfloat vLightPos[] = { 0.0f, 3.0f, 0.0f, 1.0f };
-
-
GLsizei screenWidth; // Desired window or desktop width
-
GLsizei screenHeight; // Desired window or desktop height
-
-
GLboolean bFullScreen; // Request to run full screen
-
GLboolean bAnimated; // Request for continual updates
-
-
GLShaderManager shaderManager; // Shader Manager
-
GLMatrixStack modelViewMatrix; // Modelview Matrix
-
GLMatrixStack projectionMatrix; // Projection Matrix
-
M3DMatrix44f orthoMatrix;
-
GLFrustum viewFrustum; // View Frustum
-
GLGeometryTransform transformPipeline; // Geometry Transform Pipeline
-
GLFrame cameraFrame; // Camera frame
-
-
GLTriangleBatch torusBatch;
-
GLBatch floorBatch;
-
GLBatch screenQuad;
-
-
GLuint textures[1];
-
GLuint blurTextures[6];
-
GLuint pixBuffObjs[1];
-
GLuint curBlurTarget;
-
bool bUsePBOPath;
-
GLfloat speedFactor;
-
GLuint blurProg;
-
void *pixelData;
-
GLuint pixelDataSize;
-
-
//void MoveCamera(void);
-
void DrawWorld(GLfloat yRot, GLfloat xPos);
-
bool LoadBMPTexture(const char *szFileName, GLenum minFilter, GLenum magFilter, GLenum wrapMode);
-
-
void SetupBlurProg(void);
-
-
// returns 1 - 6 for blur texture units
-
// curPixBuf is always between 0 and 5
-
void AdvanceBlurTaget()
-
{
-
curBlurTarget = ((curBlurTarget + 1) % 6);
-
}
-
GLuint GetBlurTarget0()
-
{
-
return (1 + ((curBlurTarget + 5) % 6));
-
}
-
GLuint GetBlurTarget1()
-
{
-
return (1 + ((curBlurTarget + 4) % 6));
-
}
-
GLuint GetBlurTarget2()
-
{
-
return (1 + ((curBlurTarget + 3) % 6));
-
}
-
GLuint GetBlurTarget3()
-
{
-
return (1 + ((curBlurTarget + 2) % 6));
-
}
-
GLuint GetBlurTarget4()
-
{
-
return (1 + ((curBlurTarget + 1) % 6));
-
}
-
GLuint GetBlurTarget5()
-
{
-
return (1 + ((curBlurTarget) % 6));
-
}
-
-
void UpdateFrameCount()
-
{
-
static int iFrames = 0; // Frame count
-
static CStopWatch frameTimer; // Render time
-
-
// Reset the stopwatch on first time
-
if(iFrames == 0)
-
{
-
frameTimer.Reset();
-
iFrames++;
-
}
-
// Increment the frame count
-
iFrames++;
-
-
// Do periodic frame rate calculation
-
if (iFrames == 101)
-
{
-
float fps;
-
-
fps = 100.0f / frameTimer.GetElapsedSeconds();
-
if (bUsePBOPath)
-
printf("Pix_buffs - Using PBOs %.1f fps\n", fps);
-
else
-
printf("Pix_buffs - Using Client mem copies %.1f fps\n", fps);
-
-
frameTimer.Reset();
-
iFrames = 1;
-
}
-
}
-
-
///
-
// Load in a BMP file as a texture. Allows specification of the filters and the wrap mode
-
bool LoadBMPTexture(const char *szFileName, GLenum minFilter, GLenum magFilter, GLenum wrapMode)
-
{
-
GLbyte *pBits;
-
GLint iWidth, iHeight;
-
-
pBits = gltReadBMPBits(szFileName, &iWidth, &iHeight);
-
if(pBits == NULL)
-
return false;
-
-
// Set Wrap modes
-
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode);
-
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode);
-
-
// Do I need to generate mipmaps?
-
if(minFilter == GL_LINEAR_MIPMAP_LINEAR || minFilter == GL_LINEAR_MIPMAP_NEAREST || minFilter == GL_NEAREST_MIPMAP_LINEAR || minFilter == GL_NEAREST_MIPMAP_NEAREST)
-
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
-
-
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
-
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
-
-
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, iWidth, iHeight, 0, GL_BGR, GL_UNSIGNED_BYTE, pBits);
-
return true;
-
}
-
-
///
-
// OpenGL related startup code is safe to put here. Load textures, etc.
-
void SetupRC(void)
-
{
-
GLenum err = glewInit();
-
if (GLEW_OK != err)
-
{
-
/* Problem: glewInit failed, something is seriously wrong. */
-
fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
-
}
-
-
// Initialze Shader Manager
-
shaderManager.InitializeStockShaders();
-
glEnable(GL_DEPTH_TEST);
-
-
// Black
-
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
-
-
gltMakeTorus(torusBatch, 0.4f, 0.15f, 35, 35);
-
-
GLfloat alpha = 0.25f;
-
floorBatch.Begin(GL_TRIANGLE_FAN, 4, 1);
-
floorBatch.Color4f(0.0f, 1.0f, 0.0f, alpha);
-
floorBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
-
floorBatch.Normal3f(0.0, 1.0f, 0.0f);
-
floorBatch.Vertex3f(-20.0f, -0.41f, 20.0f);
-
-
floorBatch.Color4f(0.0f, 1.0f, 0.0f, alpha);
-
floorBatch.MultiTexCoord2f(0, 10.0f, 0.0f);
-
floorBatch.Normal3f(0.0, 1.0f, 0.0f);
-
floorBatch.Vertex3f(20.0f, -0.41f, 20.0f);
-
-
floorBatch.Color4f(0.0f, 1.0f, 0.0f, alpha);
-
floorBatch.MultiTexCoord2f(0, 10.0f, 10.0f);
-
floorBatch.Normal3f(0.0, 1.0f, 0.0f);
-
floorBatch.Vertex3f(20.0f, -0.41f, -20.0f);
-
-
floorBatch.Color4f(0.0f, 1.0f, 0.0f, alpha);
-
floorBatch.MultiTexCoord2f(0, 0.0f, 10.0f);
-
floorBatch.Normal3f(0.0, 1.0f, 0.0f);
-
floorBatch.Vertex3f(-20.0f, -0.41f, -20.0f);
-
floorBatch.End();
-
-
glGenTextures(1, textures);
-
glBindTexture(GL_TEXTURE_2D, textures[0]);
-
LoadBMPTexture("marble.bmp", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_REPEAT);
-
-
// Create blur program
-
blurProg = gltLoadShaderPairWithAttributes("blur.vs", "blur.fs", 2,
-
GLT_ATTRIBUTE_VERTEX, "vVertex", GLT_ATTRIBUTE_TEXTURE0, "texCoord0");
-
-
// Create blur textures
-
glGenTextures(6, blurTextures);
-
-
// ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
-
// XXX I don't think this is necessary. Should set texture data to NULL
-
// Allocate a pixel buffer to initialize textures and PBOs
-
// 计算 像素数据的字节数
-
pixelDataSize = screenWidth * screenHeight * 3 * sizeof(unsigned int); // XXX This should be unsigned byte
-
// 可以直接用 NULL 初始化 Texture
-
//void *data = (void *)malloc(pixelDataSize);
-
//memset(data, 0x00, pixelDataSize);
-
-
// Setup 6 texture units for blur effect
-
// Initialize texture data
-
for (int i = 0; i < 6; i++)
-
{
-
glActiveTexture(GL_TEXTURE1 + i);
-
glBindTexture(GL_TEXTURE_2D, blurTextures[i]);
-
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, NULL/*data*/);
-
}
-
-
// Alloc space for copying pixels so we dont call malloc on every draw
-
// 创建分配 PBO,并绑定为Pack Buffer,类型为GL_DYNAMIC_COPY
-
glGenBuffers(1, pixBuffObjs);
-
glBindBuffer(GL_PIXEL_PACK_BUFFER, pixBuffObjs[0]);
-
glBufferData(GL_PIXEL_PACK_BUFFER, pixelDataSize, pixelData, GL_DYNAMIC_COPY);
-
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
-
// ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
-
-
// Create geometry and a matrix for screen aligned drawing
-
gltGenerateOrtho2DMat(screenWidth, screenHeight, orthoMatrix, screenQuad);
-
-
// Make sure all went well
-
gltCheckErrors();
-
}
-
-
///
-
// Do your cleanup here. Free textures, display lists, buffer objects, etc.
-
void ShutdownRC(void)
-
{
-
// Make sure default FBO is bound
-
// 确保绑定默认的 FBO
-
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
-
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
-
-
// Cleanup textures
-
for (int i = 0; i < 7; i++)
-
{
-
glActiveTexture(GL_TEXTURE0 + i);
-
glBindTexture(GL_TEXTURE_2D, 0);
-
}
-
-
// Now delete detached textures
-
glDeleteTextures(1, textures);
-
glDeleteTextures(6, blurTextures);
-
-
// delete PBO
-
// ☆ 删除 PBO
-
glDeleteBuffers(1, pixBuffObjs);
-
}
-
-
///
-
// This is called at least once and before any rendering occurs. If the screen
-
// is a resizeable window, then this will also get called whenever the window
-
// is resized.
-
void ChangeSize(int nWidth, int nHeight)
-
{
-
glViewport(0, 0, nWidth, nHeight);
-
transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
-
viewFrustum.SetPerspective(35.0f, float(nWidth) / float(nHeight), 1.0f, 100.0f);
-
projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
-
modelViewMatrix.LoadIdentity();
-
-
// update screen sizes
-
screenWidth = nWidth;
-
screenHeight = nHeight;
-
-
// reset screen aligned quad
-
gltGenerateOrtho2DMat(screenWidth, screenHeight, orthoMatrix, screenQuad);
-
-
// ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
-
free(pixelData);
-
pixelDataSize = screenWidth * screenHeight * 3 * sizeof(unsigned int);
-
pixelData = (void *)malloc(pixelDataSize);
-
-
// Resize PBOs
-
// 如果窗口大小发生变化,则重新分配 PBO
-
glBindBuffer(GL_PIXEL_PACK_BUFFER, pixBuffObjs[0]);
-
glBufferData(GL_PIXEL_PACK_BUFFER, pixelDataSize, pixelData, GL_DYNAMIC_COPY);
-
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
-
// ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
-
gltCheckErrors();
-
}
-
-
-
///
-
// Update the camera based on user input, toggle display modes
-
//
-
void ProccessKeys(unsigned char key, int x, int y)
-
{
-
static CStopWatch cameraTimer;
-
float fTime = cameraTimer.GetElapsedSeconds();
-
float linear = fTime * 12.0f;
-
cameraTimer.Reset();
-
-
// Alternate between PBOs and local memory when 'P' is pressed
-
// 按 P键 切换 PBO和内存
-
if(key == 'P' || key == 'p')
-
bUsePBOPath = (bUsePBOPath) ? GL_FALSE : GL_TRUE;
-
-
// Speed up movement
-
if(key == '+')
-
{
-
speedFactor += linear / 2;
-
if(speedFactor > 6)
-
speedFactor = 6;
-
}
-
-
// Slow down moement
-
if(key == '-')
-
{
-
speedFactor -= linear / 2;
-
if(speedFactor < 0.5)
-
speedFactor = 0.5;
-
}
-
}
-
-
-
///
-
// Load and setup program for blur effect
-
//
-
-
void SetupBlurProg(void)
-
{
-
// Set the blur program as the current one
-
glUseProgram(blurProg);
-
-
// Set MVP matrix
-
glUniformMatrix4fv(glGetUniformLocation(blurProg, "mvpMatrix"), 1, GL_FALSE, transformPipeline.GetModelViewProjectionMatrix());
-
-
// Setup the textue units for the blur targets, these rotate every frame
-
glUniform1i(glGetUniformLocation(blurProg, "textureUnit0"), GetBlurTarget0());
-
glUniform1i(glGetUniformLocation(blurProg, "textureUnit1"), GetBlurTarget1());
-
glUniform1i(glGetUniformLocation(blurProg, "textureUnit2"), GetBlurTarget2());
-
glUniform1i(glGetUniformLocation(blurProg, "textureUnit3"), GetBlurTarget3());
-
glUniform1i(glGetUniformLocation(blurProg, "textureUnit4"), GetBlurTarget4());
-
glUniform1i(glGetUniformLocation(blurProg, "textureUnit5"), GetBlurTarget5());
-
}
-
-
-
///
-
// Draw the scene
-
//
-
void DrawWorld(GLfloat yRot, GLfloat xPos)
-
{
-
M3DMatrix44f mCamera;
-
modelViewMatrix.GetMatrix(mCamera);
-
-
// Need light position relative to the Camera
-
M3DVector4f vLightTransformed;
-
m3dTransformVector4(vLightTransformed, vLightPos, mCamera);
-
-
// Draw stuff relative to the camera
-
modelViewMatrix.PushMatrix();
-
modelViewMatrix.Translate(0.0f, 0.2f, -2.5f);
-
modelViewMatrix.Translate(xPos, 0.0f, 0.0f);
-
modelViewMatrix.Rotate(yRot, 0.0f, 1.0f, 0.0f);
-
-
shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF,
-
modelViewMatrix.GetMatrix(),
-
transformPipeline.GetProjectionMatrix(),
-
vLightTransformed, vGreen, 0);
-
torusBatch.Draw();
-
modelViewMatrix.PopMatrix();
-
}
-
-
-
///
-
// Render a frame. The owning framework is responsible for buffer swaps,
-
// flushes, etc.
-
void RenderScene(void)
-
{
-
static CStopWatch animationTimer;
-
static float totalTime = 6; // To go back and forth
-
static float halfTotalTime = totalTime / 2;
-
float seconds = animationTimer.GetElapsedSeconds() * speedFactor;
-
float xPos = 0;
-
-
// Calculate the next postion of the moving object
-
// First perform a mod-like operation on the time as a float
-
while(seconds > totalTime)
-
seconds -= totalTime;
-
-
// Move object position, if it's gone half way across
-
// start bringing it back
-
if(seconds < halfTotalTime)
-
xPos = seconds - halfTotalTime * 0.5f;
-
else
-
xPos = totalTime - seconds - halfTotalTime * 0.5f;
-
-
// First draw world to screen
-
modelViewMatrix.PushMatrix();
-
M3DMatrix44f mCamera;
-
cameraFrame.GetCameraMatrix(mCamera);
-
modelViewMatrix.MultMatrix(mCamera);
-
-
glActiveTexture(GL_TEXTURE0);
-
glBindTexture(GL_TEXTURE_2D, textures[0]); // Marble
-
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
shaderManager.UseStockShader(GLT_SHADER_TEXTURE_MODULATE, transformPipeline.GetModelViewProjectionMatrix(), vWhite, 0);
-
-
floorBatch.Draw();
-
DrawWorld(0.0f, xPos);
-
modelViewMatrix.PopMatrix();
-
-
if(bUsePBOPath)
-
{
-
// First bind the PBO as the pack buffer, then read the pixels directly to the PBO
-
// ☆ 首先绑定 PBO 为 Pack Buffer,再直接从 Frame Buffer 中读取像素到 PBO ☆
-
glBindBuffer(GL_PIXEL_PACK_BUFFER, pixBuffObjs[0]);
-
glReadPixels(0, 0, screenWidth, screenHeight, GL_RGB, GL_UNSIGNED_BYTE, NULL);
-
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); // 解绑 PBO
-
-
// Next bind the PBO as the unpack buffer, then push the pixels straight into the texture
-
// ☆ 接着绑定 PBO 为 Unpack Buffer,再把 PBO 中的像素直接推送到纹理当中 ☆
-
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pixBuffObjs[0]);
-
-
// Setup texture unit for new blur, this gets imcremented every frame
-
glActiveTexture(GL_TEXTURE0 + GetBlurTarget0() );
-
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, screenWidth, screenHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
-
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); // 解绑 PBO
-
}
-
else
-
{
-
// Grab the screen pixels and copy into local memory
-
// 从FrameBuffer中获取屏幕像素,并拷贝到客户端内存中
-
glReadPixels(0, 0, screenWidth, screenHeight, GL_RGB, GL_UNSIGNED_BYTE, pixelData);
-
-
// Push pixels from client memory into texture
-
// Setup texture unit for new blur, this gets imcremented every frame
-
// 推送客户端内存中的像素到纹理中
-
glActiveTexture(GL_TEXTURE0 + GetBlurTarget0() );
-
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, screenWidth, screenHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, pixelData);
-
}
-
-
// Draw full screen quad with blur shader and all blur textures
-
projectionMatrix.PushMatrix();
-
projectionMatrix.LoadIdentity();
-
projectionMatrix.LoadMatrix(orthoMatrix);
-
modelViewMatrix.PushMatrix();
-
modelViewMatrix.LoadIdentity();
-
glDisable(GL_DEPTH_TEST);
-
SetupBlurProg();
-
screenQuad.Draw();
-
glEnable(GL_DEPTH_TEST);
-
modelViewMatrix.PopMatrix();
-
projectionMatrix.PopMatrix();
-
-
// Move to the next blur texture for the next frame
-
AdvanceBlurTaget();
-
-
// Do the buffer Swap
-
glutSwapBuffers();
-
-
// Do it again
-
glutPostRedisplay();
-
-
UpdateFrameCount();
-
}
-
-
-
int main(int argc, char *argv[])
-
{
-
screenWidth = 800;
-
screenHeight = 600;
-
bFullScreen = false;
-
bAnimated = true;
-
bUsePBOPath = false; // true
-
blurProg = 0;
-
speedFactor = 1.0f;
-
-
gltSetWorkingDirectory(argv[0]);
-
-
glutInit(&argc, argv);
-
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
-
glutInitWindowSize(screenWidth, screenHeight);
-
-
glutCreateWindow("Pix Buffs");
-
-
glutReshapeFunc(ChangeSize);
-
glutDisplayFunc(RenderScene);
-
glutKeyboardFunc(ProccessKeys);
-
-
SetupRC();
-
glutMainLoop();
-
ShutdownRC();
-
-
return 0;
-
}
执行效果图:
相关阅读:OpenGL深入探索——像素缓冲区对象 (PBO)
文章来源: panda1234lee.blog.csdn.net,作者:panda1234lee,版权归原作者所有,如需转载,请联系作者。
原文链接:panda1234lee.blog.csdn.net/article/details/53248556
【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)