Implement playable Mac client and rendering validation

This commit is contained in:
shen
2026-09-11 14:58:22 +08:00
parent 1ab68bd06e
commit 374d4165d8
233 changed files with 6546 additions and 284 deletions
+83
View File
@@ -0,0 +1,83 @@
extends SceneTree
const Materials = preload("res://fx/particle_color_material.gd")
const EffectPlayer = preload("res://fx/effect_player.gd")
var failures := 0
func check(ok: bool, label: String) -> void:
if not ok:
failures += 1
printerr("FAIL: " + label)
func _init() -> void:
call_deferred("run")
func run() -> void:
var fx := EffectPlayer.new()
var textures: Array[Texture2D] = []
for color in [Color.RED, Color.GREEN, Color.BLUE]:
var img := Image.create(4, 4, false, Image.FORMAT_RGBA8)
img.fill(color)
textures.append(ImageTexture.create_from_image(img))
var frames := fx._texture_array(textures)
check(frames != null and frames.get_layers() == 3, "independent texture-array slices")
var base := StandardMaterial3D.new()
base.blend_mode = BaseMaterial3D.BLEND_MODE_MIX
base.albedo_texture = textures[0]
var mat := Materials.build(base, 4, frames, {"TexAniType": 1, "TexAniDelay": 0.1}, 1.0)
check(mat is ShaderMaterial, "ordinary modulation supports per-particle frames")
if DisplayServer.get_name() != "headless":
await pixels(mat)
else:
print("SKIP: texture animation pixels require a renderer")
fx.free()
print("effect_texture_animation_test: failures=%d" % failures)
quit(1 if failures else 0)
func pixels(material: ShaderMaterial) -> void:
var viewport := SubViewport.new()
viewport.size = Vector2i(96, 96)
viewport.own_world_3d = true
viewport.render_target_update_mode = SubViewport.UPDATE_ALWAYS
root.add_child(viewport)
var environment := WorldEnvironment.new()
environment.environment = Environment.new()
environment.environment.background_mode = Environment.BG_COLOR
environment.environment.background_color = Color.BLACK
viewport.add_child(environment)
var camera := Camera3D.new()
camera.projection = Camera3D.PROJECTION_ORTHOGONAL
camera.size = 3.0
camera.position.z = 3.0
viewport.add_child(camera)
var instance := MultiMeshInstance3D.new()
var mesh := QuadMesh.new()
mesh.size = Vector2(0.8, 0.8)
var multi := MultiMesh.new()
multi.transform_format = MultiMesh.TRANSFORM_3D
multi.use_custom_data = true
multi.use_colors = true
multi.mesh = mesh
multi.instance_count = 2
for i in 2:
multi.set_instance_transform(i, Transform3D(Basis.IDENTITY, Vector3(-0.6 + i * 1.2, 0, 0)))
multi.set_instance_color(i, Color.WHITE)
instance.multimesh = multi
instance.material_override = material
viewport.add_child(instance)
# Same material, different ages: old shared AnimatedTexture fails this.
for type in [0, 1, 2, 3, 4]:
material.set_shader_parameter("animation_type", type)
for age in [0.15, 0.25, 0.35]:
multi.set_instance_custom_data(0, Color(0, 0, 0.2, 0))
multi.set_instance_custom_data(1, Color(0, age, 0.2, 0))
await process_frame
await RenderingServer.frame_post_draw
var img := viewport.get_texture().get_image()
var newborn := img.get_pixel(29, 48)
check(newborn.r > 0.9 and newborn.g < 0.05, "newborn always starts at frame zero type=%d" % type)
var aged := img.get_pixel(67, 48)
if type in [0, 1, 2, 4]:
var step := int(floor(age / 0.1))
var index := 0 if type == 0 else posmod(-step if type == 2 else step, 3)
var channels := [aged.r, aged.g, aged.b]
check(channels[index] > 0.9, "age selects expected frame type=%d age=%s" % [type, age])
else:
check(maxf(aged.r, maxf(aged.g, aged.b)) > 0.9, "random frame selects one valid texture")
viewport.free()
await process_frame