参考:
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);
}