Implement ambient-only lights

This commit is contained in:
Vsevolod Kremianskii 2021-05-25 10:12:03 +07:00
parent 67cfbd92ad
commit e9047a267b
13 changed files with 69 additions and 28 deletions

View file

@ -359,7 +359,7 @@ void CharacterGeneration::reloadCharacterModel() {
.modelSupplier(bind(&CharacterGeneration::getCharacterModel, this, _1))
.modelScale(kModelScale)
.cameraFromModelNode("camerahook")
.ambientLightColor(glm::vec3(0.2f))
.lightingRefFromModelNode("cgbody_light")
.build());
lblModel.setScene(move(scene));

View file

@ -120,7 +120,7 @@ void ClassSelection::setupClassButton(int index, Gender gender, ClassType clazz)
.modelSupplier([&](SceneGraph &sceneGraph) { return getCharacterModel(appearance, sceneGraph); })
.modelScale(kModelScale)
.cameraFromModelNode("camerahook")
.ambientLightColor(glm::vec3(0.2f))
.lightingRefFromModelNode("cgbody_light")
.build());
Control &control3d = getControl("3D_MODEL" + to_string(index + 1));

View file

@ -89,7 +89,7 @@ void PortraitSelection::loadHeadModel() {
.modelSupplier(bind(&PortraitSelection::getCharacterModel, this, _1))
.modelScale(kModelScale)
.cameraFromModelNode(_charGen->character().gender == Gender::Male ? "camerahookm" : "camerahookf")
.ambientLightColor(glm::vec3(0.2f))
.lightingRefFromModelNode("cghead_light")
.build());
control.setScene(move(scene));
@ -118,7 +118,6 @@ shared_ptr<ModelSceneNode> PortraitSelection::getCharacterModel(SceneGraph &scen
auto model = make_shared<ModelSceneNode>(_game->services().graphics().models().get("cghead_light"), ModelUsage::GUI, &sceneGraph);
model->attach("cghead_light", creatureModel);
return move(model);
}

View file

@ -153,7 +153,7 @@ void CharacterMenu::refresh3D() {
.modelSupplier(bind(&CharacterMenu::getSceneModel, this, _1))
.modelOffset(glm::vec2(0.0f, 1.7f))
.cameraFromModelNode("camerahook")
.ambientLightColor(glm::vec3(0.2f))
.lightingRefFromModelNode("charmain_light")
.build();
control3d.setScene(move(scene));

View file

@ -117,7 +117,7 @@ void MainMenu::setup3DView() {
.modelSupplier(bind(&MainMenu::getKotorModel, this, _1))
.modelScale(kKotorModelSize)
.cameraFromModelNode("camerahook")
.ambientLightColor(glm::vec3(0.1f))
.lightingRefFromModelNode("rootdummy")
.build());
control.setScene(move(scene));

View file

@ -138,7 +138,8 @@ struct ShaderLight {
glm::vec4 color { 1.0f };
float multiplier { 1.0f };
float radius { 1.0f };
char padding[8];
int ambientOnly { 0 };
char padding[4];
};
struct LightingUniforms {

View file

@ -130,6 +130,7 @@ struct Light {
vec4 color;
float multiplier;
float radius;
bool ambientOnly;
};
layout(std140) uniform Lighting {

View file

@ -267,6 +267,12 @@ void main() {
vec3 ambient = uGeneral.ambientColor.rgb * albedo * ao;
for (int i = 0; i < uLightCount; ++i) {
if (!uLights[i].ambientOnly) continue;
float attenuation = getAttenuationQuadratic(i);
ambient += attenuation * uLights[i].multiplier * uLights[i].color.rgb * albedo * ao;
}
if (isFeatureEnabled(FEATURE_PBRIBL)) {
vec3 F = fresnelSchlickRoughness(max(dot(N, V), 0.0), F0, roughness);
@ -293,6 +299,8 @@ void main() {
vec3 Lo = vec3(0.0);
for (int i = 0; i < uLightCount; ++i) {
if (uLights[i].ambientOnly) continue;
vec3 L = normalize(uLights[i].position.xyz - fragPosition);
vec3 H = normalize(V + L);

View file

@ -27,7 +27,20 @@ namespace graphics {
char g_shaderBaseBlinnPhong[] = R"END(
vec3 getLightingIndirect(vec3 N) {
return uGeneral.ambientColor.rgb * uMaterial.ambient.rgb;
vec3 result = uGeneral.ambientColor.rgb * uMaterial.ambient.rgb;
for (int i = 0; i < uLightCount; ++i) {
if (!uLights[i].ambientOnly) continue;
vec3 ambient = uLights[i].multiplier * uLights[i].color.rgb * uMaterial.ambient.rgb;
float attenuation = getAttenuationQuadratic(i);
ambient *= attenuation;
result += ambient;
}
return result;
}
vec3 getLightingDirect(vec3 N) {
@ -35,6 +48,8 @@ vec3 getLightingDirect(vec3 N) {
vec3 V = normalize(uGeneral.cameraPosition.xyz - fragPosition);
for (int i = 0; i < uLightCount; ++i) {
if (uLights[i].ambientOnly) continue;
vec3 L = normalize(uLights[i].position.xyz - fragPosition);
vec3 H = normalize(V + L);
@ -51,7 +66,7 @@ vec3 getLightingDirect(vec3 N) {
result += diffuse + specular;
}
return result;
return min(vec3(1.0), result);
}
)END";
@ -73,7 +88,7 @@ void main() {
} else if (isFeatureEnabled(FEATURE_LIGHTING)) {
vec3 indirect = getLightingIndirect(N);
vec3 direct = getLightingDirect(N);
lighting = min(vec3(1.0), indirect + (1.0 - shadow) * direct);
lighting = indirect + (1.0 - shadow) * direct;
} else if (isFeatureEnabled(FEATURE_SELFILLUM)) {
lighting = uGeneral.selfIllumColor.rgb;
} else {

View file

@ -54,19 +54,28 @@ unique_ptr<SceneGraph> SceneBuilder::build() {
_modelScale + _modelOffset.y,
_zNear, _zFar));
auto camera = make_shared<CameraSceneNode>("", projection, scene.get());
scene->addRoot(model);
scene->setAmbientLightColor(_ambientLightColor);
auto cameraNode = make_shared<CameraSceneNode>("", projection, scene.get());
if (_cameraNodeName.empty()) {
camera->setLocalTransform(_cameraTransform);
cameraNode->setLocalTransform(_cameraTransform);
} else {
shared_ptr<ModelNode> refModelNode(model->model()->getNodeByName(_cameraNodeName));
if (refModelNode) {
camera->setLocalTransform(refModelNode->absoluteTransform() * _cameraTransform);
shared_ptr<ModelNode> modelNode(model->model()->getNodeByName(_cameraNodeName));
if (modelNode) {
cameraNode->setLocalTransform(modelNode->absoluteTransform() * _cameraTransform);
}
}
scene->setActiveCamera(move(cameraNode));
scene->addRoot(move(model));
scene->setAmbientLightColor(_ambientLightColor);
scene->setActiveCamera(camera);
if (!_lightingRefNodeName.empty()) {
shared_ptr<ModelNode> modelNode(model->model()->getNodeByName(_lightingRefNodeName));
if (modelNode) {
auto lightingRefNode = make_shared<DummySceneNode>(modelNode, scene.get());
lightingRefNode->setLocalTransform(modelNode->absoluteTransform());
scene->setLightingRefNode(move(lightingRefNode));
}
}
return move(scene);
}
@ -97,18 +106,23 @@ SceneBuilder &SceneBuilder::modelOffset(glm::vec2 offset) {
return *this;
}
SceneBuilder &SceneBuilder::cameraTransform(const glm::mat4 &transform) {
_cameraTransform = transform;
SceneBuilder &SceneBuilder::cameraTransform(glm::mat4 transform) {
_cameraTransform = move(transform);
return *this;
}
SceneBuilder &SceneBuilder::cameraFromModelNode(const std::string &nodeName) {
_cameraNodeName = nodeName;
SceneBuilder &SceneBuilder::cameraFromModelNode(string nodeName) {
_cameraNodeName = move(nodeName);
return *this;
}
SceneBuilder &SceneBuilder::ambientLightColor(const glm::vec3 &color) {
_ambientLightColor = color;
SceneBuilder &SceneBuilder::ambientLightColor(glm::vec3 color) {
_ambientLightColor = move(color);
return *this;
}
SceneBuilder &SceneBuilder::lightingRefFromModelNode(string nodeName) {
_lightingRefNodeName = move(nodeName);
return *this;
}

View file

@ -48,9 +48,10 @@ public:
SceneBuilder &modelSupplier(const std::function<std::shared_ptr<scene::ModelSceneNode>(scene::SceneGraph &)> &supplier);
SceneBuilder &modelScale(float scale);
SceneBuilder &modelOffset(glm::vec2 offset);
SceneBuilder &cameraTransform(const glm::mat4 &transform);
SceneBuilder &cameraFromModelNode(const std::string &nodeName);
SceneBuilder &ambientLightColor(const glm::vec3 &color);
SceneBuilder &cameraTransform(glm::mat4 transform);
SceneBuilder &cameraFromModelNode(std::string nodeName);
SceneBuilder &ambientLightColor(glm::vec3 color);
SceneBuilder &lightingRefFromModelNode(std::string nodeName);
private:
graphics::GraphicsOptions _options;
@ -65,6 +66,7 @@ private:
glm::mat4 _cameraTransform { 1.0f };
std::string _cameraNodeName;
glm::vec3 _ambientLightColor { 0.0f };
std::string _lightingRefNodeName;
};
} // namespace gui

View file

@ -327,6 +327,7 @@ void MeshSceneNode::drawSingle(bool shadowPass) {
shaderLight.color = glm::vec4(lights[i]->color(), 1.0f);
shaderLight.multiplier = lights[i]->multiplier();
shaderLight.radius = lights[i]->radius();
shaderLight.ambientOnly = static_cast<int>(lights[i]->modelNode()->light()->ambientOnly);
}
}

View file

@ -99,7 +99,7 @@ void SceneGraph::updateLighting() {
_closestLights.clear();
if (_lightingRefNode) {
getLightsAt(*_lightingRefNode, _closestLights, kMaxLights, [](auto &light) { return !light.modelNode()->light()->ambientOnly; });
getLightsAt(*_lightingRefNode, _closestLights, kMaxLights);
}
}