You might also be interested in: godot-proposals#14652
1 like
Godot doesn't use interaural time differences for its 3D audio, and I think it should!
The TLDR is:
Godot 3D audio sounds like this, but I think it should sound like this
---
Recently I made a really simple horror game as a little October challenge for myself, and I was struggling with getting the 3D audio to sound right. I tried out 2 different community-made raytraced-audio plugins before realizing that neither the default AudioStreamPlayer3D node, or either of the plugins I tried, added any kind of interaural time differences to the spacial audio, which really surprised me.
I already opened a discussion on the godot-proposals repo about this, but I also wanted to post about it here, since my experience with the spacial audio plugins makes me think this may be an under-appreciated topic.
My full discussion post:
---
From Wikipedia: _The interaural time difference (or ITD) when concerning humans or animals, is the difference in arrival time of a sound between two ears. It is important in the localization of sounds, as it provides a cue to the direction or angle of the sound source from the head. If a signal arrives at the head from one side, the signal has further to travel to reach the far ear than the near ear. This pathlength difference results in a time difference between the sound's arrivals at the ears, which is detected and aids the process of identifying the direction of sound source._
Currently, Godot's AudioStreamPlayer3D and AudioListener3D use only panning to clue you in to what direction a sound is coming from, which creates a very weak illusion of spacial direction for 3D audio.
However, interaural time differences are much more important for creating the illusion of 3d audio, and Godot doesn't provide a built-in way to create that effect.
I whipped up 3 demo samples in Audacity to showcase this:
- Water droplet panned 40% to the left.
- Water droplet panned 40% to the left AND the left channel plays slightly sooner than the right.
- Water droplet panned 40% to the left AND the right channel plays slightly sooner than the left.
The first example mimics what Godot already does if an AudioStreamPlayer3D if far to your left. To my ears, it sounds like the drop is coming from the center of my head, just slightly to the left.
The second example is what I'm asking to be added. To my ears, it sounds like the drop is coming from the far left, providing a much stronger spatial effect than the first.
The third example is just here to showcase the difference in "feel" between the panning effect and the interaural effect (the sound is panned to the left, but the right plays first). To my ears, it sounds like the sound is coming slightly from my right, but with something obstructing the sound. _(This is also what it sounds like currently when you use a stereo audio sample with an AudioStreamPlayer3D node, and the directionality of the sample conflicts with the direction of the audio in-game)_
This issue can be overcome through the use of custom scripts, plus separate audio buses and AudioEffectDelays for each AudioStreamPlayer3D. Here's a small partial snippet from a recent project of mine that added this effect in a simplified way:
var interaural_delay_effect: AudioEffectDelay
# ...
## Update the interaural_delay_effect with the current delays for each ear.
## Note that this implementation always pins the closer ear to 0.0 milliseconds of delay,
## but a physically accurate effect should actually just apply the full delay to each ear.
func _update_interaural(listener: AudioListener3D) -> void:
const SPEED_OF_SOUND: float = 340.29
const SOUND_SECONDS_PER_METER: float = 1.0 / SPEED_OF_SOUND
const SOUND_MS_PER_METER: float = SOUND_SECONDS_PER_METER * 1000
var relative_sound_pos: Vector3 = listener.to_local(global_position)
var left_ear_travel_time: float = Vector3(-0.1075, 0, 0).distance_to(relative_sound_pos) * SOUND_MS_PER_METER
var right_ear_travel_time: float = Vector3(0.1075, 0, 0).distance_to(relative_sound_pos) * SOUND_MS_PER_METER
if left_ear_travel_time < right_ear_travel_time:
# Right ear delay is longer, remove left delay, add delay to right.
interaural_delay_effect.tap1_delay_ms = 0.0
interaural_delay_effect.tap2_delay_ms = right_ear_travel_time - left_ear_travel_time
else:
# Left ear delay is longer, remove right delay, add delay to left.
interaural_delay_effect.tap2_delay_ms = 0.0
interaural_delay_effect.tap1_delay_ms = left_ear_travel_time - right_ear_travel_time
However, I personally think this should be added directly into Godot's built-in 3D audio nodes, because this is the minimum requirement for audio to actually sound 3D, and I think that most users of the AudioStreamPlayer3D and AudioListener3D nodes would be hoping to achieve this kind of directional effect.
I'm suggesting this being added as an option just for compatibility reasons, but I don't think the average user would actually want this option disabled.
EDIT: Just a quick note because I realized a potential issue with understanding my examples; if you have "spacial sound for headphones" (or whatever it's called on your device) turned on, you'll have to turn it off to properly hear the difference between the examples, because that filter essentially operates by trying to guess at the effect I'm describing :)
176 points · 26 comments
@Giulio6686 One of the weakness of Godot. Even encryption wouldn't do much the key is still in the binary. Reverse engineer can pretty much get 1:1 of the same thing of the original code.
There are many proposals but no concensus yet godot-proposals#6031
237 views
This sounds nice. #godotengine
godot-proposals#5841
3 likes
High-quality character shadows without increasing shadow atlas resolution (Godot feature proposal)
While making a space game I struggled to keep directional shadow quality high for my player while increasing max shadow distance so fairly distant objects dont lose shadows. Tweaking cascades helped but required me to keep increasing directional atlas until 8192x8192 until I got results I could tolerate. But since one of my targets was Quest 3 I had to look for another solution.
So I learned about per object shadows where projection fits tightly to the shadow casting object instead of capturing large distances as cascades. Cascades can waste a lot of shadow map space when only a few objects actually need detailed shadows. One of the closest related proposals on Github made by another dev is here: godot-proposals#5841
After some time tweaking the Godot internals, I created a node type ShadowGroup3D. It is an editor node that acts like a container that tracks all meshes inside, excludes them from standard cascades and renders their shadows using a separate projection fitted tightly around those meshes. So if you'd want to get crisp shadows, you'd just create ShadowGroup3D and put your character inside.
Where I think it may be useful:
- If you're building a mobile or a VR game and want high quality shadows for your characters without being forced to increase your global directional atlas size (doubling the atlas resolution increases its pixel count by 4x). With ShadowGroup3D you'd even be able to actually reduce your current atlas size if the only reason you increased it in the first place was to just make your character shadow look less blurry/shimmery.
- Especially in VR where you'd want your character's hands and weapons to cast a really good looking shadow, given that the player can see things up close.
- For worlds that want to have shadows at large distances while keeping high quality shadows focused on things that matter: characters, weapons, important objects, npc.
- For games aiming for high end graphics standards where you'd want your main character to have the best possible shadow resolution above everything else.
- Fighting games where you have 2 characters and want to maximize their shadow quality
I haven't done thorough benchmarking yet and my implementation only supports Mobile renderer, however I'm planning to add support for Forward+ renderer as well and make a PR to the Godot repo after some more testing, polishing and refactoring.
Video recorded with Godot 4.8 beta (custom build, dev branch). Params shared by all 3 video clips:
- Mobile renderer
- Sun shadows: 2 cascade splits (PSSM), 80 m max distance, blend splits off
- Soft shadow filter quality: Soft Very Low
- Shadow blur 1.0, bias 0.1, normal bias 2.0
- 16-bit shadow depth
- 4× MSAA
Would you like to have ShadowGroup3D as a feature in Godot? Let me know.
306 points · 21 comments
Viewport rendering modes:
Add metallic and roughness visualization/display modes under "Display Advanced": godot-proposals#15655
(This one is crucial for more advanced materials, but I suspect could be difficult to implement).
2 likes
Just made a bunch of Godot proposals, as promised! Here's a thread of them.
Visual shader stuff:
Ability to preview visual shader steps: godot-proposals#15652
Improvements to "Frame" functionality: godot-proposals#15656
Backspace to delete material nodes: godot-proposals#15653
5 likes
I made a Godot addon to select and edit tiles across several TileMapLayer nodes at once
I made an addon to work around a Godot limitation that was significantly slowing down my work. I originally built it for my own project, but I'm sharing it to give back to the community. Contributions to the source and bug reports are very welcome.
The problem
My 2D project uses about six TileMapLayer but Godot lets you select and move tiles on only one layer at a time, so moving part of a level means repeating the same operation on every single layer. It's time consuming and prone to errors.
Why an addon?
This limitation has been know for more than two years and a half without a solution so I’m proposing an addon as a stopgap.
With an addon we can try an approach and help define what a built-in solution should look like. It's also quicker to experiment and to adopt than submitting to the engine.
The solution
A new Node2D, MultiLayerTileMap, that edits all of its visible TileMapLayer children at once.
Design decisions:
- The node detects the largest tile size among its children and uses it as its own grid to select and move tiles.
- Layers with different tile sizes are supported as long as their tile size divides that grid size (for example, 8 px layers on a 16 px grid).
- Layers must have no scale or rotation. Any layer that doesn't meet these conditions is ignored, and a warning is shown in the scene tree.
- Nested MultiLayerTileMap nodes act as logical groups: their layers behave as if they were direct children.
Links
- Godot Asset Store
- Source code (GitLab)
- Introduction video (YouTube)
3 points
Cubic Hexagon Implementation
Hello everyone, I have been coding with Godot for about 5 years, and recently, I was tasked with making a hexagon grid-based tactical game. At first, I saw that Godot has Hexagon support, but then I came to a halt after realising that hex-tile logic is different from square-tile logic, which led me to consider making this post.
I searched the web for help and came to find an article all about hex-tile algorithms, which solved all of my problems. However, I would love to see some of its logic, if not all, in Godot. The article I found is (redblobgames.com) from redblobgames.
I am aware that there are asset libraries for hex-tile logic, and that you can implement it yourself. The goal of this discussion is to discuss a possible implementation of hex-tile logic in the official Godot engine. The basic features that could be implemented are the cubic, axial, and double coordinate systems, and line drawing (func get_coordinates_in_between(a: CubicCoor, d: CubicCoor) -> Array[CubicCoor]: [a, b, c, d]).
I am sure there could be more to implement, so feel free to add to this post. Thank you for reading.
godot-proposals#15585
5 points · 1 comment
A proposal to enact a full ban on AI-generated code in Godot has been submitted. If that's something you have an opinion on (which it should be), you can find the proposal here.
godot-proposals#15626
2 likes · 1 repost
Mentions
You might also be interested in: godot-proposals#14652
Godot doesn't use interaural time differences for its 3D audio, and I think it should! The TLDR is: Godot 3D audio sounds like this, but I think it should sound like this --- Recently I made a really simple horror game as a little October challenge for myself, and I was struggling with getting the 3D audio to sound right. I tried out 2 different community-made raytraced-audio plugins before realizing that neither the default AudioStreamPlayer3D node, or either of the plugins I tried, added any kind of interaural time differences to the spacial audio, which really surprised me. I already opened a discussion on the godot-proposals repo about this, but I also wanted to post about it here, since my experience with the spacial audio plugins makes me think this may be an under-appreciated topic. My full discussion post: --- From Wikipedia: _The interaural time difference (or ITD) when concerning humans or animals, is the difference in arrival time of a sound between two ears. It is important in the localization of sounds, as it provides a cue to the direction or angle of the sound source from the head. If a signal arrives at the head from one side, the signal has further to travel to reach the far ear than the near ear. This pathlength difference results in a time difference between the sound's arrivals at the ears, which is detected and aids the process of identifying the direction of sound source._ Currently, Godot's AudioStreamPlayer3D and AudioListener3D use only panning to clue you in to what direction a sound is coming from, which creates a very weak illusion of spacial direction for 3D audio. However, interaural time differences are much more important for creating the illusion of 3d audio, and Godot doesn't provide a built-in way to create that effect. I whipped up 3 demo samples in Audacity to showcase this: - Water droplet panned 40% to the left. - Water droplet panned 40% to the left AND the left channel plays slightly sooner than the right. - Water droplet panned 40% to the left AND the right channel plays slightly sooner than the left. The first example mimics what Godot already does if an AudioStreamPlayer3D if far to your left. To my ears, it sounds like the drop is coming from the center of my head, just slightly to the left. The second example is what I'm asking to be added. To my ears, it sounds like the drop is coming from the far left, providing a much stronger spatial effect than the first. The third example is just here to showcase the difference in "feel" between the panning effect and the interaural effect (the sound is panned to the left, but the right plays first). To my ears, it sounds like the sound is coming slightly from my right, but with something obstructing the sound. _(This is also what it sounds like currently when you use a stereo audio sample with an AudioStreamPlayer3D node, and the directionality of the sample conflicts with the direction of the audio in-game)_ This issue can be overcome through the use of custom scripts, plus separate audio buses and AudioEffectDelays for each AudioStreamPlayer3D. Here's a small partial snippet from a recent project of mine that added this effect in a simplified way: var interaural_delay_effect: AudioEffectDelay # ... ## Update the interaural_delay_effect with the current delays for each ear. ## Note that this implementation always pins the closer ear to 0.0 milliseconds of delay, ## but a physically accurate effect should actually just apply the full delay to each ear. func _update_interaural(listener: AudioListener3D) -> void: const SPEED_OF_SOUND: float = 340.29 const SOUND_SECONDS_PER_METER: float = 1.0 / SPEED_OF_SOUND const SOUND_MS_PER_METER: float = SOUND_SECONDS_PER_METER * 1000 var relative_sound_pos: Vector3 = listener.to_local(global_position) var left_ear_travel_time: float = Vector3(-0.1075, 0, 0).distance_to(relative_sound_pos) * SOUND_MS_PER_METER var right_ear_travel_time: float = Vector3(0.1075, 0, 0).distance_to(relative_sound_pos) * SOUND_MS_PER_METER if left_ear_travel_time < right_ear_travel_time: # Right ear delay is longer, remove left delay, add delay to right. interaural_delay_effect.tap1_delay_ms = 0.0 interaural_delay_effect.tap2_delay_ms = right_ear_travel_time - left_ear_travel_time else: # Left ear delay is longer, remove right delay, add delay to left. interaural_delay_effect.tap2_delay_ms = 0.0 interaural_delay_effect.tap1_delay_ms = left_ear_travel_time - right_ear_travel_time However, I personally think this should be added directly into Godot's built-in 3D audio nodes, because this is the minimum requirement for audio to actually sound 3D, and I think that most users of the AudioStreamPlayer3D and AudioListener3D nodes would be hoping to achieve this kind of directional effect. I'm suggesting this being added as an option just for compatibility reasons, but I don't think the average user would actually want this option disabled. EDIT: Just a quick note because I realized a potential issue with understanding my examples; if you have "spacial sound for headphones" (or whatever it's called on your device) turned on, you'll have to turn it off to properly hear the difference between the examples, because that filter essentially operates by trying to guess at the effect I'm describing :)
@Giulio6686 One of the weakness of Godot. Even encryption wouldn't do much the key is still in the binary. Reverse engineer can pretty much get 1:1 of the same thing of the original code. There are many proposals but no concensus yet godot-proposals#6031
This sounds nice. #godotengine godot-proposals#5841
High-quality character shadows without increasing shadow atlas resolution (Godot feature proposal) While making a space game I struggled to keep directional shadow quality high for my player while increasing max shadow distance so fairly distant objects dont lose shadows. Tweaking cascades helped but required me to keep increasing directional atlas until 8192x8192 until I got results I could tolerate. But since one of my targets was Quest 3 I had to look for another solution. So I learned about per object shadows where projection fits tightly to the shadow casting object instead of capturing large distances as cascades. Cascades can waste a lot of shadow map space when only a few objects actually need detailed shadows. One of the closest related proposals on Github made by another dev is here: godot-proposals#5841 After some time tweaking the Godot internals, I created a node type ShadowGroup3D. It is an editor node that acts like a container that tracks all meshes inside, excludes them from standard cascades and renders their shadows using a separate projection fitted tightly around those meshes. So if you'd want to get crisp shadows, you'd just create ShadowGroup3D and put your character inside. Where I think it may be useful: - If you're building a mobile or a VR game and want high quality shadows for your characters without being forced to increase your global directional atlas size (doubling the atlas resolution increases its pixel count by 4x). With ShadowGroup3D you'd even be able to actually reduce your current atlas size if the only reason you increased it in the first place was to just make your character shadow look less blurry/shimmery. - Especially in VR where you'd want your character's hands and weapons to cast a really good looking shadow, given that the player can see things up close. - For worlds that want to have shadows at large distances while keeping high quality shadows focused on things that matter: characters, weapons, important objects, npc. - For games aiming for high end graphics standards where you'd want your main character to have the best possible shadow resolution above everything else. - Fighting games where you have 2 characters and want to maximize their shadow quality I haven't done thorough benchmarking yet and my implementation only supports Mobile renderer, however I'm planning to add support for Forward+ renderer as well and make a PR to the Godot repo after some more testing, polishing and refactoring. Video recorded with Godot 4.8 beta (custom build, dev branch). Params shared by all 3 video clips: - Mobile renderer - Sun shadows: 2 cascade splits (PSSM), 80 m max distance, blend splits off - Soft shadow filter quality: Soft Very Low - Shadow blur 1.0, bias 0.1, normal bias 2.0 - 16-bit shadow depth - 4× MSAA Would you like to have ShadowGroup3D as a feature in Godot? Let me know.
Viewport rendering modes: Add metallic and roughness visualization/display modes under "Display Advanced": godot-proposals#15655 (This one is crucial for more advanced materials, but I suspect could be difficult to implement).
Just made a bunch of Godot proposals, as promised! Here's a thread of them. Visual shader stuff: Ability to preview visual shader steps: godot-proposals#15652 Improvements to "Frame" functionality: godot-proposals#15656 Backspace to delete material nodes: godot-proposals#15653
I made a Godot addon to select and edit tiles across several TileMapLayer nodes at once I made an addon to work around a Godot limitation that was significantly slowing down my work. I originally built it for my own project, but I'm sharing it to give back to the community. Contributions to the source and bug reports are very welcome. The problem My 2D project uses about six TileMapLayer but Godot lets you select and move tiles on only one layer at a time, so moving part of a level means repeating the same operation on every single layer. It's time consuming and prone to errors. Why an addon? This limitation has been know for more than two years and a half without a solution so I’m proposing an addon as a stopgap. With an addon we can try an approach and help define what a built-in solution should look like. It's also quicker to experiment and to adopt than submitting to the engine. The solution A new Node2D, MultiLayerTileMap, that edits all of its visible TileMapLayer children at once. Design decisions: - The node detects the largest tile size among its children and uses it as its own grid to select and move tiles. - Layers with different tile sizes are supported as long as their tile size divides that grid size (for example, 8 px layers on a 16 px grid). - Layers must have no scale or rotation. Any layer that doesn't meet these conditions is ignored, and a warning is shown in the scene tree. - Nested MultiLayerTileMap nodes act as logical groups: their layers behave as if they were direct children. Links - Godot Asset Store - Source code (GitLab) - Introduction video (YouTube)
Cubic Hexagon Implementation Hello everyone, I have been coding with Godot for about 5 years, and recently, I was tasked with making a hexagon grid-based tactical game. At first, I saw that Godot has Hexagon support, but then I came to a halt after realising that hex-tile logic is different from square-tile logic, which led me to consider making this post. I searched the web for help and came to find an article all about hex-tile algorithms, which solved all of my problems. However, I would love to see some of its logic, if not all, in Godot. The article I found is (redblobgames.com) from redblobgames. I am aware that there are asset libraries for hex-tile logic, and that you can implement it yourself. The goal of this discussion is to discuss a possible implementation of hex-tile logic in the official Godot engine. The basic features that could be implemented are the cubic, axial, and double coordinate systems, and line drawing (func get_coordinates_in_between(a: CubicCoor, d: CubicCoor) -> Array[CubicCoor]: [a, b, c, d]). I am sure there could be more to implement, so feel free to add to this post. Thank you for reading. godot-proposals#15585
A proposal to enact a full ban on AI-generated code in Godot has been submitted. If that's something you have an opinion on (which it should be), you can find the proposal here. godot-proposals#15626