From 4521ade24821956f1c3def4dec5ca1d8fbafebbe Mon Sep 17 00:00:00 2001 From: Niels CHRISTOPH Date: Wed, 5 Mar 2025 10:01:36 +0100 Subject: [PATCH 01/20] premier commit --- examples/ProjetAAP/Node2D.tscn | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 examples/ProjetAAP/Node2D.tscn diff --git a/examples/ProjetAAP/Node2D.tscn b/examples/ProjetAAP/Node2D.tscn new file mode 100644 index 0000000..5f4a7b0 --- /dev/null +++ b/examples/ProjetAAP/Node2D.tscn @@ -0,0 +1,23 @@ +[gd_scene load_steps=3 format=3 uid="uid://u25v40csc7a8"] + +[ext_resource type="Script" path="res://addons/compute_shader_studio/compute_shader_studio_2d.gd" id="1_rt15t"] +[ext_resource type="Texture2D" uid="uid://demftcowdd5c6" path="res://examples/icon.svg" id="2_2cd5v"] + +[node name="Node2d" type="Node2D"] + +[node name="ComputeShaderStudio2D" type="Node" parent="." node_paths=PackedStringArray("data")] +script = ExtResource("1_rt15t") +GLSL_code = " +// Write your code HERE +void main() { + uint x = gl_GlobalInvocationID.x; + uint y = gl_GlobalInvocationID.y; + uint p = x + y * WSX; + data_0[p] = 0xFFF00FFF - int(p)*(step+1); +} +" +data = [NodePath("../Icon")] + +[node name="Icon" type="Sprite2D" parent="."] +position = Vector2(228, 133) +texture = ExtResource("2_2cd5v") From c059539eaa13d311c862b72e90f6e34f3f109810 Mon Sep 17 00:00:00 2001 From: zPrisim <76958083+zPrisim@users.noreply.github.com> Date: Mon, 10 Mar 2025 00:59:25 +0100 Subject: [PATCH 02/20] Premiers tests --- examples/ProjetAAP/Node2D.tscn | 21 ++++----- examples/ProjetAAP/script.cpp | 86 ++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 13 deletions(-) create mode 100644 examples/ProjetAAP/script.cpp diff --git a/examples/ProjetAAP/Node2D.tscn b/examples/ProjetAAP/Node2D.tscn index 5f4a7b0..3ca3c3a 100644 --- a/examples/ProjetAAP/Node2D.tscn +++ b/examples/ProjetAAP/Node2D.tscn @@ -1,23 +1,18 @@ -[gd_scene load_steps=3 format=3 uid="uid://u25v40csc7a8"] +[gd_scene load_steps=2 format=3 uid="uid://u25v40csc7a8"] [ext_resource type="Script" path="res://addons/compute_shader_studio/compute_shader_studio_2d.gd" id="1_rt15t"] -[ext_resource type="Texture2D" uid="uid://demftcowdd5c6" path="res://examples/icon.svg" id="2_2cd5v"] [node name="Node2d" type="Node2D"] [node name="ComputeShaderStudio2D" type="Node" parent="." node_paths=PackedStringArray("data")] script = ExtResource("1_rt15t") +WSX = 800 +WSY = 450 +glsl_file = "res://examples/ProjetAAP/script.cpp" GLSL_code = " -// Write your code HERE -void main() { - uint x = gl_GlobalInvocationID.x; - uint y = gl_GlobalInvocationID.y; - uint p = x + y * WSX; - data_0[p] = 0xFFF00FFF - int(p)*(step+1); -} " -data = [NodePath("../Icon")] +data = [NodePath("../TextureRect")] -[node name="Icon" type="Sprite2D" parent="."] -position = Vector2(228, 133) -texture = ExtResource("2_2cd5v") +[node name="TextureRect" type="TextureRect" parent="."] +offset_right = 800.0 +offset_bottom = 450.0 diff --git a/examples/ProjetAAP/script.cpp b/examples/ProjetAAP/script.cpp new file mode 100644 index 0000000..98af020 --- /dev/null +++ b/examples/ProjetAAP/script.cpp @@ -0,0 +1,86 @@ +#define MORT 0xFFFFFFFF +#define VIVANT 0xFF000000 + +layout(set = 0, binding = 0) buffer incBuffer +{ + uint incX; + uint incY; +}; +struct color +{ + int b; + int g; + int r; + float a; +}; + +void dessinerSphere(uint centerX, uint centerY, float radius, color c) +{ + vec2 center = vec2(centerX, centerY); + + // Coordonnees du pixel actuel + uint x = gl_GlobalInvocationID.x; + uint y = gl_GlobalInvocationID.y; + + if (x < WSX && y < WSY) + { + // Calculer la position du pixel + uint p = x + y * WSX; + + // Calculer la distance au carre entre le pixel et le centre du cercle + vec2 delta = vec2(x, y) - center; + float distanceSquared = dot(delta, delta); + + // Si le pixel est a l'interieur du cercle, le marquer comme "vivant" + if (distanceSquared <= radius * radius) + { + data_0[p] = + (int(c.a) << 24) | // ALPHA + (c.b << 16) | // BLEU + (c.g << 8) | // VERT + (c.r); // ROUGE + } + else + { + data_0[p] = MORT; + } + } +} + +void main() +{ + // Coordonnees du pixel actuel + uint x = gl_GlobalInvocationID.x; + uint y = gl_GlobalInvocationID.y; + uint p = x + y * WSX; + + int rayon = 50; + + color c = {132, 0, 255, 0.8f * 255.0f}; // bgra + + /* + if (rayon + step + rayon < 800) + { + dessinerSphere(rayon + incX, rayon, rayon, c); + incX++; + } +*/ + + if (incX + rayon * 2 < 800 && incX - rayon >= 0) + { + dessinerSphere(rayon + incX, rayon, rayon, c); + incX++; + } + else + { + dessinerSphere(rayon + incX, rayon, rayon, c); + incX--; + } + /* + if (incY + rayon < 450 ) + { + dessinerSphere(rayon, rayon + incY, rayon, c); + incY++; + }*/ + // Dessiner la sphere pour chaque pixel +} \ No newline at end of file From 2ba4d54ac50d07ab5249a4a7a69a071795734b54 Mon Sep 17 00:00:00 2001 From: zPrisim <76958083+zPrisim@users.noreply.github.com> Date: Mon, 10 Mar 2025 17:45:55 +0100 Subject: [PATCH 03/20] suite tests --- .vscode/settings.json | 3 + examples/ProjetAAP/script.cpp | 86 -------------- examples/{ProjetAAP => maze}/Node2D.tscn | 12 +- examples/maze/fond.jpeg | Bin 0 -> 83325 bytes examples/maze/fond.jpeg.import | 34 ++++++ examples/maze/maze.cpp | 23 ++++ examples/maze/script.cpp | 137 +++++++++++++++++++++++ project.godot | 6 + 8 files changed, 212 insertions(+), 89 deletions(-) create mode 100644 .vscode/settings.json delete mode 100644 examples/ProjetAAP/script.cpp rename examples/{ProjetAAP => maze}/Node2D.tscn (52%) create mode 100644 examples/maze/fond.jpeg create mode 100644 examples/maze/fond.jpeg.import create mode 100644 examples/maze/maze.cpp create mode 100644 examples/maze/script.cpp diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..70e34ec --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "C_Cpp.errorSquiggles": "disabled" +} \ No newline at end of file diff --git a/examples/ProjetAAP/script.cpp b/examples/ProjetAAP/script.cpp deleted file mode 100644 index 98af020..0000000 --- a/examples/ProjetAAP/script.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#define MORT 0xFFFFFFFF -#define VIVANT 0xFF000000 - -layout(set = 0, binding = 0) buffer incBuffer -{ - uint incX; - uint incY; -}; -struct color -{ - int b; - int g; - int r; - float a; -}; - -void dessinerSphere(uint centerX, uint centerY, float radius, color c) -{ - vec2 center = vec2(centerX, centerY); - - // Coordonnees du pixel actuel - uint x = gl_GlobalInvocationID.x; - uint y = gl_GlobalInvocationID.y; - - if (x < WSX && y < WSY) - { - // Calculer la position du pixel - uint p = x + y * WSX; - - // Calculer la distance au carre entre le pixel et le centre du cercle - vec2 delta = vec2(x, y) - center; - float distanceSquared = dot(delta, delta); - - // Si le pixel est a l'interieur du cercle, le marquer comme "vivant" - if (distanceSquared <= radius * radius) - { - data_0[p] = - (int(c.a) << 24) | // ALPHA - (c.b << 16) | // BLEU - (c.g << 8) | // VERT - (c.r); // ROUGE - } - else - { - data_0[p] = MORT; - } - } -} - -void main() -{ - // Coordonnees du pixel actuel - uint x = gl_GlobalInvocationID.x; - uint y = gl_GlobalInvocationID.y; - uint p = x + y * WSX; - - int rayon = 50; - - color c = {132, 0, 255, 0.8f * 255.0f}; // bgra - - /* - if (rayon + step + rayon < 800) - { - dessinerSphere(rayon + incX, rayon, rayon, c); - incX++; - } -*/ - - if (incX + rayon * 2 < 800 && incX - rayon >= 0) - { - dessinerSphere(rayon + incX, rayon, rayon, c); - incX++; - } - else - { - dessinerSphere(rayon + incX, rayon, rayon, c); - incX--; - } - /* - if (incY + rayon < 450 ) - { - dessinerSphere(rayon, rayon + incY, rayon, c); - incY++; - }*/ - // Dessiner la sphere pour chaque pixel -} \ No newline at end of file diff --git a/examples/ProjetAAP/Node2D.tscn b/examples/maze/Node2D.tscn similarity index 52% rename from examples/ProjetAAP/Node2D.tscn rename to examples/maze/Node2D.tscn index 3ca3c3a..f128ab8 100644 --- a/examples/ProjetAAP/Node2D.tscn +++ b/examples/maze/Node2D.tscn @@ -1,6 +1,7 @@ -[gd_scene load_steps=2 format=3 uid="uid://u25v40csc7a8"] +[gd_scene load_steps=3 format=3 uid="uid://u25v40csc7a8"] [ext_resource type="Script" path="res://addons/compute_shader_studio/compute_shader_studio_2d.gd" id="1_rt15t"] +[ext_resource type="Texture2D" uid="uid://demftcowdd5c6" path="res://examples/icon.svg" id="2_dqgei"] [node name="Node2d" type="Node2D"] @@ -8,11 +9,16 @@ script = ExtResource("1_rt15t") WSX = 800 WSY = 450 -glsl_file = "res://examples/ProjetAAP/script.cpp" +glsl_file = "res://examples/Maze/script.cpp" GLSL_code = " " -data = [NodePath("../TextureRect")] +data = [NodePath("../Icon")] + +[node name="Icon" type="Sprite2D" parent="."] +position = Vector2(387, 241) +texture = ExtResource("2_dqgei") [node name="TextureRect" type="TextureRect" parent="."] offset_right = 800.0 offset_bottom = 450.0 +mouse_default_cursor_shape = 3 diff --git a/examples/maze/fond.jpeg b/examples/maze/fond.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..9db99f8718a3fae04438d7b447ae3501617c7de6 GIT binary patch literal 83325 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�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 literal 0 HcmV?d00001 diff --git a/examples/maze/fond.jpeg.import b/examples/maze/fond.jpeg.import new file mode 100644 index 0000000..8ce5642 --- /dev/null +++ b/examples/maze/fond.jpeg.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dkblk2yh4bwkm" +path="res://.godot/imported/fond.jpeg-3499da06496c60de12e0e6b8937f72d1.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://examples/maze/fond.jpeg" +dest_files=["res://.godot/imported/fond.jpeg-3499da06496c60de12e0e6b8937f72d1.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/examples/maze/maze.cpp b/examples/maze/maze.cpp new file mode 100644 index 0000000..a7cf901 --- /dev/null +++ b/examples/maze/maze.cpp @@ -0,0 +1,23 @@ +#define MORT 0xFFFFFFFF + + + + + + + +void main() +{ + ivec2 pos = ivec2(gl_GlobalInvocationID.xy); + uint p = pos.x + pos.y * WSX; + + + + + + + + data_0[p] = MORT; + + +} \ No newline at end of file diff --git a/examples/maze/script.cpp b/examples/maze/script.cpp new file mode 100644 index 0000000..05f4185 --- /dev/null +++ b/examples/maze/script.cpp @@ -0,0 +1,137 @@ +#define MORT 0xFFFFFFFF +#define VIVANT 0xFF000000 + +//shared uint incX; + +/*layout(set = 0, binding = 0) buffer incBuffer +{ + uint incX; + uint incY; +};*/ + + + +struct color +{ + int r; + int g; + int b; +}; + + +int rgb_to_int(color c) { + return 0xFF000000 + | int(c.r) + | int(c.g) << 8 + | int(c.b) << 16; +} + +void dessinerSphere(uint centerX, uint centerY, float radius, color c) +{ + vec2 center = vec2(centerX, centerY); + + // Coordonnees du pixel actuel + ivec2 pos = ivec2(gl_GlobalInvocationID.xy); + + // Calculer la position du pixel + uint p = pos.x + pos.y * WSX; + + // Calculer la distance au carre entre le pixel et le centre du cercle + vec2 delta = pos - center; + float distanceCarre = dot(delta, delta); + + // Si le pixel est a l'interieur du cercle + if ( distanceCarre <= radius * radius) + { + data_0[p] = rgb_to_int(c); // ROUGE + } + +} + + + + +void main() +{ + + // Coordonnees du pixel actuel + ivec2 pos = ivec2(gl_GlobalInvocationID.xy); + uint p = pos.x + pos.y * WSX; + + int rayon = 50; + color c = {255, 0, 132}; // bgra + color c1 = {110, 50, 150 }; // bgra + color c2 = {255, 25, 87 }; // bgra + color c3 = {30, 0, 16 }; // bgra + + + /* + if (rayon + step + rayon < 800) + { + dessinerSphere(rayon + incX, rayon, rayon, c); + incX++; + } +*/ + + + //data_0[p] = MORT; + + if ((mousex >= 0 && gl_GlobalInvocationID.x == mousex) + || (mousey >= 0 && gl_GlobalInvocationID.y == mousey)) + { + + } + //dessinerSphere( uint(mousex), uint(mousey) , rayon, c1); + + data_0[p] = MORT; + + dessinerSphere( mousex , mousey , rayon, c1); + + + /* + if(pos.x < 400 && pos.y < 225) + { + dessinerSphere( incX*2, incX , incX, c); + } + else + { + dessinerSphere( incX*2, incX , 40 , c); + } + + for(uint i = 0; i < 800; i+=100) + { + for (uint j = 0; j < 450; j+=50) + { + dessinerSphere( i , j , rayon, c1); + } + } + */ + /* + dessinerSphere( 150 , 50 , rayon, c1); + dessinerSphere( 250 , 50 , rayon, c2); + dessinerSphere( 350 , 50 , rayon, c3); + dessinerSphere( 450 , 50, rayon, c); + dessinerSphere( 550 , 50 , rayon, c1); + dessinerSphere( 650 , 50 , rayon, c2); + dessinerSphere( 750 , 50 , rayon, c3); + + dessinerSphere( 100 , incX , rayon*2, c1); + dessinerSphere( 300 , 200 , rayon*2, c2); + */ + //incX++; + + + /*else + { + dessinerSphere(rayon + incX, rayon, rayon, c); + incX--; + } + */ + /* + if (incY + rayon < 450 ) + { + dessinerSphere(rayon, rayon + incY, rayon, c); + incY++; + }*/ + // Dessiner la sphere pour chaque pixel +} \ No newline at end of file diff --git a/project.godot b/project.godot index 725be9c..4b83996 100644 --- a/project.godot +++ b/project.godot @@ -15,6 +15,12 @@ run/main_scene="res://examples/example_1.tscn" config/features=PackedStringArray("4.3", "Forward Plus") config/icon="res://addons/compute_shader_studio/icon.png" +[display] + +window/size/viewport_width=800 +window/size/viewport_height=450 +window/size/initial_position_type=0 + [editor_plugins] enabled=PackedStringArray("res://addons/compute_shader_studio/plugin.cfg") From e4574311754677eba8c6fed1deceb5d89293355b Mon Sep 17 00:00:00 2001 From: zPrisim <76958083+zPrisim@users.noreply.github.com> Date: Mon, 10 Mar 2025 23:53:36 +0100 Subject: [PATCH 04/20] tests inputs --- .../compute_shader_studio_2d.gd | 5 + examples/example_mandelbrot.tscn | 6 + examples/maze/fond.jpeg | Bin 83325 -> 0 bytes examples/maze/fond.jpeg.import | 34 ----- examples/maze/script.cpp | 70 +++++----- examples/{maze => tron}/Node2D.tscn | 21 +-- examples/tron/script.cpp | 122 ++++++++++++++++++ examples/{maze/maze.cpp => tron/tron.cpp} | 0 project.godot | 12 ++ 9 files changed, 186 insertions(+), 84 deletions(-) delete mode 100644 examples/maze/fond.jpeg delete mode 100644 examples/maze/fond.jpeg.import rename examples/{maze => tron}/Node2D.tscn (60%) create mode 100644 examples/tron/script.cpp rename examples/{maze/maze.cpp => tron/tron.cpp} (100%) diff --git a/addons/compute_shader_studio/compute_shader_studio_2d.gd b/addons/compute_shader_studio/compute_shader_studio_2d.gd index f947c2f..aba364e 100644 --- a/addons/compute_shader_studio/compute_shader_studio_2d.gd +++ b/addons/compute_shader_studio/compute_shader_studio_2d.gd @@ -29,6 +29,7 @@ layout(binding = 0) buffer Params { int current_pass; int mousex; int mousey; + bool left_pressed; }; """ @@ -271,6 +272,10 @@ func _update_uniforms(): input_params.append(pos.x) input_params.append(pos.y) + var left_pressed : bool = Input.is_action_just_pressed("mouse_click") + input_params.append(left_pressed) + + var input_params_bytes := input_params.to_byte_array() buffer_params = rd.storage_buffer_create(input_params_bytes.size(), input_params_bytes) uniform_params = RDUniform.new() diff --git a/examples/example_mandelbrot.tscn b/examples/example_mandelbrot.tscn index a5e532c..faa22cc 100644 --- a/examples/example_mandelbrot.tscn +++ b/examples/example_mandelbrot.tscn @@ -9,9 +9,15 @@ script = ExtResource("1_5gp20") [node name="ComputeShaderStudio2D" type="Node" parent="." node_paths=PackedStringArray("data")] script = ExtResource("1_t5cx1") +print_step = null +print_passes = null +print_generated_code = null +pause = null +nb_passes = null WSX = 512 WSY = 512 glsl_file = "res://examples/example_mandelbrot.cpp" +GLSL_code = null data = [NodePath("../mandelbrot"), NodePath("../julia")] [node name="mandelbrot" type="Sprite2D" parent="."] diff --git a/examples/maze/fond.jpeg b/examples/maze/fond.jpeg deleted file mode 100644 index 9db99f8718a3fae04438d7b447ae3501617c7de6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 83325 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�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 diff --git a/examples/maze/fond.jpeg.import b/examples/maze/fond.jpeg.import deleted file mode 100644 index 8ce5642..0000000 --- a/examples/maze/fond.jpeg.import +++ /dev/null @@ -1,34 +0,0 @@ -[remap] - -importer="texture" -type="CompressedTexture2D" -uid="uid://dkblk2yh4bwkm" -path="res://.godot/imported/fond.jpeg-3499da06496c60de12e0e6b8937f72d1.ctex" -metadata={ -"vram_texture": false -} - -[deps] - -source_file="res://examples/maze/fond.jpeg" -dest_files=["res://.godot/imported/fond.jpeg-3499da06496c60de12e0e6b8937f72d1.ctex"] - -[params] - -compress/mode=0 -compress/high_quality=false -compress/lossy_quality=0.7 -compress/hdr_compression=1 -compress/normal_map=0 -compress/channel_pack=0 -mipmaps/generate=false -mipmaps/limit=-1 -roughness/mode=0 -roughness/src_normal="" -process/fix_alpha_border=true -process/premult_alpha=false -process/normal_map_invert_y=false -process/hdr_as_srgb=false -process/hdr_clamp_exposure=false -process/size_limit=0 -detect_3d/compress_to=1 diff --git a/examples/maze/script.cpp b/examples/maze/script.cpp index 05f4185..1fa417e 100644 --- a/examples/maze/script.cpp +++ b/examples/maze/script.cpp @@ -1,29 +1,24 @@ #define MORT 0xFFFFFFFF #define VIVANT 0xFF000000 -//shared uint incX; +// shared uint incX; -/*layout(set = 0, binding = 0) buffer incBuffer +layout(set = 0, binding = 0) buffer incBuffer { uint incX; uint incY; -};*/ - - +}; struct color { - int r; - int g; - int b; + uint r; + uint g; + uint b; }; - -int rgb_to_int(color c) { - return 0xFF000000 - | int(c.r) - | int(c.g) << 8 - | int(c.b) << 16; +int rgb_to_int(color c) +{ + return 0xFF000000 | int(c.r) | int(c.g) << 8 | int(c.b) << 16; } void dessinerSphere(uint centerX, uint centerY, float radius, color c) @@ -38,19 +33,15 @@ void dessinerSphere(uint centerX, uint centerY, float radius, color c) // Calculer la distance au carre entre le pixel et le centre du cercle vec2 delta = pos - center; - float distanceCarre = dot(delta, delta); + float distanceCarre = dot(delta, delta); // Si le pixel est a l'interieur du cercle - if ( distanceCarre <= radius * radius) + if (distanceCarre <= radius * radius) { - data_0[p] = rgb_to_int(c); // ROUGE + data_0[p] = rgb_to_int(c) + step; // ROUGE } - } - - - void main() { @@ -59,11 +50,10 @@ void main() uint p = pos.x + pos.y * WSX; int rayon = 50; - color c = {255, 0, 132}; // bgra - color c1 = {110, 50, 150 }; // bgra - color c2 = {255, 25, 87 }; // bgra - color c3 = {30, 0, 16 }; // bgra - + color c = {255, 0, 132}; // bgra + color c1 = {110, 50, 150}; // bgra + color c2 = {255, 25, 87}; // bgra + color c3 = {30, 0, 16}; // bgra /* if (rayon + step + rayon < 800) @@ -73,26 +63,27 @@ void main() } */ + // data_0[p] = MORT; - //data_0[p] = MORT; + // dessinerSphere( uint(mousex), uint(mousey) , rayon, c1); - if ((mousex >= 0 && gl_GlobalInvocationID.x == mousex) - || (mousey >= 0 && gl_GlobalInvocationID.y == mousey)) - { - - } - //dessinerSphere( uint(mousex), uint(mousey) , rayon, c1); - - data_0[p] = MORT; - - dessinerSphere( mousex , mousey , rayon, c1); + if(step == 0) + data_0[p] = MORT; + /* + if ((mousex >= 0) || (mousey >= 0)) + { + dessinerSphere(mousex, mousey, rayon, c1); + } + */ + if(left_pressed) + dessinerSphere(mousex, mousey, rayon, c1); /* if(pos.x < 400 && pos.y < 225) { dessinerSphere( incX*2, incX , incX, c); - } + } else { dessinerSphere( incX*2, incX , 40 , c); @@ -118,9 +109,8 @@ void main() dessinerSphere( 100 , incX , rayon*2, c1); dessinerSphere( 300 , 200 , rayon*2, c2); */ - //incX++; + // incX++; - /*else { dessinerSphere(rayon + incX, rayon, rayon, c); diff --git a/examples/maze/Node2D.tscn b/examples/tron/Node2D.tscn similarity index 60% rename from examples/maze/Node2D.tscn rename to examples/tron/Node2D.tscn index f128ab8..c76b129 100644 --- a/examples/maze/Node2D.tscn +++ b/examples/tron/Node2D.tscn @@ -1,12 +1,17 @@ [gd_scene load_steps=3 format=3 uid="uid://u25v40csc7a8"] -[ext_resource type="Script" path="res://addons/compute_shader_studio/compute_shader_studio_2d.gd" id="1_rt15t"] -[ext_resource type="Texture2D" uid="uid://demftcowdd5c6" path="res://examples/icon.svg" id="2_dqgei"] +[ext_resource type="Script" path="res://addons/compute_shader_studio/compute_shader_studio_2d.gd" id="1_ng0hm"] +[ext_resource type="Texture2D" uid="uid://demftcowdd5c6" path="res://examples/icon.svg" id="2_gn2m0"] [node name="Node2d" type="Node2D"] [node name="ComputeShaderStudio2D" type="Node" parent="." node_paths=PackedStringArray("data")] -script = ExtResource("1_rt15t") +script = ExtResource("1_ng0hm") +print_step = null +print_passes = null +print_generated_code = null +pause = null +nb_passes = null WSX = 800 WSY = 450 glsl_file = "res://examples/Maze/script.cpp" @@ -15,10 +20,6 @@ GLSL_code = " data = [NodePath("../Icon")] [node name="Icon" type="Sprite2D" parent="."] -position = Vector2(387, 241) -texture = ExtResource("2_dqgei") - -[node name="TextureRect" type="TextureRect" parent="."] -offset_right = 800.0 -offset_bottom = 450.0 -mouse_default_cursor_shape = 3 +position = Vector2(400.5, 226) +scale = Vector2(6.25781, 3.53125) +texture = ExtResource("2_gn2m0") diff --git a/examples/tron/script.cpp b/examples/tron/script.cpp new file mode 100644 index 0000000..8b911fa --- /dev/null +++ b/examples/tron/script.cpp @@ -0,0 +1,122 @@ +#define MORT 0xFFFFFFFF +#define VIVANT 0xFF000000 + +// shared uint incX; + +/*layout(set = 0, binding = 0) buffer incBuffer +{ + uint incX; + uint incY; +};*/ + +struct color +{ + int r; + int g; + int b; +}; + +int rgb_to_int(color c) +{ + return 0xFF000000 | int(c.r) | int(c.g) << 8 | int(c.b) << 16; +} + +void dessinerSphere(uint centerX, uint centerY, float radius, color c) +{ + vec2 center = vec2(centerX, centerY); + + // Coordonnees du pixel actuel + ivec2 pos = ivec2(gl_GlobalInvocationID.xy); + + // Calculer la position du pixel + uint p = pos.x + pos.y * WSX; + + // Calculer la distance au carre entre le pixel et le centre du cercle + vec2 delta = pos - center; + float distanceCarre = dot(delta, delta); + + // Si le pixel est a l'interieur du cercle + if (distanceCarre <= radius * radius) + { + data_0[p] = rgb_to_int(c); // ROUGE + } +} + +void main() +{ + + // Coordonnees du pixel actuel + ivec2 pos = ivec2(gl_GlobalInvocationID.xy); + uint p = pos.x + pos.y * WSX; + + int rayon = 50; + color c = {255, 0, 132}; // bgra + color c1 = {110, 50, 150}; // bgra + color c2 = {255, 25, 87}; // bgra + color c3 = {30, 0, 16}; // bgra + + /* + if (rayon + step + rayon < 800) + { + dessinerSphere(rayon + incX, rayon, rayon, c); + incX++; + } +*/ + + // data_0[p] = MORT; + + // dessinerSphere( uint(mousex), uint(mousey) , rayon, c1); + + data_0[p] = MORT; + + if ((mousex >= 0) || (mousey >= 0)) + { + dessinerSphere(mousex, mousey, rayon, c1); + } + + /* + if(pos.x < 400 && pos.y < 225) + { + dessinerSphere( incX*2, incX , incX, c); + } + else + { + dessinerSphere( incX*2, incX , 40 , c); + } + + for(uint i = 0; i < 800; i+=100) + { + for (uint j = 0; j < 450; j+=50) + { + dessinerSphere( i , j , rayon, c1); + } + } + */ + /* + dessinerSphere( 150 , 50 , rayon, c1); + dessinerSphere( 250 , 50 , rayon, c2); + dessinerSphere( 350 , 50 , rayon, c3); + dessinerSphere( 450 , 50, rayon, c); + dessinerSphere( 550 , 50 , rayon, c1); + dessinerSphere( 650 , 50 , rayon, c2); + dessinerSphere( 750 , 50 , rayon, c3); + + dessinerSphere( 100 , incX , rayon*2, c1); + dessinerSphere( 300 , 200 , rayon*2, c2); + */ + // incX++; + + /*else + { + dessinerSphere(rayon + incX, rayon, rayon, c); + incX--; + } + */ + /* + if (incY + rayon < 450 ) + { + dessinerSphere(rayon, rayon + incY, rayon, c); + incY++; + }*/ + // Dessiner la sphere pour chaque pixel +} \ No newline at end of file diff --git a/examples/maze/maze.cpp b/examples/tron/tron.cpp similarity index 100% rename from examples/maze/maze.cpp rename to examples/tron/tron.cpp diff --git a/project.godot b/project.godot index 4b83996..2dec6e4 100644 --- a/project.godot +++ b/project.godot @@ -21,6 +21,18 @@ window/size/viewport_width=800 window/size/viewport_height=450 window/size/initial_position_type=0 +[dotnet] + +project/assembly_name="compute_shader_studio" + [editor_plugins] enabled=PackedStringArray("res://addons/compute_shader_studio/plugin.cfg") + +[input] + +mouse_click={ +"deadzone": 0.5, +"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":1,"canceled":false,"pressed":false,"double_click":false,"script":null) +] +} From 269f44fc9ed6110d3cf6cda00b0ac003c0f23802 Mon Sep 17 00:00:00 2001 From: zPrisim <76958083+zPrisim@users.noreply.github.com> Date: Tue, 11 Mar 2025 08:19:05 +0100 Subject: [PATCH 05/20] fix pre-projet --- examples/maze/script.cpp | 127 -------------------------------------- examples/tron/Node2D.tscn | 2 +- examples/tron/script.cpp | 60 +++--------------- 3 files changed, 8 insertions(+), 181 deletions(-) delete mode 100644 examples/maze/script.cpp diff --git a/examples/maze/script.cpp b/examples/maze/script.cpp deleted file mode 100644 index 1fa417e..0000000 --- a/examples/maze/script.cpp +++ /dev/null @@ -1,127 +0,0 @@ -#define MORT 0xFFFFFFFF -#define VIVANT 0xFF000000 - -// shared uint incX; - -layout(set = 0, binding = 0) buffer incBuffer -{ - uint incX; - uint incY; -}; - -struct color -{ - uint r; - uint g; - uint b; -}; - -int rgb_to_int(color c) -{ - return 0xFF000000 | int(c.r) | int(c.g) << 8 | int(c.b) << 16; -} - -void dessinerSphere(uint centerX, uint centerY, float radius, color c) -{ - vec2 center = vec2(centerX, centerY); - - // Coordonnees du pixel actuel - ivec2 pos = ivec2(gl_GlobalInvocationID.xy); - - // Calculer la position du pixel - uint p = pos.x + pos.y * WSX; - - // Calculer la distance au carre entre le pixel et le centre du cercle - vec2 delta = pos - center; - float distanceCarre = dot(delta, delta); - - // Si le pixel est a l'interieur du cercle - if (distanceCarre <= radius * radius) - { - data_0[p] = rgb_to_int(c) + step; // ROUGE - } -} - -void main() -{ - - // Coordonnees du pixel actuel - ivec2 pos = ivec2(gl_GlobalInvocationID.xy); - uint p = pos.x + pos.y * WSX; - - int rayon = 50; - color c = {255, 0, 132}; // bgra - color c1 = {110, 50, 150}; // bgra - color c2 = {255, 25, 87}; // bgra - color c3 = {30, 0, 16}; // bgra - - /* - if (rayon + step + rayon < 800) - { - dessinerSphere(rayon + incX, rayon, rayon, c); - incX++; - } -*/ - - // data_0[p] = MORT; - - // dessinerSphere( uint(mousex), uint(mousey) , rayon, c1); - - if(step == 0) - data_0[p] = MORT; - - - /* - if ((mousex >= 0) || (mousey >= 0)) - { - dessinerSphere(mousex, mousey, rayon, c1); - } - */ - if(left_pressed) - dessinerSphere(mousex, mousey, rayon, c1); - /* - if(pos.x < 400 && pos.y < 225) - { - dessinerSphere( incX*2, incX , incX, c); - } - else - { - dessinerSphere( incX*2, incX , 40 , c); - } - - for(uint i = 0; i < 800; i+=100) - { - for (uint j = 0; j < 450; j+=50) - { - dessinerSphere( i , j , rayon, c1); - } - } - */ - /* - dessinerSphere( 150 , 50 , rayon, c1); - dessinerSphere( 250 , 50 , rayon, c2); - dessinerSphere( 350 , 50 , rayon, c3); - dessinerSphere( 450 , 50, rayon, c); - dessinerSphere( 550 , 50 , rayon, c1); - dessinerSphere( 650 , 50 , rayon, c2); - dessinerSphere( 750 , 50 , rayon, c3); - - dessinerSphere( 100 , incX , rayon*2, c1); - dessinerSphere( 300 , 200 , rayon*2, c2); - */ - // incX++; - - /*else - { - dessinerSphere(rayon + incX, rayon, rayon, c); - incX--; - } - */ - /* - if (incY + rayon < 450 ) - { - dessinerSphere(rayon, rayon + incY, rayon, c); - incY++; - }*/ - // Dessiner la sphere pour chaque pixel -} \ No newline at end of file diff --git a/examples/tron/Node2D.tscn b/examples/tron/Node2D.tscn index c76b129..bb91ba7 100644 --- a/examples/tron/Node2D.tscn +++ b/examples/tron/Node2D.tscn @@ -14,7 +14,7 @@ pause = null nb_passes = null WSX = 800 WSY = 450 -glsl_file = "res://examples/Maze/script.cpp" +glsl_file = "res://examples/tron/script.cpp" GLSL_code = " " data = [NodePath("../Icon")] diff --git a/examples/tron/script.cpp b/examples/tron/script.cpp index 8b911fa..9ba75bf 100644 --- a/examples/tron/script.cpp +++ b/examples/tron/script.cpp @@ -1,13 +1,6 @@ #define MORT 0xFFFFFFFF #define VIVANT 0xFF000000 -// shared uint incX; - -/*layout(set = 0, binding = 0) buffer incBuffer -{ - uint incX; - uint incY; -};*/ struct color { @@ -38,7 +31,7 @@ void dessinerSphere(uint centerX, uint centerY, float radius, color c) // Si le pixel est a l'interieur du cercle if (distanceCarre <= radius * radius) { - data_0[p] = rgb_to_int(c); // ROUGE + data_0[p] = rgb_to_int(c) + step; // ROUGE } } @@ -55,43 +48,18 @@ void main() color c2 = {255, 25, 87}; // bgra color c3 = {30, 0, 16}; // bgra - /* - if (rayon + step + rayon < 800) - { - dessinerSphere(rayon + incX, rayon, rayon, c); - incX++; - } -*/ - - // data_0[p] = MORT; - - // dessinerSphere( uint(mousex), uint(mousey) , rayon, c1); + if(step == 0) + data_0[p] = MORT; - data_0[p] = MORT; +/* if ((mousex >= 0) || (mousey >= 0)) { dessinerSphere(mousex, mousey, rayon, c1); } - - /* - if(pos.x < 400 && pos.y < 225) - { - dessinerSphere( incX*2, incX , incX, c); - } - else - { - dessinerSphere( incX*2, incX , 40 , c); - } - - for(uint i = 0; i < 800; i+=100) - { - for (uint j = 0; j < 450; j+=50) - { - dessinerSphere( i , j , rayon, c1); - } - } - */ +*/ + if(left_pressed) + dessinerSphere(mousex, mousey, rayon, c1); /* dessinerSphere( 150 , 50 , rayon, c1); dessinerSphere( 250 , 50 , rayon, c2); @@ -104,19 +72,5 @@ void main() dessinerSphere( 100 , incX , rayon*2, c1); dessinerSphere( 300 , 200 , rayon*2, c2); */ - // incX++; - /*else - { - dessinerSphere(rayon + incX, rayon, rayon, c); - incX--; - } - */ - /* - if (incY + rayon < 450 ) - { - dessinerSphere(rayon, rayon + incY, rayon, c); - incY++; - }*/ - // Dessiner la sphere pour chaque pixel } \ No newline at end of file From b4a9556fe32b94ecc94ada77124aa54cb1e5e367 Mon Sep 17 00:00:00 2001 From: zPrisim <76958083+zPrisim@users.noreply.github.com> Date: Tue, 11 Mar 2025 10:04:27 +0100 Subject: [PATCH 06/20] =?UTF-8?q?d=C3=A9but=20projet?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../compute_shader_studio_2d.gd | 5 - examples/tron/Node2D.tscn | 16 +- examples/tron/tron.cpp | 78 +++- examples/tron/tron.gd | 340 ++++++++++++++++++ 4 files changed, 417 insertions(+), 22 deletions(-) create mode 100644 examples/tron/tron.gd diff --git a/addons/compute_shader_studio/compute_shader_studio_2d.gd b/addons/compute_shader_studio/compute_shader_studio_2d.gd index aba364e..f947c2f 100644 --- a/addons/compute_shader_studio/compute_shader_studio_2d.gd +++ b/addons/compute_shader_studio/compute_shader_studio_2d.gd @@ -29,7 +29,6 @@ layout(binding = 0) buffer Params { int current_pass; int mousex; int mousey; - bool left_pressed; }; """ @@ -272,10 +271,6 @@ func _update_uniforms(): input_params.append(pos.x) input_params.append(pos.y) - var left_pressed : bool = Input.is_action_just_pressed("mouse_click") - input_params.append(left_pressed) - - var input_params_bytes := input_params.to_byte_array() buffer_params = rd.storage_buffer_create(input_params_bytes.size(), input_params_bytes) uniform_params = RDUniform.new() diff --git a/examples/tron/Node2D.tscn b/examples/tron/Node2D.tscn index bb91ba7..b491ae5 100644 --- a/examples/tron/Node2D.tscn +++ b/examples/tron/Node2D.tscn @@ -1,23 +1,17 @@ [gd_scene load_steps=3 format=3 uid="uid://u25v40csc7a8"] -[ext_resource type="Script" path="res://addons/compute_shader_studio/compute_shader_studio_2d.gd" id="1_ng0hm"] +[ext_resource type="Script" path="res://examples/tron/tron.gd" id="1_pd81r"] [ext_resource type="Texture2D" uid="uid://demftcowdd5c6" path="res://examples/icon.svg" id="2_gn2m0"] [node name="Node2d" type="Node2D"] [node name="ComputeShaderStudio2D" type="Node" parent="." node_paths=PackedStringArray("data")] -script = ExtResource("1_ng0hm") -print_step = null -print_passes = null -print_generated_code = null -pause = null -nb_passes = null +script = ExtResource("1_pd81r") WSX = 800 WSY = 450 -glsl_file = "res://examples/tron/script.cpp" -GLSL_code = " -" -data = [NodePath("../Icon")] +glsl_file = "res://examples/tron/tron.cpp" +GLSL_code = "" +data = [NodePath("../Icon"), null, null] [node name="Icon" type="Sprite2D" parent="."] position = Vector2(400.5, 226) diff --git a/examples/tron/tron.cpp b/examples/tron/tron.cpp index a7cf901..41ff062 100644 --- a/examples/tron/tron.cpp +++ b/examples/tron/tron.cpp @@ -1,23 +1,89 @@ -#define MORT 0xFFFFFFFF +// 800 * 450 +// data_0 : affichage +// data_1 : motos +// data_2 : faisceaux motos +/* + * Couleurs Motos : + * Rouge : 0xFF0000FF + * Bleu : 0xFF00FF00 + * Vert : 0xFFFF0000 +*/ +/* + * Couleurs faisceaux : + * Rouge modifie: 0xFF0055FF + * Bleu modifie: 0xFF55FF00 + * Vert modifie: 0xFFFF0055 +*/ +#define Init 0 +#define InitMotorcycles 1 +#define InitBeams 2 -void main() -{ - ivec2 pos = ivec2(gl_GlobalInvocationID.xy); - uint p = pos.x + pos.y * WSX; +#define Display data_0 + +#define Motorcycles data_1 +#define Beams data_2 +//fonction random +float random (ivec2 uv) { + return fract(sin(dot(uv.xy, + vec2(12.9898f,78.233f))) * 43758.5453123f); +} - data_0[p] = MORT; +void main() +{ + ivec2 pos = ivec2(gl_GlobalInvocationID.xy); + uint p = pos.x + pos.y * WSX; + if(step == Init) + { + Display[p] = 0xFF000000; + Motorcycles[p] = 0xFF000000; + Beams[p] = 0xFF000000; + } + if(step == InitMotorcycles) + { + if(pos.x >= 195 && pos.x < 205 && pos.y >= 195 && pos.y < 205) + Motorcycles[p] = 0xFF0000FF; // rouge + + if(pos.x >= 395 && pos.x < 405 && pos.y >= 195 && pos.y < 205) + Motorcycles[p] = 0xFF00FF00; // vert + + if(pos.x >= 595 && pos.x < 605 && pos.y >= 195 && pos.y < 205) + Motorcycles[p] = 0xFFFF0000; // bleu + + Display[p] += Motorcycles[p]; + } + if(step == InitBeams) + { + if(pos.x >= 198 && pos.x < 202 && pos.y >= 180 && pos.y < 195) + Beams[p] = 0xFF0055FF; // rouge modifie + if(pos.x >= 398 && pos.x < 402 && pos.y >= 180 && pos.y < 195) + Beams[p] = 0xFF55FF00; // vert modifie + if(pos.x >= 598 && pos.x < 602 && pos.y >= 180 && pos.y < 195) + Beams[p] = 0xFFFF0055; // bleu modifie + + Display[p] += Beams[p]; + } + + if(step == 3){ + if(Motorcycles[p] == 0xFF0000FF) + { + Motorcycles[(pos.x+10) + (pos.y * WSX)] = 0xFF0000FF; + } + } + if(step == 4){ + Display[p] += Motorcycles[p]; + } } \ No newline at end of file diff --git a/examples/tron/tron.gd b/examples/tron/tron.gd new file mode 100644 index 0000000..32924f7 --- /dev/null +++ b/examples/tron/tron.gd @@ -0,0 +1,340 @@ +extends Node +class_name tron + +var current_pass : int = 0 + +# Put your GLSL code in the GLSL_main string below +# Here are all the accessible variables (uniforms) inside your GLSL code: +# uint x,y : from GlobalInvocationID.x and .y +# uint p : the position [x][y] in the invocation +# uint WSX,WSY : the Global WorkSpace of invocations (generally match the data size) +# int* data_0, data_1, etc : are the data treated (can be displayed by Sprite2D, TextureRect, etc). +# Access them by data_0[p], data_1[p], etc +# uint step : simulation step of the execution. Incresed by 1 after nb_passes +# uint nb_passes: the number of passes your code needs (by step). +# There is a barrier between each pass. +# uint current_pass: pass currently executed (one pass per frame, nb_passes by step) + +#region ComputeShaderStudio + +var GLSL_header = """ +#version 450 + +// Invocations in the (x, y, z) dimension +layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; + +// Bindings to the buffers we create in our script +layout(binding = 0) buffer Params { + int step; + int current_pass; + int mousex; + int mousey; + bool left_pressed; +}; + +""" + +## Print the current step. +@export var print_step:bool = false +## Print the current pass. +@export var print_passes:bool = false +## Print in Output all the generated code. +## Can be usefull for debugging or to understand all the GLSL code needed. +@export var print_generated_code:bool = false +## Do not execute compute shader at launch. +@export var pause:bool = false +## Number of passes into each execution step. +## Between two passes, your GLSL code is synchronized. +@export var nb_passes : int = 1 +## Workspace Size X, usually it matches the x size of your image (Sprite2D or TextureRect) +@export var WSX : int = 128 +## Workspace Size Y, usually it matches the y size of your image (Sprite2D or TextureRect) +@export var WSY : int = 128 + +## Drag & drop your external GLSL file here (use .cpp for your source file extension) +@export_file("*.cpp") var glsl_file: String +## Write your GLSL code just below or use an external file above +@export_multiline var GLSL_code : String = """ +// Write your code HERE +void main() { + uint x = gl_GlobalInvocationID.x; + uint y = gl_GlobalInvocationID.y; + uint p = x + y * WSX; + data_0[p] = 0xFFF00FFF - int(p)*(step+1); + data_1[p] = 0xFF0000AA + int( 1.0 + 99999.9*sin(float(x+float(step+y))/1000.0)); +} +""" +## Drag and drop here your Sprite2D or TextureRect. +@export var data:Array[Node] + +var rd : RenderingDevice +var shader : RID +var buffers : Array[RID] +var buffer_params : RID +var buffer_user : RID + +var uniforms : Array[RDUniform] +#var uniform_2 : RDUniform +var uniform_params : RDUniform +var uniform_user : RDUniform + +var uniform_user_data : PackedByteArray = PackedByteArray([0]) + +var bindings : Array = [] + +var pipeline : RID +var uniform_set : RID + +# Called when the node enters the scene tree for the first time. +#region _ready +func _ready(): + compile() + +func compile(): + # Create a local rendering device. + rd = RenderingServer.create_local_rendering_device() + if not rd: + set_process(false) + printerr("Compute shaders are not available") + return + + # ********************* + # * SHADER CREATION * + # ********************* + + var nb_buffers : int = data.size() + + # Create GLSL Header + GLSL_header += """ +uint WSX="""+str(WSX)+""";"""+""" +uint WSY="""+str(WSY)+"""; +""" + + for i in nb_buffers: + GLSL_header += """ +layout(binding = """+str(i+2)+""") buffer Data"""+str(i)+""" { + int data_"""+str(i)+"""[]; +}; + +""" + + # The external GLSL file takes priority + if glsl_file != "": + print("Load the GLSL file:" + glsl_file ) + GLSL_code = load_glsl_file(glsl_file) + var GLSL_all : String = GLSL_header + GLSL_code + if print_generated_code == true: + print(GLSL_all) + + # Compile the shader by passing a string + var shader_src := RDShaderSource.new() + shader_src.set_stage_source(RenderingDevice.SHADER_STAGE_COMPUTE, GLSL_all) + var shader_spirv := rd.shader_compile_spirv_from_source(shader_src) + + var err:String=shader_spirv.compile_error_compute + + if err != "": + printerr(err) + get_tree().quit() + + shader = rd.shader_create_from_spirv(shader_spirv) + + + # ********************* + # * BUFFERS CREATION * + # ********************* + + # Buffer for current_pass + var input_params :PackedInt32Array = PackedInt32Array() + input_params.append(step) + input_params.append(current_pass) + var input_params_bytes := input_params.to_byte_array() + buffer_params = rd.storage_buffer_create(input_params_bytes.size(), input_params_bytes) + buffer_user = rd.storage_buffer_create(uniform_user_data.size(), uniform_user_data) + + # Creation of nb_buffers Buffers of type Int32 + for b in nb_buffers: + var input :PackedInt32Array = PackedInt32Array() + for i in range(WSX): + for j in range(WSY): + input.append(randi()) + var input_bytes :PackedByteArray = input.to_byte_array() + buffers.append(rd.storage_buffer_create(input_bytes.size(), input_bytes)) + + # ********************* + # * UNIFORMS CREATION * + # ********************* + + # Create current_pass uniform pass + uniform_params = RDUniform.new() + uniform_params.uniform_type = RenderingDevice.UNIFORM_TYPE_STORAGE_BUFFER + uniform_params.binding = 0 # this needs to match the "binding" in our shader file + uniform_params.add_id(buffer_params) + + # Create current_pass uniform pass + uniform_user = RDUniform.new() + uniform_user.uniform_type = RenderingDevice.UNIFORM_TYPE_STORAGE_BUFFER + uniform_user.binding = 1 # this needs to match the "binding" in our shader file + uniform_user.add_id(buffer_user) + + var nb_uniforms : int = data.size() + for b in nb_uniforms: + var uniform = RDUniform.new() + uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_STORAGE_BUFFER + uniform.binding = b+2 # this needs to match the "binding" in our shader file + uniform.add_id(buffers[b]) + uniforms.append(uniform) + + # Create the uniform SET between CPU & GPU + bindings = [uniform_params, uniform_user] + for b in nb_buffers: + bindings.append(uniforms[b]) + + uniform_set = rd.uniform_set_create(bindings, shader, 0) # the last parameter (the 0) needs to match the "set" in our shader file + + # ************************** + # * COMPUTE LIST CREATION * + # ************************** + # Create a compute pipeline + pipeline = rd.compute_pipeline_create(shader) + +#endregion + +func load_glsl_file(file_name:String) -> String: + var file = FileAccess.open(file_name, FileAccess.READ) + if file == null: + printerr("Unable to load GLSL file:" + file_name) + return "void main() {}" + var src_glsl:String = file.get_as_text() + return src_glsl + +func display_all_values(): + # Read back the data from the buffers + for b in data.size(): + var output_bytes : PackedByteArray = rd.buffer_get_data(buffers[b]) + if is_instance_valid(data[b]): + display_values(data[b], output_bytes) + +func display_values(disp : Node, values : PackedByteArray): # PackedInt32Array): + var img : Image = Image.create_from_data(WSX, WSY, false, Image.FORMAT_RGBA8, values) + var tex : Texture2D = ImageTexture.create_from_image(img) + + if disp is Sprite2D : + var old_width : float = disp.texture.get_width() + var old_height : float = disp.texture.get_height() + disp.set_texture(tex) + disp.scale *= Vector2(old_width/WSX, old_height/WSY) + + else : + disp.set_texture(tex) + + +var step : int = 0 + +func compute(): + if print_step == true && current_pass%nb_passes == 0: + print("Step="+str(step)) + if print_passes == true: + print(" CurrentPass="+str(current_pass)) + + _update_uniforms() + + # Prepare the Computer List ############################################ + var compute_list : int = rd.compute_list_begin() + rd.compute_list_bind_compute_pipeline(compute_list, pipeline) + rd.compute_list_bind_uniform_set(compute_list, uniform_set, 0) + rd.compute_list_dispatch(compute_list, WSX>>3, WSY>>3, 1) + rd.compute_list_end() + ####################################################################### + + # Submit to GPU and wait for sync + rd.submit() + rd.sync() + + # Update step and current_passe + current_pass = (current_pass + 1) % nb_passes + if current_pass == 0: + step += 1 + +func _process(_delta): + if pause == false: + compute() + display_all_values() + +## Pass the interesting values from CPU to GPU +func _update_uniforms(): + var input_params : PackedInt32Array = PackedInt32Array() + + input_params.append(step) + input_params.append(current_pass) + + var pos : Vector2 = screen_to_data0(get_viewport().get_mouse_position()) + input_params.append(pos.x) + input_params.append(pos.y) + + var left_pressed : bool = Input.is_action_just_pressed("mouse_click") + input_params.append(left_pressed) + + + var input_params_bytes := input_params.to_byte_array() + buffer_params = rd.storage_buffer_create(input_params_bytes.size(), input_params_bytes) + uniform_params = RDUniform.new() + uniform_params.uniform_type = RenderingDevice.UNIFORM_TYPE_STORAGE_BUFFER + uniform_params.binding = 0 # this needs to match the "binding" in our shader file + uniform_params.add_id(buffer_params) + bindings[0] = uniform_params + + buffer_user = rd.storage_buffer_create(uniform_user_data.size(), uniform_user_data) + uniform_user = RDUniform.new() + uniform_user.uniform_type = RenderingDevice.UNIFORM_TYPE_STORAGE_BUFFER + uniform_user.binding = 1 # this needs to match the "binding" in our shader file + uniform_user.add_id(buffer_user) + bindings[1] = uniform_user + + uniform_set = rd.uniform_set_create(bindings, shader, 0) + # Note: when changing the uniform set, use the same bindings Array (do not create a new Array) + +## Cleaning up the GPU resources +func _notification(what): + # Object destructor, triggered before the engine deletes this Node. + if what == NOTIFICATION_PREDELETE: + cleanup_gpu() + +func cleanup_gpu(): + if rd == null: + return + # All resources must be freed after use to avoid memory leaks. + rd.free_rid(pipeline) + pipeline = RID() + + rd.free_rid(uniform_set) + uniform_set = RID() + + rd.free_rid(shader) + shader = RID() + + rd.free() + rd = null + +#endregion + +func _on_button_step(): + pause = true + compute() + display_all_values() + + +func _on_button_play(): + pause = false # Replace with function body. + +func screen_to_data0(pos : Vector2): + if data.size() <= 0 : + return Vector2(0, 0) + + if data[0] is Sprite2D: + var sprite : Sprite2D = data[0] + pos.x = (pos.x - sprite.position.x) / sprite.scale.x + WSX/2 + pos.y = (pos.y - sprite.position.y) / sprite.scale.y + WSY/2 + return pos; + else: + return Vector2(0,0) From 7b3b8db14060306f0c2f6694270ad6323eb42fab Mon Sep 17 00:00:00 2001 From: zPrisim <76958083+zPrisim@users.noreply.github.com> Date: Tue, 11 Mar 2025 22:14:58 +0100 Subject: [PATCH 07/20] =?UTF-8?q?d=C3=A9but=20pathing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/tron/tron.cpp | 107 +++++++++++++++++++++++++++-------------- 1 file changed, 70 insertions(+), 37 deletions(-) diff --git a/examples/tron/tron.cpp b/examples/tron/tron.cpp index 41ff062..503b55b 100644 --- a/examples/tron/tron.cpp +++ b/examples/tron/tron.cpp @@ -7,22 +7,24 @@ /* * Couleurs Motos : * Rouge : 0xFF0000FF - * Bleu : 0xFF00FF00 - * Vert : 0xFFFF0000 -*/ + * Bleu : 0xFFFF0000 + */ /* * Couleurs faisceaux : * Rouge modifie: 0xFF0055FF * Bleu modifie: 0xFF55FF00 - * Vert modifie: 0xFFFF0055 -*/ + */ +#define CLEAR 0xFF000000 +#define MOTO_1 0xFF0000FF +#define MOTO_2 0xFFFF0000 #define Init 0 #define InitMotorcycles 1 #define InitBeams 2 +#define Speed 30 #define Display data_0 @@ -30,14 +32,48 @@ #define Beams data_2 +const uint dimMoto = 10; +const uint dir_haut = 0; +const uint dir_droite = 1; +const uint dir_bas = 2; +const uint dir_gauche = 3; +const int directions[4] = int[](0, 1, 2, 3); +void moveMotorcyle(int id_moto, uint dir) +{ + ivec2 pos = ivec2(gl_GlobalInvocationID.xy); + uint p = pos.x + pos.y * WSX; + + if (step % Speed == 0) + { + if (Motorcycles[p] == id_moto) + { + Motorcycles[p] = CLEAR; + Display[p] = CLEAR; + if (dir == dir_haut) + Motorcycles[(pos.x) + ((pos.y - dimMoto) * WSX)] = id_moto; + if (dir == dir_droite) + Motorcycles[(pos.x + dimMoto) + (pos.y * WSX)] = id_moto; + if (dir == dir_bas) + Motorcycles[(pos.x) + ((pos.y + dimMoto) * WSX)] = id_moto; + if (dir == dir_gauche) + Motorcycles[(pos.x - dimMoto) + (pos.y * WSX)] = id_moto; + } + } + if (step % Speed == 1) + { + Display[p] = Motorcycles[p] + Beams[p]; + } +} -//fonction random -float random (ivec2 uv) { +// fonction random +float random(vec2 uv) +{ return fract(sin(dot(uv.xy, - vec2(12.9898f,78.233f))) * 43758.5453123f); + vec2(12.9898f, 78.233f))) * + 43758.5453123f); } void main() @@ -45,45 +81,42 @@ void main() ivec2 pos = ivec2(gl_GlobalInvocationID.xy); uint p = pos.x + pos.y * WSX; - if(step == Init) + if (step == Init) { - Display[p] = 0xFF000000; - Motorcycles[p] = 0xFF000000; - Beams[p] = 0xFF000000; + Display[p] = CLEAR; + Motorcycles[p] = CLEAR; + Beams[p] = CLEAR; } - if(step == InitMotorcycles) + if (step == InitMotorcycles) { - if(pos.x >= 195 && pos.x < 205 && pos.y >= 195 && pos.y < 205) - Motorcycles[p] = 0xFF0000FF; // rouge - - if(pos.x >= 395 && pos.x < 405 && pos.y >= 195 && pos.y < 205) - Motorcycles[p] = 0xFF00FF00; // vert - - if(pos.x >= 595 && pos.x < 605 && pos.y >= 195 && pos.y < 205) - Motorcycles[p] = 0xFFFF0000; // bleu - + if (pos.x >= 195 && pos.x < 205 && pos.y >= 195 && pos.y < 205) + Motorcycles[p] = MOTO_1; // rouge + + if (pos.x >= 595 && pos.x < 605 && pos.y >= 195 && pos.y < 205) + Motorcycles[p] = MOTO_2; // bleu + Display[p] += Motorcycles[p]; } - if(step == InitBeams) + if (step == InitBeams) { - if(pos.x >= 198 && pos.x < 202 && pos.y >= 180 && pos.y < 195) + /*if (pos.x >= 198 && pos.x < 202 && pos.y >= 180 && pos.y < 195) Beams[p] = 0xFF0055FF; // rouge modifie - if(pos.x >= 398 && pos.x < 402 && pos.y >= 180 && pos.y < 195) - Beams[p] = 0xFF55FF00; // vert modifie - if(pos.x >= 598 && pos.x < 602 && pos.y >= 180 && pos.y < 195) + if (pos.x >= 598 && pos.x < 602 && pos.y >= 180 && pos.y < 195) Beams[p] = 0xFFFF0055; // bleu modifie - Display[p] += Beams[p]; + Display[p] += Beams[p];*/ } - if(step == 3){ - if(Motorcycles[p] == 0xFF0000FF) - { - Motorcycles[(pos.x+10) + (pos.y * WSX)] = 0xFF0000FF; - } - } - if(step == 4){ - Display[p] += Motorcycles[p]; - } + // moveMotorcyle(MOTO_1, directions[int(step * random(vec2(10., 10.))) % 4]); + + float choix_direction = random(vec2(float(step), float(step))); + if (choix_direction < 0.25) + moveMotorcyle(MOTO_1, dir_haut); + else if (choix_direction < 0.50) + moveMotorcyle(MOTO_1, dir_droite); + else if (choix_direction < 0.75) + moveMotorcyle(MOTO_1, dir_bas); + else + moveMotorcyle(MOTO_1, dir_gauche); } \ No newline at end of file From 062d8f92303902cffa878eade371fbb8fd6dea02 Mon Sep 17 00:00:00 2001 From: zPrisim <76958083+zPrisim@users.noreply.github.com> Date: Wed, 12 Mar 2025 23:41:31 +0100 Subject: [PATCH 08/20] ajout limites --- examples/fond noir.jpg | Bin 0 -> 50965 bytes examples/fond noir.jpg.import | 34 ++++++++++ examples/tron/Node2D.tscn | 12 ++-- examples/tron/tron.cpp | 115 ++++++++++++++++++++-------------- project.godot | 1 - 5 files changed, 108 insertions(+), 54 deletions(-) create mode 100644 examples/fond noir.jpg create mode 100644 examples/fond noir.jpg.import diff --git a/examples/fond noir.jpg b/examples/fond noir.jpg new file mode 100644 index 0000000000000000000000000000000000000000..75aab4337d2d9d7962fb51d0cc6b1470b96de658 GIT binary patch literal 50965 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 literal 0 HcmV?d00001 diff --git a/examples/fond noir.jpg.import b/examples/fond noir.jpg.import new file mode 100644 index 0000000..cd1ea10 --- /dev/null +++ b/examples/fond noir.jpg.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://d4famubcuvx74" +path="res://.godot/imported/fond noir.jpg-b123a7c5f65be3141c776d27ac42158f.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://examples/fond noir.jpg" +dest_files=["res://.godot/imported/fond noir.jpg-b123a7c5f65be3141c776d27ac42158f.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/examples/tron/Node2D.tscn b/examples/tron/Node2D.tscn index b491ae5..f431836 100644 --- a/examples/tron/Node2D.tscn +++ b/examples/tron/Node2D.tscn @@ -1,7 +1,7 @@ [gd_scene load_steps=3 format=3 uid="uid://u25v40csc7a8"] [ext_resource type="Script" path="res://examples/tron/tron.gd" id="1_pd81r"] -[ext_resource type="Texture2D" uid="uid://demftcowdd5c6" path="res://examples/icon.svg" id="2_gn2m0"] +[ext_resource type="Texture2D" uid="uid://d4famubcuvx74" path="res://examples/fond noir.jpg" id="2_2x2pa"] [node name="Node2d" type="Node2D"] @@ -11,9 +11,9 @@ WSX = 800 WSY = 450 glsl_file = "res://examples/tron/tron.cpp" GLSL_code = "" -data = [NodePath("../Icon"), null, null] +data = [NodePath("../FondNoir"), null, null, null] -[node name="Icon" type="Sprite2D" parent="."] -position = Vector2(400.5, 226) -scale = Vector2(6.25781, 3.53125) -texture = ExtResource("2_gn2m0") +[node name="FondNoir" type="Sprite2D" parent="."] +position = Vector2(400, 225.775) +scale = Vector2(1, 1.00544) +texture = ExtResource("2_2x2pa") diff --git a/examples/tron/tron.cpp b/examples/tron/tron.cpp index 503b55b..92aa850 100644 --- a/examples/tron/tron.cpp +++ b/examples/tron/tron.cpp @@ -20,46 +20,84 @@ #define MOTO_1 0xFF0000FF #define MOTO_2 0xFFFF0000 -#define Init 0 -#define InitMotorcycles 1 -#define InitBeams 2 - -#define Speed 30 - #define Display data_0 #define Motorcycles data_1 #define Beams data_2 +#define Beams_id data_3 + +#define Init 0 +#define InitMotorcycles 1 + +#define Speed 30 const uint dimMoto = 10; -const uint dir_haut = 0; -const uint dir_droite = 1; -const uint dir_bas = 2; -const uint dir_gauche = 3; +// fonction random +float random(vec2 uv) +{ + return fract(sin(dot(uv.xy, + vec2(12.9898f, 78.233f))) * + 43758.5453123f); +} -const int directions[4] = int[](0, 1, 2, 3); +bool isInside(float choix_direction) +{ + ivec2 pos = ivec2(gl_GlobalInvocationID.xy); + uint p = pos.x + pos.y * WSX; + bool res = false; -void moveMotorcyle(int id_moto, uint dir) + if (choix_direction < 0.25) // haut + { + res = !((pos.y - dimMoto) <= 0 || (pos.y - dimMoto) >= WSY - 2); + } + else if (choix_direction < 0.50) // droite + { + res = !((pos.x + dimMoto) <= 0 || (pos.x + dimMoto) >= WSX); + } + else if (choix_direction < 0.75) // bas + { + res = !((pos.y + dimMoto) <= 0 || (pos.y + dimMoto) >= WSY - 2); + } + else if (choix_direction < 1.00) // gauche + { + res = !((pos.x - dimMoto) <= 0 || (pos.x - dimMoto) >= WSX); + } + + if (res) + { + Motorcycles[p] = CLEAR; + Display[p] = CLEAR; + } + return res; +} + +void moveMotorcyle(int id_moto, float choix_direction) { ivec2 pos = ivec2(gl_GlobalInvocationID.xy); uint p = pos.x + pos.y * WSX; if (step % Speed == 0) { - if (Motorcycles[p] == id_moto) + if (isInside(choix_direction)) { - Motorcycles[p] = CLEAR; - Display[p] = CLEAR; - if (dir == dir_haut) + if (choix_direction < 0.25) // haut + { Motorcycles[(pos.x) + ((pos.y - dimMoto) * WSX)] = id_moto; - if (dir == dir_droite) + } + else if (choix_direction < 0.50) // droite + { Motorcycles[(pos.x + dimMoto) + (pos.y * WSX)] = id_moto; - if (dir == dir_bas) + } + else if (choix_direction < 0.75) // bas + { Motorcycles[(pos.x) + ((pos.y + dimMoto) * WSX)] = id_moto; - if (dir == dir_gauche) + } + else if (choix_direction < 1.00) // gauche + { Motorcycles[(pos.x - dimMoto) + (pos.y * WSX)] = id_moto; + } } } if (step % Speed == 1) @@ -68,14 +106,6 @@ void moveMotorcyle(int id_moto, uint dir) } } -// fonction random -float random(vec2 uv) -{ - return fract(sin(dot(uv.xy, - vec2(12.9898f, 78.233f))) * - 43758.5453123f); -} - void main() { ivec2 pos = ivec2(gl_GlobalInvocationID.xy); @@ -97,26 +127,17 @@ void main() Display[p] += Motorcycles[p]; } - if (step == InitBeams) - { - /*if (pos.x >= 198 && pos.x < 202 && pos.y >= 180 && pos.y < 195) - Beams[p] = 0xFF0055FF; // rouge modifie - if (pos.x >= 598 && pos.x < 602 && pos.y >= 180 && pos.y < 195) - Beams[p] = 0xFFFF0055; // bleu modifie - - Display[p] += Beams[p];*/ - } - - // moveMotorcyle(MOTO_1, directions[int(step * random(vec2(10., 10.))) % 4]); - float choix_direction = random(vec2(float(step), float(step))); + float choix_direction; - if (choix_direction < 0.25) - moveMotorcyle(MOTO_1, dir_haut); - else if (choix_direction < 0.50) - moveMotorcyle(MOTO_1, dir_droite); - else if (choix_direction < 0.75) - moveMotorcyle(MOTO_1, dir_bas); - else - moveMotorcyle(MOTO_1, dir_gauche); + if (Motorcycles[p] == MOTO_1) + { + choix_direction = random(vec2(float(step), float(MOTO_2 | 55 << 8))); + moveMotorcyle(MOTO_1, choix_direction); + } + else if (Motorcycles[p] == MOTO_2) + { + choix_direction = random(vec2(float(step), float(MOTO_2))); + moveMotorcyle(MOTO_2, choix_direction); + } } \ No newline at end of file diff --git a/project.godot b/project.godot index 2dec6e4..e378a99 100644 --- a/project.godot +++ b/project.godot @@ -19,7 +19,6 @@ config/icon="res://addons/compute_shader_studio/icon.png" window/size/viewport_width=800 window/size/viewport_height=450 -window/size/initial_position_type=0 [dotnet] From 3eec0cfb9018b916558b3304ae7e91545216c548 Mon Sep 17 00:00:00 2001 From: zPrisim <76958083+zPrisim@users.noreply.github.com> Date: Wed, 12 Mar 2025 23:49:40 +0100 Subject: [PATCH 09/20] =?UTF-8?q?fix=20d=C3=A9doublage=20code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/tron/tron.cpp | 68 ++++++++++++++++-------------------------- 1 file changed, 25 insertions(+), 43 deletions(-) diff --git a/examples/tron/tron.cpp b/examples/tron/tron.cpp index 92aa850..c8b8e58 100644 --- a/examples/tron/tron.cpp +++ b/examples/tron/tron.cpp @@ -42,36 +42,6 @@ float random(vec2 uv) 43758.5453123f); } -bool isInside(float choix_direction) -{ - ivec2 pos = ivec2(gl_GlobalInvocationID.xy); - uint p = pos.x + pos.y * WSX; - bool res = false; - - if (choix_direction < 0.25) // haut - { - res = !((pos.y - dimMoto) <= 0 || (pos.y - dimMoto) >= WSY - 2); - } - else if (choix_direction < 0.50) // droite - { - res = !((pos.x + dimMoto) <= 0 || (pos.x + dimMoto) >= WSX); - } - else if (choix_direction < 0.75) // bas - { - res = !((pos.y + dimMoto) <= 0 || (pos.y + dimMoto) >= WSY - 2); - } - else if (choix_direction < 1.00) // gauche - { - res = !((pos.x - dimMoto) <= 0 || (pos.x - dimMoto) >= WSX); - } - - if (res) - { - Motorcycles[p] = CLEAR; - Display[p] = CLEAR; - } - return res; -} void moveMotorcyle(int id_moto, float choix_direction) { @@ -80,24 +50,36 @@ void moveMotorcyle(int id_moto, float choix_direction) if (step % Speed == 0) { - if (isInside(choix_direction)) + + bool res = false; + if (choix_direction < 0.25) // haut { - if (choix_direction < 0.25) // haut - { + res = !((pos.y - dimMoto) <= 0 || (pos.y - dimMoto) >= WSY - 2); + if (res) Motorcycles[(pos.x) + ((pos.y - dimMoto) * WSX)] = id_moto; - } - else if (choix_direction < 0.50) // droite - { + } + else if (choix_direction < 0.50) // droite + { + res = !((pos.x + dimMoto) <= 0 || (pos.x + dimMoto) >= WSX); + if (res) Motorcycles[(pos.x + dimMoto) + (pos.y * WSX)] = id_moto; - } - else if (choix_direction < 0.75) // bas - { + } + else if (choix_direction < 0.75) // bas + { + res = !((pos.y + dimMoto) <= 0 || (pos.y + dimMoto) >= WSY - 2); + if (res) Motorcycles[(pos.x) + ((pos.y + dimMoto) * WSX)] = id_moto; - } - else if (choix_direction < 1.00) // gauche - { + } + else if (choix_direction < 1.00) // gauche + { + res = !((pos.x - dimMoto) <= 0 || (pos.x - dimMoto) >= WSX); + if (res) Motorcycles[(pos.x - dimMoto) + (pos.y * WSX)] = id_moto; - } + } + if (res) + { + Motorcycles[p] = CLEAR; + Display[p] = CLEAR; } } if (step % Speed == 1) From 7a8fcd50287fc24d2820dc733d578af60041179c Mon Sep 17 00:00:00 2001 From: zPrisim <76958083+zPrisim@users.noreply.github.com> Date: Thu, 13 Mar 2025 10:03:11 +0100 Subject: [PATCH 10/20] Avancement ( ne fonctionne pas --- examples/tron/Node2D.tscn | 3 +- examples/tron/tron.cpp | 86 +++++++++++++++++++++------------------ 2 files changed, 47 insertions(+), 42 deletions(-) diff --git a/examples/tron/Node2D.tscn b/examples/tron/Node2D.tscn index f431836..837a156 100644 --- a/examples/tron/Node2D.tscn +++ b/examples/tron/Node2D.tscn @@ -14,6 +14,5 @@ GLSL_code = "" data = [NodePath("../FondNoir"), null, null, null] [node name="FondNoir" type="Sprite2D" parent="."] -position = Vector2(400, 225.775) -scale = Vector2(1, 1.00544) +position = Vector2(400, 225) texture = ExtResource("2_2x2pa") diff --git a/examples/tron/tron.cpp b/examples/tron/tron.cpp index c8b8e58..746fd62 100644 --- a/examples/tron/tron.cpp +++ b/examples/tron/tron.cpp @@ -32,7 +32,7 @@ #define Speed 30 -const uint dimMoto = 10; +const int dimMoto = 10; // fonction random float random(vec2 uv) @@ -43,6 +43,20 @@ float random(vec2 uv) } + +void drawMotorcyle(int id_moto, ivec2 startPos) +{ + // Dessiner un carré de taille dimMoto x dimMoto + for (uint i = 0; i < dimMoto; i++) + { + for (uint j = 0; j < dimMoto; j++) + { + uint newPos = (startPos.x + i) + ((startPos.y + j) * WSX); + Motorcycles[newPos] = id_moto; + } + } +} + void moveMotorcyle(int id_moto, float choix_direction) { ivec2 pos = ivec2(gl_GlobalInvocationID.xy); @@ -50,42 +64,28 @@ void moveMotorcyle(int id_moto, float choix_direction) if (step % Speed == 0) { + ivec2 newPos = pos; - bool res = false; if (choix_direction < 0.25) // haut - { - res = !((pos.y - dimMoto) <= 0 || (pos.y - dimMoto) >= WSY - 2); - if (res) - Motorcycles[(pos.x) + ((pos.y - dimMoto) * WSX)] = id_moto; - } + newPos.y -= dimMoto; else if (choix_direction < 0.50) // droite - { - res = !((pos.x + dimMoto) <= 0 || (pos.x + dimMoto) >= WSX); - if (res) - Motorcycles[(pos.x + dimMoto) + (pos.y * WSX)] = id_moto; - } + newPos.x += dimMoto; else if (choix_direction < 0.75) // bas - { - res = !((pos.y + dimMoto) <= 0 || (pos.y + dimMoto) >= WSY - 2); - if (res) - Motorcycles[(pos.x) + ((pos.y + dimMoto) * WSX)] = id_moto; - } + newPos.y += dimMoto; else if (choix_direction < 1.00) // gauche - { - res = !((pos.x - dimMoto) <= 0 || (pos.x - dimMoto) >= WSX); - if (res) - Motorcycles[(pos.x - dimMoto) + (pos.y * WSX)] = id_moto; - } - if (res) + newPos.x -= dimMoto; + + if (newPos.x > 0 && newPos.x < WSX && newPos.y > 0 && newPos.y < WSY) { Motorcycles[p] = CLEAR; Display[p] = CLEAR; + uint newP = newPos.x + newPos.y * WSX; + + Motorcycles[newP] = id_moto; + } } - if (step % Speed == 1) - { - Display[p] = Motorcycles[p] + Beams[p]; - } + } void main() @@ -101,25 +101,31 @@ void main() } if (step == InitMotorcycles) { - if (pos.x >= 195 && pos.x < 205 && pos.y >= 195 && pos.y < 205) - Motorcycles[p] = MOTO_1; // rouge - - if (pos.x >= 595 && pos.x < 605 && pos.y >= 195 && pos.y < 205) + if (pos.x == 200 && pos.y == 190) + drawMotorcyle(MOTO_2, ivec2(200, 190)); +/* if (pos.x >= 600 -dimMoto && pos.x < 590 + dimMoto && pos.y >= 200 - dimMoto && pos.y < 190 + dimMoto) Motorcycles[p] = MOTO_2; // bleu - +*/ Display[p] += Motorcycles[p]; } float choix_direction; - - if (Motorcycles[p] == MOTO_1) + /* + if(step > 1 && step%2 == 0) { - choix_direction = random(vec2(float(step), float(MOTO_2 | 55 << 8))); - moveMotorcyle(MOTO_1, choix_direction); + if (Motorcycles[p] == MOTO_1) + { + choix_direction = random(vec2(float(step), float(MOTO_2 | 55 << 8))); + moveMotorcyle(MOTO_1, choix_direction); + } + else if (Motorcycles[p] == MOTO_2) + { + choix_direction = random(vec2(float(step), float(MOTO_2))); + moveMotorcyle(MOTO_2, choix_direction); + } } - else if (Motorcycles[p] == MOTO_2) + if(step > 1 && step%2 == 1) { - choix_direction = random(vec2(float(step), float(MOTO_2))); - moveMotorcyle(MOTO_2, choix_direction); - } + Display[p] = Motorcycles[p] + Beams[p]; + }*/ } \ No newline at end of file From fab6f9a18650b1830396e792c889e0e5487fcb87 Mon Sep 17 00:00:00 2001 From: zPrisim <76958083+zPrisim@users.noreply.github.com> Date: Thu, 13 Mar 2025 15:41:02 +0100 Subject: [PATCH 11/20] projet semi fonctionnel --- examples/tron/Node2D.tscn | 2 +- examples/tron/tron.cpp | 41 +++++++++++++++------------------------ project.godot | 2 +- 3 files changed, 18 insertions(+), 27 deletions(-) diff --git a/examples/tron/Node2D.tscn b/examples/tron/Node2D.tscn index 837a156..defa952 100644 --- a/examples/tron/Node2D.tscn +++ b/examples/tron/Node2D.tscn @@ -11,7 +11,7 @@ WSX = 800 WSY = 450 glsl_file = "res://examples/tron/tron.cpp" GLSL_code = "" -data = [NodePath("../FondNoir"), null, null, null] +data = [NodePath("../FondNoir"), null, null, null, null] [node name="FondNoir" type="Sprite2D" parent="."] position = Vector2(400, 225) diff --git a/examples/tron/tron.cpp b/examples/tron/tron.cpp index 746fd62..9ca936d 100644 --- a/examples/tron/tron.cpp +++ b/examples/tron/tron.cpp @@ -19,6 +19,7 @@ #define CLEAR 0xFF000000 #define MOTO_1 0xFF0000FF #define MOTO_2 0xFFFF0000 +#define BEAM 0xFF00FF00 #define Display data_0 @@ -30,7 +31,7 @@ #define Init 0 #define InitMotorcycles 1 -#define Speed 30 +#define Speed 5 const int dimMoto = 10; @@ -44,18 +45,6 @@ float random(vec2 uv) -void drawMotorcyle(int id_moto, ivec2 startPos) -{ - // Dessiner un carré de taille dimMoto x dimMoto - for (uint i = 0; i < dimMoto; i++) - { - for (uint j = 0; j < dimMoto; j++) - { - uint newPos = (startPos.x + i) + ((startPos.y + j) * WSX); - Motorcycles[newPos] = id_moto; - } - } -} void moveMotorcyle(int id_moto, float choix_direction) { @@ -75,14 +64,14 @@ void moveMotorcyle(int id_moto, float choix_direction) else if (choix_direction < 1.00) // gauche newPos.x -= dimMoto; - if (newPos.x > 0 && newPos.x < WSX && newPos.y > 0 && newPos.y < WSY) + if (newPos.x >= 0 && newPos.x < WSX && newPos.y >= 0 && newPos.y < WSY -2) { - Motorcycles[p] = CLEAR; - Display[p] = CLEAR; - uint newP = newPos.x + newPos.y * WSX; + if(Motorcycles[newPos.x + newPos.y * WSX] == CLEAR){ + Motorcycles[p] = BEAM; + Display[p] += Motorcycles[p] ; - Motorcycles[newP] = id_moto; - + Motorcycles[newPos.x + newPos.y * WSX] = id_moto; + } } } @@ -101,16 +90,18 @@ void main() } if (step == InitMotorcycles) { - if (pos.x == 200 && pos.y == 190) - drawMotorcyle(MOTO_2, ivec2(200, 190)); -/* if (pos.x >= 600 -dimMoto && pos.x < 590 + dimMoto && pos.y >= 200 - dimMoto && pos.y < 190 + dimMoto) + + if (pos.x >= 300 -dimMoto && pos.x < 290 + dimMoto && pos.y >= 200 - dimMoto && pos.y < 190 + dimMoto) + Motorcycles[p] = MOTO_1; // bleu + + if (pos.x >= 600 -dimMoto && pos.x < 590 + dimMoto && pos.y >= 200 - dimMoto && pos.y < 190 + dimMoto) Motorcycles[p] = MOTO_2; // bleu -*/ + Display[p] += Motorcycles[p]; } float choix_direction; - /* + if(step > 1 && step%2 == 0) { if (Motorcycles[p] == MOTO_1) @@ -127,5 +118,5 @@ void main() if(step > 1 && step%2 == 1) { Display[p] = Motorcycles[p] + Beams[p]; - }*/ + } } \ No newline at end of file diff --git a/project.godot b/project.godot index e378a99..6bbce3e 100644 --- a/project.godot +++ b/project.godot @@ -18,7 +18,7 @@ config/icon="res://addons/compute_shader_studio/icon.png" [display] window/size/viewport_width=800 -window/size/viewport_height=450 +window/size/viewport_height=448 [dotnet] From b6425ff40aabb936ba8adb44ec19155066e72dd2 Mon Sep 17 00:00:00 2001 From: zPrisim <76958083+zPrisim@users.noreply.github.com> Date: Thu, 13 Mar 2025 20:18:58 +0100 Subject: [PATCH 12/20] =?UTF-8?q?Manque=20d=C3=A9tection=20autour=20de=20l?= =?UTF-8?q?a=20moto?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/tron/tron.cpp | 99 +++++++++++++++++++++++++++++------------- 1 file changed, 69 insertions(+), 30 deletions(-) diff --git a/examples/tron/tron.cpp b/examples/tron/tron.cpp index 9ca936d..28a5abe 100644 --- a/examples/tron/tron.cpp +++ b/examples/tron/tron.cpp @@ -26,7 +26,6 @@ #define Motorcycles data_1 #define Beams data_2 -#define Beams_id data_3 #define Init 0 #define InitMotorcycles 1 @@ -44,37 +43,81 @@ float random(vec2 uv) } +void InitGame() +{ + ivec2 pos = ivec2(gl_GlobalInvocationID.xy); + uint p = pos.x + pos.y * WSX; + Display[p] = CLEAR; + Motorcycles[p] = CLEAR; + Beams[p] = CLEAR; +} + +ivec2 getNewPosition(ivec2 pos, int id_moto) +{ + ivec2 newPos = pos; + + float choix_direction; + if (id_moto == MOTO_1) + { + choix_direction = random(vec2(float(step), float(current_pass * sin(MOTO_1)))); + } + else if (id_moto == MOTO_2) + { + choix_direction = random(vec2(float(step), float(current_pass * sin(MOTO_2)))); + } + if (choix_direction < 0.25) // haut + newPos.y -= dimMoto; + else if (choix_direction < 0.50) // droite + newPos.x += dimMoto; + else if (choix_direction < 0.75) // bas + newPos.y += dimMoto; + else if (choix_direction < 1.00) // gauche + newPos.x -= dimMoto; -void moveMotorcyle(int id_moto, float choix_direction) + return newPos; +} + +void moveMotorcyle(int id_moto) { ivec2 pos = ivec2(gl_GlobalInvocationID.xy); uint p = pos.x + pos.y * WSX; if (step % Speed == 0) { - ivec2 newPos = pos; - - if (choix_direction < 0.25) // haut - newPos.y -= dimMoto; - else if (choix_direction < 0.50) // droite - newPos.x += dimMoto; - else if (choix_direction < 0.75) // bas - newPos.y += dimMoto; - else if (choix_direction < 1.00) // gauche - newPos.x -= dimMoto; - - if (newPos.x >= 0 && newPos.x < WSX && newPos.y >= 0 && newPos.y < WSY -2) + ivec2 newPos = getNewPosition(pos, id_moto); + + if (newPos.x >= 0 && newPos.x < WSX && newPos.y >= 0 && newPos.y < WSY - 2) { - if(Motorcycles[newPos.x + newPos.y * WSX] == CLEAR){ + if (Motorcycles[newPos.x + newPos.y * WSX] == CLEAR) + { Motorcycles[p] = BEAM; - Display[p] += Motorcycles[p] ; + Display[p] += Motorcycles[p]; Motorcycles[newPos.x + newPos.y * WSX] = id_moto; - } + } + else if (Motorcycles[newPos.x + newPos.y * WSX] == BEAM) + { + + uint cpt_beam = 0; + ivec2 finPos = getNewPosition(pos, id_moto); + if (finPos == newPos || Motorcycles[finPos.x + finPos.y * WSX] == BEAM) + { + cpt_beam++; + if (cpt_beam == 4) + { + InitGame(); + } + finPos = getNewPosition(pos, id_moto); + } + + Motorcycles[p] = BEAM; + Display[p] += Motorcycles[p]; + + Motorcycles[newPos.x + newPos.y * WSX] = id_moto; + } } } - } void main() @@ -84,38 +127,34 @@ void main() if (step == Init) { - Display[p] = CLEAR; - Motorcycles[p] = CLEAR; - Beams[p] = CLEAR; + InitGame(); } if (step == InitMotorcycles) { - if (pos.x >= 300 -dimMoto && pos.x < 290 + dimMoto && pos.y >= 200 - dimMoto && pos.y < 190 + dimMoto) + if (pos.x >= 300 - dimMoto && pos.x < 290 + dimMoto && pos.y >= 200 - dimMoto && pos.y < 190 + dimMoto) Motorcycles[p] = MOTO_1; // bleu - if (pos.x >= 600 -dimMoto && pos.x < 590 + dimMoto && pos.y >= 200 - dimMoto && pos.y < 190 + dimMoto) + if (pos.x >= 600 - dimMoto && pos.x < 590 + dimMoto && pos.y >= 200 - dimMoto && pos.y < 190 + dimMoto) Motorcycles[p] = MOTO_2; // bleu Display[p] += Motorcycles[p]; } float choix_direction; - - if(step > 1 && step%2 == 0) + + if (step > 1 && step % 2 == 0) { if (Motorcycles[p] == MOTO_1) { - choix_direction = random(vec2(float(step), float(MOTO_2 | 55 << 8))); - moveMotorcyle(MOTO_1, choix_direction); + moveMotorcyle(MOTO_1); } else if (Motorcycles[p] == MOTO_2) { - choix_direction = random(vec2(float(step), float(MOTO_2))); - moveMotorcyle(MOTO_2, choix_direction); + moveMotorcyle(MOTO_2); } } - if(step > 1 && step%2 == 1) + if (step > 1 && step % 2 == 1) { Display[p] = Motorcycles[p] + Beams[p]; } From 89fd846e19f9a447ed17e52c591e989cc09e4ae1 Mon Sep 17 00:00:00 2001 From: zPrisim <76958083+zPrisim@users.noreply.github.com> Date: Fri, 14 Mar 2025 12:26:36 +0100 Subject: [PATCH 13/20] Update tron.cpp --- examples/tron/tron.cpp | 51 +++++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/examples/tron/tron.cpp b/examples/tron/tron.cpp index 28a5abe..95e1327 100644 --- a/examples/tron/tron.cpp +++ b/examples/tron/tron.cpp @@ -30,7 +30,7 @@ #define Init 0 #define InitMotorcycles 1 -#define Speed 5 +#define Speed 1 const int dimMoto = 10; @@ -43,15 +43,34 @@ float random(vec2 uv) } -void InitGame() + + + +void InitGame(ivec2 pos) { - ivec2 pos = ivec2(gl_GlobalInvocationID.xy); uint p = pos.x + pos.y * WSX; Display[p] = CLEAR; Motorcycles[p] = CLEAR; Beams[p] = CLEAR; } +bool isEnd(ivec2 pos) +{ + + ivec2 vecHaut = ivec2(pos.x, pos.y - dimMoto); + ivec2 vecDroit = ivec2(pos.x + dimMoto, pos.y); + ivec2 vecBas = ivec2(pos.x, pos.y + dimMoto); + ivec2 vecGauche = ivec2(pos.x - dimMoto, pos.y); + + if (vecHaut.y < 0 || vecDroit.x >= WSX || vecBas.y >= WSY || vecGauche.x < 0) { + return true; + } + return false; + +} + + + ivec2 getNewPosition(ivec2 pos, int id_moto) { ivec2 newPos = pos; @@ -59,11 +78,11 @@ ivec2 getNewPosition(ivec2 pos, int id_moto) float choix_direction; if (id_moto == MOTO_1) { - choix_direction = random(vec2(float(step), float(current_pass * sin(MOTO_1)))); + choix_direction = random(vec2(float(step),float(step * current_pass))); } else if (id_moto == MOTO_2) { - choix_direction = random(vec2(float(step), float(current_pass * sin(MOTO_2)))); + choix_direction = random(vec2(float(step * current_pass),float(step))); } if (choix_direction < 0.25) // haut @@ -98,23 +117,25 @@ void moveMotorcyle(int id_moto) } else if (Motorcycles[newPos.x + newPos.y * WSX] == BEAM) { - - uint cpt_beam = 0; + if(isEnd(newPos)) + { + return; + } ivec2 finPos = getNewPosition(pos, id_moto); - if (finPos == newPos || Motorcycles[finPos.x + finPos.y * WSX] == BEAM) + int l = 0; + while ( Motorcycles[finPos.x + finPos.y * WSX] == BEAM) { - cpt_beam++; - if (cpt_beam == 4) - { - InitGame(); - } finPos = getNewPosition(pos, id_moto); + l++; + if(l == 20) + return; } + Motorcycles[p] = BEAM; Display[p] += Motorcycles[p]; - Motorcycles[newPos.x + newPos.y * WSX] = id_moto; + Motorcycles[finPos.x + finPos.y * WSX] = id_moto; } } } @@ -127,7 +148,7 @@ void main() if (step == Init) { - InitGame(); + InitGame(pos); } if (step == InitMotorcycles) { From 67faac8580d0f8a248bc1fd1bd59fb28bc87e3d4 Mon Sep 17 00:00:00 2001 From: zPrisim <76958083+zPrisim@users.noreply.github.com> Date: Fri, 14 Mar 2025 13:25:46 +0100 Subject: [PATCH 14/20] je sais pas --- examples/tron/tron.cpp | 36 +++++++++++++++++++----------------- examples/tron/tron.gd | 5 +++++ examples/tron/tron.gd.uid | 1 + project.godot | 1 - 4 files changed, 25 insertions(+), 18 deletions(-) create mode 100644 examples/tron/tron.gd.uid diff --git a/examples/tron/tron.cpp b/examples/tron/tron.cpp index 95e1327..7dcf162 100644 --- a/examples/tron/tron.cpp +++ b/examples/tron/tron.cpp @@ -19,7 +19,9 @@ #define CLEAR 0xFF000000 #define MOTO_1 0xFF0000FF #define MOTO_2 0xFFFF0000 -#define BEAM 0xFF00FF00 +#define BEAM_1 0xFF0055FF +#define BEAM_2 0xFF55FF00 + #define Display data_0 @@ -30,7 +32,7 @@ #define Init 0 #define InitMotorcycles 1 -#define Speed 1 +#define Speed 10 const int dimMoto = 10; @@ -44,8 +46,6 @@ float random(vec2 uv) - - void InitGame(ivec2 pos) { uint p = pos.x + pos.y * WSX; @@ -78,11 +78,11 @@ ivec2 getNewPosition(ivec2 pos, int id_moto) float choix_direction; if (id_moto == MOTO_1) { - choix_direction = random(vec2(float(step),float(step * current_pass))); + choix_direction = random(vec2(float(step) * 0.12345f,step)); } else if (id_moto == MOTO_2) { - choix_direction = random(vec2(float(step * current_pass),float(step))); + choix_direction = random(vec2(float(step) * 0.6789f ,step)); } if (choix_direction < 0.25) // haut @@ -105,34 +105,36 @@ void moveMotorcyle(int id_moto) if (step % Speed == 0) { ivec2 newPos = getNewPosition(pos, id_moto); + int beamColor = id_moto == MOTO_1 ? BEAM_1: BEAM_2; if (newPos.x >= 0 && newPos.x < WSX && newPos.y >= 0 && newPos.y < WSY - 2) { if (Motorcycles[newPos.x + newPos.y * WSX] == CLEAR) { - Motorcycles[p] = BEAM; + Motorcycles[p] = beamColor; Display[p] += Motorcycles[p]; Motorcycles[newPos.x + newPos.y * WSX] = id_moto; } - else if (Motorcycles[newPos.x + newPos.y * WSX] == BEAM) + else if (Motorcycles[newPos.x + newPos.y * WSX] == beamColor) { if(isEnd(newPos)) { return; } ivec2 finPos = getNewPosition(pos, id_moto); - int l = 0; - while ( Motorcycles[finPos.x + finPos.y * WSX] == BEAM) + + + for (int l = 0; l < 100000; ++l) { + if (Motorcycles[finPos.x + finPos.y * WSX] != beamColor) + { + break; + } finPos = getNewPosition(pos, id_moto); - l++; - if(l == 20) - return; } - - Motorcycles[p] = BEAM; + Motorcycles[p] = beamColor; Display[p] += Motorcycles[p]; Motorcycles[finPos.x + finPos.y * WSX] = id_moto; @@ -154,10 +156,10 @@ void main() { if (pos.x >= 300 - dimMoto && pos.x < 290 + dimMoto && pos.y >= 200 - dimMoto && pos.y < 190 + dimMoto) - Motorcycles[p] = MOTO_1; // bleu + Motorcycles[p] = MOTO_1; if (pos.x >= 600 - dimMoto && pos.x < 590 + dimMoto && pos.y >= 200 - dimMoto && pos.y < 190 + dimMoto) - Motorcycles[p] = MOTO_2; // bleu + Motorcycles[p] = MOTO_2; Display[p] += Motorcycles[p]; } diff --git a/examples/tron/tron.gd b/examples/tron/tron.gd index 32924f7..b911be8 100644 --- a/examples/tron/tron.gd +++ b/examples/tron/tron.gd @@ -30,6 +30,7 @@ layout(binding = 0) buffer Params { int mousex; int mousey; bool left_pressed; + int epoch_time; }; """ @@ -272,8 +273,12 @@ func _update_uniforms(): input_params.append(pos.x) input_params.append(pos.y) + + var left_pressed : bool = Input.is_action_just_pressed("mouse_click") input_params.append(left_pressed) + var time : int =Time.get_unix_time_from_system() + input_params.append(time) var input_params_bytes := input_params.to_byte_array() diff --git a/examples/tron/tron.gd.uid b/examples/tron/tron.gd.uid new file mode 100644 index 0000000..619133e --- /dev/null +++ b/examples/tron/tron.gd.uid @@ -0,0 +1 @@ +uid://bsnvapg1v3nl3 diff --git a/project.godot b/project.godot index 3bc0da9..5dacc8f 100644 --- a/project.godot +++ b/project.godot @@ -12,7 +12,6 @@ config_version=5 config/name="compute_shader_studio" run/main_scene="res://examples/example_1.tscn" -config/features=PackedStringArray("4.4", "Forward Plus") config/icon="res://addons/compute_shader_studio/icon.png" [display] From 777fb186f21ea8a3a42a4f4e6aa4f32ba1d0a361 Mon Sep 17 00:00:00 2001 From: zPrisim <76958083+zPrisim@users.noreply.github.com> Date: Sun, 16 Mar 2025 23:06:59 +0100 Subject: [PATCH 15/20] =?UTF-8?q?Al=C3=A9atoire=20meilleur=20qu'avant,=20l?= =?UTF-8?q?ogique=20de=20d=C3=A9placement=20=C3=A0=20am=C3=A9liorer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/tron/Node2D.tscn | 3 +- examples/tron/tron.cpp | 197 ++++++++++++++++++++++---------------- examples/tron/tron.gd | 4 +- project.godot | 3 +- 4 files changed, 121 insertions(+), 86 deletions(-) diff --git a/examples/tron/Node2D.tscn b/examples/tron/Node2D.tscn index defa952..dddd384 100644 --- a/examples/tron/Node2D.tscn +++ b/examples/tron/Node2D.tscn @@ -14,5 +14,6 @@ GLSL_code = "" data = [NodePath("../FondNoir"), null, null, null, null] [node name="FondNoir" type="Sprite2D" parent="."] -position = Vector2(400, 225) +position = Vector2(400, 225.55) +scale = Vector2(1, 1.00644) texture = ExtResource("2_2x2pa") diff --git a/examples/tron/tron.cpp b/examples/tron/tron.cpp index 7dcf162..8b9f165 100644 --- a/examples/tron/tron.cpp +++ b/examples/tron/tron.cpp @@ -22,7 +22,6 @@ #define BEAM_1 0xFF0055FF #define BEAM_2 0xFF55FF00 - #define Display data_0 #define Motorcycles data_1 @@ -30,71 +29,98 @@ #define Beams data_2 #define Init 0 -#define InitMotorcycles 1 - -#define Speed 10 const int dimMoto = 10; - // fonction random float random(vec2 uv) { - return fract(sin(dot(uv.xy, + return fract(sin(dot(uv.xy + random_time * 0.00001, vec2(12.9898f, 78.233f))) * 43758.5453123f); } - - void InitGame(ivec2 pos) { uint p = pos.x + pos.y * WSX; Display[p] = CLEAR; Motorcycles[p] = CLEAR; Beams[p] = CLEAR; -} -bool isEnd(ivec2 pos) + if (pos.x >= 300 - dimMoto && pos.x < 290 + dimMoto && pos.y >= 200 - dimMoto && pos.y < 190 + dimMoto) + Motorcycles[p] = MOTO_1; + + if (pos.x >= 600 - dimMoto && pos.x < 590 + dimMoto && pos.y >= 200 - dimMoto && pos.y < 190 + dimMoto) + Motorcycles[p] = MOTO_2; + + Display[p] += Motorcycles[p]; +} +bool isDirectionClear(ivec2 basePos, int direction) { + ivec2 nextPos = basePos; - ivec2 vecHaut = ivec2(pos.x, pos.y - dimMoto); - ivec2 vecDroit = ivec2(pos.x + dimMoto, pos.y); - ivec2 vecBas = ivec2(pos.x, pos.y + dimMoto); - ivec2 vecGauche = ivec2(pos.x - dimMoto, pos.y); + switch (direction) + { + case 0: + nextPos.y -= dimMoto; + break; // haut + case 1: + nextPos.x += dimMoto; + break; // droite + case 2: + nextPos.y += dimMoto; + break; // bas + case 3: + nextPos.x -= dimMoto; + break; // gauche + } - if (vecHaut.y < 0 || vecDroit.x >= WSX || vecBas.y >= WSY || vecGauche.x < 0) { - return true; + // check limites + if (nextPos.x < 0 || nextPos.x + dimMoto > WSX || + nextPos.y < 0 || nextPos.y + dimMoto > WSY - 2) + { + return false; } - return false; -} + // check si prochain emplacement déja rempli + for (int j = 0; j < dimMoto; j++) + { + for (int i = 0; i < dimMoto; i++) + { + ivec2 checkPos = nextPos + ivec2(i, j); + uint checkP = checkPos.x + checkPos.y * WSX; + if (Motorcycles[checkP] != CLEAR || Beams[checkP] != CLEAR) + { + return false; + } + } + } + return true; +} -ivec2 getNewPosition(ivec2 pos, int id_moto) +int chooseDirection(ivec2 basePos, int id_moto, int randomDir) { - ivec2 newPos = pos; - - float choix_direction; - if (id_moto == MOTO_1) - { - choix_direction = random(vec2(float(step) * 0.12345f,step)); - } - else if (id_moto == MOTO_2) + // si direction aléatoire disponible alors go + if (isDirectionClear(basePos, randomDir)) { - choix_direction = random(vec2(float(step) * 0.6789f ,step)); + return randomDir; } - if (choix_direction < 0.25) // haut - newPos.y -= dimMoto; - else if (choix_direction < 0.50) // droite - newPos.x += dimMoto; - else if (choix_direction < 0.75) // bas - newPos.y += dimMoto; - else if (choix_direction < 1.00) // gauche - newPos.x -= dimMoto; + // si direction aléatoire non disponible alors tenter toutes les autres + float seed = random(vec2(float(step) * 0.5678f + float(id_moto), step)); + int startDir = int(seed * 4.0); - return newPos; + for (int i = 0; i < 4; i++) + { + int dir = (startDir + i) % 4; + if (dir != randomDir && isDirectionClear(basePos, dir)) + { + return dir; + } + } + // si on trouve pas une direction valide + return -1; } void moveMotorcyle(int id_moto) @@ -102,42 +128,60 @@ void moveMotorcyle(int id_moto) ivec2 pos = ivec2(gl_GlobalInvocationID.xy); uint p = pos.x + pos.y * WSX; - if (step % Speed == 0) + if (Motorcycles[p] != id_moto) + return; + + ivec2 basePos = ivec2((pos.x / dimMoto) * dimMoto, (pos.y / dimMoto) * dimMoto); + if (pos.x != basePos.x || pos.y != basePos.y) + return; // check coin supérieur gauche + + // choix direction aléatoire + float seed = random(vec2(float(step) * (id_moto == MOTO_1 ? 0.125445f : 0.68419f), step)); // choix arbitraire des valeurs, peut largement mieux faire + int randomDir = int(seed * 4.0f); // 0: haut, 1: droite, 2: bas, 3: gauche + + int direction = chooseDirection(basePos, id_moto, randomDir); + + // si on trouve une direction valide + if (direction >= 0) { - ivec2 newPos = getNewPosition(pos, id_moto); - int beamColor = id_moto == MOTO_1 ? BEAM_1: BEAM_2; + // calcul nouvelle position + ivec2 newPos = basePos; + switch (direction) + { + case 0: + newPos.y -= dimMoto; + break; // haut + case 1: + newPos.x += dimMoto; + break; // droite + case 2: + newPos.y += dimMoto; + break; // bas + case 3: + newPos.x -= dimMoto; + break; // gauche + } - if (newPos.x >= 0 && newPos.x < WSX && newPos.y >= 0 && newPos.y < WSY - 2) + // efface avant d'avancer + for (int j = 0; j < dimMoto; j++) { - if (Motorcycles[newPos.x + newPos.y * WSX] == CLEAR) + for (int i = 0; i < dimMoto; i++) { - Motorcycles[p] = beamColor; - Display[p] += Motorcycles[p]; - - Motorcycles[newPos.x + newPos.y * WSX] = id_moto; + ivec2 oldPos = basePos + ivec2(i, j); + uint oldP = oldPos.x + oldPos.y * WSX; + Motorcycles[oldP] = CLEAR; + Beams[oldP] = (id_moto == MOTO_1) ? BEAM_1 : BEAM_2; } - else if (Motorcycles[newPos.x + newPos.y * WSX] == beamColor) + } + + // la moto avance + for (int j = 0; j < dimMoto; j++) + { + for (int i = 0; i < dimMoto; i++) { - if(isEnd(newPos)) - { - return; - } - ivec2 finPos = getNewPosition(pos, id_moto); - - - for (int l = 0; l < 100000; ++l) - { - if (Motorcycles[finPos.x + finPos.y * WSX] != beamColor) - { - break; - } - finPos = getNewPosition(pos, id_moto); - } - - Motorcycles[p] = beamColor; - Display[p] += Motorcycles[p]; - - Motorcycles[finPos.x + finPos.y * WSX] = id_moto; + ivec2 newPixelPos = newPos + ivec2(i, j); + uint newP = newPixelPos.x + newPixelPos.y * WSX; + Motorcycles[newP] = id_moto; } } } @@ -148,25 +192,14 @@ void main() ivec2 pos = ivec2(gl_GlobalInvocationID.xy); uint p = pos.x + pos.y * WSX; + int slowFactor = 10; + if (step == Init) { InitGame(pos); } - if (step == InitMotorcycles) - { - - if (pos.x >= 300 - dimMoto && pos.x < 290 + dimMoto && pos.y >= 200 - dimMoto && pos.y < 190 + dimMoto) - Motorcycles[p] = MOTO_1; - - if (pos.x >= 600 - dimMoto && pos.x < 590 + dimMoto && pos.y >= 200 - dimMoto && pos.y < 190 + dimMoto) - Motorcycles[p] = MOTO_2; - - Display[p] += Motorcycles[p]; - } - - float choix_direction; - if (step > 1 && step % 2 == 0) + if (step > 1 && step % slowFactor == 0) { if (Motorcycles[p] == MOTO_1) { @@ -177,7 +210,7 @@ void main() moveMotorcyle(MOTO_2); } } - if (step > 1 && step % 2 == 1) + if (step > 1 && step % slowFactor == 1) { Display[p] = Motorcycles[p] + Beams[p]; } diff --git a/examples/tron/tron.gd b/examples/tron/tron.gd index b911be8..de49972 100644 --- a/examples/tron/tron.gd +++ b/examples/tron/tron.gd @@ -30,7 +30,7 @@ layout(binding = 0) buffer Params { int mousex; int mousey; bool left_pressed; - int epoch_time; + int random_time; }; """ @@ -277,7 +277,7 @@ func _update_uniforms(): var left_pressed : bool = Input.is_action_just_pressed("mouse_click") input_params.append(left_pressed) - var time : int =Time.get_unix_time_from_system() + var time : int =Time.get_ticks_usec() input_params.append(time) diff --git a/project.godot b/project.godot index 5dacc8f..c21bced 100644 --- a/project.godot +++ b/project.godot @@ -12,12 +12,13 @@ config_version=5 config/name="compute_shader_studio" run/main_scene="res://examples/example_1.tscn" +config/features=PackedStringArray("4.3") config/icon="res://addons/compute_shader_studio/icon.png" [display] window/size/viewport_width=800 -window/size/viewport_height=448 +window/size/viewport_height=450 [dotnet] From 95497a3c648fd5009df08ad2f67744229a625712 Mon Sep 17 00:00:00 2001 From: Prisim Date: Mon, 17 Mar 2025 10:02:48 +0100 Subject: [PATCH 16/20] =?UTF-8?q?restart=20possible,=20choix=20du=20chemin?= =?UTF-8?q?=20a=20am=C3=A9liorer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/tron/tron.cpp | 47 +++++++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/examples/tron/tron.cpp b/examples/tron/tron.cpp index 8b9f165..a9969d7 100644 --- a/examples/tron/tron.cpp +++ b/examples/tron/tron.cpp @@ -30,7 +30,12 @@ #define Init 0 + const int dimMoto = 10; + + + + // fonction random float random(vec2 uv) { @@ -39,7 +44,7 @@ float random(vec2 uv) 43758.5453123f); } -void InitGame(ivec2 pos) +void initGame(ivec2 pos) { uint p = pos.x + pos.y * WSX; Display[p] = CLEAR; @@ -54,6 +59,24 @@ void InitGame(ivec2 pos) Display[p] += Motorcycles[p]; } + +void restartGame() +{ + ivec2 clearPos; + for (int i = 0; i < WSX; i++) + { + for (int j = 0; j < WSY; j++) + { + clearPos = ivec2(i, j); + uint p = clearPos.x + clearPos.y * WSX; + + Display[p] = CLEAR; + Motorcycles[p] = CLEAR; + Beams[p] = CLEAR; + } + } +} + bool isDirectionClear(ivec2 basePos, int direction) { ivec2 nextPos = basePos; @@ -81,7 +104,7 @@ bool isDirectionClear(ivec2 basePos, int direction) return false; } - // check si prochain emplacement déja rempli + // check si prochain emplacement deja rempli for (int j = 0; j < dimMoto; j++) { for (int i = 0; i < dimMoto; i++) @@ -101,13 +124,13 @@ bool isDirectionClear(ivec2 basePos, int direction) int chooseDirection(ivec2 basePos, int id_moto, int randomDir) { - // si direction aléatoire disponible alors go + // si direction aleatoire disponible alors go if (isDirectionClear(basePos, randomDir)) { return randomDir; } - // si direction aléatoire non disponible alors tenter toutes les autres + // si direction aleatoire non disponible alors tenter toutes les autres float seed = random(vec2(float(step) * 0.5678f + float(id_moto), step)); int startDir = int(seed * 4.0); @@ -133,11 +156,11 @@ void moveMotorcyle(int id_moto) ivec2 basePos = ivec2((pos.x / dimMoto) * dimMoto, (pos.y / dimMoto) * dimMoto); if (pos.x != basePos.x || pos.y != basePos.y) - return; // check coin supérieur gauche + return; // check coin superieur gauche - // choix direction aléatoire + // choix direction aleatoire float seed = random(vec2(float(step) * (id_moto == MOTO_1 ? 0.125445f : 0.68419f), step)); // choix arbitraire des valeurs, peut largement mieux faire - int randomDir = int(seed * 4.0f); // 0: haut, 1: droite, 2: bas, 3: gauche + int randomDir = int(seed * 4.0f); // 0: haut, 1: droite, 2: bas, 3: gauche int direction = chooseDirection(basePos, id_moto, randomDir); @@ -196,7 +219,7 @@ void main() if (step == Init) { - InitGame(pos); + initGame(pos); } if (step > 1 && step % slowFactor == 0) @@ -214,4 +237,12 @@ void main() { Display[p] = Motorcycles[p] + Beams[p]; } + if (left_pressed && step % 2 == 0) + { + restartGame(); + } + if (left_pressed && step % 2 == 1) + { + initGame(pos); + } } \ No newline at end of file From ec3603008160a8d7a41b579b119794232e68c725 Mon Sep 17 00:00:00 2001 From: Prisim Date: Mon, 17 Mar 2025 21:06:11 +0100 Subject: [PATCH 17/20] =?UTF-8?q?Placement=20al=C3=A9atoire?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/tron/tron.cpp | 62 ++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 33 deletions(-) diff --git a/examples/tron/tron.cpp b/examples/tron/tron.cpp index a9969d7..bec79e9 100644 --- a/examples/tron/tron.cpp +++ b/examples/tron/tron.cpp @@ -19,7 +19,7 @@ #define CLEAR 0xFF000000 #define MOTO_1 0xFF0000FF #define MOTO_2 0xFFFF0000 -#define BEAM_1 0xFF0055FF +#define BEAM_1 0xFF00FFFF #define BEAM_2 0xFF55FF00 #define Display data_0 @@ -30,12 +30,8 @@ #define Init 0 - const int dimMoto = 10; - - - // fonction random float random(vec2 uv) { @@ -51,32 +47,35 @@ void initGame(ivec2 pos) Motorcycles[p] = CLEAR; Beams[p] = CLEAR; - if (pos.x >= 300 - dimMoto && pos.x < 290 + dimMoto && pos.y >= 200 - dimMoto && pos.y < 190 + dimMoto) - Motorcycles[p] = MOTO_1; - if (pos.x >= 600 - dimMoto && pos.x < 590 + dimMoto && pos.y >= 200 - dimMoto && pos.y < 190 + dimMoto) - Motorcycles[p] = MOTO_2; + for(int i = 0; i < 10000; i++){} - Display[p] += Motorcycles[p]; -} + // On choisis aleatoirement une position dans la partie gauche de la simulation + float randomY1 = random(vec2(123.45f, 67.89f)) * (WSY - 2 * dimMoto) + dimMoto; + float randomX1 = random(vec2(234.56f, 78.90f)) * (WSX / 2 - 2 * dimMoto) + dimMoto; -void restartGame() -{ - ivec2 clearPos; - for (int i = 0; i < WSX; i++) - { - for (int j = 0; j < WSY; j++) - { - clearPos = ivec2(i, j); - uint p = clearPos.x + clearPos.y * WSX; + ivec2 moto1Pos = ivec2(int(randomX1), int(randomY1)); - Display[p] = CLEAR; - Motorcycles[p] = CLEAR; - Beams[p] = CLEAR; - } - } -} + // On choisis aleatoirement une position dans la partie droite de la simulation + float randomY2 = random(vec2(345.67f, 89.01f)) * (WSY - 2 * dimMoto) + dimMoto; + float randomX2 = random(vec2(456.78f, 90.12f)) * (WSX / 2 - 2 * dimMoto) + (WSX / 2); + + ivec2 moto2Pos = ivec2(int(randomX2), int(randomY2)); + + // Assure que les motos soit spawn alignees pour la suite des mouvements + moto1Pos = ivec2((moto1Pos.x / dimMoto) * dimMoto, (moto1Pos.y / dimMoto) * dimMoto); + moto2Pos = ivec2((moto2Pos.x / dimMoto) * dimMoto, (moto2Pos.y / dimMoto) * dimMoto); + // Premiere moto + if (pos.x >= moto1Pos.x && pos.x < moto1Pos.x + dimMoto && + pos.y >= moto1Pos.y && pos.y < moto1Pos.y + dimMoto) + Motorcycles[p] = MOTO_1; + + // deuxieme moto + if (pos.x >= moto2Pos.x && pos.x < moto2Pos.x + dimMoto && + pos.y >= moto2Pos.y && pos.y < moto2Pos.y + dimMoto) + Motorcycles[p] = MOTO_2; +} bool isDirectionClear(ivec2 basePos, int direction) { ivec2 nextPos = basePos; @@ -214,8 +213,8 @@ void main() { ivec2 pos = ivec2(gl_GlobalInvocationID.xy); uint p = pos.x + pos.y * WSX; - - int slowFactor = 10; + + int slowFactor = 2; if (step == Init) { @@ -237,12 +236,9 @@ void main() { Display[p] = Motorcycles[p] + Beams[p]; } - if (left_pressed && step % 2 == 0) - { - restartGame(); - } - if (left_pressed && step % 2 == 1) + if (left_pressed && step > 100) { + initGame(pos); } } \ No newline at end of file From 0db590a0d8759d21f3c19d26ea6edf4aa304339c Mon Sep 17 00:00:00 2001 From: zPrisim <76958083+zPrisim@users.noreply.github.com> Date: Tue, 18 Mar 2025 00:17:51 +0100 Subject: [PATCH 18/20] projet pour presentation --- examples/tron/tron.cpp | 90 ++++++++++++++++++++++++++++++++++-------- examples/tron/tron.gd | 9 +++-- 2 files changed, 79 insertions(+), 20 deletions(-) diff --git a/examples/tron/tron.cpp b/examples/tron/tron.cpp index bec79e9..41b39aa 100644 --- a/examples/tron/tron.cpp +++ b/examples/tron/tron.cpp @@ -1,4 +1,3 @@ - // 800 * 450 // data_0 : affichage // data_1 : motos @@ -47,9 +46,6 @@ void initGame(ivec2 pos) Motorcycles[p] = CLEAR; Beams[p] = CLEAR; - - for(int i = 0; i < 10000; i++){} - // On choisis aleatoirement une position dans la partie gauche de la simulation float randomY1 = random(vec2(123.45f, 67.89f)) * (WSY - 2 * dimMoto) + dimMoto; float randomX1 = random(vec2(234.56f, 78.90f)) * (WSX / 2 - 2 * dimMoto) + dimMoto; @@ -62,7 +58,7 @@ void initGame(ivec2 pos) ivec2 moto2Pos = ivec2(int(randomX2), int(randomY2)); - // Assure que les motos soit spawn alignees pour la suite des mouvements + // pour que les motos soit spawn alignees pour la suite des mouvements moto1Pos = ivec2((moto1Pos.x / dimMoto) * dimMoto, (moto1Pos.y / dimMoto) * dimMoto); moto2Pos = ivec2((moto2Pos.x / dimMoto) * dimMoto, (moto2Pos.y / dimMoto) * dimMoto); @@ -123,25 +119,88 @@ bool isDirectionClear(ivec2 basePos, int direction) int chooseDirection(ivec2 basePos, int id_moto, int randomDir) { - // si direction aleatoire disponible alors go + // Trouver la position de l'autre moto + ivec2 enemyPos = ivec2(-1, -1); + int enemyMoto = (id_moto == MOTO_1) ? MOTO_2 : MOTO_1; + + for (int y = 0; y < WSY; y++) + { + for (int x = 0; x < WSX; x++) + { + uint p = x + y * WSX; + if (Motorcycles[p] == enemyMoto) + { + enemyPos = ivec2(x, y); + break; + } + } + if (enemyPos.x != -1) + break; + } + + // Si on trouve l'autre moto, on calcule la direction ver elle + if (enemyPos.x != -1) + { + ivec2 diff = enemyPos - basePos; + + // nombre aleatoire pour decider si on suit l'ennemi ou si on fait un mouvement aleatoire + float chaseChance = random(vec2(float(step) * 0.7234f + float(id_moto), step)); + + // 70% de chance de suivre l'autre moto', 30% de faire un mouvement aleatoire + if (chaseChance < 0.70f) + { + int dirTab[4]; + float dirChoice = random(vec2(float(step) * 0.3456f + float(id_moto), step)); + + if (abs(diff.x) > abs(diff.y) || dirChoice > 0.5f) + { + dirTab[0] = (diff.x > 0) ? 1 : 3; // Droite ou Gauche + dirTab[1] = (diff.y > 0) ? 2 : 0; // Bas ou Haut + dirTab[2] = (random(vec2(step * 0.1234f, id_moto)) > 0.5f) ? 0 : 2; // Y aleatoire + dirTab[3] = (random(vec2(step * 0.5678f, id_moto)) > 0.5f) ? 1 : 3; // X aleatoire + } + else + { + dirTab[0] = (diff.y > 0) ? 2 : 0; // Bas ou Haut + dirTab[1] = (diff.x > 0) ? 1 : 3; // Droite ou Gauche + dirTab[2] = (random(vec2(step * 0.9012f, id_moto)) > 0.5f) ? 1 : 3; // X aleatoire + dirTab[3] = (random(vec2(step * 0.3456f, id_moto)) > 0.5f) ? 2 : 0; // Y aleatoire + } + + // Essayer chaque direction dans l'ordre de preference + for (int i = 0; i < 4; i++) + { + if (isDirectionClear(basePos, dirTab[i])) + { + return dirTab[i]; + } + } + } + } + if (isDirectionClear(basePos, randomDir)) { return randomDir; } - // si direction aleatoire non disponible alors tenter toutes les autres - float seed = random(vec2(float(step) * 0.5678f + float(id_moto), step)); - int startDir = int(seed * 4.0); + // essayer toutes les directions dans un ordre aleatoire + int essais[4] = {0, 1, 2, 3}; + for (int i = 3; i > 0; i--) + { + int j = int(random(vec2(float(step) * 0.8901f + float(i), id_moto)) * float(i + 1)); + int temp = essais[i]; + essais[i] = essais[j]; + essais[j] = temp; + } for (int i = 0; i < 4; i++) { - int dir = (startDir + i) % 4; - if (dir != randomDir && isDirectionClear(basePos, dir)) + if (isDirectionClear(basePos, essais[i])) { - return dir; + return essais[i]; } } - // si on trouve pas une direction valide + return -1; } @@ -213,7 +272,7 @@ void main() { ivec2 pos = ivec2(gl_GlobalInvocationID.xy); uint p = pos.x + pos.y * WSX; - + int slowFactor = 2; if (step == Init) @@ -236,9 +295,8 @@ void main() { Display[p] = Motorcycles[p] + Beams[p]; } - if (left_pressed && step > 100) + if (mouse_button > 0 && step > 100) { - initGame(pos); } } \ No newline at end of file diff --git a/examples/tron/tron.gd b/examples/tron/tron.gd index de49972..1f9f5e5 100644 --- a/examples/tron/tron.gd +++ b/examples/tron/tron.gd @@ -29,7 +29,7 @@ layout(binding = 0) buffer Params { int current_pass; int mousex; int mousey; - bool left_pressed; + int mouse_button; int random_time; }; @@ -274,9 +274,10 @@ func _update_uniforms(): input_params.append(pos.y) - - var left_pressed : bool = Input.is_action_just_pressed("mouse_click") - input_params.append(left_pressed) + # Mouse button + input_params.append(Input.get_mouse_button_mask()) + # var left_pressed : bool = Input.is_action_just_pressed("mouse_click") + # input_params.append(left_pressed) var time : int =Time.get_ticks_usec() input_params.append(time) From 20ea41ae082d6c9af577e0bf2e7de1012454626d Mon Sep 17 00:00:00 2001 From: Prisim Date: Tue, 18 Mar 2025 10:29:27 +0100 Subject: [PATCH 19/20] clear project --- examples/tron/script.cpp | 76 ---------------------------------------- 1 file changed, 76 deletions(-) delete mode 100644 examples/tron/script.cpp diff --git a/examples/tron/script.cpp b/examples/tron/script.cpp deleted file mode 100644 index 9ba75bf..0000000 --- a/examples/tron/script.cpp +++ /dev/null @@ -1,76 +0,0 @@ -#define MORT 0xFFFFFFFF -#define VIVANT 0xFF000000 - - -struct color -{ - int r; - int g; - int b; -}; - -int rgb_to_int(color c) -{ - return 0xFF000000 | int(c.r) | int(c.g) << 8 | int(c.b) << 16; -} - -void dessinerSphere(uint centerX, uint centerY, float radius, color c) -{ - vec2 center = vec2(centerX, centerY); - - // Coordonnees du pixel actuel - ivec2 pos = ivec2(gl_GlobalInvocationID.xy); - - // Calculer la position du pixel - uint p = pos.x + pos.y * WSX; - - // Calculer la distance au carre entre le pixel et le centre du cercle - vec2 delta = pos - center; - float distanceCarre = dot(delta, delta); - - // Si le pixel est a l'interieur du cercle - if (distanceCarre <= radius * radius) - { - data_0[p] = rgb_to_int(c) + step; // ROUGE - } -} - -void main() -{ - - // Coordonnees du pixel actuel - ivec2 pos = ivec2(gl_GlobalInvocationID.xy); - uint p = pos.x + pos.y * WSX; - - int rayon = 50; - color c = {255, 0, 132}; // bgra - color c1 = {110, 50, 150}; // bgra - color c2 = {255, 25, 87}; // bgra - color c3 = {30, 0, 16}; // bgra - - if(step == 0) - data_0[p] = MORT; - - -/* - if ((mousex >= 0) || (mousey >= 0)) - { - dessinerSphere(mousex, mousey, rayon, c1); - } -*/ - if(left_pressed) - dessinerSphere(mousex, mousey, rayon, c1); - /* - dessinerSphere( 150 , 50 , rayon, c1); - dessinerSphere( 250 , 50 , rayon, c2); - dessinerSphere( 350 , 50 , rayon, c3); - dessinerSphere( 450 , 50, rayon, c); - dessinerSphere( 550 , 50 , rayon, c1); - dessinerSphere( 650 , 50 , rayon, c2); - dessinerSphere( 750 , 50 , rayon, c3); - - dessinerSphere( 100 , incX , rayon*2, c1); - dessinerSphere( 300 , 200 , rayon*2, c2); - */ - -} \ No newline at end of file From 00c3bcf81def0a2805f30cc8a223bd8764323494 Mon Sep 17 00:00:00 2001 From: Prisim Date: Tue, 18 Mar 2025 11:34:31 +0100 Subject: [PATCH 20/20] clear --- examples/ProjetAAP/Node2D.tscn | 23 ----------------------- 1 file changed, 23 deletions(-) delete mode 100644 examples/ProjetAAP/Node2D.tscn diff --git a/examples/ProjetAAP/Node2D.tscn b/examples/ProjetAAP/Node2D.tscn deleted file mode 100644 index 5f4a7b0..0000000 --- a/examples/ProjetAAP/Node2D.tscn +++ /dev/null @@ -1,23 +0,0 @@ -[gd_scene load_steps=3 format=3 uid="uid://u25v40csc7a8"] - -[ext_resource type="Script" path="res://addons/compute_shader_studio/compute_shader_studio_2d.gd" id="1_rt15t"] -[ext_resource type="Texture2D" uid="uid://demftcowdd5c6" path="res://examples/icon.svg" id="2_2cd5v"] - -[node name="Node2d" type="Node2D"] - -[node name="ComputeShaderStudio2D" type="Node" parent="." node_paths=PackedStringArray("data")] -script = ExtResource("1_rt15t") -GLSL_code = " -// Write your code HERE -void main() { - uint x = gl_GlobalInvocationID.x; - uint y = gl_GlobalInvocationID.y; - uint p = x + y * WSX; - data_0[p] = 0xFFF00FFF - int(p)*(step+1); -} -" -data = [NodePath("../Icon")] - -[node name="Icon" type="Sprite2D" parent="."] -position = Vector2(228, 133) -texture = ExtResource("2_2cd5v")