FrameBufferObject.cpp

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


 

你可能感兴趣的:(FrameBufferObject.cpp)