1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-09-30 19:22:14 +00:00
This commit is contained in:
Mircea Kitsune 2025-09-29 21:41:52 +03:00 committed by GitHub
commit 4f9def7adf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 109 additions and 84 deletions

View file

@ -8902,6 +8902,10 @@ 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.
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
@ -8910,9 +8914,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.
For `"skybox_back"` and `"skybox_front"` types, the textures should have an alpha channel.
* `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"` `"skybox_back"` `"skybox_front"` types, containing the following values:
* `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.

View file

@ -2831,46 +2831,29 @@ void Game::handleClientEvent_HudChange(ClientEvent *event, CameraOrientation *ca
void Game::handleClientEvent_SetSky(ClientEvent *event, CameraOrientation *cam)
{
sky->setVisible(false);
if (!event->set_sky->isTextured() && !event->set_sky->hasAlpha() && 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->hasAlpha());
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->hasAlpha())
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->textures.size() == 6) {
// Disable the dyanmic mesh skybox:
sky->setVisible(false);
// Set fog colors:
else
sky->setFallbackBgColor(event->set_sky->bgcolor);
// Set sunrise and sunset fog tinting:
// Use horizon tint for regular or skybox skies.
if (event->set_sky->isTextured() || event->set_sky->hasAlpha()) {
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);
} 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);
sky->setFallbackBgColor(event->set_sky->bgcolor);
// Disable directional sun/moon tinting on plain or invalid skyboxes.
sky->setHorizonTint(
event->set_sky->bgcolor,
event->set_sky->bgcolor,
@ -2878,14 +2861,21 @@ void Game::handleClientEvent_SetSky(ClientEvent *event, CameraOrientation *cam)
);
}
// Clear the old textures out in case we switch rendering type.
sky->clearSkyboxTextures();
// Add textures to skybox.
if (event->set_sky->isTextured()) {
for (int i = 0; i < 6; i++)
sky->addTextureToSkybox(event->set_sky->textures[i], i, texture_src, event->set_sky->hasAlpha());
}
// 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");

View file

@ -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();
@ -170,42 +209,13 @@ void Sky::render()
if (m_in_clouds)
return;
// Draw the six sided skybox,
if (m_sky_params.textures.size() == 6) {
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, solid or transparent background.
if (m_sky_params.type == "skybox" || m_sky_params.type == "skybox_back")
renderTextures(driver);
// Draw far cloudy fog thing blended with skycolor
if (m_visible) {
// Disabled when using a textured skybox to prevent clipping
if (m_visible && !m_sky_params.isTextured()) {
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 +278,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 && !m_sky_params.isTextured()) {
driver->setMaterial(m_materials[1]);
for (u32 j = 0; j < 4; j++) {
@ -304,6 +314,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, transparent foreground.
if (m_sky_params.type == "skybox_front")
renderTextures(driver);
}
}
@ -872,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)
@ -882,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_SOLID;
m_materials[material_id+5].MaterialType = transparent ? video::EMT_TRANSPARENT_ALPHA_CHANNEL : video::EMT_SOLID;
}
float getWickedTimeOfDay(float time_of_day)

View file

@ -82,6 +82,7 @@ public:
const video::SColorf &getCloudColor() const { return m_cloudcolor_f; }
void setVisible(bool visible) { m_visible = visible; }
void setType(const std::string &type) { m_sky_params.type = type; }
// Set only from set_sky API
void setCloudsEnabled(bool clouds_enabled) { m_clouds_enabled = clouds_enabled; }
@ -105,7 +106,7 @@ public:
void setInClouds(bool clouds) { m_in_clouds = clouds; }
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; }
@ -124,6 +125,8 @@ public:
private:
aabb3f m_box{{0.0f, 0.0f, 0.0f}};
video::SMaterial m_materials[SKY_MATERIAL_COUNT];
void renderTextures(video::IVideoDriver *driver);
// How much sun & moon transition should affect horizon color
float m_horizon_blend()
{

View file

@ -1337,8 +1337,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", "skybox_back", "skybox_front" skies as color isn't kept:
if (skybox.hasAlpha()) {
skybox.sky_color = SkyboxDefaults::getSkyColorDefaults();
skybox.fog_tint_type = "default";
skybox.fog_moon_tint = video::SColor(255, 255, 255, 255);
@ -1378,7 +1378,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") {
if (skybox.isTextured()) {
u16 texture_count;
std::string texture;
*pkt >> texture_count;
@ -1386,7 +1386,8 @@ void Client::handleCommand_HudSetSky(NetworkPacket* pkt)
*pkt >> texture;
skybox.textures.emplace_back(texture);
}
} else if (skybox.type == "regular") {
}
if (skybox.hasAlpha()) {
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;

View file

@ -2082,7 +2082,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") {
if (lua_istable(L, -1) && sky_params.isTextured()) {
lua_pushnil(L);
while (lua_next(L, -2) != 0) {
// Key is at index -2 and value at index -1
@ -2176,7 +2176,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.hasAlpha()) {
sun_params.visible = true;
sun_params.sunrise_visible = true;
moon_params.visible = true;
@ -2198,7 +2198,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.isTextured() && sky_params.textures.size() != 6)
throw LuaError("Skybox expects 6 textures.");
sky_params.clouds = true;
@ -2217,7 +2217,7 @@ int ObjectRef::l_set_sky(lua_State *L)
static void push_sky_color(lua_State *L, const SkyboxParams &params)
{
lua_newtable(L);
if (params.type == "regular") {
if (params.hasAlpha()) {
push_ARGB8(L, params.sky_color.day_sky);
lua_setfield(L, -2, "day_sky");
push_ARGB8(L, params.sky_color.day_horizon);

View file

@ -1912,11 +1912,12 @@ void Server::SendSetSky(session_t peer_id, const SkyboxParams &params)
<< params.clouds << params.fog_sun_tint
<< params.fog_moon_tint << params.fog_tint_type;
if (params.type == "skybox") {
if (params.isTextured()) {
pkt << (u16) params.textures.size();
for (const std::string &texture : params.textures)
pkt << texture;
} else if (params.type == "regular") {
}
if (params.hasAlpha()) {
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;

View file

@ -37,6 +37,18 @@ 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
bool isTextured() const
{
return type == "skybox" || type == "skybox_back" || type == "skybox_front";
}
// Check whether transparency is used
bool hasAlpha() const
{
return type == "regular" || type == "skybox_back" || type == "skybox_front";
}
};
struct SunParams