Select lights closest to the reference node, not per model

This makes dynamic lighting slighly more performant and improves area
lighting.
This commit is contained in:
Vsevolod Kremianskii 2021-05-10 11:55:13 +07:00
parent 563238fd92
commit 200b1ad6d8
6 changed files with 22 additions and 70 deletions

View file

@ -725,15 +725,17 @@ void Game::updateSceneGraph(float dt) {
const Camera *camera = getActiveCamera();
if (!camera) return;
shared_ptr<SceneNode> shadowReference;
// Select a reference node for dynamic lighting
shared_ptr<SceneNode> lightingRefNode;
shared_ptr<Creature> partyLeader(_party.getLeader());
if (partyLeader && _cameraType == CameraType::ThirdPerson) {
shadowReference = partyLeader->getModelSceneNode();
lightingRefNode = partyLeader->getModelSceneNode();
} else {
shadowReference = camera->sceneNode();
lightingRefNode = camera->sceneNode();
}
_sceneGraph.setActiveCamera(camera->sceneNode());
_sceneGraph.setShadowReference(shadowReference);
_sceneGraph.setLightingRefNode(lightingRefNode);
_sceneGraph.setUpdateRoots(!_paused);
_sceneGraph.update(dt);
}

View file

@ -304,7 +304,7 @@ void ModelNodeSceneNode::drawSingle(bool shadowPass) {
uniforms.combined.general.selfIllumColor = glm::vec4(_selfIllumColor, 1.0f);
}
if (isLightingEnabled()) {
const vector<LightSceneNode *> &lights = _modelSceneNode->lightsAffectedBy();
const vector<LightSceneNode *> &lights = _sceneGraph->closestLights();
uniforms.combined.featureMask |= UniformFeatureFlags::lighting;
if (_material.custom) {

View file

@ -246,34 +246,6 @@ void ModelSceneNode::attach(const string &parent, const shared_ptr<SceneNode> &n
}
}
void ModelSceneNode::updateAbsoluteTransform() {
SceneNode::updateAbsoluteTransform();
_lightingDirty = true;
}
void ModelSceneNode::updateLighting() {
if (!_lightingDirty) return;
_lightsAffectedBy.clear();
_sceneGraph->getLightsAt(*this, _lightsAffectedBy, kMaxLights, bind(&ModelSceneNode::isAffectableByLight, this, _1));
_lightingDirty = false;
for (auto &attached : _attachedModels) {
attached.second->setLightsAffectedBy(_lightsAffectedBy);
}
}
bool ModelSceneNode::isAffectableByLight(const LightSceneNode &light) const {
if (light.isAmbientOnly()) {
return _usage == ModelUsage::Room;
}
return true;
}
void ModelSceneNode::setLightingIsDirty() {
_lightingDirty = true;
}
bool ModelSceneNode::getNodeAbsolutePosition(const string &name, glm::vec3 &position) const {
shared_ptr<ModelNode> node(_model->findNodeByName(name));
if (!node) {
@ -313,9 +285,6 @@ void ModelSceneNode::setVisible(bool visible) {
for (auto &attached : _attachedModels) {
attached.second->setVisible(visible);
}
if (visible) {
_lightingDirty = true;
}
}
void ModelSceneNode::setAlpha(float alpha) {
@ -330,10 +299,6 @@ void ModelSceneNode::setProjectileSpeed(float speed) {
_projectileSpeed = speed;
}
void ModelSceneNode::setLightsAffectedBy(const vector<LightSceneNode *> &lights) {
_lightsAffectedBy = lights;
}
void ModelSceneNode::setWalkmesh(shared_ptr<Walkmesh> walkmesh) {
_walkmesh = move(walkmesh);
}

View file

@ -83,17 +83,6 @@ public:
// END Attachments
// Dynamic lighting
void updateLighting();
void setLightingIsDirty();
const std::vector<LightSceneNode *> &lightsAffectedBy() const { return _lightsAffectedBy; }
void setLightsAffectedBy(const std::vector<LightSceneNode *> &lights);
// END Dynamic lighting
private:
IAnimationEventListener *_animEventListener;
@ -109,14 +98,9 @@ private:
std::unordered_map<uint16_t, std::shared_ptr<ModelSceneNode>> _attachedModels;
bool _visible { true };
float _alpha { 1.0f };
std::vector<LightSceneNode *> _lightsAffectedBy;
bool _lightingDirty { true };
float _projectileSpeed { 0.0f };
void initModelNodes();
void updateAbsoluteTransform() override;
bool isAffectableByLight(const LightSceneNode &light) const;
std::unique_ptr<ModelNodeSceneNode> getModelNodeSceneNode(graphics::ModelNode &node) const;
};

View file

@ -86,11 +86,10 @@ void SceneGraph::cullRoots() {
}
void SceneGraph::updateLighting() {
// Associate each model node with light sources
for (auto &root : _roots) {
if (root->type() == SceneNodeType::Model) {
static_pointer_cast<ModelSceneNode>(root)->updateLighting();
}
_closestLights.clear();
if (_lightingRefNode) {
getLightsAt(*_lightingRefNode, _closestLights, kMaxLights, [](auto &light) { return !light.isAmbientOnly(); });
}
}
@ -167,9 +166,9 @@ void SceneGraph::refreshFromSceneNode(const std::shared_ptr<SceneNode> &node) {
void SceneGraph::refreshShadowLight() {
const LightSceneNode *nextShadowLight = nullptr;
if (_shadowReference) {
if (_lightingRefNode) {
vector<LightSceneNode *> lights;
getLightsAt(*_shadowReference, lights, 1, [](auto &light) { return light.isShadow(); });
getLightsAt(*_lightingRefNode, lights, 1, [](auto &light) { return light.isShadow(); });
if (!lights.empty()) {
nextShadowLight = lights.front();

View file

@ -66,7 +66,6 @@ public:
void setUpdateRoots(bool update) { _updateRoots = update; }
void setActiveCamera(std::shared_ptr<CameraSceneNode> camera) { _activeCamera = std::move(camera); }
void setShadowReference(std::shared_ptr<SceneNode> reference) { _shadowReference = std::move(reference); }
void setUniformsPrototype(graphics::ShaderUniforms &&uniforms) { _uniformsPrototype = uniforms; }
// Roots
@ -77,7 +76,7 @@ public:
// END Roots
// Lights and shadows
// Lighting and shadows
/**
* Fill lights vector with up to count lights, sorted by priority and
@ -90,12 +89,14 @@ public:
std::function<bool(const LightSceneNode &)> predicate = [](auto &light) { return true; }) const;
const glm::vec3 &ambientLightColor() const { return _ambientLightColor; }
const std::vector<LightSceneNode *> closestLights() const { return _closestLights; }
const LightSceneNode *shadowLight() const { return _shadowLight; }
float shadowStrength() const { return _shadowStrength; }
void setAmbientLightColor(glm::vec3 color) { _ambientLightColor = std::move(color); }
void setLightingRefNode(std::shared_ptr<SceneNode> node) { _lightingRefNode = std::move(node); }
// END Lights and shadows
// END Lighting and shadows
// Fog
@ -127,19 +128,20 @@ private:
std::vector<std::pair<EmitterSceneNode *, std::vector<Particle *>>> _particles;
std::vector<std::pair<GrassSceneNode *, std::vector<GrassCluster>>> _grassClusters;
glm::vec3 _ambientLightColor { 0.5f };
uint32_t _textureId { 0 };
bool _updateRoots { true };
graphics::ShaderUniforms _uniformsPrototype;
// Shadows
// Lighting and shadows
glm::vec3 _ambientLightColor { 0.5f };
std::shared_ptr<SceneNode> _lightingRefNode; /**< reference node to use when selecting closest light sources */
std::vector<LightSceneNode *> _closestLights;
const LightSceneNode *_shadowLight { nullptr };
std::shared_ptr<SceneNode> _shadowReference;
float _shadowStrength { 1.0f };
bool _shadowFading { false };
// END Shadows
// END Lighting and shadows
// Fog