godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.16k stars 97 forks source link

Expose the lightmap shadow value to scripting using a raycast #2198

Open cenullum opened 3 years ago

cenullum commented 3 years ago

Describe the project you are working on

I want to work on Thief clone

Describe the problem or limitation you are having in your project

Main feature of Thief clone, detecting whether is player on shadow is not possible in Godot or I couldn't find the way

You can see what I try to achieve at 5:20 of the video https://www.youtube.com/watch?v=4Dnd4AWKT5Q

Describe the feature / enhancement and how it helps to overcome the problem or limitation

I know it will be unprofessional with this way to tell what I want, but I think it will be easier to understand. https://docs.unity3d.com/ScriptReference/RaycastHit-lightmapCoord.html . In Unity you can get lightmap value with raycast. It would be good to overcome the detecting is player on shadow.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

var space_state = get_world_2d().direct_space_state
var result = space_state.intersect_ray(Vector2(0, 0), Vector2(50, 100))  
if result:
      var value= result.lightmap_value # this will be return value between 0.0 and 1.0 
      print("lightmap color",value) 
      if (value >0.5):
            print( "player on shadow and can't be detect by NPCs")

If this enhancement will not be used often, can it be worked around with a few lines of script?

I wish I could workaround but description of bakedlightmap isn't don't yet, so I didn't find a way to do the feature with current state. https://docs.godotengine.org/en/stable/classes/class_bakedlightmapdata.html#class-bakedlightmapdata

Is there a reason why this should be core and not an add-on in the asset library?

I think it should be part of the core because it is very useful for basic of stealth games.

Calinou commented 3 years ago

There are many ways to achieve Thief-like light sensors without relying on rendering-specific stuff or baked lightmaps. For instance, you could perform a raycast from every light in range and use this to compute a "lightness" value at the player position. This can be done with both DirectionalLights and OmniLights.

For SpotLights, you'll also have to add a dot product check (Vector3.dot()) to make sure the player is actually in the spotlight's angle radius.

Zireael07 commented 3 years ago

Thief and Deus Ex used a "light/dark" value baked into the map structure, just FYI (the lighting was static) - my most recent project happens to be Deus Ex based although no light/dark support yet

cenullum commented 3 years ago

It came to my mind to measure the value of all lights, at least the dynamic ones but I was thinking of bake the static ones so maybe this kind of feature would be helpful. Frankly, I don't know how good it is to loop for all lights every second, maybe I can just loop the near ones for performance or maybe this is not even necessary.

Calinou commented 3 years ago

Frankly, I don't know how good it is to loop for all lights every second, maybe I can just loop the near ones for performance or maybe this is not even necessary.

Individual raycasts aren't that expensive. Just make sure to use a Timer node to not perform it too frequently, and exclude lights which aren't in the player's range (with the exception of DirectionalLight which always uses a fixed "angle" for its shadow).

atirut-w commented 3 years ago

you could perform a raycast from every light in range and use this to compute a "lightness" value at the player position. This can be done with both DirectionalLights and OmniLights.

This will probably be difficult to match the actual lighting, I think

Zireael07 commented 2 years ago

I'm back to poking around that DX-1 like game, and the solution I will be going with (as the game will feature dynamic day/night system) will be based on raycasts. This shouldn't be difficult to match with actual lighting unless the lighting is doing something super weird.

Hint: https://stackoverflow.com/questions/46767188/detect-if-object3d-is-receiving-shadows-r86

Zireael07 commented 2 years ago

Proof of concept of raycast use: https://github.com/Zireael07/Stealth-fps/commit/106ac5f916f672ad583e0ec1b4cd472168992e13