帧缓冲区对象,Frame Buffer Object.创建渲染缓冲区,将渲染管线的输出可指定到渲染缓冲区,同时可以读渲染缓冲区.这些都是通过绑定帧缓冲区来做的.代码中将颜色输出分别写到两个渲染缓冲区中,再将这两个缓冲区的内容分别写到默认帧缓冲区中,效果就是左右颜色明暗不一样.书上的代码很复杂,我又实现了一个简单版的.加油吧,抓紧学习渲染,目前的进度比自己预想的慢太多太多了.
// FrameBufferObject.cpp - 2013/09/28 - 20:35 #include "stdafx.h" #include <GLTools.h> #include <GLShaderManager.h> #include <GLFrustum.h> #include <GLBatch.h> #include <GLMatrixStack.h> #include <GLGeometryTransform.h> #include <StopWatch.h> #define FREEGLUT_STATIC #include <GL/glut.h> GLenum frameBufferObjectBuffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1,} ; GLuint frameBufferObjectName ; GLuint renderBufferNames[2] ; GLFrame viewFrame; GLFrustum viewFrustum; GLTriangleBatch sphereBatch; GLMatrixStack modelViewMatrix; GLMatrixStack projectionMatrix; GLGeometryTransform transformPipeline; GLShaderManager shaderManager; GLuint ADSLightShader; GLint locAmbient; GLint locDiffuse; GLint locSpecular; GLint locLight; GLint locMVP; GLint locMV; GLint locNM; GLfloat vEyeLight[] = { -100.0f, 100.0f, 100.0f }; GLfloat vAmbientColor[] = { 0.1f, 0.1f, 0.1f, 1.0f }; GLfloat vDiffuseColor[] = { 0.0f, 0.0f, 1.0f, 1.0f }; GLfloat vSpecularColor[] = { 1.0f, 1.0f, 1.0f, 1.0f }; GLint screenWidth ; GLint screenHeight ; void SetupRC(void) { glClearColor(0.0f, 0.0f, 0.0f, 1.0f ); glEnable(GL_DEPTH_TEST | GL_CULL_FACE); shaderManager.InitializeStockShaders(); viewFrame.MoveForward(4.0f); gltMakeSphere(sphereBatch, 1.0f, 26, 13); ADSLightShader = shaderManager.LoadShaderPairWithAttributes( "ADSGouraud.vp", "ADSGouraud.fp", 2, GLT_ATTRIBUTE_VERTEX, "vVertex", GLT_ATTRIBUTE_NORMAL, "vNormal") ; locAmbient = glGetUniformLocation(ADSLightShader, "ambientColor"); locDiffuse = glGetUniformLocation(ADSLightShader, "diffuseColor"); locSpecular = glGetUniformLocation(ADSLightShader, "specularColor"); locLight = glGetUniformLocation(ADSLightShader, "vLightPosition"); locMVP = glGetUniformLocation(ADSLightShader, "mvpMatrix"); locMV = glGetUniformLocation(ADSLightShader, "mvMatrix"); locNM = glGetUniformLocation(ADSLightShader, "normalMatrix"); glLinkProgram(ADSLightShader) ; glGenFramebuffers(1, &frameBufferObjectName) ; glGenRenderbuffers(2, renderBufferNames) ; glBindRenderbuffer(GL_RENDERBUFFER, renderBufferNames[0]) ; glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, screenWidth, screenHeight) ; glBindRenderbuffer(GL_RENDERBUFFER, renderBufferNames[1]) ; glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, screenWidth, screenHeight) ; glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBufferObjectName) ; glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderBufferNames[0]) ; glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, renderBufferNames[1]) ; glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0) ; } void ShutdownRC(void) { glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0) ; glBindFramebuffer(GL_READ_FRAMEBUFFER, 0) ; glDeleteRenderbuffers(2, renderBufferNames) ; glDeleteFramebuffers(1, &frameBufferObjectName) ; glUseProgram(0) ; glDeleteProgram(ADSLightShader) ; } void ChangeSize(int w, int h) { if(h == 0) h = 1; 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); screenWidth = w ; screenHeight = h ; glBindRenderbuffer(GL_RENDERBUFFER, renderBufferNames[0]); glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, screenWidth, screenHeight); glBindRenderbuffer(GL_RENDERBUFFER, renderBufferNames[1]); glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, screenWidth, screenHeight); glBindRenderbuffer(GL_RENDERBUFFER, renderBufferNames[2]); glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, screenWidth, screenHeight); } void RenderScene(void) { static CStopWatch rotTimer; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); modelViewMatrix.PushMatrix(viewFrame); modelViewMatrix.Rotate(rotTimer.GetElapsedSeconds() * 10.0f, 0.0f, 1.0f, 0.0f); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBufferObjectName) ; glDrawBuffers(2, frameBufferObjectBuffers) ; glUseProgram(ADSLightShader); glUniform4fv(locAmbient, 1, vAmbientColor); glUniform4fv(locDiffuse, 1, vDiffuseColor); glUniform4fv(locSpecular, 1, vSpecularColor); glUniform3fv(locLight, 1, vEyeLight); glUniformMatrix4fv(locMVP, 1, GL_FALSE, transformPipeline.GetModelViewProjectionMatrix()); glUniformMatrix4fv(locMV, 1, GL_FALSE, transformPipeline.GetModelViewMatrix()); glUniformMatrix3fv(locNM, 1, GL_FALSE, transformPipeline.GetNormalMatrix()); sphereBatch.Draw(); modelViewMatrix.PopMatrix(); glBindFramebuffer(GL_READ_FRAMEBUFFER, frameBufferObjectName) ; glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0) ; glReadBuffer(GL_COLOR_ATTACHMENT0) ; glBlitFramebuffer( 0, 0, screenWidth / 2, screenHeight, 0, 0, screenWidth / 2, screenHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST) ; glReadBuffer(GL_COLOR_ATTACHMENT1) ; glBlitFramebuffer( screenWidth / 2, 0, screenWidth, screenHeight, screenWidth / 2, 0, screenWidth, screenHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST) ; glutSwapBuffers(); glutPostRedisplay(); } int main(int argc, char* argv[]) { gltSetWorkingDirectory(argv[0]); glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH); glutInitWindowSize(800, 600); glutCreateWindow("Frame 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; }