Generalized handling of terrain & material audio

This commit is contained in:
Rob Kelly 2024-11-22 21:15:54 -07:00
parent cbed315048
commit c1b7d1b15f
11 changed files with 99 additions and 41 deletions

Binary file not shown.

BIN
assets/textures/grass_green/grass_green_albedo.dds (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/textures/grass_green/grass_green_normal.dds (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -27,7 +27,7 @@ noise = SubResource("FastNoiseLite_rpgb7")
[sub_resource type="Terrain3DMaterial" id="Terrain3DMaterial_woy2k"] [sub_resource type="Terrain3DMaterial" id="Terrain3DMaterial_woy2k"]
_shader_parameters = { _shader_parameters = {
"auto_base_texture": 3, "auto_base_texture": 4,
"auto_height_reduction": 0.1, "auto_height_reduction": 0.1,
"auto_overlay_texture": 0, "auto_overlay_texture": 0,
"auto_slope": 0.41, "auto_slope": 0.41,

Binary file not shown.

BIN
levels/debug_level/terrain_assets.res (Stored with Git LFS)

Binary file not shown.

View File

@ -197,7 +197,12 @@ ball_previous={
3d_physics/layer_1="Collision Geometry" 3d_physics/layer_1="Collision Geometry"
3d_physics/layer_2="Layer 3" 3d_physics/layer_2="Layer 3"
3d_physics/layer_32="Grass Audio" 3d_physics/layer_27="Glass Material"
3d_physics/layer_28="Metal Material"
3d_physics/layer_29="Rock Material"
3d_physics/layer_30="Wood Material"
3d_physics/layer_31="Sand Material"
3d_physics/layer_32="Grass Material"
[physics] [physics]

View File

@ -5,9 +5,6 @@ const BASE_VOLUME := -36.0
const MAX_VOLUME := 3.0 const MAX_VOLUME := 3.0
const VELOCITY_ATTENUATION_SCALE := 400.0 const VELOCITY_ATTENUATION_SCALE := 400.0
const GRASS_PHYSICAL_LAYER := 1 << 32
const SAND_PHYSICAL_LAYER := 1 << 31
@onready var parent: GameBall = $".." @onready var parent: GameBall = $".."
@onready var grass_sfx_player: AudioStreamPlayer3D = %GrassSFXPlayer @onready var grass_sfx_player: AudioStreamPlayer3D = %GrassSFXPlayer
@ -24,30 +21,17 @@ func _force_attenuated_volume() -> float:
) )
func _play_sfx(player: AudioStreamPlayer3D) -> void: func _play(player: AudioStreamPlayer3D) -> void:
player.volume_db = _force_attenuated_volume() player.volume_db = _force_attenuated_volume()
print("PLAYING: ", player, "... VOLUME: ", player.volume_db) print("PLAYING: ", player, "... VOLUME: ", player.volume_db)
player.play() player.play()
func play_terrain_sfx(tex_id: int) -> void: func play_sfx(terrain: Terrain.Type) -> void:
var player := grass_sfx_player match terrain:
match tex_id: Terrain.Type.ROUGH, Terrain.Type.GREEN, Terrain.Type.FAIRWAY:
2: # sand _play(grass_sfx_player)
player = sand_sfx_player Terrain.Type.CONCRETE, Terrain.Type.ROCK:
3: # rock _play(concrete_sfx_player)
player = concrete_sfx_player Terrain.Type.SAND:
_play(sand_sfx_player)
_play_sfx(player)
## Select the appropriate SFX to play based on the collision layer of the collider.
##
## We use the upper bits of the collision layer to indicate standard SFX.
func play_physical_sfx(collision_mask: int) -> void:
var player := concrete_sfx_player
if collision_mask & GRASS_PHYSICAL_LAYER:
player = grass_sfx_player
elif collision_mask & SAND_PHYSICAL_LAYER:
player = sand_sfx_player
_play_sfx(player)

View File

@ -148,17 +148,10 @@ func _on_sleeping_state_changed() -> void:
func _on_collision(body: Node) -> void: func _on_collision(body: Node) -> void:
if body is Terrain3D: if body is Terrain3D:
var texture_blend: Vector3 = (body as Terrain3D).data.get_texture_id(global_position) sfx.play_sfx(Terrain.at_position(global_position, body as Terrain3D))
print("T3D texture blend: ", texture_blend)
# TODO maybe blend audio?
# Figure out audio for autoshader
var tex_id: float = 0 if texture_blend.x == 3 and texture_blend.z == 0 else texture_blend.x
sfx.play_terrain_sfx(tex_id)
elif body is CSGShape3D: elif body is CSGShape3D:
sfx.play_physical_sfx((body as CSGShape3D).collision_layer) sfx.play_sfx(Terrain.from_physical_layer((body as CSGShape3D).collision_layer))
elif body is CollisionObject3D: elif body is CollisionObject3D:
sfx.play_physical_sfx((body as CollisionObject3D).collision_layer) sfx.play_sfx(Terrain.from_physical_layer((body as CollisionObject3D).collision_layer))
else: else:
print_debug("COLLIDER: ", body) print_debug("COLLIDER: ", body)

View File

@ -8,6 +8,7 @@ data = PackedVector3Array(0, 0, -5.2392, -1.2315, 0, -2.5941, 1.2315, 0, -2.5941
[node name="Sailboat" instance=ExtResource("1_ivu5q")] [node name="Sailboat" instance=ExtResource("1_ivu5q")]
[node name="StaticBody3D" type="StaticBody3D" parent="." index="1"] [node name="StaticBody3D" type="StaticBody3D" parent="." index="1"]
collision_layer = 536870913
[node name="CollisionShape3D" type="CollisionShape3D" parent="StaticBody3D" index="0"] [node name="CollisionShape3D" type="CollisionShape3D" parent="StaticBody3D" index="0"]
shape = SubResource("ConcavePolygonShape3D_mrf68") shape = SubResource("ConcavePolygonShape3D_mrf68")

69
src/world/terrain.gd Normal file
View File

@ -0,0 +1,69 @@
class_name Terrain
## Tools for working with different terrain types.
## This provides a unified interface to Terrain3D and regular meshes.
## Basic terrain materials
enum Type {
NONE,
ROUGH,
FAIRWAY,
GREEN,
SAND,
CONCRETE,
ROCK,
WOOD,
METAL,
GLASS,
}
## We use the upper bits of collision layers to encode material data
const PHYSICAL_LAYERS := {
1 << 31: Type.ROUGH,
1 << 30: Type.SAND,
1 << 29: Type.WOOD,
1 << 28: Type.ROCK,
1 << 27: Type.METAL,
1 << 26: Type.GLASS,
}
## Get the `Terrain.Type` value which corresponds to the given Terrain3D texture ID.
##
## Note that this relies on the ordering of textures in our Terrain3DAsset resource!
## If the order textures are defined in changes, this will break!
static func from_texture_id(tex_id: int) -> Type:
match tex_id:
0:
return Type.ROUGH
1:
return Type.FAIRWAY
2:
return Type.SAND
3:
return Type.GREEN
4:
return Type.ROCK
_:
return Type.NONE
## Get the `Terrain.Type` value encoded in the given collision layer setting.
##
## We use the upper bits in the collision layer to encode material data.
## Check the collision layer descriptions for more information.
static func from_physical_layer(collision_layer: int) -> Type:
for bit: int in PHYSICAL_LAYERS:
if collision_layer & bit:
return PHYSICAL_LAYERS[bit]
return Type.CONCRETE
## Get the `Terrain.Type` value at the given position in a Terrain3D node.
static func at_position(global_position: Vector3, terrain3d: Terrain3D) -> Type:
var blend := terrain3d.data.get_texture_id(global_position)
var id: int
if terrain3d.data.get_control_auto(global_position):
id = blend.x if blend.z > 0 else blend.y
else:
id = blend.x
return from_texture_id(id)