Merge branch 'JoeyDeVries:master' into master

This commit is contained in:
Ankit Singh Kushwah
2022-03-02 09:13:08 +05:30
committed by GitHub
5 changed files with 363 additions and 14 deletions

View File

@@ -0,0 +1,235 @@
#ifndef SHADER_H
#define SHADER_H
#include <glad/glad.h>
#include <glm/glm.hpp>
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
class Shader
{
public:
unsigned int ID;
// constructor generates the shader on the fly
// ------------------------------------------------------------------------
Shader(const char* vertexPath, const char* fragmentPath, const char* geometryPath = nullptr,
const char* tessControlPath = nullptr, const char* tessEvalPath = nullptr)
{
// 1. retrieve the vertex/fragment source code from filePath
std::string vertexCode;
std::string fragmentCode;
std::string geometryCode;
std::string tessControlCode;
std::string tessEvalCode;
std::ifstream vShaderFile;
std::ifstream fShaderFile;
std::ifstream gShaderFile;
std::ifstream tcShaderFile;
std::ifstream teShaderFile;
// ensure ifstream objects can throw exceptions:
vShaderFile.exceptions (std::ifstream::failbit | std::ifstream::badbit);
fShaderFile.exceptions (std::ifstream::failbit | std::ifstream::badbit);
gShaderFile.exceptions (std::ifstream::failbit | std::ifstream::badbit);
tcShaderFile.exceptions (std::ifstream::failbit | std::ifstream::badbit);
teShaderFile.exceptions (std::ifstream::failbit | std::ifstream::badbit);
try
{
// open files
vShaderFile.open(vertexPath);
fShaderFile.open(fragmentPath);
std::stringstream vShaderStream, fShaderStream;
// read file's buffer contents into streams
vShaderStream << vShaderFile.rdbuf();
fShaderStream << fShaderFile.rdbuf();
// close file handlers
vShaderFile.close();
fShaderFile.close();
// convert stream into string
vertexCode = vShaderStream.str();
fragmentCode = fShaderStream.str();
// if geometry shader path is present, also load a geometry shader
if(geometryPath != nullptr)
{
gShaderFile.open(geometryPath);
std::stringstream gShaderStream;
gShaderStream << gShaderFile.rdbuf();
gShaderFile.close();
geometryCode = gShaderStream.str();
}
if(tessControlPath != nullptr) {
tcShaderFile.open(tessControlPath);
std::stringstream tcShaderStream;
tcShaderStream << tcShaderFile.rdbuf();
tcShaderFile.close();
tessControlCode = tcShaderStream.str();
}
if(tessEvalPath != nullptr) {
teShaderFile.open(tessEvalPath);
std::stringstream teShaderStream;
teShaderStream << teShaderFile.rdbuf();
teShaderFile.close();
tessEvalCode = teShaderStream.str();
}
}
catch (std::ifstream::failure& e)
{
std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl;
}
const char* vShaderCode = vertexCode.c_str();
const char * fShaderCode = fragmentCode.c_str();
// 2. compile shaders
unsigned int vertex, fragment;
// vertex shader
vertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex, 1, &vShaderCode, NULL);
glCompileShader(vertex);
checkCompileErrors(vertex, "VERTEX");
// fragment Shader
fragment = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment, 1, &fShaderCode, NULL);
glCompileShader(fragment);
checkCompileErrors(fragment, "FRAGMENT");
// if geometry shader is given, compile geometry shader
unsigned int geometry;
if(geometryPath != nullptr)
{
const char * gShaderCode = geometryCode.c_str();
geometry = glCreateShader(GL_GEOMETRY_SHADER);
glShaderSource(geometry, 1, &gShaderCode, NULL);
glCompileShader(geometry);
checkCompileErrors(geometry, "GEOMETRY");
}
// if tessellation shader is given, compile tessellation shader
unsigned int tessControl;
if(tessControlPath != nullptr)
{
const char * tcShaderCode = tessControlCode.c_str();
tessControl = glCreateShader(GL_TESS_CONTROL_SHADER);
glShaderSource(tessControl, 1, &tcShaderCode, NULL);
glCompileShader(tessControl);
checkCompileErrors(tessControl, "TESS_CONTROL");
}
unsigned int tessEval;
if(tessEvalPath != nullptr)
{
const char * teShaderCode = tessEvalCode.c_str();
tessEval = glCreateShader(GL_TESS_EVALUATION_SHADER);
glShaderSource(tessEval, 1, &teShaderCode, NULL);
glCompileShader(tessEval);
checkCompileErrors(tessEval, "TESS_EVALUATION");
}
// shader Program
ID = glCreateProgram();
glAttachShader(ID, vertex);
glAttachShader(ID, fragment);
if(geometryPath != nullptr)
glAttachShader(ID, geometry);
if(tessControlPath != nullptr)
glAttachShader(ID, tessControl);
if(tessEvalPath != nullptr)
glAttachShader(ID, tessEval);
glLinkProgram(ID);
checkCompileErrors(ID, "PROGRAM");
// delete the shaders as they're linked into our program now and no longer necessery
glDeleteShader(vertex);
glDeleteShader(fragment);
if(geometryPath != nullptr)
glDeleteShader(geometry);
}
// activate the shader
// ------------------------------------------------------------------------
void use()
{
glUseProgram(ID);
}
// utility uniform functions
// ------------------------------------------------------------------------
void setBool(const std::string &name, bool value) const
{
glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value);
}
// ------------------------------------------------------------------------
void setInt(const std::string &name, int value) const
{
glUniform1i(glGetUniformLocation(ID, name.c_str()), value);
}
// ------------------------------------------------------------------------
void setFloat(const std::string &name, float value) const
{
glUniform1f(glGetUniformLocation(ID, name.c_str()), value);
}
// ------------------------------------------------------------------------
void setVec2(const std::string &name, const glm::vec2 &value) const
{
glUniform2fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]);
}
void setVec2(const std::string &name, float x, float y) const
{
glUniform2f(glGetUniformLocation(ID, name.c_str()), x, y);
}
// ------------------------------------------------------------------------
void setVec3(const std::string &name, const glm::vec3 &value) const
{
glUniform3fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]);
}
void setVec3(const std::string &name, float x, float y, float z) const
{
glUniform3f(glGetUniformLocation(ID, name.c_str()), x, y, z);
}
// ------------------------------------------------------------------------
void setVec4(const std::string &name, const glm::vec4 &value) const
{
glUniform4fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]);
}
void setVec4(const std::string &name, float x, float y, float z, float w)
{
glUniform4f(glGetUniformLocation(ID, name.c_str()), x, y, z, w);
}
// ------------------------------------------------------------------------
void setMat2(const std::string &name, const glm::mat2 &mat) const
{
glUniformMatrix2fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]);
}
// ------------------------------------------------------------------------
void setMat3(const std::string &name, const glm::mat3 &mat) const
{
glUniformMatrix3fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]);
}
// ------------------------------------------------------------------------
void setMat4(const std::string &name, const glm::mat4 &mat) const
{
glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]);
}
private:
// utility function for checking shader compilation/linking errors.
// ------------------------------------------------------------------------
void checkCompileErrors(GLuint shader, std::string type)
{
GLint success;
GLchar infoLog[1024];
if(type != "PROGRAM")
{
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if(!success)
{
glGetShaderInfoLog(shader, 1024, NULL, infoLog);
std::cout << "ERROR::SHADER_COMPILATION_ERROR of type: " << type << "\n" << infoLog << "\n -- --------------------------------------------------- -- " << std::endl;
}
}
else
{
glGetProgramiv(shader, GL_LINK_STATUS, &success);
if(!success)
{
glGetProgramInfoLog(shader, 1024, NULL, infoLog);
std::cout << "ERROR::PROGRAM_LINKING_ERROR of type: " << type << "\n" << infoLog << "\n -- --------------------------------------------------- -- " << std::endl;
}
}
}
};
#endif

View File

@@ -0,0 +1,9 @@
#version 460 core
out vec4 FragColor;
uniform vec4 color;
void main()
{
FragColor = color;
}

View File

@@ -0,0 +1,10 @@
#version 460 core
layout (location = 0) in vec3 aPos;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * vec4(aPos, 1.0);
}

View File

@@ -51,20 +51,23 @@ float ShadowCalculation(vec3 fragPosWorldSpace)
// get depth of current fragment from light's perspective
float currentDepth = projCoords.z;
if (currentDepth > 1.0)
// keep the shadow at 0.0 when outside the far_plane region of the light's frustum.
if (currentDepth > 1.0)
{
return 0.0;
}
// calculate bias (based on depth map resolution and slope)
vec3 normal = normalize(fs_in.Normal);
float bias = max(0.05 * (1.0 - dot(normal, lightDir)), 0.005);
const float biasModifier = 0.5f;
if (layer == cascadeCount)
{
bias *= 1 / (farPlane * 0.5f);
bias *= 1 / (farPlane * biasModifier);
}
else
{
bias *= 1 / (cascadePlaneDistances[layer] * 0.5f);
bias *= 1 / (cascadePlaneDistances[layer] * biasModifier);
}
// PCF
@@ -74,17 +77,11 @@ float ShadowCalculation(vec3 fragPosWorldSpace)
{
for(int y = -1; y <= 1; ++y)
{
float pcfDepth = texture(shadowMap, vec3(projCoords.xy + vec2(x, y) * texelSize, layer)).r;
float pcfDepth = texture(shadowMap, vec3(projCoords.xy + vec2(x, y) * texelSize, layer)).r;
shadow += (currentDepth - bias) > pcfDepth ? 1.0 : 0.0;
}
}
shadow /= 9.0;
// keep the shadow at 0.0 when outside the far_plane region of the light's frustum.
if(projCoords.z > 1.0)
{
shadow = 0.0;
}
return shadow;
}

View File

@@ -23,6 +23,8 @@ void renderScene(const Shader &shader);
void renderCube();
void renderQuad();
std::vector<glm::mat4> getLightSpaceMatrices();
std::vector<glm::vec4> getFrustumCornersWorldSpace(const glm::mat4& projview);
void drawCascadeVolumeVisualizers(const std::vector<glm::mat4>& lightMatrices, Shader* shader);
// settings
const unsigned int SCR_WIDTH = 2560;
@@ -58,8 +60,11 @@ bool showQuad = false;
std::random_device device;
std::mt19937 generator = std::mt19937(device());
std::vector<glm::mat4> lightMatricesCache;
int main()
{
//generator.seed(2);
// glfw: initialize and configure
// ------------------------------
glfwInit();
@@ -105,6 +110,7 @@ int main()
Shader shader("10.shadow_mapping.vs", "10.shadow_mapping.fs");
Shader simpleDepthShader("10.shadow_mapping_depth.vs", "10.shadow_mapping_depth.fs", "10.shadow_mapping_depth.gs");
Shader debugDepthQuad("10.debug_quad.vs", "10.debug_quad_depth.fs");
Shader debugCascadeShader("10.debug_cascade.vs", "10.debug_cascade.fs");
// set up vertex data (and buffer(s)) and configure vertex attributes
// ------------------------------------------------------------------
@@ -261,6 +267,17 @@ int main()
glBindTexture(GL_TEXTURE_2D_ARRAY, lightDepthMaps);
renderScene(shader);
if (lightMatricesCache.size() != 0)
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
debugCascadeShader.use();
debugCascadeShader.setMat4("projection", projection);
debugCascadeShader.setMat4("view", view);
drawCascadeVolumeVisualizers(lightMatricesCache, &debugCascadeShader);
glDisable(GL_BLEND);
}
// render Depth map to quad for visual debugging
// ---------------------------------------------
debugDepthQuad.use();
@@ -271,7 +288,6 @@ int main()
{
renderQuad();
}
std::cout << glm::length(camera.Position) << "\n";
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
// -------------------------------------------------------------------------------
@@ -429,6 +445,76 @@ void renderQuad()
glBindVertexArray(0);
}
std::vector<GLuint> visualizerVAOs;
std::vector<GLuint> visualizerVBOs;
std::vector<GLuint> visualizerEBOs;
void drawCascadeVolumeVisualizers(const std::vector<glm::mat4>& lightMatrices, Shader* shader)
{
visualizerVAOs.resize(8);
visualizerEBOs.resize(8);
visualizerVBOs.resize(8);
const GLuint indices[] = {
0, 2, 3,
0, 3, 1,
4, 6, 2,
4, 2, 0,
5, 7, 6,
5, 6, 4,
1, 3, 7,
1, 7, 5,
6, 7, 3,
6, 3, 2,
1, 5, 4,
0, 1, 4
};
const glm::vec4 colors[] = {
{1.0, 0.0, 0.0, 0.5f},
{0.0, 1.0, 0.0, 0.5f},
{0.0, 0.0, 1.0, 0.5f},
};
for (int i = 0; i < lightMatrices.size(); ++i)
{
const auto corners = getFrustumCornersWorldSpace(lightMatrices[i]);
std::vector<glm::vec3> vec3s;
for (const auto& v : corners)
{
vec3s.push_back(glm::vec3(v));
}
glGenVertexArrays(1, &visualizerVAOs[i]);
glGenBuffers(1, &visualizerVBOs[i]);
glGenBuffers(1, &visualizerEBOs[i]);
glBindVertexArray(visualizerVAOs[i]);
glBindBuffer(GL_ARRAY_BUFFER, visualizerVBOs[i]);
glBufferData(GL_ARRAY_BUFFER, vec3s.size() * sizeof(glm::vec3), &vec3s[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, visualizerEBOs[i]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 36 * sizeof(GLuint), &indices[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), (void*)0);
glBindVertexArray(visualizerVAOs[i]);
shader->setVec4("color", colors[i % 3]);
glDrawElements(GL_TRIANGLES, GLsizei(36), GL_UNSIGNED_INT, 0);
glDeleteBuffers(1, &visualizerVBOs[i]);
glDeleteBuffers(1, &visualizerEBOs[i]);
glDeleteVertexArrays(1, &visualizerVAOs[i]);
glBindVertexArray(0);
}
visualizerVAOs.clear();
visualizerEBOs.clear();
visualizerVBOs.clear();
}
// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
// ---------------------------------------------------------------------------------------------------------
void processInput(GLFWwindow *window)
@@ -464,6 +550,13 @@ void processInput(GLFWwindow *window)
}
}
plusPress = glfwGetKey(window, GLFW_KEY_KP_ADD);
static int cPress = GLFW_RELEASE;
if (glfwGetKey(window, GLFW_KEY_C) == GLFW_RELEASE && cPress == GLFW_PRESS)
{
lightMatricesCache = getLightSpaceMatrices();
}
cPress = glfwGetKey(window, GLFW_KEY_C);
}
// glfw: whenever the window size changed (by OS or user resize) this callback function executes
@@ -541,10 +634,9 @@ unsigned int loadTexture(char const * path)
return textureID;
}
std::vector<glm::vec4> getFrustumCornersWorldSpace(const glm::mat4& proj, const glm::mat4& view)
std::vector<glm::vec4> getFrustumCornersWorldSpace(const glm::mat4& projview)
{
const auto inv = glm::inverse(proj * view);
const auto inv = glm::inverse(projview);
std::vector<glm::vec4> frustumCorners;
for (unsigned int x = 0; x < 2; ++x)
@@ -562,6 +654,12 @@ std::vector<glm::vec4> getFrustumCornersWorldSpace(const glm::mat4& proj, const
return frustumCorners;
}
std::vector<glm::vec4> getFrustumCornersWorldSpace(const glm::mat4& proj, const glm::mat4& view)
{
return getFrustumCornersWorldSpace(proj * view);
}
glm::mat4 getLightSpaceMatrix(const float nearPlane, const float farPlane)
{
const auto proj = glm::perspective(