OpenGL FrameBufferObject 基础 (1)



参考:

http://learnopengl-cn.readthedocs.io/zh/latest/04%20Advanced%20OpenGL/05%20Framebuffers/





**********************************************************************************************************************************************************************

main.cpp


#include <string>

#define GLEW_STATIC
#include <GL/glew.h>

#include <GLFW/glfw3.h>

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

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

#include <SOIL/SOIL.h>

#include <vector>

#pragma comment (lib, "opengl32.lib")
#pragma comment (lib, "glew32s.lib")
#pragma comment (lib, "glfw3.lib") 
#pragma comment (lib, "glfw3dll.lib") 
#pragma comment (lib, "glew32mxs.lib")
#pragma comment (lib, "assimp.lib")
#pragma comment(lib, "SOIL.lib")


GLuint WIDTH = 800, HEIGHT = 600;

void key_callback(GLFWwindow* pWnd, int key, int scancode, int action, int mode);
void scroll_callback(GLFWwindow* pWnd, double xoffset, double yoffset);
void mouse_callback(GLFWwindow* pWnd, double xpos, double ypos);
void Do_Movement();
GLuint loadTexture(GLchar* path, GLboolean alpha = false);
GLuint generateAttachmentTexture(GLboolean depth, GLboolean stencil);

// Camera
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
bool keys[1024];
GLfloat lastX = 400, lastY = 300;
bool firstMouse = true;

GLfloat deltaTime = 0.0f;
GLfloat lastFrame = 0.0f;

int main()
{
	glfwInit();
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
	glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

	GLFWwindow* pWnd = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr); // Windowed
	glfwMakeContextCurrent(pWnd);

	glfwSetKeyCallback(pWnd, key_callback);
	glfwSetCursorPosCallback(pWnd, mouse_callback);
	glfwSetScrollCallback(pWnd, scroll_callback);

	//glfwSetInputMode(pWnd, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
	glewExperimental = GL_TRUE;
	glewInit();

	glViewport(0, 0, WIDTH, HEIGHT);

	glDepthFunc(GL_LESS);

	// 立方体
	GLfloat 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
	};

	// 地面
	GLfloat floorVertices[] = {
		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
	};

	

	GLfloat 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
	};

	// 数据处理
	// 盒子
	GLuint 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(GLfloat), (GLvoid*)0);
	glEnableVertexAttribArray(1);
	glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
	glBindVertexArray(0);

	// 地面
	GLuint floorVAO, floorVBO;
	glGenVertexArrays(1, &floorVAO);
	glBindVertexArray(floorVAO);

	{
		glGenBuffers(1, &floorVBO);
		glBindBuffer(GL_ARRAY_BUFFER, floorVBO);
		glBufferData(GL_ARRAY_BUFFER, sizeof(floorVertices), floorVertices, GL_STATIC_DRAW);

		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)0);
		glEnableVertexAttribArray(0);

		glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat)));
		glEnableVertexAttribArray(1);
	}
	glBindVertexArray(0);
	
	GLuint quadVAO, quadVBO;
	glGenVertexArrays(1, &quadVAO);
	glBindVertexArray(quadVAO);

	{
		glGenBuffers(1, &quadVBO);
		glBindBuffer(GL_ARRAY_BUFFER, quadVBO);
		glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), quadVertices, GL_STATIC_DRAW);

		glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GL_FLOAT), (void*)0);
		glEnableVertexAttribArray(0);

		glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GL_FLOAT), (void*)(2 * sizeof(GL_FLOAT)));
		glEnableVertexAttribArray(1);
	}
	glBindVertexArray(0);

	// Shader
	Shader shader("./Shader/advanced_vertex", "./Shader/advanced_fragement");
	Shader screenShader("./Shader/screen_vertex", "./Shader/screen_fragement");

	// 纹理
	GLuint textCube = loadTexture("./Img/cube.jpg");
	GLuint textFloor = loadTexture("./Img/floor.jpg");
	
	// 缓冲
	GLuint frameBufferObj;
	glGenFramebuffers(1, &frameBufferObj);	// 创建一个帧缓冲对象FBO
	// 创建一个空纹理
	GLuint textureColorBuffer = generateAttachmentTexture(GL_FALSE, GL_FALSE);
	glBindFramebuffer(GL_FRAMEBUFFER, frameBufferObj);

	{
		// 把创建的空纹理附加到帧缓冲上
		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureColorBuffer, 0);

		GLuint renderBufferObj;
		glGenRenderbuffers(1, &renderBufferObj);	// 创建一个渲染缓冲对象 RenderBufferObject
		glBindRenderbuffer(GL_RENDERBUFFER, renderBufferObj);	// 把渲染缓冲对象绑定,后续渲染缓冲将在此RBO上操作
		// 创建一个深度和模板渲染缓冲对象    24位的深度和8位的模板缓冲
		glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, WIDTH, HEIGHT);
		glBindRenderbuffer(GL_RENDERBUFFER, 0);

		// 将创建的RBO附加到FBO上
		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, renderBufferObj);

		if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)	// 检查FBO是否正确
		{
			std::cout << "glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE" << std::endl;
		}
	}
	glBindFramebuffer(GL_FRAMEBUFFER, 0);	// 解绑帧缓冲

	//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // 使用线框模式绘制
	// 绘制
	while (!glfwWindowShouldClose(pWnd))
	{
		GLfloat currentFrame = glfwGetTime();
		deltaTime = currentFrame - lastFrame;
		lastFrame = currentFrame;

		glfwPollEvents();

		Do_Movement();

		glBindFramebuffer(GL_FRAMEBUFFER, frameBufferObj);	// 绑定到之前创建的FBO上, 并在此上绘制

		{
			glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

			glEnable(GL_DEPTH_TEST);

			shader.useShaderPrograme();

			glm::mat4 model = glm::mat4();
			glm::mat4 view = camera.GetViewMatrix();	 // 获取视变换矩阵
			// 投影矩阵
			glm::mat4 projection =
				glm::perspective(camera.Zoom, (float)WIDTH / (float)HEIGHT, 0.1f, 10.0f);

			glUniformMatrix4fv(glGetUniformLocation(shader.getPrograme(), "view"), 
				1, GL_FALSE, glm::value_ptr(view));

			glUniformMatrix4fv(glGetUniformLocation(shader.getPrograme(), "projection"), 1,
				GL_FALSE, glm::value_ptr(projection));

			// 绘制地面
			glBindVertexArray(floorVAO);
			glBindTexture(GL_TEXTURE_2D, textFloor);

			{
				model = glm::mat4();
				glUniformMatrix4fv(glGetUniformLocation(shader.getPrograme(), "model"),
					1, GL_FALSE, glm::value_ptr(model));
				glDrawArrays(GL_TRIANGLES, 0, 6);
			}
			glBindTexture(GL_TEXTURE_2D, 0);
			glBindVertexArray(0);

			// 绘制立方体
			glBindVertexArray(cubeVAO);
			glBindTexture(GL_TEXTURE_2D, textCube);

			{
				//model = glm::mat4();
				model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f));
				glUniformMatrix4fv(glGetUniformLocation(shader.getPrograme(), "model"),
					1, GL_FALSE, glm::value_ptr(model));
				glDrawArrays(GL_TRIANGLES, 0, 36);	// 第一个立方体

				model = glm::mat4();
				model = glm::translate(model, glm::vec3(2.0f, 0.0f, 0.0f));
				glUniformMatrix4fv(glGetUniformLocation(shader.getPrograme(), "model"),
					1, GL_FALSE, glm::value_ptr(model));
				glDrawArrays(GL_TRIANGLES, 0, 36);	// 第二个立方体
			}
			glBindTexture(GL_TEXTURE_2D, 0);
			glBindVertexArray(0);

			// 恢复默认FBO	在矩形上绘制FBO的纹理
			// 普通绘制
			glBindFramebuffer(GL_FRAMEBUFFER, 0);	// 解绑帧缓冲

			{
				glClearColor(0.25f, 0.25f, 0.25f, 1.0f);
				glClear(GL_COLOR_BUFFER_BIT);
				glDisable(GL_DEPTH_TEST);

				screenShader.useShaderPrograme();

				glBindVertexArray(quadVAO);	// 像使用普通纹理一样需要绑定 注释掉即恍然大悟
				glBindTexture(GL_TEXTURE_2D, textureColorBuffer);
				{
					glDrawArrays(GL_TRIANGLES, 0, 6);
				}
				glBindVertexArray(0);
			}
		}
		//glBindFramebuffer(GL_FRAMEBUFFER, 0);	// 解绑帧缓冲

		glfwSwapBuffers(pWnd);	 // 交换缓存
	}

	// While 循环之后  清理资源,退出程序
	glDeleteVertexArrays(1, &cubeVAO);
	glDeleteVertexArrays(1, &floorVAO);
	glDeleteVertexArrays(1, &quadVAO);
	glDeleteBuffers(1, &cubeVBO);
	glDeleteBuffers(1, &floorVBO);
	glDeleteBuffers(1, &quadVBO);
	glDeleteFramebuffers(1, &frameBufferObj);

	glfwTerminate();
	return 0;
}


// 加载纹理
// 当把一个纹理附加到帧缓冲上的时候,所有渲染命令会写入到纹理上,就像它是一个普通的颜色/深度或者模板缓冲一样
GLuint loadTexture(GLchar* path, GLboolean alpha /*= false*/)
{
	int nPicW = 0, nPicH = 0;
	unsigned char* pChImg =
		SOIL_load_image(path, &nPicW, &nPicH, 0, alpha ? SOIL_LOAD_RGBA : SOIL_LOAD_RGB);

	GLuint textureID = 0;
	glGenTextures(1, &textureID);
	glBindTexture(GL_TEXTURE_2D, textureID);
	glTexImage2D(GL_TEXTURE_2D, 0, alpha ? GL_RGBA : GL_RGB, nPicW, nPicH, 0,
		alpha ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, pChImg);
	glGenerateMipmap(GL_TEXTURE_2D);

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, alpha ? GL_CLAMP_TO_EDGE : GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, alpha ? GL_CLAMP_TO_EDGE : GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glBindTexture(GL_TEXTURE_2D, 0);
	SOIL_free_image_data(pChImg);
	return textureID;
}



// 添加纹理附件
GLuint generateAttachmentTexture(GLboolean depth, GLboolean stencil)
{
	GLenum eAttachType = 0;
	if ((!depth) && (!stencil))
	{
		eAttachType = GL_RGB;
	}
	else if (depth && (!stencil))
	{
		eAttachType = GL_DEPTH_COMPONENT;
	}
	else if ((!depth) && stencil)
	{
		eAttachType = GL_STENCIL_INDEX;
	}

	GLuint textureID = 0;
	glGenTextures(1, &textureID);	// 创建一个纹理对象
	glBindTexture(GL_TEXTURE_2D, textureID);	// 绑定纹理对象
	{
		// 将纹理对象创建一个空内存
		// 纹理设置为屏幕大小 不用关心环绕方式或者Mipmap,因为在大多数时候都不会需要它们的
		if ((!depth) && (!stencil))
		{
			glTexImage2D(GL_TEXTURE_2D, 0, eAttachType, WIDTH, HEIGHT, 0, 
				eAttachType, GL_UNSIGNED_BYTE, nullptr);
		}
		else
		{
			glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, WIDTH, HEIGHT, 0,
				GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, nullptr);
		}
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	}
	glBindTexture(GL_TEXTURE_2D, 0);
	return textureID;
}


void Do_Movement()
{
	// Camera controls
	if (keys[GLFW_KEY_W])
		camera.ProcessKeyboard(FORWARD, deltaTime);
	if (keys[GLFW_KEY_S])
		camera.ProcessKeyboard(BACKWARD, deltaTime);
	if (keys[GLFW_KEY_A])
		camera.ProcessKeyboard(LEFT, deltaTime);
	if (keys[GLFW_KEY_D])
		camera.ProcessKeyboard(RIGHT, deltaTime);
}


// Is called whenever a key is pressed/released via GLFW
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
{
	if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
		glfwSetWindowShouldClose(window, GL_TRUE);

	if (action == GLFW_PRESS)
		keys[key] = true;
	else if (action == GLFW_RELEASE)
		keys[key] = false;
}


void mouse_callback(GLFWwindow* window, double xpos, double ypos)
{
	if (firstMouse)
	{
		lastX = xpos;
		lastY = ypos;
		firstMouse = false;
	}

	GLfloat xoffset = xpos - lastX;
	GLfloat yoffset = lastY - ypos;

	lastX = xpos;
	lastY = ypos;

	camera.ProcessMouseMovement(xoffset, yoffset);
}


void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
	camera.ProcessMouseScroll(yoffset);
}


**********************************************************************************************************************************************************************

Camera.h


//Camera.h 

#pragma once

// Std. Includes
#include <vector>

// GL Includes
#include <GL/glew.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>


// 摄像机移动方向  程序中用WSAD控制
enum Camera_Movement {
	FORWARD,
	BACKWARD,
	LEFT,
	RIGHT
};

// Default camera values
const GLfloat YAW = -90.0f;
const GLfloat PITCH = 0.0f;
const GLfloat SPEED = 3.0f;
const GLfloat SENSITIVTY = 0.25f;
const GLfloat ZOOM = 45.0f;


class Camera
{
public:
	// Camera Attributes
	glm::vec3 Position;
	glm::vec3 Front;
	glm::vec3 Up;
	glm::vec3 Right;
	glm::vec3 WorldUp;
	// Eular Angles
	GLfloat Yaw;
	GLfloat Pitch;
	// Camera options
	GLfloat MovementSpeed;
	GLfloat MouseSensitivity;
	GLfloat Zoom;

	// Constructor with vectors
	Camera(glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f), 
		glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f), GLfloat yaw = YAW, 
		GLfloat pitch = PITCH) : Front(glm::vec3(0.0f, 0.0f, -1.0f)), 
		MovementSpeed(SPEED), MouseSensitivity(SENSITIVTY), Zoom(ZOOM)
	{
		this->Position = position;
		this->WorldUp = up;
		this->Yaw = yaw;
		this->Pitch = pitch;
		this->updateCameraVectors();
	}
	// Constructor with scalar values
	Camera(GLfloat posX, GLfloat posY, GLfloat posZ, GLfloat upX, GLfloat upY, 
		GLfloat upZ, GLfloat yaw, GLfloat pitch) : Front(glm::vec3(0.0f, 0.0f, -1.0f)), 
		MovementSpeed(SPEED), MouseSensitivity(SENSITIVTY), Zoom(ZOOM)
	{
		this->Position = glm::vec3(posX, posY, posZ);
		this->WorldUp = glm::vec3(upX, upY, upZ);
		this->Yaw = yaw;
		this->Pitch = pitch;
		this->updateCameraVectors();
	}

	// Returns the view matrix calculated using Eular Angles and the LookAt Matrix
	glm::mat4 GetViewMatrix()
	{
		return glm::lookAt(this->Position, this->Position + this->Front, this->Up);
	}

	// 按键处理
	void ProcessKeyboard(Camera_Movement direction, GLfloat deltaTime)
	{
		GLfloat velocity = this->MovementSpeed * deltaTime;
		if (direction == FORWARD)
			this->Position += this->Front * velocity;
		if (direction == BACKWARD)
			this->Position -= this->Front * velocity;
		if (direction == LEFT)
			this->Position -= this->Right * velocity;
		if (direction == RIGHT)
			this->Position += this->Right * velocity;
	}

	// 鼠标移动处理
	void ProcessMouseMovement(GLfloat xoffset, GLfloat yoffset, 
		GLboolean constrainPitch = true)
	{
		xoffset *= this->MouseSensitivity;
		yoffset *= this->MouseSensitivity;

		this->Yaw += xoffset;
		this->Pitch += yoffset;

		// Make sure that when pitch is out of bounds, screen doesn't get flipped
		if (constrainPitch)
		{
			if (this->Pitch > 89.0f)
				this->Pitch = 89.0f;
			if (this->Pitch < -89.0f)
				this->Pitch = -89.0f;
		}

		// Update Front, Right and Up Vectors using the updated Eular angles
		this->updateCameraVectors();
	}

	// Processes input received from a mouse scroll-wheel event. 
	//		Only requires input on the vertical wheel-axis
	void ProcessMouseScroll(GLfloat yoffset)
	{
		if (this->Zoom >= 1.0f && this->Zoom <= 45.0f)
			this->Zoom -= yoffset;
		if (this->Zoom <= 1.0f)
			this->Zoom = 1.0f;
		if (this->Zoom >= 45.0f)
			this->Zoom = 45.0f;
	}

private:
	// Calculates the front vector from the Camera's (updated) Eular Angles
	void updateCameraVectors()
	{
		// Calculate the new Front vector
		glm::vec3 front;
		front.x = cos(glm::radians(this->Yaw)) * cos(glm::radians(this->Pitch));
		front.y = sin(glm::radians(this->Pitch));
		front.z = sin(glm::radians(this->Yaw)) * cos(glm::radians(this->Pitch));
		this->Front = glm::normalize(front);
		// Also re-calculate the Right and Up vector
		// Normalize the vectors, because their length gets closer to 0 the more 
		//		you look up or down which results in slower movement.
		this->Right = glm::normalize(glm::cross(this->Front, this->WorldUp));  
		this->Up = glm::normalize(glm::cross(this->Right, this->Front));
	}
};




**********************************************************************************************************************************************************************

Shader.h



//Shader.h 
#pragma once

#ifndef TEXTURE_SHADER_H_
#define TEXTURE_SHADER_H_

#include <string>
#include <fstream>
#include <sstream>
#include <iostream>

#include <gl/glew.h>

#include <string>
#include <fstream>
#include <sstream>
#include <iostream>

#include <GL/glew.h>

class Shader
{
public:
	Shader(const GLchar* vertexPath, const GLchar* fragmentPath);
	~Shader();

public:
	void useShaderPrograme();

	GLuint getPrograme() {
		return this->m_nProgram;
	}

private:
	GLuint  m_nProgram;
};

Shader::Shader(const GLchar* vertexPath, const GLchar* fragmentPath)
{
	std::string vertexCode;
	std::string fragmentCode;
	std::ifstream vertexShaderF;
	std::ifstream fragementShaderF;

	vertexShaderF.exceptions(std::ifstream::badbit);
	fragementShaderF.exceptions(std::ifstream::badbit);

	try
	{
		vertexShaderF.open(vertexPath);		// 打开文件
		fragementShaderF.open(fragmentPath);

		std::stringstream vertexShaderStream, fragementShaderStream;
		vertexShaderStream << vertexShaderF.rdbuf();	// 读取文件至stringstream中
		fragementShaderStream << fragementShaderF.rdbuf();

		vertexShaderF.close();
		fragementShaderF.close();

		vertexCode = vertexShaderStream.str();		// 转换成string类型
		fragmentCode = fragementShaderStream.str();
	}
	catch (std::ifstream::failure e)
	{
		std::cout << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ:" << std::endl;
	}

	const GLchar* pVertexCode = vertexCode.c_str();	// string 转 char*
	const GLchar* pFragementCode = fragmentCode.c_str();

	GLuint nVertexShader, nFragementShader;
	GLint nRes = 0;
	GLchar chLogInfo[512] = { '\0' };

	// 创建顶点着色器
	nVertexShader = glCreateShader(GL_VERTEX_SHADER);
	// 将顶点着色程序的源代码字符数组绑定到顶点着色器对象
	glShaderSource(nVertexShader, 1, &pVertexCode, nullptr);
	glCompileShader(nVertexShader); // compile shader 编译着色器

	// 获取编译结果
	glGetShaderiv(nVertexShader, GL_COMPILE_STATUS, &nRes);
	if (!nRes)
	{
		glGetShaderInfoLog(nVertexShader, 512, nullptr, chLogInfo);
		std::cout << "ERROR::SHADEF::VERTEX::COMPILATION_FAILED:" << chLogInfo << std::endl;
	}

	// 创建片断着色器
	nFragementShader = glCreateShader(GL_FRAGMENT_SHADER);
	// 将片段着色程序的源代码字符数组绑定到片段着色器对象
	glShaderSource(nFragementShader, 1, &pFragementCode, nullptr);
	glCompileShader(nFragementShader);
	glGetShaderiv(nFragementShader, GL_COMPILE_STATUS, &nRes);
	if (!nRes)
	{
		glGetShaderInfoLog(nFragementShader, 512, nullptr, chLogInfo);
		std::cout << "ERROR::SHADEF::FRAGEMENT::COMPILATION_FAILED:" << chLogInfo << std::endl;
	}

	this->m_nProgram = glCreateProgram();	// 创建GLSL程序
	glAttachShader(this->m_nProgram, nVertexShader);	// 绑定shader到program
	glAttachShader(this->m_nProgram, nFragementShader);

	// glLinkProgram操作产生最后的可执行程序,它包含最后可以在硬件上执行的硬件指令
	glLinkProgram(this->m_nProgram);		// 链接
	glGetProgramiv(this->m_nProgram, GL_LINK_STATUS, &nRes);
	if (!nRes)
	{
		glGetProgramInfoLog(this->m_nProgram, 512, nullptr, chLogInfo);
		std::cout << "ERROR::SHADEF::FRAGEMENT::LINK_FAILED:" << chLogInfo << std::endl;
	}

	glDeleteShader(nVertexShader);
	glDeleteShader(nFragementShader);
}

Shader::~Shader()
{
}

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

void Shader::useShaderPrograme()
{
	glUseProgram(this->m_nProgram);	// 使用porgram
}

#endif





**********************************************************************************************************************************************************************

***********************************************************************************


GLSL Shader 部分



**********************************************************************************************************************************************************************

advanced_vertex


// Vertex shader:
// ================
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec2 texCoords;

out vec2 TexCoords;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
    gl_Position = projection * view * model * vec4(position, 1.0f);
    TexCoords = texCoords;
}



**********************************************************************************************************************************************************************

advanced_fragement


// Fragment shader:
// ================
#version 330 core

in vec2 TexCoords;

out vec4 color;

uniform sampler2D ourTexture;

void main()
{
    color = texture(ourTexture, TexCoords);
}



**********************************************************************************************************************************************************************

screen_vertex


// Vertex shader:
// ================
#version 330 core

layout(location = 0) in vec2 position;
layout(location = 1) in vec2 textCoord;


uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;

out vec2 TextCoord;

void main()
{
	gl_Position = vec4(position.x, position.y, 0.0, 1.0);
	TextCoord = textCoord;
}


**********************************************************************************************************************************************************************

screen_fragement


// Fragment shader:
// ================
#version 330 core

in vec2 TextCoord;
uniform sampler2D text;

out vec4 color;

void main()
{
	color = texture(text, TextCoord);
}




glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // 使用线框模式绘制  

效果:








源码下载: VS2015

http://download.csdn.net/detail/yulinxx/9719073


advanced_fragement  中 , 修改如下红色一行, 则可以实现反色:

#version 330 core


in vec2 TexCoords;


out vec4 color;


uniform sampler2D ourTexture;


void main()
{
    color =1-texture(ourTexture, TexCoords);
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值