Merge branch 'sRGB' into master
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -3,3 +3,5 @@ build
|
||||
lib/assimp/libassimp.so.5.0.0
|
||||
res/models
|
||||
res/textures
|
||||
.kdev4/Fall-Fever.kdev4
|
||||
Fall-Fever.kdev4
|
||||
|
||||
@@ -9,7 +9,7 @@ Size=894,195
|
||||
Collapsed=0
|
||||
|
||||
[Window][Debug Utils]
|
||||
Pos=39,30
|
||||
Size=908,204
|
||||
Pos=12,15
|
||||
Size=871,365
|
||||
Collapsed=0
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ layout(location = 0) out vec4 f_color;
|
||||
in vec3 v_normal;
|
||||
in vec2 v_texCoord;
|
||||
in vec3 v_fragmentPosition;
|
||||
in vec4 v_fragmentPositionDirectionalLightSpace;
|
||||
|
||||
struct Material {
|
||||
sampler2D texture_diffuse0;
|
||||
@@ -35,8 +36,6 @@ struct PointLight {
|
||||
bool isActive;
|
||||
vec3 position;
|
||||
|
||||
float K_c;
|
||||
float K_l;
|
||||
float K_q;
|
||||
|
||||
vec3 ambient;
|
||||
@@ -54,8 +53,6 @@ struct SpotLight {
|
||||
float innerCutOff;
|
||||
float outerCutOff;
|
||||
|
||||
float K_c;
|
||||
float K_l;
|
||||
float K_q;
|
||||
|
||||
vec3 ambient;
|
||||
@@ -67,6 +64,24 @@ uniform SpotLight u_spotLight;
|
||||
uniform mat3 u_normalMatrix;
|
||||
uniform vec3 u_viewPosition;
|
||||
|
||||
uniform sampler2D u_texture_directionalShadowMap;
|
||||
uniform samplerCube u_texture_pointShadowMap0;
|
||||
//uniform samplerCube u_texture_pointShadowMap1;
|
||||
//uniform samplerCube u_texture_pointShadowMap2;
|
||||
//uniform samplerCube u_texture_pointShadowMap3;
|
||||
|
||||
vec3 sampleOffsetDirections[20] = vec3[] (
|
||||
vec3( 1, 1, 1), vec3( 1, -1, 1), vec3(-1, -1, 1), vec3(-1, 1, 1),
|
||||
vec3( 1, 1, -1), vec3( 1, -1, -1), vec3(-1, -1, -1), vec3(-1, 1, -1),
|
||||
vec3( 1, 1, 0), vec3( 1, -1, 0), vec3(-1, -1, 0), vec3(-1, 1, 0),
|
||||
vec3( 1, 0, 1), vec3(-1, 0, 1), vec3( 1, 0, -1), vec3(-1, 0, -1),
|
||||
vec3( 0, 1, 1), vec3( 0, -1, 1), vec3( 0, -1, -1), vec3( 0, 1, -1)
|
||||
);
|
||||
|
||||
uniform bool b_drawShadows;
|
||||
|
||||
uniform float pointShadowDepthMapFarPlane;
|
||||
|
||||
vec3 directionalLightContribution(DirectionalLight light, vec3 normal, vec3 viewDir);
|
||||
vec3 pointLightContribution(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir);
|
||||
vec3 spotLightContribution(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir);
|
||||
@@ -77,7 +92,10 @@ void computeShading(
|
||||
out vec3 ambient, out vec3 diffuse, out vec3 specular
|
||||
);
|
||||
|
||||
float computeAttenuation(vec3 lightPos, vec3 fragPos, float K_c, float K_l, float K_q);
|
||||
float computeAttenuation(vec3 lightPos, vec3 fragPos, float K_q);
|
||||
|
||||
float computeDirectionalShadows(vec4 fragPosLightSpace, vec3 normal, vec3 lightDir);
|
||||
float computePointShadows(vec3 fragPos, vec3 lightPos);
|
||||
|
||||
void main() {
|
||||
|
||||
@@ -109,7 +127,11 @@ vec3 directionalLightContribution(DirectionalLight light, vec3 normal, vec3 view
|
||||
vec3 ambient, diffuse, specular;
|
||||
computeShading(light.ambient, light.diffuse, light.specular, lightDir, viewDir, normal, ambient, diffuse, specular);
|
||||
|
||||
return (ambient + diffuse + specular) * 0.5f;
|
||||
float shadows = 0.0f;
|
||||
if(b_drawShadows)
|
||||
shadows = computeDirectionalShadows(v_fragmentPositionDirectionalLightSpace, normal, lightDir);
|
||||
|
||||
return (ambient + (1.0f - shadows) * (diffuse + specular));
|
||||
}
|
||||
|
||||
vec3 pointLightContribution(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir) {
|
||||
@@ -123,12 +145,16 @@ vec3 pointLightContribution(PointLight light, vec3 normal, vec3 fragPos, vec3 vi
|
||||
vec3 ambient, diffuse, specular;
|
||||
computeShading(light.ambient, light.diffuse, light.specular, lightDir, viewDir, normal, ambient, diffuse, specular);
|
||||
|
||||
float attenuation = computeAttenuation(light.position, fragPos, light.K_c, light.K_l, light.K_q);
|
||||
float attenuation = computeAttenuation(light.position, fragPos, light.K_q);
|
||||
ambient *= attenuation;
|
||||
diffuse *= attenuation;
|
||||
specular *= attenuation;
|
||||
|
||||
return (ambient + diffuse + specular);
|
||||
float shadows = 0.0f;
|
||||
if(b_drawShadows)
|
||||
shadows = computePointShadows(fragPos, light.position);
|
||||
|
||||
return (ambient + (1.0f - shadows) * (diffuse + specular));
|
||||
}
|
||||
|
||||
vec3 spotLightContribution(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir) {
|
||||
@@ -142,7 +168,7 @@ vec3 spotLightContribution(SpotLight light, vec3 normal, vec3 fragPos, vec3 view
|
||||
vec3 ambient, diffuse, specular;
|
||||
computeShading(light.ambient, light.diffuse, light.specular, lightDir, viewDir, normal, ambient, diffuse, specular);
|
||||
|
||||
float attenuation = computeAttenuation(light.position, fragPos, light.K_c, light.K_l, light.K_q);
|
||||
float attenuation = computeAttenuation(light.position, fragPos, light.K_q);
|
||||
ambient *= attenuation;
|
||||
diffuse *= attenuation;
|
||||
specular *= attenuation;
|
||||
@@ -178,9 +204,70 @@ void computeShading(
|
||||
|
||||
}
|
||||
|
||||
float computeAttenuation(vec3 lightPos, vec3 fragPos, float K_c, float K_l, float K_q) {
|
||||
float computeAttenuation(vec3 lightPos, vec3 fragPos, float K_q) {
|
||||
|
||||
float distanceLightFragment = length(lightPos - fragPos);
|
||||
return 1.0f / (K_c + K_l * distanceLightFragment + K_q * distanceLightFragment * distanceLightFragment);
|
||||
|
||||
return 1.0f / (K_q * distanceLightFragment * distanceLightFragment);
|
||||
|
||||
}
|
||||
|
||||
float computeDirectionalShadows(vec4 fragPosLightSpace, vec3 normal, vec3 lightDir) {
|
||||
|
||||
// Perspective divide
|
||||
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
|
||||
|
||||
// Transform from [-1,1] to [0,1]
|
||||
projCoords *= 0.5f;
|
||||
projCoords += 0.5f;
|
||||
|
||||
if(projCoords.z > 1.0f) return 0.0f;
|
||||
|
||||
float closestDepth = texture(u_texture_directionalShadowMap, projCoords.xy).r;
|
||||
float currentDepth = projCoords.z;
|
||||
|
||||
float bias = max(0.05 * (1.0 - dot(normal, lightDir)), 0.005);
|
||||
bias *= 0.25f;
|
||||
|
||||
float shadow = 0.0;
|
||||
vec2 texelSize = 1.0 / textureSize(u_texture_directionalShadowMap, 0);
|
||||
for(int x = -1; x <= 1; x++) {
|
||||
|
||||
for(int y = -1; y <= 1; y++) {
|
||||
|
||||
float pcfDepth = texture(u_texture_directionalShadowMap, projCoords.xy + vec2(x, y) * texelSize).r;
|
||||
shadow += currentDepth - bias > pcfDepth ? 1.0 : 0.0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
shadow /= 9.0f;
|
||||
|
||||
|
||||
return shadow;
|
||||
}
|
||||
|
||||
float computePointShadows(vec3 fragPos, vec3 lightPos) {
|
||||
|
||||
// get vector between fragment position and light position
|
||||
vec3 fragToLight = fragPos - lightPos;
|
||||
|
||||
// now get current linear depth as the length between the fragment and light position
|
||||
float currentDepth = length(fragToLight);
|
||||
|
||||
float shadow = 0.0;
|
||||
float bias = 0.05;
|
||||
int samples = 20;
|
||||
float viewDistance = length(u_viewPosition - fragPos);
|
||||
float diskRadius = 0.05;
|
||||
|
||||
for(int i = 0; i < samples; ++i) {
|
||||
float closestDepth = texture(u_texture_pointShadowMap0, fragToLight + sampleOffsetDirections[i] * diskRadius).r;
|
||||
closestDepth *= pointShadowDepthMapFarPlane;
|
||||
if(currentDepth - bias > closestDepth)
|
||||
shadow += 1.0;
|
||||
}
|
||||
|
||||
shadow /= float(samples);
|
||||
return shadow;
|
||||
}
|
||||
|
||||
@@ -8,14 +8,18 @@ out vec3 v_normal;
|
||||
out vec2 v_texCoord;
|
||||
|
||||
out vec3 v_fragmentPosition;
|
||||
out vec4 v_fragmentPositionDirectionalLightSpace;
|
||||
|
||||
uniform mat4 u_modelViewProjMatrix;
|
||||
uniform mat4 u_modelMatrix;
|
||||
|
||||
uniform mat4 u_directionalLightViewProjMatrix;
|
||||
|
||||
void main() {
|
||||
gl_Position = u_modelViewProjMatrix * vec4(a_position, 1.0f);
|
||||
|
||||
v_fragmentPosition = vec3(u_modelMatrix * vec4(a_position, 1.0f));
|
||||
v_fragmentPositionDirectionalLightSpace = u_directionalLightViewProjMatrix * vec4(v_fragmentPosition, 1.0);
|
||||
|
||||
v_normal = a_normal;
|
||||
v_texCoord = a_texCoord;
|
||||
|
||||
7
res/shaders/directionalShadowDepth.frag
Normal file
7
res/shaders/directionalShadowDepth.frag
Normal file
@@ -0,0 +1,7 @@
|
||||
#version 330 core
|
||||
|
||||
void main() {
|
||||
|
||||
// Empty as we aren't rendering to any color buffer
|
||||
|
||||
}
|
||||
11
res/shaders/directionalShadowDepth.vert
Normal file
11
res/shaders/directionalShadowDepth.vert
Normal file
@@ -0,0 +1,11 @@
|
||||
#version 330 core
|
||||
|
||||
layout(location = 0) in vec3 a_position;
|
||||
|
||||
uniform mat4 u_modelViewProjMatrix;
|
||||
|
||||
void main() {
|
||||
|
||||
gl_Position = u_modelViewProjMatrix * vec4(a_position, 1.0f);
|
||||
|
||||
}
|
||||
17
res/shaders/pointShadowDepth.frag
Normal file
17
res/shaders/pointShadowDepth.frag
Normal file
@@ -0,0 +1,17 @@
|
||||
#version 330 core
|
||||
in vec4 v_fragmentPosition;
|
||||
|
||||
uniform vec3 v_lightPos;
|
||||
uniform float pointShadowDepthMapFarPlane;
|
||||
|
||||
void main() {
|
||||
|
||||
// Distance between fragment and light source
|
||||
float lightDistance = length(v_fragmentPosition.xyz - v_lightPos);
|
||||
|
||||
// map to [0;1] range
|
||||
lightDistance = lightDistance / pointShadowDepthMapFarPlane;
|
||||
|
||||
gl_FragDepth = lightDistance;
|
||||
|
||||
}
|
||||
25
res/shaders/pointShadowDepth.geom
Normal file
25
res/shaders/pointShadowDepth.geom
Normal file
@@ -0,0 +1,25 @@
|
||||
#version 330 core
|
||||
layout (triangles) in;
|
||||
layout (triangle_strip, max_vertices=18) out;
|
||||
|
||||
uniform mat4 u_shadowMatrices[6];
|
||||
|
||||
out vec4 v_fragmentPosition;
|
||||
|
||||
void main() {
|
||||
|
||||
for(int face = 0; face < 6; face++) {
|
||||
|
||||
gl_Layer = face;
|
||||
for(int i = 0; i < 3; i++) {
|
||||
|
||||
v_fragmentPosition = gl_in[i].gl_Position;
|
||||
gl_Position = u_shadowMatrices[face] * v_fragmentPosition;
|
||||
EmitVertex();
|
||||
|
||||
}
|
||||
|
||||
EndPrimitive();
|
||||
|
||||
}
|
||||
}
|
||||
11
res/shaders/pointShadowDepth.vert
Normal file
11
res/shaders/pointShadowDepth.vert
Normal file
@@ -0,0 +1,11 @@
|
||||
#version 330 core
|
||||
|
||||
layout(location = 0) in vec3 a_position;
|
||||
|
||||
uniform mat4 u_modelMatrix;
|
||||
|
||||
void main() {
|
||||
|
||||
gl_Position = u_modelMatrix * vec4(a_position, 1.0f);
|
||||
|
||||
}
|
||||
25
res/shaders/postprocessing.frag
Normal file
25
res/shaders/postprocessing.frag
Normal file
@@ -0,0 +1,25 @@
|
||||
#version 330 core
|
||||
|
||||
const float GAMMA = 2.2f;
|
||||
|
||||
layout(location = 0) out vec4 f_color;
|
||||
|
||||
in vec2 v_tex_coords;
|
||||
|
||||
uniform float u_exposure;
|
||||
|
||||
uniform sampler2D u_texture;
|
||||
|
||||
void main() {
|
||||
|
||||
vec3 fragmentColor = vec3(texture2D(u_texture, v_tex_coords));
|
||||
|
||||
// Exposure tone mapping
|
||||
fragmentColor = vec3(1.0) - exp(-fragmentColor * u_exposure);
|
||||
|
||||
// Gamma correction
|
||||
fragmentColor = pow(fragmentColor, vec3(1.0/GAMMA));
|
||||
|
||||
f_color = vec4(fragmentColor, 1.0f);
|
||||
|
||||
}
|
||||
11
res/shaders/postprocessing.vert
Normal file
11
res/shaders/postprocessing.vert
Normal file
@@ -0,0 +1,11 @@
|
||||
#version 330 core
|
||||
|
||||
out vec2 v_tex_coords;
|
||||
|
||||
void main() {
|
||||
float x = -1.0 + float((gl_VertexID & 1) << 2);
|
||||
float y = -1.0 + float((gl_VertexID & 2) << 1);
|
||||
v_tex_coords.x = (x+1.0)*0.5;
|
||||
v_tex_coords.y = (y+1.0)*0.5;
|
||||
gl_Position = vec4(x, y, 0, 1);
|
||||
}
|
||||
@@ -8,6 +8,8 @@ uniform samplerCube u_skybox;
|
||||
|
||||
void main() {
|
||||
|
||||
f_color = texture(u_skybox, v_texCoord);
|
||||
vec3 fragmentColor = vec3(texture(u_skybox, v_texCoord));
|
||||
|
||||
}
|
||||
f_color = vec4(fragmentColor, 1.0f);
|
||||
|
||||
}
|
||||
|
||||
@@ -14,4 +14,4 @@ void main() {
|
||||
|
||||
v_texCoord = a_position;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ add_executable(Fall-Fever
|
||||
Entity.cpp
|
||||
Light.cpp
|
||||
World.cpp
|
||||
Framebuffer.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include "ShaderProgram.h"
|
||||
|
||||
class Camera {
|
||||
|
||||
@@ -17,6 +18,11 @@ public:
|
||||
void translate(glm::vec3 translateVector);
|
||||
|
||||
void setPosition(glm::vec3 position) { this->position = position; }
|
||||
void setExposure(ShaderProgram *shaderProgram) {
|
||||
shaderProgram->setUniform("exposure", exposure);
|
||||
this->exposure = exposure;
|
||||
}
|
||||
|
||||
void lookAtTarget(glm::vec3 target);
|
||||
void lookForward();
|
||||
|
||||
@@ -43,5 +49,6 @@ private:
|
||||
float speed = 2.0f;
|
||||
|
||||
float fov;
|
||||
float exposure = 1.0f;
|
||||
|
||||
};
|
||||
|
||||
@@ -31,7 +31,6 @@ Controller::Controller() {
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
glfwWindowHint(GLFW_SAMPLES, 4);
|
||||
|
||||
#ifndef _DEBUG
|
||||
glfwWindowHint(GLFW_MAXIMIZED, GL_TRUE);
|
||||
@@ -69,23 +68,29 @@ Controller::~Controller() {
|
||||
delete gameWindow;
|
||||
delete gameEventHandler;
|
||||
delete camera;
|
||||
delete pp_framebuffer;
|
||||
glfwTerminate();
|
||||
|
||||
}
|
||||
|
||||
void Controller::run() {
|
||||
glClearColor(0.15f, 0.15f, 0.15f, 1.0f);
|
||||
glClearColor(0.0015f, 0.0015f, 0.0015f, 1.0f);
|
||||
|
||||
ShaderProgram shaderProgram("res/shaders/basic.vert", "res/shaders/basic.frag");
|
||||
ShaderProgram lightProgram("res/shaders/light.vert", "res/shaders/light.frag");
|
||||
ShaderProgram skyboxProgram("res/shaders/skybox.vert", "res/shaders/skybox.frag");
|
||||
ShaderProgram postProcessingProgram("res/shaders/postprocessing.vert", "res/shaders/postprocessing.frag");
|
||||
ShaderProgram directionalShadowDepthProgram("res/shaders/directionalShadowDepth.vert", "res/shaders/directionalShadowDepth.frag");
|
||||
ShaderProgram pointShadowDepthProgram("res/shaders/pointShadowDepth.vert", "res/shaders/pointShadowDepth.geom", "res/shaders/pointShadowDepth.frag");
|
||||
|
||||
updateExposure(&postProcessingProgram);
|
||||
|
||||
//Model model_backpack("res/models/backpack.ffo");
|
||||
//Model model_plant("res/models/plant.ffo");
|
||||
//Model model_container("res/models/container.ffo");
|
||||
Model model_cube("res/models/cube.ffo");
|
||||
Model model_dragon("res/models/dragon.ffo");
|
||||
Model model_ground("res/models/ground.ffo");
|
||||
Model model_ground("res/models/wood_floor.ffo");
|
||||
//Model model_moon("res/models/moon.ffo");
|
||||
//Model model_hut("res/models/hut.ffo");
|
||||
//Model model_sphere("res/models/sphere.ffo");
|
||||
@@ -100,10 +105,12 @@ void Controller::run() {
|
||||
Entity ground(&model_ground, &shaderProgram);
|
||||
Entity lightSource(&model_cube, &lightProgram);
|
||||
|
||||
dragon.setRotation(glm::vec3(0.0f));
|
||||
dragon.setScale(0.2f);
|
||||
lightSource.setScale(0.1f);
|
||||
lightSource.setRotation(glm::vec3(0.f));
|
||||
lightSource.setPosition(glm::vec3(-2.f, 1.5f, 2.f));
|
||||
lightSource.setIsLightSource(true);
|
||||
|
||||
Skybox skybox(&model_cube, &skyboxProgram, "res/textures/skybox/");
|
||||
|
||||
@@ -114,6 +121,8 @@ void Controller::run() {
|
||||
|
||||
camera->translate(glm::vec3(0.0f, 1.5f, 5.0f));
|
||||
|
||||
pp_framebuffer = new Framebuffer(INIT_WINDOW_WIDTH, INIT_WINDOW_HEIGHT, &postProcessingProgram);
|
||||
|
||||
// This is the game loop
|
||||
while(!glfwWindowShouldClose(gameWindow->getGLFWwindow())) {
|
||||
// Timing
|
||||
@@ -121,38 +130,57 @@ void Controller::run() {
|
||||
|
||||
// Update game
|
||||
// ...
|
||||
static bool rotateLightSource = 0;
|
||||
static bool rotateLightSource = false, rotateEntity = false;
|
||||
if(rotateLightSource) {
|
||||
float radius = 4.0;
|
||||
glm::vec3 newPos = glm::vec3(-cos(glfwGetTime()*0.5), 0.5f, sin(glfwGetTime()*0.5)) * radius;
|
||||
world.getEntities()->operator[](1).setPosition(newPos);
|
||||
}
|
||||
if(rotateEntity) {
|
||||
world.getEntities()->operator[](0).rotate(glm::vec3(0.0f, 1.0f, 0.0f), 0.2f * deltaTime);
|
||||
}
|
||||
static glm::vec3 lightColor = glm::vec3(1.f);
|
||||
world.updatePointLight(0, true, world.getEntities()->operator[](1).getPosition(), lightColor);
|
||||
world.updateDirectionalLight(true, glm::vec3(1.0f), lightColor);
|
||||
static float intensity = 10.f;
|
||||
world.updatePointLight(0, true, world.getEntities()->operator[](1).getPosition(), lightColor * intensity);
|
||||
world.updateDirectionalLight(true, glm::vec3(-0.2f, -1.0f, -0.3f), lightColor * 0.25f);
|
||||
lightProgram.bind();
|
||||
lightProgram.setUniform("v_lightColor", lightColor);
|
||||
lightProgram.setUniform("v_lightColor", lightColor * 100.0f);
|
||||
lightProgram.unbind();
|
||||
|
||||
// Render and buffer swap
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
|
||||
// Calc shadows
|
||||
static bool drawShadows = true;
|
||||
shaderProgram.bind();
|
||||
shaderProgram.setUniform("b_drawShadows", (int)drawShadows);
|
||||
shaderProgram.unbind();
|
||||
if(drawShadows)
|
||||
world.calculateShadows(&directionalShadowDepthProgram, &pointShadowDepthProgram);
|
||||
|
||||
pp_framebuffer->bind();
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
camera->lookForward();
|
||||
camera->updateVPM();
|
||||
|
||||
skybox.draw(camera->getView(), camera->getProj());
|
||||
glViewport(0, 0, gameWindow->getWindowWidth(), gameWindow->getWindowHeight());
|
||||
|
||||
skybox.draw(camera->getView(), camera->getProj());
|
||||
world.draw(camera->getViewProj(), camera->getPosition());
|
||||
|
||||
pp_framebuffer->unbind();
|
||||
pp_framebuffer->render();
|
||||
|
||||
#ifdef _DEBUG
|
||||
renderImGui(world.getEntities(), &lightColor, &rotateLightSource);
|
||||
renderImGui(world.getEntities(), &world.getPointLights()[0], &lightColor, &rotateEntity, &rotateLightSource, &postProcessingProgram, &intensity, &drawShadows);
|
||||
#endif
|
||||
|
||||
glfwSwapBuffers(gameWindow->getGLFWwindow());
|
||||
|
||||
// Update window size
|
||||
if(gameWindow->checkWindowWasResized())
|
||||
updateWindowSize();
|
||||
updateWindowSize(&postProcessingProgram);
|
||||
|
||||
// Check events, handle input
|
||||
gameEventHandler->handleEvents();
|
||||
@@ -193,13 +221,22 @@ void Controller::error_callback(int error, const char* description) {
|
||||
fprintf(stderr, "Error: %s\n", description);
|
||||
}
|
||||
|
||||
void Controller::updateWindowSize() {
|
||||
void Controller::updateWindowSize(ShaderProgram *pp_program) {
|
||||
camera->updateAspectRatio(gameWindow->getWindowAspectRatio());
|
||||
gameEventHandler->setFirstMouseInput(1);
|
||||
|
||||
delete pp_framebuffer;
|
||||
pp_framebuffer = new Framebuffer(gameWindow->getWindowWidth(), gameWindow->getWindowHeight(), pp_program);
|
||||
}
|
||||
|
||||
void Controller::updateExposure(ShaderProgram *shaderProgram) {
|
||||
shaderProgram->bind();
|
||||
shaderProgram->setUniform("u_exposure", exposure);
|
||||
shaderProgram->unbind();
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
void Controller::renderImGui(std::vector<Entity> *entites, glm::vec3 *lightColor, bool *rotateLightSource) {
|
||||
void Controller::renderImGui(std::vector<Entity> *entites, PointLight *pointLight, glm::vec3 *lightColor, bool *rotateEntity, bool *rotateLightSource, ShaderProgram *postProcessingProgram, float *intensity, bool *drawShadows) {
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
@@ -207,26 +244,40 @@ void Controller::renderImGui(std::vector<Entity> *entites, glm::vec3 *lightColor
|
||||
|
||||
// render your GUI
|
||||
ImGui::Begin("Debug Utils");
|
||||
ImGui::Text("Dragon");
|
||||
ImGui::Text("Object");
|
||||
static float rotation = 0.0;
|
||||
ImGui::SliderFloat("Rotation", &rotation, 0, 2 * M_PI);
|
||||
static float translation[] = {0.0f, 0.0f};
|
||||
ImGui::SliderFloat2("Position", translation, -4.0, 4.0);
|
||||
static float translation[] = {0.0f, 0.0f, 0.0f};
|
||||
ImGui::SliderFloat3("Position", translation, -4.0, 4.0);
|
||||
static float scale = 0.2f;
|
||||
ImGui::SliderFloat("Scale", &scale, 0.02, 2.0);
|
||||
ImGui::Checkbox("Rotate Object", rotateEntity);
|
||||
|
||||
entites->operator[](0).setPosition(glm::vec3(translation[0], 0.0f, translation[1]));
|
||||
entites->operator[](0).setRotation(glm::vec3(0.f,1.0f,0.f), rotation);
|
||||
entites->operator[](0).setPosition(glm::vec3(translation[0], translation[1], translation[2]));
|
||||
if(!*rotateEntity) entites->operator[](0).setRotation(glm::vec3(0.f,1.0f,0.f), rotation);
|
||||
entites->operator[](0).setScale(scale);
|
||||
|
||||
// color picker
|
||||
ImGui::Text("Light Source");
|
||||
ImGui::Text("\nLight Source");
|
||||
static float K_q = 1.0f;
|
||||
ImGui::SliderFloat("Attenuation Parameter", &K_q, 0, 1.5f);
|
||||
|
||||
updateExposure(postProcessingProgram);
|
||||
pointLight->setParameters(K_q);
|
||||
|
||||
static float color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
|
||||
ImGui::SliderFloat("Intensity", intensity, 0, 50.f);
|
||||
|
||||
ImGui::ColorEdit3("Color", color);
|
||||
lightColor->x = color[0];
|
||||
lightColor->y = color[1];
|
||||
lightColor->z = color[2];
|
||||
|
||||
ImGui::Text("\nMiscellaneous");
|
||||
ImGui::SliderFloat("Exposure", &exposure, 0, 5.0f);
|
||||
|
||||
ImGui::Checkbox("Draw Shadows", drawShadows);
|
||||
ImGui::Checkbox("Rotate Lightsource", rotateLightSource);
|
||||
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)",
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include "ShaderProgram.h"
|
||||
#include "Entity.h"
|
||||
#include "defines.h"
|
||||
#include "Light.h"
|
||||
#include "Framebuffer.h"
|
||||
|
||||
|
||||
class Controller {
|
||||
@@ -24,17 +26,22 @@ private:
|
||||
|
||||
void limit_framerate();
|
||||
|
||||
void updateWindowSize();
|
||||
void updateWindowSize(ShaderProgram *pp_program);
|
||||
void updateExposure(ShaderProgram *shaderProgram);
|
||||
|
||||
void renderImGui(std::vector<Entity> *entites, glm::vec3 *lightColor, bool *rotateLightSource);
|
||||
void renderImGui(std::vector<Entity> *entites, PointLight *pointLight, glm::vec3 *lightColor, bool *rotateEntity, bool *rotateLightSource, ShaderProgram *postProcessingProgram, float *intensity, bool *drawShadows);
|
||||
|
||||
Window *gameWindow;
|
||||
EventHandler *gameEventHandler;
|
||||
Camera *camera;
|
||||
|
||||
Framebuffer *pp_framebuffer;
|
||||
|
||||
const uint16_t MAX_FPS = 60;
|
||||
double deltaTime;
|
||||
|
||||
bool wireFrameMode = 0;
|
||||
|
||||
float exposure = 1.0f;
|
||||
|
||||
};
|
||||
|
||||
@@ -32,6 +32,33 @@ void Entity::draw(glm::mat4 viewProjMatrix, glm::vec3 viewPosition) {
|
||||
|
||||
}
|
||||
|
||||
void Entity::drawDirectionalShadows(glm::mat4 viewProjMatrix, ShaderProgram *p_shaderProgram) {
|
||||
|
||||
p_shaderProgram->bind();
|
||||
|
||||
glm::mat4 modelViewProj = viewProjMatrix * modelMatrix;
|
||||
shaderProgram->setUniform("u_modelViewProjMatrix", modelViewProj);
|
||||
|
||||
// Draw the model
|
||||
model->drawWithoutTextures();
|
||||
|
||||
p_shaderProgram->unbind();
|
||||
|
||||
}
|
||||
|
||||
void Entity::drawPointShadows(ShaderProgram *p_shaderProgram) {
|
||||
|
||||
p_shaderProgram->bind();
|
||||
|
||||
p_shaderProgram->setUniform("u_modelMatrix", modelMatrix);
|
||||
|
||||
// Draw the model
|
||||
model->drawWithoutTextures();
|
||||
|
||||
p_shaderProgram->unbind();
|
||||
|
||||
}
|
||||
|
||||
void Entity::translate(glm::vec3 vector) {
|
||||
position += vector;
|
||||
updateModelMatrix();
|
||||
|
||||
@@ -15,6 +15,8 @@ public:
|
||||
~Entity() = default;
|
||||
|
||||
void draw(glm::mat4 viewProjMatrix, glm::vec3 viewPosition);
|
||||
void drawDirectionalShadows(glm::mat4 viewProjMatrix, ShaderProgram *p_shaderProgram);
|
||||
void drawPointShadows(ShaderProgram *p_shaderProgram);
|
||||
|
||||
void translate(glm::vec3 vector);
|
||||
void rotate(glm::vec3 axis, float radians);
|
||||
@@ -24,17 +26,21 @@ public:
|
||||
void setRotation(glm::vec3 axis, float radians);
|
||||
void setScale(float scaleFactor);
|
||||
|
||||
void setIsLightSource(bool temp) { isLightSource = temp;}
|
||||
|
||||
void setId(uint32_t id) { this->id = id; }
|
||||
uint32_t getId() { return id; }
|
||||
|
||||
glm::vec3 getPosition() { return position; }
|
||||
glm::mat4 getModelMatrix() { return modelMatrix; }
|
||||
bool getIsLightSource() { return isLightSource; }
|
||||
|
||||
private:
|
||||
|
||||
void updateModelMatrix();
|
||||
|
||||
uint32_t id;
|
||||
bool isLightSource = false;
|
||||
|
||||
glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||
glm::quat quaternion;
|
||||
|
||||
116
src/Framebuffer.cpp
Normal file
116
src/Framebuffer.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
#include "Framebuffer.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <iostream>
|
||||
|
||||
Framebuffer::Framebuffer(uint32_t width, uint32_t height, ShaderProgram *shaderProgram) {
|
||||
|
||||
this->shaderProgram = shaderProgram;
|
||||
|
||||
glGenFramebuffers(1, &FBO);
|
||||
|
||||
glGenTextures(2, textures);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, textures[0]);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, 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, textures[1]);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, width, height, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 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);
|
||||
|
||||
bind();
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0], 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, textures[1], 0);
|
||||
unbind();
|
||||
}
|
||||
|
||||
Framebuffer::~Framebuffer() {
|
||||
glDeleteFramebuffers(1, &FBO);
|
||||
glDeleteTextures(2, textures);
|
||||
}
|
||||
|
||||
void Framebuffer::bind() {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, FBO);
|
||||
}
|
||||
|
||||
void Framebuffer::unbind() {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
void Framebuffer::render() {
|
||||
|
||||
// Disable wireframe mode
|
||||
GLint wireframe;
|
||||
glGetIntegerv(GL_POLYGON_MODE, &wireframe);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
|
||||
shaderProgram->bind();
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, getTextureId());
|
||||
GLint location = glGetUniformLocation(shaderProgram->getShaderProgramId(), "u_texture");
|
||||
glUniform1i(location, 0);
|
||||
|
||||
// A VAO is necessary although no data is stored in it
|
||||
GLuint temp_vao;
|
||||
glGenVertexArrays(1, &temp_vao);
|
||||
glBindVertexArray(temp_vao);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
glBindVertexArray(0);
|
||||
|
||||
glPolygonMode(GL_FRONT_AND_BACK, wireframe);
|
||||
shaderProgram->unbind();
|
||||
}
|
||||
|
||||
|
||||
|
||||
DepthMap::DepthMap(int TYPE, int RESOLUTION)
|
||||
: cubeMap(RESOLUTION) {
|
||||
|
||||
if(TYPE == DEPTHMAP_NORMAL) {
|
||||
|
||||
glGenFramebuffers(1, &depthMapFBO);
|
||||
|
||||
glGenTextures(1, &depthMap);
|
||||
glBindTexture(GL_TEXTURE_2D, depthMap);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, RESOLUTION, RESOLUTION, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
bind();
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthMap, 0);
|
||||
glDrawBuffer(GL_NONE);
|
||||
glReadBuffer(GL_NONE);
|
||||
unbind();
|
||||
|
||||
} else if(TYPE == DEPTHMAP_CUBEMAP) {
|
||||
|
||||
glGenFramebuffers(1, &depthMapFBO);
|
||||
|
||||
// CubeMap is already created
|
||||
|
||||
bind();
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, cubeMap.getTextureId(), 0);
|
||||
glDrawBuffer(GL_NONE);
|
||||
glReadBuffer(GL_NONE);
|
||||
unbind();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void DepthMap::bind() {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO);
|
||||
}
|
||||
|
||||
void DepthMap::unbind() {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
59
src/Framebuffer.h
Normal file
59
src/Framebuffer.h
Normal file
@@ -0,0 +1,59 @@
|
||||
#pragma once
|
||||
|
||||
#include <glad/glad.h>
|
||||
#include "ShaderProgram.h"
|
||||
#include "Texture.h"
|
||||
|
||||
class Framebuffer {
|
||||
|
||||
public:
|
||||
|
||||
Framebuffer(uint32_t width, uint32_t height, ShaderProgram *ShaderProgram);
|
||||
~Framebuffer();
|
||||
|
||||
void bind();
|
||||
void unbind();
|
||||
|
||||
void render();
|
||||
|
||||
GLuint getTextureId() {
|
||||
return textures[0];
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
GLuint FBO;
|
||||
GLuint textures[2];
|
||||
|
||||
ShaderProgram *shaderProgram;
|
||||
|
||||
};
|
||||
|
||||
enum depthMapType {DEPTHMAP_NORMAL, DEPTHMAP_CUBEMAP};
|
||||
|
||||
// Framebuffer without color buffer. (Shadows)
|
||||
class DepthMap {
|
||||
|
||||
public:
|
||||
|
||||
// Normal depthMap with texture and point depthMap with cubeMap
|
||||
DepthMap(int TYPE, int RESOLUTION);
|
||||
|
||||
void bind();
|
||||
void unbind();
|
||||
|
||||
GLuint getFBO() { return depthMapFBO; }
|
||||
GLuint getDepthMap() { return depthMap; }
|
||||
GLuint getCubeMapId() { return cubeMap.getTextureId(); }
|
||||
|
||||
private:
|
||||
|
||||
GLuint depthMapFBO;
|
||||
|
||||
// Either a normal depthMap is used (Directional shadows)
|
||||
// or a cubeMap is used (Point shadows)
|
||||
GLuint depthMap;
|
||||
CubeMap cubeMap;
|
||||
|
||||
|
||||
};
|
||||
@@ -18,8 +18,6 @@ void PointLight::update() {
|
||||
shaderProgram->setUniform((_getStructMemberName() + "ambient").c_str(), ambientColor);
|
||||
shaderProgram->setUniform((_getStructMemberName() + "diffuse").c_str(), diffuseColor);
|
||||
shaderProgram->setUniform((_getStructMemberName() + "specular").c_str(), specularColor);
|
||||
shaderProgram->setUniform((_getStructMemberName() + "K_c").c_str(), K_c);
|
||||
shaderProgram->setUniform((_getStructMemberName() + "K_l").c_str(), K_l);
|
||||
shaderProgram->setUniform((_getStructMemberName() + "K_q").c_str(), K_q);
|
||||
|
||||
shaderProgram->unbind();
|
||||
@@ -45,9 +43,9 @@ void DirectionalLight::update() {
|
||||
|
||||
shaderProgram->setUniform("u_directionalLight.isActive", isActive);
|
||||
shaderProgram->setUniform("u_directionalLight.direction", direction);
|
||||
shaderProgram->setUniform("u_directionalLight.ambient", ambientColor * 0.25f);
|
||||
shaderProgram->setUniform("u_directionalLight.diffuse", diffuseColor * 0.25f);
|
||||
shaderProgram->setUniform("u_directionalLight.specular", specularColor * 0.25f);
|
||||
shaderProgram->setUniform("u_directionalLight.ambient", ambientColor);
|
||||
shaderProgram->setUniform("u_directionalLight.diffuse", diffuseColor);
|
||||
shaderProgram->setUniform("u_directionalLight.specular", specularColor);
|
||||
|
||||
shaderProgram->unbind();
|
||||
|
||||
|
||||
19
src/Light.h
19
src/Light.h
@@ -19,7 +19,7 @@ public:
|
||||
void setColor(glm::vec3 color) {
|
||||
lightColor = color;
|
||||
diffuseColor = lightColor * glm::vec3(1.0f);
|
||||
ambientColor = diffuseColor * glm::vec3(0.1f);
|
||||
ambientColor = diffuseColor * glm::vec3(0.002f);
|
||||
specularColor = lightColor * glm::vec3(1.0f);
|
||||
update();
|
||||
}
|
||||
@@ -29,14 +29,16 @@ public:
|
||||
update();
|
||||
}
|
||||
|
||||
glm::vec3 getColor() { return lightColor; }
|
||||
|
||||
protected:
|
||||
|
||||
Light() = default;
|
||||
Light(ShaderProgram *shaderProgram) : shaderProgram(shaderProgram) {}
|
||||
|
||||
ShaderProgram *shaderProgram;
|
||||
|
||||
bool isActive = false;
|
||||
bool shouldCastShadow = true;
|
||||
|
||||
// Color
|
||||
glm::vec3 lightColor;
|
||||
@@ -50,7 +52,6 @@ class PointLight : public Light {
|
||||
|
||||
public:
|
||||
|
||||
PointLight() = default;
|
||||
PointLight(ShaderProgram *shaderProgram);
|
||||
|
||||
void setPosition(glm::vec3 position) {
|
||||
@@ -58,8 +59,12 @@ public:
|
||||
update();
|
||||
}
|
||||
|
||||
void setParameters(float K_q) { this->K_q = K_q; }
|
||||
|
||||
void setId(unsigned int id) { lightId = id; }
|
||||
|
||||
glm::vec3 getPosition() { return position; }
|
||||
|
||||
|
||||
private:
|
||||
|
||||
@@ -68,8 +73,7 @@ private:
|
||||
unsigned int lightId;
|
||||
|
||||
glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||
float K_c = 1.0f;
|
||||
float K_l = 0.09f;
|
||||
|
||||
float K_q = 0.032f;
|
||||
|
||||
};
|
||||
@@ -78,7 +82,6 @@ class DirectionalLight : public Light {
|
||||
|
||||
public:
|
||||
|
||||
DirectionalLight() = default;
|
||||
DirectionalLight(ShaderProgram *shaderProgram);
|
||||
|
||||
void setDirection(glm::vec3 direction) {
|
||||
@@ -90,8 +93,6 @@ private:
|
||||
|
||||
void update() override;
|
||||
|
||||
bool isActive = true;
|
||||
|
||||
glm::vec3 direction = glm::vec3(-0.2f, -1.0f, -0.3f);
|
||||
glm::vec3 direction;
|
||||
|
||||
};
|
||||
|
||||
@@ -28,6 +28,15 @@ void Model::draw(ShaderProgram *shaderProgram) {
|
||||
|
||||
}
|
||||
|
||||
void Model::drawWithoutTextures() {
|
||||
|
||||
// Iterate through every mesh and call the draw function
|
||||
for(auto it = meshes.begin(); it != meshes.end(); it++) {
|
||||
(*it)->drawWithoutTextures();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Model::loadModel(std::string pathToModel) {
|
||||
|
||||
std::ifstream input(pathToModel, std::ios::in | std::ios::binary);
|
||||
|
||||
@@ -13,6 +13,7 @@ public:
|
||||
~Model();
|
||||
|
||||
void draw(ShaderProgram *shaderProgram);
|
||||
void drawWithoutTextures();
|
||||
|
||||
Mesh * getMesh(unsigned int index) { return meshes[index]; }
|
||||
|
||||
|
||||
@@ -6,13 +6,64 @@
|
||||
#include "ShaderProgram.h"
|
||||
|
||||
ShaderProgram::ShaderProgram(const char* vertexShaderPath, const char* fragmentShaderPath) {
|
||||
shaderProgramId = createShader(vertexShaderPath, fragmentShaderPath);
|
||||
|
||||
// Set transformation matrix as default to identity matrix
|
||||
bind();
|
||||
glm::mat4 identity_matrix = glm::mat4(1.0f);
|
||||
setUniform("transform", identity_matrix);
|
||||
unbind();
|
||||
std::string vertexShaderSource = parse(vertexShaderPath);
|
||||
std::string fragmentShaderSource = parse(fragmentShaderPath);
|
||||
|
||||
shaderProgramId = glCreateProgram();
|
||||
GLuint vs = compile(vertexShaderSource, GL_VERTEX_SHADER);
|
||||
GLuint fs = compile(fragmentShaderSource, GL_FRAGMENT_SHADER);
|
||||
|
||||
glAttachShader(shaderProgramId, vs);
|
||||
glAttachShader(shaderProgramId, fs);
|
||||
|
||||
glLinkProgram(shaderProgramId);
|
||||
|
||||
GLint isLinked = 0;
|
||||
glGetProgramiv(shaderProgramId, GL_LINK_STATUS, &isLinked);
|
||||
if(!isLinked) std::cout << "Failed to link shaderProgram: " << vertexShaderPath << ", " << fragmentShaderPath << std::endl;
|
||||
|
||||
#ifdef _RELEASE
|
||||
glDetachShader(program, vs);
|
||||
glDetachShader(program, fs);
|
||||
|
||||
glDeleteShader(vs);
|
||||
glDeleteShader(fs);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
ShaderProgram::ShaderProgram(const char* vertexShaderPath, const char* geometryShaderPath, const char* fragmentShaderPath) {
|
||||
|
||||
std::string vertexShaderSource = parse(vertexShaderPath);
|
||||
std::string geometryShaderSource = parse(geometryShaderPath);
|
||||
std::string fragmentShaderSource = parse(fragmentShaderPath);
|
||||
|
||||
shaderProgramId = glCreateProgram();
|
||||
GLuint vs = compile(vertexShaderSource, GL_VERTEX_SHADER);
|
||||
GLuint gs = compile(geometryShaderSource, GL_GEOMETRY_SHADER);
|
||||
GLuint fs = compile(fragmentShaderSource, GL_FRAGMENT_SHADER);
|
||||
|
||||
glAttachShader(shaderProgramId, vs);
|
||||
glAttachShader(shaderProgramId, gs);
|
||||
glAttachShader(shaderProgramId, fs);
|
||||
|
||||
glLinkProgram(shaderProgramId);
|
||||
|
||||
GLint isLinked = 0;
|
||||
glGetProgramiv(shaderProgramId, GL_LINK_STATUS, &isLinked);
|
||||
if(!isLinked) std::cout << "Failed to link shaderProgram: " << vertexShaderPath << ", " << geometryShaderPath << ", " << fragmentShaderPath << std::endl;
|
||||
|
||||
#ifdef _RELEASE
|
||||
glDetachShader(program, vs);
|
||||
glDetachShader(program, gs);
|
||||
glDetachShader(program, fs);
|
||||
|
||||
glDeleteShader(vs);
|
||||
glDeleteShader(gs);
|
||||
glDeleteShader(fs);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
ShaderProgram::~ShaderProgram() {
|
||||
@@ -27,35 +78,11 @@ void ShaderProgram::unbind() {
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
GLuint ShaderProgram::createShader(const char* vertexShaderPath, const char* framentShaderPath) {
|
||||
std::string vertexShaderSource = parse(vertexShaderPath);
|
||||
std::string fragmentShaderSource = parse(framentShaderPath);
|
||||
|
||||
GLuint program = glCreateProgram();
|
||||
GLuint vs = compile(vertexShaderSource, GL_VERTEX_SHADER);
|
||||
GLuint fs = compile(fragmentShaderSource, GL_FRAGMENT_SHADER);
|
||||
|
||||
glAttachShader(program, vs);
|
||||
glAttachShader(program, fs);
|
||||
|
||||
glLinkProgram(program);
|
||||
|
||||
#ifdef _RELEASE
|
||||
glDetachShader(program, vs);
|
||||
glDetachShader(program, fs);
|
||||
|
||||
glDeleteShader(vs);
|
||||
glDeleteShader(fs);
|
||||
#endif
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
std::string ShaderProgram::parse(const char* filename) {
|
||||
FILE* file;
|
||||
file = fopen(filename, "rb");
|
||||
if(!file) {
|
||||
std::cout << "File " << filename << " not found!" << std::endl;
|
||||
std::cout << "Shader " << filename << " not found!" << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,8 @@ class ShaderProgram {
|
||||
|
||||
public:
|
||||
|
||||
ShaderProgram(const char* vertexShaderPath, const char* framentShaderPath);
|
||||
ShaderProgram(const char* vertexShaderPath, const char* fragmentShaderPath);
|
||||
ShaderProgram(const char* vertexShaderPath, const char* geometryShaderPath, const char* fragmentShaderPath);
|
||||
~ShaderProgram();
|
||||
|
||||
void bind();
|
||||
@@ -28,7 +29,6 @@ private:
|
||||
|
||||
std::string parse(const char* filename);
|
||||
GLuint compile(std::string shaderSource, GLenum type);
|
||||
GLuint createShader(const char* vertexShaderPath, const char* framentShaderPath);
|
||||
|
||||
GLuint shaderProgramId;
|
||||
|
||||
|
||||
@@ -28,7 +28,10 @@ Texture::Texture(const char* texturePath, uint8_t textureType) {
|
||||
return;
|
||||
}
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, textureWidth, textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureBuffer);
|
||||
if(textureType == texture_diffuse)
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB8_ALPHA8, textureWidth, textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureBuffer);
|
||||
else
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, textureWidth, textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureBuffer);
|
||||
//glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
stbi_image_free(textureBuffer);
|
||||
@@ -91,7 +94,7 @@ CubeMap::CubeMap(const char* texturePseudoPath) {
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
|
||||
for(unsigned int i = 0; i < CUBEMAP_FACES_NUM_ITEMS; i++) {
|
||||
|
||||
@@ -102,7 +105,7 @@ CubeMap::CubeMap(const char* texturePseudoPath) {
|
||||
return;
|
||||
}
|
||||
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA8, textureWidth, textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureBuffer);
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_SRGB8_ALPHA8, textureWidth, textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureBuffer);
|
||||
|
||||
stbi_image_free(textureBuffer);
|
||||
|
||||
@@ -112,6 +115,26 @@ CubeMap::CubeMap(const char* texturePseudoPath) {
|
||||
|
||||
}
|
||||
|
||||
CubeMap::CubeMap(int RESOLUTION)
|
||||
: textureWidth(RESOLUTION), textureHeight(RESOLUTION) {
|
||||
|
||||
glGenTextures(1, &textureId);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, textureId);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
|
||||
const int CUBEMAP_NUM_FACES = 6;
|
||||
for (unsigned int i = 0; i < CUBEMAP_NUM_FACES; i++)
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_DEPTH_COMPONENT, RESOLUTION, RESOLUTION, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
|
||||
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
|
||||
|
||||
}
|
||||
|
||||
CubeMap::~CubeMap() {
|
||||
glDeleteTextures(1, &textureId);
|
||||
}
|
||||
|
||||
@@ -44,11 +44,15 @@ class CubeMap {
|
||||
public:
|
||||
|
||||
CubeMap(const char* texturePseudoPath);
|
||||
CubeMap(int RESOLUTION);
|
||||
|
||||
~CubeMap();
|
||||
|
||||
void bind(ShaderProgram *shaderProgram);
|
||||
void unbind();
|
||||
|
||||
GLuint getTextureId() { return textureId; }
|
||||
|
||||
private:
|
||||
|
||||
void fillTexturePathVector(const char* texturePseudoPath);
|
||||
|
||||
@@ -42,6 +42,9 @@ Window::Window() {
|
||||
#endif
|
||||
setCatchedCursor(mouseCatched);
|
||||
|
||||
// Enable primitive gamma correction
|
||||
// glEnable(GL_FRAMEBUFFER_SRGB);
|
||||
|
||||
// Maximize in release build
|
||||
#ifndef _DEBUG
|
||||
glfwMaximizeWindow(window);
|
||||
|
||||
129
src/World.cpp
129
src/World.cpp
@@ -2,29 +2,40 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
// At this moment, I don't have any idea how to implement the initializer list
|
||||
// with an array of objects that don't have an default contructor. So the default
|
||||
// constructors for Light and PointLight have only this reason to exist.
|
||||
|
||||
World::World(ShaderProgram *shaderProgram)
|
||||
: shaderProgram(shaderProgram) {
|
||||
: shaderProgram(shaderProgram),
|
||||
directionalLight(shaderProgram),
|
||||
depthMapDirectionalFBO(DEPTHMAP_NORMAL, SHADOW_RES) {
|
||||
|
||||
// PointLights
|
||||
for(unsigned int i = 0; i < NUM_POINT_LIGHTS; i++) {
|
||||
pointLights[i].setId(i);
|
||||
pointLights[i].setShaderProgram(shaderProgram);
|
||||
PointLight new_pointLight(shaderProgram);
|
||||
new_pointLight.setId(i);
|
||||
pointLights.push_back(new_pointLight);
|
||||
}
|
||||
|
||||
// DirectionalLight
|
||||
directionalLight.setShaderProgram(shaderProgram);
|
||||
// Create 4 depthMaps
|
||||
for(int i = 0; i < 4; i++) {
|
||||
DepthMap *temp_depthMap = new DepthMap(DEPTHMAP_CUBEMAP, SHADOW_RES);
|
||||
depthMapPointFBO.push_back(temp_depthMap);
|
||||
}
|
||||
|
||||
// This will be removed in future when gloss maps are implemented
|
||||
shaderProgram->bind();
|
||||
shaderProgram->setUniform("u_material.shininess", 64.0f);
|
||||
shaderProgram->setUniform("u_material.shininess", 100.0f);
|
||||
shaderProgram->unbind();
|
||||
|
||||
}
|
||||
|
||||
World::~World() {
|
||||
|
||||
// Iterate over depthMapPointFBO vector and delete all items
|
||||
for(auto it = depthMapPointFBO.begin(); it != depthMapPointFBO.end(); it++) {
|
||||
delete (*it);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void World::addEntity(Entity entity) {
|
||||
uint32_t new_id = entities.size();
|
||||
entity.setId(new_id);
|
||||
@@ -57,8 +68,106 @@ void World::updateDirectionalLight(bool active, glm::vec3 direction, glm::vec3 c
|
||||
|
||||
void World::draw(glm::mat4 viewProjMatrix, glm::vec3 viewPosition) {
|
||||
|
||||
// Draw all entities
|
||||
for(auto it = entities.begin(); it != entities.end(); it++) {
|
||||
it->draw(viewProjMatrix, viewPosition);
|
||||
}
|
||||
|
||||
// Calculate shadows
|
||||
// calculateShadows();
|
||||
|
||||
}
|
||||
|
||||
void World::calculateShadows(ShaderProgram *directionalShaderProgram, ShaderProgram *pointShaderProgram) {
|
||||
|
||||
// Get old viewport dimensions to reset them later...
|
||||
GLint VIEWPORT[4];
|
||||
glGetIntegerv(GL_VIEWPORT, VIEWPORT);
|
||||
|
||||
glViewport(0, 0, SHADOW_RES, SHADOW_RES);
|
||||
// Switch face culling (Peter panning)
|
||||
glCullFace(GL_BACK);
|
||||
|
||||
depthMapDirectionalFBO.bind();
|
||||
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// --- Directional shadows ---
|
||||
glm::mat4 directionalLightView = glm::lookAt(-5.0f * glm::vec3(-0.2f, -1.0f, -0.3f), glm::vec3( 0.0f, 0.0f, 0.0f), glm::vec3( 0.0f, 1.0f, 0.0f));
|
||||
glm::mat4 directionalLightViewProjectionMatrix = directionalLightProjection * directionalLightView;
|
||||
|
||||
// Draw scene from light perspective
|
||||
// Draw all entities
|
||||
for(auto it = entities.begin(); it != entities.end(); it++) {
|
||||
it->drawDirectionalShadows(directionalLightViewProjectionMatrix, directionalShaderProgram);
|
||||
}
|
||||
|
||||
depthMapDirectionalFBO.unbind();
|
||||
|
||||
shaderProgram->bind();
|
||||
|
||||
// Send lightViewProjMatrix to basic shader
|
||||
shaderProgram->setUniform("u_directionalLightViewProjMatrix", directionalLightViewProjectionMatrix);
|
||||
|
||||
// Send shadowMap to basic shader
|
||||
int textureUnit = TEXTURE_TYPE_NUM_ITEMS * 2;
|
||||
shaderProgram->setUniform("u_texture_directionalShadowMap", (int)textureUnit);
|
||||
glActiveTexture(GL_TEXTURE0 + textureUnit);
|
||||
glBindTexture(GL_TEXTURE_2D, depthMapDirectionalFBO.getDepthMap());
|
||||
|
||||
shaderProgram->unbind();
|
||||
|
||||
|
||||
// --- Point shadows ---
|
||||
|
||||
// 4 depthMaps for 4 point lights
|
||||
for(int i = 0; i < 1; i++) {
|
||||
|
||||
depthMapPointFBO[i]->bind();
|
||||
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// Create 6 view matrices for every face of the cubeMap
|
||||
std::vector<glm::mat4> viewProjMatrices;
|
||||
glm::vec3 lightPos = pointLights[i].getPosition();
|
||||
viewProjMatrices.push_back(pointLightProjection * glm::lookAt(lightPos, lightPos + glm::vec3(1.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f)));
|
||||
viewProjMatrices.push_back(pointLightProjection * glm::lookAt(lightPos, lightPos + glm::vec3(-1.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f)));
|
||||
viewProjMatrices.push_back(pointLightProjection * glm::lookAt(lightPos, lightPos + glm::vec3(0.0f, 1.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)));
|
||||
viewProjMatrices.push_back(pointLightProjection * glm::lookAt(lightPos, lightPos + glm::vec3(0.0f, -1.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)));
|
||||
viewProjMatrices.push_back(pointLightProjection * glm::lookAt(lightPos, lightPos + glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3(0.0f, -1.0f, 0.0f)));
|
||||
viewProjMatrices.push_back(pointLightProjection * glm::lookAt(lightPos, lightPos + glm::vec3(0.0f, 0.0f, -1.0f), glm::vec3(0.0f, -1.0f, 0.0f)));
|
||||
|
||||
pointShaderProgram->bind();
|
||||
|
||||
for(int i = 0; i < 6; i++) {
|
||||
pointShaderProgram->setUniform(("u_shadowMatrices[" + std::to_string(i) + "]").c_str(), viewProjMatrices[i]);
|
||||
}
|
||||
|
||||
pointShaderProgram->setUniform("pointShadowDepthMapFarPlane", far);
|
||||
pointShaderProgram->setUniform("v_lightPos", lightPos);
|
||||
|
||||
// Draw scene from light perspective
|
||||
// Draw all entities
|
||||
for(auto it = entities.begin(); it != entities.end(); it++) {
|
||||
it->drawPointShadows(pointShaderProgram);
|
||||
}
|
||||
|
||||
depthMapPointFBO[i]->unbind();
|
||||
|
||||
shaderProgram->bind();
|
||||
|
||||
shaderProgram->setUniform("pointShadowDepthMapFarPlane", far);
|
||||
|
||||
textureUnit = TEXTURE_TYPE_NUM_ITEMS * 2 + i + 1;
|
||||
shaderProgram->setUniform("u_texture_pointShadowMap0", (int)textureUnit);
|
||||
glActiveTexture(GL_TEXTURE0 + textureUnit);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, depthMapPointFBO[i]->getCubeMapId());
|
||||
|
||||
shaderProgram->unbind();
|
||||
}
|
||||
|
||||
|
||||
// Reset viewport size
|
||||
glViewport(VIEWPORT[0], VIEWPORT[1], VIEWPORT[2], VIEWPORT[3]);
|
||||
glCullFace(GL_FRONT);
|
||||
}
|
||||
|
||||
20
src/World.h
20
src/World.h
@@ -5,13 +5,15 @@
|
||||
#include "Light.h"
|
||||
#include "Camera.h"
|
||||
#include "Entity.h"
|
||||
#include "ShaderProgram.h"
|
||||
#include "Framebuffer.h"
|
||||
|
||||
class World {
|
||||
|
||||
public:
|
||||
|
||||
World(ShaderProgram *shaderProgram);
|
||||
~World() = default;
|
||||
~World();
|
||||
|
||||
void addEntity(Entity entity);
|
||||
void removeEntity(uint32_t id);
|
||||
@@ -21,7 +23,10 @@ public:
|
||||
|
||||
std::vector<Entity> * getEntities() { return &entities; }
|
||||
|
||||
PointLight * getPointLights() { return pointLights.data(); }
|
||||
|
||||
void draw(glm::mat4 viewProjMatrix, glm::vec3 viewPosition);
|
||||
void calculateShadows(ShaderProgram *directionalShaderProgram, ShaderProgram *pointShaderProgram);
|
||||
|
||||
private:
|
||||
|
||||
@@ -29,8 +34,19 @@ private:
|
||||
|
||||
std::vector<Entity> entities;
|
||||
|
||||
// Lights
|
||||
DirectionalLight directionalLight;
|
||||
PointLight pointLights[NUM_POINT_LIGHTS];
|
||||
std::vector<PointLight> pointLights;
|
||||
//SpotLight spotLight;
|
||||
|
||||
// Shadows
|
||||
const int SHADOW_RES = 4096/4;
|
||||
DepthMap depthMapDirectionalFBO;
|
||||
std::vector<DepthMap*> depthMapPointFBO;
|
||||
// Shadow projection matrices
|
||||
float near_plane = 1.0f, far_plane = 15.0f;
|
||||
glm::mat4 directionalLightProjection = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, near_plane, far_plane);
|
||||
float aspect = 1.0f, near = 1.0f, far = 25.0f;
|
||||
glm::mat4 pointLightProjection = glm::perspective(glm::radians(90.0f), aspect, near, far);
|
||||
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user