FBO render to texture渲染到纹理

代码参考1:https://github.com/wld0595/FBO

// Include standard headers
#include <stdio.h>

// Include GLEW
#include <GL/glew.h>

// Include GLFW
#include <GLFW/glfw3.h>
GLFWwindow* window;

#include <common/shader.hpp>
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>

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 <stdlib.h>
#include <stdio.h>
#include <GL/glew.h>
#include <SDL2/SDL.h>

/* 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 <glad/glad.h>
#include <GLFW/glfw3.h>
#include "stb_image.h"

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

#include "Shader.h"
#include "Camera.h"
#include "Model.h"

#include <iostream>

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 <GL/glew.h>
#include <GLFW/glfw3.h>

#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();
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值