mirror of
https://github.com/JoeyDeVries/LearnOpenGL.git
synced 2026-01-30 20:13:22 +08:00
New tutorial code
New tutorial code
This commit is contained in:
@@ -115,8 +115,8 @@ int main()
|
|||||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view));
|
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, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
|
||||||
// Render normal-mapped quad
|
// Render normal-mapped quad
|
||||||
glm::mat4 model;
|
glm::mat4 model;
|
||||||
model = glm::rotate(model, (GLfloat)glfwGetTime() * -10, glm::normalize(glm::vec3(1.0, 0.0, 1.0))); // Rotates the quad to show parallax mapping works in all directions
|
//model = glm::rotate(model, (GLfloat)glfwGetTime() * -10, glm::normalize(glm::vec3(1.0, 0.0, 1.0))); // Rotates the quad to show parallax mapping works in all directions
|
||||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||||
glUniform3fv(glGetUniformLocation(shader.Program, "lightPos"), 1, &lightPos[0]);
|
glUniform3fv(glGetUniformLocation(shader.Program, "lightPos"), 1, &lightPos[0]);
|
||||||
glUniform3fv(glGetUniformLocation(shader.Program, "viewPos"), 1, &camera.Position[0]);
|
glUniform3fv(glGetUniformLocation(shader.Program, "viewPos"), 1, &camera.Position[0]);
|
||||||
@@ -282,9 +282,9 @@ void Do_Movement()
|
|||||||
|
|
||||||
// Change parallax height scale
|
// Change parallax height scale
|
||||||
if (keys[GLFW_KEY_Q])
|
if (keys[GLFW_KEY_Q])
|
||||||
height_scale -= 0.001;
|
height_scale -= 0.05 * deltaTime;
|
||||||
else if (keys[GLFW_KEY_E])
|
else if (keys[GLFW_KEY_E])
|
||||||
height_scale += 0.001;
|
height_scale += 0.05 * deltaTime;
|
||||||
|
|
||||||
// Enable/disable parallax mapping
|
// Enable/disable parallax mapping
|
||||||
if (keys[GLFW_KEY_SPACE] && !keysPressed[GLFW_KEY_SPACE])
|
if (keys[GLFW_KEY_SPACE] && !keysPressed[GLFW_KEY_SPACE])
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ vec2 ParallaxMapping(vec2 texCoords, vec3 viewDir)
|
|||||||
// return texCoords - viewDir.xy * (height * height_scale);
|
// return texCoords - viewDir.xy * (height * height_scale);
|
||||||
|
|
||||||
// number of depth layers
|
// number of depth layers
|
||||||
const float minLayers = 10;
|
const float minLayers = 8;
|
||||||
const float maxLayers = 20;
|
const float maxLayers = 32;
|
||||||
float numLayers = mix(maxLayers, minLayers, abs(dot(vec3(0.0, 0.0, 1.0), viewDir)));
|
float numLayers = mix(maxLayers, minLayers, abs(dot(vec3(0.0, 0.0, 1.0), viewDir)));
|
||||||
// calculate the size of each layer
|
// calculate the size of each layer
|
||||||
float layerDepth = 1.0 / numLayers;
|
float layerDepth = 1.0 / numLayers;
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
// Std. Includes
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
// GLEW
|
// GLEW
|
||||||
#define GLEW_STATIC
|
#define GLEW_STATIC
|
||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
@@ -21,7 +18,7 @@
|
|||||||
#include <SOIL.h>
|
#include <SOIL.h>
|
||||||
|
|
||||||
// Properties
|
// Properties
|
||||||
GLuint screenWidth = 800, screenHeight = 600;
|
const GLuint SCR_WIDTH = 800, SCR_HEIGHT = 600;
|
||||||
|
|
||||||
// Function prototypes
|
// Function prototypes
|
||||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
|
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
|
||||||
@@ -29,16 +26,24 @@ void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
|
|||||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
|
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
|
||||||
void Do_Movement();
|
void Do_Movement();
|
||||||
GLuint loadTexture(GLchar* path);
|
GLuint loadTexture(GLchar* path);
|
||||||
|
void RenderScene(Shader &shader);
|
||||||
|
void RenderCube();
|
||||||
|
void RenderQuad();
|
||||||
|
|
||||||
// Camera
|
// Camera
|
||||||
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
|
Camera camera(glm::vec3(0.0f, 0.0f, 5.0f));
|
||||||
bool keys[1024];
|
|
||||||
GLfloat lastX = 400, lastY = 300;
|
|
||||||
bool firstMouse = true;
|
|
||||||
|
|
||||||
|
// Delta
|
||||||
GLfloat deltaTime = 0.0f;
|
GLfloat deltaTime = 0.0f;
|
||||||
GLfloat lastFrame = 0.0f;
|
GLfloat lastFrame = 0.0f;
|
||||||
|
|
||||||
|
// Options
|
||||||
|
GLboolean hdr = true; // Change with 'Space'
|
||||||
|
GLfloat exposure = 1.0f; // Change with Q and E
|
||||||
|
|
||||||
|
// Global variables
|
||||||
|
GLuint woodTexture;
|
||||||
|
|
||||||
// The MAIN function, from here we start our application and run our Game loop
|
// The MAIN function, from here we start our application and run our Game loop
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
@@ -49,7 +54,7 @@ int main()
|
|||||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||||
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
|
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
|
||||||
|
|
||||||
GLFWwindow* window = glfwCreateWindow(screenWidth, screenHeight, "LearnOpenGL", nullptr, nullptr); // Windowed
|
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", nullptr, nullptr); // Windowed
|
||||||
glfwMakeContextCurrent(window);
|
glfwMakeContextCurrent(window);
|
||||||
|
|
||||||
// Set the required callback functions
|
// Set the required callback functions
|
||||||
@@ -65,103 +70,59 @@ int main()
|
|||||||
glewInit();
|
glewInit();
|
||||||
|
|
||||||
// Define the viewport dimensions
|
// Define the viewport dimensions
|
||||||
glViewport(0, 0, screenWidth, screenHeight);
|
glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT);
|
||||||
|
|
||||||
// Setup some OpenGL options
|
// Setup some OpenGL options
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
// glDepthFunc(GL_ALWAYS); // Set to always pass the depth test (same effect as glDisable(GL_DEPTH_TEST))
|
|
||||||
|
|
||||||
// Setup and compile our shaders
|
// Setup and compile our shaders
|
||||||
Shader shader("depth_testing.vs", "depth_testing.frag");
|
Shader shader("lighting.vs", "lighting.frag");
|
||||||
|
Shader hdrShader("hdr.vs", "hdr.frag");
|
||||||
|
|
||||||
#pragma region "object_initialization"
|
// Light sources
|
||||||
// Set the object data (buffers, vertex attributes)
|
// - Positions
|
||||||
GLfloat cubeVertices[] = {
|
std::vector<glm::vec3> lightPositions;
|
||||||
// Positions // Texture Coords
|
lightPositions.push_back(glm::vec3(0.0f, 0.0f, 49.5f)); // back light
|
||||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
|
lightPositions.push_back(glm::vec3(-1.4f, -1.9f, 9.0f));
|
||||||
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
|
lightPositions.push_back(glm::vec3(0.0f, -1.8f, 4.0f));
|
||||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
lightPositions.push_back(glm::vec3(0.8f, -1.7f, 6.0f));
|
||||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
// - Colors
|
||||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
|
std::vector<glm::vec3> lightColors;
|
||||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
|
lightColors.push_back(glm::vec3(200.0f, 200.0f, 200.0f));
|
||||||
|
lightColors.push_back(glm::vec3(0.1f, 0.0f, 0.0f));
|
||||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
lightColors.push_back(glm::vec3(0.0f, 0.0f, 0.2f));
|
||||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
|
lightColors.push_back(glm::vec3(0.0f, 0.1f, 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[] = {
|
|
||||||
// Positions // Texture Coords (note we set these higher than 1 that together with GL_REPEAT as texture wrapping mode will cause the floor texture to repeat)
|
|
||||||
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
|
|
||||||
};
|
|
||||||
// Setup cube VAO
|
|
||||||
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);
|
|
||||||
// Setup plane VAO
|
|
||||||
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);
|
|
||||||
|
|
||||||
// Load textures
|
// Load textures
|
||||||
GLuint cubeTexture = loadTexture("../../../resources/textures/marble.jpg");
|
woodTexture = loadTexture("../../../resources/textures/wood.png");
|
||||||
GLuint floorTexture = loadTexture("../../../resources/textures/metal.png");
|
|
||||||
#pragma endregion
|
// Set up floating point framebuffer to render scene to
|
||||||
|
GLuint hdrFBO;
|
||||||
|
glGenFramebuffers(1, &hdrFBO);
|
||||||
|
// - Create floating point color buffer
|
||||||
|
GLuint colorBuffer;
|
||||||
|
glGenTextures(1, &colorBuffer);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, colorBuffer);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_FLOAT, NULL);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
// - Create depth buffer (renderbuffer)
|
||||||
|
GLuint rboDepth;
|
||||||
|
glGenRenderbuffers(1, &rboDepth);
|
||||||
|
glBindRenderbuffer(GL_RENDERBUFFER, rboDepth);
|
||||||
|
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, SCR_WIDTH, SCR_HEIGHT);
|
||||||
|
// - Attach buffers
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, hdrFBO);
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBuffer, 0);
|
||||||
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboDepth);
|
||||||
|
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||||
|
std::cout << "Framebuffer not complete!" << std::endl;
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
|
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
||||||
|
|
||||||
// Game loop
|
// Game loop
|
||||||
while(!glfwWindowShouldClose(window))
|
while (!glfwWindowShouldClose(window))
|
||||||
{
|
{
|
||||||
// Set frame time
|
// Set frame time
|
||||||
GLfloat currentFrame = glfwGetTime();
|
GLfloat currentFrame = glfwGetTime();
|
||||||
@@ -172,35 +133,43 @@ int main()
|
|||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
Do_Movement();
|
Do_Movement();
|
||||||
|
|
||||||
// Clear the colorbuffer
|
// 1. Render scene into floating point framebuffer
|
||||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
glBindFramebuffer(GL_FRAMEBUFFER, hdrFBO);
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
glm::mat4 projection = glm::perspective(camera.Zoom, (GLfloat)SCR_WIDTH / (GLfloat)SCR_HEIGHT, 0.1f, 100.0f);
|
||||||
|
glm::mat4 view = camera.GetViewMatrix();
|
||||||
|
glm::mat4 model;
|
||||||
|
shader.Use();
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view));
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, woodTexture);
|
||||||
|
// - set lighting uniforms
|
||||||
|
for (GLuint i = 0; i < lightPositions.size(); i++)
|
||||||
|
{
|
||||||
|
glUniform3fv(glGetUniformLocation(shader.Program, ("lights[" + std::to_string(i) + "].Position").c_str()), 1, &lightPositions[i][0]);
|
||||||
|
glUniform3fv(glGetUniformLocation(shader.Program, ("lights[" + std::to_string(i) + "].Color").c_str()), 1, &lightColors[i][0]);
|
||||||
|
}
|
||||||
|
glUniform3fv(glGetUniformLocation(shader.Program, "viewPos"), 1, &camera.Position[0]);
|
||||||
|
// - render tunnel
|
||||||
|
model = glm::mat4();
|
||||||
|
model = glm::translate(model, glm::vec3(0.0f, 0.0f, 25.0));
|
||||||
|
model = glm::scale(model, glm::vec3(5.0f, 5.0f, 55.0f));
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||||
|
glUniform1i(glGetUniformLocation(shader.Program, "inverse_normals"), GL_TRUE);
|
||||||
|
RenderCube();
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
// Draw objects
|
// 2. Now render floating point color buffer to 2D quad and tonemap HDR colors to default framebuffer's (clamped) color range
|
||||||
shader.Use();
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
glm::mat4 model;
|
hdrShader.Use();
|
||||||
glm::mat4 view = camera.GetViewMatrix();
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glm::mat4 projection = glm::perspective(camera.Zoom, (float)screenWidth/(float)screenHeight, 0.1f, 100.0f);
|
glBindTexture(GL_TEXTURE_2D, colorBuffer);
|
||||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view));
|
glUniform1i(glGetUniformLocation(hdrShader.Program, "hdr"), hdr);
|
||||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
|
glUniform1f(glGetUniformLocation(hdrShader.Program, "exposure"), exposure);
|
||||||
// Cubes
|
RenderQuad();
|
||||||
glBindVertexArray(cubeVAO);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, cubeTexture); // We omit the glActiveTexture part since TEXTURE0 is already the default active texture unit. (sampler used in fragment is set to 0 as well as default)
|
|
||||||
model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f));
|
|
||||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "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.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
|
||||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
|
||||||
// Floor
|
|
||||||
glBindVertexArray(planeVAO);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, floorTexture);
|
|
||||||
model = glm::mat4();
|
|
||||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
|
||||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
|
||||||
glBindVertexArray(0);
|
|
||||||
|
|
||||||
|
std::cout << "exposure: " << exposure << std::endl;
|
||||||
|
|
||||||
// Swap the buffers
|
// Swap the buffers
|
||||||
glfwSwapBuffers(window);
|
glfwSwapBuffers(window);
|
||||||
@@ -210,63 +179,189 @@ int main()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// RenderQuad() Renders a 1x1 quad in NDC, best used for framebuffer color targets
|
||||||
|
// and post-processing effects.
|
||||||
|
GLuint quadVAO = 0;
|
||||||
|
GLuint quadVBO;
|
||||||
|
void RenderQuad()
|
||||||
|
{
|
||||||
|
if (quadVAO == 0)
|
||||||
|
{
|
||||||
|
GLfloat quadVertices[] = {
|
||||||
|
// Positions // Texture Coords
|
||||||
|
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
|
||||||
|
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
|
||||||
|
1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
|
||||||
|
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
|
||||||
|
};
|
||||||
|
// Setup plane VAO
|
||||||
|
glGenVertexArrays(1, &quadVAO);
|
||||||
|
glGenBuffers(1, &quadVBO);
|
||||||
|
glBindVertexArray(quadVAO);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, quadVBO);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, 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(quadVAO);
|
||||||
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||||
|
glBindVertexArray(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// RenderCube() Renders a 1x1 3D cube in NDC.
|
||||||
|
GLuint cubeVAO = 0;
|
||||||
|
GLuint cubeVBO = 0;
|
||||||
|
void RenderCube()
|
||||||
|
{
|
||||||
|
// Initialize (if necessary)
|
||||||
|
if (cubeVAO == 0)
|
||||||
|
{
|
||||||
|
GLfloat vertices[] = {
|
||||||
|
// Back face
|
||||||
|
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, // Bottom-left
|
||||||
|
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, // top-right
|
||||||
|
0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, // bottom-right
|
||||||
|
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, // top-right
|
||||||
|
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, // bottom-left
|
||||||
|
-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f,// top-left
|
||||||
|
// Front face
|
||||||
|
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom-left
|
||||||
|
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, // bottom-right
|
||||||
|
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // top-right
|
||||||
|
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // top-right
|
||||||
|
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, // top-left
|
||||||
|
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom-left
|
||||||
|
// Left face
|
||||||
|
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-right
|
||||||
|
-0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top-left
|
||||||
|
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-left
|
||||||
|
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-left
|
||||||
|
-0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // bottom-right
|
||||||
|
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-right
|
||||||
|
// Right face
|
||||||
|
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-left
|
||||||
|
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-right
|
||||||
|
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top-right
|
||||||
|
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-right
|
||||||
|
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-left
|
||||||
|
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // bottom-left
|
||||||
|
// Bottom face
|
||||||
|
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, // top-right
|
||||||
|
0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, // top-left
|
||||||
|
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f,// bottom-left
|
||||||
|
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom-left
|
||||||
|
-0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, // bottom-right
|
||||||
|
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, // top-right
|
||||||
|
// Top face
|
||||||
|
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,// top-left
|
||||||
|
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom-right
|
||||||
|
0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, // top-right
|
||||||
|
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom-right
|
||||||
|
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,// top-left
|
||||||
|
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f // bottom-left
|
||||||
|
};
|
||||||
|
glGenVertexArrays(1, &cubeVAO);
|
||||||
|
glGenBuffers(1, &cubeVBO);
|
||||||
|
// Fill buffer
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||||
|
// Link vertex attributes
|
||||||
|
glBindVertexArray(cubeVAO);
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);
|
||||||
|
glEnableVertexAttribArray(1);
|
||||||
|
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
|
||||||
|
glEnableVertexAttribArray(2);
|
||||||
|
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
glBindVertexArray(0);
|
||||||
|
}
|
||||||
|
// Render Cube
|
||||||
|
glBindVertexArray(cubeVAO);
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||||
|
glBindVertexArray(0);
|
||||||
|
}
|
||||||
|
|
||||||
// This function loads a texture from file. Note: texture loading functions like these are usually
|
// This function loads a texture from file. Note: texture loading functions like these are usually
|
||||||
// managed by a 'Resource Manager' that manages all resources (like textures, models, audio).
|
// managed by a 'Resource Manager' that manages all resources (like textures, models, audio).
|
||||||
// For learning purposes we'll just define it as a utility function.
|
// For learning purposes we'll just define it as a utility function.
|
||||||
GLuint loadTexture(GLchar* path)
|
GLuint loadTexture(GLchar* path)
|
||||||
{
|
{
|
||||||
//Generate texture ID and load texture data
|
// Generate texture ID and load texture data
|
||||||
GLuint textureID;
|
GLuint textureID;
|
||||||
glGenTextures(1, &textureID);
|
glGenTextures(1, &textureID);
|
||||||
int width,height;
|
int width, height;
|
||||||
unsigned char* image = SOIL_load_image(path, &width, &height, 0, SOIL_LOAD_RGB);
|
unsigned char* image = SOIL_load_image(path, &width, &height, 0, SOIL_LOAD_RGB);
|
||||||
// Assign texture to ID
|
// Assign texture to ID
|
||||||
glBindTexture(GL_TEXTURE_2D, textureID);
|
glBindTexture(GL_TEXTURE_2D, textureID);
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
|
||||||
glGenerateMipmap(GL_TEXTURE_2D);
|
glGenerateMipmap(GL_TEXTURE_2D);
|
||||||
|
|
||||||
// Parameters
|
// Parameters
|
||||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
|
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_WRAP_T, GL_REPEAT);
|
||||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
SOIL_free_image_data(image);
|
SOIL_free_image_data(image);
|
||||||
return textureID;
|
return textureID;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma region "User input"
|
bool keys[1024];
|
||||||
|
bool keysPressed[1024];
|
||||||
// Moves/alters the camera positions based on user input
|
// Moves/alters the camera positions based on user input
|
||||||
void Do_Movement()
|
void Do_Movement()
|
||||||
{
|
{
|
||||||
// Camera controls
|
// Camera controls
|
||||||
if(keys[GLFW_KEY_W])
|
if (keys[GLFW_KEY_W])
|
||||||
camera.ProcessKeyboard(FORWARD, deltaTime);
|
camera.ProcessKeyboard(FORWARD, deltaTime);
|
||||||
if(keys[GLFW_KEY_S])
|
if (keys[GLFW_KEY_S])
|
||||||
camera.ProcessKeyboard(BACKWARD, deltaTime);
|
camera.ProcessKeyboard(BACKWARD, deltaTime);
|
||||||
if(keys[GLFW_KEY_A])
|
if (keys[GLFW_KEY_A])
|
||||||
camera.ProcessKeyboard(LEFT, deltaTime);
|
camera.ProcessKeyboard(LEFT, deltaTime);
|
||||||
if(keys[GLFW_KEY_D])
|
if (keys[GLFW_KEY_D])
|
||||||
camera.ProcessKeyboard(RIGHT, deltaTime);
|
camera.ProcessKeyboard(RIGHT, deltaTime);
|
||||||
|
|
||||||
|
if (keys[GLFW_KEY_SPACE] && !keysPressed[GLFW_KEY_SPACE])
|
||||||
|
{
|
||||||
|
hdr = !hdr;
|
||||||
|
keysPressed[GLFW_KEY_SPACE] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change parallax height scale
|
||||||
|
if (keys[GLFW_KEY_Q])
|
||||||
|
exposure -= 0.5 * deltaTime;
|
||||||
|
else if (keys[GLFW_KEY_E])
|
||||||
|
exposure += 0.5 * deltaTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLfloat lastX = 400, lastY = 300;
|
||||||
|
bool firstMouse = true;
|
||||||
// Is called whenever a key is pressed/released via GLFW
|
// Is called whenever a key is pressed/released via GLFW
|
||||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
|
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
|
||||||
{
|
{
|
||||||
if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
|
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
|
||||||
glfwSetWindowShouldClose(window, GL_TRUE);
|
glfwSetWindowShouldClose(window, GL_TRUE);
|
||||||
|
|
||||||
if(action == GLFW_PRESS)
|
if (key >= 0 && key <= 1024)
|
||||||
keys[key] = true;
|
{
|
||||||
else if(action == GLFW_RELEASE)
|
if (action == GLFW_PRESS)
|
||||||
keys[key] = false;
|
keys[key] = true;
|
||||||
|
else if (action == GLFW_RELEASE)
|
||||||
|
{
|
||||||
|
keys[key] = false;
|
||||||
|
keysPressed[key] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
|
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
|
||||||
{
|
{
|
||||||
if(firstMouse)
|
if (firstMouse)
|
||||||
{
|
{
|
||||||
lastX = xpos;
|
lastX = xpos;
|
||||||
lastY = ypos;
|
lastY = ypos;
|
||||||
@@ -274,17 +369,15 @@ void mouse_callback(GLFWwindow* window, double xpos, double ypos)
|
|||||||
}
|
}
|
||||||
|
|
||||||
GLfloat xoffset = xpos - lastX;
|
GLfloat xoffset = xpos - lastX;
|
||||||
GLfloat yoffset = lastY - ypos;
|
GLfloat yoffset = lastY - ypos;
|
||||||
|
|
||||||
lastX = xpos;
|
lastX = xpos;
|
||||||
lastY = ypos;
|
lastY = ypos;
|
||||||
|
|
||||||
camera.ProcessMouseMovement(xoffset, yoffset);
|
camera.ProcessMouseMovement(xoffset, yoffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
|
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
|
||||||
{
|
{
|
||||||
camera.ProcessMouseScroll(yoffset);
|
camera.ProcessMouseScroll(yoffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma endregion
|
|
||||||
@@ -1,16 +1,28 @@
|
|||||||
#version 330 core
|
#version 330 core
|
||||||
out vec4 color;
|
out vec4 color;
|
||||||
|
in vec2 TexCoords;
|
||||||
|
|
||||||
float LinearizeDepth(float depth) // Note that this ranges from [0,1] instead of up to 'far plane distance' since we divide by 'far'
|
uniform sampler2D hdrBuffer;
|
||||||
{
|
uniform bool hdr;
|
||||||
float near = 0.1;
|
uniform float exposure;
|
||||||
float far = 100.0;
|
|
||||||
float z = depth * 2.0 - 1.0; // Back to NDC
|
|
||||||
return (2.0 * near) / (far + near - z * (far - near));
|
|
||||||
}
|
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
float depth = LinearizeDepth(gl_FragCoord.z);
|
const float gamma = 2.2;
|
||||||
color = vec4(vec3(depth), 1.0f);
|
vec3 hdrColor = texture(hdrBuffer, TexCoords).rgb;
|
||||||
|
if(hdr)
|
||||||
|
{
|
||||||
|
// reinhard
|
||||||
|
// vec3 result = hdrColor / (hdrColor + vec3(1.0));
|
||||||
|
// exposure
|
||||||
|
vec3 result = vec3(1.0) - exp(-hdrColor * exposure);
|
||||||
|
// also gamma correct while we're at it
|
||||||
|
result = pow(result, vec3(1.0 / gamma));
|
||||||
|
color = vec4(result, 1.0f);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vec3 result = pow(hdrColor, vec3(1.0 / gamma));
|
||||||
|
color = vec4(result, 1.0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -4,12 +4,8 @@ layout (location = 1) in vec2 texCoords;
|
|||||||
|
|
||||||
out vec2 TexCoords;
|
out vec2 TexCoords;
|
||||||
|
|
||||||
uniform mat4 model;
|
|
||||||
uniform mat4 view;
|
|
||||||
uniform mat4 projection;
|
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
gl_Position = projection * view * model * vec4(position, 1.0f);
|
gl_Position = vec4(position, 1.0f);
|
||||||
TexCoords = texCoords;
|
TexCoords = texCoords;
|
||||||
}
|
}
|
||||||
41
src/5.advanced_lighting/6.hdr/lighting.frag
Normal file
41
src/5.advanced_lighting/6.hdr/lighting.frag
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#version 330 core
|
||||||
|
out vec4 FragColor;
|
||||||
|
|
||||||
|
in VS_OUT {
|
||||||
|
vec3 FragPos;
|
||||||
|
vec3 Normal;
|
||||||
|
vec2 TexCoords;
|
||||||
|
} fs_in;
|
||||||
|
|
||||||
|
struct Light {
|
||||||
|
vec3 Position;
|
||||||
|
vec3 Color;
|
||||||
|
};
|
||||||
|
|
||||||
|
uniform Light lights[16];
|
||||||
|
uniform sampler2D diffuseTexture;
|
||||||
|
uniform vec3 viewPos;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec3 color = texture(diffuseTexture, fs_in.TexCoords).rgb;
|
||||||
|
vec3 normal = normalize(fs_in.Normal);
|
||||||
|
// Ambient
|
||||||
|
vec3 ambient = 0.0 * color;
|
||||||
|
// Lighting
|
||||||
|
vec3 lighting = vec3(0.0f);
|
||||||
|
for(int i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
// Diffuse
|
||||||
|
vec3 lightDir = normalize(lights[i].Position - fs_in.FragPos);
|
||||||
|
float diff = max(dot(lightDir, normal), 0.0);
|
||||||
|
vec3 diffuse = lights[i].Color * diff * color;
|
||||||
|
vec3 result = diffuse;
|
||||||
|
// Attenuation (use quadratic as we have gamma correction)
|
||||||
|
float distance = length(fs_in.FragPos - lights[i].Position);
|
||||||
|
result *= 1.0 / (distance * distance);
|
||||||
|
lighting += result;
|
||||||
|
|
||||||
|
}
|
||||||
|
FragColor = vec4(ambient + lighting, 1.0f);
|
||||||
|
}
|
||||||
28
src/5.advanced_lighting/6.hdr/lighting.vs
Normal file
28
src/5.advanced_lighting/6.hdr/lighting.vs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#version 330 core
|
||||||
|
layout (location = 0) in vec3 position;
|
||||||
|
layout (location = 1) in vec3 normal;
|
||||||
|
layout (location = 2) in vec2 texCoords;
|
||||||
|
|
||||||
|
out VS_OUT {
|
||||||
|
vec3 FragPos;
|
||||||
|
vec3 Normal;
|
||||||
|
vec2 TexCoords;
|
||||||
|
} vs_out;
|
||||||
|
|
||||||
|
uniform mat4 projection;
|
||||||
|
uniform mat4 view;
|
||||||
|
uniform mat4 model;
|
||||||
|
|
||||||
|
uniform bool inverse_normals;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = projection * view * model * vec4(position, 1.0f);
|
||||||
|
vs_out.FragPos = vec3(model * vec4(position, 1.0));
|
||||||
|
vs_out.TexCoords = texCoords;
|
||||||
|
|
||||||
|
vec3 n = inverse_normals ? -normal : normal;
|
||||||
|
|
||||||
|
mat3 normalMatrix = transpose(inverse(mat3(model)));
|
||||||
|
vs_out.Normal = normalize(normalMatrix * n);
|
||||||
|
}
|
||||||
@@ -1,6 +1,3 @@
|
|||||||
// Std. Includes
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
// GLEW
|
// GLEW
|
||||||
#define GLEW_STATIC
|
#define GLEW_STATIC
|
||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
@@ -21,7 +18,7 @@
|
|||||||
#include <SOIL.h>
|
#include <SOIL.h>
|
||||||
|
|
||||||
// Properties
|
// Properties
|
||||||
GLuint screenWidth = 800, screenHeight = 600;
|
const GLuint SCR_WIDTH = 800, SCR_HEIGHT = 600;
|
||||||
|
|
||||||
// Function prototypes
|
// Function prototypes
|
||||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
|
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
|
||||||
@@ -29,185 +26,361 @@ void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
|
|||||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
|
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
|
||||||
void Do_Movement();
|
void Do_Movement();
|
||||||
GLuint loadTexture(GLchar* path);
|
GLuint loadTexture(GLchar* path);
|
||||||
|
void RenderScene(Shader &shader);
|
||||||
|
void RenderCube();
|
||||||
|
void RenderQuad();
|
||||||
|
|
||||||
// Camera
|
// Camera
|
||||||
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
|
Camera camera(glm::vec3(0.0f, 0.0f, 5.0f));
|
||||||
bool keys[1024];
|
|
||||||
GLfloat lastX = 400, lastY = 300;
|
|
||||||
bool firstMouse = true;
|
|
||||||
|
|
||||||
|
// Delta
|
||||||
GLfloat deltaTime = 0.0f;
|
GLfloat deltaTime = 0.0f;
|
||||||
GLfloat lastFrame = 0.0f;
|
GLfloat lastFrame = 0.0f;
|
||||||
|
|
||||||
|
// Options
|
||||||
|
GLboolean bloom = true; // Change with 'Space'
|
||||||
|
GLfloat exposure = 1.0f; // Change with Q and E
|
||||||
|
|
||||||
// The MAIN function, from here we start our application and run our Game loop
|
// The MAIN function, from here we start our application and run our Game loop
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
// Init GLFW
|
// Init GLFW
|
||||||
glfwInit();
|
glfwInit();
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||||
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
|
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
|
||||||
|
|
||||||
GLFWwindow* window = glfwCreateWindow(screenWidth, screenHeight, "LearnOpenGL", nullptr, nullptr); // Windowed
|
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", nullptr, nullptr); // Windowed
|
||||||
glfwMakeContextCurrent(window);
|
glfwMakeContextCurrent(window);
|
||||||
|
|
||||||
// Set the required callback functions
|
// Set the required callback functions
|
||||||
glfwSetKeyCallback(window, key_callback);
|
glfwSetKeyCallback(window, key_callback);
|
||||||
glfwSetCursorPosCallback(window, mouse_callback);
|
glfwSetCursorPosCallback(window, mouse_callback);
|
||||||
glfwSetScrollCallback(window, scroll_callback);
|
glfwSetScrollCallback(window, scroll_callback);
|
||||||
|
|
||||||
// Options
|
// Options
|
||||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||||
|
|
||||||
// Initialize GLEW to setup the OpenGL Function pointers
|
// Initialize GLEW to setup the OpenGL Function pointers
|
||||||
glewExperimental = GL_TRUE;
|
glewExperimental = GL_TRUE;
|
||||||
glewInit();
|
glewInit();
|
||||||
|
|
||||||
// Define the viewport dimensions
|
// Define the viewport dimensions
|
||||||
glViewport(0, 0, screenWidth, screenHeight);
|
glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT);
|
||||||
|
|
||||||
// Setup some OpenGL options
|
// Setup some OpenGL options
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
// glDepthFunc(GL_ALWAYS); // Set to always pass the depth test (same effect as glDisable(GL_DEPTH_TEST))
|
|
||||||
|
|
||||||
// Setup and compile our shaders
|
// Setup and compile our shaders
|
||||||
Shader shader("depth_testing.vs", "depth_testing.frag");
|
Shader shader("bloom.vs", "bloom.frag");
|
||||||
|
Shader shaderLight("bloom.vs", "light_box.frag");
|
||||||
|
Shader shaderBlur("blur.vs", "blur.frag");
|
||||||
|
Shader shaderBloomFinal("bloom_final.vs", "bloom_final.frag");
|
||||||
|
|
||||||
#pragma region "object_initialization"
|
// Set samplers
|
||||||
// Set the object data (buffers, vertex attributes)
|
shaderBloomFinal.Use();
|
||||||
GLfloat cubeVertices[] = {
|
glUniform1i(glGetUniformLocation(shaderBloomFinal.Program, "scene"), 0);
|
||||||
// Positions // Texture Coords
|
glUniform1i(glGetUniformLocation(shaderBloomFinal.Program, "bloomBlur"), 1);
|
||||||
-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,
|
// Light sources
|
||||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
|
// - Positions
|
||||||
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
|
std::vector<glm::vec3> lightPositions;
|
||||||
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
|
lightPositions.push_back(glm::vec3(0.0f, 0.5f, 1.5f)); // back light
|
||||||
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
|
lightPositions.push_back(glm::vec3(-4.0f, 0.5f, -3.0f));
|
||||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
lightPositions.push_back(glm::vec3(3.0f, 0.5f, 1.0f));
|
||||||
|
lightPositions.push_back(glm::vec3(-.8f, 2.4f, -1.0f));
|
||||||
|
// - Colors
|
||||||
|
std::vector<glm::vec3> lightColors;
|
||||||
|
lightColors.push_back(glm::vec3(5.0f, 5.0f, 5.0f));
|
||||||
|
lightColors.push_back(glm::vec3(5.5f, 0.0f, 0.0f));
|
||||||
|
lightColors.push_back(glm::vec3(0.0f, 0.0f, 15.0f));
|
||||||
|
lightColors.push_back(glm::vec3(0.0f, 1.5f, 0.0f));
|
||||||
|
|
||||||
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
// Load textures
|
||||||
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
GLuint woodTexture = loadTexture("../../../resources/textures/wood.png");
|
||||||
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
GLuint containerTexture = loadTexture("../../../resources/textures/container2.png");
|
||||||
-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,
|
// Set up floating point framebuffer to render scene to
|
||||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
GLuint hdrFBO;
|
||||||
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
glGenFramebuffers(1, &hdrFBO);
|
||||||
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
glBindFramebuffer(GL_FRAMEBUFFER, hdrFBO);
|
||||||
0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
// - Create 2 floating point color buffers (1 for normal rendering, other for brightness treshold values)
|
||||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
GLuint colorBuffers[2];
|
||||||
|
glGenTextures(2, colorBuffers);
|
||||||
|
for (GLuint i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
|
glBindTexture(GL_TEXTURE_2D, colorBuffers[i]);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_FLOAT, NULL);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); // We clamp to the edge as the blur filter would otherwise sample repeated texture values!
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
// attach texture to framebuffer
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, colorBuffers[i], 0);
|
||||||
|
}
|
||||||
|
// - Create and attach depth buffer (renderbuffer)
|
||||||
|
GLuint rboDepth;
|
||||||
|
glGenRenderbuffers(1, &rboDepth);
|
||||||
|
glBindRenderbuffer(GL_RENDERBUFFER, rboDepth);
|
||||||
|
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, SCR_WIDTH, SCR_HEIGHT);
|
||||||
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboDepth);
|
||||||
|
// - Tell OpenGL which color attachments we'll use (of this framebuffer) for rendering
|
||||||
|
GLuint attachments[2] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
|
||||||
|
glDrawBuffers(2, attachments);
|
||||||
|
// - Finally check if framebuffer is complete
|
||||||
|
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||||
|
std::cout << "Framebuffer not complete!" << std::endl;
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
// Ping pong framebuffer for blurring
|
||||||
0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
|
GLuint pingpongFBO[2];
|
||||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
|
GLuint pingpongColorbuffers[2];
|
||||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
|
glGenFramebuffers(2, pingpongFBO);
|
||||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
glGenTextures(2, pingpongColorbuffers);
|
||||||
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
for (GLuint i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, pingpongFBO[i]);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, pingpongColorbuffers[i]);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_FLOAT, NULL);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); // We clamp to the edge as the blur filter would otherwise sample repeated texture values!
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pingpongColorbuffers[i], 0);
|
||||||
|
// Also check if framebuffers are complete (no need for depth buffer)
|
||||||
|
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||||
|
std::cout << "Framebuffer not complete!" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
|
glClearColor(0.0f, 0.0f, 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[] = {
|
|
||||||
// Positions // Texture Coords (note we set these higher than 1 that together with GL_REPEAT as texture wrapping mode will cause the floor texture to repeat)
|
|
||||||
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,
|
// Game loop
|
||||||
-5.0f, -0.5f, -5.0f, 0.0f, 2.0f,
|
while (!glfwWindowShouldClose(window))
|
||||||
5.0f, -0.5f, -5.0f, 2.0f, 2.0f
|
{
|
||||||
};
|
// Set frame time
|
||||||
// Setup cube VAO
|
GLfloat currentFrame = glfwGetTime();
|
||||||
GLuint cubeVAO, cubeVBO;
|
deltaTime = currentFrame - lastFrame;
|
||||||
glGenVertexArrays(1, &cubeVAO);
|
lastFrame = currentFrame;
|
||||||
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);
|
|
||||||
// Setup plane VAO
|
|
||||||
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);
|
|
||||||
|
|
||||||
// Load textures
|
// Check and call events
|
||||||
GLuint cubeTexture = loadTexture("../../../resources/textures/marble.jpg");
|
glfwPollEvents();
|
||||||
GLuint floorTexture = loadTexture("../../../resources/textures/metal.png");
|
Do_Movement();
|
||||||
#pragma endregion
|
|
||||||
|
|
||||||
// Game loop
|
// 1. Render scene into floating point framebuffer
|
||||||
while(!glfwWindowShouldClose(window))
|
glBindFramebuffer(GL_FRAMEBUFFER, hdrFBO);
|
||||||
{
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
// Set frame time
|
glm::mat4 projection = glm::perspective(camera.Zoom, (GLfloat)SCR_WIDTH / (GLfloat)SCR_HEIGHT, 0.1f, 100.0f);
|
||||||
GLfloat currentFrame = glfwGetTime();
|
glm::mat4 view = camera.GetViewMatrix();
|
||||||
deltaTime = currentFrame - lastFrame;
|
glm::mat4 model;
|
||||||
lastFrame = currentFrame;
|
shader.Use();
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view));
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, woodTexture);
|
||||||
|
// - set lighting uniforms
|
||||||
|
for (GLuint i = 0; i < lightPositions.size(); i++)
|
||||||
|
{
|
||||||
|
glUniform3fv(glGetUniformLocation(shader.Program, ("lights[" + std::to_string(i) + "].Position").c_str()), 1, &lightPositions[i][0]);
|
||||||
|
glUniform3fv(glGetUniformLocation(shader.Program, ("lights[" + std::to_string(i) + "].Color").c_str()), 1, &lightColors[i][0]);
|
||||||
|
}
|
||||||
|
glUniform3fv(glGetUniformLocation(shader.Program, "viewPos"), 1, &camera.Position[0]);
|
||||||
|
// - create one large cube that acts as the floor
|
||||||
|
model = glm::mat4();
|
||||||
|
model = glm::translate(model, glm::vec3(0.0f, -1.0f, 0.0));
|
||||||
|
model = glm::scale(model, glm::vec3(25.0f, 1.0f, 25.0f));
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||||
|
RenderCube();
|
||||||
|
// - then create multiple cubes as the scenery
|
||||||
|
glBindTexture(GL_TEXTURE_2D, containerTexture);
|
||||||
|
model = glm::mat4();
|
||||||
|
model = glm::translate(model, glm::vec3(0.0f, 1.5f, 0.0));
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||||
|
RenderCube();
|
||||||
|
model = glm::mat4();
|
||||||
|
model = glm::translate(model, glm::vec3(2.0f, 0.0f, 1.0));
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||||
|
RenderCube();
|
||||||
|
model = glm::mat4();
|
||||||
|
model = glm::translate(model, glm::vec3(-1.0f, -1.0f, 2.0));
|
||||||
|
model = glm::rotate(model, 60.0f, glm::normalize(glm::vec3(1.0, 0.0, 1.0)));
|
||||||
|
model = glm::scale(model, glm::vec3(2.0));
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||||
|
RenderCube();
|
||||||
|
model = glm::mat4();
|
||||||
|
model = glm::translate(model, glm::vec3(0.0f, 2.7f, 4.0));
|
||||||
|
model = glm::rotate(model, 23.0f, glm::normalize(glm::vec3(1.0, 0.0, 1.0)));
|
||||||
|
model = glm::scale(model, glm::vec3(2.5));
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||||
|
RenderCube();
|
||||||
|
model = glm::mat4();
|
||||||
|
model = glm::translate(model, glm::vec3(-2.0f, 1.0f, -3.0));
|
||||||
|
model = glm::rotate(model, 124.0f, glm::normalize(glm::vec3(1.0, 0.0, 1.0)));
|
||||||
|
model = glm::scale(model, glm::vec3(2.0));
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||||
|
RenderCube();
|
||||||
|
RenderCube();
|
||||||
|
model = glm::mat4();
|
||||||
|
model = glm::translate(model, glm::vec3(-3.0f, 0.0f, 0.0));
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||||
|
RenderCube();
|
||||||
|
// - finally show all the light sources as bright cubes
|
||||||
|
shaderLight.Use();
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(shaderLight.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(shaderLight.Program, "view"), 1, GL_FALSE, glm::value_ptr(view));
|
||||||
|
|
||||||
// Check and call events
|
for (GLuint i = 0; i < lightPositions.size(); i++)
|
||||||
glfwPollEvents();
|
{
|
||||||
Do_Movement();
|
model = glm::mat4();
|
||||||
|
model = glm::translate(model, glm::vec3(lightPositions[i]));
|
||||||
|
model = glm::scale(model, glm::vec3(0.5f));
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(shaderLight.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||||
|
glUniform3fv(glGetUniformLocation(shaderLight.Program, "lightColor"), 1, &lightColors[i][0]);
|
||||||
|
RenderCube();
|
||||||
|
}
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
// Clear the colorbuffer
|
// 2. Blur bright fragments w/ two-pass Gaussian Blur
|
||||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
GLboolean horizontal = true, first_iteration = true;
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
GLuint amount = 10;
|
||||||
|
shaderBlur.Use();
|
||||||
|
for (GLuint i = 0; i < amount; i++)
|
||||||
|
{
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, pingpongFBO[horizontal]);
|
||||||
|
glUniform1i(glGetUniformLocation(shaderBlur.Program, "horizontal"), horizontal);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, first_iteration ? colorBuffers[1] : pingpongColorbuffers[!horizontal]); // bind texture of other framebuffer (or scene if first iteration)
|
||||||
|
RenderQuad();
|
||||||
|
horizontal = !horizontal;
|
||||||
|
if (first_iteration)
|
||||||
|
first_iteration = false;
|
||||||
|
}
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
// Draw objects
|
// 2. Now render floating point color buffer to 2D quad and tonemap HDR colors to default framebuffer's (clamped) color range
|
||||||
shader.Use();
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
glm::mat4 model;
|
shaderBloomFinal.Use();
|
||||||
glm::mat4 view = camera.GetViewMatrix();
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glm::mat4 projection = glm::perspective(camera.Zoom, (float)screenWidth/(float)screenHeight, 0.1f, 100.0f);
|
glBindTexture(GL_TEXTURE_2D, colorBuffers[0]);
|
||||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view));
|
//glBindTexture(GL_TEXTURE_2D, pingpongColorbuffers[!horizontal]);
|
||||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
|
glActiveTexture(GL_TEXTURE1);
|
||||||
// Cubes
|
glBindTexture(GL_TEXTURE_2D, pingpongColorbuffers[!horizontal]);
|
||||||
glBindVertexArray(cubeVAO);
|
glUniform1i(glGetUniformLocation(shaderBloomFinal.Program, "bloom"), bloom);
|
||||||
glBindTexture(GL_TEXTURE_2D, cubeTexture); // We omit the glActiveTexture part since TEXTURE0 is already the default active texture unit. (sampler used in fragment is set to 0 as well as default)
|
glUniform1f(glGetUniformLocation(shaderBloomFinal.Program, "exposure"), exposure);
|
||||||
model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f));
|
RenderQuad();
|
||||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "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.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
|
||||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
|
||||||
// Floor
|
|
||||||
glBindVertexArray(planeVAO);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, floorTexture);
|
|
||||||
model = glm::mat4();
|
|
||||||
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
|
||||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
|
||||||
glBindVertexArray(0);
|
|
||||||
|
|
||||||
|
|
||||||
// Swap the buffers
|
// Swap the buffers
|
||||||
glfwSwapBuffers(window);
|
glfwSwapBuffers(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
glfwTerminate();
|
glfwTerminate();
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// RenderQuad() Renders a 1x1 quad in NDC, best used for framebuffer color targets
|
||||||
|
// and post-processing effects.
|
||||||
|
GLuint quadVAO = 0;
|
||||||
|
GLuint quadVBO;
|
||||||
|
void RenderQuad()
|
||||||
|
{
|
||||||
|
if (quadVAO == 0)
|
||||||
|
{
|
||||||
|
GLfloat quadVertices[] = {
|
||||||
|
// Positions // Texture Coords
|
||||||
|
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
|
||||||
|
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
|
||||||
|
1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
|
||||||
|
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
|
||||||
|
};
|
||||||
|
// Setup plane VAO
|
||||||
|
glGenVertexArrays(1, &quadVAO);
|
||||||
|
glGenBuffers(1, &quadVBO);
|
||||||
|
glBindVertexArray(quadVAO);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, quadVBO);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, 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(quadVAO);
|
||||||
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||||
|
glBindVertexArray(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// RenderCube() Renders a 1x1 3D cube in NDC.
|
||||||
|
GLuint cubeVAO = 0;
|
||||||
|
GLuint cubeVBO = 0;
|
||||||
|
void RenderCube()
|
||||||
|
{
|
||||||
|
// Initialize (if necessary)
|
||||||
|
if (cubeVAO == 0)
|
||||||
|
{
|
||||||
|
GLfloat vertices[] = {
|
||||||
|
// Back face
|
||||||
|
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, // Bottom-left
|
||||||
|
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, // top-right
|
||||||
|
0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, // bottom-right
|
||||||
|
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, // top-right
|
||||||
|
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, // bottom-left
|
||||||
|
-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f,// top-left
|
||||||
|
// Front face
|
||||||
|
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom-left
|
||||||
|
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, // bottom-right
|
||||||
|
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // top-right
|
||||||
|
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // top-right
|
||||||
|
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, // top-left
|
||||||
|
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom-left
|
||||||
|
// Left face
|
||||||
|
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-right
|
||||||
|
-0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top-left
|
||||||
|
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-left
|
||||||
|
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-left
|
||||||
|
-0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // bottom-right
|
||||||
|
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-right
|
||||||
|
// Right face
|
||||||
|
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-left
|
||||||
|
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-right
|
||||||
|
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top-right
|
||||||
|
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // bottom-right
|
||||||
|
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // top-left
|
||||||
|
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // bottom-left
|
||||||
|
// Bottom face
|
||||||
|
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, // top-right
|
||||||
|
0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, // top-left
|
||||||
|
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f,// bottom-left
|
||||||
|
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom-left
|
||||||
|
-0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, // bottom-right
|
||||||
|
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, // top-right
|
||||||
|
// Top face
|
||||||
|
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,// top-left
|
||||||
|
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom-right
|
||||||
|
0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, // top-right
|
||||||
|
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom-right
|
||||||
|
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,// top-left
|
||||||
|
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f // bottom-left
|
||||||
|
};
|
||||||
|
glGenVertexArrays(1, &cubeVAO);
|
||||||
|
glGenBuffers(1, &cubeVBO);
|
||||||
|
// Fill buffer
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||||
|
// Link vertex attributes
|
||||||
|
glBindVertexArray(cubeVAO);
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);
|
||||||
|
glEnableVertexAttribArray(1);
|
||||||
|
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
|
||||||
|
glEnableVertexAttribArray(2);
|
||||||
|
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
glBindVertexArray(0);
|
||||||
|
}
|
||||||
|
// Render Cube
|
||||||
|
glBindVertexArray(cubeVAO);
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||||
|
glBindVertexArray(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function loads a texture from file. Note: texture loading functions like these are usually
|
// This function loads a texture from file. Note: texture loading functions like these are usually
|
||||||
@@ -215,76 +388,94 @@ int main()
|
|||||||
// For learning purposes we'll just define it as a utility function.
|
// For learning purposes we'll just define it as a utility function.
|
||||||
GLuint loadTexture(GLchar* path)
|
GLuint loadTexture(GLchar* path)
|
||||||
{
|
{
|
||||||
//Generate texture ID and load texture data
|
// Generate texture ID and load texture data
|
||||||
GLuint textureID;
|
GLuint textureID;
|
||||||
glGenTextures(1, &textureID);
|
glGenTextures(1, &textureID);
|
||||||
int width,height;
|
int width, height;
|
||||||
unsigned char* image = SOIL_load_image(path, &width, &height, 0, SOIL_LOAD_RGB);
|
unsigned char* image = SOIL_load_image(path, &width, &height, 0, SOIL_LOAD_RGB);
|
||||||
// Assign texture to ID
|
// Assign texture to ID
|
||||||
glBindTexture(GL_TEXTURE_2D, textureID);
|
glBindTexture(GL_TEXTURE_2D, textureID);
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
|
||||||
glGenerateMipmap(GL_TEXTURE_2D);
|
glGenerateMipmap(GL_TEXTURE_2D);
|
||||||
|
|
||||||
// Parameters
|
// Parameters
|
||||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
|
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_WRAP_T, GL_REPEAT);
|
||||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
SOIL_free_image_data(image);
|
SOIL_free_image_data(image);
|
||||||
return textureID;
|
return textureID;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma region "User input"
|
bool keys[1024];
|
||||||
|
bool keysPressed[1024];
|
||||||
// Moves/alters the camera positions based on user input
|
// Moves/alters the camera positions based on user input
|
||||||
void Do_Movement()
|
void Do_Movement()
|
||||||
{
|
{
|
||||||
// Camera controls
|
// Camera controls
|
||||||
if(keys[GLFW_KEY_W])
|
if (keys[GLFW_KEY_W])
|
||||||
camera.ProcessKeyboard(FORWARD, deltaTime);
|
camera.ProcessKeyboard(FORWARD, deltaTime);
|
||||||
if(keys[GLFW_KEY_S])
|
if (keys[GLFW_KEY_S])
|
||||||
camera.ProcessKeyboard(BACKWARD, deltaTime);
|
camera.ProcessKeyboard(BACKWARD, deltaTime);
|
||||||
if(keys[GLFW_KEY_A])
|
if (keys[GLFW_KEY_A])
|
||||||
camera.ProcessKeyboard(LEFT, deltaTime);
|
camera.ProcessKeyboard(LEFT, deltaTime);
|
||||||
if(keys[GLFW_KEY_D])
|
if (keys[GLFW_KEY_D])
|
||||||
camera.ProcessKeyboard(RIGHT, deltaTime);
|
camera.ProcessKeyboard(RIGHT, deltaTime);
|
||||||
|
|
||||||
|
if (keys[GLFW_KEY_SPACE] && !keysPressed[GLFW_KEY_SPACE])
|
||||||
|
{
|
||||||
|
bloom = !bloom;
|
||||||
|
keysPressed[GLFW_KEY_SPACE] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change parallax height scale
|
||||||
|
if (keys[GLFW_KEY_Q])
|
||||||
|
exposure -= 0.5 * deltaTime;
|
||||||
|
else if (keys[GLFW_KEY_E])
|
||||||
|
exposure += 0.5 * deltaTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLfloat lastX = 400, lastY = 300;
|
||||||
|
bool firstMouse = true;
|
||||||
// Is called whenever a key is pressed/released via GLFW
|
// Is called whenever a key is pressed/released via GLFW
|
||||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
|
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
|
||||||
{
|
{
|
||||||
if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
|
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
|
||||||
glfwSetWindowShouldClose(window, GL_TRUE);
|
glfwSetWindowShouldClose(window, GL_TRUE);
|
||||||
|
|
||||||
if(action == GLFW_PRESS)
|
if (key >= 0 && key <= 1024)
|
||||||
keys[key] = true;
|
{
|
||||||
else if(action == GLFW_RELEASE)
|
if (action == GLFW_PRESS)
|
||||||
keys[key] = false;
|
keys[key] = true;
|
||||||
|
else if (action == GLFW_RELEASE)
|
||||||
|
{
|
||||||
|
keys[key] = false;
|
||||||
|
keysPressed[key] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
|
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
|
||||||
{
|
{
|
||||||
if(firstMouse)
|
if (firstMouse)
|
||||||
{
|
{
|
||||||
lastX = xpos;
|
lastX = xpos;
|
||||||
lastY = ypos;
|
lastY = ypos;
|
||||||
firstMouse = false;
|
firstMouse = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLfloat xoffset = xpos - lastX;
|
GLfloat xoffset = xpos - lastX;
|
||||||
GLfloat yoffset = lastY - ypos;
|
GLfloat yoffset = lastY - ypos;
|
||||||
|
|
||||||
lastX = xpos;
|
|
||||||
lastY = ypos;
|
|
||||||
|
|
||||||
camera.ProcessMouseMovement(xoffset, yoffset);
|
lastX = xpos;
|
||||||
}
|
lastY = ypos;
|
||||||
|
|
||||||
|
camera.ProcessMouseMovement(xoffset, yoffset);
|
||||||
|
}
|
||||||
|
|
||||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
|
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
|
||||||
{
|
{
|
||||||
camera.ProcessMouseScroll(yoffset);
|
camera.ProcessMouseScroll(yoffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma endregion
|
|
||||||
@@ -1,16 +1,49 @@
|
|||||||
#version 330 core
|
#version 330 core
|
||||||
out vec4 color;
|
layout (location = 0) out vec4 FragColor;
|
||||||
|
layout (location = 1) out vec4 BrightColor;
|
||||||
|
|
||||||
float LinearizeDepth(float depth) // Note that this ranges from [0,1] instead of up to 'far plane distance' since we divide by 'far'
|
in VS_OUT {
|
||||||
{
|
vec3 FragPos;
|
||||||
float near = 0.1;
|
vec3 Normal;
|
||||||
float far = 100.0;
|
vec2 TexCoords;
|
||||||
float z = depth * 2.0 - 1.0; // Back to NDC
|
} fs_in;
|
||||||
return (2.0 * near) / (far + near - z * (far - near));
|
|
||||||
}
|
struct Light {
|
||||||
|
vec3 Position;
|
||||||
|
vec3 Color;
|
||||||
|
};
|
||||||
|
|
||||||
|
uniform Light lights[4];
|
||||||
|
uniform sampler2D diffuseTexture;
|
||||||
|
uniform vec3 viewPos;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
float depth = LinearizeDepth(gl_FragCoord.z);
|
vec3 color = texture(diffuseTexture, fs_in.TexCoords).rgb;
|
||||||
color = vec4(vec3(depth), 1.0f);
|
vec3 normal = normalize(fs_in.Normal);
|
||||||
|
// Ambient
|
||||||
|
vec3 ambient = 0.0 * color;
|
||||||
|
// Lighting
|
||||||
|
vec3 lighting = vec3(0.0f);
|
||||||
|
vec3 viewDir = normalize(viewPos - fs_in.FragPos);
|
||||||
|
for(int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
// Diffuse
|
||||||
|
vec3 lightDir = normalize(lights[i].Position - fs_in.FragPos);
|
||||||
|
float diff = max(dot(lightDir, normal), 0.0);
|
||||||
|
vec3 result = lights[i].Color * diff * color;
|
||||||
|
// Attenuation (use quadratic as we have gamma correction)
|
||||||
|
float distance = length(fs_in.FragPos - lights[i].Position);
|
||||||
|
result *= 1.0 / (distance * distance);
|
||||||
|
lighting += result;
|
||||||
|
|
||||||
|
}
|
||||||
|
vec3 result = ambient + lighting;
|
||||||
|
// Check whether result is higher than some threshold, if so, output as bloom threshold color
|
||||||
|
float brightness = dot(result, vec3(0.2126, 0.7152, 0.0722));
|
||||||
|
if(brightness > 1.0)
|
||||||
|
BrightColor = vec4(result, 1.0);
|
||||||
|
// else
|
||||||
|
// BloomColor = vec4(0.0, 0.0, 0.0, 1.0);
|
||||||
|
FragColor = vec4(result, 1.0f);
|
||||||
}
|
}
|
||||||
@@ -1,15 +1,24 @@
|
|||||||
#version 330 core
|
#version 330 core
|
||||||
layout (location = 0) in vec3 position;
|
layout (location = 0) in vec3 position;
|
||||||
layout (location = 1) in vec2 texCoords;
|
layout (location = 1) in vec3 normal;
|
||||||
|
layout (location = 2) in vec2 texCoords;
|
||||||
|
|
||||||
out vec2 TexCoords;
|
out VS_OUT {
|
||||||
|
vec3 FragPos;
|
||||||
|
vec3 Normal;
|
||||||
|
vec2 TexCoords;
|
||||||
|
} vs_out;
|
||||||
|
|
||||||
uniform mat4 model;
|
|
||||||
uniform mat4 view;
|
|
||||||
uniform mat4 projection;
|
uniform mat4 projection;
|
||||||
|
uniform mat4 view;
|
||||||
|
uniform mat4 model;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
gl_Position = projection * view * model * vec4(position, 1.0f);
|
gl_Position = projection * view * model * vec4(position, 1.0f);
|
||||||
TexCoords = texCoords;
|
vs_out.FragPos = vec3(model * vec4(position, 1.0));
|
||||||
|
vs_out.TexCoords = texCoords;
|
||||||
|
|
||||||
|
mat3 normalMatrix = transpose(inverse(mat3(model)));
|
||||||
|
vs_out.Normal = normalize(normalMatrix * normal);
|
||||||
}
|
}
|
||||||
22
src/5.advanced_lighting/7.bloom/bloom_final.frag
Normal file
22
src/5.advanced_lighting/7.bloom/bloom_final.frag
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#version 330 core
|
||||||
|
out vec4 FragColor;
|
||||||
|
in vec2 TexCoords;
|
||||||
|
|
||||||
|
uniform sampler2D scene;
|
||||||
|
uniform sampler2D bloomBlur;
|
||||||
|
uniform bool bloom;
|
||||||
|
uniform float exposure;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
const float gamma = 2.2;
|
||||||
|
vec3 hdrColor = texture(scene, TexCoords).rgb;
|
||||||
|
vec3 bloomColor = texture(bloomBlur, TexCoords).rgb;
|
||||||
|
if(bloom)
|
||||||
|
hdrColor += bloomColor; // additive blending
|
||||||
|
// tone mapping
|
||||||
|
vec3 result = vec3(1.0) - exp(-hdrColor * exposure);
|
||||||
|
// also gamma correct while we're at it
|
||||||
|
result = pow(result, vec3(1.0 / gamma));
|
||||||
|
FragColor = vec4(result, 1.0f);
|
||||||
|
}
|
||||||
11
src/5.advanced_lighting/7.bloom/bloom_final.vs
Normal file
11
src/5.advanced_lighting/7.bloom/bloom_final.vs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#version 330 core
|
||||||
|
layout (location = 0) in vec3 position;
|
||||||
|
layout (location = 1) in vec2 texCoords;
|
||||||
|
|
||||||
|
out vec2 TexCoords;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = vec4(position, 1.0f);
|
||||||
|
TexCoords = texCoords;
|
||||||
|
}
|
||||||
31
src/5.advanced_lighting/7.bloom/blur.frag
Normal file
31
src/5.advanced_lighting/7.bloom/blur.frag
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#version 330 core
|
||||||
|
out vec4 FragColor;
|
||||||
|
in vec2 TexCoords;
|
||||||
|
|
||||||
|
uniform sampler2D image;
|
||||||
|
uniform bool horizontal;
|
||||||
|
|
||||||
|
uniform float weight[5] = float[] (0.2270270270, 0.1945945946, 0.1216216216, 0.0540540541, 0.0162162162);
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec2 tex_offset = 1.0 / textureSize(image, 0); // gets size of single texel
|
||||||
|
vec3 result = texture(image, TexCoords).rgb * weight[0];
|
||||||
|
if(horizontal)
|
||||||
|
{
|
||||||
|
for(int i = 1; i < 5; ++i)
|
||||||
|
{
|
||||||
|
result += texture(image, TexCoords + vec2(tex_offset.x * i, 0.0)).rgb * weight[i];
|
||||||
|
result += texture(image, TexCoords - vec2(tex_offset.x * i, 0.0)).rgb * weight[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(int i = 1; i < 5; ++i)
|
||||||
|
{
|
||||||
|
result += texture(image, TexCoords + vec2(0.0, tex_offset.y * i)).rgb * weight[i];
|
||||||
|
result += texture(image, TexCoords - vec2(0.0, tex_offset.y * i)).rgb * weight[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FragColor = vec4(result, 1.0);
|
||||||
|
}
|
||||||
11
src/5.advanced_lighting/7.bloom/blur.vs
Normal file
11
src/5.advanced_lighting/7.bloom/blur.vs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#version 330 core
|
||||||
|
layout (location = 0) in vec3 position;
|
||||||
|
layout (location = 1) in vec2 texCoords;
|
||||||
|
|
||||||
|
out vec2 TexCoords;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = vec4(position, 1.0f);
|
||||||
|
TexCoords = texCoords;
|
||||||
|
}
|
||||||
19
src/5.advanced_lighting/7.bloom/light_box.frag
Normal file
19
src/5.advanced_lighting/7.bloom/light_box.frag
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#version 330 core
|
||||||
|
layout (location = 0) out vec4 FragColor;
|
||||||
|
layout (location = 1) out vec4 BrightColor;
|
||||||
|
|
||||||
|
in VS_OUT {
|
||||||
|
vec3 FragPos;
|
||||||
|
vec3 Normal;
|
||||||
|
vec2 TexCoords;
|
||||||
|
} fs_in;
|
||||||
|
|
||||||
|
uniform vec3 lightColor;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
FragColor = vec4(lightColor, 1.0);
|
||||||
|
float brightness = dot(FragColor.rgb, vec3(0.2126, 0.7152, 0.0722));
|
||||||
|
if(brightness > 1.0)
|
||||||
|
BrightColor = vec4(FragColor.rgb, 1.0);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user