From 6f17876e863a25f88ffaf05a26ef0b6da362229a Mon Sep 17 00:00:00 2001 From: MirceaKitsune Date: Tue, 22 Apr 2025 23:37:37 +0300 Subject: [PATCH 1/6] Support skybox textures with alpha channel --- doc/lua_api.md | 4 ++-- src/client/game.cpp | 9 ++++----- src/client/sky.cpp | 14 ++++++++------ src/network/clientpackethandler.cpp | 7 ++++--- src/script/lua_api/l_object.cpp | 4 ++-- src/server.cpp | 3 ++- 6 files changed, 22 insertions(+), 19 deletions(-) diff --git a/doc/lua_api.md b/doc/lua_api.md index 6943dec16..66312d189 100644 --- a/doc/lua_api.md +++ b/doc/lua_api.md @@ -8790,8 +8790,8 @@ child will follow movement and rotation of that bone. Some top and bottom textures expect to be aligned with the north face and will need to be rotated by -90 and 90 degrees, respectively, to fit the eastward orientation. * `clouds`: Boolean for whether clouds appear. (default: `true`) - * `sky_color`: A table used in `"regular"` type only, containing the - following values (alpha is ignored): + * `sky_color`: A table used in `"regular"` and `"skybox"` types only. If used with the later, + the `textures` should have an alpha channel. Contains the following values (alpha is ignored): * `day_sky`: ColorSpec, for the top half of the sky during the day. (default: `#61b5f5`) * `day_horizon`: ColorSpec, for the bottom half of the sky during the day. diff --git a/src/client/game.cpp b/src/client/game.cpp index 08be9c809..8fa2ec48a 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -2866,11 +2866,10 @@ void Game::handleClientEvent_SetSky(ClientEvent *event, CameraOrientation *cam) ); } else if (event->set_sky->type == "skybox" && event->set_sky->textures.size() == 6) { - // Disable the dyanmic mesh skybox: - sky->setVisible(false); - // Set fog colors: - sky->setFallbackBgColor(event->set_sky->bgcolor); - // Set sunrise and sunset fog tinting: + // Shows the mesh skybox + sky->setVisible(true); + // Update mesh based skybox colours if applicable. + sky->setSkyColors(event->set_sky->sky_color); sky->setHorizonTint( event->set_sky->fog_sun_tint, event->set_sky->fog_moon_tint, diff --git a/src/client/sky.cpp b/src/client/sky.cpp index 958ffa953..b553f2bb6 100644 --- a/src/client/sky.cpp +++ b/src/client/sky.cpp @@ -158,6 +158,7 @@ void Sky::render() const f32 t = 1.0f; const f32 o = 0.0f; + const bool has_tex = m_sky_params.textures.size() == 6; static const u16 indices[6] = {0, 1, 2, 0, 2, 3}; video::S3DVertex vertices[4]; @@ -171,7 +172,7 @@ void Sky::render() return; // Draw the six sided skybox, - if (m_sky_params.textures.size() == 6) { + if (has_tex) { for (u32 j = 5; j < 11; j++) { video::SColor c(255, 255, 255, 255); driver->setMaterial(m_materials[j]); @@ -205,7 +206,8 @@ void Sky::render() } // Draw far cloudy fog thing blended with skycolor - if (m_visible) { + // Disabled when using a textured skybox to prevent clipping + if (m_visible && !has_tex) { driver->setMaterial(m_materials[1]); for (u32 j = 0; j < 4; j++) { vertices[0] = video::S3DVertex(-1, -0.02, -1, 0, 0, 1, m_bgcolor, t, t); @@ -268,9 +270,9 @@ void Sky::render() if (m_moon_params.visible) draw_moon(driver, mooncolor, mooncolor2, wicked_time_of_day); - // Draw far cloudy fog thing below all horizons in front of sun, moon - // and stars. - if (m_visible) { + // Draw far cloudy fog thing below all horizons in front of sun, moon and stars. + // Disabled when using a textured skybox to prevent clipping + if (m_visible && !has_tex) { driver->setMaterial(m_materials[1]); for (u32 j = 0; j < 4; j++) { @@ -881,7 +883,7 @@ void Sky::addTextureToSkybox(const std::string &texture, int material_id, video::ITexture *result = tsrc->getTextureForMesh(texture); m_materials[material_id+5] = baseMaterial(); m_materials[material_id+5].setTexture(0, result); - m_materials[material_id+5].MaterialType = video::EMT_SOLID; + m_materials[material_id+5].MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; } float getWickedTimeOfDay(float time_of_day) diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index bb1930d96..777ac0406 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -1302,8 +1302,8 @@ void Client::handleCommand_HudSetSky(NetworkPacket* pkt) MoonParams moon = SkyboxDefaults::getMoonDefaults(); StarParams stars = SkyboxDefaults::getStarDefaults(); - // Fix for "regular" skies, as color isn't kept: - if (skybox.type == "regular") { + // Fix for "regular" and "skybox" skies, as color isn't kept: + if (skybox.type == "regular" || skybox.type == "skybox") { skybox.sky_color = SkyboxDefaults::getSkyColorDefaults(); skybox.fog_tint_type = "default"; skybox.fog_moon_tint = video::SColor(255, 255, 255, 255); @@ -1351,7 +1351,8 @@ void Client::handleCommand_HudSetSky(NetworkPacket* pkt) *pkt >> texture; skybox.textures.emplace_back(texture); } - } else if (skybox.type == "regular") { + } + if (skybox.type == "regular" || skybox.type == "skybox") { auto &c = skybox.sky_color; *pkt >> c.day_sky >> c.day_horizon >> c.dawn_sky >> c.dawn_horizon >> c.night_sky >> c.night_horizon >> c.indoors; diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index 816f42857..ec0eeb3d3 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -2140,7 +2140,7 @@ int ObjectRef::l_set_sky(lua_State *L) // Preserve old behavior of the sun, moon and stars // when using the old set_sky call. - if (sky_params.type == "regular") { + if (sky_params.type == "regular" || sky_params.type == "skybox") { sun_params.visible = true; sun_params.sunrise_visible = true; moon_params.visible = true; @@ -2181,7 +2181,7 @@ int ObjectRef::l_set_sky(lua_State *L) static void push_sky_color(lua_State *L, const SkyboxParams ¶ms) { lua_newtable(L); - if (params.type == "regular") { + if (params.type == "regular" || params.type == "skybox") { push_ARGB8(L, params.sky_color.day_sky); lua_setfield(L, -2, "day_sky"); push_ARGB8(L, params.sky_color.day_horizon); diff --git a/src/server.cpp b/src/server.cpp index 4fe2d3c4a..a7535cbe7 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1867,7 +1867,8 @@ void Server::SendSetSky(session_t peer_id, const SkyboxParams ¶ms) pkt << (u16) params.textures.size(); for (const std::string &texture : params.textures) pkt << texture; - } else if (params.type == "regular") { + } + if (params.type == "regular" || params.type == "skybox") { auto &c = params.sky_color; pkt << c.day_sky << c.day_horizon << c.dawn_sky << c.dawn_horizon << c.night_sky << c.night_horizon << c.indoors; From d4e0dfa5f66722f346e61ad70c29385f764b6112 Mon Sep 17 00:00:00 2001 From: MirceaKitsune Date: Wed, 23 Apr 2025 01:28:04 +0300 Subject: [PATCH 2/6] Support drawing the skybox in front of the default sky --- doc/lua_api.md | 3 ++ src/client/game.cpp | 1 + src/client/sky.cpp | 79 +++++++++++++++++------------ src/client/sky.h | 3 ++ src/network/clientpackethandler.cpp | 3 +- src/script/lua_api/l_object.cpp | 3 ++ src/server.cpp | 3 +- src/skyparams.h | 2 + 8 files changed, 62 insertions(+), 35 deletions(-) diff --git a/doc/lua_api.md b/doc/lua_api.md index 66312d189..2d8e345c8 100644 --- a/doc/lua_api.md +++ b/doc/lua_api.md @@ -8789,6 +8789,9 @@ child will follow movement and rotation of that bone. bottom texture and the bottom edge of the top texture touch the east face). Some top and bottom textures expect to be aligned with the north face and will need to be rotated by -90 and 90 degrees, respectively, to fit the eastward orientation. + * `textures_front`: Used by the `"skybox"` type. Enable to draw a skybox with an alpha channel in + front of the sun / moon / stars rather than behind them. The sky color will always be shown + behind the alpha channel (default: `false`) * `clouds`: Boolean for whether clouds appear. (default: `true`) * `sky_color`: A table used in `"regular"` and `"skybox"` types only. If used with the later, the `textures` should have an alpha channel. Contains the following values (alpha is ignored): diff --git a/src/client/game.cpp b/src/client/game.cpp index 8fa2ec48a..5143bbfcd 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -2850,6 +2850,7 @@ void Game::handleClientEvent_SetSky(ClientEvent *event, CameraOrientation *cam) sky->setVisible(false); // Whether clouds are visible in front of a custom skybox. sky->setCloudsEnabled(event->set_sky->clouds); + sky->setTexturesFront(event->set_sky->textures_front); // Clear the old textures out in case we switch rendering type. sky->clearSkyboxTextures(); diff --git a/src/client/sky.cpp b/src/client/sky.cpp index b553f2bb6..3a12d1baa 100644 --- a/src/client/sky.cpp +++ b/src/client/sky.cpp @@ -93,6 +93,45 @@ void Sky::OnRegisterSceneNode() scene::ISceneNode::OnRegisterSceneNode(); } +void Sky::renderTextures(video::IVideoDriver *driver) +{ + const f32 t = 1.0f; + const f32 o = 0.0f; + static const u16 indices[6] = {0, 1, 2, 0, 2, 3}; + video::S3DVertex vertices[4]; + + for (u32 j = 5; j < 11; j++) { + video::SColor c(255, 255, 255, 255); + driver->setMaterial(m_materials[j]); + // Use 1.05 rather than 1.0 to avoid colliding with the + // sun, moon and stars, as this is a background skybox. + vertices[0] = video::S3DVertex(-1.05, -1.05, -1.05, 0, 0, 1, c, t, t); + vertices[1] = video::S3DVertex( 1.05, -1.05, -1.05, 0, 0, 1, c, o, t); + vertices[2] = video::S3DVertex( 1.05, 1.05, -1.05, 0, 0, 1, c, o, o); + vertices[3] = video::S3DVertex(-1.05, 1.05, -1.05, 0, 0, 1, c, t, o); + for (video::S3DVertex &vertex : vertices) { + if (j == 5) { // Top texture + vertex.Pos.rotateYZBy(90); + vertex.Pos.rotateXZBy(90); + } else if (j == 6) { // Bottom texture + vertex.Pos.rotateYZBy(-90); + vertex.Pos.rotateXZBy(90); + } else if (j == 7) { // Left texture + vertex.Pos.rotateXZBy(90); + } else if (j == 8) { // Right texture + vertex.Pos.rotateXZBy(-90); + } else if (j == 9) { // Front texture, do nothing + // Irrlicht doesn't like it when vertexes are left + // alone and not rotated for some reason. + vertex.Pos.rotateXZBy(0); + } else {// Back texture + vertex.Pos.rotateXZBy(180); + } + } + driver->drawIndexedTriangleList(&vertices[0], 4, indices, 2); + } +} + void Sky::render() { video::IVideoDriver *driver = SceneManager->getVideoDriver(); @@ -171,39 +210,9 @@ void Sky::render() if (m_in_clouds) return; - // Draw the six sided skybox, - if (has_tex) { - for (u32 j = 5; j < 11; j++) { - video::SColor c(255, 255, 255, 255); - driver->setMaterial(m_materials[j]); - // Use 1.05 rather than 1.0 to avoid colliding with the - // sun, moon and stars, as this is a background skybox. - vertices[0] = video::S3DVertex(-1.05, -1.05, -1.05, 0, 0, 1, c, t, t); - vertices[1] = video::S3DVertex( 1.05, -1.05, -1.05, 0, 0, 1, c, o, t); - vertices[2] = video::S3DVertex( 1.05, 1.05, -1.05, 0, 0, 1, c, o, o); - vertices[3] = video::S3DVertex(-1.05, 1.05, -1.05, 0, 0, 1, c, t, o); - for (video::S3DVertex &vertex : vertices) { - if (j == 5) { // Top texture - vertex.Pos.rotateYZBy(90); - vertex.Pos.rotateXZBy(90); - } else if (j == 6) { // Bottom texture - vertex.Pos.rotateYZBy(-90); - vertex.Pos.rotateXZBy(90); - } else if (j == 7) { // Left texture - vertex.Pos.rotateXZBy(90); - } else if (j == 8) { // Right texture - vertex.Pos.rotateXZBy(-90); - } else if (j == 9) { // Front texture, do nothing - // Irrlicht doesn't like it when vertexes are left - // alone and not rotated for some reason. - vertex.Pos.rotateXZBy(0); - } else {// Back texture - vertex.Pos.rotateXZBy(180); - } - } - driver->drawIndexedTriangleList(&vertices[0], 4, indices, 2); - } - } + // Draw the six sided skybox, in the background. + if(has_tex && !m_textures_front) + renderTextures(driver); // Draw far cloudy fog thing blended with skycolor // Disabled when using a textured skybox to prevent clipping @@ -306,6 +315,10 @@ void Sky::render() vertices[3] = video::S3DVertex(-1, -1.0, 1, 0, 1, 0, c, t, o); driver->drawIndexedTriangleList(&vertices[0], 4, indices, 2); } + + // Draw the six sided skybox, in the foreground. + if(has_tex && m_textures_front) + renderTextures(driver); } } diff --git a/src/client/sky.h b/src/client/sky.h index 7d3cdba3d..cbf065b38 100644 --- a/src/client/sky.h +++ b/src/client/sky.h @@ -33,6 +33,7 @@ public: virtual void OnRegisterSceneNode(); //! renders the node. + virtual void renderTextures(video::IVideoDriver *driver); virtual void render(); virtual const aabb3f &getBoundingBox() const { return m_box; } @@ -103,6 +104,7 @@ public: void setHorizonTint(video::SColor sun_tint, video::SColor moon_tint, const std::string &use_sun_tint); void setInClouds(bool clouds) { m_in_clouds = clouds; } + void setTexturesFront(bool textures_front) { m_textures_front = textures_front; } void clearSkyboxTextures() { m_sky_params.textures.clear(); } void addTextureToSkybox(const std::string &texture, int material_id, ITextureSource *tsrc); @@ -174,6 +176,7 @@ private: bool m_clouds_enabled = true; // Initialised to true, reset only by set_sky API bool m_directional_colored_fog; bool m_in_clouds = true; // Prevent duplicating bools to remember old values + bool m_textures_front = false; // Whether textures are rendered behind the default sky video::SColorf m_bgcolor_bright_f = video::SColorf(1.0f, 1.0f, 1.0f, 1.0f); video::SColorf m_skycolor_bright_f = video::SColorf(1.0f, 1.0f, 1.0f, 1.0f); diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index 777ac0406..9d3a504ab 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -1295,6 +1295,7 @@ void Client::handleCommand_HudSetSky(NetworkPacket* pkt) for (size_t i = 0; i < count; i++) skybox.textures.emplace_back(deSerializeString16(is)); + skybox.textures_front = false; skybox.clouds = readU8(is) != 0; // Use default skybox settings: @@ -1340,7 +1341,7 @@ void Client::handleCommand_HudSetSky(NetworkPacket* pkt) SkyboxParams skybox; - *pkt >> skybox.bgcolor >> skybox.type >> skybox.clouds >> + *pkt >> skybox.bgcolor >> skybox.type >> skybox.textures_front >> skybox.clouds >> skybox.fog_sun_tint >> skybox.fog_moon_tint >> skybox.fog_tint_type; if (skybox.type == "skybox") { diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index ec0eeb3d3..ebf7b27d6 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -2061,6 +2061,7 @@ int ObjectRef::l_set_sky(lua_State *L) if (sky_params.textures.size() != 6 && !sky_params.textures.empty()) throw LuaError("Skybox expects 6 textures!"); + sky_params.textures_front = getboolfield_default(L, 2, "textures_front", sky_params.textures_front); sky_params.clouds = getboolfield_default(L, 2, "clouds", sky_params.clouds); lua_getfield(L, 2, "sky_color"); @@ -2250,6 +2251,8 @@ int ObjectRef::l_get_sky(lua_State *L) lua_rawseti(L, -2, i++); } lua_setfield(L, -2, "textures"); + lua_pushboolean(L, skybox_params.textures_front); + lua_setfield(L, -2, "textures_front"); lua_pushboolean(L, skybox_params.clouds); lua_setfield(L, -2, "clouds"); diff --git a/src/server.cpp b/src/server.cpp index a7535cbe7..6a681acbf 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1857,10 +1857,11 @@ void Server::SendSetSky(session_t peer_id, const SkyboxParams ¶ms) for (const std::string& texture : params.textures) pkt << texture; + pkt << false; pkt << params.clouds; } else { // Handle current clients and future clients pkt << params.bgcolor << params.type - << params.clouds << params.fog_sun_tint + << params.textures_front << params.clouds << params.fog_sun_tint << params.fog_moon_tint << params.fog_tint_type; if (params.type == "skybox") { diff --git a/src/skyparams.h b/src/skyparams.h index c5cd574cd..84f74db84 100644 --- a/src/skyparams.h +++ b/src/skyparams.h @@ -29,6 +29,7 @@ struct SkyboxParams video::SColor bgcolor; std::string type; std::vector textures; + bool textures_front; bool clouds; SkyColor sky_color; video::SColor fog_sun_tint; @@ -89,6 +90,7 @@ public: SkyboxParams sky; sky.bgcolor = video::SColor(255, 255, 255, 255); sky.type = "regular"; + sky.textures_front = false; sky.clouds = true; sky.sky_color = getSkyColorDefaults(); sky.fog_sun_tint = video::SColor(255, 244, 125, 29); From ab3073e4252e0f7aef91b68ff95e076d306d9a2b Mon Sep 17 00:00:00 2001 From: MirceaKitsune Date: Wed, 23 Apr 2025 02:15:08 +0300 Subject: [PATCH 3/6] Transparency setting defaulting to previous behavior --- doc/lua_api.md | 7 ++++--- src/client/game.cpp | 19 +++++++++++++------ src/client/sky.cpp | 12 ++++++------ src/client/sky.h | 6 +++--- src/network/clientpackethandler.cpp | 4 ++-- src/script/lua_api/l_object.cpp | 10 +++++++--- src/server.cpp | 7 +++---- src/skyparams.h | 4 ++-- 8 files changed, 40 insertions(+), 29 deletions(-) diff --git a/doc/lua_api.md b/doc/lua_api.md index 2d8e345c8..e77410eaa 100644 --- a/doc/lua_api.md +++ b/doc/lua_api.md @@ -8789,9 +8789,10 @@ child will follow movement and rotation of that bone. bottom texture and the bottom edge of the top texture touch the east face). Some top and bottom textures expect to be aligned with the north face and will need to be rotated by -90 and 90 degrees, respectively, to fit the eastward orientation. - * `textures_front`: Used by the `"skybox"` type. Enable to draw a skybox with an alpha channel in - front of the sun / moon / stars rather than behind them. The sky color will always be shown - behind the alpha channel (default: `false`) + * `transparency`: Used by the `"skybox"` type. The type of transparency to use. (default: `"solid"`) + * `"solid"`: For textures without an alpha channel, `sky_color` is not used. + * `"transparent_back"`: Show stars / sun / moon over the alpha channel, `sky_color` is used. + * `"transparent_front"`: Show stars / sun / moon behind the alpha channel, `sky_color` is used. * `clouds`: Boolean for whether clouds appear. (default: `true`) * `sky_color`: A table used in `"regular"` and `"skybox"` types only. If used with the later, the `textures` should have an alpha channel. Contains the following values (alpha is ignored): diff --git a/src/client/game.cpp b/src/client/game.cpp index 5143bbfcd..0cfdfab12 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -2850,7 +2850,7 @@ void Game::handleClientEvent_SetSky(ClientEvent *event, CameraOrientation *cam) sky->setVisible(false); // Whether clouds are visible in front of a custom skybox. sky->setCloudsEnabled(event->set_sky->clouds); - sky->setTexturesFront(event->set_sky->textures_front); + sky->setTransparency(event->set_sky->transparency); // Clear the old textures out in case we switch rendering type. sky->clearSkyboxTextures(); @@ -2867,10 +2867,17 @@ void Game::handleClientEvent_SetSky(ClientEvent *event, CameraOrientation *cam) ); } else if (event->set_sky->type == "skybox" && event->set_sky->textures.size() == 6) { - // Shows the mesh skybox - sky->setVisible(true); - // Update mesh based skybox colours if applicable. - sky->setSkyColors(event->set_sky->sky_color); + const bool transparent = event->set_sky->transparency != "solid"; + + // Show the mesh and sky colors only if transparency is used. + if(transparent) { + sky->setVisible(true); + sky->setSkyColors(event->set_sky->sky_color); + } else { + sky->setVisible(false); + sky->setFallbackBgColor(event->set_sky->bgcolor); + } + // Set sunrise and sunset fog tinting: sky->setHorizonTint( event->set_sky->fog_sun_tint, event->set_sky->fog_moon_tint, @@ -2878,7 +2885,7 @@ void Game::handleClientEvent_SetSky(ClientEvent *event, CameraOrientation *cam) ); // Add textures to skybox. for (int i = 0; i < 6; i++) - sky->addTextureToSkybox(event->set_sky->textures[i], i, texture_src); + sky->addTextureToSkybox(event->set_sky->textures[i], i, texture_src, transparent); } else { // Handle everything else as plain color. if (event->set_sky->type != "plain") diff --git a/src/client/sky.cpp b/src/client/sky.cpp index 3a12d1baa..7a7652661 100644 --- a/src/client/sky.cpp +++ b/src/client/sky.cpp @@ -210,8 +210,8 @@ void Sky::render() if (m_in_clouds) return; - // Draw the six sided skybox, in the background. - if(has_tex && !m_textures_front) + // Draw the six sided skybox, solid or transparent background. + if(has_tex && (m_transparency == "solid" || m_transparency == "transparent_back")) renderTextures(driver); // Draw far cloudy fog thing blended with skycolor @@ -316,8 +316,8 @@ void Sky::render() driver->drawIndexedTriangleList(&vertices[0], 4, indices, 2); } - // Draw the six sided skybox, in the foreground. - if(has_tex && m_textures_front) + // Draw the six sided skybox, transparent foreground. + if(has_tex && m_transparency == "transparent_front") renderTextures(driver); } } @@ -886,7 +886,7 @@ void Sky::setHorizonTint(video::SColor sun_tint, video::SColor moon_tint, } void Sky::addTextureToSkybox(const std::string &texture, int material_id, - ITextureSource *tsrc) + ITextureSource *tsrc, bool transparent) { // Sanity check for more than six textures. if (material_id + 5 >= SKY_MATERIAL_COUNT) @@ -896,7 +896,7 @@ void Sky::addTextureToSkybox(const std::string &texture, int material_id, video::ITexture *result = tsrc->getTextureForMesh(texture); m_materials[material_id+5] = baseMaterial(); m_materials[material_id+5].setTexture(0, result); - m_materials[material_id+5].MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; + m_materials[material_id+5].MaterialType = transparent ? video::EMT_TRANSPARENT_ALPHA_CHANNEL : video::EMT_SOLID; } float getWickedTimeOfDay(float time_of_day) diff --git a/src/client/sky.h b/src/client/sky.h index cbf065b38..00eb29256 100644 --- a/src/client/sky.h +++ b/src/client/sky.h @@ -85,6 +85,7 @@ public: void setVisible(bool visible) { m_visible = visible; } // Set only from set_sky API + void setTransparency(std::string transparency) { m_transparency = transparency; } void setCloudsEnabled(bool clouds_enabled) { m_clouds_enabled = clouds_enabled; } void setFallbackBgColor(video::SColor fallback_bg_color) { @@ -104,10 +105,9 @@ public: void setHorizonTint(video::SColor sun_tint, video::SColor moon_tint, const std::string &use_sun_tint); void setInClouds(bool clouds) { m_in_clouds = clouds; } - void setTexturesFront(bool textures_front) { m_textures_front = textures_front; } void clearSkyboxTextures() { m_sky_params.textures.clear(); } void addTextureToSkybox(const std::string &texture, int material_id, - ITextureSource *tsrc); + ITextureSource *tsrc, bool transparent); // Note: the Sky class doesn't use these values. It just stores them. void setFogDistance(s16 fog_distance) { m_sky_params.fog_distance = fog_distance; } @@ -176,7 +176,7 @@ private: bool m_clouds_enabled = true; // Initialised to true, reset only by set_sky API bool m_directional_colored_fog; bool m_in_clouds = true; // Prevent duplicating bools to remember old values - bool m_textures_front = false; // Whether textures are rendered behind the default sky + std::string m_transparency = "solid"; // Type of transparency used video::SColorf m_bgcolor_bright_f = video::SColorf(1.0f, 1.0f, 1.0f, 1.0f); video::SColorf m_skycolor_bright_f = video::SColorf(1.0f, 1.0f, 1.0f, 1.0f); diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index 9d3a504ab..e9207d4b5 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -1290,12 +1290,12 @@ void Client::handleCommand_HudSetSky(NetworkPacket* pkt) SkyboxParams skybox; skybox.bgcolor = video::SColor(readARGB8(is)); skybox.type = std::string(deSerializeString16(is)); + skybox.transparency = std::string("solid"); u16 count = readU16(is); for (size_t i = 0; i < count; i++) skybox.textures.emplace_back(deSerializeString16(is)); - skybox.textures_front = false; skybox.clouds = readU8(is) != 0; // Use default skybox settings: @@ -1341,7 +1341,7 @@ void Client::handleCommand_HudSetSky(NetworkPacket* pkt) SkyboxParams skybox; - *pkt >> skybox.bgcolor >> skybox.type >> skybox.textures_front >> skybox.clouds >> + *pkt >> skybox.bgcolor >> skybox.type >> skybox.transparency >> skybox.clouds >> skybox.fog_sun_tint >> skybox.fog_moon_tint >> skybox.fog_tint_type; if (skybox.type == "skybox") { diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index ebf7b27d6..8c35c4212 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -2044,6 +2044,11 @@ int ObjectRef::l_set_sky(lua_State *L) sky_params.type = luaL_checkstring(L, -1); lua_pop(L, 1); + lua_getfield(L, 2, "transparency"); + if (!lua_isnil(L, -1)) + sky_params.transparency = luaL_checkstring(L, -1); + lua_pop(L, 1); + lua_getfield(L, 2, "textures"); sky_params.textures.clear(); if (lua_istable(L, -1) && sky_params.type == "skybox") { @@ -2061,7 +2066,6 @@ int ObjectRef::l_set_sky(lua_State *L) if (sky_params.textures.size() != 6 && !sky_params.textures.empty()) throw LuaError("Skybox expects 6 textures!"); - sky_params.textures_front = getboolfield_default(L, 2, "textures_front", sky_params.textures_front); sky_params.clouds = getboolfield_default(L, 2, "clouds", sky_params.clouds); lua_getfield(L, 2, "sky_color"); @@ -2239,6 +2243,8 @@ int ObjectRef::l_get_sky(lua_State *L) lua_setfield(L, -2, "base_color"); lua_pushlstring(L, skybox_params.type.c_str(), skybox_params.type.size()); lua_setfield(L, -2, "type"); + lua_pushlstring(L, skybox_params.transparency.c_str(), skybox_params.transparency.size()); + lua_setfield(L, -2, "transparency"); if (skybox_params.body_orbit_tilt != SkyboxParams::INVALID_SKYBOX_TILT) { lua_pushnumber(L, skybox_params.body_orbit_tilt); @@ -2251,8 +2257,6 @@ int ObjectRef::l_get_sky(lua_State *L) lua_rawseti(L, -2, i++); } lua_setfield(L, -2, "textures"); - lua_pushboolean(L, skybox_params.textures_front); - lua_setfield(L, -2, "textures_front"); lua_pushboolean(L, skybox_params.clouds); lua_setfield(L, -2, "clouds"); diff --git a/src/server.cpp b/src/server.cpp index 6a681acbf..49bd41661 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1852,16 +1852,15 @@ void Server::SendSetSky(session_t peer_id, const SkyboxParams ¶ms) // Handle prior clients here if (m_clients.getProtocolVersion(peer_id) < 39) { - pkt << params.bgcolor << params.type << (u16) params.textures.size(); + pkt << params.bgcolor << params.type << std::string("solid") << (u16) params.textures.size(); for (const std::string& texture : params.textures) pkt << texture; - pkt << false; pkt << params.clouds; } else { // Handle current clients and future clients - pkt << params.bgcolor << params.type - << params.textures_front << params.clouds << params.fog_sun_tint + pkt << params.bgcolor << params.type << params.transparency + << params.clouds << params.fog_sun_tint << params.fog_moon_tint << params.fog_tint_type; if (params.type == "skybox") { diff --git a/src/skyparams.h b/src/skyparams.h index 84f74db84..74e30a5be 100644 --- a/src/skyparams.h +++ b/src/skyparams.h @@ -28,8 +28,8 @@ struct SkyboxParams video::SColor bgcolor; std::string type; + std::string transparency; std::vector textures; - bool textures_front; bool clouds; SkyColor sky_color; video::SColor fog_sun_tint; @@ -90,7 +90,7 @@ public: SkyboxParams sky; sky.bgcolor = video::SColor(255, 255, 255, 255); sky.type = "regular"; - sky.textures_front = false; + sky.transparency = "solid"; sky.clouds = true; sky.sky_color = getSkyColorDefaults(); sky.fog_sun_tint = video::SColor(255, 244, 125, 29); From de5328c851e0eca38ef82ad3ee6893d15f4ac08e Mon Sep 17 00:00:00 2001 From: MirceaKitsune Date: Wed, 23 Apr 2025 22:53:42 +0300 Subject: [PATCH 4/6] Convert transparency flag to skybox types --- doc/lua_api.md | 10 ++++------ src/client/game.cpp | 9 ++++----- src/client/sky.cpp | 4 ++-- src/client/sky.h | 4 ++-- src/network/clientpackethandler.cpp | 12 +++++++----- src/script/lua_api/l_object.cpp | 13 ++++--------- src/server.cpp | 8 +++++--- src/skyparams.h | 2 -- 8 files changed, 28 insertions(+), 34 deletions(-) diff --git a/doc/lua_api.md b/doc/lua_api.md index e77410eaa..f625f757c 100644 --- a/doc/lua_api.md +++ b/doc/lua_api.md @@ -8781,6 +8781,8 @@ child will follow movement and rotation of that bone. * `type`: Available types: * `"regular"`: Uses 0 textures, `base_color` ignored * `"skybox"`: Uses 6 textures, `base_color` used as fog. + * `"skybox_back"`: Uses 6 textures, `sky_color` used as fog, stars / sun / moon in foreground. + * `"skybox_front"`: Uses 6 textures, `sky_color` used as fog, stars / sun / moon in background. * `"plain"`: Uses 0 textures, `base_color` used as both fog and sky. (default: `"regular"`) * `textures`: A table containing up to six textures in the following @@ -8789,13 +8791,9 @@ child will follow movement and rotation of that bone. bottom texture and the bottom edge of the top texture touch the east face). Some top and bottom textures expect to be aligned with the north face and will need to be rotated by -90 and 90 degrees, respectively, to fit the eastward orientation. - * `transparency`: Used by the `"skybox"` type. The type of transparency to use. (default: `"solid"`) - * `"solid"`: For textures without an alpha channel, `sky_color` is not used. - * `"transparent_back"`: Show stars / sun / moon over the alpha channel, `sky_color` is used. - * `"transparent_front"`: Show stars / sun / moon behind the alpha channel, `sky_color` is used. * `clouds`: Boolean for whether clouds appear. (default: `true`) - * `sky_color`: A table used in `"regular"` and `"skybox"` types only. If used with the later, - the `textures` should have an alpha channel. Contains the following values (alpha is ignored): + * `sky_color`: A table used in `"regular"`, `"skybox_back"`, `"skybox_front"` types only. For a skybox + the `textures` should have an alpha channel. Contains the following values (alpha is ignored): * `day_sky`: ColorSpec, for the top half of the sky during the day. (default: `#61b5f5`) * `day_horizon`: ColorSpec, for the bottom half of the sky during the day. diff --git a/src/client/game.cpp b/src/client/game.cpp index 0cfdfab12..b16ba9db8 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -2848,9 +2848,9 @@ void Game::handleClientEvent_HudChange(ClientEvent *event, CameraOrientation *ca void Game::handleClientEvent_SetSky(ClientEvent *event, CameraOrientation *cam) { sky->setVisible(false); + sky->setType(event->set_sky->type); // Whether clouds are visible in front of a custom skybox. sky->setCloudsEnabled(event->set_sky->clouds); - sky->setTransparency(event->set_sky->transparency); // Clear the old textures out in case we switch rendering type. sky->clearSkyboxTextures(); @@ -2865,11 +2865,10 @@ void Game::handleClientEvent_SetSky(ClientEvent *event, CameraOrientation *cam) event->set_sky->fog_moon_tint, event->set_sky->fog_tint_type ); - } else if (event->set_sky->type == "skybox" && - event->set_sky->textures.size() == 6) { - const bool transparent = event->set_sky->transparency != "solid"; - + } else if ((event->set_sky->type == "skybox" || event->set_sky->type == "skybox_back" || + event->set_sky->type == "skybox_front") && event->set_sky->textures.size() == 6) { // Show the mesh and sky colors only if transparency is used. + const bool transparent = event->set_sky->type == "skybox_back" || event->set_sky->type == "skybox_front"; if(transparent) { sky->setVisible(true); sky->setSkyColors(event->set_sky->sky_color); diff --git a/src/client/sky.cpp b/src/client/sky.cpp index 7a7652661..b4c589749 100644 --- a/src/client/sky.cpp +++ b/src/client/sky.cpp @@ -211,7 +211,7 @@ void Sky::render() return; // Draw the six sided skybox, solid or transparent background. - if(has_tex && (m_transparency == "solid" || m_transparency == "transparent_back")) + if(has_tex && (m_type == "skybox" || m_type == "skybox_back")) renderTextures(driver); // Draw far cloudy fog thing blended with skycolor @@ -317,7 +317,7 @@ void Sky::render() } // Draw the six sided skybox, transparent foreground. - if(has_tex && m_transparency == "transparent_front") + if(has_tex && m_type == "skybox_front") renderTextures(driver); } } diff --git a/src/client/sky.h b/src/client/sky.h index 00eb29256..0589ff50b 100644 --- a/src/client/sky.h +++ b/src/client/sky.h @@ -83,9 +83,9 @@ public: const video::SColorf &getCloudColor() const { return m_cloudcolor_f; } void setVisible(bool visible) { m_visible = visible; } + void setType(std::string type) { m_type = type; } // Set only from set_sky API - void setTransparency(std::string transparency) { m_transparency = transparency; } void setCloudsEnabled(bool clouds_enabled) { m_clouds_enabled = clouds_enabled; } void setFallbackBgColor(video::SColor fallback_bg_color) { @@ -164,6 +164,7 @@ private: } bool m_visible = true; + std::string m_type = "regular"; // Used when m_visible=false video::SColor m_fallback_bg_color = video::SColor(255, 255, 255, 255); bool m_first_update = true; // Set before the sky is updated for the first time @@ -176,7 +177,6 @@ private: bool m_clouds_enabled = true; // Initialised to true, reset only by set_sky API bool m_directional_colored_fog; bool m_in_clouds = true; // Prevent duplicating bools to remember old values - std::string m_transparency = "solid"; // Type of transparency used video::SColorf m_bgcolor_bright_f = video::SColorf(1.0f, 1.0f, 1.0f, 1.0f); video::SColorf m_skycolor_bright_f = video::SColorf(1.0f, 1.0f, 1.0f, 1.0f); diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index e9207d4b5..3f5115ed9 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -1290,7 +1290,6 @@ void Client::handleCommand_HudSetSky(NetworkPacket* pkt) SkyboxParams skybox; skybox.bgcolor = video::SColor(readARGB8(is)); skybox.type = std::string(deSerializeString16(is)); - skybox.transparency = std::string("solid"); u16 count = readU16(is); for (size_t i = 0; i < count; i++) @@ -1304,7 +1303,8 @@ void Client::handleCommand_HudSetSky(NetworkPacket* pkt) StarParams stars = SkyboxDefaults::getStarDefaults(); // Fix for "regular" and "skybox" skies, as color isn't kept: - if (skybox.type == "regular" || skybox.type == "skybox") { + if (skybox.type == "regular" || skybox.type == "skybox" || + skybox.type == "skybox_back" || skybox.type == "skybox_front") { skybox.sky_color = SkyboxDefaults::getSkyColorDefaults(); skybox.fog_tint_type = "default"; skybox.fog_moon_tint = video::SColor(255, 255, 255, 255); @@ -1341,10 +1341,11 @@ void Client::handleCommand_HudSetSky(NetworkPacket* pkt) SkyboxParams skybox; - *pkt >> skybox.bgcolor >> skybox.type >> skybox.transparency >> skybox.clouds >> + *pkt >> skybox.bgcolor >> skybox.type >> skybox.clouds >> skybox.fog_sun_tint >> skybox.fog_moon_tint >> skybox.fog_tint_type; - if (skybox.type == "skybox") { + if (skybox.type == "skybox" || + skybox.type == "skybox_back" || skybox.type == "skybox_front") { u16 texture_count; std::string texture; *pkt >> texture_count; @@ -1353,7 +1354,8 @@ void Client::handleCommand_HudSetSky(NetworkPacket* pkt) skybox.textures.emplace_back(texture); } } - if (skybox.type == "regular" || skybox.type == "skybox") { + if (skybox.type == "regular" || skybox.type == "skybox" || + skybox.type == "skybox_back" || skybox.type == "skybox_front") { auto &c = skybox.sky_color; *pkt >> c.day_sky >> c.day_horizon >> c.dawn_sky >> c.dawn_horizon >> c.night_sky >> c.night_horizon >> c.indoors; diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index 8c35c4212..09b234a6a 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -2044,14 +2044,10 @@ int ObjectRef::l_set_sky(lua_State *L) sky_params.type = luaL_checkstring(L, -1); lua_pop(L, 1); - lua_getfield(L, 2, "transparency"); - if (!lua_isnil(L, -1)) - sky_params.transparency = luaL_checkstring(L, -1); - lua_pop(L, 1); - lua_getfield(L, 2, "textures"); sky_params.textures.clear(); - if (lua_istable(L, -1) && sky_params.type == "skybox") { + if (lua_istable(L, -1) && (sky_params.type == "skybox" || + sky_params.type == "skybox_back" || sky_params.type == "skybox_front")) { lua_pushnil(L); while (lua_next(L, -2) != 0) { // Key is at index -2 and value at index -1 @@ -2186,7 +2182,8 @@ int ObjectRef::l_set_sky(lua_State *L) static void push_sky_color(lua_State *L, const SkyboxParams ¶ms) { lua_newtable(L); - if (params.type == "regular" || params.type == "skybox") { + if (params.type == "regular" || params.type == "skybox" || + params.type == "skybox_back" || params.type == "skybox_front") { push_ARGB8(L, params.sky_color.day_sky); lua_setfield(L, -2, "day_sky"); push_ARGB8(L, params.sky_color.day_horizon); @@ -2243,8 +2240,6 @@ int ObjectRef::l_get_sky(lua_State *L) lua_setfield(L, -2, "base_color"); lua_pushlstring(L, skybox_params.type.c_str(), skybox_params.type.size()); lua_setfield(L, -2, "type"); - lua_pushlstring(L, skybox_params.transparency.c_str(), skybox_params.transparency.size()); - lua_setfield(L, -2, "transparency"); if (skybox_params.body_orbit_tilt != SkyboxParams::INVALID_SKYBOX_TILT) { lua_pushnumber(L, skybox_params.body_orbit_tilt); diff --git a/src/server.cpp b/src/server.cpp index 49bd41661..714173dcf 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1859,16 +1859,18 @@ void Server::SendSetSky(session_t peer_id, const SkyboxParams ¶ms) pkt << params.clouds; } else { // Handle current clients and future clients - pkt << params.bgcolor << params.type << params.transparency + pkt << params.bgcolor << params.type << params.clouds << params.fog_sun_tint << params.fog_moon_tint << params.fog_tint_type; - if (params.type == "skybox") { + if (params.type == "skybox" || + params.type == "skybox_back" || params.type == "skybox_front") { pkt << (u16) params.textures.size(); for (const std::string &texture : params.textures) pkt << texture; } - if (params.type == "regular" || params.type == "skybox") { + if (params.type == "regular" || params.type == "skybox" || + params.type == "skybox_back" || params.type == "skybox_front") { auto &c = params.sky_color; pkt << c.day_sky << c.day_horizon << c.dawn_sky << c.dawn_horizon << c.night_sky << c.night_horizon << c.indoors; diff --git a/src/skyparams.h b/src/skyparams.h index 74e30a5be..c5cd574cd 100644 --- a/src/skyparams.h +++ b/src/skyparams.h @@ -28,7 +28,6 @@ struct SkyboxParams video::SColor bgcolor; std::string type; - std::string transparency; std::vector textures; bool clouds; SkyColor sky_color; @@ -90,7 +89,6 @@ public: SkyboxParams sky; sky.bgcolor = video::SColor(255, 255, 255, 255); sky.type = "regular"; - sky.transparency = "solid"; sky.clouds = true; sky.sky_color = getSkyColorDefaults(); sky.fog_sun_tint = video::SColor(255, 244, 125, 29); From fcd65f0b99543cacf039047180e05bc8491acd29 Mon Sep 17 00:00:00 2001 From: MirceaKitsune Date: Wed, 23 Apr 2025 23:58:36 +0300 Subject: [PATCH 5/6] Fix type checks --- src/client/game.cpp | 2 +- src/network/clientpackethandler.cpp | 6 +++--- src/script/lua_api/l_object.cpp | 5 +++-- src/server.cpp | 4 ++-- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/client/game.cpp b/src/client/game.cpp index b16ba9db8..cc6fede16 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -2867,8 +2867,8 @@ void Game::handleClientEvent_SetSky(ClientEvent *event, CameraOrientation *cam) ); } else if ((event->set_sky->type == "skybox" || event->set_sky->type == "skybox_back" || event->set_sky->type == "skybox_front") && event->set_sky->textures.size() == 6) { - // Show the mesh and sky colors only if transparency is used. const bool transparent = event->set_sky->type == "skybox_back" || event->set_sky->type == "skybox_front"; + // Show the mesh and sky colors only if transparency is used. if(transparent) { sky->setVisible(true); sky->setSkyColors(event->set_sky->sky_color); diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index 3f5115ed9..5732b3ce2 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -1302,8 +1302,8 @@ void Client::handleCommand_HudSetSky(NetworkPacket* pkt) MoonParams moon = SkyboxDefaults::getMoonDefaults(); StarParams stars = SkyboxDefaults::getStarDefaults(); - // Fix for "regular" and "skybox" skies, as color isn't kept: - if (skybox.type == "regular" || skybox.type == "skybox" || + // Fix for "regular", "skybox_back", "skybox_front" skies as color isn't kept: + if (skybox.type == "regular" || skybox.type == "skybox_back" || skybox.type == "skybox_front") { skybox.sky_color = SkyboxDefaults::getSkyColorDefaults(); skybox.fog_tint_type = "default"; @@ -1354,7 +1354,7 @@ void Client::handleCommand_HudSetSky(NetworkPacket* pkt) skybox.textures.emplace_back(texture); } } - if (skybox.type == "regular" || skybox.type == "skybox" || + if (skybox.type == "regular" || skybox.type == "skybox_back" || skybox.type == "skybox_front") { auto &c = skybox.sky_color; *pkt >> c.day_sky >> c.day_horizon >> c.dawn_sky >> c.dawn_horizon diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index 09b234a6a..44fdfe203 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -2141,7 +2141,8 @@ int ObjectRef::l_set_sky(lua_State *L) // Preserve old behavior of the sun, moon and stars // when using the old set_sky call. - if (sky_params.type == "regular" || sky_params.type == "skybox") { + if (sky_params.type == "regular" || + sky_params.type == "skybox_back" || sky_params.type == "skybox_front") { sun_params.visible = true; sun_params.sunrise_visible = true; moon_params.visible = true; @@ -2182,7 +2183,7 @@ int ObjectRef::l_set_sky(lua_State *L) static void push_sky_color(lua_State *L, const SkyboxParams ¶ms) { lua_newtable(L); - if (params.type == "regular" || params.type == "skybox" || + if (params.type == "regular" || params.type == "skybox_back" || params.type == "skybox_front") { push_ARGB8(L, params.sky_color.day_sky); lua_setfield(L, -2, "day_sky"); diff --git a/src/server.cpp b/src/server.cpp index 714173dcf..90405fdce 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1852,7 +1852,7 @@ void Server::SendSetSky(session_t peer_id, const SkyboxParams ¶ms) // Handle prior clients here if (m_clients.getProtocolVersion(peer_id) < 39) { - pkt << params.bgcolor << params.type << std::string("solid") << (u16) params.textures.size(); + pkt << params.bgcolor << params.type << (u16) params.textures.size(); for (const std::string& texture : params.textures) pkt << texture; @@ -1869,7 +1869,7 @@ void Server::SendSetSky(session_t peer_id, const SkyboxParams ¶ms) for (const std::string &texture : params.textures) pkt << texture; } - if (params.type == "regular" || params.type == "skybox" || + if (params.type == "regular" || params.type == "skybox_back" || params.type == "skybox_front") { auto &c = params.sky_color; pkt << c.day_sky << c.day_horizon << c.dawn_sky << c.dawn_horizon From cc363a77d7e30f5a8aaeeeaecaa710b0765816d8 Mon Sep 17 00:00:00 2001 From: MirceaKitsune Date: Sun, 1 Jun 2025 00:28:48 +0300 Subject: [PATCH 6/6] Universal skybox type checks, simplify sky type application, formatting fixes --- doc/lua_api.md | 2 + src/client/game.cpp | 70 +++++++++++------------------ src/client/sky.cpp | 9 ++-- src/client/sky.h | 6 +-- src/network/clientpackethandler.cpp | 9 ++-- src/script/lua_api/l_object.cpp | 11 ++--- src/server.cpp | 6 +-- src/skyparams.h | 10 +++++ 8 files changed, 55 insertions(+), 68 deletions(-) diff --git a/doc/lua_api.md b/doc/lua_api.md index 74e5c7d44..a7219e202 100644 --- a/doc/lua_api.md +++ b/doc/lua_api.md @@ -8811,7 +8811,9 @@ child will follow movement and rotation of that bone. * `"regular"`: Uses 0 textures, `base_color` ignored * `"skybox"`: Uses 6 textures, `base_color` used as fog. * `"skybox_back"`: Uses 6 textures, `sky_color` used as fog, stars / sun / moon in foreground. + Note: Requires Luanti client version 5.13 or greater. * `"skybox_front"`: Uses 6 textures, `sky_color` used as fog, stars / sun / moon in background. + Note: Requires Luanti client version 5.13 or greater. * `"plain"`: Uses 0 textures, `base_color` used as both fog and sky. (default: `"regular"`) * `textures`: A table containing up to six textures in the following diff --git a/src/client/game.cpp b/src/client/game.cpp index 862ca50e6..fac6b4be4 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -2851,67 +2851,51 @@ void Game::handleClientEvent_HudChange(ClientEvent *event, CameraOrientation *ca void Game::handleClientEvent_SetSky(ClientEvent *event, CameraOrientation *cam) { - sky->setVisible(false); + // Handle invalid sky type. + if (!event->set_sky->isSkybox() && !event->set_sky->isTransparent() && event->set_sky->type != "plain") + infostream << "Unknown sky type: " << (event->set_sky->type) << std::endl; + + // Show the mesh sky if transparent. + sky->setVisible(event->set_sky->isTransparent()); sky->setType(event->set_sky->type); // Whether clouds are visible in front of a custom skybox. sky->setCloudsEnabled(event->set_sky->clouds); - // Clear the old textures out in case we switch rendering type. - sky->clearSkyboxTextures(); - // Handle according to type - if (event->set_sky->type == "regular") { - // Shows the mesh skybox - sky->setVisible(true); - // Update mesh based skybox colours if applicable. + // Show the mesh sky and use skybox colours if transparent. + if (event->set_sky->isTransparent()) sky->setSkyColors(event->set_sky->sky_color); - sky->setHorizonTint( - event->set_sky->fog_sun_tint, - event->set_sky->fog_moon_tint, - event->set_sky->fog_tint_type - ); - } else if ((event->set_sky->type == "skybox" || event->set_sky->type == "skybox_back" || - event->set_sky->type == "skybox_front") && event->set_sky->textures.size() == 6) { - const bool transparent = event->set_sky->type == "skybox_back" || event->set_sky->type == "skybox_front"; - // Show the mesh and sky colors only if transparency is used. - if(transparent) { - sky->setVisible(true); - sky->setSkyColors(event->set_sky->sky_color); - } else { - sky->setVisible(false); - sky->setFallbackBgColor(event->set_sky->bgcolor); - } - // Set sunrise and sunset fog tinting: - sky->setHorizonTint( - event->set_sky->fog_sun_tint, - event->set_sky->fog_moon_tint, - event->set_sky->fog_tint_type - ); - // Add textures to skybox. - for (int i = 0; i < 6; i++) - sky->addTextureToSkybox(event->set_sky->textures[i], i, texture_src, transparent); - } else { - // Handle everything else as plain color. - if (event->set_sky->type != "plain") - infostream << "Unknown sky type: " - << (event->set_sky->type) << std::endl; - sky->setVisible(false); + else sky->setFallbackBgColor(event->set_sky->bgcolor); - // Disable directional sun/moon tinting on plain or invalid skyboxes. + + // Use horizon tint for regular or skybox skies. + if (event->set_sky->isSkybox() || event->set_sky->isTransparent()) + sky->setHorizonTint( + event->set_sky->fog_sun_tint, + event->set_sky->fog_moon_tint, + event->set_sky->fog_tint_type + ); + else sky->setHorizonTint( event->set_sky->bgcolor, event->set_sky->bgcolor, "custom" ); + + // Clear the old textures out in case we switch rendering type. + sky->clearSkyboxTextures(); + // Add textures to skybox. + if(event->set_sky->isSkybox()) { + for (int i = 0; i < 6; i++) + sky->addTextureToSkybox(event->set_sky->textures[i], i, texture_src, event->set_sky->isTransparent()); } // Orbit Tilt: sky->setBodyOrbitTilt(event->set_sky->body_orbit_tilt); - // fog - // do not override a potentially smaller client setting. + // Fog, do not override a potentially smaller client setting. sky->setFogDistance(event->set_sky->fog_distance); - // if the fog distance is reset, switch back to the client's viewing_range + // If the fog distance is reset, switch back to the client's viewing_range if (event->set_sky->fog_distance < 0) draw_control->wanted_range = g_settings->getS16("viewing_range"); diff --git a/src/client/sky.cpp b/src/client/sky.cpp index b4c589749..f190f8210 100644 --- a/src/client/sky.cpp +++ b/src/client/sky.cpp @@ -197,7 +197,6 @@ void Sky::render() const f32 t = 1.0f; const f32 o = 0.0f; - const bool has_tex = m_sky_params.textures.size() == 6; static const u16 indices[6] = {0, 1, 2, 0, 2, 3}; video::S3DVertex vertices[4]; @@ -211,12 +210,12 @@ void Sky::render() return; // Draw the six sided skybox, solid or transparent background. - if(has_tex && (m_type == "skybox" || m_type == "skybox_back")) + if (m_sky_params.type == "skybox" || m_sky_params.type == "skybox_back") renderTextures(driver); // Draw far cloudy fog thing blended with skycolor // Disabled when using a textured skybox to prevent clipping - if (m_visible && !has_tex) { + if (m_visible && !m_sky_params.isSkybox()) { driver->setMaterial(m_materials[1]); for (u32 j = 0; j < 4; j++) { vertices[0] = video::S3DVertex(-1, -0.02, -1, 0, 0, 1, m_bgcolor, t, t); @@ -281,7 +280,7 @@ void Sky::render() // Draw far cloudy fog thing below all horizons in front of sun, moon and stars. // Disabled when using a textured skybox to prevent clipping - if (m_visible && !has_tex) { + if (m_visible && !m_sky_params.isSkybox()) { driver->setMaterial(m_materials[1]); for (u32 j = 0; j < 4; j++) { @@ -317,7 +316,7 @@ void Sky::render() } // Draw the six sided skybox, transparent foreground. - if(has_tex && m_type == "skybox_front") + if (m_sky_params.type == "skybox_front") renderTextures(driver); } } diff --git a/src/client/sky.h b/src/client/sky.h index 0589ff50b..f10cb203f 100644 --- a/src/client/sky.h +++ b/src/client/sky.h @@ -33,7 +33,6 @@ public: virtual void OnRegisterSceneNode(); //! renders the node. - virtual void renderTextures(video::IVideoDriver *driver); virtual void render(); virtual const aabb3f &getBoundingBox() const { return m_box; } @@ -83,7 +82,7 @@ public: const video::SColorf &getCloudColor() const { return m_cloudcolor_f; } void setVisible(bool visible) { m_visible = visible; } - void setType(std::string type) { m_type = type; } + void setType(std::string type) { m_sky_params.type = type; } // Set only from set_sky API void setCloudsEnabled(bool clouds_enabled) { m_clouds_enabled = clouds_enabled; } @@ -126,6 +125,8 @@ public: private: aabb3f m_box{{0.0f, 0.0f, 0.0f}}; video::SMaterial m_materials[SKY_MATERIAL_COUNT]; + virtual void renderTextures(video::IVideoDriver *driver); + // How much sun & moon transition should affect horizon color float m_horizon_blend() { @@ -164,7 +165,6 @@ private: } bool m_visible = true; - std::string m_type = "regular"; // Used when m_visible=false video::SColor m_fallback_bg_color = video::SColor(255, 255, 255, 255); bool m_first_update = true; // Set before the sky is updated for the first time diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index 5732b3ce2..773a6c61a 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -1303,8 +1303,7 @@ void Client::handleCommand_HudSetSky(NetworkPacket* pkt) StarParams stars = SkyboxDefaults::getStarDefaults(); // Fix for "regular", "skybox_back", "skybox_front" skies as color isn't kept: - if (skybox.type == "regular" || - skybox.type == "skybox_back" || skybox.type == "skybox_front") { + if (skybox.isTransparent()) { skybox.sky_color = SkyboxDefaults::getSkyColorDefaults(); skybox.fog_tint_type = "default"; skybox.fog_moon_tint = video::SColor(255, 255, 255, 255); @@ -1344,8 +1343,7 @@ void Client::handleCommand_HudSetSky(NetworkPacket* pkt) *pkt >> skybox.bgcolor >> skybox.type >> skybox.clouds >> skybox.fog_sun_tint >> skybox.fog_moon_tint >> skybox.fog_tint_type; - if (skybox.type == "skybox" || - skybox.type == "skybox_back" || skybox.type == "skybox_front") { + if (skybox.isSkybox()) { u16 texture_count; std::string texture; *pkt >> texture_count; @@ -1354,8 +1352,7 @@ void Client::handleCommand_HudSetSky(NetworkPacket* pkt) skybox.textures.emplace_back(texture); } } - if (skybox.type == "regular" || - skybox.type == "skybox_back" || skybox.type == "skybox_front") { + if (skybox.isTransparent()) { auto &c = skybox.sky_color; *pkt >> c.day_sky >> c.day_horizon >> c.dawn_sky >> c.dawn_horizon >> c.night_sky >> c.night_horizon >> c.indoors; diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index 16fdbe6a0..5267bd2e9 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -2065,8 +2065,7 @@ int ObjectRef::l_set_sky(lua_State *L) lua_getfield(L, 2, "textures"); sky_params.textures.clear(); - if (lua_istable(L, -1) && (sky_params.type == "skybox" || - sky_params.type == "skybox_back" || sky_params.type == "skybox_front")) { + if (lua_istable(L, -1) && sky_params.isSkybox()) { lua_pushnil(L); while (lua_next(L, -2) != 0) { // Key is at index -2 and value at index -1 @@ -2160,8 +2159,7 @@ int ObjectRef::l_set_sky(lua_State *L) // Preserve old behavior of the sun, moon and stars // when using the old set_sky call. - if (sky_params.type == "regular" || - sky_params.type == "skybox_back" || sky_params.type == "skybox_front") { + if (sky_params.isTransparent()) { sun_params.visible = true; sun_params.sunrise_visible = true; moon_params.visible = true; @@ -2183,7 +2181,7 @@ int ObjectRef::l_set_sky(lua_State *L) lua_pop(L, 1); } } - if (sky_params.type == "skybox" && sky_params.textures.size() != 6) + if (sky_params.isSkybox() && sky_params.textures.size() != 6) throw LuaError("Skybox expects 6 textures."); sky_params.clouds = true; @@ -2202,8 +2200,7 @@ int ObjectRef::l_set_sky(lua_State *L) static void push_sky_color(lua_State *L, const SkyboxParams ¶ms) { lua_newtable(L); - if (params.type == "regular" || - params.type == "skybox_back" || params.type == "skybox_front") { + if (params.isTransparent()) { push_ARGB8(L, params.sky_color.day_sky); lua_setfield(L, -2, "day_sky"); push_ARGB8(L, params.sky_color.day_horizon); diff --git a/src/server.cpp b/src/server.cpp index 6d8beed9f..4d30a6067 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1865,14 +1865,12 @@ void Server::SendSetSky(session_t peer_id, const SkyboxParams ¶ms) << params.clouds << params.fog_sun_tint << params.fog_moon_tint << params.fog_tint_type; - if (params.type == "skybox" || - params.type == "skybox_back" || params.type == "skybox_front") { + if (params.isSkybox()) { pkt << (u16) params.textures.size(); for (const std::string &texture : params.textures) pkt << texture; } - if (params.type == "regular" || - params.type == "skybox_back" || params.type == "skybox_front") { + if (params.isTransparent()) { auto &c = params.sky_color; pkt << c.day_sky << c.day_horizon << c.dawn_sky << c.dawn_horizon << c.night_sky << c.night_horizon << c.indoors; diff --git a/src/skyparams.h b/src/skyparams.h index c5cd574cd..16925a53f 100644 --- a/src/skyparams.h +++ b/src/skyparams.h @@ -38,6 +38,16 @@ struct SkyboxParams s16 fog_distance { -1 }; float fog_start { -1.0f }; video::SColor fog_color { 0 }; // override, only used if alpha > 0 + + // Check if this is a textured skybox and whether transparency is used + bool isSkybox() const + { + return type == "skybox" || type == "skybox_back" || type == "skybox_front"; + } + bool isTransparent() const + { + return type == "regular" || type == "skybox_back" || type == "skybox_front"; + } }; struct SunParams