Skip to content

Commit

Permalink
Merge pull request #181 from ucsd-cse125-sp24/fix/lighting
Browse files Browse the repository at this point in the history
lighting improvements
  • Loading branch information
Tyler-Lentz authored Jun 3, 2024
2 parents 7cf0a4b + 7abc6ce commit 57f7874
Show file tree
Hide file tree
Showing 6 changed files with 240 additions and 47 deletions.
1 change: 1 addition & 0 deletions include/client/client.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ class Client {
/* Shader objects for various */
std::shared_ptr<Shader> deferred_geometry_shader;
std::shared_ptr<Shader> deferred_lighting_shader;
std::shared_ptr<Shader> dm_deferred_lighting_shader;
std::shared_ptr<Shader> deferred_light_box_shader;

/* Character models and lighting objects, might need to move to different classes later */
Expand Down
17 changes: 17 additions & 0 deletions include/shared/game/dir_light.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#pragma once

#include <glm/glm.hpp>

/**
* @brief DirLight holds lighting information
* for directional light source. Note that this
* is different than point lights which emit from
* a certain point.
*/
struct DirLight {
glm::vec3 direction;

glm::vec3 ambient_color;
glm::vec3 diffuse_color;
glm::vec3 specular_color;
};
87 changes: 69 additions & 18 deletions src/client/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <boost/archive/text_iarchive.hpp>

#include <iostream>
#include <string>
#include <thread>
#include <sstream>

Expand All @@ -24,6 +25,7 @@
#include "glm/fwd.hpp"
#include "server/game/object.hpp"
#include "server/game/solidsurface.hpp"
#include "shared/game/dir_light.hpp"
#include "shared/game/event.hpp"
#include "shared/game/sharedobject.hpp"
#include "shared/network/constants.hpp"
Expand Down Expand Up @@ -188,7 +190,9 @@ bool Client::init() {

auto deferred_lighting_vert_path = shaders_dir / "deferred_lighting.vert";
auto deferred_lighting_frag_path = shaders_dir / "deferred_lighting.frag";
auto dm_deferred_lighting_frag_path = shaders_dir / "dm_deferred_lighting.frag";
this->deferred_lighting_shader = std::make_shared<Shader>(deferred_lighting_vert_path.string(), deferred_lighting_frag_path.string());
this->dm_deferred_lighting_shader = std::make_shared<Shader>(deferred_lighting_vert_path.string(), dm_deferred_lighting_frag_path.string());

auto deferred_light_box_vert_path = shaders_dir / "deferred_light_box.vert";
auto deferred_light_box_frag_path = shaders_dir / "deferred_light_box.frag";
Expand Down Expand Up @@ -569,6 +573,11 @@ void Client::configureGBuffer() {
this->deferred_lighting_shader->setInt("gPosition", 0);
this->deferred_lighting_shader->setInt("gNormal", 1);
this->deferred_lighting_shader->setInt("gAlbedoSpec", 2);

this->dm_deferred_lighting_shader->use();
this->dm_deferred_lighting_shader->setInt("gPosition", 0);
this->dm_deferred_lighting_shader->setInt("gNormal", 1);
this->dm_deferred_lighting_shader->setInt("gAlbedoSpec", 2);
}

void Client::draw() {
Expand Down Expand Up @@ -930,6 +939,11 @@ void Client::geometryPass() {
}*/
break;
}
// case ObjectType::Torchlight: {
// this->torchlight_model->setDimensions(2.0f * sharedObject->physics.dimensions);
// this->torchlight_model->translateAbsolute(sharedObject->physics.getCenterPosition());
// this->torchlight_model->draw(this->deferred_geometry_shader.get(), this->cam->getPos(), true);
// }
default:
break;
}
Expand All @@ -947,9 +961,35 @@ void Client::lightingPass() {
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, gAlbedoSpec);

this->deferred_lighting_shader->use();
bool is_dm = this->session->getInfo().is_dungeon_master.value();
auto eid = this->session->getInfo().client_eid.value();
glm::vec3 my_pos = this->gameState.objects[eid]->physics.corner;

std::shared_ptr<Shader> lighting_shader = is_dm ? dm_deferred_lighting_shader: deferred_lighting_shader;

lighting_shader->use();
auto camPos = this->cam->getPos();
this->deferred_lighting_shader->setVec3("viewPos", camPos);
lighting_shader->setVec3("viewPos", camPos);

if (is_dm) {
auto ambient = glm::vec3(0.1, 0.1, 0.1);
auto diffuse = glm::vec3(0.1, 0.1, 0.1);
auto specular = glm::vec3(0.1, 0.1, 0.1);
std::array<DirLight, 4> dirLights = {
DirLight{glm::vec3(1.0f, 0.0f, 0.0f), ambient, diffuse, specular},
DirLight{glm::vec3(-1.0f, 1.0f, 0.0f), ambient, diffuse, specular},
DirLight{glm::vec3(0.0f, 1.0f, 1.0f), ambient, diffuse, specular},
DirLight{glm::vec3(0.0f, 1.0f, -1.0f), ambient, diffuse, specular},
};

for (int i = 0; i < dirLights.size(); i++) {
std::string i_s = std::to_string(i);
lighting_shader->setVec3("dirLights[" + i_s + "].direction", dirLights[i].direction);
lighting_shader->setVec3("dirLights[" + i_s + "].ambient_color", ambient);
lighting_shader->setVec3("dirLights[" + i_s + "].diffuse_color", diffuse);
lighting_shader->setVec3("dirLights[" + i_s + "].specular_color", specular);
}
}
for (int i = 0; i < this->closest_light_sources.size(); i++) {
boost::optional<SharedObject>& curr_source = this->closest_light_sources.at(i);
if (!curr_source.has_value()) {
Expand All @@ -959,11 +999,16 @@ void Client::lightingPass() {

glm::vec3 pos = curr_source->physics.getCenterPosition();

this->deferred_lighting_shader->setVec3("lights[" + std::to_string(i) + "].Position", pos);
this->deferred_lighting_shader->setVec3("lights[" + std::to_string(i) + "].Color", properties.diffuse_color);
// update attenuation parameters and calculate radius
this->deferred_lighting_shader->setFloat("lights[" + std::to_string(i) + "].Linear", properties.attenuation_linear);
this->deferred_lighting_shader->setFloat("lights[" + std::to_string(i) + "].Quadratic", properties.attenuation_quadratic);

lighting_shader->setFloat("pointLights[" + std::to_string(i) + "].intensity", properties.intensity);
lighting_shader->setVec3("pointLights[" + std::to_string(i) + "].position", pos);

lighting_shader->setVec3("pointLights[" + std::to_string(i) + "].ambient_color", properties.ambient_color);
lighting_shader->setVec3("pointLights[" + std::to_string(i) + "].diffuse_color", properties.diffuse_color);
lighting_shader->setVec3("pointLights[" + std::to_string(i) + "].specular_color", properties.specular_color);

lighting_shader->setFloat("pointLights[" + std::to_string(i) + "].attn_linear", properties.attenuation_linear);
lighting_shader->setFloat("pointLights[" + std::to_string(i) + "].attn_quadratic", properties.attenuation_quadratic);
}

if (quadVAO == 0) {
Expand All @@ -989,8 +1034,7 @@ void Client::lightingPass() {
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);

// 2.5. copy content of geometry's depth buffer to default framebuffer's depth buffer
// ----------------------------------------------------------------------------------
// copy content of geometry's depth buffer to default framebuffer's depth buffer
glBindFramebuffer(GL_READ_FRAMEBUFFER, gBuffer);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); // write to default framebuffer
// blit to default framebuffer. Note that this may or may not work as the internal formats of both the FBO and default framebuffer have to match.
Expand All @@ -1000,27 +1044,34 @@ void Client::lightingPass() {
glBindFramebuffer(GL_FRAMEBUFFER, 0);


// 3. render lights on top of scene
// --------------------------------
// render torch lights on top of scene
this->deferred_light_box_shader->use();
glm::mat4 viewProj = this->cam->getViewProj();
this->deferred_light_box_shader->setMat4("viewProj", viewProj);
for (int i = 0; i < this->closest_light_sources.size(); i++) {
boost::optional<SharedObject>& curr_source = this->closest_light_sources.at(i);
if (!curr_source.has_value()) {
for (auto& [id, sharedObject] : this->gameState.objects) {
if (!sharedObject.has_value()) {
continue;
}

if (!curr_source->pointLightInfo.has_value()) {
if (sharedObject->type != ObjectType::Torchlight) {
continue;
}

auto dist = glm::distance(sharedObject->physics.corner, my_pos);
if (!is_dm && dist > RENDER_DISTANCE) {
continue;
}

if (!sharedObject->pointLightInfo.has_value()) {
std::cout << "got a torch without point light info for some reason" << std::endl;
continue;
}
SharedPointLightInfo& properties = curr_source->pointLightInfo.value();
SharedPointLightInfo& properties = sharedObject->pointLightInfo.value();

this->deferred_light_box_shader->use();
this->deferred_light_box_shader->setVec3("lightColor", properties.diffuse_color);
this->torchlight_model->setDimensions(2.0f * curr_source->physics.dimensions);
this->torchlight_model->translateAbsolute(curr_source->physics.getCenterPosition());
this->torchlight_model->setDimensions(2.0f * sharedObject->physics.dimensions);
this->torchlight_model->translateAbsolute(sharedObject->physics.getCenterPosition());
this->torchlight_model->draw(this->deferred_light_box_shader.get(), this->cam->getPos(), true);
}

Expand Down
76 changes: 49 additions & 27 deletions src/client/shaders/deferred_lighting.frag
Original file line number Diff line number Diff line change
Expand Up @@ -9,45 +9,67 @@ uniform sampler2D gPosition;
uniform sampler2D gNormal;
uniform sampler2D gAlbedoSpec;

struct Light {
vec3 Position;
vec3 Color;
struct PointLight {
// from 0-1
float intensity;

vec3 position;

vec3 ambient_color;
vec3 diffuse_color;
vec3 specular_color;

float Linear;
float Quadratic;
float attn_linear;
float attn_quadratic;
};
const int NR_LIGHTS = 32;
uniform Light lights[NR_LIGHTS];

#define NR_POINT_LIGHTS 32
uniform PointLight pointLights[NR_POINT_LIGHTS];

uniform vec3 viewPos;

void main()
{
vec3 CalcPointLight(in PointLight light, in vec3 fragPos, in vec3 normal, in vec3 viewDir,
vec3 mat_diffuse, float mat_shininess) {

vec3 lightDir = normalize(light.position - fragPos);
vec3 halfwayDir = normalize(lightDir + viewDir);
float diff = max(dot(normal, lightDir), 0.0);

vec3 ambient = light.ambient_color * mat_diffuse;
vec3 diffuse = light.diffuse_color * diff * mat_diffuse;
float spec = pow(max(dot(normal, halfwayDir), 0.0), 16.0);
vec3 specular = light.specular_color * spec * mat_shininess;

// attenuation
float distance = length(light.position - fragPos);
float attenuation = 1.0 / (1.0 + light.attn_linear * distance +
light.attn_quadratic * (distance * distance));
ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;
return (ambient + diffuse + specular) * light.intensity;
}

void main() {
// retrieve data from gbuffer
vec3 FragPos = texture(gPosition, TexCoords).rgb;
vec3 Normal = texture(gNormal, TexCoords).rgb;
vec3 Normal = normalize(texture(gNormal, TexCoords).rgb);
vec3 Diffuse = texture(gAlbedoSpec, TexCoords).rgb;
float Specular = texture(gAlbedoSpec, TexCoords).a;

// then calculate lighting as usual
vec3 lighting = Diffuse * 0.1; // hard-coded ambient component
vec3 viewDir = normalize(viewPos - FragPos);
for(int i = 0; i < NR_LIGHTS; ++i)
{
// diffuse
vec3 lightDir = normalize(lights[i].Position - FragPos);
vec3 diffuse = max(dot(Normal, lightDir), 0.0) * Diffuse * lights[i].Color;
// specular
vec3 halfwayDir = normalize(lightDir + viewDir);
float spec = pow(max(dot(Normal, halfwayDir), 0.0), 16.0);
vec3 specular = lights[i].Color * spec * Specular;
// attenuation
float distance = length(lights[i].Position - FragPos);
float attenuation = 1.0 / (1.0 + lights[i].Linear * distance + lights[i].Quadratic * distance * distance);
diffuse *= attenuation;
specular *= attenuation;
lighting += diffuse + specular;
vec3 result = vec3(0.0, 0.0, 0.0);
for(int i = 0; i < NR_POINT_LIGHTS; ++i) {
result += CalcPointLight(
pointLights[i],
FragPos,
Normal,
viewDir,
Diffuse,
Specular);
}
FragColor = vec4(lighting, 1.0);
FragColor = vec4(result, 1.0);
}


102 changes: 102 additions & 0 deletions src/client/shaders/dm_deferred_lighting.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#version 330 core
out vec4 FragColor;

in vec2 TexCoords;

uniform sampler2D gPosition;
uniform sampler2D gNormal;
uniform sampler2D gAlbedoSpec;

struct DirLight {
vec3 direction;

vec3 ambient_color;
vec3 diffuse_color;
vec3 specular_color;
};

struct PointLight {
// from 0-1
float intensity;

vec3 position;

vec3 ambient_color;
vec3 diffuse_color;
vec3 specular_color;

float attn_linear;
float attn_quadratic;
};

#define NR_DIR_LIGHTS 4
uniform DirLight dirLights[NR_DIR_LIGHTS];

#define NR_POINT_LIGHTS 32
uniform PointLight pointLights[NR_POINT_LIGHTS];

uniform vec3 viewPos;

vec3 CalcPointLight(in PointLight light, in vec3 fragPos, in vec3 normal, in vec3 viewDir,
vec3 mat_diffuse, float mat_shininess) {

vec3 lightDir = normalize(light.position - fragPos);
vec3 halfwayDir = normalize(lightDir + viewDir);
float diff = max(dot(normal, lightDir), 0.0);

// vec3 ambient = light.ambient_color * mat_diffuse;
vec3 diffuse = light.diffuse_color * diff * mat_diffuse;
float spec = pow(max(dot(normal, halfwayDir), 0.0), 16.0);
vec3 specular = light.specular_color * spec * mat_shininess;

// attenuation
float distance = length(light.position - fragPos);
float attenuation = 1.0 / (1.0 + light.attn_linear * distance +
light.attn_quadratic * (distance * distance));
// ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;
return (diffuse + specular);
}

vec3 CalcDirLight(in DirLight light, in vec3 normal, in vec3 viewDir,
in vec3 mat_diffuse, in float mat_shininess) {
vec3 lightDir = normalize(-light.direction);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), 16.0);
// combine results
vec3 ambient = light.ambient_color * mat_diffuse;
vec3 diffuse = light.diffuse_color * diff * mat_diffuse;
vec3 specular = light.specular_color * spec * mat_shininess;
return (ambient + diffuse + specular);
}

void main() {
// retrieve data from gbuffer
vec3 FragPos = texture(gPosition, TexCoords).rgb;
vec3 Normal = normalize(texture(gNormal, TexCoords).rgb);
vec3 Diffuse = texture(gAlbedoSpec, TexCoords).rgb;
float Specular = texture(gAlbedoSpec, TexCoords).a;

// then calculate lighting as usual
vec3 viewDir = normalize(viewPos - FragPos);
vec3 result = vec3(0.0, 0.0, 0.0);
for(int i = 0; i < NR_DIR_LIGHTS; ++i) {
result += CalcDirLight(dirLights[i], Normal, viewDir, Diffuse, Specular);
}
for(int i = 0; i < NR_POINT_LIGHTS; ++i) {
result += CalcPointLight(
pointLights[i],
FragPos,
Normal,
viewDir,
Diffuse,
Specular);
}
FragColor = vec4(result, 1.0);
}


Loading

0 comments on commit 57f7874

Please sign in to comment.