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