Implement playable Mac client and rendering validation
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
extends SceneTree
|
||||
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()
|
||||
fx.build({"particles": [{"emitter": {"TimeEventLifeTime": [[0, 1.0]]}, "particle": {
|
||||
"BillboardType": 1, "RotationType": 4, "RotationSpeed": 90, "ColorOperationType": 4}}]})
|
||||
var emitter: GPUParticles3D = fx._emitters[0]
|
||||
var pm: ParticleProcessMaterial = emitter.process_material
|
||||
var material: ShaderMaterial = emitter.material_override
|
||||
check(pm.angular_velocity_min == 0 and pm.angular_velocity_max == 0, "no second angular integration")
|
||||
check(pm.anim_offset_min == 0 and pm.anim_offset_max == 1 and pm.anim_speed_max == 0, "stable per-birth sign seed")
|
||||
check(material.get_shader_parameter("random_rotation") == true, "random rotation enabled")
|
||||
check(is_equal_approx(material.get_shader_parameter("rotation_speed"), PI / 2), "full magnitude in radians")
|
||||
if DisplayServer.get_name() != "headless": await pixels(material)
|
||||
fx.free()
|
||||
print("effect_random_rotation_test: failures=%d" % failures)
|
||||
quit(1 if failures else 0)
|
||||
func pixels(material: ShaderMaterial) -> void:
|
||||
var viewport := SubViewport.new()
|
||||
viewport.size = Vector2i(128, 128)
|
||||
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 image := Image.create(2, 2, false, Image.FORMAT_RGBA8)
|
||||
image.fill(Color.WHITE)
|
||||
material.set_shader_parameter("albedo_texture", ImageTexture.create_from_image(image))
|
||||
material.set_shader_parameter("rotation_lifetime", 1.0)
|
||||
var node := MultiMeshInstance3D.new()
|
||||
node.multimesh = MultiMesh.new()
|
||||
node.multimesh.transform_format = MultiMesh.TRANSFORM_3D
|
||||
node.multimesh.use_custom_data = true
|
||||
node.multimesh.mesh = QuadMesh.new()
|
||||
node.multimesh.mesh.size = Vector2(1.2, 0.16)
|
||||
node.multimesh.instance_count = 1
|
||||
node.multimesh.set_instance_transform(0, Transform3D.IDENTITY)
|
||||
node.material_override = material
|
||||
viewport.add_child(node)
|
||||
var camera := Camera3D.new()
|
||||
camera.projection = Camera3D.PROJECTION_ORTHOGONAL
|
||||
camera.size = 2.0
|
||||
camera.position.z = 3
|
||||
viewport.add_child(camera)
|
||||
var results: Array[Image] = []
|
||||
for seed in [0.25, 0.75]:
|
||||
node.multimesh.set_instance_custom_data(0, Color(0, 0.5, seed, 1))
|
||||
await process_frame
|
||||
await RenderingServer.frame_post_draw
|
||||
results.append(viewport.get_texture().get_image())
|
||||
var positive := 0
|
||||
var negative := 0
|
||||
var mismatch := 0
|
||||
var lit := 0
|
||||
for y in 128:
|
||||
for x in 128:
|
||||
var a := results[0].get_pixel(x, y).r > 0.5
|
||||
var b := results[1].get_pixel(x, y).r > 0.5
|
||||
if a:
|
||||
lit += 1
|
||||
positive += (2 * x - 127) * (2 * y - 127)
|
||||
if b: negative += (2 * x - 127) * (2 * y - 127)
|
||||
if a != (results[1].get_pixel(127 - x, y).r > 0.5): mismatch += 1
|
||||
check(lit > 300, "rendered visible particles")
|
||||
check(positive * float(negative) < 0, "opposite rotation directions")
|
||||
check(mismatch < 60, "equal magnitude produces mirrored GPU images")
|
||||
viewport.free()
|
||||
await process_frame
|
||||
Reference in New Issue
Block a user