《OpenGL 超级宝典(Super Bible)第五版》 有关 PBO 的 Example

举报
ShaderJoy 发表于 2021/12/29 23:39:20 2021/12/29
【摘要】 代码即关键注释如下: 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...


代码即关键注释如下:


  
  1. static GLfloat vGreen[] = { 0.0f, 1.0f, 0.0f, 1.0f };
  2. static GLfloat vWhite[] = { 1.0f, 1.0f, 1.0f, 1.0f };
  3. static GLfloat vLightPos[] = { 0.0f, 3.0f, 0.0f, 1.0f };
  4. GLsizei screenWidth; // Desired window or desktop width
  5. GLsizei screenHeight; // Desired window or desktop height
  6. GLboolean bFullScreen; // Request to run full screen
  7. GLboolean bAnimated; // Request for continual updates
  8. GLShaderManager shaderManager; // Shader Manager
  9. GLMatrixStack modelViewMatrix; // Modelview Matrix
  10. GLMatrixStack projectionMatrix; // Projection Matrix
  11. M3DMatrix44f orthoMatrix;
  12. GLFrustum viewFrustum; // View Frustum
  13. GLGeometryTransform transformPipeline; // Geometry Transform Pipeline
  14. GLFrame cameraFrame; // Camera frame
  15. GLTriangleBatch torusBatch;
  16. GLBatch floorBatch;
  17. GLBatch screenQuad;
  18. GLuint textures[1];
  19. GLuint blurTextures[6];
  20. GLuint pixBuffObjs[1];
  21. GLuint curBlurTarget;
  22. bool bUsePBOPath;
  23. GLfloat speedFactor;
  24. GLuint blurProg;
  25. void *pixelData;
  26. GLuint pixelDataSize;
  27. //void MoveCamera(void);
  28. void DrawWorld(GLfloat yRot, GLfloat xPos);
  29. bool LoadBMPTexture(const char *szFileName, GLenum minFilter, GLenum magFilter, GLenum wrapMode);
  30. void SetupBlurProg(void);
  31. // returns 1 - 6 for blur texture units
  32. // curPixBuf is always between 0 and 5
  33. void AdvanceBlurTaget()
  34. {
  35. curBlurTarget = ((curBlurTarget + 1) % 6);
  36. }
  37. GLuint GetBlurTarget0()
  38. {
  39. return (1 + ((curBlurTarget + 5) % 6));
  40. }
  41. GLuint GetBlurTarget1()
  42. {
  43. return (1 + ((curBlurTarget + 4) % 6));
  44. }
  45. GLuint GetBlurTarget2()
  46. {
  47. return (1 + ((curBlurTarget + 3) % 6));
  48. }
  49. GLuint GetBlurTarget3()
  50. {
  51. return (1 + ((curBlurTarget + 2) % 6));
  52. }
  53. GLuint GetBlurTarget4()
  54. {
  55. return (1 + ((curBlurTarget + 1) % 6));
  56. }
  57. GLuint GetBlurTarget5()
  58. {
  59. return (1 + ((curBlurTarget) % 6));
  60. }
  61. void UpdateFrameCount()
  62. {
  63. static int iFrames = 0; // Frame count
  64. static CStopWatch frameTimer; // Render time
  65. // Reset the stopwatch on first time
  66. if(iFrames == 0)
  67. {
  68. frameTimer.Reset();
  69. iFrames++;
  70. }
  71. // Increment the frame count
  72. iFrames++;
  73. // Do periodic frame rate calculation
  74. if (iFrames == 101)
  75. {
  76. float fps;
  77. fps = 100.0f / frameTimer.GetElapsedSeconds();
  78. if (bUsePBOPath)
  79. printf("Pix_buffs - Using PBOs %.1f fps\n", fps);
  80. else
  81. printf("Pix_buffs - Using Client mem copies %.1f fps\n", fps);
  82. frameTimer.Reset();
  83. iFrames = 1;
  84. }
  85. }
  86. ///
  87. // Load in a BMP file as a texture. Allows specification of the filters and the wrap mode
  88. bool LoadBMPTexture(const char *szFileName, GLenum minFilter, GLenum magFilter, GLenum wrapMode)
  89. {
  90. GLbyte *pBits;
  91. GLint iWidth, iHeight;
  92. pBits = gltReadBMPBits(szFileName, &iWidth, &iHeight);
  93. if(pBits == NULL)
  94. return false;
  95. // Set Wrap modes
  96. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode);
  97. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode);
  98. // Do I need to generate mipmaps?
  99. if(minFilter == GL_LINEAR_MIPMAP_LINEAR || minFilter == GL_LINEAR_MIPMAP_NEAREST || minFilter == GL_NEAREST_MIPMAP_LINEAR || minFilter == GL_NEAREST_MIPMAP_NEAREST)
  100. glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
  101. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
  102. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
  103. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, iWidth, iHeight, 0, GL_BGR, GL_UNSIGNED_BYTE, pBits);
  104. return true;
  105. }
  106. ///
  107. // OpenGL related startup code is safe to put here. Load textures, etc.
  108. void SetupRC(void)
  109. {
  110. GLenum err = glewInit();
  111. if (GLEW_OK != err)
  112. {
  113. /* Problem: glewInit failed, something is seriously wrong. */
  114. fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
  115. }
  116. // Initialze Shader Manager
  117. shaderManager.InitializeStockShaders();
  118. glEnable(GL_DEPTH_TEST);
  119. // Black
  120. glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
  121. gltMakeTorus(torusBatch, 0.4f, 0.15f, 35, 35);
  122. GLfloat alpha = 0.25f;
  123. floorBatch.Begin(GL_TRIANGLE_FAN, 4, 1);
  124. floorBatch.Color4f(0.0f, 1.0f, 0.0f, alpha);
  125. floorBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
  126. floorBatch.Normal3f(0.0, 1.0f, 0.0f);
  127. floorBatch.Vertex3f(-20.0f, -0.41f, 20.0f);
  128. floorBatch.Color4f(0.0f, 1.0f, 0.0f, alpha);
  129. floorBatch.MultiTexCoord2f(0, 10.0f, 0.0f);
  130. floorBatch.Normal3f(0.0, 1.0f, 0.0f);
  131. floorBatch.Vertex3f(20.0f, -0.41f, 20.0f);
  132. floorBatch.Color4f(0.0f, 1.0f, 0.0f, alpha);
  133. floorBatch.MultiTexCoord2f(0, 10.0f, 10.0f);
  134. floorBatch.Normal3f(0.0, 1.0f, 0.0f);
  135. floorBatch.Vertex3f(20.0f, -0.41f, -20.0f);
  136. floorBatch.Color4f(0.0f, 1.0f, 0.0f, alpha);
  137. floorBatch.MultiTexCoord2f(0, 0.0f, 10.0f);
  138. floorBatch.Normal3f(0.0, 1.0f, 0.0f);
  139. floorBatch.Vertex3f(-20.0f, -0.41f, -20.0f);
  140. floorBatch.End();
  141. glGenTextures(1, textures);
  142. glBindTexture(GL_TEXTURE_2D, textures[0]);
  143. LoadBMPTexture("marble.bmp", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_REPEAT);
  144. // Create blur program
  145. blurProg = gltLoadShaderPairWithAttributes("blur.vs", "blur.fs", 2,
  146. GLT_ATTRIBUTE_VERTEX, "vVertex", GLT_ATTRIBUTE_TEXTURE0, "texCoord0");
  147. // Create blur textures
  148. glGenTextures(6, blurTextures);
  149. // ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
  150. // XXX I don't think this is necessary. Should set texture data to NULL
  151. // Allocate a pixel buffer to initialize textures and PBOs
  152. // 计算 像素数据的字节数
  153. pixelDataSize = screenWidth * screenHeight * 3 * sizeof(unsigned int); // XXX This should be unsigned byte
  154. // 可以直接用 NULL 初始化 Texture
  155. //void *data = (void *)malloc(pixelDataSize);
  156. //memset(data, 0x00, pixelDataSize);
  157. // Setup 6 texture units for blur effect
  158. // Initialize texture data
  159. for (int i = 0; i < 6; i++)
  160. {
  161. glActiveTexture(GL_TEXTURE1 + i);
  162. glBindTexture(GL_TEXTURE_2D, blurTextures[i]);
  163. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  164. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  165. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  166. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  167. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, screenWidth, screenHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL/*data*/);
  168. }
  169. // Alloc space for copying pixels so we dont call malloc on every draw
  170. // 创建分配 PBO,并绑定为Pack Buffer,类型为GL_DYNAMIC_COPY
  171. glGenBuffers(1, pixBuffObjs);
  172. glBindBuffer(GL_PIXEL_PACK_BUFFER, pixBuffObjs[0]);
  173. glBufferData(GL_PIXEL_PACK_BUFFER, pixelDataSize, pixelData, GL_DYNAMIC_COPY);
  174. glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
  175. // ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
  176. // Create geometry and a matrix for screen aligned drawing
  177. gltGenerateOrtho2DMat(screenWidth, screenHeight, orthoMatrix, screenQuad);
  178. // Make sure all went well
  179. gltCheckErrors();
  180. }
  181. ///
  182. // Do your cleanup here. Free textures, display lists, buffer objects, etc.
  183. void ShutdownRC(void)
  184. {
  185. // Make sure default FBO is bound
  186. // 确保绑定默认的 FBO
  187. glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
  188. glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
  189. // Cleanup textures
  190. for (int i = 0; i < 7; i++)
  191. {
  192. glActiveTexture(GL_TEXTURE0 + i);
  193. glBindTexture(GL_TEXTURE_2D, 0);
  194. }
  195. // Now delete detached textures
  196. glDeleteTextures(1, textures);
  197. glDeleteTextures(6, blurTextures);
  198. // delete PBO
  199. // ☆ 删除 PBO
  200. glDeleteBuffers(1, pixBuffObjs);
  201. }
  202. ///
  203. // This is called at least once and before any rendering occurs. If the screen
  204. // is a resizeable window, then this will also get called whenever the window
  205. // is resized.
  206. void ChangeSize(int nWidth, int nHeight)
  207. {
  208. glViewport(0, 0, nWidth, nHeight);
  209. transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
  210. viewFrustum.SetPerspective(35.0f, float(nWidth) / float(nHeight), 1.0f, 100.0f);
  211. projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
  212. modelViewMatrix.LoadIdentity();
  213. // update screen sizes
  214. screenWidth = nWidth;
  215. screenHeight = nHeight;
  216. // reset screen aligned quad
  217. gltGenerateOrtho2DMat(screenWidth, screenHeight, orthoMatrix, screenQuad);
  218. // ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
  219. free(pixelData);
  220. pixelDataSize = screenWidth * screenHeight * 3 * sizeof(unsigned int);
  221. pixelData = (void *)malloc(pixelDataSize);
  222. // Resize PBOs
  223. // 如果窗口大小发生变化,则重新分配 PBO
  224. glBindBuffer(GL_PIXEL_PACK_BUFFER, pixBuffObjs[0]);
  225. glBufferData(GL_PIXEL_PACK_BUFFER, pixelDataSize, pixelData, GL_DYNAMIC_COPY);
  226. glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
  227. // ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
  228. gltCheckErrors();
  229. }
  230. ///
  231. // Update the camera based on user input, toggle display modes
  232. //
  233. void ProccessKeys(unsigned char key, int x, int y)
  234. {
  235. static CStopWatch cameraTimer;
  236. float fTime = cameraTimer.GetElapsedSeconds();
  237. float linear = fTime * 12.0f;
  238. cameraTimer.Reset();
  239. // Alternate between PBOs and local memory when 'P' is pressed
  240. // 按 P键 切换 PBO和内存
  241. if(key == 'P' || key == 'p')
  242. bUsePBOPath = (bUsePBOPath) ? GL_FALSE : GL_TRUE;
  243. // Speed up movement
  244. if(key == '+')
  245. {
  246. speedFactor += linear / 2;
  247. if(speedFactor > 6)
  248. speedFactor = 6;
  249. }
  250. // Slow down moement
  251. if(key == '-')
  252. {
  253. speedFactor -= linear / 2;
  254. if(speedFactor < 0.5)
  255. speedFactor = 0.5;
  256. }
  257. }
  258. ///
  259. // Load and setup program for blur effect
  260. //
  261. void SetupBlurProg(void)
  262. {
  263. // Set the blur program as the current one
  264. glUseProgram(blurProg);
  265. // Set MVP matrix
  266. glUniformMatrix4fv(glGetUniformLocation(blurProg, "mvpMatrix"), 1, GL_FALSE, transformPipeline.GetModelViewProjectionMatrix());
  267. // Setup the textue units for the blur targets, these rotate every frame
  268. glUniform1i(glGetUniformLocation(blurProg, "textureUnit0"), GetBlurTarget0());
  269. glUniform1i(glGetUniformLocation(blurProg, "textureUnit1"), GetBlurTarget1());
  270. glUniform1i(glGetUniformLocation(blurProg, "textureUnit2"), GetBlurTarget2());
  271. glUniform1i(glGetUniformLocation(blurProg, "textureUnit3"), GetBlurTarget3());
  272. glUniform1i(glGetUniformLocation(blurProg, "textureUnit4"), GetBlurTarget4());
  273. glUniform1i(glGetUniformLocation(blurProg, "textureUnit5"), GetBlurTarget5());
  274. }
  275. ///
  276. // Draw the scene
  277. //
  278. void DrawWorld(GLfloat yRot, GLfloat xPos)
  279. {
  280. M3DMatrix44f mCamera;
  281. modelViewMatrix.GetMatrix(mCamera);
  282. // Need light position relative to the Camera
  283. M3DVector4f vLightTransformed;
  284. m3dTransformVector4(vLightTransformed, vLightPos, mCamera);
  285. // Draw stuff relative to the camera
  286. modelViewMatrix.PushMatrix();
  287. modelViewMatrix.Translate(0.0f, 0.2f, -2.5f);
  288. modelViewMatrix.Translate(xPos, 0.0f, 0.0f);
  289. modelViewMatrix.Rotate(yRot, 0.0f, 1.0f, 0.0f);
  290. shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF,
  291. modelViewMatrix.GetMatrix(),
  292. transformPipeline.GetProjectionMatrix(),
  293. vLightTransformed, vGreen, 0);
  294. torusBatch.Draw();
  295. modelViewMatrix.PopMatrix();
  296. }
  297. ///
  298. // Render a frame. The owning framework is responsible for buffer swaps,
  299. // flushes, etc.
  300. void RenderScene(void)
  301. {
  302. static CStopWatch animationTimer;
  303. static float totalTime = 6; // To go back and forth
  304. static float halfTotalTime = totalTime / 2;
  305. float seconds = animationTimer.GetElapsedSeconds() * speedFactor;
  306. float xPos = 0;
  307. // Calculate the next postion of the moving object
  308. // First perform a mod-like operation on the time as a float
  309. while(seconds > totalTime)
  310. seconds -= totalTime;
  311. // Move object position, if it's gone half way across
  312. // start bringing it back
  313. if(seconds < halfTotalTime)
  314. xPos = seconds - halfTotalTime * 0.5f;
  315. else
  316. xPos = totalTime - seconds - halfTotalTime * 0.5f;
  317. // First draw world to screen
  318. modelViewMatrix.PushMatrix();
  319. M3DMatrix44f mCamera;
  320. cameraFrame.GetCameraMatrix(mCamera);
  321. modelViewMatrix.MultMatrix(mCamera);
  322. glActiveTexture(GL_TEXTURE0);
  323. glBindTexture(GL_TEXTURE_2D, textures[0]); // Marble
  324. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  325. shaderManager.UseStockShader(GLT_SHADER_TEXTURE_MODULATE, transformPipeline.GetModelViewProjectionMatrix(), vWhite, 0);
  326. floorBatch.Draw();
  327. DrawWorld(0.0f, xPos);
  328. modelViewMatrix.PopMatrix();
  329. if(bUsePBOPath)
  330. {
  331. // First bind the PBO as the pack buffer, then read the pixels directly to the PBO
  332. // ☆ 首先绑定 PBO 为 Pack Buffer,再直接从 Frame Buffer 中读取像素到 PBO ☆
  333. glBindBuffer(GL_PIXEL_PACK_BUFFER, pixBuffObjs[0]);
  334. glReadPixels(0, 0, screenWidth, screenHeight, GL_RGB, GL_UNSIGNED_BYTE, NULL);
  335. glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); // 解绑 PBO
  336. // Next bind the PBO as the unpack buffer, then push the pixels straight into the texture
  337. // ☆ 接着绑定 PBO 为 Unpack Buffer,再把 PBO 中的像素直接推送到纹理当中 ☆
  338. glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pixBuffObjs[0]);
  339. // Setup texture unit for new blur, this gets imcremented every frame
  340. glActiveTexture(GL_TEXTURE0 + GetBlurTarget0() );
  341. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, screenWidth, screenHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
  342. glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); // 解绑 PBO
  343. }
  344. else
  345. {
  346. // Grab the screen pixels and copy into local memory
  347. // 从FrameBuffer中获取屏幕像素,并拷贝到客户端内存中
  348. glReadPixels(0, 0, screenWidth, screenHeight, GL_RGB, GL_UNSIGNED_BYTE, pixelData);
  349. // Push pixels from client memory into texture
  350. // Setup texture unit for new blur, this gets imcremented every frame
  351. // 推送客户端内存中的像素到纹理中
  352. glActiveTexture(GL_TEXTURE0 + GetBlurTarget0() );
  353. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, screenWidth, screenHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, pixelData);
  354. }
  355. // Draw full screen quad with blur shader and all blur textures
  356. projectionMatrix.PushMatrix();
  357. projectionMatrix.LoadIdentity();
  358. projectionMatrix.LoadMatrix(orthoMatrix);
  359. modelViewMatrix.PushMatrix();
  360. modelViewMatrix.LoadIdentity();
  361. glDisable(GL_DEPTH_TEST);
  362. SetupBlurProg();
  363. screenQuad.Draw();
  364. glEnable(GL_DEPTH_TEST);
  365. modelViewMatrix.PopMatrix();
  366. projectionMatrix.PopMatrix();
  367. // Move to the next blur texture for the next frame
  368. AdvanceBlurTaget();
  369. // Do the buffer Swap
  370. glutSwapBuffers();
  371. // Do it again
  372. glutPostRedisplay();
  373. UpdateFrameCount();
  374. }
  375. int main(int argc, char *argv[])
  376. {
  377. screenWidth = 800;
  378. screenHeight = 600;
  379. bFullScreen = false;
  380. bAnimated = true;
  381. bUsePBOPath = false; // true
  382. blurProg = 0;
  383. speedFactor = 1.0f;
  384. gltSetWorkingDirectory(argv[0]);
  385. glutInit(&argc, argv);
  386. glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
  387. glutInitWindowSize(screenWidth, screenHeight);
  388. glutCreateWindow("Pix Buffs");
  389. glutReshapeFunc(ChangeSize);
  390. glutDisplayFunc(RenderScene);
  391. glutKeyboardFunc(ProccessKeys);
  392. SetupRC();
  393. glutMainLoop();
  394. ShutdownRC();
  395. return 0;
  396. }



执行效果图:




相关阅读:OpenGL深入探索——像素缓冲区对象 (PBO)

























文章来源: panda1234lee.blog.csdn.net,作者:panda1234lee,版权归原作者所有,如需转载,请联系作者。

原文链接:panda1234lee.blog.csdn.net/article/details/53248556

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。