Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: API to control shadow intensity from the game/mod #11944

Merged
merged 13 commits into from
Mar 26, 2022

Conversation

x2048
Copy link
Contributor

@x2048 x2048 commented Jan 8, 2022

This is a proposal to fix #11365 and #11972.

Specification

Lua API

A game should be able to control intensity of ambient shadows as part of a new set_lighting() API call

   local player = core.get_player_by_name("singleplayer")
   player:set_lighting( { shadows = { intensity = 0.5 } } )

set_lighting() API call will also be used for ambient brightness (#11499) and saturation (#11854). A matching get_lighting() API call will be used to retrieve the current values of the lighting and shadows parameters.

Network
set_lighting call translates into a new TOCLIENT_SET_LIGHTING network packet containing parameters packed one after another.

Client

Introduce new setting shadow_intensity_gamma to control the visual darkness of shadow intensity values to accommodate for differences between computer screens.

The formula is: actual_intensity = (input_intensity) * (1 / shadow_intensity_gamma).

When actual_intensity is zero:

  • Stop generating shadow mapping textures
  • Disable shadow mapping code in the shaders.

To do

This PR is Ready for Review.

Follow-up tasks:

  • Slight change to the Lua API, this

How to test

  • Enable dynamic shadows
  • Tune shadow_strength_gamma parameter
  • Launch a devtest world
  • /set_lighting 0 - shadows disappear, and FPS goes up
  • /set_lighting 0.5 - shadows appear at half intensity
  • /set_lighting 1 - shadows appear at full intensity (black)

Check games/devtest/mods/experimental/lighting.lua for the example code.

Note

Deleting and recreating the SM textures at runtime causes irrlicht errors and an eventual crash, won't fix in this PR.

Edit: spelling, add a todo

@x2048
Copy link
Contributor Author

x2048 commented Jan 9, 2022

The API is designed to be used with weather mods, allowing to change visual appearance of the sky and shadow intensity in one network packet.
I also considered tying shadow intensity to Sun and Moon, but that would require more complicated code by the modders.

@sfan5 sfan5 added @ Script API Discussion Issues meant for discussion of one or more proposals labels Jan 9, 2022
@rubenwardy rubenwardy requested a review from hecktest January 9, 2022 00:47
@erlehmann
Copy link
Contributor

I am highly sceptical that this belongs in player:set_sky.

What is the rationale to expand that function instead of making a player:set_shadows instead?

@kilbith
Copy link
Contributor

kilbith commented Jan 9, 2022

I'd put it inside player:set_shadows with the ability to change the orbit tilt as well.

@lhofhansl
Copy link
Contributor

lhofhansl commented Jan 9, 2022

The sky has the sun (or not), it makes sense to me to control it from there.

It does not feel like a player thing. (Two players at the same place would not want to see different shadows, no? It's an environmental thing.)

Update: Apparently I am tired. Sky is also per player. Still seems right to attach it to the thing that controls sun and clouds.

@lhofhansl
Copy link
Contributor

lhofhansl commented Jan 9, 2022

I'd put the lua command behind the debug (or some other) priv, though.

NM: It's devtest only.

@lhofhansl
Copy link
Contributor

lhofhansl commented Jan 9, 2022

Weird testing leftover at the top/left... In dynamicshadowsrender.cpp

screenshot_20220108_205102

@x2048
Copy link
Contributor Author

x2048 commented Jan 9, 2022

@erlehmann @kilbith I was considering a separate api call for controlling the shadows, and went with set_sky because both the color of the sky, clouds and shadow intensity are part of atmospheric ambience, and clouds are already in set_sky.

I see a much stronger use case for shadows to be changed with the weather (sky and clouds) than with, say moon phase or sun texture.

As for orbit tilt, that clearly belongs to the sky bodies (and it could even be made different for sun and moon)

@x2048
Copy link
Contributor Author

x2048 commented Jan 9, 2022

#11499 proposes player:set_ambient_light() API that would control the brightness and tint. We can also combine this with shadows and add more tweaks such as shadow color. Does everyone agree that would be a better strategy?

@celeron55
Copy link
Member

celeron55 commented Jan 9, 2022

I like this solution. The question for me really only is the API design.

@kilbith

I'd put it inside player:set_shadows with the ability to change the orbit tilt as well.

@x2048

#11499 proposes player:set_ambient_light() API that would control the brightness and tint. We can also combine this with shadows and add more tweaks such as shadow color. Does everyone agree that would be a better strategy?

player:set_lighting()?

@lhofhansl
Copy link
Contributor

As long as we are talking about shadows cast by the sun (or moon) I would still prefer this to be part of the sky API, it's also what is currently controlling the angle of the shadow.

@celeron55
Copy link
Member

celeron55 commented Jan 9, 2022

It's a matter of how you want to plan on grouping stuff in the future. set_sky() is fine to me.

@sfan5
Copy link
Member

sfan5 commented Jan 9, 2022

I don't think this is the right solution for 5.5.0.
Not being able to disable shadows is the primary but not the only issue with them, games also need the ability to:

  • change which position in the sky emits light or decouple this entirely (static position)
  • define which objects cast shadows
  • more which I can't think of

With this PR there's also the question of what the default shadow intensity would be, it needs to be zero so that the feature is entirely opt-in.

If preserving the shadow feature for 5.5 is a priority then I can envision a solution that allow games to opt-in via their game.conf. This would of course be temporary.

@celeron55
Copy link
Member

celeron55 commented Jan 9, 2022

@sfan5 but this is enough to allow a maintained game to disable shadows very easily (which satisfies the requirements @hecktest came up with), and there's nothing in this that would make it difficult to extend this to the features you mention in later versions. Right?

Of course if you go with the strict compatibility definition of "no shadows unless the game explicitly requests them", then the default should be 0.

I can think of another (maybe more serious) problem: The scale of shadow intensity doesn't go to 100% which would be something along the lines of "completely black" (or actually that'd be "completely ambient brightness" (see #11499 for what that'll probably work and look like in the future)), which a game might want to do. So this doesn't give the kind of total control we should aim for.

@sfan5
Copy link
Member

sfan5 commented Jan 9, 2022

Sure it is an opt-out solution but is that what hecks requested? Short of asking him again there's no sure way, going by his hard stance on "pulling the rug" I think an opt-out is better.
(There could be a longer discussion here about whether it's okay to require that games are maintained, we already do sort of on some issues then for others it's considered that strict compatibility is a must...)

Regardless of the opt-in/opt-out decision, I think an explicitly temporary way is better than adding an API that will inevitably need changes because it won't match the final idea of what the API should be (see also #11366)

@x2048
Copy link
Contributor Author

x2048 commented Jan 9, 2022

@sfan5 @celeron55 A strict opt-in solution will prevent people from trying shadows on older servers until the server owners upgrade and use the new API, which in turn would mean a client upgrade for their entire user base.

The solution here is a tradeoff between user and game control, allowing the users to opt-in shadows on older games and servers if they see fit and newer/maintained games to opt-out or take (some) control of the shadows as they want.

As for giving the game the full control (up to 100%), might be a good idea. I make shadow_strength only the default setting for the games that do not modify it or set shadow_intensity to nil.

@rubenwardy
Copy link
Member

Hecks has said a few times that he's fine with updating his game after an engine change. I support defaulting with allowing shadows

@lhofhansl
Copy link
Contributor

MHO, this is right compromise. We can (and have) endlessly discuss this; perhaps this should be controlled by the Biome, or perhaps by the player, or the gamedev, or ..., or ... Arrghhh. It's just shadows for chrissake! :)

At this rate we'll never add anything new to Minetest. @0xLiso has already left us (probably due to the tone of a some folks who will remain unnamed).

With this the client can set it, game can override if they care. We have already proposed turning it off by default on the client, so players would have to actively turn it on, and then presumably they want it.

As usually, just my $0.02.

With @SmallJoker's concern addressed I fully support this.

@erlehmann
Copy link
Contributor

this is enough to allow a maintained game to disable shadows very easily (which satisfies the requirements @hecktest came up with)

@celeron55 wHy does @hecktest specify the requirements regarding shadows being opt-in or not? Other games, like the MCL games, have light/shadow mechanics too! Is it because @hecktest has a game which is affected very badly?

Some games simply do not have mechanics where a sun-cast shadow makes little sense.
Think of the end dimension in MineClone2 / MineClone5 / Mineclonia!

@lhofhansl
Copy link
Contributor

Tried it. Works. Code looks good.

@celeron55
Copy link
Member

@erlehmann It is pretty much just because @hecktest formulated a general rule that seems to make sense to me. He's one of the people who care about the issue because he has a game with a very specific art style. Some others don't have a similar reason to care about it. You can propose another general rule if you'd like. Have you mentioned what your take on opt-in/opt-out would be?

@x2048's "allowing the users to opt-in shadows on older games and servers if they see fit" seems to make sense to me also, though.

@x2048
Copy link
Contributor Author

x2048 commented Jan 10, 2022

So, it looks like we have some agreement around opt-out behavior, but there is doubt about (ab-)using set_sky.

Is player:set_lighting() proposed by @celeron55 accepted by everyone? I'm in, and I will change this PR and #11499 to converge towards the same API.

I will expand shadow_intensity to the full range and rename shadow_strength to shadow_strength_default.

I will keep orbit inclination with set_sun/set_moon, it belongs there.

@sfan5
Copy link
Member

sfan5 commented Jan 10, 2022

[...] until the server owners upgrade and use the new API, which in turn would mean a client upgrade for their entire user base.

Usage of the new API (to enable a new feature on new clients) does not mean incompatibility with old clients.

Anyway I've stated my opinion on this already. Don't forget the last sentence in my comment, which applies regardless of opt-in or opt-out!

@lhofhansl
Copy link
Contributor

Is player:set_lighting() proposed by @celeron55 accepted by everyone?

As long as we have an API, it's cool. :)

@lhofhansl
Copy link
Contributor

I will expand shadow_intensity to the full range and rename shadow_strength to shadow_strength_default.

What does that mean? It's no longer multiplied by the client setting? So if the game does not set it the client setting is used, if the games sets it the client setting is ignored?

@x2048
Copy link
Contributor Author

x2048 commented Jan 11, 2022

@lhofhansl yes

Create shadows namespace for all future shadow-specific parameters
@x2048 x2048 requested review from lhofhansl and SmallJoker March 16, 2022 22:11
@lhofhansl
Copy link
Contributor

Sorry... Missed the update here. Will review and test today.

Copy link
Contributor

@lhofhansl lhofhansl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tried it. Works. Code looks fine.

I would like to accompany that with a change in MTG that sets the shadow strength based on cloud coverage. There is already code to set the cloud density based on biome humidity, it's just 3 lines of code there.

@x2048
Copy link
Contributor Author

x2048 commented Mar 17, 2022

Added One Approval label based on @lhofhansl's approval.

@lhofhansl
Copy link
Contributor

Should we add things like saturation et all later?

@x2048
Copy link
Contributor Author

x2048 commented Mar 18, 2022

@lhofhansl Yes, I'll add more stuff to set_lighting in later PRs.

@sfan5
Copy link
Member

sfan5 commented Mar 19, 2022

Is the API in this PR currently opt-in or opt-out?
And are we sure that this API can persist and make sense in the future when more fine grained (per-object?) shadow control is added?

@x2048
Copy link
Contributor Author

x2048 commented Mar 19, 2022

@sfan5
It's an opt-in, a game that does not do anything, will not generate shadowmaps or shadows. The only quirk now is that SM textures will still be allocated if the client enables shadows. This is because Irrlicht crashes if I delete/recreate SM textures.

Here is how I see the API for shadows, and the current API is within this design:

  1. Global control is done via set_lighting({ shadows = { intensity = ..., source = { type = <fixed|skybody>, direction = { x, y, z } }, tint = "#...", casters = {nodes = true, entities = true } } }). This method would also be used to change ambient brightness, color tint and saturation.
  2. Sky bodies are controlled via set_sun(), set_moon(): orbit_inclination, casts_shadows etc.
  3. Per-node flags can be controlled via register_node(): shadow_caster = true, shadow_receiver = true. This can be linked to general lighting control, e.g. having emissive brightness/color.
  4. Per-entity flags via register_entity() would be the same as for nodes.
  5. Materials could receive shadow flags if/when that API is added.

@lhofhansl
Copy link
Contributor

While we're at it. I still prefer an opt-out for games that care about this. But I take this over nothing.

@lhofhansl
Copy link
Contributor

(ah, downvote-nocomment-@wsor4035 has graced us with his vote again :) )

@wsor4035
Copy link
Contributor

(ah, downvote-nocomment-@wsor4035 has graced us with his vote again :) )

my opinion has not changed from #11944 (comment)

@sfan5
Copy link
Member

sfan5 commented Mar 25, 2022

It's an opt-in, a game that does not do anything, will not generate shadowmaps or shadows.

Sounds good, I have no complaints about that. I might have time to review this soon but if not feel free to merge it with someone else's approval.

@x2048
Copy link
Contributor Author

x2048 commented Mar 25, 2022

@lhofhansl

I've added support for sun/moon being hidden. If you approve 3677ddd, I'll merge this PR.

@x2048 x2048 merged commit 0f25fa7 into minetest:master Mar 26, 2022
@x2048 x2048 deleted the shadow_intensity branch March 26, 2022 15:58
@NathanSalapat
Copy link
Contributor

NathanSalapat commented Mar 28, 2022

So uhh this is stinking great. Now I have to manually add code to enable shadows, which isn't a huge deal, but it breaks the server for anybody that is using the stable release. Effectively this makes shadows completely useless.
Edit: no protocol change either, is it even possible for me to see if a player has support for this feature?

@sfan5
Copy link
Member

sfan5 commented Mar 28, 2022

Why does it break the server for anyone on a stable release?

@NathanSalapat
Copy link
Contributor

@sfan5 When joining a the server with a client running the stable version the client would crash because it didn't know how to handle player:get_lighting()

BuckarooBanzai came through with a solution on the discord.
if player.get_lighting then local light = player:get_lighting() light.shadows.intensity = 0.5 player:set_lighting(light) end

@sfan5
Copy link
Member

sfan5 commented Mar 28, 2022

Please be more specific. The client does not handle Lua calls, it's all server side.
The code you posted would be a solution for a mod to be compatible to both 5.5 and 5.6-dev servers, but this has nothing to do with the version of a potential client.

@BuckarooBanzay
Copy link
Contributor

BuckarooBanzai came through with a solution on the discord.

This might be a compatibility-workaround as sfan5 said for multiple engine-version support but i think your problem with the crashes in the clients (?!) should not happen like that, do you have that installed on a public server for easier testing by any chance?
as far as i understood the new command_id should be ignored and dropped by older clients 😕

(this is getting OT though, might be the time to open a separate issue)

@NathanSalapat
Copy link
Contributor

Please be more specific. The client does not handle Lua calls, it's all server side. The code you posted would be a solution for a mod to be compatible to both 5.5 and 5.6-dev servers, but this has nothing to do with the version of a potential client.

So I added the code that was included in the merge, I think the bit from devtest. Singleplayer crashed on stable, dev was fine. Now that I think about it I didn't push the changes to my server, so maybe that actually wasn't/isn't a problem.

@NathanSalapat
Copy link
Contributor

NathanSalapat commented Mar 29, 2022

My original comment is incorrect, I apologize for that. I was irked that this was made opt-in and posted too hastily, I should have done better testing.
Adding

local light = player:get_lighting()
 light.shadows.intensity = 0.5
 player:set_lighting(light)

to a minetest.register_on_joinplayer() callback on a dev server doesn't crash stable clients, they obviously see no shadows. A dev client joining the dev server does see shadows.
A stable server can't run the code, so nobody gets shadows there.
The solution BuckarooBanzay gave me works for singleplayer, so stable and dev clients can both run the game, it also works on servers, but again nobody gets shadows.

Running a dev client after this commit effectively nukes shadows on all games/servers, unless the server is running a dev build or the game has the compatibility code. How is anybody suppose to do any testing of the shadows when no games/servers support them? As far as I can tell neither MTG or DevTest have the shadows enabled.

@lhofhansl
Copy link
Contributor

@NathanSalapat As you can see from my various comments and suggestions I wholeheartedly agree with you.

Of all things that you can set on the client to break things or change gameplay or emergence it seems to be shadows that has been elected by most of the core-devs to be the one things that breaks gameplay. (And why let a user decide what (s)he sees with their own client when we can also make it all really complicated, just to serve the one or two one-off games that do not want shadows. Oh well.)

On this, note however, that dev test already has a chat command to turn on shadows: "set_lighting"
Also see also my minetest/minetest_game#2938 to get shadows to be enabled by default in Minetest Game.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Discussion Issues meant for discussion of one or more proposals One approval ✅ ◻️ Roadmap The change matches an item on the current roadmap @ Script API
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Shadowmaps cannot be disabled by the server