计算机图形学期末大作业:实现
Skybox
天空盒,以及Shadow volume
阴影体。
写在前面
本人才疏学浅,水平有限,只实现了 Skybox
,Shadow volume
没有完全实现(我真的太菜了)。前期跟着老师课堂教学,感觉都能跟上。后期直接跳到引入 模型
,发现自己真的跟不上了。大作业做得我心态爆炸,网上教程看一下午,就是看不进去,怎么也做不出来。
加上隔得时间有点长,所以本篇博客可能写得会非常水。见谅~
一、思路
参照网上教程,完成 Skybox
天空盒部分。再实现 Shadow volume
阴影体。
二、代码
- main.cpp
//
// main.cpp
// Course 4
//
// Created by rui huang on 10/27/17.
// Copyright © 2017 rui huang. All rights reserved.
//
#include <iostream>
#define GLM_ENABLE_EXPERIMENTAL
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "Shader.h"
#include "SOIL2/SOIL2.h"
#include "SOIL2/stb_image.h"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/rotate_vector.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "Camera.h"
#include "Model.h"
#include "Mesh.h"
#include "Light.h"
const GLint WIDTH = 800, HEIGHT = 800;
void KeyCallback(GLFWwindow *window, int key, int scancode, int action, int mode);
void ScrollCallback(GLFWwindow *window, double xOffset, double yOffset);
void MouseCallback(GLFWwindow *window, double xPos, double yPos);
//
GLuint loadCubemap(vector<const GLchar*> faces);
void DoMovement();
Camera camera(glm::vec3(0.0f, 0.0f, 2.0f));
GLfloat lastX = WIDTH / 2.0;
GLfloat lastY = HEIGHT / 2.0;
bool keys[1024];
GLfloat deltaTime = 0.0f;
GLfloat lastTime = 0.0f;
bool firstMouse = true;
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_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
GLFWwindow *window = glfwCreateWindow(WIDTH, HEIGHT, "OpenGL B16xxxxxx", nullptr, nullptr);
int screenWidth, screenHeight;
glfwGetFramebufferSize(window, &screenWidth, &screenHeight);
if (nullptr == window) {
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
// Set the required callback function
glfwSetKeyCallback(window, KeyCallback);
glfwSetCursorPosCallback(window, MouseCallback);
glfwSetScrollCallback(window, ScrollCallback);
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
glewExperimental = GL_TRUE;
if (GLEW_OK != glewInit()) {
std::cout << "Failed to initialise GLEW" << std::endl;
return -1;
}
glViewport(0, 0, screenWidth, screenHeight);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
//glDepthFunc(GL_LESS);
Shader shader("shaders/modelLoad.vs", "shaders/modelLoad.frag");
Shader lightShader("shaders/core.vs", "shaders/core.frag");
Shader skyboxShader("shaders/skybox.vs", "shaders/skybox.frag");
Shader volumeShader("shaders/shadow_volume.vs", "shaders/shadow_volume.frag", "shaders/shadow_volume.geom");
Shader floor("shaders/plane.vs", "shaders/plane.frag");
//Shader floor("shaders/silhouette.vs", "shaders/silhouette.gs");
// Load models
Model ourModel((GLchar *)"models/nanosuit.obj");
Light lightModel = Light();
glm::vec3 LightPos1 = glm::vec3(1.0f, 1.5f, 0.0f);
//glm::vec3 LightPos1 = glm::vec3(15.0f, 1.5f, 2.5f); //横向光源
//glm::vec3 LightPos2 = glm::vec3(0.0f, 5.0f, 0.0f); //第一个:左右 第二个:上下 第三个:前后
//glm::vec3 LightPos3 = glm::vec3(1.3f, 0.0f, 0.0f);
float skyboxVertices[] = {
// positions
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f
};
GLfloat plainVertices[] = {
15.0f, 0.0f, 15.0f, //1.0f, 0.0f, 0.0f,
-15.0f, 0.0f, 15.0f, //1.0f, 0.0f, 0.0f,
15.0f, 0.0f, -15.0f, //1.0f, 0.0f, 0.0f,
-15.0f, 0.0f, -15.0f, //1.0f, 0.0f, 0.0f
};
unsigned int indices[] = {
0,1,3,
1,2,3
};
GLuint VBO[1], VAO[1];
glGenVertexArrays(1, VAO);
glGenBuffers(1, VBO);
glBindVertexArray(VAO[0]);
glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(plainVertices), plainVertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GL_FLOAT), (GLvoid*)0);
glEnableVertexAttribArray(0);
//glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GL_FLOAT), (GLvoid*)(3 * sizeof(GLfloat)));
//glEnableVertexAttribArray(1);
glBindVertexArray(0);
GLuint EBO;
glGenBuffers(1, &EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
// Setup skybox VAO
GLuint skyboxVAO, skyboxVBO;
glGenVertexArrays(1, &skyboxVAO);
glGenBuffers(1, &skyboxVBO);
glBindVertexArray(skyboxVAO);
glBindBuffer(GL_ARRAY_BUFFER, skyboxVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glBindVertexArray(0);
// Cubemap (Skybox)
vector<const GLchar*> faces;
faces.push_back("skybox/right.jpg");
faces.push_back("skybox/left.jpg");
faces.push_back("skybox/top.jpg");
faces.push_back("skybox/bottom.jpg");
faces.push_back("skybox/back.jpg");
faces.push_back("skybox/front.jpg");
GLuint cubemapTexture = loadCubemap(faces);
while (!glfwWindowShouldClose(window)) {
// Get the delta time between frames
GLfloat currentFrame = glfwGetTime();
deltaTime = currentFrame - lastTime;
lastTime = currentFrame;
//LightPos1 = glm::rotate(LightPos1, 0.01f, glm::vec3(0.0f, 1.0f, 0.0f));
//LightPos2 = glm::rotate(LightPos2, 0.01f, glm::vec3(1.0f, 0.0f, 0.0f));
// Check and call events
glfwPollEvents();
DoMovement();
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
//glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glm::mat4 view = camera.GetViewMatrix();
glm::mat4 projection = glm::perspective(glm::radians(camera.GetZoom()), (float)screenWidth / (float)screenHeight, 0.1f, 100.0f);
glm::mat4 model = glm::mat4(1.0f);
// Draw skybox first
glDepthMask(GL_FALSE);// 关掉深度
skyboxShader.Use();
view = glm::mat4(glm::mat3(camera.GetViewMatrix())); // Remove any translation component of the view matrix
//view = camera.GetViewMatrix();
//glm::mat4(glm::mat3(camera.GetViewMatrix()));
//glm::mat4 projection = glm::perspective(glm::radians(camera.GetZoom()), (float)screenWidth / (float)screenHeight, 0.1f, 100.0f);
//projection = glm::perspective(glm::radians(camera.GetZoom()), (float)screenWidth / (float)screenHeight, 0.1f, 100.0f);
glUniformMatrix4fv(glGetUniformLocation(skyboxShader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(glGetUniformLocation(skyboxShader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
// skybox cube
glBindVertexArray(skyboxVAO);
glActiveTexture(GL_TEXTURE0);
glUniform1i(glGetUniformLocation(shader.Program, "skybox"), 0);
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTexture);
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);
// depth
//view = camera.GetViewMatrix();
glDepthMask(GL_TRUE);
lightShader.Use();
view = camera.GetViewMatrix();
//projection = glm::perspective(glm::radians(camera.GetZoom()), (float)screenWidth / (float)screenHeight, 0.1f, 100.0f);
model = glm::mat4(1.0f);
model = glm::translate(model, LightPos1);
//model = glm::translate(model, LightPos1 + glm::vec3(0.0f, 2.0f, 0.0f));
model = glm::scale(model, glm::vec3(0.1f, 0.1f, 0.1f));
//glUniformMatrix4fv(glGetUniformLocation(lightShader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
//lightModel.Draw(lightShader);
glUniformMatrix4fv(glGetUniformLocation(lightShader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(glGetUniformLocation(lightShader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
glUniformMatrix4fv(glGetUniformLocation(lightShader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
lightModel.Draw(lightShader);
/* // 第二个光源 model = glm::mat4(1.0f); model = glm::translate(model, LightPos2); //model = glm::translate(model, LightPos2 + glm::vec3(0.0f, 2.0f, 0.0f)); model = glm::scale(model, glm::vec3(0.1f, 0.1f, 0.1f)); glUniformMatrix4fv(glGetUniformLocation(lightShader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); lightModel.Draw(lightShader); */
/* // 第三个光源 model = glm::mat4(1.0f); //model = glm::translate(model, LightPos3); model = glm::scale(model, glm::vec3(0.1f, 0.1f, 0.1f)); glUniformMatrix4fv(glGetUniformLocation(lightShader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); lightModel.Draw(lightShader); */
// model
view = camera.GetViewMatrix();
glDepthMask(GL_TRUE);
// 关闭颜色缓存写入
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
shader.Use();
model = glm::mat4(1.0f);
model = glm::scale(model, glm::vec3(0.0f, -10.0f, -20.0f));
model = glm::scale(model, glm::vec3(0.2f, 0.2f, 0.2f));
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
glUniform3f(glGetUniformLocation(shader.Program, "ViewPos"), camera.GetPosition().x, camera.GetPosition().y, camera.GetPosition().z);
glUniform3f(glGetUniformLocation(shader.Program, "LightPos1"), LightPos1.x, LightPos1.y, LightPos1.z);
//glUniform3f(glGetUniformLocation(shader.Program, "LightPos2"), LightPos2.x, LightPos2.y, LightPos2.z);
//glUniform3f(glGetUniformLocation(shader.Program, "LightPos"), LightPos3.x, LightPos3.y, LightPos3.z);
glUniform1f(glGetUniformLocation(shader.Program, "material.shininess"), 64.0f);
ourModel.Draw(shader);
glDepthMask(GL_TRUE);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
// floor
floor.Use();
model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(0.0f, -10.0f, -20.0f));
glUniformMatrix4fv(glGetUniformLocation(floor.Program, "view"), 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(glGetUniformLocation(floor.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
glUniformMatrix4fv(glGetUniformLocation(floor.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
glBindVertexArray(VAO[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
// shadow volume
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glDepthMask(GL_FALSE);
glEnable(GL_DEPTH_CLAMP);
glClear(GL_STENCIL_BUFFER_BIT);
glEnable(GL_STENCIL_TEST);
glClearStencil(1);
glStencilFunc(GL_ALWAYS, 1, 0xff);
// zfail
glStencilOpSeparate(GL_BACK, GL_KEEP, GL_INCR_WRAP, GL_KEEP);
glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_DECR_WRAP, GL_KEEP);
volumeShader.Use();
model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(0.0f, -10.0f, -20.0f));
model = glm::scale(model, glm::vec3(0.2f, 0.2f, 0.2f));
glUniformMatrix4fv(glGetUniformLocation(volumeShader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(glGetUniformLocation(volumeShader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(glGetUniformLocation(volumeShader.Program, "ProjMatrix"), 1, GL_FALSE, glm::value_ptr(projection));
glUniform3f(glGetUniformLocation(volumeShader.Program, "LightPosition"), (LightPos1).x, (LightPos1).y, (LightPos1).z);
ourModel.Draw(volumeShader);
glDisable(GL_DEPTH_CLAMP);
glDisable(GL_STENCIL_TEST);
// ambient light
glStencilFunc(GL_ALWAYS, 1, 0xff);
glDepthMask(GL_TRUE);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
floor.Use();
model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(0.0f, -10.0f, -20.0f));
glUniform1f(glGetUniformLocation(floor.Program, "ambientStrength"), 0.1f);
glUniform1f(glGetUniformLocation(floor.Program, "diffuseStrength"), 0.0f);
glUniform1f(glGetUniformLocation(floor.Program, "specularStrength"), 0.0f);
glUniformMatrix4fv(glGetUniformLocation(floor.Program, "view"), 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(glGetUniformLocation(floor.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
glUniformMatrix4fv(glGetUniformLocation(floor.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
glUniform3f(glGetUniformLocation(floor.Program, "objectColor"), 1.0f, 0.5f, 0.3f);
glUniform3f(glGetUniformLocation(floor.Program, "lightColor"), 1.0f, 1.0f, 1.0f);
glUniform3f(glGetUniformLocation(floor.Program, "lightPos"), LightPos1.x, LightPos1.y, LightPos1.z);
glUniform3f(glGetUniformLocation(floor.Program, "viewPos"), camera.GetPosition().x, camera.GetPosition().y, camera.GetPosition().z);
glBindVertexArray(VAO[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glStencilFunc(GL_ALWAYS, 1, 0xff);
shader.Use();
model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(0.0f, -10.0f, -20.0f));
model = glm::scale(model, glm::vec3(0.2f, 0.2f, 0.2f));
glUniform1f(glGetUniformLocation(shader.Program, "ambientStrength"), 0.4f);
glUniform1f(glGetUniformLocation(shader.Program, "diffuseStrength"), 0.0f);
glUniform1f(glGetUniformLocation(shader.Program, "specularStrength"), 0.0f);
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
glUniform3f(glGetUniformLocation(shader.Program, "ViewPos"), camera.GetPosition().x, camera.GetPosition().y, camera.GetPosition().z);
glUniform3f(glGetUniformLocation(shader.Program, "LightPos1"), LightPos1.x, LightPos1.y, LightPos1.z);
glUniform1f(glGetUniformLocation(shader.Program, "material.shininess"), 64.0f);
ourModel.Draw(shader);
// diffuse light
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_ONE, GL_ONE);
glDepthFunc(GL_LEQUAL);
glDepthMask(GL_TRUE);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glEnable(GL_STENCIL_TEST);
glEnable(GL_STENCIL);
glStencilFunc(GL_EQUAL, 1, 0xff);
glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_KEEP);
shader.Use();
model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(0.0f, -10.0f, -20.0f));
model = glm::scale(model, glm::vec3(0.2f, 0.2f, 0.2f));
glUniform1f(glGetUniformLocation(shader.Program, "ambientStrength"), 0.0f);
glUniform1f(glGetUniformLocation(shader.Program, "diffuseStrength"), 0.6f);
glUniform1f(glGetUniformLocation(shader.Program, "specularStrength"), 0.9f);
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
glUniform3f(glGetUniformLocation(shader.Program, "ViewPos"), camera.GetPosition().x, camera.GetPosition().y, camera.GetPosition().z);
glUniform3f(glGetUniformLocation(shader.Program, "LightPos"), LightPos1.x, LightPos1.y, LightPos1.z);
glUniform1f(glGetUniformLocation(shader.Program, "material.shininess"), 64.0f);
ourModel.Draw(shader);
glStencilFunc(GL_EQUAL, 1, 0xff);
glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_KEEP);
floor.Use();
model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(0.0f, -10.0f, -20.0f));
glUniform1f(glGetUniformLocation(floor.Program, "ambientStrength"), 0.0f);
glUniform1f(glGetUniformLocation(floor.Program, "diffuseStrength"), 0.6f);
glUniform1f(glGetUniformLocation(floor.Program, "specularStrength"), 0.9f);
glUniformMatrix4fv(glGetUniformLocation(floor.Program, "view"), 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(glGetUniformLocation(floor.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
glUniformMatrix4fv(glGetUniformLocation(floor.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
glUniform3f(glGetUniformLocation(floor.Program, "objectColor"), 1.0f, 0.5f, 0.3f);
glUniform3f(glGetUniformLocation(floor.Program, "lightColor"), 1.0f, 1.0f, 1.0f);
glUniform3f(glGetUniformLocation(floor.Program, "lightPos"), LightPos1.x, LightPos1.y, LightPos1.z);
glUniform3f(glGetUniformLocation(floor.Program, "viewPos"), camera.GetPosition().x, camera.GetPosition().y, camera.GetPosition().z);
glBindVertexArray(VAO[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glDisable(GL_STENCIL_TEST);
glDisable(GL_BLEND);
glEnable(GL_CULL_FACE);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glDisable(GL_CULL_FACE);
glDisable(GL_STENCIL_TEST);
glfwSwapBuffers(window);
}
glfwTerminate();
return 0;
}
void KeyCallback(GLFWwindow *window, int key, int scancode, int action, int mode)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
{
glfwSetWindowShouldClose(window, GL_TRUE);
}
if (key >= 0 && key < 1024)
{
if (action == GLFW_PRESS) {
keys[key] = true;
}
else if (action == GLFW_RELEASE)
{
keys[key] = false;
}
}
}
void ScrollCallback(GLFWwindow *window, double xOffset, double yOffset)
{
camera.ProcessMouseScroll(yOffset);
}
void MouseCallback(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;
// Process the camera direction
camera.ProcessMouseMovement(xOffset, yOffset);
}
void DoMovement()
{
if (keys[GLFW_KEY_W] || keys[GLFW_KEY_UP]) {
camera.ProcessKeyboard(FORWARD, deltaTime);
}
if (keys[GLFW_KEY_S] || keys[GLFW_KEY_DOWN]) {
camera.ProcessKeyboard(BACKWARD, deltaTime);
}
if (keys[GLFW_KEY_A] || keys[GLFW_KEY_LEFT]) {
camera.ProcessKeyboard(LEFT, deltaTime);
}
if (keys[GLFW_KEY_D] || keys[GLFW_KEY_RIGHT]) {
camera.ProcessKeyboard(RIGHT, deltaTime);
}
}
//Skybox
GLuint loadCubemap(vector<const GLchar*> faces)
{
GLuint textureID;
glGenTextures(1, &textureID);
glActiveTexture(GL_TEXTURE0);
int width, height;
unsigned char* image;
glBindTexture(GL_TEXTURE_CUBE_MAP, textureID);
for (GLuint i = 0; i < faces.size(); i++)
{
image = SOIL_load_image(faces[i], &width, &height, 0, SOIL_LOAD_RGB);
glTexImage2D(
GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0,
GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image
);
}
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);//GL_LINEAR整体看效果稍微模糊
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);//边界处采用纹理边缘自己的的颜色,和边框无关
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
return textureID;
}
- shadow_volume.geom
/* #version 330 layout (triangles_adjacency) in; layout (triangle_strip, max_vertices = 18) out; in vec3 WorldPos[]; uniform vec3 gLightPos; uniform mat4 gVP; float EPSILON = 0.01; void EmitQuad(int StartIndex, vec3 StartVertex, int EndIndex, vec3 EndVertex) { vec3 LightDir = normalize(StartVertex - gLightPos); vec3 l = LightDir * EPSILON; gl_Position = gVP * vec4((StartVertex + l), 1.0); EmitVertex(); gl_Position = gVP * vec4(LightDir, 0.0); EmitVertex(); LightDir = normalize(EndVertex - gLightPos); l = LightDir * EPSILON; gl_Position = gVP * vec4((EndVertex + l), 1.0); EmitVertex(); gl_Position = gVP * vec4(LightDir, 0.0); EmitVertex(); EndPrimitive(); } void main() { vec3 e1 = WorldPos[2] - WorldPos[0]; vec3 e2 = WorldPos[4] - WorldPos[0]; vec3 e3 = WorldPos[1] - WorldPos[0]; vec3 e4 = WorldPos[3] - WorldPos[2]; vec3 e5 = WorldPos[4] - WorldPos[2]; vec3 e6 = WorldPos[5] - WorldPos[0]; vec3 Normal = cross(e1,e2); vec3 LightDir = gLightPos - WorldPos[0]; if (dot(Normal, LightDir) > 0.000001) { Normal = cross(e3,e1); if (dot(Normal, LightDir) <= 0) { vec3 StartVertex = WorldPos[0]; vec3 EndVertex = WorldPos[2]; EmitQuad(0, StartVertex, 2, EndVertex); } Normal = cross(e4,e5); LightDir = gLightPos - WorldPos[2]; if (dot(Normal, LightDir) <= 0) { vec3 StartVertex = WorldPos[2]; vec3 EndVertex = WorldPos[4]; EmitQuad(2, StartVertex, 4, EndVertex); } Normal = cross(e2,e6); LightDir = gLightPos - WorldPos[4]; if (dot(Normal, LightDir) <= 0) { vec3 StartVertex = WorldPos[4]; vec3 EndVertex = WorldPos[0]; EmitQuad(4, StartVertex, 0, EndVertex); } vec3 LightDir = (normalize(WorldPos[0] - gLightPos)) * EPSILON; gl_Position = gVP * vec4((WorldPos[0] + LightDir), 1.0); EmitVertex(); LightDir = (normalize(WorldPos[2] - gLightPos)) * EPSILON; gl_Position = gVP * vec4((WorldPos[2] + LightDir), 1.0); EmitVertex(); LightDir = (normalize(WorldPos[4] - gLightPos)) * EPSILON; gl_Position = gVP * vec4((WorldPos[4] + LightDir), 1.0); EmitVertex(); EndPrimitive(); } } */
#version 430
layout(triangles_adjacency) in;
layout( triangle_strip, max_vertices = 18 ) out;
in vec3 VPosition[];
uniform vec3 LightPosition;
uniform mat4 ProjMatrix;
float EPSILON = 0.01;
bool facesLight( vec3 a, vec3 b, vec3 c )
{
vec3 n = cross( b - a, c - a );
vec3 da = LightPosition.xyz - a;
vec3 db = LightPosition.xyz - b;
vec3 dc = LightPosition.xyz - c;
return dot(n, da) > 0 || dot(n, db) > 0 || dot(n, dc) > 0;
}
void emitEdgeQuad( vec3 a, vec3 b ) {
vec3 LightDir = normalize(a - LightPosition.xyz);
vec3 deviation = LightDir * EPSILON;
gl_Position = ProjMatrix * vec4(a + deviation, 1);
EmitVertex();
gl_Position = ProjMatrix * vec4(LightDir, 0);
EmitVertex();
LightDir = normalize(b - LightPosition.xyz);
deviation = LightDir * EPSILON;
gl_Position = ProjMatrix * vec4(b + deviation, 1);
EmitVertex();
gl_Position = ProjMatrix * vec4(LightDir, 0);
EmitVertex();
EndPrimitive();
}
void main()
{
if( facesLight(VPosition[0], VPosition[2], VPosition[4]) ) {
if( ! facesLight(VPosition[0],VPosition[1],VPosition[2]) )
emitEdgeQuad(VPosition[0],VPosition[2]);
if( ! facesLight(VPosition[2],VPosition[3],VPosition[4]) )
emitEdgeQuad(VPosition[2],VPosition[4]);
if( ! facesLight(VPosition[4],VPosition[5],VPosition[0]) )
emitEdgeQuad(VPosition[4],VPosition[0]);
//FRONT CAP
vec3 LightDir = normalize(VPosition[0] - LightPosition.xyz);
vec3 deviation = LightDir * EPSILON;
gl_Position = ProjMatrix * vec4(VPosition[0] + deviation, 1);
EmitVertex();
LightDir = normalize(VPosition[2] - LightPosition.xyz);
deviation = LightDir * EPSILON;
gl_Position = ProjMatrix * vec4(VPosition[2] + deviation, 1);
EmitVertex();
LightDir = normalize(VPosition[4] - LightPosition.xyz);
deviation = LightDir * EPSILON;
gl_Position = ProjMatrix * vec4(VPosition[4] + deviation, 1);
EmitVertex();
EndPrimitive();
//BACK CAP
LightDir = normalize(VPosition[0] - LightPosition.xyz);
gl_Position = ProjMatrix * vec4(LightDir, 0);
EmitVertex();
LightDir = normalize(VPosition[4] - LightPosition.xyz);
gl_Position = ProjMatrix * vec4(LightDir, 0);
EmitVertex();
LightDir = normalize(VPosition[2] - LightPosition.xyz);
gl_Position = ProjMatrix * vec4(LightDir, 0);
EmitVertex();
EndPrimitive();
}
}
- shadow_volume.frag
#version 430
out vec4 color;
void main() {
color = vec4(1.0f, 0.0f, 0.0f, 1.0f);
}
- shadow_volume.vs
/* #version 330 layout (location = 0) in vec3 Position; layout (location = 1) in vec2 TexCoord; layout (location = 2) in vec3 Normal; out vec3 WorldPos; uniform mat4 gWVP; uniform mat4 gWorld; void main() { vec4 PosL = vec4(Position, 1.0); gl_Position = gWVP * PosL; WorldPos = (gWorld * PosL).xyz; } */
#version 430
layout (location = 0) in vec3 VertexPosition;
layout (location = 1) in vec3 VertexNormal;
out vec3 VPosition;
uniform mat4 ModelViewMatrix;
void main()
{
VPosition = (ModelViewMatrix * vec4(VertexPosition,1.0)).xyz;
}
- plane.vs
/* #version 330 layout (location = 0) in vec3 Position; layout (location = 1) in vec2 TexCoord; layout (location = 2) in vec3 Normal; out vec3 WorldPos; uniform mat4 gWVP; uniform mat4 gWorld; void main() { vec4 PosL = vec4(Position, 1.0); gl_Position = gWVP * PosL; WorldPos = (gWorld * PosL).xyz; } */
#version 430
layout (location = 0) in vec3 VertexPosition;
layout (location = 1) in vec3 VertexNormal;
out vec3 VPosition;
uniform mat4 ModelViewMatrix;
void main()
{
VPosition = (ModelViewMatrix * vec4(VertexPosition,1.0)).xyz;
}
- Camera.h
//
// Camera.h
// Course 3
//
// Created by rui huang on 10/18/17.
// Copyright © 2017 rui huang. All rights reserved.
//
#pragma once
#include <vector>
#define GLEW_STATIC
#include <GL/glew.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
enum Camera_Movement
{
FORWARD,
BACKWARD,
LEFT,
RIGHT
};
const GLfloat YAW = -90.0f;
const GLfloat PITCH = 0.0f;
const GLfloat SPEED = 6.0f;
const GLfloat SENSITIVITY = 0.25f;
const GLfloat ZOOM = 45.0f;
// An abstract camera class that processes input and calculates the corresponding Eular Angles, Vectors and Matrices for OpenGL
class Camera
{
public:
// 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(SENSITIVITY), 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 = YAW, GLfloat pitch = PITCH):front(glm::vec3(0.0f, 0.0f, -1.0f)), movementSpeed(SPEED), mouseSensitivity(SENSITIVITY), zoom(ZOOM)
{
this->position = glm::vec3(posX, posY, posZ);
this->worldUp = glm::vec3(upX, upY, upZ);
this->yaw = yaw;
this->pitch = pitch;
this->updateCameraVectors();
}
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 constrainPith = true)
{
xOffset *= this->mouseSensitivity;
yOffset *= this->mouseSensitivity;
this->yaw += xOffset;
this->pitch +=yOffset;
if (constrainPith) {
if (this->pitch >89.0f) {
this->pitch = 89.0f;
}
if (this->pitch < -89.0f) {
this->pitch = -89.0f;
}
}
this->updateCameraVectors();
}
void ProcessMouseScroll( GLfloat yOffset)
{
if ( this->zoom >= 1.0f && this->zoom <= 60.0f )
{
this->zoom += yOffset;
}
if ( this->zoom <= 1.0f )
{
this->zoom = 1.0f;
}
if ( this->zoom >= 60.0f )
{
this->zoom = 60.0f;
}
}
glm::mat4 GetViewMatrix()
{
return glm::lookAt( this->position, this->position+this->front, this->up);
}
GLfloat GetZoom()
{
return this->zoom;
}
glm::vec3 GetPosition()
{
return this->position;
}
private:
glm::vec3 position;
glm::vec3 front;
glm::vec3 up;
glm::vec3 right;
glm::vec3 worldUp;
GLfloat yaw;
GLfloat pitch;
GLfloat movementSpeed;
GLfloat mouseSensitivity;
GLfloat zoom;
void updateCameraVectors()
{
glm::vec3 front;
front.x = cos( glm::radians(this->pitch)) * cos( glm::radians(this->yaw));
front.y = sin( glm::radians(this->pitch));
front.z = cos( glm::radians(this->pitch)) * sin( glm::radians(this->yaw));
this->front = glm::normalize( front );
this->right = glm::normalize(glm::cross(this->front, this->worldUp));
this->up = glm::normalize(glm::cross(this->right, this->front));
}
};
- Light.h
//
// Light.h
// Course 4
//
// Created by rui huang on 11/15/17.
// Copyright © 2017 rui huang. All rights reserved.
//
#pragma once
#include <GL/glew.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
GLfloat vertices[] =
{
-0.5f, -0.5f, -0.5f,
0.5f, -0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
-0.5f, 0.5f, -0.5f,
-0.5f, -0.5f, -0.5f,
-0.5f, -0.5f, 0.5f,
0.5f, -0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
-0.5f, -0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, -0.5f,
-0.5f, -0.5f, -0.5f,
-0.5f, -0.5f, -0.5f,
-0.5f, -0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
0.5f, 0.5f, -0.5f,
0.5f, -0.5f, -0.5f,
0.5f, -0.5f, -0.5f,
0.5f, -0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
-0.5f, -0.5f, -0.5f,
0.5f, -0.5f, -0.5f,
0.5f, -0.5f, 0.5f,
0.5f, -0.5f, 0.5f,
-0.5f, -0.5f, 0.5f,
-0.5f, -0.5f, -0.5f,
-0.5f, 0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
0.5f, 0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, -0.5f
};
class Light{
public:
Light()
{
this->update();
}
void Draw(Shader &shader)
{
glBindVertexArray(this->VAO);
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);
}
private:
GLuint VAO, VBO;
void update()
{
glGenVertexArrays(1, &this->VAO);
glGenBuffers(1, &this->VBO);
glBindVertexArray(this->VAO);
glBindBuffer(GL_ARRAY_BUFFER, this->VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindVertexArray(0);
}
};
- Model.h
//
// Model.h
// Course 4
//
// Created by rui huang on 11/1/17.
// Copyright © 2017 rui huang. All rights reserved.
//
#pragma once
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <map>
#include <vector>
#include <GL/glew.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include "SOIL2/SOIL2.h"
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
#include "Mesh.h"
using namespace std;
GLint TextureFromFile( const char *path, string directory);
class Model
{
public:
Model( GLchar *path)
{
this->loadModel(path);
}
void Draw( Shader &shader)
{
for ( GLuint i = 0; i < this->meshes.size( ); i++ )
{
this->meshes[i].Draw( shader );
}
}
private:
// Model Data
vector<Mesh> meshes;
string directory;
vector<Texture> textures_loaded;
// Functions
void loadModel( string path)
{
// Read file via ASSIMP
Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(path,
aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_GenNormals);
// Check for errors
if (!scene || scene->mFlags == AI_SCENE_FLAGS_INCOMPLETE|| !scene->mRootNode) {
cout << "ERROR::ASSIMP:: " << importer.GetErrorString() << endl;
return;
}
this->directory = path.substr(0, path.find_last_of( '/'));
this->processNode( scene->mRootNode, scene);
}
void processNode(aiNode *node, const aiScene *scene)
{
// Process each mesh located at the current node
for ( GLuint i = 0; i < node->mNumMeshes; i++)
{
aiMesh *mesh = scene->mMeshes[node->mMeshes[i]];
this->meshes.push_back( this->processMesh( mesh, scene));
}
for (GLuint i = 0; i<node->mNumChildren; i++)
{
this->processNode(node->mChildren[i], scene);
}
}
Mesh processMesh( aiMesh *mesh, const aiScene *scene )
{
// Data to fill
vector<Vertex> vertices;
vector<GLuint> indices;
vector<Texture> textures;
// each of the mesh's vertices
for (GLuint i = 0; i< mesh->mNumVertices; i++) {
Vertex vertex;
glm::vec3 vector;
// Positions
vector.x = mesh->mVertices[i].x;
vector.y = mesh->mVertices[i].y;
vector.z = mesh->mVertices[i].z;
vertex.Position = vector;
// Normals
vector.x = mesh->mNormals[i].x;
vector.y = mesh->mNormals[i].y;
vector.z = mesh->mNormals[i].z;
vertex.Normal = vector;
// UV coords
if (mesh->mTextureCoords[0]) {
glm::vec2 vec;
vec.x = mesh->mTextureCoords[0][i].x;
vec.y = mesh->mTextureCoords[0][i].y;
vertex.TexCoords = vec;
} else{
vertex.TexCoords = glm::vec2( 0.0f, 0.0f);
}
vertices.push_back( vertex);
}
// Indices
for ( GLuint i = 0; i<mesh->mNumFaces; i++)
{
aiFace face = mesh->mFaces[i];
for (GLuint j = 0; j < face.mNumIndices; j++)
{
indices.push_back(face.mIndices[j]);
}
}
// Process materials
if (mesh->mMaterialIndex >= 0) {
aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
// 1. Diffuse maps
vector<Texture> diffuseMaps = this->loadMaterialTextures( material, aiTextureType_DIFFUSE, "texture_diffuse");
textures.insert( textures.end(), diffuseMaps.begin(), diffuseMaps.end());
// 2. Specular maps
vector<Texture> specularMaps = this->loadMaterialTextures( material, aiTextureType_SPECULAR, "texture_specular");
textures.insert( textures.end(), specularMaps.begin(), specularMaps.end());
}
return Mesh( vertices, indices, textures);
}
vector<Texture> loadMaterialTextures( aiMaterial * mat, aiTextureType type, string typeName)
{
vector<Texture> textures;
for ( GLuint i = 0; i < mat->GetTextureCount(type); i++)
{
aiString str;
mat->GetTexture(type, i, &str);
// Check if texture was loaded before
GLboolean skip = false;
for ( GLuint j = 0; j < this->textures_loaded.size(); j++)
{
if (this->textures_loaded[j].path == str) {
textures.push_back(this->textures_loaded[j]);
skip = true;
break;
}
}
if (!skip)
{
Texture texture;
texture.id = TextureFromFile( str.C_Str(), this->directory);
texture.type = typeName;
texture.path = str;
textures.push_back(texture);
this->textures_loaded.push_back( texture);
}
}
return textures;
}
};
GLint TextureFromFile( const char *path, string directory)
{
string filename = string(path);
filename = directory + '/' + filename;
GLuint textureID;
glGenTextures(1, &textureID);
int width, height;
unsigned char *image = SOIL_load_image(filename.c_str(), &width, &height, 0, SOIL_LOAD_RGBA);
// Assign texture to ID
glBindTexture( GL_TEXTURE_2D, textureID );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image );
glGenerateMipmap(GL_TEXTURE_2D);
// Parameters
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);
glBindTexture( GL_TEXTURE_2D, 0 );
SOIL_free_image_data( image );
return textureID;
}
- plane.frag
#version 430
in vec3 Position;
in vec3 Normal;
//in vec3 ourColor;
//out vec4 color;
uniform vec4 LightPosition;
uniform float LightIntensity;
uniform vec3 u_color;
layout( location = 0 ) out vec4 Ambient;
layout( location = 1 ) out vec4 DiffSpec;
void main() {
vec3 toLight = normalize(vec3(LightPosition) - Position);
vec3 toV = normalize(vec3(-Position));
vec3 r = reflect( -toLight, Normal );
//color = vec4(ourColor, 0.7f);
//color = vec4(1.0f, 0.0f, 0.0f, 0.1f);
float diffuse = max(0.0f, dot(Normal, toLight));
float specular = pow(max(0.0, dot(r, Normal)), 640.0);
Ambient = vec4(u_color, 1.0f) * 0.2f *LightIntensity;
DiffSpec =vec4(u_color, 1.0f)*(diffuse+specular)*LightIntensity+Ambient;
}
- Shader.h
#pragma once
//#ifndef shader_h
//#define shader_h
//#endif // !shader.hpp
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <GL/glew.h>
class Shader {
GLuint vertex, fragment, geometry;
bool flag = false;
public:
GLuint Program;
Shader(const GLchar *vertexPath, const GLchar *fragmentPath, const GLchar* geometryPath = nullptr) {
std::string vertexCode;
std::string fragmentCode;
std::string geometryCode;
std::ifstream vShaderFile;
std::ifstream fShaderFile;
std::ifstream gShaderFile;
vShaderFile.exceptions(std::ifstream::badbit | std::ifstream::badbit);
fShaderFile.exceptions(std::ifstream::badbit | std::ifstream::badbit);
gShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
try {
// 打开文件
vShaderFile.open(vertexPath);
fShaderFile.open(fragmentPath);
//gShaderFile.open(geometryPath);
std::stringstream vShaderStream, fShaderStream;
// 读取文件
vShaderStream << vShaderFile.rdbuf();
fShaderStream << fShaderFile.rdbuf();
//gShaderStream << gShaderFile.rdbuf();
// 关闭文件
vShaderFile.close();
fShaderFile.close();
//gShaderFile.close();
//将流转换为字符串
vertexCode = vShaderStream.str();
fragmentCode = fShaderStream.str();
//geometryCode = gShaderStream.str();
}
catch (std::ifstream::failure e) {
std::cout << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ" << std::endl;
}
// 编译着色器
const GLchar *vShaderCode = vertexCode.c_str();
const GLchar *fShaderCode = fragmentCode.c_str();
//const GLchar *gShaderCode = geometryCode.c_str();
vertex = glCreateShader(GL_VERTEX_SHADER);//顶点调色器
glShaderSource(vertex, 1, &vShaderCode, NULL);
glCompileShader(vertex);//编译
GLint success;
GLchar infoLog[512];
glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);//获取编译情况
if (!success) {
glGetShaderInfoLog(vertex, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
fragment = glCreateShader(GL_FRAGMENT_SHADER);//片元调色器
glShaderSource(fragment, 1, &fShaderCode, NULL);
glCompileShader(fragment);//编译
glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(fragment, 512, NULL, infoLog);
std::cout << "ERROR::SHADER:fragment::COMPILATION_FAILED\n" << infoLog << std::endl;
}
if (geometryPath != nullptr) {
flag = true;
const char * gShaderCode = geometryCode.c_str();
geometry = glCreateShader(GL_GEOMETRY_SHADER);//几何着色器
glShaderSource(geometry, 1, &gShaderCode, NULL);
glCompileShader(geometry);
glGetShaderiv(geometry, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(geometry, 512, NULL, infoLog);
std::cout << "ERROR::SHADER:geometry::COMPILATION_FAILED\n" << infoLog << std::endl;
}
}
//链接
this->Program = glCreateProgram();//创建着色器程序
glAttachShader(this->Program, vertex);
glAttachShader(this->Program, fragment);
if (geometryPath != nullptr)
glAttachShader(this->Program, geometry);
glLinkProgram(this->Program);//链接
glValidateProgram(this->Program);
glGetProgramiv(this->Program, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(this->Program, 512, NULL, infoLog);//获取链接情况
std::cout << "ERROR::SHADER:PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
}
}
~Shader() {
glDetachShader(this->Program, vertex);
glDetachShader(this->Program, fragment);
// 删除着色器
glDeleteShader(vertex);
glDeleteShader(fragment);
if (flag == true)
glDeleteShader(geometry);
glDeleteProgram(this->Program);
}
void Use() {
glUseProgram(this->Program);
}
};
- skybox.frag
#version 330 core
in vec3 TexCoords;
out vec4 color;
uniform samplerCube skybox; // 立方体贴图纹理采样器
void main()
{
color = texture(skybox, TexCoords);
}
- skybox.vs
#version 330 core
layout (location = 0) in vec3 position;
out vec3 TexCoords;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * vec4(position, 1.0f);
TexCoords = position;
}
程序正常运行,能得到以下结果。(GIF文件太大,传个截图随便看看吧:)
三、讲解
1. Skybox
天空盒部分网上官方教程写得还是很详细的。
2. Shadow volume
注意,要用到 Stencil Buffer
。
显示阴影有两种方法:Z-pass 算法
和 Z-fail 算法
。