1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-08-11 17:51:04 +00:00

Visual Effects Vol. 1 (#14610)

This PR adds a variety of effects to enhance the visual experience.

    "soft" clouds look
    Tinted shadows
    Crude water reflections (sky and sun) and waves
    Translucent foliage
    Node specular highlights
    Adjusted fog color (more saturated where the fog is lighter)
    Minor changes to volumetric lighting (crudely simulates the effect of depth)

Co-authored-by: sfan5 <sfan5@live.de>
This commit is contained in:
GefullteTaubenbrust2 2024-09-24 20:14:27 +02:00 committed by GitHub
parent 4ac86db8e3
commit d8f1daac25
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
24 changed files with 356 additions and 53 deletions

View file

@ -137,6 +137,7 @@ struct ClientEvent
f32 density;
u32 color_bright;
u32 color_ambient;
u32 color_shadow;
f32 height;
f32 thickness;
f32 speed_x;

View file

@ -1209,11 +1209,22 @@ void ClientMap::renderMapShadows(video::IVideoDriver *driver,
// Render all mesh buffers in order
drawcall_count += draw_order.size();
bool translucent_foliage = g_settings->getBool("enable_translucent_foliage");
video::E_MATERIAL_TYPE leaves_material = video::EMT_SOLID;
// For translucent leaves, we want to use backface culling instead of frontface.
if (translucent_foliage) {
// this is the material leaves would use, compare to nodedef.cpp
auto* shdsrc = m_client->getShaderSource();
const u32 leaves_shader = shdsrc->getShader("nodes_shader", TILE_MATERIAL_WAVING_LEAVES, NDT_ALLFACES);
leaves_material = shdsrc->getShaderInfo(leaves_shader).material;
}
for (auto &descriptor : draw_order) {
if (!descriptor.m_reuse_material) {
// override some material properties
video::SMaterial local_material = descriptor.getMaterial();
local_material.MaterialType = material.MaterialType;
// do not override culling if the original material renders both back
// and front faces in solid mode (e.g. plantlike)
// Transparent plants would still render shadows only from one side,
@ -1222,6 +1233,11 @@ void ClientMap::renderMapShadows(video::IVideoDriver *driver,
local_material.BackfaceCulling = material.BackfaceCulling;
local_material.FrontfaceCulling = material.FrontfaceCulling;
}
if (local_material.MaterialType == leaves_material && translucent_foliage) {
local_material.BackfaceCulling = true;
local_material.FrontfaceCulling = false;
}
local_material.MaterialType = material.MaterialType;
local_material.BlendOperation = material.BlendOperation;
driver->setMaterial(local_material);
++material_swaps;

View file

@ -65,6 +65,8 @@ Clouds::Clouds(scene::ISceneManager* mgr, IShaderSource *ssrc,
readSettings();
g_settings->registerChangedCallback("enable_3d_clouds",
&cloud_3d_setting_changed, this);
g_settings->registerChangedCallback("soft_clouds",
&cloud_3d_setting_changed, this);
updateBox();
@ -76,6 +78,8 @@ Clouds::~Clouds()
{
g_settings->deregisterChangedCallback("enable_3d_clouds",
&cloud_3d_setting_changed, this);
g_settings->deregisterChangedCallback("soft_clouds",
&cloud_3d_setting_changed, this);
}
void Clouds::OnRegisterSceneNode()
@ -141,15 +145,18 @@ void Clouds::updateMesh()
// shader mixes the base color, set via ColorParam
c_top_f = c_side_1_f = c_side_2_f = c_bottom_f = video::SColorf(1.0f, 1.0f, 1.0f, 1.0f);
}
c_side_1_f.r *= 0.95f;
c_side_1_f.g *= 0.95f;
c_side_1_f.b *= 0.95f;
c_side_2_f.r *= 0.90f;
c_side_2_f.g *= 0.90f;
c_side_2_f.b *= 0.90f;
c_bottom_f.r *= 0.80f;
c_bottom_f.g *= 0.80f;
c_bottom_f.b *= 0.80f;
video::SColorf shadow = m_params.color_shadow;
c_side_1_f.r *= shadow.r * 0.25f + 0.75f;
c_side_1_f.g *= shadow.g * 0.25f + 0.75f;
c_side_1_f.b *= shadow.b * 0.25f + 0.75f;
c_side_2_f.r *= shadow.r * 0.5f + 0.5f;
c_side_2_f.g *= shadow.g * 0.5f + 0.5f;
c_side_2_f.b *= shadow.b * 0.5f + 0.5f;
c_bottom_f.r *= shadow.r;
c_bottom_f.g *= shadow.g;
c_bottom_f.b *= shadow.b;
video::SColor c_top = c_top_f.toSColor();
video::SColor c_side_1 = c_side_1_f.toSColor();
video::SColor c_side_2 = c_side_2_f.toSColor();
@ -221,13 +228,14 @@ void Clouds::updateMesh()
const f32 ry = is3D() ? m_params.thickness * BS : 0.0f;
const f32 rz = cloud_size / 2;
for(u32 i = 0; i < num_faces_to_draw; i++)
bool soft_clouds_enabled = g_settings->getBool("soft_clouds");
for (u32 i = 0; i < num_faces_to_draw; i++)
{
switch(i)
switch (i)
{
case 0: // top
for (video::S3DVertex &vertex : v) {
vertex.Normal.set(0,1,0);
for (video::S3DVertex& vertex : v) {
vertex.Normal.set(0, 1, 0);
}
v[0].Pos.set(-rx, ry,-rz);
v[1].Pos.set(-rx, ry, rz);
@ -237,12 +245,20 @@ void Clouds::updateMesh()
case 1: // back
if (INAREA(xi, zi - 1, m_cloud_radius_i)) {
u32 j = GETINDEX(xi, zi - 1, m_cloud_radius_i);
if(grid[j])
if (grid[j])
continue;
}
for (video::S3DVertex &vertex : v) {
vertex.Color = c_side_1;
vertex.Normal.set(0,0,-1);
if (soft_clouds_enabled) {
for (video::S3DVertex& vertex : v) {
vertex.Normal.set(0, 0, -1);
}
v[2].Color = c_bottom;
v[3].Color = c_bottom;
} else {
for (video::S3DVertex& vertex : v) {
vertex.Color = c_side_1;
vertex.Normal.set(0, 0, -1);
}
}
v[0].Pos.set(-rx, ry,-rz);
v[1].Pos.set( rx, ry,-rz);
@ -251,28 +267,45 @@ void Clouds::updateMesh()
break;
case 2: //right
if (INAREA(xi + 1, zi, m_cloud_radius_i)) {
u32 j = GETINDEX(xi+1, zi, m_cloud_radius_i);
if(grid[j])
u32 j = GETINDEX(xi + 1, zi, m_cloud_radius_i);
if (grid[j])
continue;
}
for (video::S3DVertex &vertex : v) {
vertex.Color = c_side_2;
vertex.Normal.set(1,0,0);
if (soft_clouds_enabled) {
for (video::S3DVertex& vertex : v) {
vertex.Normal.set(1, 0, 0);
}
v[2].Color = c_bottom;
v[3].Color = c_bottom;
}
v[0].Pos.set( rx, ry,-rz);
v[1].Pos.set( rx, ry, rz);
v[2].Pos.set( rx, 0, rz);
v[3].Pos.set( rx, 0,-rz);
else {
for (video::S3DVertex& vertex : v) {
vertex.Color = c_side_2;
vertex.Normal.set(1, 0, 0);
}
}
v[0].Pos.set(rx, ry,-rz);
v[1].Pos.set(rx, ry, rz);
v[2].Pos.set(rx, 0, rz);
v[3].Pos.set(rx, 0,-rz);
break;
case 3: // front
if (INAREA(xi, zi + 1, m_cloud_radius_i)) {
u32 j = GETINDEX(xi, zi + 1, m_cloud_radius_i);
if(grid[j])
if (grid[j])
continue;
}
for (video::S3DVertex &vertex : v) {
vertex.Color = c_side_1;
vertex.Normal.set(0,0,-1);
if (soft_clouds_enabled) {
for (video::S3DVertex& vertex : v) {
vertex.Normal.set(0, 0, -1);
}
v[2].Color = c_bottom;
v[3].Color = c_bottom;
} else {
for (video::S3DVertex& vertex : v) {
vertex.Color = c_side_1;
vertex.Normal.set(0, 0, -1);
}
}
v[0].Pos.set( rx, ry, rz);
v[1].Pos.set(-rx, ry, rz);
@ -280,14 +313,22 @@ void Clouds::updateMesh()
v[3].Pos.set( rx, 0, rz);
break;
case 4: // left
if (INAREA(xi-1, zi, m_cloud_radius_i)) {
u32 j = GETINDEX(xi-1, zi, m_cloud_radius_i);
if(grid[j])
if (INAREA(xi - 1, zi, m_cloud_radius_i)) {
u32 j = GETINDEX(xi - 1, zi, m_cloud_radius_i);
if (grid[j])
continue;
}
for (video::S3DVertex &vertex : v) {
vertex.Color = c_side_2;
vertex.Normal.set(-1,0,0);
if (soft_clouds_enabled) {
for (video::S3DVertex& vertex : v) {
vertex.Normal.set(-1, 0, 0);
}
v[2].Color = c_bottom;
v[3].Color = c_bottom;
} else {
for (video::S3DVertex& vertex : v) {
vertex.Color = c_side_2;
vertex.Normal.set(-1, 0, 0);
}
}
v[0].Pos.set(-rx, ry, rz);
v[1].Pos.set(-rx, ry,-rz);
@ -295,9 +336,9 @@ void Clouds::updateMesh()
v[3].Pos.set(-rx, 0, rz);
break;
case 5: // bottom
for (video::S3DVertex &vertex : v) {
for (video::S3DVertex& vertex : v) {
vertex.Color = c_bottom;
vertex.Normal.set(0,-1,0);
vertex.Normal.set(0, -1, 0);
}
v[0].Pos.set( rx, 0, rz);
v[1].Pos.set(-rx, 0, rz);

View file

@ -109,6 +109,14 @@ public:
m_params.color_ambient = color_ambient;
}
void setColorShadow(video::SColor color_shadow)
{
if (m_params.color_shadow == color_shadow)
return;
m_params.color_shadow = color_shadow;
invalidateMesh();
}
void setHeight(float height)
{
if (m_params.height == height)

View file

@ -83,7 +83,8 @@ MapblockMeshGenerator::MapblockMeshGenerator(MeshMakeData *input, MeshCollector
meshmanip(mm),
blockpos_nodes(data->m_blockpos * MAP_BLOCKSIZE),
enable_mesh_cache(g_settings->getBool("enable_mesh_cache") &&
!data->m_smooth_lighting) // Mesh cache is not supported with smooth lighting
!data->m_smooth_lighting), // Mesh cache is not supported with smooth lighting
smooth_liquids(g_settings->getBool("enable_water_reflections"))
{
}
@ -717,7 +718,7 @@ void MapblockMeshGenerator::drawLiquidSides()
if (data->m_smooth_lighting)
cur_node.color = blendLightColor(pos);
pos += cur_node.origin;
vertices[j] = video::S3DVertex(pos.X, pos.Y, pos.Z, 0, 0, 0, cur_node.color, vertex.u, v);
vertices[j] = video::S3DVertex(pos.X, pos.Y, pos.Z, face.dir.X, face.dir.Y, face.dir.Z, cur_node.color, vertex.u, v);
};
collector->append(cur_liquid.tile, vertices, 4, quad_indices, 6);
}
@ -740,6 +741,19 @@ void MapblockMeshGenerator::drawLiquidTop()
for (int i = 0; i < 4; i++) {
int u = corner_resolve[i][0];
int w = corner_resolve[i][1];
if (smooth_liquids) {
int x = vertices[i].Pos.X > 0;
int z = vertices[i].Pos.Z > 0;
f32 dx = 0.5f * (cur_liquid.neighbors[z][x].level - cur_liquid.neighbors[z][x + 1].level +
cur_liquid.neighbors[z + 1][x].level - cur_liquid.neighbors[z + 1][x + 1].level);
f32 dz = 0.5f * (cur_liquid.neighbors[z][x].level - cur_liquid.neighbors[z + 1][x].level +
cur_liquid.neighbors[z][x + 1].level - cur_liquid.neighbors[z + 1][x + 1].level);
vertices[i].Normal = v3f(dx, 1., dz).normalize();
}
vertices[i].Pos.Y += cur_liquid.corner_levels[w][u] * BS;
if (data->m_smooth_lighting)
vertices[i].Color = blendLightColor(vertices[i].Pos);
@ -779,6 +793,10 @@ void MapblockMeshGenerator::drawLiquidTop()
vertex.TCoords += tcoord_center;
vertex.TCoords += tcoord_translate;
if (!smooth_liquids) {
vertex.Normal = v3f(dx, 1., dz).normalize();
}
}
std::swap(vertices[0].TCoords, vertices[2].TCoords);

View file

@ -134,6 +134,7 @@ private:
f32 corner_levels[2][2];
};
LiquidData cur_liquid;
bool smooth_liquids = false;
void prepareLiquidNodeDrawing();
void getLiquidNeighborhood();

View file

@ -386,6 +386,8 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter
CachedPixelShaderSetting<float, 3> m_minimap_yaw{"yawVec"};
CachedPixelShaderSetting<float, 3> m_camera_offset_pixel{"cameraOffset"};
CachedVertexShaderSetting<float, 3> m_camera_offset_vertex{"cameraOffset"};
CachedPixelShaderSetting<float, 3> m_camera_position_pixel{ "cameraPosition" };
CachedVertexShaderSetting<float, 3> m_camera_position_vertex{ "cameraPosition" };
CachedPixelShaderSetting<SamplerLayer_t> m_texture0{"texture0"};
CachedPixelShaderSetting<SamplerLayer_t> m_texture1{"texture1"};
CachedPixelShaderSetting<SamplerLayer_t> m_texture2{"texture2"};
@ -492,6 +494,10 @@ public:
m_camera_offset_pixel.set(offset, services);
m_camera_offset_vertex.set(offset, services);
v3f camera_position = m_client->getCamera()->getPosition();
m_camera_position_pixel.set(camera_position, services);
m_camera_position_pixel.set(camera_position, services);
SamplerLayer_t tex_id;
tex_id = 0;
m_texture0.set(&tex_id, services);
@ -3184,6 +3190,7 @@ void Game::handleClientEvent_CloudParams(ClientEvent *event, CameraOrientation *
clouds->setDensity(event->cloud_params.density);
clouds->setColorBright(video::SColor(event->cloud_params.color_bright));
clouds->setColorAmbient(video::SColor(event->cloud_params.color_ambient));
clouds->setColorShadow(video::SColor(event->cloud_params.color_shadow));
clouds->setHeight(event->cloud_params.height);
clouds->setThickness(event->cloud_params.thickness);
clouds->setSpeed(v2f(event->cloud_params.speed_x, event->cloud_params.speed_y));
@ -4315,7 +4322,9 @@ void Game::updateShadows()
float timeoftheday = getWickedTimeOfDay(in_timeofday);
bool is_day = timeoftheday > 0.25 && timeoftheday < 0.75;
bool is_shadow_visible = is_day ? sky->getSunVisible() : sky->getMoonVisible();
shadow->setShadowIntensity(is_shadow_visible ? client->getEnv().getLocalPlayer()->getLighting().shadow_intensity : 0.0f);
const auto &lighting = client->getEnv().getLocalPlayer()->getLighting();
shadow->setShadowIntensity(is_shadow_visible ? lighting.shadow_intensity : 0.0f);
shadow->setShadowTint(lighting.shadow_tint);
timeoftheday = std::fmod(timeoftheday + 0.75f, 0.5f) + 0.25f;
const float offset_constant = 10000.0f;

View file

@ -689,6 +689,15 @@ ShaderInfo ShaderSource::generateShader(const std::string &name,
if (g_settings->getBool("shadow_poisson_filter"))
shaders_header << "#define POISSON_FILTER 1\n";
if (g_settings->getBool("enable_water_reflections"))
shaders_header << "#define ENABLE_WATER_REFLECTIONS 1\n";
if (g_settings->getBool("enable_translucent_foliage"))
shaders_header << "#define ENABLE_TRANSLUCENT_FOLIAGE 1\n";
if (g_settings->getBool("enable_node_specular"))
shaders_header << "#define ENABLE_NODE_SPECULAR 1\n";
s32 shadow_filter = g_settings->getS32("shadow_filters");
shaders_header << "#define SHADOW_FILTER " << shadow_filter << "\n";

View file

@ -94,9 +94,11 @@ public:
bool is_active() const { return m_shadows_enabled && shadowMapTextureFinal != nullptr; }
void setTimeOfDay(float isDay) { m_time_day = isDay; };
void setShadowIntensity(float shadow_intensity);
void setShadowTint(video::SColor shadow_tint) { m_shadow_tint = shadow_tint; }
s32 getShadowSamples() const { return m_shadow_samples; }
float getShadowStrength() const { return m_shadows_enabled ? m_shadow_strength : 0.0f; }
video::SColor getShadowTint() const { return m_shadow_tint; }
float getTimeOfDay() const { return m_time_day; }
f32 getPerspectiveBiasXY() { return m_perspective_bias_xy; }
@ -131,6 +133,7 @@ private:
std::vector<NodeToApply> m_shadow_node_array;
float m_shadow_strength;
video::SColor m_shadow_tint{ 255, 0, 0, 0 };
float m_shadow_strength_gamma;
float m_shadow_map_max_distance;
float m_shadow_map_texture_size;

View file

@ -40,6 +40,9 @@ void ShadowConstantSetter::onSetConstants(video::IMaterialRendererServices *serv
f32 ShadowStrength = shadow->getShadowStrength();
m_shadow_strength.set(&ShadowStrength, services);
video::SColor ShadowTint = shadow->getShadowTint();
m_shadow_tint.set(ShadowTint, services);
f32 timeOfDay = shadow->getTimeOfDay();
m_time_of_day.set(&timeOfDay, services);

View file

@ -31,6 +31,7 @@ class ShadowConstantSetter : public IShaderConstantSetter
CachedPixelShaderSetting<f32, 3> m_light_direction{"v_LightDirection"};
CachedPixelShaderSetting<f32> m_texture_res{"f_textureresolution"};
CachedPixelShaderSetting<f32> m_shadow_strength{"f_shadow_strength"};
CachedPixelShaderSetting<f32, 3> m_shadow_tint{ "shadow_tint" };
CachedPixelShaderSetting<f32> m_time_of_day{"f_timeofday"};
CachedPixelShaderSetting<f32> m_shadowfar{"f_shadowfar"};
CachedPixelShaderSetting<f32, 4> m_camera_pos{"CameraPos"};

View file

@ -275,6 +275,7 @@ void set_default_settings()
settings->setDefault("view_bobbing_amount", "1.0");
settings->setDefault("fall_bobbing_amount", "0.03");
settings->setDefault("enable_3d_clouds", "true");
settings->setDefault("soft_clouds", "false");
settings->setDefault("cloud_radius", "12");
settings->setDefault("menu_clouds", "true");
settings->setDefault("translucent_liquids", "true");
@ -335,6 +336,9 @@ void set_default_settings()
settings->setDefault("bloom_intensity", "0.05");
settings->setDefault("bloom_radius", "1");
settings->setDefault("enable_volumetric_lighting", "false");
settings->setDefault("enable_water_reflections", "false");
settings->setDefault("enable_translucent_foliage", "false");
settings->setDefault("enable_node_specular", "false");
// Effects Shadows
settings->setDefault("enable_dynamic_shadows", "false");

View file

@ -18,7 +18,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
*/
#pragma once
#include "SColor.h"
using namespace irr;
/**
* Parameters for automatic exposure compensation
@ -54,4 +56,5 @@ struct Lighting
float shadow_intensity {0.0f};
float saturation {1.0f};
float volumetric_light_strength {0.0f};
video::SColor shadow_tint;
};

View file

@ -1476,6 +1476,7 @@ void Client::handleCommand_CloudParams(NetworkPacket* pkt)
f32 density;
video::SColor color_bright;
video::SColor color_ambient;
video::SColor color_shadow = video::SColor(255, 204, 204, 204);
f32 height;
f32 thickness;
v2f speed;
@ -1483,6 +1484,10 @@ void Client::handleCommand_CloudParams(NetworkPacket* pkt)
*pkt >> density >> color_bright >> color_ambient
>> height >> thickness >> speed;
if (pkt->getRemainingBytes() >= 4) {
*pkt >> color_shadow;
}
ClientEvent *event = new ClientEvent();
event->type = CE_CLOUD_PARAMS;
event->cloud_params.density = density;
@ -1491,6 +1496,7 @@ void Client::handleCommand_CloudParams(NetworkPacket* pkt)
// we avoid using new() and delete() for no good reason
event->cloud_params.color_bright = color_bright.color;
event->cloud_params.color_ambient = color_ambient.color;
event->cloud_params.color_shadow = color_shadow.color;
event->cloud_params.height = height;
event->cloud_params.thickness = thickness;
// same here: deconstruct to skip constructor
@ -1821,4 +1827,6 @@ void Client::handleCommand_SetLighting(NetworkPacket *pkt)
}
if (pkt->getRemainingBytes() >= 4)
*pkt >> lighting.volumetric_light_strength;
if (pkt->getRemainingBytes() >= 4)
*pkt >> lighting.shadow_tint;
}

View file

@ -229,10 +229,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
[bump for 5.9.1]
PROTOCOL VERSION 46:
Move default hotbar from client-side C++ to server-side builtin Lua
Add shadow tint to Lighting packets
Add shadow color to CloudParam packets
[scheduled bump for 5.10.0]
*/
#define LATEST_PROTOCOL_VERSION 46
#define LATEST_PROTOCOL_VERSION_STRING TOSTRING(LATEST_PROTOCOL_VERSION)
// Server's supported network protocol range
@ -1176,4 +1179,4 @@ enum InteractAction : u8
INTERACT_PLACE, // 3: place block or item (to abovesurface)
INTERACT_USE, // 4: use item
INTERACT_ACTIVATE // 5: rightclick air ("activate")
};
};

View file

@ -2448,6 +2448,10 @@ int ObjectRef::l_set_clouds(lua_State *L)
if (!lua_isnil(L, -1))
read_color(L, -1, &cloud_params.color_ambient);
lua_pop(L, 1);
lua_getfield(L, 2, "shadow");
if (!lua_isnil(L, -1))
read_color(L, -1, &cloud_params.color_shadow);
lua_pop(L, 1);
cloud_params.height = getfloatfield_default(L, 2, "height", cloud_params.height);
cloud_params.thickness = getfloatfield_default(L, 2, "thickness", cloud_params.thickness);
@ -2483,6 +2487,8 @@ int ObjectRef::l_get_clouds(lua_State *L)
lua_setfield(L, -2, "color");
push_ARGB8(L, cloud_params.color_ambient);
lua_setfield(L, -2, "ambient");
push_ARGB8(L, cloud_params.color_shadow);
lua_setfield(L, -2, "shadow");
lua_pushnumber(L, cloud_params.height);
lua_setfield(L, -2, "height");
lua_pushnumber(L, cloud_params.thickness);
@ -2611,6 +2617,8 @@ int ObjectRef::l_set_lighting(lua_State *L)
lua_getfield(L, 2, "shadows");
if (lua_istable(L, -1)) {
getfloatfield(L, -1, "intensity", lighting.shadow_intensity);
lua_getfield(L, -1, "tint");
read_color(L, -1, &lighting.shadow_tint);
}
lua_pop(L, 1); // shadows
@ -2654,6 +2662,8 @@ int ObjectRef::l_get_lighting(lua_State *L)
lua_newtable(L); // "shadows"
lua_pushnumber(L, lighting.shadow_intensity);
lua_setfield(L, -2, "intensity");
push_ARGB8(L, lighting.shadow_tint);
lua_setfield(L, -2, "tint");
lua_setfield(L, -2, "shadows");
lua_pushnumber(L, lighting.saturation);
lua_setfield(L, -2, "saturation");

View file

@ -1843,7 +1843,7 @@ void Server::SendCloudParams(session_t peer_id, const CloudParams &params)
{
NetworkPacket pkt(TOCLIENT_CLOUD_PARAMS, 0, peer_id);
pkt << params.density << params.color_bright << params.color_ambient
<< params.height << params.thickness << params.speed;
<< params.height << params.thickness << params.speed << params.color_shadow;
Send(&pkt);
}
@ -1873,7 +1873,7 @@ void Server::SendSetLighting(session_t peer_id, const Lighting &lighting)
<< lighting.exposure.speed_bright_dark
<< lighting.exposure.center_weight_power;
pkt << lighting.volumetric_light_strength;
pkt << lighting.volumetric_light_strength << lighting.shadow_tint;
Send(&pkt);
}

View file

@ -81,6 +81,7 @@ struct CloudParams
float density;
video::SColor color_bright;
video::SColor color_ambient;
video::SColor color_shadow;
float thickness;
float height;
v2f speed;
@ -160,6 +161,7 @@ public:
clouds.density = 0.4f;
clouds.color_bright = video::SColor(229, 240, 240, 255);
clouds.color_ambient = video::SColor(255, 0, 0, 0);
clouds.color_shadow = video::SColor(255, 204, 204, 204);
clouds.thickness = 16.0f;
clouds.height = 120;
clouds.speed = v2f(0.0f, -2.0f);