代码参考1:https://github.com/wld0595/FBO
// Include standard headers
#include
// Include GLEW
#include
// Include GLFW
#include
GLFWwindow* window;
#include
#define STB_IMAGE_IMPLEMENTATION
#include
typedef struct
{
GLfloat x;
GLfloat y;
GLfloat z;
GLfloat u;
GLfloat v;
}Vertex;
int main( void )
{
if( !glfwInit() )
{
fprintf( stderr, "Failed to initialize GLFW.\n" );
getchar();
return -1;
}
glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
window = glfwCreateWindow( 1024, 768, "Render To Texture", NULL, NULL);
if( window == NULL )
{
fprintf( stderr, "Failed to open GLFW window.\n" );
getchar();
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
int windowWidth,windowHeight;
glfwGetWindowSize(window,&windowWidth,&windowHeight);
glfwGetFramebufferSize(window, &windowWidth, &windowHeight);
glewExperimental = true;
if (glewInit() != GLEW_OK)
{
fprintf(stderr, "Failed to initialize GLEW\n");
getchar();
glfwTerminate();
return -1;
}
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
glEnable(GL_TEXTURE_2D);
//vertex data
Vertex g_VertexBufferDataQ[]={
{-1.0,1.0,0.0, 0.0,1.0},
{1.0,1.0,0.0, 1.0,1.0},
{-1.0,-1.0,0.0, 0.0,0.0},
{1.0,-1.0,0.0, 1.0,0.0},
};
Vertex g_VertexBufferDataT[]={
{-1.0,-1.0,0.0, 0.0,0.0},
{1.0,-1.0,0.0, 0.0,0.0},
{0.0,1.0,0.0, 0.0,0.0},
};
GLuint VertexArrayID;
//===Generate the vertex array
glGenVertexArrays(1,&VertexArrayID);
glBindVertexArray(VertexArrayID);
GLuint VertexBufferQ;
glGenBuffers(1,&VertexBufferQ);
glBindBuffer(GL_ARRAY_BUFFER,VertexBufferQ);
glBufferData(GL_ARRAY_BUFFER,sizeof(g_VertexBufferDataQ),g_VertexBufferDataQ,GL_STATIC_DRAW);
GLuint VertexBufferT;
glGenBuffers(1,&VertexBufferT);
glBindBuffer(GL_ARRAY_BUFFER,VertexBufferT);
glBufferData(GL_ARRAY_BUFFER,sizeof(g_VertexBufferDataT),g_VertexBufferDataT,GL_STATIC_DRAW);
GLuint ProgramIDT = LoadShaders("VertexShaderT.vertexshader","FragmentShaderT.fragmentshader");
GLint VertexPositionIDT=glGetAttribLocation(ProgramIDT,"vertexPosition_modelspace");
GLuint ProgramIDQ = LoadShaders("VertexShaderQ.vertexshader","FragmentShaderQ.fragmentshader");
GLint VertexPositionIDQ=glGetAttribLocation(ProgramIDQ,"vertexPosition_modelspace");
GLint UVIDQ=glGetAttribLocation(ProgramIDQ,"vertexUV");
GLint TextureIndexQ =glGetUniformLocation(ProgramIDQ, "myTextureSampler");
////Create a texture
GLuint renderedTexture;
//GLint texWidth=windowWidth,texHeight=windowHeight;
GLint texWidth=832,texHeight=416;
glGenTextures(1, &renderedTexture);
glBindTexture(GL_TEXTURE_2D, renderedTexture);
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, texWidth, texHeight, 0,GL_RGB, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//Create a FBO
GLuint FramebufferName = 0;
glGenFramebuffers(1, &FramebufferName);
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName);
glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D, renderedTexture,0);
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
return false;
do{
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName);
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
glViewport(0,0,texWidth,texHeight);
glUseProgram(ProgramIDT);
glEnableVertexAttribArray(VertexPositionIDT);
glBindBuffer(GL_ARRAY_BUFFER,VertexBufferT);
glVertexAttribPointer(VertexPositionIDT,3,GL_FLOAT,GL_FALSE,20,(void *)0);
glDrawArrays(GL_TRIANGLE_STRIP,0,3);
glDisableVertexAttribArray(VertexPositionIDT);
//=====////äÖȾµ½ÆÁÄ»ÉÏ
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClearColor( 1, 1, 1, 0 );
glClear( GL_COLOR_BUFFER_BIT);
glViewport(0,0,windowWidth,windowHeight);
glUseProgram(ProgramIDQ);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, renderedTexture);
glUniform1i(TextureIndexQ,0);
glEnableVertexAttribArray(VertexPositionIDQ);
glBindBuffer(GL_ARRAY_BUFFER,VertexBufferQ);
glVertexAttribPointer(VertexPositionIDQ,3,GL_FLOAT,GL_FALSE,20,(void *)0);
glEnableVertexAttribArray(UVIDQ);
/*glBindBuffer(GL_ARRAY_BUFFER,VertexBufferQ);*/
glVertexAttribPointer(UVIDQ,2,GL_FLOAT,GL_FALSE,20,(void *)12);
glDrawArrays(GL_TRIANGLE_STRIP,0,4);
glDisableVertexAttribArray(VertexPositionIDQ);
glDisableVertexAttribArray(UVIDQ);
// Swap buffers
glfwSwapBuffers(window);
glfwPollEvents();
}
while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS &&
glfwWindowShouldClose(window) == 0 );
/*glDeleteFramebuffers(1, &FramebufferName);
glDeleteTextures(1, &renderedTexture);*/
glfwTerminate();
return 0;
}
代码参考2:https://github.com/mcdooda/gl-fbo-example
#include
#include
#include
#include
/* headers */
GLuint compileProgram(GLuint fragmentShaderId, GLuint vertexShaderId);
void checkProgram(GLuint programId);
GLuint loadShader(GLenum shaderType, const GLchar* source);
void checkShader(GLuint shaderId);
/* shaders */
/* 1st pass */
const GLchar* vertexShaderSource1 =
"#version 130\n"
"in vec2 position;"
"void main()"
"{"
"gl_Position = vec4(position, 0.0, 1.0);"
"}";
const GLchar* fragmentShaderSource1 =
"#version 130\n"
"out vec4 outColor;"
"uniform vec4 color;"
"void main()"
"{"
"outColor = color;"
"}";
/* 2nd pass */
const GLchar* vertexShaderSource2 =
"#version 130\n"
"in vec2 position;"
"in vec2 texturePosition;"
"out vec2 texturePosition2;"
"void main()"
"{"
"gl_Position = vec4(position, 0.0, 1.0);"
"texturePosition2 = texturePosition;"
"}";
const GLchar* fragmentShaderSource2 =
"#version 130\n"
"in vec2 texturePosition2;"
"out vec4 outColor;"
"uniform sampler2D renderTexture;"
"void main()"
"{"
"ivec2 renderTextureSize = textureSize(renderTexture, 0);"
"float dx = 1.0 / renderTextureSize.x;"
"float dy = 1.0 / renderTextureSize.y;"
"float x = texturePosition2.x;"
"float y = texturePosition2.y;"
"vec3 color = vec3(0.0, 0.0, 0.0);"
"int blurRadius = 4;"
"for (int i = -blurRadius; i <= blurRadius; i++)"
"{"
"for (int j = -blurRadius; j <= blurRadius; j++)"
"{"
"color += texture(renderTexture, vec2(x + i * dx, y + j * dy)).xyz;"
"}"
"}"
"color /= (blurRadius * 2 - 1) * (blurRadius * 2 - 1);"
"outColor = vec4(color, 1.0);"
"}";
/* vertices */
/* 1st pass */
const GLfloat redSquareVertices[] = {
-0.5f, -0.5f,
0.25f,-0.5f,
0.25f, 0.25f,
-0.5f, 0.25f
};
const GLfloat blueSquareVertices[] = {
-0.25f,-0.25f,
0.5f, -0.25f,
0.5f, 0.5f,
-0.25f, 0.5f
};
/* 2nd pass */
const GLfloat screenVertices[] = {
-0.9f,-0.9f,
0.9f,-0.9f,
0.9f, 0.9f,
-0.9f, 0.9f
};
const GLfloat screenTextureCoordinates[] = {
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f
};
/* window size */
#define WINDOW_WIDTH 512
#define WINDOW_HEIGHT 512
int main(int argc, char* argv[])
{
SDL_Init(SDL_INIT_VIDEO);
SDL_Event e;
SDL_Window* window;
SDL_Renderer* renderer;
SDL_CreateWindowAndRenderer(WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_OPENGL, &window, &renderer);
glewInit();
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
/* load programs */
/* 1st pass */
GLuint fragmentShaderId1 = loadShader(GL_FRAGMENT_SHADER, fragmentShaderSource1);
GLuint vertexShaderId1 = loadShader(GL_VERTEX_SHADER, vertexShaderSource1);
GLuint programId1 = compileProgram(fragmentShaderId1, vertexShaderId1);
/* 2nd pass */
GLuint fragmentShaderId2 = loadShader(GL_FRAGMENT_SHADER, fragmentShaderSource2);
GLuint vertexShaderId2 = loadShader(GL_VERTEX_SHADER, vertexShaderSource2);
GLuint programId2 = compileProgram(fragmentShaderId2, vertexShaderId2);
/* retrieve attribs and uniforms */
/* 1st pass */
GLint positionAttribLocation1 = glGetAttribLocation(programId1, "position");
if (positionAttribLocation1 == -1)
fprintf(stderr, "warning: positionAttribLocation1 invalid\n");
GLint colorUniformLocation1 = glGetUniformLocation(programId1, "color");
if (colorUniformLocation1 == -1)
fprintf(stderr, "warning: colorUniformLocation1 invalid\n");
/* 2nd pass */
GLint positionAttribLocation2 = glGetAttribLocation(programId2, "position");
if (positionAttribLocation2 == -1)
fprintf(stderr, "warning: positionAttribLocation2 invalid\n");
GLint texturePositionAttribLocation2 = glGetAttribLocation(programId2, "texturePosition");
if (texturePositionAttribLocation2 == -1)
fprintf(stderr, "warning: texturePositionAttribLocation2 invalid\n");
GLint renderTextureUniformLocation2 = glGetUniformLocation(programId2, "renderTexture");
if (renderTextureUniformLocation2 == -1)
fprintf(stderr, "warning: renderTextureUniformLocation2 invalid\n");
/* create FBO */
GLuint fboId;
glGenFramebuffers(1, &fboId);
GLuint renderTextureId;
glGenTextures(1, &renderTextureId);
glBindTexture(GL_TEXTURE_2D, renderTextureId);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, WINDOW_WIDTH, WINDOW_HEIGHT, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glBindFramebuffer(GL_FRAMEBUFFER, fboId);
glBindTexture(GL_TEXTURE_2D, renderTextureId);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTextureId, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
int keepRunning = 1;
while (keepRunning)
{
SDL_PollEvent(&e);
if (e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_ESCAPE)
keepRunning = 0;
/* 1st pass */
glBindFramebuffer(GL_FRAMEBUFFER, fboId);
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
GLenum bufferlist [] = {
GL_COLOR_ATTACHMENT0
};
glDrawBuffers(1, bufferlist);
glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(programId1);
glEnableVertexAttribArray(positionAttribLocation1);
glUniform4f(colorUniformLocation1, 1.0f, 0.0f, 0.0f, 1.0f);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, redSquareVertices);
glDrawArrays(GL_QUADS, 0, 4);
glUniform4f(colorUniformLocation1, 0.0f, 0.0f, 1.0f, 1.0f);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, blueSquareVertices);
glDrawArrays(GL_QUADS, 0, 4);
glDisableVertexAttribArray(positionAttribLocation1);
/* 2nd pass */
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(programId2);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, renderTextureId);
glUniform1i(renderTextureUniformLocation2, 0);
glEnableVertexAttribArray(positionAttribLocation2);
glEnableVertexAttribArray(texturePositionAttribLocation2);
glVertexAttribPointer(positionAttribLocation2, 2, GL_FLOAT, GL_FALSE, 0, screenVertices);
glVertexAttribPointer(texturePositionAttribLocation2, 2, GL_FLOAT, GL_FALSE, 0, screenTextureCoordinates);
glDrawArrays(GL_QUADS, 0, 4);
glDisableVertexAttribArray(positionAttribLocation2);
glDisableVertexAttribArray(texturePositionAttribLocation2);
glUseProgram(0);
glFlush();
SDL_RenderPresent(renderer);
}
SDL_Quit();
return 0;
}
GLuint compileProgram(GLuint fragmentShaderId, GLuint vertexShaderId)
{
GLuint programId = glCreateProgram();
glAttachShader(programId, vertexShaderId);
glAttachShader(programId, fragmentShaderId);
glLinkProgram(programId);
checkProgram(programId);
return programId;
}
void checkProgram(GLuint programId)
{
GLint result = GL_FALSE;
glGetProgramiv(programId, GL_LINK_STATUS, &result);
if (!result)
{
GLint infoLogLength;
glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar* message = alloca(infoLogLength * sizeof(GLchar));
glGetProgramInfoLog(programId, infoLogLength, NULL, message);
fprintf(stderr, "Warning: %s\n", message);
}
}
GLuint loadShader(GLenum shaderType, const GLchar* source)
{
GLuint shaderId = glCreateShader(shaderType);
glShaderSource(shaderId, 1, &source, NULL);
glCompileShader(shaderId);
checkShader(shaderId);
return shaderId;
}
void checkShader(GLuint shaderId)
{
GLint result = GL_FALSE;
glGetShaderiv(shaderId, GL_COMPILE_STATUS, &result);
if (!result)
{
GLint infoLogLength;
glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar* message = alloca(infoLogLength * sizeof(GLchar));
glGetShaderInfoLog(shaderId, infoLogLength, NULL, message);
fprintf(stderr, "Warning: %s\n", message);
}
}
代码参考3:https://github.com/SweeneyChoi/FBO-in-OpenGL
#include
#include
#include "stb_image.h"
#include
#include
#include
#include "Shader.h"
#include "Camera.h"
#include "Model.h"
#include
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
void processInput(GLFWwindow *window);
unsigned int loadTexture(const char *path);
const unsigned int SCR_WIDTH = 1280;
const unsigned int SCR_HEIGHT = 720;
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
float lastX = (float)SCR_WIDTH / 2.0;
float lastY = (float)SCR_HEIGHT / 2.0;
bool firstMouse = true;
float deltaTime = 0.0f;
float lastFrame = 0.0f;
int main()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4 );
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "ImageProcess", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
glfwSetCursorPosCallback(window, mouse_callback);
glfwSetScrollCallback(window, scroll_callback);
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
glEnable(GL_DEPTH_TEST);
Shader shader("vshader.glsl", "fshader.glsl");
Shader screenShader("screenvShader.glsl", "screenfShader.glsl");
float cubeVertices[] = {
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f
};
float planeVertices[] = {
5.0f, -0.5f, 5.0f, 2.0f, 0.0f,
-5.0f, -0.5f, 5.0f, 0.0f, 0.0f,
-5.0f, -0.5f, -5.0f, 0.0f, 2.0f,
5.0f, -0.5f, 5.0f, 2.0f, 0.0f,
-5.0f, -0.5f, -5.0f, 0.0f, 2.0f,
5.0f, -0.5f, -5.0f, 2.0f, 2.0f
};
float quadVertices[] = {
-1.0f, 1.0f, 0.0f, 1.0f,
-1.0f, -1.0f, 0.0f, 0.0f,
1.0f, -1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 1.0f,
1.0f, -1.0f, 1.0f, 0.0f,
1.0f, 1.0f, 1.0f, 1.0f
};
unsigned int cubeVAO, cubeVBO;
glGenVertexArrays(1, &cubeVAO);
glGenBuffers(1, &cubeVBO);
glBindVertexArray(cubeVAO);
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), &cubeVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
unsigned int planeVAO, planeVBO;
glGenVertexArrays(1, &planeVAO);
glGenBuffers(1, &planeVBO);
glBindVertexArray(planeVAO);
glBindBuffer(GL_ARRAY_BUFFER, planeVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(planeVertices), &planeVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
unsigned int quadVAO, quadVBO;
glGenVertexArrays(1, &quadVAO);
glGenBuffers(1, &quadVBO);
glBindVertexArray(quadVAO);
glBindBuffer(GL_ARRAY_BUFFER, quadVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float)));
unsigned int cubeTexture = loadTexture("container.jpg");
unsigned int floorTexture = loadTexture("metal.png");
shader.use();
shader.setInt("texture1", 0);
screenShader.use();
screenShader.setInt("screenTexture", 0);
unsigned int frameBuffer;
glGenFramebuffers(1, &frameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
unsigned int textureColorBufferMultiSampled;
glGenTextures(1, &textureColorBufferMultiSampled);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textureColorBufferMultiSampled);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGB, SCR_WIDTH, SCR_HEIGHT, GL_TRUE);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, textureColorBufferMultiSampled, 0);
unsigned int rbo;
glGenRenderbuffers(1, &rbo);
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, SCR_WIDTH, SCR_HEIGHT);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
cout << "ERROR: FRAMENBUFFER:: Framebuffer is not complete!" << endl;
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
unsigned int intermediateFBO;
glGenFramebuffers(1, &intermediateFBO);
glBindFramebuffer(GL_FRAMEBUFFER, intermediateFBO);
unsigned int screenTexture;
glGenTextures(1, &screenTexture);
glBindTexture(GL_TEXTURE_2D, screenTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, screenTexture, 0);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
cout << "ERROR: FRAMENBUFFER:: Framebuffer is not complete!" << endl;
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
while (!glfwWindowShouldClose(window))
{
float currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
processInput(window);
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
glEnable(GL_DEPTH_TEST);
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
shader.use();
glm::mat4 model;
glm::mat4 view = camera.GetViewMatrix();
glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
shader.setMat4("view", view);
shader.setMat4("projection", projection);
glBindVertexArray(cubeVAO);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, cubeTexture);
model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f));
shader.setMat4("model", model);
glDrawArrays(GL_TRIANGLES, 0, 36);
model = glm::mat4();
model = glm::translate(model, glm::vec3(2.0f, 0.0f, 0.0f));
shader.setMat4("model", model);
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(planeVAO);
glBindTexture(GL_TEXTURE_2D, floorTexture);
shader.setMat4("model", glm::mat4());
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
glBindFramebuffer(GL_READ_FRAMEBUFFER, frameBuffer);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, intermediateFBO);
glBlitFramebuffer(0, 0, SCR_WIDTH, SCR_HEIGHT, 0, 0, SCR_WIDTH, SCR_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDisable(GL_DEPTH_TEST);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
screenShader.use();
glBindVertexArray(quadVAO);
glBindTexture(GL_TEXTURE_2D, screenTexture);
glDrawArrays(GL_TRIANGLES, 0, 6);
glfwSwapBuffers(window);
glfwPollEvents();
}
glDeleteVertexArrays(1, &cubeVAO);
glDeleteVertexArrays(1, &planeVAO);
glDeleteVertexArrays(1, &quadVAO);
glDeleteBuffers(1, &cubeVBO);
glDeleteBuffers(1, &planeVBO);
glDeleteBuffers(1, &quadVBO);
glfwTerminate();
return 0;
}
void processInput(GLFWwindow *window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
camera.ProcessKeyboard(FORWARD, deltaTime);
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
camera.ProcessKeyboard(BACKWARD, deltaTime);
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
camera.ProcessKeyboard(LEFT, deltaTime);
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
camera.ProcessKeyboard(RIGHT, deltaTime);
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
{
if (firstMouse)
{
lastX = xpos;
lastY = ypos;
firstMouse = false;
}
float xoffset = xpos - lastX;
float yoffset = lastY - ypos;
lastX = xpos;
lastY = ypos;
camera.ProcessMouseMovement(xoffset, yoffset);
}
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
camera.ProcessMouseScroll(yoffset);
}
unsigned int loadTexture(char const * path)
{
unsigned int textureID;
glGenTextures(1, &textureID);
int width, height, nrComponents;
unsigned char *data = stbi_load(path, &width, &height, &nrComponents, 0);
if (data)
{
GLenum format;
if (nrComponents == 1)
format = GL_RED;
else if (nrComponents == 3)
format = GL_RGB;
else if (nrComponents == 4)
format = GL_RGBA;
glBindTexture(GL_TEXTURE_2D, textureID);
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
stbi_image_free(data);
}
else
{
std::cout << "Texture failed to load at path: " << path << std::endl;
stbi_image_free(data);
}
return textureID;
}
代码参考4:https://github.com/robbor78/OpenGL_BasicFBO
#include
#include
#include "shader_utils.h"
void Initialize();
void InitGL();
void InitProgramFBO();
void InitProgramScreen();
void InitBuffer();
void InitFBO();
void Loop();
void RenderToFBO();
void RenderToScreen();
void Shutdown();
void OnWindowResize(GLFWwindow* window, int width, int height);
GLFWwindow* window;
int screenWidth = 640;
int screenHeight = 480;
GLuint render2FBOProgram;
GLuint render2ScreenProgram;
GLuint vao;
GLuint vbo;
GLuint fbo;
GLuint color_texture;
int main() {
Initialize();
Loop();
Shutdown();
return 0;
}
void Initialize() {
InitGL();
InitProgramScreen();
InitProgramFBO();
InitBuffer();
InitFBO();
}
void InitGL() {
glfwInit();
window = glfwCreateWindow(screenWidth, screenHeight, "FBO Demo", NULL, NULL);
glfwMakeContextCurrent(window);
glewInit();
glClearColor(0.0f, 0.0f, 0.1f, 1.0f);
}
void InitProgramFBO() {
GLuint vs;
GLuint fs;
render2FBOProgram = create_program("vs.glsl", "fbo.fs.glsl", vs, fs);
glDeleteShader(vs);
glDeleteShader(fs);
}
void InitProgramScreen() {
GLuint vs;
GLuint fs;
render2ScreenProgram = create_program("vs.glsl", "screen.fs.glsl", vs, fs);
glDeleteShader(vs);
glDeleteShader(fs);
}
void InitBuffer() {
//define the square made up of 2 triangles
static const GLfloat points[] = {
//x y z texcoord u and v
-0.5f, 0.5f, 0.0f, 0.0f, 0.0f,
0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
0.5f, -0.5f, 0.0f, 1.0f, 1.0f,
0.5f, -0.5f, 0.0f, 1.0f, 1.0f,
-0.5f, -0.5f, 0.0f, 0.0f, 1.0f,
-0.5f, 0.5f, 0.0f, 0.0f, 0.0f
};
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
//create buffer for points
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);
//tell opengl how to find the coordinate data
glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (GLubyte*)NULL);
glEnableVertexAttribArray(0);
//tell opengl how to find the texcoord data
glVertexAttribPointer (1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (GLvoid *)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
}
void InitFBO() {
//create a framebuffer
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
//create a texture as the backing store for the framebuffer
glGenTextures(1, &color_texture);
glBindTexture(GL_TEXTURE_2D, color_texture);
glTexStorage2D(GL_TEXTURE_2D, 9, GL_RGBA8, 512, 512); //1 = mipmap levels
//mip map filtering
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//attach the texture as the color attachment of the framebuffer
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color_texture, 0);
//tell opengl to draw into the color attachment
static const GLenum draw_buffers[] = { GL_COLOR_ATTACHMENT0 };
glDrawBuffers(1, draw_buffers);
}
void Loop() {
//glBindVertexArray(vao);
//glBindBuffer(GL_ARRAY_BUFFER, vbo);
while (!glfwWindowShouldClose(window)) {
RenderToFBO();
RenderToScreen();
glfwSwapBuffers(window);
glfwPollEvents();
if (GLFW_PRESS == glfwGetKey(window, GLFW_KEY_ESCAPE)) {
glfwSetWindowShouldClose(window, 1);
}
}
}
void RenderToFBO() {
static const GLfloat green[] = { 0.0f, 1.0f, 0.0f, 1.0f }; //texture background is green
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glViewport(0, 0, 512, 512); //set view port to texture size
glClearBufferfv(GL_COLOR, 0, green);
glUseProgram(render2FBOProgram);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
void RenderToScreen() {
static const GLfloat blue[] = { 0.0f, 0.0f, 1.0f, 1.0f }; //screen background is blue
glViewport(0, 0, screenWidth, screenHeight);
glClearBufferfv(GL_COLOR, 0, blue);
glBindTexture(GL_TEXTURE_2D, color_texture);
glUseProgram(render2ScreenProgram);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindTexture(GL_TEXTURE_2D, 0);
}
void Shutdown() {
glUseProgram(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDeleteProgram(render2FBOProgram);
glDeleteProgram(render2ScreenProgram);
glfwTerminate();
}
// a call-back function
void OnWindowResize(GLFWwindow* window, int width, int height) {
screenWidth = width;
screenHeight = height;
glViewport(0, 0, screenWidth, screenHeight);
}
代码参考5:
GLuint VolRenCore::RendrToFBO()
{
if (!m_Data || !m_Data->GetData()) return 0;
if (tex)
{
glDeleteTexturesEXT(1, &tex);
tex = 0;
}
//init gl
glEnable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);
//fbo
GLuint fb;
glGenFramebuffersEXT(1, &fb);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
//texture buffer
glGenTextures(1, &tex);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_ViewPort[0], m_ViewPort[1], 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
//render buffer
GLuint rbo;
glGenRenderbuffersEXT(1, &rbo);
glBindRenderbufferEXT(GL_RENDERBUFFER, rbo);
glRenderbufferStorageEXT(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, m_ViewPort[0], m_ViewPort[1]);
//glBindRenderbufferEXT(GL_RENDERBUFFER, 0);
//attach
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, tex, 0);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo);
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
//检查FBO状态
bool status = checkFramebufferStatus();
if (!status)
return 0;
if(!Render()) return 0;
//////////////////////////////////////////////////////////////////////////
// glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
// //glReadBuffer(GL_DEPTH_ATTACHMENT);
// int w = m_ViewPort[0];
// int h = m_ViewPort[1];
// QImage img(w,h, QImage::Format_ARGB32);
// glReadPixels(0,0,w,h,GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
// mDisplayDialog fbo(img);
// fbo.exec();
//////////////////////////////////////////////////////////////////////////
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glDeleteFramebuffersEXT(1, &fb);
glDeleteRenderbuffersEXT(1, &rbo);
return tex;
}
void VRDisplayWidget::paintGL()
{
GLuint tex1;
GLuint tex2;
if (m_Core)
{
tex1 = m_Core->RendrToFBO();
m_Core->m_VolTextureNeedUpdate = true;
tex2 = m_Core1->RendrToFBO();
m_Core1->m_VolTextureNeedUpdate = true;
if (!tex1) return;
if(!tex2) return;
glClearColor(0.0, 0.0, 0.0, 0.0f);
glClearDepth(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glFrontFace(GL_CCW);
//gl
glEnable(GL_BLEND);
//glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glBlendFunc(GL_SRC_ALPHA,GL_SRC_ALPHA);
//texture0
glActiveTexture(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tex1);
//texture1
glActiveTexture(GL_TEXTURE1_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tex2);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
glMultiTexCoord2f(GL_TEXTURE0_ARB, 0.0, 0.0);glMultiTexCoord2f(GL_TEXTURE1_ARB, 0.0, 0.0); glVertex2f(0.0, 0.0);
glMultiTexCoord2f(GL_TEXTURE0_ARB, 0.0, 1.0);glMultiTexCoord2f(GL_TEXTURE1_ARB, 0.0, 1.0); glVertex2f(0.0, hei);
glMultiTexCoord2f(GL_TEXTURE0_ARB, 1.0, 1.0);glMultiTexCoord2f(GL_TEXTURE1_ARB, 1.0, 1.0); glVertex2f(wid, hei);
glMultiTexCoord2f(GL_TEXTURE0_ARB, 1.0, 0.0);glMultiTexCoord2f(GL_TEXTURE1_ARB, 1.0, 0.0); glVertex2f(wid, 0.0);
glEnd();
/*glFlush();*/
glPushAttrib(GL_ALL_ATTRIB_BITS);
glColor3f(1.0f,0.0f,0.0f);
renderText(30,40,QString::number(m_fps)+"FPS",QFont("Arial",20));
glPopAttrib();
}
}