feat(world): triplanar seabed shader with procedural normal maps and detail shading
Rock is normal-mapped triplanar in world space at two scales, sand carries an oriented ripple normal map on the xz plane, and a grain map drives detail occlusion, albedo mottling and roughness. The three maps are seamless, seeded, mipmapped textures built synchronously by SeabedDetailTextures, so no asset is needed and builds are deterministic. The mesh has no tangents: perturbed normals are computed in world space and written to NORMAL. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
f22a5e69aa
commit
17f58912c1
12 files changed
+208
-16
No files matched your search
@@ -2,14 +2,17 @@ class_name BathymetricTerrainActor
|
||||
extends StaticBody3D
|
||||
|
||||
const TerrainHeightField = preload("res://game/domain/sites/terrain_height_field.gd")
|
||||
const SeabedDetailTextures = preload("res://game/world/sites/seabed_detail_textures.gd")
|
||||
const TERRAIN_SHADER = preload("res://game/world/sites/seabed_terrain.gdshader")
|
||||
|
||||
const TILE_CELLS := 64
|
||||
const VISIBILITY_RANGE_END_M := 420.0
|
||||
const VISIBILITY_RANGE_MARGIN_M := 60.0
|
||||
const DETAIL_TEXTURE_SEED := 4102
|
||||
|
||||
var _field: TerrainHeightField
|
||||
var _material: ShaderMaterial
|
||||
var _detail_textures: SeabedDetailTextures
|
||||
var _tiles_root: Node3D
|
||||
var _collision: CollisionShape3D
|
||||
|
||||
@@ -19,8 +22,13 @@ func configure(field: TerrainHeightField) -> String:
|
||||
return "terrain field is missing"
|
||||
_clear()
|
||||
_field = field
|
||||
if _detail_textures == null:
|
||||
_detail_textures = SeabedDetailTextures.build(DETAIL_TEXTURE_SEED)
|
||||
_material = ShaderMaterial.new()
|
||||
_material.shader = TERRAIN_SHADER
|
||||
_material.set_shader_parameter(&"sand_normal_map", _detail_textures.sand_normal)
|
||||
_material.set_shader_parameter(&"rock_normal_map", _detail_textures.rock_normal)
|
||||
_material.set_shader_parameter(&"rock_grain_map", _detail_textures.rock_grain)
|
||||
_build_tiles()
|
||||
_build_collision()
|
||||
return ""
|
||||
@@ -30,6 +38,10 @@ func height_field() -> TerrainHeightField:
|
||||
return _field
|
||||
|
||||
|
||||
func terrain_material() -> ShaderMaterial:
|
||||
return _material
|
||||
|
||||
|
||||
func tile_count() -> int:
|
||||
return 0 if _tiles_root == null else _tiles_root.get_child_count()
|
||||
|
||||
|
||||
Reference in new issue
Block a user