generated from karl/cpp-template
Compare commits
4 Commits
5de6d88d37
...
08204fe63a
Author | SHA1 | Date | |
---|---|---|---|
08204fe63a | |||
a58aea923a | |||
ffd3807d0d | |||
71aa55acb6 |
65
BumpMapDemo.cpp
Normal file
65
BumpMapDemo.cpp
Normal file
@ -0,0 +1,65 @@
|
||||
#include "BumpMapDemo.h"
|
||||
#include "Input.h"
|
||||
#include <glm/common.hpp>
|
||||
|
||||
BumpMapDemo::BumpMapDemo()
|
||||
: number_of_steps(10.0), number_of_refinement_steps(10.0), bump_depth(0.1),
|
||||
render_shader(Shader("Shader/bump.vs", "Shader/bump.fs")),
|
||||
camera(Camera(90, 1920, 1080, 0.1, 1000.0)),
|
||||
albedo("Resources/Textures/PavingStones/PavingStones070_2K_Color.jpg", Texture::Settings()),
|
||||
bump("Resources/Textures/PavingStones/PavingStones070_2K_Displacement.jpg",
|
||||
Texture::Settings()),
|
||||
normal("Resources/Textures/PavingStones/PavingStones070_2K_Normal.jpg", Texture::Settings()) {
|
||||
// Move and rotate the camera so we see the quad well
|
||||
camera.translate(glm::vec3(0.0, -1.0, 1.0));
|
||||
camera.rotate(30, glm::vec3(1.0, 0.0, 0.0));
|
||||
}
|
||||
|
||||
void BumpMapDemo::render(float delta) {
|
||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
render_shader.use();
|
||||
|
||||
// Camera
|
||||
render_shader.setMat4("projection", camera.get_projection());
|
||||
render_shader.setMat4("view", camera.get_view());
|
||||
render_shader.setVec3("viewPos", camera.get_translation());
|
||||
|
||||
// Lighting
|
||||
render_shader.setVec3("lightPos", glm::vec3(0.0, 1.0, 5.0));
|
||||
|
||||
// Settings for bump mapping
|
||||
if (Input::is_key_down(GLFW_KEY_Q)) {
|
||||
number_of_steps += delta * 5.0;
|
||||
}
|
||||
if (Input::is_key_down(GLFW_KEY_W)) {
|
||||
number_of_steps -= delta * 5.0;
|
||||
}
|
||||
if (Input::is_key_down(GLFW_KEY_A)) {
|
||||
number_of_refinement_steps += delta * 5.0;
|
||||
}
|
||||
if (Input::is_key_down(GLFW_KEY_S)) {
|
||||
number_of_refinement_steps -= delta * 5.0;
|
||||
}
|
||||
if (Input::is_key_down(GLFW_KEY_Z)) {
|
||||
bump_depth += delta * 0.1;
|
||||
}
|
||||
if (Input::is_key_down(GLFW_KEY_X)) {
|
||||
bump_depth -= delta * 0.1;
|
||||
}
|
||||
|
||||
render_shader.setFloat("number_of_steps", glm::max(0.0f, number_of_steps));
|
||||
render_shader.setFloat("number_of_refinement_steps",
|
||||
glm::max(0.0f, number_of_refinement_steps));
|
||||
render_shader.setFloat("bump_depth", glm::max(0.0f, bump_depth));
|
||||
|
||||
// Textures
|
||||
albedo.bind_to(0);
|
||||
normal.bind_to(1);
|
||||
bump.bind_to(2);
|
||||
|
||||
// Quad which is rendered onto
|
||||
quad_mesh.rotate(delta * 25.0f, glm::normalize(glm::vec3(0.0, 0.0, 1.0)));
|
||||
quad_mesh.render(render_shader);
|
||||
}
|
32
BumpMapDemo.h
Normal file
32
BumpMapDemo.h
Normal file
@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include "Camera.h"
|
||||
#include "Framebuffer3D.h"
|
||||
#include "QuadMesh.h"
|
||||
#include "Shader.h"
|
||||
#include "Texture.h"
|
||||
#include "VertexBuffer.h"
|
||||
|
||||
class BumpMapDemo {
|
||||
public:
|
||||
BumpMapDemo();
|
||||
|
||||
void render(float delta);
|
||||
|
||||
private:
|
||||
float number_of_steps;
|
||||
float number_of_refinement_steps;
|
||||
float bump_depth;
|
||||
|
||||
Shader render_shader;
|
||||
|
||||
VertexBuffer vertex_rectangle;
|
||||
|
||||
Camera camera;
|
||||
|
||||
Texture albedo;
|
||||
Texture bump;
|
||||
Texture normal;
|
||||
|
||||
QuadMesh quad_mesh;
|
||||
};
|
119
QuadMesh.h
Normal file
119
QuadMesh.h
Normal file
@ -0,0 +1,119 @@
|
||||
#pragma once
|
||||
|
||||
// Must be the first include
|
||||
#include <glad/glad.h>
|
||||
|
||||
// Other includes
|
||||
#include "Shader.h"
|
||||
#include "Spatial.h"
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
// A simple 2x2 quad mesh consisting of two triangles. Oriented upwards by default.
|
||||
class QuadMesh : public Spatial {
|
||||
public:
|
||||
QuadMesh() {
|
||||
// Positions
|
||||
glm::vec3 pos1(-1.0f, 1.0f, 0.0f);
|
||||
glm::vec3 pos2(-1.0f, -1.0f, 0.0f);
|
||||
glm::vec3 pos3(1.0f, -1.0f, 0.0f);
|
||||
glm::vec3 pos4(1.0f, 1.0f, 0.0f);
|
||||
|
||||
// Texture coordinates
|
||||
glm::vec2 uv1(0.0f, 1.0f);
|
||||
glm::vec2 uv2(0.0f, 0.0f);
|
||||
glm::vec2 uv3(1.0f, 0.0f);
|
||||
glm::vec2 uv4(1.0f, 1.0f);
|
||||
|
||||
// Normal vector
|
||||
glm::vec3 nm(0.0f, 0.0f, 1.0f);
|
||||
|
||||
// Calculate tangent/bitangent vectors of both triangles
|
||||
glm::vec3 tangent1, bitangent1;
|
||||
glm::vec3 tangent2, bitangent2;
|
||||
|
||||
// Triangle 1
|
||||
glm::vec3 edge1 = pos2 - pos1;
|
||||
glm::vec3 edge2 = pos3 - pos1;
|
||||
glm::vec2 deltaUV1 = uv2 - uv1;
|
||||
glm::vec2 deltaUV2 = uv3 - uv1;
|
||||
|
||||
float f = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV2.x * deltaUV1.y);
|
||||
|
||||
tangent1.x = f * (deltaUV2.y * edge1.x - deltaUV1.y * edge2.x);
|
||||
tangent1.y = f * (deltaUV2.y * edge1.y - deltaUV1.y * edge2.y);
|
||||
tangent1.z = f * (deltaUV2.y * edge1.z - deltaUV1.y * edge2.z);
|
||||
tangent1 = glm::normalize(tangent1);
|
||||
|
||||
bitangent1.x = f * (-deltaUV2.x * edge1.x + deltaUV1.x * edge2.x);
|
||||
bitangent1.y = f * (-deltaUV2.x * edge1.y + deltaUV1.x * edge2.y);
|
||||
bitangent1.z = f * (-deltaUV2.x * edge1.z + deltaUV1.x * edge2.z);
|
||||
bitangent1 = glm::normalize(bitangent1);
|
||||
|
||||
// Triangle 2
|
||||
edge1 = pos3 - pos1;
|
||||
edge2 = pos4 - pos1;
|
||||
deltaUV1 = uv3 - uv1;
|
||||
deltaUV2 = uv4 - uv1;
|
||||
|
||||
f = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV2.x * deltaUV1.y);
|
||||
|
||||
tangent2.x = f * (deltaUV2.y * edge1.x - deltaUV1.y * edge2.x);
|
||||
tangent2.y = f * (deltaUV2.y * edge1.y - deltaUV1.y * edge2.y);
|
||||
tangent2.z = f * (deltaUV2.y * edge1.z - deltaUV1.y * edge2.z);
|
||||
tangent2 = glm::normalize(tangent2);
|
||||
|
||||
bitangent2.x = f * (-deltaUV2.x * edge1.x + deltaUV1.x * edge2.x);
|
||||
bitangent2.y = f * (-deltaUV2.x * edge1.y + deltaUV1.x * edge2.y);
|
||||
bitangent2.z = f * (-deltaUV2.x * edge1.z + deltaUV1.x * edge2.z);
|
||||
bitangent2 = glm::normalize(bitangent2);
|
||||
|
||||
float quadVertices[] = {
|
||||
// positions // normal // texcoords // tangent // bitangent
|
||||
pos1.x, pos1.y, pos1.z, nm.x, nm.y, nm.z, uv1.x,
|
||||
uv1.y, tangent1.x, tangent1.y, tangent1.z, bitangent1.x, bitangent1.y, bitangent1.z,
|
||||
pos2.x, pos2.y, pos2.z, nm.x, nm.y, nm.z, uv2.x,
|
||||
uv2.y, tangent1.x, tangent1.y, tangent1.z, bitangent1.x, bitangent1.y, bitangent1.z,
|
||||
pos3.x, pos3.y, pos3.z, nm.x, nm.y, nm.z, uv3.x,
|
||||
uv3.y, tangent1.x, tangent1.y, tangent1.z, bitangent1.x, bitangent1.y, bitangent1.z,
|
||||
|
||||
pos1.x, pos1.y, pos1.z, nm.x, nm.y, nm.z, uv1.x,
|
||||
uv1.y, tangent2.x, tangent2.y, tangent2.z, bitangent2.x, bitangent2.y, bitangent2.z,
|
||||
pos3.x, pos3.y, pos3.z, nm.x, nm.y, nm.z, uv3.x,
|
||||
uv3.y, tangent2.x, tangent2.y, tangent2.z, bitangent2.x, bitangent2.y, bitangent2.z,
|
||||
pos4.x, pos4.y, pos4.z, nm.x, nm.y, nm.z, uv4.x,
|
||||
uv4.y, tangent2.x, tangent2.y, tangent2.z, bitangent2.x, bitangent2.y, bitangent2.z};
|
||||
|
||||
// Configure 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, 14 * sizeof(float), (void *)0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 14 * sizeof(float),
|
||||
(void *)(3 * sizeof(float)));
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 14 * sizeof(float),
|
||||
(void *)(6 * sizeof(float)));
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 14 * sizeof(float),
|
||||
(void *)(8 * sizeof(float)));
|
||||
glEnableVertexAttribArray(4);
|
||||
glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, 14 * sizeof(float),
|
||||
(void *)(11 * sizeof(float)));
|
||||
}
|
||||
|
||||
void render(Shader &shader) {
|
||||
shader.setMat4("model", get_matrix());
|
||||
|
||||
glBindVertexArray(quadVAO);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned int quadVAO = 0;
|
||||
unsigned int quadVBO;
|
||||
};
|
95
Shader/bump.fs
Normal file
95
Shader/bump.fs
Normal file
@ -0,0 +1,95 @@
|
||||
#version 430 core
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
in VS_OUT {
|
||||
vec3 FragPos;
|
||||
vec2 TexCoords;
|
||||
vec3 TangentLightPos;
|
||||
vec3 TangentViewPos;
|
||||
vec3 TangentFragPos;
|
||||
} fs_in;
|
||||
|
||||
layout (binding = 0) uniform sampler2D albedoMap;
|
||||
layout (binding = 1) uniform sampler2D normalMap;
|
||||
layout (binding = 2) uniform sampler2D depthMap;
|
||||
|
||||
uniform float bump_depth;
|
||||
uniform float number_of_steps;
|
||||
uniform float number_of_refinement_steps;
|
||||
|
||||
vec2 get_parallax_offset_uv(vec2 uv, vec3 view_direction) {
|
||||
float layer_depth = 1.0 / number_of_steps;
|
||||
float refinement_layer_depth = layer_depth / number_of_refinement_steps;
|
||||
|
||||
float current_layer_depth = 0.0;
|
||||
|
||||
// the amount to shift the texture coordinates per layer (from vector total_uv_shift)
|
||||
vec2 total_uv_shift = view_direction.xy / view_direction.z * bump_depth;
|
||||
vec2 uv_shift_per_layer = total_uv_shift / number_of_steps;
|
||||
vec2 uv_refine_shift_per_layer = total_uv_shift / (number_of_steps * number_of_refinement_steps);
|
||||
|
||||
// Initial values
|
||||
vec2 current_uv = uv;
|
||||
float current_bump_value = 1.0 - texture(depthMap, current_uv).r;
|
||||
|
||||
// Loop until our depth is greater than the value in the bump map, meaning our ray collided
|
||||
while(current_layer_depth < current_bump_value) {
|
||||
current_uv -= uv_shift_per_layer;
|
||||
current_bump_value = 1.0 - texture(depthMap, current_uv).r;
|
||||
current_layer_depth += layer_depth;
|
||||
}
|
||||
|
||||
// Reverse the last operations so we're at the point before the collision
|
||||
current_uv += uv_shift_per_layer;
|
||||
current_bump_value = 1.0 - texture(depthMap, current_uv).r;
|
||||
|
||||
// Loop again for the refinement steps
|
||||
while(current_layer_depth < current_bump_value) {
|
||||
current_uv -= uv_refine_shift_per_layer;
|
||||
current_bump_value = 1.0 - texture(depthMap, current_uv).r;
|
||||
current_layer_depth += refinement_layer_depth;
|
||||
}
|
||||
|
||||
// Referse the UV operation again and return the result
|
||||
current_uv += uv_refine_shift_per_layer;
|
||||
|
||||
return current_uv;
|
||||
}
|
||||
|
||||
void main() {
|
||||
// Offset texture coordinates with Parallax Mapping
|
||||
vec3 view_direction = normalize(fs_in.TangentViewPos - fs_in.TangentFragPos);
|
||||
vec2 uv = fs_in.TexCoords;
|
||||
|
||||
uv = get_parallax_offset_uv(fs_in.TexCoords, view_direction);
|
||||
|
||||
// Discard if the parallax offset moved us outside of the texture
|
||||
if (uv.x > 1.0 || uv.y > 1.0 || uv.x < 0.0 || uv.y < 0.0)
|
||||
discard;
|
||||
|
||||
// Get normal from normal map and scale it to -1..1
|
||||
vec3 normal = texture(normalMap, uv).rgb;
|
||||
normal = normalize(normal * 2.0 - 1.0);
|
||||
|
||||
// Get albedo color
|
||||
vec3 color = texture(albedoMap, uv).rgb;
|
||||
|
||||
// Ambient lighting
|
||||
vec3 ambient = 0.1 * color;
|
||||
|
||||
// Apply albedo with intensity based on the dot product between the light direction and the normal here
|
||||
vec3 light_direction = normalize(fs_in.TangentLightPos - fs_in.TangentFragPos);
|
||||
float light_normal_dot = max(dot(light_direction, normal), 0.0);
|
||||
vec3 albedo = light_normal_dot * color;
|
||||
|
||||
// Specular lighting
|
||||
vec3 halfway_reflected_light_direction = normalize(light_direction + view_direction);
|
||||
float spec = pow(max(dot(normal, halfway_reflected_light_direction), 0.0), 32.0);
|
||||
|
||||
vec3 specular = vec3(0.2) * spec;
|
||||
|
||||
// Apply
|
||||
FragColor = vec4(ambient + albedo + specular, 1.0);
|
||||
}
|
||||
|
37
Shader/bump.vs
Normal file
37
Shader/bump.vs
Normal file
@ -0,0 +1,37 @@
|
||||
#version 430
|
||||
|
||||
layout (location = 0) in vec3 aPos;
|
||||
layout (location = 1) in vec3 aNormal;
|
||||
layout (location = 2) in vec2 aTexCoords;
|
||||
layout (location = 3) in vec3 aTangent;
|
||||
layout (location = 4) in vec3 aBitangent;
|
||||
|
||||
out VS_OUT {
|
||||
vec3 FragPos;
|
||||
vec2 TexCoords;
|
||||
vec3 TangentLightPos;
|
||||
vec3 TangentViewPos;
|
||||
vec3 TangentFragPos;
|
||||
} vs_out;
|
||||
|
||||
uniform mat4 projection;
|
||||
uniform mat4 view;
|
||||
uniform mat4 model;
|
||||
|
||||
uniform vec3 lightPos;
|
||||
uniform vec3 viewPos;
|
||||
|
||||
void main() {
|
||||
gl_Position = projection * view * model * vec4(aPos, 1.0);
|
||||
vs_out.FragPos = vec3(model * vec4(aPos, 1.0));
|
||||
vs_out.TexCoords = aTexCoords;
|
||||
|
||||
vec3 T = normalize(mat3(model) * aTangent);
|
||||
vec3 B = normalize(mat3(model) * aBitangent);
|
||||
vec3 N = normalize(mat3(model) * aNormal);
|
||||
mat3 TBN = transpose(mat3(T, B, N));
|
||||
|
||||
vs_out.TangentLightPos = TBN * lightPos;
|
||||
vs_out.TangentViewPos = TBN * viewPos;
|
||||
vs_out.TangentFragPos = TBN * vs_out.FragPos;
|
||||
}
|
3
main.cpp
3
main.cpp
@ -5,6 +5,7 @@
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <iostream>
|
||||
|
||||
#include "BumpMapDemo.h"
|
||||
#include "Framebuffer3D.h"
|
||||
#include "Input.h"
|
||||
#include "MCRenderer.h"
|
||||
@ -59,7 +60,7 @@ int main() {
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
// Setup the Marching Cubes renderer
|
||||
MCRenderer renderer = MCRenderer(128, 128, 128);
|
||||
BumpMapDemo renderer;
|
||||
|
||||
// render loop
|
||||
double timeInLastFrame = glfwGetTime();
|
||||
|
Loading…
x
Reference in New Issue
Block a user