Merge branch 'sRGB' into master

This commit is contained in:
2020-10-10 19:51:34 +02:00
32 changed files with 766 additions and 99 deletions

2
.gitignore vendored
View File

@@ -3,3 +3,5 @@ build
lib/assimp/libassimp.so.5.0.0
res/models
res/textures
.kdev4/Fall-Fever.kdev4
Fall-Fever.kdev4

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -0,0 +1,7 @@
#version 330 core
void main() {
// Empty as we aren't rendering to any color buffer
}

View 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);
}

View 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;
}

View 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();
}
}

View 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);
}

View 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);
}

View 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);
}

View File

@@ -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);
}

View File

@@ -14,4 +14,4 @@ void main() {
v_texCoord = a_position;
}
}

View File

@@ -12,6 +12,7 @@ add_executable(Fall-Fever
Entity.cpp
Light.cpp
World.cpp
Framebuffer.cpp
)
target_link_libraries(

View File

@@ -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;
};

View File

@@ -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)",

View File

@@ -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;
};

View File

@@ -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();

View File

@@ -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
View 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
View 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;
};

View File

@@ -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();

View File

@@ -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;
};

View File

@@ -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);

View File

@@ -13,6 +13,7 @@ public:
~Model();
void draw(ShaderProgram *shaderProgram);
void drawWithoutTextures();
Mesh * getMesh(unsigned int index) { return meshes[index]; }

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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);
};