参考:
http://learnopengl-cn.readthedocs.io/zh/latest/04%20Advanced%20OpenGL/03%20Blending/
修正:
通过绑定为0来使默认帧缓冲被激活
glBindFramebuffer(GL_FRAMEBUFFER, 0); // 通过绑定为0来使默认帧缓冲被激活
****************************************************************************
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 screenWidth = 800, screenHeight = 600;
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
void Do_Movement();
GLuint loadTexture(GLchar* path, GLboolean bAlpha = GL_FALSE);
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
GLfloat lastX = 400, lastY = 300;
bool keys[1024];
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* window = glfwCreateWindow(screenWidth, screenHeight, "LearnOpenGL", nullptr, nullptr);
glfwMakeContextCurrent(window);
glfwSetKeyCallback(window, key_callback);
glfwSetCursorPosCallback(window, mouse_callback);
glfwSetScrollCallback(window, scroll_callback);
// Options
//glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
glewExperimental = GL_TRUE;
glewInit();
glViewport(0, 0, screenWidth, screenHeight);
glEnable(GL_DEPTH_TEST); // 开启深度测试
glDepthFunc(GL_LESS);
glEnable(GL_STENCIL_TEST); // 开启模板测试
glStencilFunc(GL_NOTEQUAL, 1, 0xFF);
// 先开启模板测试,设置模板、深度测试通过或失败时才采取动作
// 1 保持现有模板值, 2 若模板测试通过,深度测试失败,保持现有模板值
// 3 深度与模板均通过,将模板值用 glStencilFunc函数设置的ref值替换
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
// Shader 源码
Shader shader("./Shader/advanced_vertex", "./Shader/advanced_fragement");
Shader shaderSingleColor("./Shader/advanced_vertex", "./Shader/single_color_fragement");
// 立方体数据
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 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
};
// 草的纹理
GLfloat grassVertices[] = {
0.0f, 0.5f, 0.0f, 0.0f, 0.0f,
0.0f, -0.5f, 0.0f, 0.0f, 1.0f,
1.0f, -0.5f, 0.0f, 1.0f, 1.0f,
0.0f, 0.5f, 0.0f, 0.0f, 0.0f,
1.0f, -0.5f, 0.0f, 1.0f, 1.0f,
1.0f, 0.5f, 0.0f, 1.0f, 0.0f
};
// 草的位置
std::vector<glm::vec3> grassPos;
grassPos.push_back(glm::vec3(-1.5f, 0.0f, -0.48f));
grassPos.push_back(glm::vec3(1.5f, 0.0f, 0.51f));
grassPos.push_back(glm::vec3(0.0f, 0.0f, 0.7f));
grassPos.push_back(glm::vec3(-0.3f, 0.0f, -2.3f));
grassPos.push_back(glm::vec3(0.5f, 0.0f, -0.6f));
// 立方体
GLuint cubeVAO, cubeVBO;
glGenVertexArrays(1, &cubeVAO);
glBindVertexArray(cubeVAO);
glGenBuffers(1, &cubeVBO);
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 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(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glBindVertexArray(0);
// 草
GLuint grassVAO, grassVBO;
glGenVertexArrays(1, &grassVAO);
glBindVertexArray(grassVAO);
glGenBuffers(1, &grassVBO);
glBindBuffer(GL_ARRAY_BUFFER, grassVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(grassVertices), &grassVertices, 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);
// 纹理ID
GLuint cubeTexture = loadTexture("./Img/a.jpg");
GLuint floorTexture = loadTexture("./Img/b.jpg");
GLuint grassTexture = loadTexture("./Img/grass.png", GL_TRUE);
while (!glfwWindowShouldClose(window))
{
GLfloat currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
glfwPollEvents();
Do_Movement();
glClearColor(0.1f, 0.1f, 0.41f, 1.0f); // 偏蓝色背景 当天空
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// 视图设置
glm::mat4 model;
glm::mat4 view = camera.GetViewMatrix();
glm::mat4 projection = glm::perspective(camera.Zoom, (float)screenWidth / (float)screenHeight, 0.1f, 100.0f);
shaderSingleColor.useShaderPrograme();
glUniformMatrix4fv(glGetUniformLocation(shaderSingleColor.getPrograme(), "view"), 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(glGetUniformLocation(shaderSingleColor.getPrograme(), "projection"), 1, GL_FALSE, glm::value_ptr(projection));
shader.useShaderPrograme();
glUniformMatrix4fv(glGetUniformLocation(shader.getPrograme(), "view"), 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(glGetUniformLocation(shader.getPrograme(), "projection"), 1, GL_FALSE, glm::value_ptr(projection));
// 绘制草地 此时模板缓冲区不可写
glStencilMask(0x00);// 位遮罩 0x00,所有写入深度缓冲最后都是0 // 0x00 == 0b00000000 == 0 //此时,模板值与它进行按位与运算结果是0,模板缓冲不可写
glBindVertexArray(grassVAO);
glBindTexture(GL_TEXTURE_2D, grassTexture);
for (GLuint i = 0; i < grassPos.size(); i++)
{
model = glm::mat4();
model = glm::translate(model, grassPos[i]);
glUniformMatrix4fv(glGetUniformLocation(shader.getPrograme(), "model"), 1, GL_FALSE, glm::value_ptr(model));
glDrawArrays(GL_TRIANGLES, 0, 6);
}
glBindVertexArray(0);
glBindVertexArray(planeVAO);
glBindTexture(GL_TEXTURE_2D, floorTexture);
model = glm::mat4();
glUniformMatrix4fv(glGetUniformLocation(shader.getPrograme(), "model"), 1, GL_FALSE, glm::value_ptr(model));
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
// 模板缓冲先清空模板缓冲设置所有片段的模板值为0,然后开启矩形片段用1填充
// 所有片段都要写入模板缓冲 在绘制物体前,把模板方程设置为GL_ALWAYS,用1更新物体将被渲染的片段。
glStencilFunc(GL_ALWAYS, 1, 0xFF);
// 模板缓冲区可写
// 位遮罩 模板值进行按位与(AND)运算决定缓冲是否可写, //此时,模板值与它进行按位与运算结果是模板值,模板缓冲可写
glStencilMask(0xFF);
// 绘制两个立方体 写入模板缓冲 绘制之处,模板缓冲更新为1
glBindVertexArray(cubeVAO);
glBindTexture(GL_TEXTURE_2D, cubeTexture);
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);
glBindVertexArray(0);
// == =============
// 2nd. Render pass, now draw slightly scaled versions of the objects, this time disabling stencil writing.
// Because stencil buffer is now filled with several 1s. The parts of the buffer that are 1 are now not drawn, thus only drawing
// the objects' size differences, making it look like borders.
glStencilFunc(GL_NOTEQUAL, 1, 0xFF); // 只绘制前面绘制的箱子外围的那部分
// 关闭模板写入
glStencilMask(0x00);
// 关闭深度测试
glDisable(GL_DEPTH_TEST);
shaderSingleColor.useShaderPrograme();
GLfloat scale = 1.02; // 放大
// 渲染物体,更新模板缓冲
// 使用一个不同的片段着色器用来输出一个纯颜色。
glBindVertexArray(cubeVAO);
glBindTexture(GL_TEXTURE_2D, cubeTexture);
model = glm::mat4();
model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f));
model = glm::scale(model, glm::vec3(scale, scale, scale));
glUniformMatrix4fv(glGetUniformLocation(shaderSingleColor.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));
model = glm::scale(model, glm::vec3(scale, scale, scale));
glUniformMatrix4fv(glGetUniformLocation(shaderSingleColor.getPrograme(), "model"), 1, GL_FALSE, glm::value_ptr(model));
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);
// 开启模板写入和深度测试
glStencilMask(0xFF);
glEnable(GL_DEPTH_TEST);
glfwSwapBuffers(window);
}
glfwTerminate();
return 0;
}
void DrawScene()
{
}
// 纹理数据加载
GLuint loadTexture(GLchar* path, GLboolean bAlpha)
{
GLuint textureID;
glGenTextures(1, &textureID);
int width, height;
unsigned char* image = SOIL_load_image(path, &width, &height, 0, bAlpha?SOIL_LOAD_RGBA:SOIL_LOAD_RGB);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexImage2D(GL_TEXTURE_2D, 0, bAlpha?GL_RGBA:GL_RGB, width, height, 0, bAlpha ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D);
// Parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, bAlpha ? GL_CLAMP_TO_EDGE : GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, bAlpha ? 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(image);
return textureID;
}
void Do_Movement()
{
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);
}
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 texture1;
void main()
{
//color = texture(texture1, TexCoords);
vec4 texColor = texture(texture1, TexCoords);
if(texColor.a < 0.1)
discard;
color = texColor;
}
single_color_fragement
// 边框颜色
#version 330 core
in vec2 TexCoords;
out vec4 color;
uniform sampler2D texture1;
void main()
{
color = vec4(0.6, 0.18, 0.16, 1.0);
}
源码: VS2015
http://download.csdn.net/detail/yulinxx/9717121