diff --git a/Assets/Compute Shaders/automata.acompute b/Assets/Compute Shaders/automata.acompute index 520f086..2c0aeae 100644 --- a/Assets/Compute Shaders/automata.acompute +++ b/Assets/Compute Shaders/automata.acompute @@ -9,16 +9,25 @@ layout(rgba8, set = 0, binding = 0) uniform image2D _RenderTarget; layout(r16f, set = 0, binding = 2) uniform image2D _AutomatonFrom; layout(r16f, set = 0, binding = 3) uniform image2D _AutomatonTo; +struct Neighborhood { + uint64_t upper_left_mask; + uint64_t upper_right_mask; + uint64_t lower_left_mask; + uint64_t lower_right_mask; +}; + layout(binding = 1) uniform UniformBufferObject { - vec4 _Exposure; + ivec4 _RuleRanges; + ivec4 _RuleRanges2; + ivec4 _RuleRanges3; + ivec4 _RuleRanges4; }; layout(push_constant, std430) uniform Params { - uint64_t _UpperLeftMask; - uint64_t _UpperRightMask; - uint64_t _LowerLeftMask; - uint64_t _LowerRightMask; - ivec4 _RuleRanges; + Neighborhood _Neighborhood1; + Neighborhood _Neighborhood2; + Neighborhood _Neighborhood3; + Neighborhood _Neighborhood4; }; float pseudo(vec2 v) { @@ -91,22 +100,55 @@ void Automaton() { // uint64_t lower_left_mask = 4557430888798814208UL & ~(top_row_mask); // uint64_t lower_right_mask = 18229723555195256832UL & ~(top_row_mask | left_column_mask); - uint64_t upper_left_mask = _UpperLeftMask; - uint64_t upper_right_mask = _UpperRightMask & ~(left_column_mask); - uint64_t lower_left_mask = _LowerLeftMask & ~(top_row_mask); - uint64_t lower_right_mask = _LowerRightMask & ~(top_row_mask | left_column_mask); + uint64_t upper_left_mask = _Neighborhood1.upper_left_mask; + uint64_t upper_right_mask = _Neighborhood1.upper_right_mask & ~(left_column_mask); + uint64_t lower_left_mask = _Neighborhood1.lower_left_mask & ~(top_row_mask); + uint64_t lower_right_mask = _Neighborhood1.lower_right_mask & ~(top_row_mask | left_column_mask); + + uint64_t upper_left_mask2 = _Neighborhood2.upper_left_mask; + uint64_t upper_right_mask2 = _Neighborhood2.upper_right_mask & ~(left_column_mask); + uint64_t lower_left_mask2 = _Neighborhood2.lower_left_mask & ~(top_row_mask); + uint64_t lower_right_mask2 = _Neighborhood2.lower_right_mask & ~(top_row_mask | left_column_mask); + + uint64_t upper_left_mask3 = _Neighborhood3.upper_left_mask; + uint64_t upper_right_mask3 = _Neighborhood3.upper_right_mask & ~(left_column_mask); + uint64_t lower_left_mask3 = _Neighborhood3.lower_left_mask & ~(top_row_mask); + uint64_t lower_right_mask3 = _Neighborhood3.lower_right_mask & ~(top_row_mask | left_column_mask); + + uint64_t upper_left_mask4 = _Neighborhood4.upper_left_mask; + uint64_t upper_right_mask4 = _Neighborhood4.upper_right_mask & ~(left_column_mask); + uint64_t lower_left_mask4 = _Neighborhood4.lower_left_mask & ~(top_row_mask); + uint64_t lower_right_mask4 = _Neighborhood4.lower_right_mask & ~(top_row_mask | left_column_mask); - uint64_t upper_left_quadrant_bits = encode_tile_to_uint(uv) & upper_left_mask; - uint64_t upper_right_quadrant_bits = encode_tile_to_uint(uv + ivec2(7, 0)) & upper_right_mask; - uint64_t lower_left_quadrant_bits = encode_tile_to_uint(uv + ivec2(0, 7)) & lower_left_mask; - uint64_t lower_right_quadrant_bits = encode_tile_to_uint(uv + ivec2(7, 7)) & lower_right_mask; + uint64_t upper_left_quadrant_bits = encode_tile_to_uint(uv); + uint64_t upper_right_quadrant_bits = encode_tile_to_uint(uv + ivec2(7, 0)); + uint64_t lower_left_quadrant_bits = encode_tile_to_uint(uv + ivec2(0, 7)); + uint64_t lower_right_quadrant_bits = encode_tile_to_uint(uv + ivec2(7, 7)); - uint neighbor_count = 0; - neighbor_count += sum_uint_bits(upper_left_quadrant_bits); - neighbor_count += sum_uint_bits(upper_right_quadrant_bits); - neighbor_count += sum_uint_bits(lower_left_quadrant_bits); - neighbor_count += sum_uint_bits(lower_right_quadrant_bits); + uint neighbor_count1 = 0; + neighbor_count1 += sum_uint_bits(upper_left_quadrant_bits & upper_left_mask); + neighbor_count1 += sum_uint_bits(upper_right_quadrant_bits & upper_right_mask); + neighbor_count1 += sum_uint_bits(lower_left_quadrant_bits & lower_left_mask); + neighbor_count1 += sum_uint_bits(lower_right_quadrant_bits & lower_right_mask); + + uint neighbor_count2 = 0; + neighbor_count2 += sum_uint_bits(upper_left_quadrant_bits & upper_left_mask2); + neighbor_count2 += sum_uint_bits(upper_right_quadrant_bits & upper_right_mask2); + neighbor_count2 += sum_uint_bits(lower_left_quadrant_bits & lower_left_mask2); + neighbor_count2 += sum_uint_bits(lower_right_quadrant_bits & lower_right_mask2); + + uint neighbor_count3 = 0; + neighbor_count3 += sum_uint_bits(upper_left_quadrant_bits & upper_left_mask3); + neighbor_count3 += sum_uint_bits(upper_right_quadrant_bits & upper_right_mask3); + neighbor_count3 += sum_uint_bits(lower_left_quadrant_bits & lower_left_mask3); + neighbor_count3 += sum_uint_bits(lower_right_quadrant_bits & lower_right_mask3); + + uint neighbor_count4 = 0; + neighbor_count4 += sum_uint_bits(upper_left_quadrant_bits & upper_left_mask4); + neighbor_count4 += sum_uint_bits(upper_right_quadrant_bits & upper_right_mask4); + neighbor_count4 += sum_uint_bits(lower_left_quadrant_bits & lower_left_mask4); + neighbor_count4 += sum_uint_bits(lower_right_quadrant_bits & lower_right_mask4); // for (int x = -1; x <= 1; ++x) { @@ -124,9 +166,34 @@ void Automaton() { // if (neighbor_count == 3) cell = 1; // if (neighbor_count >= 4) cell = 0; - if (_RuleRanges.x <= neighbor_count && neighbor_count <= _RuleRanges.y) { // Spawn + + if (_RuleRanges.x <= neighbor_count1 && neighbor_count1 <= _RuleRanges.y) { // Spawn cell = 1; - } else if (_RuleRanges.z <= neighbor_count && neighbor_count <= _RuleRanges.w) { // Stable + } else if (_RuleRanges.z <= neighbor_count1 && neighbor_count1 <= _RuleRanges.w) { // Stable + cell = cell; + } else { + cell = 0; // RIP + } + + if (_RuleRanges2.x <= neighbor_count2 && neighbor_count2 <= _RuleRanges2.y) { // Spawn + cell = 1; + } else if (_RuleRanges2.z <= neighbor_count2 && neighbor_count2 <= _RuleRanges2.w) { // Stable + cell = cell; + } else { + cell = 0; // RIP + } + + if (_RuleRanges3.x <= neighbor_count3 && neighbor_count3 <= _RuleRanges3.y) { // Spawn + cell = 1; + } else if (_RuleRanges3.z <= neighbor_count3 && neighbor_count3 <= _RuleRanges3.w) { // Stable + cell = cell; + } else { + cell = 0; // RIP + } + + if (_RuleRanges4.x <= neighbor_count4 && neighbor_count4 <= _RuleRanges4.y) { // Spawn + cell = 1; + } else if (_RuleRanges4.z <= neighbor_count4 && neighbor_count4 <= _RuleRanges4.w) { // Stable cell = cell; } else { cell = 0; // RIP @@ -139,7 +206,7 @@ void Automaton() { void Blit() { ivec2 uv = ivec2(gl_GlobalInvocationID.xy); - float automata = imageLoad(_AutomatonTo, uv).r; + float automata = imageLoad(_AutomatonTo, uv / 2).r; imageStore(_RenderTarget, uv, vec4(automata, 0, 0, 1.0)); } \ No newline at end of file diff --git a/Assets/Scenes/main.tscn b/Assets/Scenes/main.tscn index 3e10202..96893a2 100644 --- a/Assets/Scenes/main.tscn +++ b/Assets/Scenes/main.tscn @@ -47,7 +47,7 @@ needs_motion_vectors = false needs_normal_roughness = false script = ExtResource("1_vlji8") pause = false -update_speed = 0.025 +update_speed = 0.001 exposure = Vector4(2, 1, 1, 1) metadata/_custom_type_script = "uid://drfxlavovcgta" @@ -100,8 +100,8 @@ blend_mode = 2 [sub_resource type="ShaderMaterial" id="ShaderMaterial_052nx"] shader = ExtResource("36_l2vhu") -shader_parameter/first_color = Color(0.147984, 0.050227, 0.0839159, 1) -shader_parameter/second_color = Color(0.743183, 0.702316, 0.71273, 1) +shader_parameter/first_color = Color(0.120647, 0.229811, 0.120427, 1) +shader_parameter/second_color = Color(0.449922, 0.532924, 0.299953, 1) [node name="Node3D" type="Node3D"] diff --git a/Assets/Scripts/automata_compositor_effect.gd b/Assets/Scripts/automata_compositor_effect.gd index 526bc4f..d52f12f 100644 --- a/Assets/Scripts/automata_compositor_effect.gd +++ b/Assets/Scripts/automata_compositor_effect.gd @@ -106,17 +106,15 @@ func _render_callback(p_effect_callback_type, p_render_data): var automaton = GameMaster.get_active_automaton() if not automaton: return - var rule_ranges = automaton.get_rule_ranges() - var neighborhood_bytes = automaton.get_neighorhood_bytes().slice(0, 32) - - push_constant.append_array(neighborhood_bytes) - push_constant.append_array(PackedInt32Array([rule_ranges[0], rule_ranges[1], rule_ranges[2], rule_ranges[3]]).to_byte_array()) + # print("neighborhood_bytes: ") + # print(neighborhood_bytes) + push_constant.append_array(automaton.get_neighorhood_bytes()) # print(push_constant) for view in range(render_scene_buffers.get_view_count()): # Pack the exposure vector into a byte array - var uniform_array = PackedFloat32Array([exposure.x, exposure.y, exposure.z, exposure.w]).to_byte_array() + var uniform_array = PackedInt32Array(automaton.get_rule_ranges()).to_byte_array() # ACompute handles uniform caching under the hood, as long as the exposure value doesn't change or the render target doesn't change, these functions will only do work once exposure_compute.set_texture(0, world_texture) diff --git a/Assets/Scripts/neighborhood_wizard.gd b/Assets/Scripts/neighborhood_wizard.gd index b2d443a..ffef65f 100644 --- a/Assets/Scripts/neighborhood_wizard.gd +++ b/Assets/Scripts/neighborhood_wizard.gd @@ -103,10 +103,10 @@ func encode_grid_to_neighborhood_bytes() -> void: byte_array.encode_u8(y + 7, byte_string.bin_to_int()) - for i in range(0, 8): print(byte_strings[7 - i]) + # for i in range(0, 8): print(byte_strings[7 - i]) - print(byte_array) - print(neighborhood.get_neighborhood_bytes()) + # print(byte_array) + # print(neighborhood.get_neighborhood_bytes()) upper_left_quadrant = PackedByteArray(byte_array)