diff --git a/3d/procedural_materials/README.md b/3d/procedural_materials/README.md new file mode 100644 index 00000000..c3bd41da --- /dev/null +++ b/3d/procedural_materials/README.md @@ -0,0 +1,37 @@ +# Procedural Materials + +This demo includes procedurally generated materials with 3 different techniques: + +- **[NoiseTexture2D](https://docs.godotengine.org/en/stable/classes/class_noisetexture2d.html):** + Built-in class that generates images on the CPU based on + noise patterns (such as Simplex or Cellular). This is suited for static + textures only. Texture generation is done asynchronously and is faster than + using scripting, since the noise algorithms are implemented in C++ in the + engine. + +- **Scripting:** Uses the + [Image](https://docs.godotengine.org/en/stable/classes/class_image.html) class + to procedurally generate an + [ImageTexture](https://docs.godotengine.org/en/stable/classes/class_imagetexture.html) + on the CPU. This is suited for static textures only. This approach is more + flexible than NoiseTexture2D, but is slower to generate textures. Once the + texture is generated, rendering performance is identical to NoiseTexture2D. + +- **Shaders:** Uses a 2D shader on a + [ColorRect](https://docs.godotengine.org/en/stable/classes/class_colorrect.html) + node that matches a + [Viewport](https://docs.godotengine.org/en/stable/classes/class_viewport.html)'s + size with the resulting + [ViewportTexture](https://docs.godotengine.org/en/stable/classes/class_viewporttexture.html) + applied to a material. This is updated on the GPU in real-time, and is most + suited for animated textures. This approach can also be used for static + textures, with a lower performance overhead since the texture doesn't need to + be updated every frame. + +Language: GDScript + +Renderer: Forward Plus + +## Screenshots + +![Screenshot](screenshots/procedural_materials.webp) diff --git a/3d/procedural_materials/checker.png b/3d/procedural_materials/checker.png new file mode 100644 index 00000000..374a5d06 Binary files /dev/null and b/3d/procedural_materials/checker.png differ diff --git a/3d/procedural_materials/checker.png.import b/3d/procedural_materials/checker.png.import new file mode 100644 index 00000000..4458677c --- /dev/null +++ b/3d/procedural_materials/checker.png.import @@ -0,0 +1,35 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://chjqieyps5n5r" +path.s3tc="res://.godot/imported/checker.png-6bb199bedbd039461e4248c1d0b9691d.s3tc.ctex" +metadata={ +"imported_formats": ["s3tc_bptc"], +"vram_texture": true +} + +[deps] + +source_file="res://checker.png" +dest_files=["res://.godot/imported/checker.png-6bb199bedbd039461e4248c1d0b9691d.s3tc.ctex"] + +[params] + +compress/mode=2 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=true +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=0 diff --git a/3d/procedural_materials/icon.webp b/3d/procedural_materials/icon.webp new file mode 100644 index 00000000..abadd428 Binary files /dev/null and b/3d/procedural_materials/icon.webp differ diff --git a/3d/procedural_materials/icon.webp.import b/3d/procedural_materials/icon.webp.import new file mode 100644 index 00000000..ec42a0e6 --- /dev/null +++ b/3d/procedural_materials/icon.webp.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://ny54l3w66vw3" +path="res://.godot/imported/icon.webp-e94f9a68b0f625a567a797079e4d325f.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://icon.webp" +dest_files=["res://.godot/imported/icon.webp-e94f9a68b0f625a567a797079e4d325f.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/3d/procedural_materials/loading.gd b/3d/procedural_materials/loading.gd new file mode 100644 index 00000000..9f4c7921 --- /dev/null +++ b/3d/procedural_materials/loading.gd @@ -0,0 +1,13 @@ +# This acts as a staging scene shown until the main scene is fully loaded. +extends Control + + +func _ready(): + for i in 2: + # Wait 2 frames before starting to change to the main scene, + # so that the loading text can be shown instead of the splash screen. + await get_tree().process_frame + + # Do not use `preload()` to avoid incurring the loading time before the + # loading text can be shown. + get_tree().change_scene_to_packed(load("res://test.tscn")) diff --git a/3d/procedural_materials/loading.tscn b/3d/procedural_materials/loading.tscn new file mode 100644 index 00000000..2f034d34 --- /dev/null +++ b/3d/procedural_materials/loading.tscn @@ -0,0 +1,30 @@ +[gd_scene load_steps=2 format=3 uid="uid://b1odr115brm8m"] + +[ext_resource type="Script" path="res://loading.gd" id="1_anktk"] + +[node name="Loading" type="ColorRect"] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +color = Color(0.494118, 0.580392, 0.686275, 1) +script = ExtResource("1_anktk") + +[node name="Label" type="Label" parent="."] +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -74.5 +offset_top = -24.0 +offset_right = 74.5 +offset_bottom = 24.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_colors/font_outline_color = Color(0, 0, 0, 1) +theme_override_constants/outline_size = 6 +theme_override_font_sizes/font_size = 32 +text = "Generating textures, please wait…" diff --git a/3d/procedural_materials/materials/grass.tres b/3d/procedural_materials/materials/grass.tres new file mode 100644 index 00000000..2cb457f1 --- /dev/null +++ b/3d/procedural_materials/materials/grass.tres @@ -0,0 +1,10 @@ +[gd_resource type="StandardMaterial3D" load_steps=3 format=3 uid="uid://chsncadr63hoc"] + +[ext_resource type="Texture2D" uid="uid://1adlmerrq6tb" path="res://materials/textures/grass_albedo.tres" id="1_m5akc"] +[ext_resource type="Texture2D" uid="uid://b7c28bnw0u27e" path="res://materials/textures/grass_normal.tres" id="2_spkki"] + +[resource] +albedo_texture = ExtResource("1_m5akc") +normal_enabled = true +normal_texture = ExtResource("2_spkki") +texture_filter = 5 diff --git a/3d/procedural_materials/materials/ice.tres b/3d/procedural_materials/materials/ice.tres new file mode 100644 index 00000000..1bc1e2f9 --- /dev/null +++ b/3d/procedural_materials/materials/ice.tres @@ -0,0 +1,42 @@ +[gd_resource type="StandardMaterial3D" load_steps=6 format=3 uid="uid://cbijbaq5qol7n"] + +[sub_resource type="Gradient" id="Gradient_16ij7"] +colors = PackedColorArray(0.6, 0.8, 1, 1, 1, 1, 1, 1) + +[sub_resource type="FastNoiseLite" id="FastNoiseLite_qbhty"] +frequency = 0.003 +fractal_type = 2 +fractal_lacunarity = 2.5 + +[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_m8iqd"] +width = 1024 +height = 1024 +seamless = true +color_ramp = SubResource("Gradient_16ij7") +noise = SubResource("FastNoiseLite_qbhty") + +[sub_resource type="FastNoiseLite" id="FastNoiseLite_5tmlw"] +frequency = 0.003 +fractal_type = 2 +fractal_octaves = 10 +fractal_lacunarity = 1.342 +fractal_gain = 0.776 +fractal_weighted_strength = 0.04 + +[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_gyhec"] +width = 1024 +height = 1024 +seamless = true +as_normal_map = true +bump_strength = 4.0 +noise = SubResource("FastNoiseLite_5tmlw") + +[resource] +albedo_texture = SubResource("NoiseTexture2D_m8iqd") +metallic_specular = 1.0 +roughness = 0.0 +normal_enabled = true +normal_texture = SubResource("NoiseTexture2D_gyhec") +backlight_enabled = true +backlight = Color(0.3, 0.4, 0.5, 1) +texture_filter = 5 diff --git a/3d/procedural_materials/materials/lava.tres b/3d/procedural_materials/materials/lava.tres new file mode 100644 index 00000000..c9baeb18 --- /dev/null +++ b/3d/procedural_materials/materials/lava.tres @@ -0,0 +1,57 @@ +[gd_resource type="StandardMaterial3D" load_steps=7 format=3 uid="uid://b74tdcluvrao6"] + +[sub_resource type="Gradient" id="Gradient_f6rvr"] +offsets = PackedFloat32Array(0.00813008, 0.28628, 0.358839, 0.53562, 0.699187, 0.766491, 1) +colors = PackedColorArray(0, 0, 0, 1, 0.436461, 0.0783241, 0.09101, 1, 0.601977, 0, 0.175375, 1, 1, 0, 0.25, 1, 1, 0.716667, 0, 1, 0.91, 0.761973, 0.3549, 1, 1, 1, 1, 1) + +[sub_resource type="FastNoiseLite" id="FastNoiseLite_cl4ii"] +noise_type = 2 +frequency = 0.005 +fractal_type = 3 +fractal_octaves = 1 +cellular_return_type = 6 +domain_warp_enabled = true +domain_warp_type = 2 +domain_warp_amplitude = 100.0 +domain_warp_frequency = 0.01 +domain_warp_fractal_octaves = 10 +domain_warp_fractal_lacunarity = 2.204 +domain_warp_fractal_gain = 0.6 + +[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_itinc"] +width = 1024 +height = 1024 +seamless = true +color_ramp = SubResource("Gradient_f6rvr") +noise = SubResource("FastNoiseLite_cl4ii") + +[sub_resource type="Gradient" id="Gradient_t5fqa"] +offsets = PackedFloat32Array(0.444591, 0.502639, 0.699187, 0.766491, 1) +colors = PackedColorArray(0, 0, 0, 1, 1, 0, 0.25, 1, 1, 0.716667, 0, 1, 0.91, 0.761973, 0.3549, 1, 1, 1, 1, 1) + +[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_fuepi"] +width = 1024 +height = 1024 +seamless = true +color_ramp = SubResource("Gradient_t5fqa") +noise = SubResource("FastNoiseLite_cl4ii") + +[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_w1lhv"] +width = 1024 +height = 1024 +seamless = true +color_ramp = SubResource("Gradient_f6rvr") +noise = SubResource("FastNoiseLite_cl4ii") + +[resource] +albedo_texture = SubResource("NoiseTexture2D_itinc") +emission_enabled = true +emission_texture = SubResource("NoiseTexture2D_fuepi") +heightmap_enabled = true +heightmap_scale = 2.0 +heightmap_deep_parallax = true +heightmap_min_layers = 8 +heightmap_max_layers = 32 +heightmap_texture = SubResource("NoiseTexture2D_w1lhv") +heightmap_flip_texture = true +texture_filter = 5 diff --git a/3d/procedural_materials/materials/marble.tres b/3d/procedural_materials/materials/marble.tres new file mode 100644 index 00000000..c00d8661 --- /dev/null +++ b/3d/procedural_materials/materials/marble.tres @@ -0,0 +1,30 @@ +[gd_resource type="StandardMaterial3D" load_steps=4 format=3 uid="uid://c5wve1c3hypfo"] + +[sub_resource type="Gradient" id="Gradient_57yod"] +offsets = PackedFloat32Array(0, 0.51049, 0.671329, 1) +colors = PackedColorArray(0.0235294, 0.0235294, 0.0392157, 1, 0.113725, 0.113725, 0.164706, 1, 0.128, 0.145067, 0.16, 1, 1, 1, 1, 1) + +[sub_resource type="FastNoiseLite" id="FastNoiseLite_vdicb"] +frequency = 0.006 +fractal_type = 2 +fractal_octaves = 10 +fractal_lacunarity = 3.0 +fractal_gain = 0.6 +domain_warp_amplitude = 15.0 +domain_warp_frequency = 0.03 +domain_warp_fractal_octaves = 10 + +[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_oc5fq"] +width = 1024 +height = 1024 +seamless = true +color_ramp = SubResource("Gradient_57yod") +noise = SubResource("FastNoiseLite_vdicb") + +[resource] +albedo_texture = SubResource("NoiseTexture2D_oc5fq") +roughness = 0.0 +rim_enabled = true +rim_tint = 1.0 +clearcoat_roughness = 0.0 +texture_filter = 5 diff --git a/3d/procedural_materials/materials/pixel_art.tres b/3d/procedural_materials/materials/pixel_art.tres new file mode 100644 index 00000000..07a10476 --- /dev/null +++ b/3d/procedural_materials/materials/pixel_art.tres @@ -0,0 +1,4 @@ +[gd_resource type="StandardMaterial3D" format=3 uid="uid://d0yum6cvd2cyb"] + +[resource] +texture_filter = 4 diff --git a/3d/procedural_materials/materials/sand.tres b/3d/procedural_materials/materials/sand.tres new file mode 100644 index 00000000..1d38e081 --- /dev/null +++ b/3d/procedural_materials/materials/sand.tres @@ -0,0 +1,10 @@ +[gd_resource type="StandardMaterial3D" load_steps=3 format=3 uid="uid://3odjrwml2nes"] + +[ext_resource type="Texture2D" uid="uid://caf47v17px0e" path="res://materials/textures/sand_albedo.tres" id="1_kw214"] +[ext_resource type="Texture2D" uid="uid://2u8c47a4cd5" path="res://materials/textures/sand_normal.tres" id="2_52v72"] + +[resource] +albedo_texture = ExtResource("1_kw214") +normal_enabled = true +normal_texture = ExtResource("2_52v72") +texture_filter = 5 diff --git a/3d/procedural_materials/materials/textures/grass_albedo.tres b/3d/procedural_materials/materials/textures/grass_albedo.tres new file mode 100644 index 00000000..1410db1c --- /dev/null +++ b/3d/procedural_materials/materials/textures/grass_albedo.tres @@ -0,0 +1,20 @@ +[gd_resource type="NoiseTexture2D" load_steps=3 format=3 uid="uid://1adlmerrq6tb"] + +[sub_resource type="Gradient" id="Gradient_8sl6j"] +colors = PackedColorArray(0, 0.21, 0, 1, 0.5418, 0.72, 0.324, 1) + +[sub_resource type="FastNoiseLite" id="FastNoiseLite_ryabi"] +noise_type = 4 +frequency = 0.005 +fractal_type = 3 +fractal_octaves = 9 +fractal_lacunarity = 10.896 +fractal_gain = 1.0 +fractal_ping_pong_strength = 2.1 + +[resource] +width = 1024 +height = 1024 +seamless = true +color_ramp = SubResource("Gradient_8sl6j") +noise = SubResource("FastNoiseLite_ryabi") diff --git a/3d/procedural_materials/materials/textures/grass_normal.tres b/3d/procedural_materials/materials/textures/grass_normal.tres new file mode 100644 index 00000000..8428e28d --- /dev/null +++ b/3d/procedural_materials/materials/textures/grass_normal.tres @@ -0,0 +1,19 @@ +[gd_resource type="NoiseTexture2D" load_steps=3 format=3 uid="uid://b7c28bnw0u27e"] + +[sub_resource type="Gradient" id="Gradient_8sl6j"] +colors = PackedColorArray(0, 0.243137, 0, 1, 0.486275, 0.756863, 0.14902, 1) + +[sub_resource type="FastNoiseLite" id="FastNoiseLite_7ucal"] +noise_type = 4 +frequency = 0.005 +fractal_type = 2 +fractal_lacunarity = 2.416 +fractal_ping_pong_strength = 2.1 + +[resource] +width = 1024 +height = 1024 +seamless = true +as_normal_map = true +color_ramp = SubResource("Gradient_8sl6j") +noise = SubResource("FastNoiseLite_7ucal") diff --git a/3d/procedural_materials/materials/textures/sand_albedo.tres b/3d/procedural_materials/materials/textures/sand_albedo.tres new file mode 100644 index 00000000..fa756c56 --- /dev/null +++ b/3d/procedural_materials/materials/textures/sand_albedo.tres @@ -0,0 +1,19 @@ +[gd_resource type="NoiseTexture2D" load_steps=3 format=3 uid="uid://caf47v17px0e"] + +[sub_resource type="Gradient" id="Gradient_pheaa"] +offsets = PackedFloat32Array(0.0243902, 1) +colors = PackedColorArray(1, 0.743333, 0.45, 1, 1, 0.874, 0.73, 1) + +[sub_resource type="FastNoiseLite" id="FastNoiseLite_nwsqr"] +noise_type = 3 +fractal_octaves = 8 +domain_warp_enabled = true +domain_warp_type = 1 +domain_warp_fractal_gain = 1.0 + +[resource] +width = 1024 +height = 1024 +seamless = true +color_ramp = SubResource("Gradient_pheaa") +noise = SubResource("FastNoiseLite_nwsqr") diff --git a/3d/procedural_materials/materials/textures/sand_normal.tres b/3d/procedural_materials/materials/textures/sand_normal.tres new file mode 100644 index 00000000..f3bebdde --- /dev/null +++ b/3d/procedural_materials/materials/textures/sand_normal.tres @@ -0,0 +1,13 @@ +[gd_resource type="NoiseTexture2D" load_steps=2 format=3 uid="uid://2u8c47a4cd5"] + +[sub_resource type="FastNoiseLite" id="FastNoiseLite_qi0cj"] +fractal_octaves = 3 +fractal_lacunarity = 1.612 + +[resource] +width = 1024 +height = 1024 +seamless = true +as_normal_map = true +bump_strength = 16.0 +noise = SubResource("FastNoiseLite_qi0cj") diff --git a/3d/procedural_materials/materials/textures/trypophobia_albedo.tres b/3d/procedural_materials/materials/textures/trypophobia_albedo.tres new file mode 100644 index 00000000..6d78cb29 --- /dev/null +++ b/3d/procedural_materials/materials/textures/trypophobia_albedo.tres @@ -0,0 +1,19 @@ +[gd_resource type="NoiseTexture2D" load_steps=3 format=3 uid="uid://dw4mslgkir1bd"] + +[sub_resource type="Gradient" id="Gradient_d5vv8"] +offsets = PackedFloat32Array(0.00813008, 0.341463, 0.674797, 1) +colors = PackedColorArray(0.05, 0.05, 0.05, 1, 0.510312, 0.415082, 0.239094, 1, 0.95, 0.799267, 0.627, 1, 1, 1, 1, 1) + +[sub_resource type="FastNoiseLite" id="FastNoiseLite_65rwj"] +noise_type = 2 +frequency = 0.005 +fractal_type = 3 +fractal_octaves = 9 +fractal_ping_pong_strength = 5.84 + +[resource] +width = 1024 +height = 1024 +seamless = true +color_ramp = SubResource("Gradient_d5vv8") +noise = SubResource("FastNoiseLite_65rwj") diff --git a/3d/procedural_materials/materials/textures/trypophobia_normal.tres b/3d/procedural_materials/materials/textures/trypophobia_normal.tres new file mode 100644 index 00000000..2b56ac69 --- /dev/null +++ b/3d/procedural_materials/materials/textures/trypophobia_normal.tres @@ -0,0 +1,21 @@ +[gd_resource type="NoiseTexture2D" load_steps=3 format=3 uid="uid://dd5i28wnuc2cs"] + +[sub_resource type="Gradient" id="Gradient_3xmi8"] +offsets = PackedFloat32Array(0.00813008, 0.341463, 0.674797, 1) +colors = PackedColorArray(0.05, 0.05, 0.05, 1, 0.43, 0.43, 0.43, 1, 0.89, 0.89, 0.89, 1, 1, 1, 1, 1) + +[sub_resource type="FastNoiseLite" id="FastNoiseLite_6p36u"] +noise_type = 2 +frequency = 0.005 +fractal_type = 3 +fractal_octaves = 9 +fractal_ping_pong_strength = 5.84 + +[resource] +width = 1024 +height = 1024 +seamless = true +as_normal_map = true +bump_strength = 3.0 +color_ramp = SubResource("Gradient_3xmi8") +noise = SubResource("FastNoiseLite_6p36u") diff --git a/3d/procedural_materials/materials/textures/trypophobia_roughness.tres b/3d/procedural_materials/materials/textures/trypophobia_roughness.tres new file mode 100644 index 00000000..8246bc5c --- /dev/null +++ b/3d/procedural_materials/materials/textures/trypophobia_roughness.tres @@ -0,0 +1,19 @@ +[gd_resource type="NoiseTexture2D" load_steps=3 format=3 uid="uid://muqmqaqefsrm"] + +[sub_resource type="Gradient" id="Gradient_2rffn"] +offsets = PackedFloat32Array(0.00813008, 0.341463, 0.674797, 1) +colors = PackedColorArray(0, 0, 0, 1, 0, 0, 0, 1, 0.89, 0.89, 0.89, 1, 1, 1, 1, 1) + +[sub_resource type="FastNoiseLite" id="FastNoiseLite_65rwj"] +noise_type = 2 +frequency = 0.005 +fractal_type = 3 +fractal_octaves = 9 +fractal_ping_pong_strength = 5.84 + +[resource] +width = 1024 +height = 1024 +seamless = true +color_ramp = SubResource("Gradient_2rffn") +noise = SubResource("FastNoiseLite_65rwj") diff --git a/3d/procedural_materials/materials/textures/wet_concrete_albedo.tres b/3d/procedural_materials/materials/textures/wet_concrete_albedo.tres new file mode 100644 index 00000000..f077f9f5 --- /dev/null +++ b/3d/procedural_materials/materials/textures/wet_concrete_albedo.tres @@ -0,0 +1,16 @@ +[gd_resource type="NoiseTexture2D" load_steps=3 format=3 uid="uid://ch81ib0h0gfqg"] + +[sub_resource type="Gradient" id="Gradient_8ut3h"] +colors = PackedColorArray(0.55, 0.55, 0.55, 1, 0.683077, 0.683077, 0.683077, 1) + +[sub_resource type="FastNoiseLite" id="FastNoiseLite_bgo3j"] +noise_type = 0 +frequency = 0.08 +domain_warp_enabled = true + +[resource] +width = 1024 +height = 1024 +seamless = true +color_ramp = SubResource("Gradient_8ut3h") +noise = SubResource("FastNoiseLite_bgo3j") diff --git a/3d/procedural_materials/materials/textures/wet_concrete_orm.tres b/3d/procedural_materials/materials/textures/wet_concrete_orm.tres new file mode 100644 index 00000000..43fe1c8a --- /dev/null +++ b/3d/procedural_materials/materials/textures/wet_concrete_orm.tres @@ -0,0 +1,13 @@ +[gd_resource type="NoiseTexture2D" load_steps=3 format=3 uid="uid://bm0om4im5p1da"] + +[sub_resource type="Gradient" id="Gradient_ac24k"] +colors = PackedColorArray(0, 0.258824, 0, 1, 1, 1, 1, 1) + +[sub_resource type="FastNoiseLite" id="FastNoiseLite_t6fbr"] + +[resource] +width = 1024 +height = 1024 +seamless = true +color_ramp = SubResource("Gradient_ac24k") +noise = SubResource("FastNoiseLite_t6fbr") diff --git a/3d/procedural_materials/materials/trypophobia.tres b/3d/procedural_materials/materials/trypophobia.tres new file mode 100644 index 00000000..eae1df07 --- /dev/null +++ b/3d/procedural_materials/materials/trypophobia.tres @@ -0,0 +1,12 @@ +[gd_resource type="StandardMaterial3D" load_steps=4 format=3 uid="uid://b2588u4jkfiog"] + +[ext_resource type="Texture2D" uid="uid://dw4mslgkir1bd" path="res://materials/textures/trypophobia_albedo.tres" id="1_1gqoj"] +[ext_resource type="Texture2D" uid="uid://dd5i28wnuc2cs" path="res://materials/textures/trypophobia_normal.tres" id="2_0h02x"] +[ext_resource type="Texture2D" uid="uid://muqmqaqefsrm" path="res://materials/textures/trypophobia_roughness.tres" id="2_2fvnl"] + +[resource] +albedo_texture = ExtResource("1_1gqoj") +roughness_texture = ExtResource("2_2fvnl") +normal_enabled = true +normal_texture = ExtResource("2_0h02x") +texture_filter = 5 diff --git a/3d/procedural_materials/materials/wet_concrete.tres b/3d/procedural_materials/materials/wet_concrete.tres new file mode 100644 index 00000000..cdb46422 --- /dev/null +++ b/3d/procedural_materials/materials/wet_concrete.tres @@ -0,0 +1,9 @@ +[gd_resource type="ORMMaterial3D" load_steps=3 format=3 uid="uid://cw85kxowmkj37"] + +[ext_resource type="Texture2D" uid="uid://ch81ib0h0gfqg" path="res://materials/textures/wet_concrete_albedo.tres" id="1_or44f"] +[ext_resource type="Texture2D" uid="uid://bm0om4im5p1da" path="res://materials/textures/wet_concrete_orm.tres" id="2_k25x3"] + +[resource] +albedo_texture = ExtResource("1_or44f") +orm_texture = ExtResource("2_k25x3") +ao_enabled = true diff --git a/3d/procedural_materials/project.godot b/3d/procedural_materials/project.godot new file mode 100644 index 00000000..0314f9f8 --- /dev/null +++ b/3d/procedural_materials/project.godot @@ -0,0 +1,27 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=5 + +[application] + +config/name="Procedural Materials" +run/main_scene="res://loading.tscn" +config/features=PackedStringArray("4.0") +config/icon="res://icon.webp" + +[display] + +window/stretch/mode="canvas_items" +window/stretch/aspect="expand" + +[rendering] + +textures/default_filters/anisotropic_filtering_level=4 +environment/defaults/default_clear_color=Color(0.301961, 0.301961, 0.301961, 1) +anti_aliasing/quality/msaa_3d=2 diff --git a/3d/procedural_materials/screenshots/.gdignore b/3d/procedural_materials/screenshots/.gdignore new file mode 100644 index 00000000..e69de29b diff --git a/3d/procedural_materials/screenshots/procedural_materials.webp b/3d/procedural_materials/screenshots/procedural_materials.webp new file mode 100644 index 00000000..e5f3730c Binary files /dev/null and b/3d/procedural_materials/screenshots/procedural_materials.webp differ diff --git a/3d/procedural_materials/scripts/grid.gd b/3d/procedural_materials/scripts/grid.gd new file mode 100644 index 00000000..64a60088 --- /dev/null +++ b/3d/procedural_materials/scripts/grid.gd @@ -0,0 +1,37 @@ +# This script creates the ImageTexture and assigns it to an existing material at runtime. +# By not having `@tool`, this avoids saving the raw image data in the scene file, +# which would make it much larger. +extends MeshInstance3D + +const TEXTURE_SIZE = Vector2i(512, 512) +const GRID_SIZE = 32 +const GRID_THICKNESS = 4 + +func _ready() -> void: + var image := Image.create(TEXTURE_SIZE.x, TEXTURE_SIZE.y, false, Image.FORMAT_RGB8) + # Use 1-dimensional loop as it's faster than a nested loop. + for i in TEXTURE_SIZE.x * TEXTURE_SIZE.y: + var x := i % TEXTURE_SIZE.y + var y := i / TEXTURE_SIZE.y + var color := Color() + + # Draw a grid with more contrasted points where X and Y lines meet. + # Center the grid's lines so that lines are visible on all the texture's edges. + if (x + GRID_THICKNESS / 2) % GRID_SIZE < GRID_THICKNESS and (y + GRID_THICKNESS / 2) % GRID_SIZE < GRID_THICKNESS: + color.g = 0.8 + elif (x + GRID_THICKNESS / 2) % GRID_SIZE < GRID_THICKNESS or (y + GRID_THICKNESS / 2) % GRID_SIZE < GRID_THICKNESS: + color.g = 0.25 + + # Add some random noise for detail. + color += Color(randf(), randf(), randf()) * 0.1 + + image.set_pixel(x, y, color) + + image.generate_mipmaps() + var image_texture := ImageTexture.create_from_image(image) + get_surface_override_material(0).albedo_texture = image_texture + + image.bump_map_to_normal_map(5.0) + image.generate_mipmaps() + var image_texture_normal := ImageTexture.create_from_image(image) + get_surface_override_material(0).normal_texture = image_texture_normal diff --git a/3d/procedural_materials/shaders/plasma.gdshader b/3d/procedural_materials/shaders/plasma.gdshader new file mode 100644 index 00000000..3201e35e --- /dev/null +++ b/3d/procedural_materials/shaders/plasma.gdshader @@ -0,0 +1,12 @@ +shader_type canvas_item; + +uniform sampler2D noise1 : repeat_enable; +uniform sampler2D noise2 : repeat_enable; + +const float SCROLL_SPEED = 0.04; + +void fragment() { + vec2 noise1_uv = UV + vec2(SCROLL_SPEED) * TIME; + COLOR = texture(noise1, noise1_uv); + COLOR.rgb += 0.3 * texture(noise2, UV * 4.0 - vec2(texture(noise1, noise1_uv * 0.3).xy * 0.015) * TIME * 2.0).r; +} diff --git a/3d/procedural_materials/test.tscn b/3d/procedural_materials/test.tscn new file mode 100644 index 00000000..5a78b472 --- /dev/null +++ b/3d/procedural_materials/test.tscn @@ -0,0 +1,448 @@ +[gd_scene load_steps=40 format=3 uid="uid://c4i1xdk0nc7s0"] + +[ext_resource type="Material" uid="uid://b2588u4jkfiog" path="res://materials/trypophobia.tres" id="3_322sv"] +[ext_resource type="Material" uid="uid://chsncadr63hoc" path="res://materials/grass.tres" id="4_gplko"] +[ext_resource type="Material" uid="uid://3odjrwml2nes" path="res://materials/sand.tres" id="5_12jug"] +[ext_resource type="Material" uid="uid://cw85kxowmkj37" path="res://materials/wet_concrete.tres" id="6_q1c2f"] +[ext_resource type="Material" uid="uid://c5wve1c3hypfo" path="res://materials/marble.tres" id="7_ebvqo"] +[ext_resource type="Material" uid="uid://cbijbaq5qol7n" path="res://materials/ice.tres" id="7_k1q1v"] +[ext_resource type="Material" uid="uid://b74tdcluvrao6" path="res://materials/lava.tres" id="8_jphcw"] +[ext_resource type="Script" path="res://scripts/grid.gd" id="10_wwlcf"] +[ext_resource type="Shader" path="res://shaders/plasma.gdshader" id="11_aoush"] +[ext_resource type="Texture2D" uid="uid://chjqieyps5n5r" path="res://checker.png" id="14"] +[ext_resource type="Script" path="res://tester.gd" id="18"] + +[sub_resource type="ProceduralSkyMaterial" id="9"] + +[sub_resource type="Sky" id="10"] +sky_material = SubResource("9") + +[sub_resource type="Environment" id="11"] +background_mode = 2 +sky = SubResource("10") +tonemap_mode = 3 +tonemap_white = 6.0 + +[sub_resource type="StandardMaterial3D" id="13"] +diffuse_mode = 1 +albedo_texture = ExtResource("14") +uv1_scale = Vector3(32, 32, 1) +texture_filter = 5 + +[sub_resource type="PlaneMesh" id="14"] +material = SubResource("13") +size = Vector2(128, 128) + +[sub_resource type="Animation" id="Animation_2qwoj"] +length = 0.001 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Testers/NoiseTextureLava/MeshInstance3D:surface_material_override/0:uv1_offset") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Vector3(0, 0, 0)] +} + +[sub_resource type="Animation" id="Animation_nbv0n"] +resource_name = "animate_textures" +length = 300.0 +loop_mode = 1 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Testers/NoiseTextureLava/MeshInstance3D:surface_material_override/0:uv1_offset") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 300), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [Vector3(0, 0, 0), Vector3(4, 1, 0)] +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_sin37"] +_data = { +"RESET": SubResource("Animation_2qwoj"), +"animate_textures": SubResource("Animation_nbv0n") +} + +[sub_resource type="SphereMesh" id="SphereMesh_be5u0"] +radius = 0.75 +height = 1.5 + +[sub_resource type="BoxMesh" id="BoxMesh_opf1g"] +size = Vector3(3, 1, 4) + +[sub_resource type="Gradient" id="Gradient_iy4y2"] +offsets = PackedFloat32Array(0, 0.0211082, 0.0435356, 0.0633245, 1) +colors = PackedColorArray(0, 0, 0, 1, 0.733005, 0.733005, 0.733005, 1, 0.0461741, 0.0461741, 0.0461741, 1, 0.72, 0.69192, 0.6264, 1, 1, 1, 1, 1) + +[sub_resource type="FastNoiseLite" id="FastNoiseLite_mc7b4"] +noise_type = 2 +frequency = 0.042 +fractal_type = 0 +fractal_octaves = 3 +fractal_gain = 1.596 +fractal_weighted_strength = 0.44 +cellular_jitter = 0.03 +cellular_return_type = 4 +domain_warp_enabled = true +domain_warp_type = 2 +domain_warp_amplitude = 2.0 +domain_warp_fractal_type = 2 + +[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_e1o5w"] +width = 1024 +height = 1024 +seamless = true +seamless_blend_skirt = 0.0 +color_ramp = SubResource("Gradient_iy4y2") +noise = SubResource("FastNoiseLite_mc7b4") + +[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_71qgk"] +width = 1024 +height = 1024 +seamless = true +seamless_blend_skirt = 0.065 +as_normal_map = true +bump_strength = 2.0 +color_ramp = SubResource("Gradient_iy4y2") +noise = SubResource("FastNoiseLite_mc7b4") + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_aq2a1"] +albedo_texture = SubResource("NoiseTexture2D_e1o5w") +roughness = 0.5 +roughness_texture = SubResource("NoiseTexture2D_e1o5w") +normal_enabled = true +normal_texture = SubResource("NoiseTexture2D_71qgk") +texture_filter = 5 + +[sub_resource type="Gradient" id="Gradient_5l3re"] +interpolation_mode = 2 +offsets = PackedFloat32Array(0, 0.135884, 0.329815, 0.341689, 0.544855, 0.581794, 0.770449, 0.943272) +colors = PackedColorArray(0, 0, 0, 1, 0.111922, 0.139008, 0.140144, 1, 0.398808, 0.12884, 0.147843, 1, 0.421438, 0.289437, 0.227878, 1, 0.65045, 0.360142, 0.181692, 1, 0.739192, 0.503788, 0.301212, 1, 1, 0.672262, 0.366251, 1, 1, 1, 1, 1) + +[sub_resource type="FastNoiseLite" id="FastNoiseLite_10olv"] +frequency = 0.05 +fractal_weighted_strength = 1.0 +domain_warp_enabled = true + +[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_e0bku"] +width = 64 +height = 64 +seamless = true +color_ramp = SubResource("Gradient_5l3re") +noise = SubResource("FastNoiseLite_10olv") + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_k7qv4"] +albedo_texture = SubResource("NoiseTexture2D_e0bku") +texture_filter = 4 + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_msbte"] +roughness = 0.75 +normal_enabled = true +texture_filter = 5 + +[sub_resource type="ViewportTexture" id="ViewportTexture_ykq6a"] +viewport_path = NodePath("Testers/ShaderPlasma/SubViewport") + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_4ovjj"] +resource_local_to_scene = true +shading_mode = 0 +albedo_texture = SubResource("ViewportTexture_ykq6a") +heightmap_enabled = true +heightmap_scale = 9.0 +heightmap_deep_parallax = true +heightmap_min_layers = 8 +heightmap_max_layers = 32 +heightmap_texture = SubResource("ViewportTexture_ykq6a") +heightmap_flip_texture = true +texture_filter = 5 + +[sub_resource type="Gradient" id="Gradient_hsp0x"] +offsets = PackedFloat32Array(0, 0.385224, 0.655673, 0.886544, 1) +colors = PackedColorArray(1.95531e-08, 0.0213273, 0.0973903, 1, 0.294665, 0.332091, 0.73046, 1, 0.22273, 0.723553, 0.777314, 1, 0.877091, 0.64938, 0.963435, 1, 0.932381, 0.719091, 0.921475, 1) + +[sub_resource type="FastNoiseLite" id="FastNoiseLite_r8ncc"] +frequency = 0.002 +fractal_type = 2 +fractal_octaves = 4 +fractal_lacunarity = 2.901 +fractal_gain = 0.353 + +[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_n04ac"] +width = 1024 +height = 1024 +seamless = true +color_ramp = SubResource("Gradient_hsp0x") +noise = SubResource("FastNoiseLite_r8ncc") + +[sub_resource type="FastNoiseLite" id="FastNoiseLite_25kcu"] +seed = 60607 +fractal_gain = 0.695 +domain_warp_enabled = true + +[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_pn44s"] +width = 1024 +height = 1024 +seamless = true +noise = SubResource("FastNoiseLite_25kcu") + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_2p45w"] +shader = ExtResource("11_aoush") +shader_parameter/noise1 = SubResource("NoiseTexture2D_n04ac") +shader_parameter/noise2 = SubResource("NoiseTexture2D_pn44s") + +[node name="WorldEnvironment" type="WorldEnvironment"] +environment = SubResource("11") +script = ExtResource("18") + +[node name="Plane" type="MeshInstance3D" parent="."] +layers = 2 +mesh = SubResource("14") + +[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] +transform = Transform3D(0.909487, -0.23874, 0.340349, 0, 0.818672, 0.574262, -0.415733, -0.522284, 0.744571, 3.9506, 3.39961, 3.54442) +shadow_enabled = true +shadow_bias = 0.04 +directional_shadow_mode = 0 +directional_shadow_fade_start = 1.0 +directional_shadow_max_distance = 24.0 + +[node name="ReflectionProbe" type="ReflectionProbe" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 8) +max_distance = 100.0 +size = Vector3(100, 100, 100) +box_projection = true +enable_shadows = true +ambient_mode = 0 + +[node name="AnimationPlayer" type="AnimationPlayer" parent="."] +autoplay = "animate_textures" +libraries = { +"": SubResource("AnimationLibrary_sin37") +} + +[node name="CameraHolder" type="Node3D" parent="."] +transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 0, 0.125, 26) + +[node name="RotationX" type="Node3D" parent="CameraHolder"] + +[node name="Camera3D" type="Camera3D" parent="CameraHolder/RotationX"] +fov = 70.0 + +[node name="Testers" type="Node3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 4) + +[node name="NoiseTextureGrass" type="Node3D" parent="Testers"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.025, 22) + +[node name="MeshInstance3D" type="MeshInstance3D" parent="Testers/NoiseTextureGrass"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.25, 0) +mesh = SubResource("SphereMesh_be5u0") +skeleton = NodePath("../../..") +surface_material_override/0 = ExtResource("4_gplko") + +[node name="MeshInstance3D2" type="MeshInstance3D" parent="Testers/NoiseTextureGrass"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1.5, 0) +mesh = SubResource("BoxMesh_opf1g") +surface_material_override/0 = ExtResource("4_gplko") + +[node name="NoiseTextureSand" type="Node3D" parent="Testers"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.025, 18) + +[node name="MeshInstance3D" type="MeshInstance3D" parent="Testers/NoiseTextureSand"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.25, 0) +mesh = SubResource("SphereMesh_be5u0") +skeleton = NodePath("../../..") +surface_material_override/0 = ExtResource("5_12jug") + +[node name="MeshInstance3D2" type="MeshInstance3D" parent="Testers/NoiseTextureSand"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1.5, 0) +mesh = SubResource("BoxMesh_opf1g") +surface_material_override/0 = ExtResource("5_12jug") + +[node name="NoiseTextureWetConcrete" type="Node3D" parent="Testers"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.025, 14) + +[node name="MeshInstance3D" type="MeshInstance3D" parent="Testers/NoiseTextureWetConcrete"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.25, 0) +mesh = SubResource("SphereMesh_be5u0") +skeleton = NodePath("../../..") +surface_material_override/0 = ExtResource("6_q1c2f") + +[node name="MeshInstance3D2" type="MeshInstance3D" parent="Testers/NoiseTextureWetConcrete"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1.5, 0) +mesh = SubResource("BoxMesh_opf1g") +surface_material_override/0 = ExtResource("6_q1c2f") + +[node name="NoiseTextureBathroomFloorTile" type="Node3D" parent="Testers"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.025, 10) + +[node name="MeshInstance3D" type="MeshInstance3D" parent="Testers/NoiseTextureBathroomFloorTile"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.25, 0) +mesh = SubResource("SphereMesh_be5u0") +skeleton = NodePath("../../..") +surface_material_override/0 = SubResource("StandardMaterial3D_aq2a1") + +[node name="MeshInstance3D2" type="MeshInstance3D" parent="Testers/NoiseTextureBathroomFloorTile"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1.5, 0) +mesh = SubResource("BoxMesh_opf1g") +surface_material_override/0 = SubResource("StandardMaterial3D_aq2a1") + +[node name="NoiseTextureIce" type="Node3D" parent="Testers"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.025, 6) + +[node name="MeshInstance3D" type="MeshInstance3D" parent="Testers/NoiseTextureIce"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.25, 0) +mesh = SubResource("SphereMesh_be5u0") +skeleton = NodePath("../../..") +surface_material_override/0 = ExtResource("7_k1q1v") + +[node name="MeshInstance3D2" type="MeshInstance3D" parent="Testers/NoiseTextureIce"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1.5, 0) +mesh = SubResource("BoxMesh_opf1g") +surface_material_override/0 = ExtResource("7_k1q1v") + +[node name="NoiseTextureMarble" type="Node3D" parent="Testers"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.025, 2) + +[node name="MeshInstance3D" type="MeshInstance3D" parent="Testers/NoiseTextureMarble"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.25, 0) +mesh = SubResource("SphereMesh_be5u0") +skeleton = NodePath("../../..") +surface_material_override/0 = ExtResource("7_ebvqo") + +[node name="MeshInstance3D2" type="MeshInstance3D" parent="Testers/NoiseTextureMarble"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1.5, 0) +mesh = SubResource("BoxMesh_opf1g") +surface_material_override/0 = ExtResource("7_ebvqo") + +[node name="NoiseTextureLava" type="Node3D" parent="Testers"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.025, -2) + +[node name="MeshInstance3D" type="MeshInstance3D" parent="Testers/NoiseTextureLava"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.25, 0) +mesh = SubResource("SphereMesh_be5u0") +skeleton = NodePath("../../..") +surface_material_override/0 = ExtResource("8_jphcw") + +[node name="MeshInstance3D2" type="MeshInstance3D" parent="Testers/NoiseTextureLava"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1.5, 0) +mesh = SubResource("BoxMesh_opf1g") +surface_material_override/0 = ExtResource("8_jphcw") + +[node name="NoiseTextureTrypophobia" type="Node3D" parent="Testers"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.025, -6) + +[node name="MeshInstance3D" type="MeshInstance3D" parent="Testers/NoiseTextureTrypophobia"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.00275182, -0.244153, -0.000101089) +mesh = SubResource("SphereMesh_be5u0") +skeleton = NodePath("../../..") +surface_material_override/0 = ExtResource("3_322sv") + +[node name="MeshInstance3D2" type="MeshInstance3D" parent="Testers/NoiseTextureTrypophobia"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1.5, 0) +mesh = SubResource("BoxMesh_opf1g") +surface_material_override/0 = ExtResource("3_322sv") + +[node name="NoiseTexturePixelArt" type="Node3D" parent="Testers"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.025, -10) + +[node name="MeshInstance3D" type="MeshInstance3D" parent="Testers/NoiseTexturePixelArt"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.00275182, -0.244153, -0.000101089) +mesh = SubResource("SphereMesh_be5u0") +skeleton = NodePath("../../..") +surface_material_override/0 = SubResource("StandardMaterial3D_k7qv4") + +[node name="MeshInstance3D2" type="MeshInstance3D" parent="Testers/NoiseTexturePixelArt"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1.5, 0) +mesh = SubResource("BoxMesh_opf1g") +surface_material_override/0 = SubResource("StandardMaterial3D_k7qv4") + +[node name="ScriptGrid" type="Node3D" parent="Testers"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.025, -14) + +[node name="MeshInstance3D" type="MeshInstance3D" parent="Testers/ScriptGrid"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.00275182, -0.244153, -0.000101089) +mesh = SubResource("SphereMesh_be5u0") +skeleton = NodePath("../../..") +surface_material_override/0 = SubResource("StandardMaterial3D_msbte") +script = ExtResource("10_wwlcf") + +[node name="MeshInstance3D2" type="MeshInstance3D" parent="Testers/ScriptGrid"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1.5, 0) +mesh = SubResource("BoxMesh_opf1g") +surface_material_override/0 = SubResource("StandardMaterial3D_msbte") + +[node name="ShaderPlasma" type="Node3D" parent="Testers"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.025, -18) + +[node name="MeshInstance3D" type="MeshInstance3D" parent="Testers/ShaderPlasma"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.00275182, -0.244153, -0.000101089) +mesh = SubResource("SphereMesh_be5u0") +skeleton = NodePath("../../..") +surface_material_override/0 = SubResource("StandardMaterial3D_4ovjj") + +[node name="MeshInstance3D2" type="MeshInstance3D" parent="Testers/ShaderPlasma"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1.5, 0) +mesh = SubResource("BoxMesh_opf1g") +surface_material_override/0 = SubResource("StandardMaterial3D_4ovjj") + +[node name="SubViewport" type="SubViewport" parent="Testers/ShaderPlasma"] +size = Vector2i(1024, 1024) + +[node name="ColorRect" type="ColorRect" parent="Testers/ShaderPlasma/SubViewport"] +material = SubResource("ShaderMaterial_2p45w") +offset_right = 1024.0 +offset_bottom = 1024.0 + +[node name="TestName" type="Label" parent="."] +anchors_preset = 7 +anchor_left = 0.5 +anchor_top = 1.0 +anchor_right = 0.5 +anchor_bottom = 1.0 +offset_left = -192.0 +offset_top = -58.0 +offset_right = 192.0 +offset_bottom = -24.0 +grow_horizontal = 2 +grow_vertical = 0 +theme_override_colors/font_outline_color = Color(0, 0, 0, 1) +theme_override_constants/outline_size = 5 +theme_override_font_sizes/font_size = 24 +horizontal_alignment = 1 + +[node name="Previous" type="Button" parent="."] +anchors_preset = 2 +anchor_top = 1.0 +anchor_bottom = 1.0 +offset_left = 24.0 +offset_top = -55.0 +offset_right = 135.0 +offset_bottom = -24.0 +grow_vertical = 0 +text = "« Previous" + +[node name="Next" type="Button" parent="."] +anchors_preset = 3 +anchor_left = 1.0 +anchor_top = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = -107.0 +offset_top = -55.0 +offset_right = -24.0 +offset_bottom = -24.0 +grow_horizontal = 0 +grow_vertical = 0 +text = "Next »" + +[connection signal="pressed" from="Previous" to="." method="_on_previous_pressed"] +[connection signal="pressed" from="Next" to="." method="_on_next_pressed"] diff --git a/3d/procedural_materials/tester.gd b/3d/procedural_materials/tester.gd new file mode 100644 index 00000000..842cc061 --- /dev/null +++ b/3d/procedural_materials/tester.gd @@ -0,0 +1,70 @@ +extends WorldEnvironment + +const ROT_SPEED = 0.003 +const ZOOM_SPEED = 0.125 +const MAIN_BUTTONS = MOUSE_BUTTON_MASK_LEFT | MOUSE_BUTTON_MASK_RIGHT | MOUSE_BUTTON_MASK_MIDDLE + +var tester_index = 0 +var rot_x = deg_to_rad(-22.5) # This must be kept in sync with RotationX. +var rot_y = deg_to_rad(90) # This must be kept in sync with CameraHolder. +var zoom = 2.5 +var base_height = ProjectSettings.get_setting("display/window/size/viewport_height") + +@onready var testers = $Testers +@onready var camera_holder = $CameraHolder # Has a position and rotates on Y. +@onready var rotation_x = $CameraHolder/RotationX +@onready var camera = $CameraHolder/RotationX/Camera3D + + +func _ready(): + camera_holder.transform.basis = Basis.from_euler(Vector3(0, rot_y, 0)) + rotation_x.transform.basis = Basis.from_euler(Vector3(rot_x, 0, 0)) + update_gui() + + +func _unhandled_input(event): + if event.is_action_pressed("ui_left"): + _on_previous_pressed() + if event.is_action_pressed("ui_right"): + _on_next_pressed() + + if event is InputEventMouseButton: + if event.button_index == MOUSE_BUTTON_WHEEL_UP: + zoom -= ZOOM_SPEED + if event.button_index == MOUSE_BUTTON_WHEEL_DOWN: + zoom += ZOOM_SPEED + zoom = clamp(zoom, 1.5, 4) + + if event is InputEventMouseMotion and event.button_mask & MAIN_BUTTONS: + # Compensate motion speed to be resolution-independent (based on the window height). + var relative_motion = event.relative * DisplayServer.window_get_size().y / base_height + rot_y -= relative_motion.x * ROT_SPEED + rot_x -= relative_motion.y * ROT_SPEED + rot_x = clamp(rot_x, deg_to_rad(-90), 0) + camera_holder.transform.basis = Basis.from_euler(Vector3(0, rot_y, 0)) + rotation_x.transform.basis = Basis.from_euler(Vector3(rot_x, 0, 0)) + + +func _process(delta): + var current_tester = testers.get_child(tester_index) + # This code assumes CameraHolder's X and Y coordinates are already correct. + var current_position = camera_holder.global_transform.origin.z + var target_position = current_tester.global_transform.origin.z + camera_holder.global_transform.origin.z = lerpf(current_position, target_position, 3 * delta) + camera.position.z = lerpf(camera.position.z, zoom, 10 * delta) + + +func _on_previous_pressed(): + tester_index = max(0, tester_index - 1) + update_gui() + + +func _on_next_pressed(): + tester_index = min(tester_index + 1, testers.get_child_count() - 1) + update_gui() + + +func update_gui(): + $TestName.text = str(testers.get_child(tester_index).name).capitalize() + $Previous.disabled = tester_index == 0 + $Next.disabled = tester_index == testers.get_child_count() - 1