Implement area fog

This commit is contained in:
Vsevolod Kremianskii 2021-04-20 10:02:11 +07:00
parent b4d4803c7d
commit 43ada622db
11 changed files with 109 additions and 14 deletions

View file

@ -640,7 +640,13 @@ static glm::vec3 getRandomPointInTriangle(const Walkmesh::Face &face) {
void Area::fill(SceneGraph &sceneGraph) {
sceneGraph.clear();
// Room models + grass
// Area properties
sceneGraph.setAmbientLightColor(_ambientColor);
sceneGraph.setFogEnabled(_fogEnabled);
sceneGraph.setFogNear(_fogNear);
sceneGraph.setFogFar(_fogFar);
sceneGraph.setFogColor(_fogColor);
shared_ptr<GrassSceneNode> grass;
if (_grass.texture) {
@ -648,6 +654,8 @@ void Area::fill(SceneGraph &sceneGraph) {
sceneGraph.setGrass(grass);
}
// Room models
for (auto &room : _rooms) {
shared_ptr<ModelSceneNode> sceneNode(room.second->model());
if (sceneNode) {

View file

@ -195,6 +195,7 @@ private:
CreatureFinder _creatureFinder;
Grass _grass;
Perception _perception;
glm::vec3 _ambientColor { 0.0f };
// Scripts
@ -234,6 +235,15 @@ private:
// END Stealth
// Fog
bool _fogEnabled { false };
float _fogNear { 0.0f };
float _fogFar { 0.0f };
glm::vec3 _fogColor { 0.0f };
// END Fog
void init();
void loadLYT();
@ -274,6 +284,7 @@ private:
void loadMap(const resource::GffStruct &are);
void loadStealthXP(const resource::GffStruct &are);
void loadGrass(const resource::GffStruct &are);
void loadFog(const resource::GffStruct &are);
// END Loading ARE

View file

@ -45,6 +45,7 @@ void Area::loadARE(const GffStruct &are) {
loadMap(are);
loadStealthXP(are);
loadGrass(are);
loadFog(are);
}
void Area::loadCameraStyle(const GffStruct &are) {
@ -60,15 +61,7 @@ void Area::loadCameraStyle(const GffStruct &are) {
}
void Area::loadAmbientColor(const GffStruct &are) {
int ambientColorValue = are.getInt("DynAmbientColor");
glm::vec3 ambientColor(
ambientColorValue & 0xff,
(ambientColorValue >> 8) & 0xff,
(ambientColorValue >> 16) & 0xff);
ambientColor /= 255.0f;
_game->sceneGraph().setAmbientLightColor(ambientColor);
_ambientColor = are.getColor("DynAmbientColor");
}
void Area::loadScripts(const GffStruct &are) {
@ -103,6 +96,13 @@ void Area::loadGrass(const GffStruct &are) {
_grass.probabilities[3] = are.getFloat("Grass_Prob_LR");
}
void Area::loadFog(const GffStruct &are) {
_fogEnabled = are.getBool("SunFogOn");
_fogNear = are.getFloat("SunFogNear");
_fogFar = are.getFloat("SunFogFar");
_fogColor = are.getColor("SunFogColor");
}
} // namespace game
} // namespace reone

View file

@ -521,7 +521,7 @@ void MdlReader::doLoad() {
uint8_t classification = readByte();
uint8_t subclassification = readByte();
ignore(1); // unknown
uint8_t ignoreFog = readByte();
uint8_t affectedByFog = readByte();
uint32_t numChildModels = readUint32();
ArrayDefinition animationArrayDef(readArrayDefinition());
uint32_t superModelRef = readUint32();
@ -552,6 +552,7 @@ void MdlReader::doLoad() {
}
_model = make_unique<Model>(name, getClassification(classification), animationScale, move(rootNode), anims, superModel);
_model->setAffectedByFog(affectedByFog != 0);
}
MdlReader::ArrayDefinition MdlReader::readArrayDefinition() {

View file

@ -61,6 +61,8 @@ public:
void init();
bool isAffectedByFog() const { return _affectedByFog; }
std::vector<std::string> getAnimationNames() const;
std::shared_ptr<Animation> getAnimation(const std::string &name) const;
std::shared_ptr<ModelNode> findNodeByNumber(uint16_t number) const;
@ -73,6 +75,8 @@ public:
std::shared_ptr<Model> superModel() const { return _superModel; }
const AABB &aabb() const { return _aabb; }
void setAffectedByFog(bool affected) { _affectedByFog = affected; }
private:
std::string _name;
Classification _classification;
@ -84,6 +88,7 @@ private:
std::unordered_map<uint16_t, std::shared_ptr<ModelNode>> _nodeByNumber;
std::unordered_map<std::string, std::shared_ptr<ModelNode>> _nodeByName;
AABB _aabb;
bool _affectedByFog { false };
void initInternal(const std::shared_ptr<ModelNode> &node);

View file

@ -60,6 +60,7 @@ const int FEATURE_PARTICLES = 0x400;
const int FEATURE_WATER = 0x800;
const int FEATURE_HDR = 0x1000;
const int FEATURE_CUSTOMMAT = 0x2000;
const int FEATURE_FOG = 0x20000;
const int NUM_CUBE_FACES = 6;
const int MAX_BONES = 128;
@ -85,11 +86,14 @@ struct General {
vec4 ambientColor;
vec4 selfIllumColor;
vec4 discardColor;
vec4 fogColor;
vec2 uvOffset;
float alpha;
float waterAlpha;
float roughness;
float exposure;
float fogNear;
float fogFar;
};
struct Material {
@ -294,6 +298,11 @@ float getLightAttenuation(int light) {
return D / (D + r);
}
vec3 applyFog(vec3 rgb, float distance) {
float fogAmount = clamp(distance - uGeneral.fogNear, 0.0, uGeneral.fogFar - uGeneral.fogNear) / (uGeneral.fogFar - uGeneral.fogNear);
return mix(rgb, uGeneral.fogColor.rgb, fogAmount);
}
)END";
static constexpr GLchar kShaderBasePBR[] = R"END(
@ -661,7 +670,8 @@ void main() {
diffuseSample = vec4(vec3(0.5), 1.0);
}
vec3 V = normalize(uGeneral.cameraPosition.xyz - fragPosition);
vec3 cameraToFragment = uGeneral.cameraPosition.xyz - fragPosition;
vec3 V = normalize(cameraToFragment);
vec3 N;
if (isFeatureEnabled(FEATURE_BUMPMAPS)) {
@ -711,6 +721,9 @@ void main() {
vec3 S = vec3(1.0) - max(vec3(0.0), vec3(getShadow()) - uGeneral.ambientColor.rgb);
objectColor *= S;
}
if (isFeatureEnabled(FEATURE_FOG)) {
objectColor = applyFog(objectColor, length(cameraToFragment));
}
float objectAlpha = uGeneral.alpha;
if (!isFeatureEnabled(FEATURE_ENVMAP) && !isFeatureEnabled(FEATURE_BUMPMAPS)) {
@ -754,7 +767,8 @@ void main() {
N = normalize(fragNormal);
}
vec3 V = normalize(uGeneral.cameraPosition.xyz - fragPosition);
vec3 cameraToFragment = uGeneral.cameraPosition.xyz - fragPosition;
vec3 V = normalize(cameraToFragment);
vec3 R = reflect(-V, N);
vec3 albedo = isFeatureEnabled(FEATURE_HDR) ? pow(diffuseSample.rgb, vec3(GAMMA)) : diffuseSample.rgb;
@ -850,6 +864,9 @@ void main() {
vec3 S = vec3(1.0) - max(vec3(0.0), vec3(getShadow()) - uGeneral.ambientColor.rgb);
objectColor *= S;
}
if (isFeatureEnabled(FEATURE_FOG)) {
objectColor = applyFog(objectColor, length(cameraToFragment));
}
float objectAlpha = uGeneral.alpha;
if (!isFeatureEnabled(FEATURE_ENVMAP) && !isFeatureEnabled(FEATURE_BUMPMAPS)) {

View file

@ -71,6 +71,7 @@ struct UniformFeatureFlags {
static constexpr int blur = 0x4000;
static constexpr int text = 0x8000;
static constexpr int grass = 0x10000;
static constexpr int fog = 0x20000;
};
struct ShaderGeneral {
@ -82,12 +83,14 @@ struct ShaderGeneral {
glm::vec4 ambientColor { 1.0f };
glm::vec4 selfIllumColor { 1.0f };
glm::vec4 discardColor { 0.0f };
glm::vec4 fogColor { 0.0f };
glm::vec2 uvOffset { 0.0f };
float alpha { 1.0f };
float waterAlpha { 1.0f };
float roughness { 0.0f };
float exposure { 1.0f };
char padding[8];
float fogNear { 0.0f };
float fogFar { 0.0f };
};
struct ShaderMaterial {

View file

@ -65,6 +65,24 @@ uint32_t GffStruct::getUint(const string &name, uint32_t defValue) const {
return field->uintValue;
}
static glm::vec3 colorFromUint32(uint32_t value) {
glm::vec3 result(
value & 0xff,
(value >> 8) & 0xff,
(value >> 16) & 0xff);
result /= 255.0f;
return move(result);
}
glm::vec3 GffStruct::getColor(const string &name, glm::vec3 defValue) const {
const Field *field = get(name);
if (!field) return move(defValue);
return colorFromUint32(field->uintValue);
}
float GffStruct::getFloat(const string &name, float defValue) const {
const Field *field = get(name);
if (!field) return defValue;

View file

@ -85,6 +85,7 @@ public:
bool getBool(const std::string &name, bool defValue = false) const;
int getInt(const std::string &name, int defValue = 0) const;
uint32_t getUint(const std::string &name, uint32_t defValue = 0) const;
glm::vec3 getColor(const std::string &name, glm::vec3 defValue = glm::vec3(0.0f)) const;
float getFloat(const std::string &name, float defValue = 0.0f) const;
std::string getString(const std::string &name, std::string defValue = "") const;
glm::vec3 getVector(const std::string &name, glm::vec3 defValue = glm::vec3(0.0f)) const;

View file

@ -305,6 +305,13 @@ void ModelNodeSceneNode::drawSingle(bool shadowPass) {
uniforms.combined.general.waterAlpha = waterAlpha;
}
}
if (_sceneGraph->isFogEnabled() && _modelSceneNode->model()->isAffectedByFog()) {
uniforms.combined.featureMask |= UniformFeatureFlags::fog;
uniforms.combined.general.fogNear = _sceneGraph->fogNear();
uniforms.combined.general.fogFar = _sceneGraph->fogFar();
uniforms.combined.general.fogColor = glm::vec4(_sceneGraph->fogColor(), 1.0f);
}
}
Shaders::instance().activate(program, uniforms);

View file

@ -97,6 +97,21 @@ public:
// END Lights and shadows
// Fog
bool isFogEnabled() const { return _fogEnabled; }
float fogNear() const { return _fogNear; }
float fogFar() const { return _fogFar; }
const glm::vec3 &fogColor() const { return _fogColor; }
void setFogEnabled(bool enabled) { _fogEnabled = enabled; }
void setFogNear(float near) { _fogNear = near; }
void setFogFar(float far) { _fogFar = far; }
void setFogColor(glm::vec3 color) { _fogColor = std::move(color); }
// END Fog
private:
render::GraphicsOptions _opts;
@ -127,6 +142,15 @@ private:
// END Shadows
// Fog
bool _fogEnabled { false };
float _fogNear { 0.0f };
float _fogFar { 0.0f };
glm::vec3 _fogColor { 0.0f };
// END Fog
void refreshNodeLists();
void refreshFromSceneNode(const std::shared_ptr<SceneNode> &node);
void refreshShadowLight();