Last active
September 25, 2016 21:12
-
-
Save SammyVimes/688957989ee1267ae4c7e6e2155714e5 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#version 330 core | |
in vec3 Normal; | |
in vec3 Position; | |
out vec4 color; | |
uniform vec3 cameraPos; | |
uniform sampler2D skybox; | |
void main() | |
{ | |
float ratio = 1.00 / 1.52; | |
vec3 I = normalize(Position - cameraPos); | |
vec3 R = refract(I, normalize(Normal), ratio); | |
//vec3 I = normalize(Position - cameraPos); | |
//vec3 R = reflect(I, normalize(Normal)); | |
color = texture(skybox, vec2(R.x, R.y)); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#version 330 core | |
layout (location = 0) in vec3 position; | |
layout (location = 1) in vec3 normal; | |
out vec3 Normal; | |
out vec3 Position; | |
uniform mat4 model; | |
uniform mat4 view; | |
uniform mat4 projection; | |
void main() | |
{ | |
gl_Position = projection * view * model * vec4(position, 1.0f); | |
Normal = mat3(transpose(inverse(model))) * normal; | |
Position = vec3(model * vec4(position, 1.0f)); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// GLEW | |
#define GLEW_STATIC | |
#include <GL/glew.h> | |
// GLFW | |
#include <GLFW/glfw3.h> | |
// GL includes | |
#include <learnopengl/shader.h> | |
#include <learnopengl/camera.h> | |
#include <learnopengl/model.h> | |
// GLM Mathemtics | |
#include <glm/glm.hpp> | |
#include <glm/gtc/matrix_transform.hpp> | |
#include <glm/gtc/type_ptr.hpp> | |
// Other Libs | |
#include <SOIL.h> | |
#include <learnopengl/filesystem.h> | |
// Properties | |
const GLuint SCR_WIDTH = 800, SCR_HEIGHT = 600; | |
// Function prototypes | |
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode); | |
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset); | |
void mouse_callback(GLFWwindow* window, double xpos, double ypos); | |
void Do_Movement(); | |
GLuint loadTexture(GLchar const * path); | |
void RenderScene(Shader &shader); | |
void RenderCube(); | |
void RenderQuad(); | |
GLuint cubeVAO = 0; | |
GLuint cubeVBO = 0; | |
// Camera | |
Camera camera(glm::vec3(0.0f, 0.0f, 5.0f)); | |
// Delta | |
GLfloat deltaTime = 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 | |
int main() | |
{ | |
// Init GLFW | |
glfwInit(); | |
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); | |
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); | |
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); | |
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); | |
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", nullptr, nullptr); // Windowed | |
glfwMakeContextCurrent(window); | |
// Set the required callback functions | |
glfwSetKeyCallback(window, key_callback); | |
glfwSetCursorPosCallback(window, mouse_callback); | |
glfwSetScrollCallback(window, scroll_callback); | |
// Options | |
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); | |
// Initialize GLEW to setup the OpenGL Function pointers | |
glewExperimental = GL_TRUE; | |
glewInit(); | |
// Define the viewport dimensions | |
glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT); | |
// Setup some OpenGL options | |
glEnable(GL_DEPTH_TEST); | |
// Setup and compile our shaders | |
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"); | |
Shader shaderMirror("cubemaps.vs", "cubemaps.frag"); | |
// Set samplers | |
shaderBloomFinal.Use(); | |
glUniform1i(glGetUniformLocation(shaderBloomFinal.Program, "scene"), 0); | |
glUniform1i(glGetUniformLocation(shaderBloomFinal.Program, "bloomBlur"), 1); | |
// Light sources | |
// - Positions | |
std::vector<glm::vec3> lightPositions; | |
lightPositions.push_back(glm::vec3(0.0f, 0.5f, 1.5f)); // back light | |
lightPositions.push_back(glm::vec3(-4.0f, 0.5f, -3.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)); | |
// Load textures | |
GLuint woodTexture = loadTexture(FileSystem::getPath("resources/textures/wood.png").c_str()); | |
GLuint containerTexture = loadTexture(FileSystem::getPath("resources/textures/container2.png").c_str()); | |
// Создаём зеркальный FBO | |
GLuint mirrorFBO; | |
glGenFramebuffers(1, &mirrorFBO); | |
glBindFramebuffer(GL_FRAMEBUFFER, mirrorFBO); | |
// Создаём текстуру для рендеринга зеркала | |
GLuint texColorBuffer; | |
glGenTextures(1, &texColorBuffer); | |
glBindTexture(GL_TEXTURE_2D, texColorBuffer); | |
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 800, 600, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |
glBindTexture(GL_TEXTURE_2D, 0); | |
// Аттачим к зеркальному FBO | |
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texColorBuffer, 0); | |
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { | |
cout << "ERROR::MIRROR FRAMEBUFFER:: Framebuffer is not complete!" << endl; | |
return 0; | |
} | |
glBindFramebuffer(GL_FRAMEBUFFER, 0); | |
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 800, 600, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |
// Set up floating point framebuffer to render scene to | |
GLuint hdrFBO; | |
glGenFramebuffers(1, &hdrFBO); | |
glBindFramebuffer(GL_FRAMEBUFFER, hdrFBO); | |
// - Create 2 floating point color buffers (1 for normal rendering, other for brightness treshold values) | |
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); | |
// Ping pong framebuffer for blurring | |
GLuint pingpongFBO[2]; | |
GLuint pingpongColorbuffers[2]; | |
glGenFramebuffers(2, pingpongFBO); | |
glGenTextures(2, pingpongColorbuffers); | |
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; | |
} | |
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); | |
// Game loop | |
while (!glfwWindowShouldClose(window)) | |
{ | |
// Set frame time | |
GLfloat currentFrame = glfwGetTime(); | |
deltaTime = currentFrame - lastFrame; | |
lastFrame = currentFrame; | |
// Check and call events | |
glfwPollEvents(); | |
Do_Movement(); | |
// 1. Render scene into floating point framebuffer | |
glBindFramebuffer(GL_FRAMEBUFFER, hdrFBO); | |
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]); | |
// - 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, texColorBuffer); | |
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(); | |
glBindTexture(GL_TEXTURE_2D, containerTexture); | |
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)); | |
for (GLuint i = 0; i < lightPositions.size(); i++) | |
{ | |
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); | |
// 2. Blur bright fragments w/ two-pass Gaussian Blur | |
GLboolean horizontal = true, first_iteration = true; | |
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); | |
glBindFramebuffer(GL_FRAMEBUFFER, mirrorFBO); | |
glClearColor(0.1f, 0.1f, 0.1f, 1.0f); | |
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // We're not using stencil buffer now | |
glEnable(GL_DEPTH_TEST); | |
for (int pass = 0; pass < 2; pass++) { | |
// 2. Now render floating point color buffer to 2D quad and tonemap HDR colors to default framebuffer's (clamped) color range | |
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | |
shaderBloomFinal.Use(); | |
glActiveTexture(GL_TEXTURE0); | |
glBindTexture(GL_TEXTURE_2D, colorBuffers[0]); | |
//glBindTexture(GL_TEXTURE_2D, pingpongColorbuffers[!horizontal]); | |
glActiveTexture(GL_TEXTURE1); | |
glBindTexture(GL_TEXTURE_2D, pingpongColorbuffers[!horizontal]); | |
glUniform1i(glGetUniformLocation(shaderBloomFinal.Program, "bloom"), bloom); | |
glUniform1f(glGetUniformLocation(shaderBloomFinal.Program, "exposure"), exposure); | |
RenderQuad(); | |
glBindFramebuffer(GL_FRAMEBUFFER, 0); | |
} | |
model = glm::mat4(); | |
model = glm::translate(model, glm::vec3(0.0f, 1.5f, 0.0)); | |
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]); | |
// - 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(); | |
// shaderMirror.Use(); | |
// glUniform3f(glGetUniformLocation(shaderMirror.Program, "cameraPos"), camera.Position.x, camera.Position.y, camera.Position.z); | |
// glUniformMatrix4fv(glGetUniformLocation(shaderMirror.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); | |
// glUniformMatrix4fv(glGetUniformLocation(shaderMirror.Program, "view"), 1, GL_FALSE, glm::value_ptr(view)); | |
// glUniformMatrix4fv(glGetUniformLocation(shaderMirror.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); | |
// glBindVertexArray(cubeVAO); | |
//// glBindTexture(GL_TEXTURE_2D, woodTexture); | |
// glDrawArrays(GL_TRIANGLES, 0, 36); | |
// glBindVertexArray(0); | |
// Swap the buffers | |
glfwSwapBuffers(window); | |
} | |
glfwTerminate(); | |
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. | |
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 | |
// 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. | |
GLuint loadTexture(GLchar const * path) | |
{ | |
// Generate texture ID and load texture data | |
GLuint textureID; | |
glGenTextures(1, &textureID); | |
int width, height; | |
unsigned char* image = SOIL_load_image(path, &width, &height, 0, SOIL_LOAD_RGB); | |
// Assign texture to ID | |
glBindTexture(GL_TEXTURE_2D, textureID); | |
glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB, width, height, 0, GL_RGB, 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; | |
} | |
bool keys[1024]; | |
bool keysPressed[1024]; | |
// Moves/alters the camera positions based on user input | |
void Do_Movement() | |
{ | |
// Camera controls | |
if (keys[GLFW_KEY_W]) | |
camera.ProcessKeyboard(FORWARD, deltaTime); | |
if (keys[GLFW_KEY_S]) | |
camera.ProcessKeyboard(BACKWARD, deltaTime); | |
if (keys[GLFW_KEY_A]) | |
camera.ProcessKeyboard(LEFT, deltaTime); | |
if (keys[GLFW_KEY_D]) | |
camera.ProcessKeyboard(RIGHT, deltaTime); | |
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 | |
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) | |
{ | |
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) | |
glfwSetWindowShouldClose(window, GL_TRUE); | |
if (key >= 0 && key <= 1024) | |
{ | |
if (action == GLFW_PRESS) | |
keys[key] = true; | |
else if (action == GLFW_RELEASE) | |
{ | |
keys[key] = false; | |
keysPressed[key] = false; | |
} | |
} | |
} | |
void mouse_callback(GLFWwindow* window, double xpos, double ypos) | |
{ | |
if (firstMouse) | |
{ | |
lastX = xpos; | |
lastY = ypos; | |
firstMouse = false; | |
} | |
GLfloat xoffset = xpos - lastX; | |
GLfloat yoffset = lastY - ypos; | |
lastX = xpos; | |
lastY = ypos; | |
camera.ProcessMouseMovement(xoffset, yoffset); | |
} | |
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) | |
{ | |
camera.ProcessMouseScroll(yoffset); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// GLEW | |
#define GLEW_STATIC | |
#include <GL/glew.h> | |
// GLFW | |
#include <GLFW/glfw3.h> | |
// GL includes | |
#include <learnopengl/shader.h> | |
#include <learnopengl/camera.h> | |
#include <learnopengl/model.h> | |
// GLM Mathemtics | |
#include <glm/glm.hpp> | |
#include <glm/gtc/matrix_transform.hpp> | |
#include <glm/gtc/type_ptr.hpp> | |
// Other Libs | |
#include <SOIL.h> | |
#include <learnopengl/filesystem.h> | |
// Properties | |
const GLuint SCR_WIDTH = 800, SCR_HEIGHT = 600; | |
// Function prototypes | |
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode); | |
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset); | |
void mouse_callback(GLFWwindow* window, double xpos, double ypos); | |
void Do_Movement(); | |
GLuint loadTexture(GLchar const * path); | |
void RenderScene(Shader &shader); | |
void RenderCube(); | |
void RenderQuad(); | |
GLuint cubeVAO = 0; | |
GLuint cubeVBO = 0; | |
// Camera | |
Camera camera(glm::vec3(0.0f, 0.0f, 5.0f)); | |
// Delta | |
GLfloat deltaTime = 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 | |
int main() | |
{ | |
// Init GLFW | |
glfwInit(); | |
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); | |
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); | |
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); | |
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); | |
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", nullptr, nullptr); // Windowed | |
glfwMakeContextCurrent(window); | |
// Set the required callback functions | |
glfwSetKeyCallback(window, key_callback); | |
glfwSetCursorPosCallback(window, mouse_callback); | |
glfwSetScrollCallback(window, scroll_callback); | |
// Options | |
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); | |
// Initialize GLEW to setup the OpenGL Function pointers | |
glewExperimental = GL_TRUE; | |
glewInit(); | |
// Define the viewport dimensions | |
glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT); | |
// Setup some OpenGL options | |
glEnable(GL_DEPTH_TEST); | |
// Setup and compile our shaders | |
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"); | |
Shader shaderMirror("cubemaps.vs", "cubemaps.frag"); | |
// Set samplers | |
shaderBloomFinal.Use(); | |
glUniform1i(glGetUniformLocation(shaderBloomFinal.Program, "scene"), 0); | |
glUniform1i(glGetUniformLocation(shaderBloomFinal.Program, "bloomBlur"), 1); | |
// Light sources | |
// - Positions | |
std::vector<glm::vec3> lightPositions; | |
lightPositions.push_back(glm::vec3(0.0f, 0.5f, 1.5f)); // back light | |
lightPositions.push_back(glm::vec3(-4.0f, 0.5f, -3.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)); | |
// Load textures | |
GLuint woodTexture = loadTexture(FileSystem::getPath("resources/textures/wood.png").c_str()); | |
GLuint containerTexture = loadTexture(FileSystem::getPath("resources/textures/container2.png").c_str()); | |
// Создаём зеркальный FBO | |
GLuint mirrorFBO; | |
glGenFramebuffers(1, &mirrorFBO); | |
glBindFramebuffer(GL_FRAMEBUFFER, mirrorFBO); | |
// Создаём текстуру для рендеринга зеркала | |
GLuint texColorBuffer; | |
glGenTextures(1, &texColorBuffer); | |
glBindTexture(GL_TEXTURE_2D, texColorBuffer); | |
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 800, 600, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |
glBindTexture(GL_TEXTURE_2D, 0); | |
// Аттачим к зеркальному FBO | |
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texColorBuffer, 0); | |
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { | |
cout << "ERROR::MIRROR FRAMEBUFFER:: Framebuffer is not complete!" << endl; | |
return 0; | |
} | |
glBindFramebuffer(GL_FRAMEBUFFER, 0); | |
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 800, 600, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |
// Set up floating point framebuffer to render scene to | |
GLuint hdrFBO; | |
glGenFramebuffers(1, &hdrFBO); | |
glBindFramebuffer(GL_FRAMEBUFFER, hdrFBO); | |
// - Create 2 floating point color buffers (1 for normal rendering, other for brightness treshold values) | |
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); | |
// Ping pong framebuffer for blurring | |
GLuint pingpongFBO[2]; | |
GLuint pingpongColorbuffers[2]; | |
glGenFramebuffers(2, pingpongFBO); | |
glGenTextures(2, pingpongColorbuffers); | |
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; | |
} | |
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); | |
// Game loop | |
while (!glfwWindowShouldClose(window)) | |
{ | |
// Set frame time | |
GLfloat currentFrame = glfwGetTime(); | |
deltaTime = currentFrame - lastFrame; | |
lastFrame = currentFrame; | |
// Check and call events | |
glfwPollEvents(); | |
Do_Movement(); | |
// 1. Render scene into floating point framebuffer | |
glBindFramebuffer(GL_FRAMEBUFFER, hdrFBO); | |
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]); | |
// - 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, texColorBuffer); | |
shaderMirror.Use(); | |
glUniform3f(glGetUniformLocation(shaderMirror.Program, "cameraPos"), camera.Position.x, camera.Position.y, camera.Position.z); | |
glUniformMatrix4fv(glGetUniformLocation(shaderMirror.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); | |
glUniformMatrix4fv(glGetUniformLocation(shaderMirror.Program, "view"), 1, GL_FALSE, glm::value_ptr(view)); | |
model = glm::mat4(); | |
model = glm::translate(model, glm::vec3(0.0f, 1.5f, 0.0)); | |
glUniformMatrix4fv(glGetUniformLocation(shaderMirror.Program, "model"), 1, GL_FALSE, glm::value_ptr(model)); | |
RenderCube(); | |
glBindTexture(GL_TEXTURE_2D, containerTexture); | |
shader.Use(); | |
glUniform3fv(glGetUniformLocation(shader.Program, "viewPos"), 1, &camera.Position[0]); | |
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); | |
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "view"), 1, GL_FALSE, glm::value_ptr(view)); | |
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)); | |
for (GLuint i = 0; i < lightPositions.size(); i++) | |
{ | |
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); | |
// 2. Blur bright fragments w/ two-pass Gaussian Blur | |
GLboolean horizontal = true, first_iteration = true; | |
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); | |
glBindFramebuffer(GL_FRAMEBUFFER, mirrorFBO); | |
glClearColor(0.1f, 0.1f, 0.1f, 1.0f); | |
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // We're not using stencil buffer now | |
glEnable(GL_DEPTH_TEST); | |
for (int pass = 0; pass < 2; pass++) { | |
// 2. Now render floating point color buffer to 2D quad and tonemap HDR colors to default framebuffer's (clamped) color range | |
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | |
shaderBloomFinal.Use(); | |
glActiveTexture(GL_TEXTURE0); | |
glBindTexture(GL_TEXTURE_2D, colorBuffers[0]); | |
//glBindTexture(GL_TEXTURE_2D, pingpongColorbuffers[!horizontal]); | |
glActiveTexture(GL_TEXTURE1); | |
glBindTexture(GL_TEXTURE_2D, pingpongColorbuffers[!horizontal]); | |
glUniform1i(glGetUniformLocation(shaderBloomFinal.Program, "bloom"), bloom); | |
glUniform1f(glGetUniformLocation(shaderBloomFinal.Program, "exposure"), exposure); | |
RenderQuad(); | |
glBindFramebuffer(GL_FRAMEBUFFER, 0); | |
} | |
glfwSwapBuffers(window); | |
} | |
glfwTerminate(); | |
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. | |
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 | |
// 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. | |
GLuint loadTexture(GLchar const * path) | |
{ | |
// Generate texture ID and load texture data | |
GLuint textureID; | |
glGenTextures(1, &textureID); | |
int width, height; | |
unsigned char* image = SOIL_load_image(path, &width, &height, 0, SOIL_LOAD_RGB); | |
// Assign texture to ID | |
glBindTexture(GL_TEXTURE_2D, textureID); | |
glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB, width, height, 0, GL_RGB, 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; | |
} | |
bool keys[1024]; | |
bool keysPressed[1024]; | |
// Moves/alters the camera positions based on user input | |
void Do_Movement() | |
{ | |
// Camera controls | |
if (keys[GLFW_KEY_W]) | |
camera.ProcessKeyboard(FORWARD, deltaTime); | |
if (keys[GLFW_KEY_S]) | |
camera.ProcessKeyboard(BACKWARD, deltaTime); | |
if (keys[GLFW_KEY_A]) | |
camera.ProcessKeyboard(LEFT, deltaTime); | |
if (keys[GLFW_KEY_D]) | |
camera.ProcessKeyboard(RIGHT, deltaTime); | |
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 | |
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) | |
{ | |
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) | |
glfwSetWindowShouldClose(window, GL_TRUE); | |
if (key >= 0 && key <= 1024) | |
{ | |
if (action == GLFW_PRESS) | |
keys[key] = true; | |
else if (action == GLFW_RELEASE) | |
{ | |
keys[key] = false; | |
keysPressed[key] = false; | |
} | |
} | |
} | |
void mouse_callback(GLFWwindow* window, double xpos, double ypos) | |
{ | |
if (firstMouse) | |
{ | |
lastX = xpos; | |
lastY = ypos; | |
firstMouse = false; | |
} | |
GLfloat xoffset = xpos - lastX; | |
GLfloat yoffset = lastY - ypos; | |
lastX = xpos; | |
lastY = ypos; | |
camera.ProcessMouseMovement(xoffset, yoffset); | |
} | |
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) | |
{ | |
camera.ProcessMouseScroll(yoffset); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment