这是书中第八章的最后一节内容,在我机制的简化问题后,写出了想要的效果.应用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; }