Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added directional lights #2

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 20 additions & 4 deletions engine/include/rev/Light.h
Original file line number Diff line number Diff line change
@@ -1,21 +1,37 @@
#pragma once

#include <optional>

#include <glm/glm.hpp>

namespace rev {

class Light {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think having a shared base class here isn't really worth it, IMO. They only really share the one member and some getters, and the inheritance looks kind of like polymorphism even though they can't be polymorphic (no virtual functions). I they do share some properties and there may be a way to leverage that at some point, but let's not worry about that right now. After all, the fragment shaders they use are mostly copy/pasted anyway even though they share a lot of the same code.

public:
Light();
enum class Type
{
Directional,
Point
};

Light(Type type);

const glm::vec3& getBaseColor() const;
void setBaseColor(const glm::vec3& color);
void setBaseColor(const glm::vec3& baseColor);

const glm::vec3& getDirection() const;
void setDirection(const glm::vec3& direction);

const glm::vec3& getPosition() const;
void setPosition(const glm::vec3& position);

Type getType() const;

private:
glm::vec3 _baseColor;
glm::vec3 _position;
std::optional<glm::vec3> _position;
std::optional<glm::vec3> _direction;
Type _type;
};

} // namespace rev
} // namespace rev
9 changes: 6 additions & 3 deletions engine/include/rev/Scene.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,18 @@ class SceneObject;
class Scene
{
public:
std::shared_ptr<Light> addLight();
std::shared_ptr<Light> addPointLight();
std::shared_ptr<Light> addDirectionalLight();

void renderAllObjects(Camera &camera);
void renderAllLights(Uniform<glm::vec3>& lightPositionUniform, Uniform<glm::vec3>& lightBaseColor);
void renderAllPointLights(Uniform<glm::vec3>& lightPositionUniform, Uniform<glm::vec3>& lightBaseColor);
void renderAllDirectionalLights(Uniform<glm::vec3>& lightDirectionUniform, Uniform<glm::vec3>& lightBaseColor);

void addObjectGroup(std::shared_ptr<ISceneObjectGroup> group);
private:
std::vector<std::shared_ptr<ISceneObjectGroup>> _objectGroups;
std::set<std::shared_ptr<Light>> _lights;
std::set<std::shared_ptr<Light>> _pointLights;
std::set<std::shared_ptr<Light>> _directionalLights;
};

} // namespace rev
22 changes: 18 additions & 4 deletions engine/include/rev/SceneView.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ class SceneView
std::shared_ptr<Camera> _camera;

RectSize<GLsizei> _outputSize;
ProgramResource _lightingProgram;
ProgramResource _pointLightingProgram;
ProgramResource _directionalLightingProgram;

struct WorldSpaceNormalProperty
{
Expand Down Expand Up @@ -108,8 +109,21 @@ class SceneView
VertexArray _fullScreenVao;
Buffer _fullScreenVertexBuffer;

Uniform<glm::vec3> _lightPosition;
Uniform<glm::vec3> _lightBaseColor;
Uniform<glm::vec3> _camPosition;
struct DirectionalLightUniforms
{
Uniform<glm::vec3> lightDirection;
Uniform<glm::vec3> lightBaseColor;
Uniform<glm::vec3> camPosition;
};

struct PointLightUniforms
{
Uniform<glm::vec3> lightPosition;
Uniform<glm::vec3> lightBaseColor;
Uniform<glm::vec3> camPosition;
};

PointLightUniforms _pointLightUniforms;
DirectionalLightUniforms _directionalLightUniforms;
};
} // namespace rev
38 changes: 31 additions & 7 deletions engine/src/Light.cpp
Original file line number Diff line number Diff line change
@@ -1,30 +1,54 @@
#include "rev/Light.h"

using namespace std;
using namespace glm;

namespace rev
{
Light::Light()
: _baseColor(glm::vec3(1.0))
, _position(glm::vec3(0.0))
// Light
Light::Light(Type type)
: _baseColor(0.f), _type(type)
{
}

Light::Type Light::getType() const
{
return _type;
}

const glm::vec3& Light::getBaseColor() const
{
return _baseColor;
}

void Light::setBaseColor(const glm::vec3& color)
void Light::setBaseColor(const glm::vec3& baseColor)
{
_baseColor = color;
_baseColor = baseColor;
}

const glm::vec3& Light::getPosition() const
{
return _position;
assert(_position.has_value());
return *_position;
}

void Light::setPosition(const glm::vec3& position)
{
_position = position;
assert(_type == Type::Point);
_position = make_optional<glm::vec3>(position);
}

const glm::vec3& Light::getDirection() const
{
assert(_direction.has_value());
return *_direction;
}

void Light::setDirection(const glm::vec3& direction)
{
//TODO: Is there a way to ensure that the programmer is not
// calling these methods on the wrong type of light statically?
assert(_type == Type::Directional);
_direction = make_optional<glm::vec3>(direction);
}
}
29 changes: 24 additions & 5 deletions engine/src/Scene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,17 @@
namespace rev
{

std::shared_ptr<Light> Scene::addLight()
std::shared_ptr<Light> Scene::addPointLight()
{
auto light = std::make_shared<Light>();
_lights.insert(light);
auto light = std::make_shared<Light>(Light::Type::Point);
_pointLights.insert(light);
return std::move(light);
}

std::shared_ptr<Light> Scene::addDirectionalLight()
{
auto light = std::make_shared<Light>(Light::Type::Directional);
_directionalLights.insert(light);
return std::move(light);
}

Expand All @@ -26,10 +33,22 @@ void Scene::renderAllObjects(Camera &camera)
}
}

void Scene::renderAllLights(Uniform<glm::vec3> &lightPositionUniform,
void Scene::renderAllDirectionalLights(Uniform<glm::vec3> &lightDirectionUniform,
Uniform<glm::vec3> &lightBaseColor)
{
for (const auto & light : _directionalLights)
{
lightDirectionUniform.set(light->getDirection());
lightBaseColor.set(light->getBaseColor());

glDrawArrays(GL_TRIANGLES, 0, 6);
}
}

void Scene::renderAllPointLights(Uniform<glm::vec3> &lightPositionUniform,
Uniform<glm::vec3> &lightBaseColor)
{
for (const auto & light : _lights)
for (const auto & light : _pointLights)
{
lightPositionUniform.set(light->getPosition());
lightBaseColor.set(light->getBaseColor());
Expand Down
115 changes: 96 additions & 19 deletions engine/src/SceneView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,54 @@ constexpr const char *kDeferredVertexShader = R"vertexShader(

)vertexShader";

constexpr const char *kDeferredFragmentShader = R"fragmentShader(
constexpr const char *kDeferredDirectionalLightFragmentShader = R"fragmentShader(
#version 330 core

in vec2 texCoord;

uniform vec3 lightDirection;
uniform vec3 lightBaseColor;
uniform vec3 camPosition;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OMFG this uniform was never set before! I knew there was something weird about how the specular highlights were moving in relation to the camera.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually it was set above, nevermind.


uniform sampler2D fragPosition;
uniform sampler2D normals;

uniform sampler2D ambient;
uniform sampler2D emissive;
uniform sampler2D diffuse;
uniform sampler2D specular;
uniform sampler2D specularExponent;

out vec4 fragColor;
void main()
{
vec3 normal = texture(normals, texCoord).rgb;
vec3 diffuse = texture(diffuse, texCoord).rgb;

vec3 fragmentPosition = texture(fragPosition, texCoord).rgb;
vec3 lightVector = -1.0f * lightDirection;
float angleMultiplier = max(dot(normalize(lightVector), normalize(normal)), 0.0f);

float specularExponent = texture(specularExponent, texCoord).r;
vec3 specularCoefficient = texture(specular, texCoord).rgb;

vec3 eyeVector = normalize(camPosition - fragmentPosition);
vec3 reflectVector = normalize(reflect(lightVector, normalize(normal)));
float specularComponent = max(dot(eyeVector, reflectVector), 0.0f);

vec3 ambientLight = vec3(0.01f) * diffuse;
vec3 diffuseLight = diffuse * lightBaseColor * angleMultiplier;
vec3 specularLight = (specularExponent > 0.01)
? lightBaseColor * specularCoefficient * pow(vec3(specularComponent) , vec3(specularExponent))
: vec3(0.0f);

vec3 totalLight = diffuseLight + specularLight;

fragColor = vec4(totalLight, 1.0f);
}
)fragmentShader";

constexpr const char *kDeferredPointLightFragmentShader = R"fragmentShader(
#version 330 core

in vec2 texCoord;
Expand Down Expand Up @@ -87,22 +134,42 @@ constexpr glm::vec2 kFullScreenQuadVertices[] = {

SceneView::SceneView() : _camera(std::make_shared<Camera>())
{
_lightingProgram.buildWithSource(kDeferredVertexShader,
kDeferredFragmentShader);
_pointLightingProgram.buildWithSource(kDeferredVertexShader,
kDeferredPointLightFragmentShader);
{
ProgramContext programContext(_lightingProgram);
_lightPosition = _lightingProgram.getUniform<glm::vec3>("lightPosition");
_lightBaseColor = _lightingProgram.getUniform<glm::vec3>("lightBaseColor");
_camPosition = _lightingProgram.getUniform<glm::vec3>("camPosition");

_lightingProgram.getUniform<GLint>("fragPosition").set(0);
_lightingProgram.getUniform<GLint>("normals").set(1);

_lightingProgram.getUniform<GLint>("ambient").set(2);
_lightingProgram.getUniform<GLint>("emissive").set(3);
_lightingProgram.getUniform<GLint>("diffuse").set(4);
_lightingProgram.getUniform<GLint>("specular").set(5);
_lightingProgram.getUniform<GLint>("specularExponent").set(6);
ProgramContext programContext(_pointLightingProgram);

_pointLightUniforms.lightPosition = _pointLightingProgram.getUniform<glm::vec3>("lightPosition");
_pointLightUniforms.lightBaseColor = _pointLightingProgram.getUniform<glm::vec3>("lightBaseColor");
_pointLightUniforms.camPosition = _pointLightingProgram.getUniform<glm::vec3>("camPosition");

_pointLightingProgram.getUniform<GLint>("fragPosition").set(0);
_pointLightingProgram.getUniform<GLint>("normals").set(1);

_pointLightingProgram.getUniform<GLint>("ambient").set(2);
_pointLightingProgram.getUniform<GLint>("emissive").set(3);
_pointLightingProgram.getUniform<GLint>("diffuse").set(4);
_pointLightingProgram.getUniform<GLint>("specular").set(5);
_pointLightingProgram.getUniform<GLint>("specularExponent").set(6);
}

_directionalLightingProgram.buildWithSource(kDeferredVertexShader,
kDeferredDirectionalLightFragmentShader);
{
ProgramContext programContext(_directionalLightingProgram);

_directionalLightUniforms.lightDirection = _directionalLightingProgram.getUniform<glm::vec3>("lightDirection");
_directionalLightUniforms.lightBaseColor = _directionalLightingProgram.getUniform<glm::vec3>("lightBaseColor");
_directionalLightUniforms.camPosition = _directionalLightingProgram.getUniform<glm::vec3>("camPosition");

_directionalLightingProgram.getUniform<GLint>("fragPosition").set(0);
_directionalLightingProgram.getUniform<GLint>("normals").set(1);

_directionalLightingProgram.getUniform<GLint>("ambient").set(2);
_directionalLightingProgram.getUniform<GLint>("emissive").set(3);
_directionalLightingProgram.getUniform<GLint>("diffuse").set(4);
_directionalLightingProgram.getUniform<GLint>("specular").set(5);
_directionalLightingProgram.getUniform<GLint>("specularExponent").set(6);
}

VertexArrayContext vaoContext(_fullScreenVao);
Expand Down Expand Up @@ -162,10 +229,8 @@ void SceneView::render()

// Lighting pass
{
ProgramContext programContext(_lightingProgram);
auto fbContext = _lightingStage.getRenderContext();

_camPosition.set(_camera->getPosition());
glViewport(0, 0, _outputSize.width, _outputSize.height);

glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
Expand All @@ -192,7 +257,19 @@ void SceneView::render()

VertexArrayContext vaoContext(_fullScreenVao);

_scene->renderAllLights(_lightPosition, _lightBaseColor);
// Render all point lights
{
ProgramContext programContext(_pointLightingProgram);
_pointLightUniforms.camPosition.set(_camera->getPosition());
_scene->renderAllPointLights(_pointLightUniforms.lightPosition, _pointLightUniforms.lightBaseColor);
}

// Render all directional lights
{
ProgramContext programContext(_directionalLightingProgram);
_directionalLightUniforms.camPosition.set(_camera->getPosition());
_scene->renderAllDirectionalLights(_directionalLightUniforms.lightDirection, _directionalLightUniforms.lightBaseColor);
}
}
}

Expand Down
10 changes: 7 additions & 3 deletions testGame/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -339,18 +339,22 @@ int main(void)

auto bikeController = std::make_shared<BikeController>(bikeParticle, object);

auto yellowLight = scene->addLight();
auto yellowLight = scene->addPointLight();
yellowLight->setPosition(glm::vec3(4.0f, 3.0f, 3.0f));
yellowLight->setBaseColor(glm::vec3(1.0f, 1.0f, 0.8f));

auto blueLight = scene->addLight();
auto blueLight = scene->addPointLight();
blueLight->setPosition(glm::vec3(-1.5f, -2.0f, 1.5f));
blueLight->setBaseColor(glm::vec3(0.2f, 0.2f, 1.0f));

auto orangeLight = scene->addLight();
auto orangeLight = scene->addPointLight();
orangeLight->setPosition(glm::vec3(3.0f, 0.75f, -2.5f));
orangeLight->setBaseColor(glm::vec3(1.0f, 0.3f, 0.0f));

auto directionalLight = scene->addDirectionalLight();
directionalLight->setDirection(glm::vec3(-1.0, 0.0f, 0.0f));
directionalLight->setBaseColor(glm::vec3(1.0f, 1.0f, 1.0f));

auto camera = sceneView->getCamera();
camera->setTarget({0.0f, 0.0f, 0.0f});
camera->setPosition({4.0f, 4.0f, 4.0f});
Expand Down