feat: Implement fading of the shadow light
This commit is contained in:
parent
14c3ee3722
commit
230e5efc16
6 changed files with 59 additions and 23 deletions
|
@ -100,6 +100,7 @@ layout(std140) uniform General {
|
|||
float uWaterAlpha;
|
||||
int uFeatureMask;
|
||||
bool uShadowLightPresent;
|
||||
float uShadowStrength;
|
||||
float uRoughness;
|
||||
float uExposure;
|
||||
};
|
||||
|
@ -237,7 +238,7 @@ float getShadow() {
|
|||
}
|
||||
}
|
||||
|
||||
return shadow / (samples * samples * samples);
|
||||
return uShadowStrength * shadow / (samples * samples * samples);
|
||||
}
|
||||
|
||||
float getLightAttenuation(int light) {
|
||||
|
|
|
@ -98,6 +98,7 @@ struct GeneralUniforms {
|
|||
float waterAlpha { 1.0f };
|
||||
int featureMask { 0 }; /**< any combination of UniformFeaturesFlags */
|
||||
int shadowLightPresent { false };
|
||||
float shadowStrength { 1.0f };
|
||||
float roughness { 0.0f };
|
||||
float exposure { 1.0f };
|
||||
};
|
||||
|
|
|
@ -72,8 +72,6 @@ void ControlRenderPipeline::render(const glm::ivec2 &offset) {
|
|||
uniforms.general.projection = _scene->activeCamera()->projection();
|
||||
uniforms.general.view = _scene->activeCamera()->view();
|
||||
uniforms.general.cameraPosition = _scene->activeCamera()->absoluteTransform()[3];
|
||||
uniforms.general.shadowLightPresent = _scene->isShadowLightPresent();
|
||||
uniforms.general.shadowLightPosition = glm::vec4(_scene->shadowLightPosition(), 1.0f);
|
||||
_scene->setUniformsPrototype(move(uniforms));
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "../../render/window.h"
|
||||
|
||||
#include "../node/cameranode.h"
|
||||
#include "../node/lightnode.h"
|
||||
#include "../scenegraph.h"
|
||||
|
||||
using namespace std;
|
||||
|
@ -131,19 +132,21 @@ void WorldRenderPipeline::render() {
|
|||
}
|
||||
|
||||
void WorldRenderPipeline::drawShadows() {
|
||||
if (!_scene->isShadowLightPresent() || _opts.shadowResolution < 1) return;
|
||||
if (_opts.shadowResolution < 1) return;
|
||||
|
||||
withViewport(glm::ivec4(0, 0, 1024 * _opts.shadowResolution, 1024 * _opts.shadowResolution), [this]() {
|
||||
const LightSceneNode *shadowLight = _scene->shadowLight();
|
||||
if (!shadowLight) return;
|
||||
|
||||
withViewport(glm::ivec4(0, 0, 1024 * _opts.shadowResolution, 1024 * _opts.shadowResolution), [&]() {
|
||||
_shadows.bind();
|
||||
|
||||
glDrawBuffer(GL_NONE);
|
||||
glReadBuffer(GL_NONE);
|
||||
|
||||
glm::mat4 projection(glm::perspective(glm::radians(90.0f), 1.0f, 1.0f, kShadowFarPlane));
|
||||
glm::vec3 lightPosition(_scene->shadowLightPosition());
|
||||
glm::vec3 lightPosition(shadowLight->absoluteTransform()[3]);
|
||||
|
||||
ShaderUniforms uniforms;
|
||||
uniforms.general.shadowLightPresent = true;
|
||||
uniforms.general.shadowLightPosition = glm::vec4(lightPosition, 1.0f);
|
||||
|
||||
for (int i = 0; i < kNumCubeFaces; ++i) {
|
||||
|
@ -183,15 +186,18 @@ void WorldRenderPipeline::drawGeometry() {
|
|||
static constexpr GLenum buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
|
||||
glDrawBuffers(2, buffers);
|
||||
|
||||
const LightSceneNode *shadowLight = _scene->shadowLight();
|
||||
|
||||
ShaderUniforms uniforms;
|
||||
uniforms.general.projection = _scene->activeCamera()->projection();
|
||||
uniforms.general.view = _scene->activeCamera()->view();
|
||||
uniforms.general.cameraPosition = _scene->activeCamera()->absoluteTransform()[3];
|
||||
uniforms.general.shadowLightPresent = _scene->isShadowLightPresent();
|
||||
uniforms.general.shadowLightPosition = glm::vec4(_scene->shadowLightPosition(), 1.0f);
|
||||
uniforms.general.shadowLightPresent = static_cast<bool>(shadowLight);
|
||||
uniforms.general.shadowLightPosition = shadowLight ? shadowLight->absoluteTransform()[3] : glm::vec4(0.0f);
|
||||
uniforms.general.shadowStrength = _scene->shadowStrength();
|
||||
_scene->setUniformsPrototype(move(uniforms));
|
||||
|
||||
if (_scene->isShadowLightPresent()) {
|
||||
if (shadowLight) {
|
||||
setActiveTextureUnit(TextureUnits::shadowMap);
|
||||
_shadowsDepth->bind();
|
||||
}
|
||||
|
|
|
@ -157,16 +157,35 @@ void SceneGraph::refreshFromSceneNode(const std::shared_ptr<SceneNode> &node) {
|
|||
}
|
||||
|
||||
void SceneGraph::refreshShadowLight() {
|
||||
_shadowLightPresent = false;
|
||||
const LightSceneNode *nextShadowLight = nullptr;
|
||||
|
||||
if (!_shadowReference) return;
|
||||
if (_shadowReference) {
|
||||
vector<LightSceneNode *> lights;
|
||||
getLightsAt(*_shadowReference, lights, 1, [](auto &light) { return light.isShadow(); });
|
||||
|
||||
vector<LightSceneNode *> lights;
|
||||
getLightsAt(*_shadowReference, lights, 1, [](auto &light) { return light.isShadow(); });
|
||||
if (!lights.empty()) {
|
||||
nextShadowLight = lights.front();
|
||||
}
|
||||
}
|
||||
|
||||
if (!lights.empty()) {
|
||||
_shadowLightPresent = true;
|
||||
_shadowLightPosition = lights.front()->absoluteTransform()[3];
|
||||
if (!nextShadowLight) {
|
||||
_shadowLight = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_shadowLight) {
|
||||
_shadowLight = nextShadowLight;
|
||||
_shadowFading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_shadowLight == nextShadowLight) return;
|
||||
|
||||
if (_shadowFading && _shadowStrength == 0.0f) {
|
||||
_shadowLight = nextShadowLight;
|
||||
_shadowFading = false;
|
||||
} else {
|
||||
_shadowFading = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -176,6 +195,12 @@ void SceneGraph::update(float dt) {
|
|||
for (auto &root : _roots) {
|
||||
root->update(dt);
|
||||
}
|
||||
|
||||
if (_shadowFading) {
|
||||
_shadowStrength = glm::max(0.0f, _shadowStrength - dt);
|
||||
} else {
|
||||
_shadowStrength = glm::min(_shadowStrength + dt, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
void SceneGraph::render(bool shadowPass) {
|
||||
|
|
|
@ -71,8 +71,6 @@ public:
|
|||
|
||||
// Lights and shadows
|
||||
|
||||
bool isShadowLightPresent() const { return _shadowLightPresent; }
|
||||
|
||||
/**
|
||||
* Fills lights vector with up to count lights, sorted by priority and
|
||||
* proximity to the reference node.
|
||||
|
@ -84,7 +82,8 @@ public:
|
|||
std::function<bool(const LightSceneNode &)> predicate = [](auto &light) { return true; }) const;
|
||||
|
||||
const glm::vec3 &ambientLightColor() const { return _ambientLightColor; }
|
||||
const glm::vec3 &shadowLightPosition() const { return _shadowLightPosition; }
|
||||
const LightSceneNode *shadowLight() const { return _shadowLight; }
|
||||
float shadowStrength() const { return _shadowStrength; }
|
||||
|
||||
void setAmbientLightColor(const glm::vec3 &color);
|
||||
|
||||
|
@ -102,13 +101,19 @@ private:
|
|||
std::shared_ptr<CameraSceneNode> _activeCamera;
|
||||
glm::vec3 _ambientLightColor { 0.5f };
|
||||
uint32_t _textureId { 0 };
|
||||
bool _shadowLightPresent { false };
|
||||
glm::vec3 _shadowLightPosition { 0.0f };
|
||||
std::shared_ptr<SceneNode> _shadowReference;
|
||||
bool _update { true };
|
||||
render::ShaderUniforms _uniformsPrototype;
|
||||
float _exposure { kDefaultExposure };
|
||||
|
||||
// Shadows
|
||||
|
||||
const LightSceneNode *_shadowLight { nullptr };
|
||||
std::shared_ptr<SceneNode> _shadowReference;
|
||||
float _shadowStrength { 1.0f };
|
||||
bool _shadowFading { false };
|
||||
|
||||
// END Shadows
|
||||
|
||||
void refreshNodeLists();
|
||||
void refreshFromSceneNode(const std::shared_ptr<SceneNode> &node);
|
||||
void refreshShadowLight();
|
||||
|
|
Loading…
Reference in a new issue