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(); const Camera *camera = getActiveCamera();
if (!camera) return; if (!camera) return;
shared_ptr<SceneNode> shadowReference; // Select a reference node for dynamic lighting
shared_ptr<SceneNode> lightingRefNode;
shared_ptr<Creature> partyLeader(_party.getLeader()); shared_ptr<Creature> partyLeader(_party.getLeader());
if (partyLeader && _cameraType == CameraType::ThirdPerson) { if (partyLeader && _cameraType == CameraType::ThirdPerson) {
shadowReference = partyLeader->getModelSceneNode(); lightingRefNode = partyLeader->getModelSceneNode();
} else { } else {
shadowReference = camera->sceneNode(); lightingRefNode = camera->sceneNode();
} }
_sceneGraph.setActiveCamera(camera->sceneNode()); _sceneGraph.setActiveCamera(camera->sceneNode());
_sceneGraph.setShadowReference(shadowReference); _sceneGraph.setLightingRefNode(lightingRefNode);
_sceneGraph.setUpdateRoots(!_paused); _sceneGraph.setUpdateRoots(!_paused);
_sceneGraph.update(dt); _sceneGraph.update(dt);
} }

View file

@ -304,7 +304,7 @@ void ModelNodeSceneNode::drawSingle(bool shadowPass) {
uniforms.combined.general.selfIllumColor = glm::vec4(_selfIllumColor, 1.0f); uniforms.combined.general.selfIllumColor = glm::vec4(_selfIllumColor, 1.0f);
} }
if (isLightingEnabled()) { if (isLightingEnabled()) {
const vector<LightSceneNode *> &lights = _modelSceneNode->lightsAffectedBy(); const vector<LightSceneNode *> &lights = _sceneGraph->closestLights();
uniforms.combined.featureMask |= UniformFeatureFlags::lighting; uniforms.combined.featureMask |= UniformFeatureFlags::lighting;
if (_material.custom) { 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 { bool ModelSceneNode::getNodeAbsolutePosition(const string &name, glm::vec3 &position) const {
shared_ptr<ModelNode> node(_model->findNodeByName(name)); shared_ptr<ModelNode> node(_model->findNodeByName(name));
if (!node) { if (!node) {
@ -313,9 +285,6 @@ void ModelSceneNode::setVisible(bool visible) {
for (auto &attached : _attachedModels) { for (auto &attached : _attachedModels) {
attached.second->setVisible(visible); attached.second->setVisible(visible);
} }
if (visible) {
_lightingDirty = true;
}
} }
void ModelSceneNode::setAlpha(float alpha) { void ModelSceneNode::setAlpha(float alpha) {
@ -330,10 +299,6 @@ void ModelSceneNode::setProjectileSpeed(float speed) {
_projectileSpeed = speed; _projectileSpeed = speed;
} }
void ModelSceneNode::setLightsAffectedBy(const vector<LightSceneNode *> &lights) {
_lightsAffectedBy = lights;
}
void ModelSceneNode::setWalkmesh(shared_ptr<Walkmesh> walkmesh) { void ModelSceneNode::setWalkmesh(shared_ptr<Walkmesh> walkmesh) {
_walkmesh = move(walkmesh); _walkmesh = move(walkmesh);
} }

View file

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

View file

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

View file

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