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:
parent
563238fd92
commit
200b1ad6d8
6 changed files with 22 additions and 70 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue