帧缓冲区对象,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;
}