这是书中第八章的最后一节内容,在我机制的简化问题后,写出了想要的效果.应用FBO渲染到纹理,可以直接用.这个用来实现镜面效果什么的,好啊.再一个,貌似我现在已经可以去写延迟渲染流水线了,那个用到多渲染目标,之后再处理.呼,继续学习吧,这些东西还真得实践才行啊.
// RenderToTexture.cpp -- 2013/10/11-20:49
#include "stdafx.h"
#include <iostream>
#include <GLTools.h>
#include <GLShaderManager.h>
#define FREEGLUT_STATIC
#include <GL/glut.h>
GLBatch triangleBatch;
GLBatch texturedTriangleBatch ;
GLShaderManager shaderManager;
GLint triangleShader ;
GLint texturedTriangleShader ;
GLuint fboName ;
GLuint generatedTexutre ;
GLenum windowBuffer[] = {GL_BACK_LEFT,} ;
GLenum fboBuffers[] = {GL_COLOR_ATTACHMENT0,} ;
GLsizei const generatedTextureWidth = 400 ;
GLsizei const generatedTextureHeight = 300 ;
GLint screenWidth = 800 ;
GLint screenHeight = 600 ;
void ShutdownRC(void)
{
glDeleteProgram(triangleShader) ;
glDeleteProgram(texturedTriangleShader) ;
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0) ;
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0) ;
glActiveTexture(GL_TEXTURE0) ;
glBindTexture(GL_TEXTURE_2D, 0) ;
glDeleteTextures(1, &generatedTexutre) ;
glDeleteFramebuffers(1, &fboName) ;
}
void ChangeSize(int w, int h)
{
glViewport(0, 0, w, h);
screenWidth = w ;
screenHeight = h ;
}
void SetupRC()
{
shaderManager.InitializeStockShaders();
triangleShader = shaderManager.LoadShaderPairWithAttributes(
"triangle.vp", "triangle.fp",
1,
GLT_ATTRIBUTE_VERTEX, "vVertex") ;
texturedTriangleShader = shaderManager.LoadShaderPairWithAttributes(
"texturedTriangle.vp", "texturedTriangle.fp",
2,
GLT_ATTRIBUTE_VERTEX, "vVertex",
GLT_ATTRIBUTE_TEXTURE0, "vTexCoords") ;
GLfloat vVerts[] = {
-0.5f, 0.0f, 0.0f,
0.5f, 0.0f, 0.0f,
0.0f, 0.5f, 0.0f };
GLfloat vTexCoords[] = {
0, 0,
1.0f, 0,
0.5f, 1.0f,
} ;
triangleBatch.Begin(GL_TRIANGLES, 3);
triangleBatch.CopyVertexData3f(vVerts);
triangleBatch.End();
texturedTriangleBatch.Begin(GL_TRIANGLES, 3, 1) ;
texturedTriangleBatch.CopyVertexData3f(vVerts) ;
texturedTriangleBatch.CopyTexCoordData2f(vTexCoords, 0) ;
texturedTriangleBatch.End();
glGenFramebuffers(1, &fboName) ;
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboName) ;
glGenTextures(1, &generatedTexutre) ;
glBindTexture(GL_TEXTURE_2D, generatedTexutre) ;
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
glGenerateMipmap(GL_TEXTURE_2D);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, generatedTextureWidth, generatedTextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, generatedTexutre, 0) ;
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0) ;
}
void RenderScene(void)
{
// 先以黑底画红色三角形到纹理中
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0, 0, 0, 1.0f);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboName) ;
glDrawBuffers(1, fboBuffers) ;
glViewport(0, 0, generatedTextureWidth, generatedTextureHeight) ;
glUseProgram(triangleShader) ;
GLint iColorLocation = glGetUniformLocation(triangleShader, "vColor") ;
GLfloat vColor[] = { 1.0f, 0.0f, 0.0f, 1.0f };
glUniform4fv(iColorLocation, 1, vColor) ;
triangleBatch.Draw();
// 再以白底将刚生成的纹理贴到三角形上画出来,汉字好难组织说啊...
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0) ;
glDrawBuffers(1, windowBuffer) ;
glViewport(0, 0, screenWidth, screenHeight) ;
glUseProgram(texturedTriangleShader) ;
glBindTexture(GL_TEXTURE_2D, generatedTexutre) ;
GLint iTextureUniform = glGetUniformLocation(texturedTriangleShader, "colorMap") ;
glUniform1i(iTextureUniform, 0) ;
texturedTriangleBatch.Draw() ;
glutSwapBuffers();
}
int main(int argc, char* argv[])
{
gltSetWorkingDirectory(argv[0]);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowSize(screenWidth, screenHeight);
glutCreateWindow("Render To Texture");
glutReshapeFunc(ChangeSize);
glutDisplayFunc(RenderScene);
GLenum err = glewInit();
if (err != GLEW_OK)
{
fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
return 1;
}
SetupRC();
glutMainLoop();
return 0;
}