From a4e429c837615d44d38e9c00171cdf39a8d58247 Mon Sep 17 00:00:00 2001 From: Benjamin Luke Date: Sat, 26 Jan 2019 17:33:54 -0800 Subject: [PATCH 1/3] Added directional lights --- engine/include/rev/Light.h | 25 +++++++- engine/include/rev/Scene.h | 12 ++-- engine/include/rev/SceneView.h | 4 +- engine/src/Light.cpp | 28 ++++++++- engine/src/Scene.cpp | 29 +++++++-- engine/src/SceneView.cpp | 108 +++++++++++++++++++++++++++------ testGame/src/main.cpp | 10 ++- 7 files changed, 179 insertions(+), 37 deletions(-) diff --git a/engine/include/rev/Light.h b/engine/include/rev/Light.h index 79e4e55..3458f16 100644 --- a/engine/include/rev/Light.h +++ b/engine/include/rev/Light.h @@ -5,17 +5,36 @@ namespace rev { class Light { -public: +protected: Light(); - +public: const glm::vec3& getBaseColor() const; void setBaseColor(const glm::vec3& color); + const glm::mat4x4& getLightSpaceTransform() const; + void setLightSpaceTransform(const glm::mat4x4& transform); +private: + glm::vec3 _baseColor; +}; + +class PointLight: public Light { +public: + PointLight(); + const glm::vec3& getPosition() const; void setPosition(const glm::vec3& position); private: - glm::vec3 _baseColor; glm::vec3 _position; }; +class DirectionalLight: public Light { +public: + DirectionalLight(); + + const glm::vec3& getDirection() const; + void setDirection(const glm::vec3& direction); +private: + glm::vec3 _direction; +}; + } // namespace rev \ No newline at end of file diff --git a/engine/include/rev/Scene.h b/engine/include/rev/Scene.h index 2d2a747..7ea4ac4 100644 --- a/engine/include/rev/Scene.h +++ b/engine/include/rev/Scene.h @@ -11,22 +11,26 @@ namespace rev { -class Light; +class PointLight; +class DirectionalLight; class IModel; class SceneObject; class Scene { public: - std::shared_ptr addLight(); + std::shared_ptr addPointLight(); + std::shared_ptr addDirectionalLight(); void renderAllObjects(Camera &camera); - void renderAllLights(Uniform& lightPositionUniform, Uniform& lightBaseColor); + void renderAllPointLights(Uniform& lightPositionUniform, Uniform& lightBaseColor); + void renderAllDirectionalLights(Uniform& lightDirectionUniform, Uniform& lightBaseColor); void addObjectGroup(std::shared_ptr group); private: std::vector> _objectGroups; - std::set> _lights; + std::set> _pointLights; + std::set> _directionalLights; }; } // namespace rev \ No newline at end of file diff --git a/engine/include/rev/SceneView.h b/engine/include/rev/SceneView.h index 83e94de..c10eba8 100644 --- a/engine/include/rev/SceneView.h +++ b/engine/include/rev/SceneView.h @@ -35,7 +35,8 @@ class SceneView std::shared_ptr _camera; RectSize _outputSize; - ProgramResource _lightingProgram; + ProgramResource _pointLightingProgram; + ProgramResource _directionalLightingProgram; struct WorldSpaceNormalProperty { @@ -109,6 +110,7 @@ class SceneView Buffer _fullScreenVertexBuffer; Uniform _lightPosition; + Uniform _lightDirection; Uniform _lightBaseColor; Uniform _camPosition; }; diff --git a/engine/src/Light.cpp b/engine/src/Light.cpp index e8b804e..d53dc22 100644 --- a/engine/src/Light.cpp +++ b/engine/src/Light.cpp @@ -2,9 +2,9 @@ namespace rev { + // Light Light::Light() : _baseColor(glm::vec3(1.0)) - , _position(glm::vec3(0.0)) { } @@ -18,13 +18,35 @@ namespace rev _baseColor = color; } - const glm::vec3& Light::getPosition() const + // PointLight + PointLight::PointLight() + : _position(glm::vec3(0.0)) + { + } + + const glm::vec3& PointLight::getPosition() const { return _position; } - void Light::setPosition(const glm::vec3& position) + void PointLight::setPosition(const glm::vec3& position) { _position = position; } + + // DirectionalLight + DirectionalLight::DirectionalLight() + : _direction(glm::vec3(0.0, -1.0, 0.0)) + { + } + + const glm::vec3& DirectionalLight::getDirection() const + { + return _direction; + } + + void DirectionalLight::setDirection(const glm::vec3& direction) + { + _direction = direction; + } } diff --git a/engine/src/Scene.cpp b/engine/src/Scene.cpp index eebfac3..9016880 100644 --- a/engine/src/Scene.cpp +++ b/engine/src/Scene.cpp @@ -6,10 +6,17 @@ namespace rev { -std::shared_ptr Scene::addLight() +std::shared_ptr Scene::addPointLight() { - auto light = std::make_shared(); - _lights.insert(light); + auto light = std::make_shared(); + _pointLights.insert(light); + return std::move(light); +} + +std::shared_ptr Scene::addDirectionalLight() +{ + auto light = std::make_shared(); + _directionalLights.insert(light); return std::move(light); } @@ -26,10 +33,22 @@ void Scene::renderAllObjects(Camera &camera) } } -void Scene::renderAllLights(Uniform &lightPositionUniform, +void Scene::renderAllDirectionalLights(Uniform &lightDirectionUniform, + Uniform &lightBaseColor) +{ + for (const auto & light : _directionalLights) + { + lightDirectionUniform.set(light->getDirection()); + lightBaseColor.set(light->getBaseColor()); + + glDrawArrays(GL_TRIANGLES, 0, 6); + } +} + +void Scene::renderAllPointLights(Uniform &lightPositionUniform, Uniform &lightBaseColor) { - for (const auto & light : _lights) + for (const auto & light : _pointLights) { lightPositionUniform.set(light->getPosition()); lightBaseColor.set(light->getBaseColor()); diff --git a/engine/src/SceneView.cpp b/engine/src/SceneView.cpp index 127bc3b..467f170 100644 --- a/engine/src/SceneView.cpp +++ b/engine/src/SceneView.cpp @@ -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; + + 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; @@ -87,22 +134,32 @@ constexpr glm::vec2 kFullScreenQuadVertices[] = { SceneView::SceneView() : _camera(std::make_shared()) { - _lightingProgram.buildWithSource(kDeferredVertexShader, - kDeferredFragmentShader); + _pointLightingProgram.buildWithSource(kDeferredVertexShader, + kDeferredPointLightFragmentShader); + { + ProgramContext programContext(_pointLightingProgram); + _pointLightingProgram.getUniform("fragPosition").set(0); + _pointLightingProgram.getUniform("normals").set(1); + + _pointLightingProgram.getUniform("ambient").set(2); + _pointLightingProgram.getUniform("emissive").set(3); + _pointLightingProgram.getUniform("diffuse").set(4); + _pointLightingProgram.getUniform("specular").set(5); + _pointLightingProgram.getUniform("specularExponent").set(6); + } + + _directionalLightingProgram.buildWithSource(kDeferredVertexShader, + kDeferredDirectionalLightFragmentShader); { - ProgramContext programContext(_lightingProgram); - _lightPosition = _lightingProgram.getUniform("lightPosition"); - _lightBaseColor = _lightingProgram.getUniform("lightBaseColor"); - _camPosition = _lightingProgram.getUniform("camPosition"); - - _lightingProgram.getUniform("fragPosition").set(0); - _lightingProgram.getUniform("normals").set(1); - - _lightingProgram.getUniform("ambient").set(2); - _lightingProgram.getUniform("emissive").set(3); - _lightingProgram.getUniform("diffuse").set(4); - _lightingProgram.getUniform("specular").set(5); - _lightingProgram.getUniform("specularExponent").set(6); + ProgramContext programContext(_directionalLightingProgram); + _directionalLightingProgram.getUniform("fragPosition").set(0); + _directionalLightingProgram.getUniform("normals").set(1); + + _directionalLightingProgram.getUniform("ambient").set(2); + _directionalLightingProgram.getUniform("emissive").set(3); + _directionalLightingProgram.getUniform("diffuse").set(4); + _directionalLightingProgram.getUniform("specular").set(5); + _directionalLightingProgram.getUniform("specularExponent").set(6); } VertexArrayContext vaoContext(_fullScreenVao); @@ -162,7 +219,6 @@ void SceneView::render() // Lighting pass { - ProgramContext programContext(_lightingProgram); auto fbContext = _lightingStage.getRenderContext(); _camPosition.set(_camera->getPosition()); @@ -192,7 +248,23 @@ void SceneView::render() VertexArrayContext vaoContext(_fullScreenVao); - _scene->renderAllLights(_lightPosition, _lightBaseColor); + // Render all point lights + { + ProgramContext programContext(_pointLightingProgram); + _lightPosition = _pointLightingProgram.getUniform("lightPosition"); + _lightBaseColor = _pointLightingProgram.getUniform("lightBaseColor"); + _camPosition = _pointLightingProgram.getUniform("camPosition"); + _scene->renderAllPointLights(_lightPosition, _lightBaseColor); + } + + // Render all directional lights + { + ProgramContext programContext(_directionalLightingProgram); + _lightDirection = _directionalLightingProgram.getUniform("lightDirection"); + _lightBaseColor = _directionalLightingProgram.getUniform("lightBaseColor"); + _camPosition = _directionalLightingProgram.getUniform("camPosition"); + _scene->renderAllDirectionalLights(_lightDirection, _lightBaseColor); + } } } diff --git a/testGame/src/main.cpp b/testGame/src/main.cpp index 1740374..edad1fc 100644 --- a/testGame/src/main.cpp +++ b/testGame/src/main.cpp @@ -339,18 +339,22 @@ int main(void) auto bikeController = std::make_shared(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}); From 19c4d3bf86369fa181d3a8aea1daa7898da2ccb6 Mon Sep 17 00:00:00 2001 From: Benjamin Luke Date: Sun, 27 Jan 2019 14:04:51 -0800 Subject: [PATCH 2/3] First pass at PR comments --- engine/include/rev/Light.h | 3 --- engine/include/rev/SceneView.h | 20 ++++++++++++++++---- engine/src/SceneView.cpp | 23 ++++++++++++++--------- 3 files changed, 30 insertions(+), 16 deletions(-) diff --git a/engine/include/rev/Light.h b/engine/include/rev/Light.h index 3458f16..ce42fd2 100644 --- a/engine/include/rev/Light.h +++ b/engine/include/rev/Light.h @@ -10,9 +10,6 @@ class Light { public: const glm::vec3& getBaseColor() const; void setBaseColor(const glm::vec3& color); - - const glm::mat4x4& getLightSpaceTransform() const; - void setLightSpaceTransform(const glm::mat4x4& transform); private: glm::vec3 _baseColor; }; diff --git a/engine/include/rev/SceneView.h b/engine/include/rev/SceneView.h index c10eba8..e0fa9ba 100644 --- a/engine/include/rev/SceneView.h +++ b/engine/include/rev/SceneView.h @@ -109,9 +109,21 @@ class SceneView VertexArray _fullScreenVao; Buffer _fullScreenVertexBuffer; - Uniform _lightPosition; - Uniform _lightDirection; - Uniform _lightBaseColor; - Uniform _camPosition; + struct DirectionalLightUniforms + { + Uniform lightDirection; + Uniform lightBaseColor; + Uniform camPosition; + }; + + struct PointLightUniforms + { + Uniform lightPosition; + Uniform lightBaseColor; + Uniform camPosition; + }; + + PointLightUniforms _pointLightUniforms; + DirectionalLightUniforms _directionalLightUniforms; }; } // namespace rev \ No newline at end of file diff --git a/engine/src/SceneView.cpp b/engine/src/SceneView.cpp index 467f170..938c039 100644 --- a/engine/src/SceneView.cpp +++ b/engine/src/SceneView.cpp @@ -138,6 +138,11 @@ SceneView::SceneView() : _camera(std::make_shared()) kDeferredPointLightFragmentShader); { ProgramContext programContext(_pointLightingProgram); + + _pointLightUniforms.lightPosition = _pointLightingProgram.getUniform("lightPosition"); + _pointLightUniforms.lightBaseColor = _pointLightingProgram.getUniform("lightBaseColor"); + _pointLightUniforms.camPosition = _pointLightingProgram.getUniform("camPosition"); + _pointLightingProgram.getUniform("fragPosition").set(0); _pointLightingProgram.getUniform("normals").set(1); @@ -152,6 +157,11 @@ SceneView::SceneView() : _camera(std::make_shared()) kDeferredDirectionalLightFragmentShader); { ProgramContext programContext(_directionalLightingProgram); + + _directionalLightUniforms.lightDirection = _directionalLightingProgram.getUniform("lightDirection"); + _directionalLightUniforms.lightBaseColor = _directionalLightingProgram.getUniform("lightBaseColor"); + _directionalLightUniforms.camPosition = _directionalLightingProgram.getUniform("camPosition"); + _directionalLightingProgram.getUniform("fragPosition").set(0); _directionalLightingProgram.getUniform("normals").set(1); @@ -221,7 +231,6 @@ void SceneView::render() { auto fbContext = _lightingStage.getRenderContext(); - _camPosition.set(_camera->getPosition()); glViewport(0, 0, _outputSize.width, _outputSize.height); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); @@ -251,19 +260,15 @@ void SceneView::render() // Render all point lights { ProgramContext programContext(_pointLightingProgram); - _lightPosition = _pointLightingProgram.getUniform("lightPosition"); - _lightBaseColor = _pointLightingProgram.getUniform("lightBaseColor"); - _camPosition = _pointLightingProgram.getUniform("camPosition"); - _scene->renderAllPointLights(_lightPosition, _lightBaseColor); + _pointLightUniforms.camPosition.set(_camera->getPosition()); + _scene->renderAllPointLights(_pointLightUniforms.lightPosition, _pointLightUniforms.lightBaseColor); } // Render all directional lights { ProgramContext programContext(_directionalLightingProgram); - _lightDirection = _directionalLightingProgram.getUniform("lightDirection"); - _lightBaseColor = _directionalLightingProgram.getUniform("lightBaseColor"); - _camPosition = _directionalLightingProgram.getUniform("camPosition"); - _scene->renderAllDirectionalLights(_lightDirection, _lightBaseColor); + _directionalLightUniforms.camPosition.set(_camera->getPosition()); + _scene->renderAllDirectionalLights(_directionalLightUniforms.lightDirection, _directionalLightUniforms.lightBaseColor); } } } From 1132b88447e24a2dd22de45cccfcedda20ee14e5 Mon Sep 17 00:00:00 2001 From: Benjamin Luke Date: Mon, 11 Feb 2019 09:53:02 -0800 Subject: [PATCH 3/3] PR Comments --- engine/include/rev/Light.h | 38 ++++++++++++++--------------- engine/include/rev/Scene.h | 11 ++++----- engine/src/Light.cpp | 50 ++++++++++++++++++++------------------ engine/src/Scene.cpp | 8 +++--- engine/src/SceneView.cpp | 2 +- 5 files changed, 55 insertions(+), 54 deletions(-) diff --git a/engine/include/rev/Light.h b/engine/include/rev/Light.h index ce42fd2..699b145 100644 --- a/engine/include/rev/Light.h +++ b/engine/include/rev/Light.h @@ -1,37 +1,37 @@ #pragma once +#include + #include namespace rev { class Light { -protected: - Light(); public: + enum class Type + { + Directional, + Point + }; + + Light(Type type); + const glm::vec3& getBaseColor() const; - void setBaseColor(const glm::vec3& color); -private: - glm::vec3 _baseColor; -}; + void setBaseColor(const glm::vec3& baseColor); -class PointLight: public Light { -public: - PointLight(); + const glm::vec3& getDirection() const; + void setDirection(const glm::vec3& direction); const glm::vec3& getPosition() const; void setPosition(const glm::vec3& position); -private: - glm::vec3 _position; -}; -class DirectionalLight: public Light { -public: - DirectionalLight(); + Type getType() const; - const glm::vec3& getDirection() const; - void setDirection(const glm::vec3& direction); private: - glm::vec3 _direction; + glm::vec3 _baseColor; + std::optional _position; + std::optional _direction; + Type _type; }; -} // namespace rev \ No newline at end of file +} // namespace rev diff --git a/engine/include/rev/Scene.h b/engine/include/rev/Scene.h index 7ea4ac4..6bce244 100644 --- a/engine/include/rev/Scene.h +++ b/engine/include/rev/Scene.h @@ -11,16 +11,15 @@ namespace rev { -class PointLight; -class DirectionalLight; +class Light; class IModel; class SceneObject; class Scene { public: - std::shared_ptr addPointLight(); - std::shared_ptr addDirectionalLight(); + std::shared_ptr addPointLight(); + std::shared_ptr addDirectionalLight(); void renderAllObjects(Camera &camera); void renderAllPointLights(Uniform& lightPositionUniform, Uniform& lightBaseColor); @@ -29,8 +28,8 @@ class Scene void addObjectGroup(std::shared_ptr group); private: std::vector> _objectGroups; - std::set> _pointLights; - std::set> _directionalLights; + std::set> _pointLights; + std::set> _directionalLights; }; } // namespace rev \ No newline at end of file diff --git a/engine/src/Light.cpp b/engine/src/Light.cpp index d53dc22..a5b5713 100644 --- a/engine/src/Light.cpp +++ b/engine/src/Light.cpp @@ -1,52 +1,54 @@ #include "rev/Light.h" +using namespace std; +using namespace glm; + namespace rev { // Light - Light::Light() - : _baseColor(glm::vec3(1.0)) + Light::Light(Type type) + : _baseColor(0.f), _type(type) { } - const glm::vec3& Light::getBaseColor() const + Light::Type Light::getType() const { - return _baseColor; - } + return _type; + } - void Light::setBaseColor(const glm::vec3& color) - { - _baseColor = color; - } - - // PointLight - PointLight::PointLight() - : _position(glm::vec3(0.0)) + const glm::vec3& Light::getBaseColor() const { + return _baseColor; } - const glm::vec3& PointLight::getPosition() const + void Light::setBaseColor(const glm::vec3& baseColor) { - return _position; + _baseColor = baseColor; } - void PointLight::setPosition(const glm::vec3& position) + const glm::vec3& Light::getPosition() const { - _position = position; + assert(_position.has_value()); + return *_position; } - // DirectionalLight - DirectionalLight::DirectionalLight() - : _direction(glm::vec3(0.0, -1.0, 0.0)) + void Light::setPosition(const glm::vec3& position) { + assert(_type == Type::Point); + _position = make_optional(position); } - const glm::vec3& DirectionalLight::getDirection() const + const glm::vec3& Light::getDirection() const { - return _direction; + assert(_direction.has_value()); + return *_direction; } - void DirectionalLight::setDirection(const glm::vec3& direction) + void Light::setDirection(const glm::vec3& direction) { - _direction = 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(direction); } } diff --git a/engine/src/Scene.cpp b/engine/src/Scene.cpp index 9016880..8a91c73 100644 --- a/engine/src/Scene.cpp +++ b/engine/src/Scene.cpp @@ -6,16 +6,16 @@ namespace rev { -std::shared_ptr Scene::addPointLight() +std::shared_ptr Scene::addPointLight() { - auto light = std::make_shared(); + auto light = std::make_shared(Light::Type::Point); _pointLights.insert(light); return std::move(light); } -std::shared_ptr Scene::addDirectionalLight() +std::shared_ptr Scene::addDirectionalLight() { - auto light = std::make_shared(); + auto light = std::make_shared(Light::Type::Directional); _directionalLights.insert(light); return std::move(light); } diff --git a/engine/src/SceneView.cpp b/engine/src/SceneView.cpp index 938c039..ad5ada7 100644 --- a/engine/src/SceneView.cpp +++ b/engine/src/SceneView.cpp @@ -52,7 +52,7 @@ constexpr const char *kDeferredDirectionalLightFragmentShader = R"fragmentShader vec3 diffuse = texture(diffuse, texCoord).rgb; vec3 fragmentPosition = texture(fragPosition, texCoord).rgb; - vec3 lightVector = 1.0f * lightDirection; + vec3 lightVector = -1.0f * lightDirection; float angleMultiplier = max(dot(normalize(lightVector), normalize(normal)), 0.0f); float specularExponent = texture(specularExponent, texCoord).r;