diff --git a/editor/editor_resource_picker.cpp b/editor/editor_resource_picker.cpp index 66e73e16d..e8ab61b26 100644 --- a/editor/editor_resource_picker.cpp +++ b/editor/editor_resource_picker.cpp @@ -65,6 +65,8 @@ #include "scene/main/node.h" #include "scene/main/viewport.h" #include "scene/resources/material/material.h" +#include "scene/resources/material/spatial_material.h" +#include "scene/resources/material/shader_material.h" #include "scene/resources/shader.h" #include "scene/resources/style_box.h" #include "scene/resources/texture.h" diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index 2767cd1db..22d95b092 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -50,6 +50,8 @@ #include "scene/resources/resource_format_text.h" #include "core/scene/resources/shapes/shape.h" #include "core/scene/resources/shapes/sphere_shape.h" +#include "scene/resources/material/spatial_material.h" +#include "scene/resources/material/shader_material.h" uint32_t EditorSceneImporter::get_import_flags() const { if (get_script_instance()) { diff --git a/editor/plugins/animation_player_editor_plugin.h b/editor/plugins/animation_player_editor_plugin.h index 5dad60b6a..da408f8fd 100644 --- a/editor/plugins/animation_player_editor_plugin.h +++ b/editor/plugins/animation_player_editor_plugin.h @@ -41,6 +41,8 @@ #include "core/string/ustring.h" #include "core/containers/vector.h" +#include "scene/resources/material/shader_material.h" + class AnimationTrackEditor; class AnimationPlayerEditorPlugin; class AcceptDialog; diff --git a/editor/plugins/collision_polygon_editor_plugin.cpp b/editor/plugins/collision_polygon_editor_plugin.cpp index 7c573a2d7..9140b98c2 100644 --- a/editor/plugins/collision_polygon_editor_plugin.cpp +++ b/editor/plugins/collision_polygon_editor_plugin.cpp @@ -62,6 +62,7 @@ #include "scene/main/node.h" #include "scene/main/scene_tree.h" #include "scene/resources/material/material.h" +#include "scene/resources/material/spatial_material.h" #include "scene/resources/mesh/mesh.h" #include "scene/resources/texture.h" diff --git a/editor/plugins/material_editor_plugin.cpp b/editor/plugins/material_editor_plugin.cpp index a542dcb40..a9d1beafc 100644 --- a/editor/plugins/material_editor_plugin.cpp +++ b/editor/plugins/material_editor_plugin.cpp @@ -36,6 +36,8 @@ #include "scene/main/viewport.h" #include "scene/resources/environment_3d.h" #include "scene/resources/material/particles_material.h" +#include "scene/resources/material/spatial_material.h" +#include "scene/resources/material/shader_material.h" #include "scene/resources/sky.h" #include "scene/resources/world_3d.h" #include "core/object/class_db.h" diff --git a/editor/plugins/navigation_obstacle_3d_editor_plugin.h b/editor/plugins/navigation_obstacle_3d_editor_plugin.h index 3b31e62f5..3d76054a1 100644 --- a/editor/plugins/navigation_obstacle_3d_editor_plugin.h +++ b/editor/plugins/navigation_obstacle_3d_editor_plugin.h @@ -36,6 +36,7 @@ #include "scene/3d/mesh_instance.h" #include "scene/gui/box_container.h" #include "scene/resources/mesh/immediate_mesh.h" +#include "scene/resources/material/spatial_material.h" #include "scene/3d/navigation_obstacle.h" diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h index 2c7dd2266..c8b583d13 100644 --- a/editor/plugins/spatial_editor_plugin.h +++ b/editor/plugins/spatial_editor_plugin.h @@ -62,6 +62,8 @@ #include "editor/spatial_editor_gizmos.h" #include "scene/resources/material/material.h" +#include "scene/resources/material/spatial_material.h" +#include "scene/resources/material/shader_material.h" #include "scene/resources/mesh/mesh.h" #include "scene/resources/texture.h" diff --git a/editor/spatial_editor_gizmos.cpp b/editor/spatial_editor_gizmos.cpp index 5d73b8bba..a8b5cf3bb 100644 --- a/editor/spatial_editor_gizmos.cpp +++ b/editor/spatial_editor_gizmos.cpp @@ -93,6 +93,8 @@ #include "core/scene/resources/shapes/cylinder_shape.h" #include "core/scene/resources/shapes/height_map_shape.h" #include "scene/resources/material/material.h" +#include "scene/resources/material/spatial_material.h" +#include "scene/resources/material/shader_material.h" #include "scene/resources/navigation/navigation_mesh.h" #include "scene/resources/occluder_shape.h" #include "scene/resources/occluder_shape_polygon.h" diff --git a/editor/spatial_editor_gizmos.h b/editor/spatial_editor_gizmos.h index 2eb48cb32..f93a2c54a 100644 --- a/editor/spatial_editor_gizmos.h +++ b/editor/spatial_editor_gizmos.h @@ -46,6 +46,7 @@ #include "core/variant/variant.h" #include "scene/resources/mesh/mesh.h" +#include "scene/resources/material/spatial_material.h" #include "modules/modules_enabled.gen.h" diff --git a/editor_modules/gltf/gltf_document.h b/editor_modules/gltf/gltf_document.h index 65dc02ad9..b5bfbb7b9 100644 --- a/editor_modules/gltf/gltf_document.h +++ b/editor_modules/gltf/gltf_document.h @@ -36,6 +36,7 @@ #include "scene/main/spatial.h" #include "scene/animation/animation_player.h" #include "scene/resources/material/material.h" +#include "scene/resources/material/spatial_material.h" #include "scene/resources/texture.h" #include "extensions/gltf_document_extension.h" diff --git a/modules/entity_spell_system/material_cache/ess_material_cache_pcm.cpp b/modules/entity_spell_system/material_cache/ess_material_cache_pcm.cpp index 7c81727f1..49bcb0c37 100644 --- a/modules/entity_spell_system/material_cache/ess_material_cache_pcm.cpp +++ b/modules/entity_spell_system/material_cache/ess_material_cache_pcm.cpp @@ -25,6 +25,8 @@ SOFTWARE. #include "../../texture_packer/texture_packer.h" #include "../singletons/ess.h" #include "scene/resources/texture.h" +#include "scene/resources/material/spatial_material.h" +#include "scene/resources/material/shader_material.h" int ESSMaterialCachePCM::get_texture_flags() const { return _packer->get_texture_flags(); diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp index cb0864950..d905aadbc 100644 --- a/modules/gridmap/grid_map.cpp +++ b/modules/gridmap/grid_map.cpp @@ -43,6 +43,7 @@ #include "scene/resources/navigation/navigation_mesh.h" #include "scene/resources/world_3d.h" +#include "scene/resources/material/spatial_material.h" bool GridMap::_set(const StringName &p_name, const Variant &p_value) { String name = p_name; diff --git a/modules/gridmap/grid_map_editor_plugin.h b/modules/gridmap/grid_map_editor_plugin.h index d027c4627..cc22b78cb 100644 --- a/modules/gridmap/grid_map_editor_plugin.h +++ b/modules/gridmap/grid_map_editor_plugin.h @@ -40,6 +40,8 @@ #include "editor/pane_drag.h" #include "grid_map.h" +#include "scene/resources/material/spatial_material.h" + class UndoRedo; class Panel; class MenuButton; diff --git a/modules/material_maker/editor/widgets/gradient_editor/gradient_editor.cpp b/modules/material_maker/editor/widgets/gradient_editor/gradient_editor.cpp index 5179961b3..a238c2fce 100644 --- a/modules/material_maker/editor/widgets/gradient_editor/gradient_editor.cpp +++ b/modules/material_maker/editor/widgets/gradient_editor/gradient_editor.cpp @@ -17,6 +17,7 @@ #include "scene/gui/option_button.h" #include "scene/gui/texture_rect.h" #include "scene/resources/material/material.h" +#include "scene/resources/material/shader_material.h" MMGraphNode *MMGradientEditor::get_graph_node() { return graph_node; diff --git a/modules/mesh_data_resource/nodes/mesh_data_instance.cpp b/modules/mesh_data_resource/nodes/mesh_data_instance.cpp index 4083dc1d1..156df5aa5 100644 --- a/modules/mesh_data_resource/nodes/mesh_data_instance.cpp +++ b/modules/mesh_data_resource/nodes/mesh_data_instance.cpp @@ -1,6 +1,7 @@ #include "mesh_data_instance.h" #include "scene/resources/texture.h" +#include "scene/resources/material/spatial_material.h" #include "core/io/image.h" diff --git a/modules/mesh_data_resource/props/prop_data_mesh_data.cpp b/modules/mesh_data_resource/props/prop_data_mesh_data.cpp index 6cc78106f..42ad23322 100644 --- a/modules/mesh_data_resource/props/prop_data_mesh_data.cpp +++ b/modules/mesh_data_resource/props/prop_data_mesh_data.cpp @@ -28,6 +28,7 @@ SOFTWARE. #include "../nodes/mesh_data_instance.h" #include "scene/resources/material/material.h" +#include "scene/resources/material/spatial_material.h" Ref PropDataMeshData::get_mesh() const { return _mesh; diff --git a/modules/props/material_cache/prop_material_cache_pcm.cpp b/modules/props/material_cache/prop_material_cache_pcm.cpp index 363bc2e7c..80e66fe16 100644 --- a/modules/props/material_cache/prop_material_cache_pcm.cpp +++ b/modules/props/material_cache/prop_material_cache_pcm.cpp @@ -25,6 +25,8 @@ SOFTWARE. #include "../../texture_packer/texture_packer.h" #include "../singleton/prop_cache.h" #include "scene/resources/texture.h" +#include "scene/resources/material/spatial_material.h" +#include "scene/resources/material/shader_material.h" int PropMaterialCachePCM::get_texture_flags() const { return _packer->get_texture_flags(); diff --git a/modules/props/prop_instance.cpp b/modules/props/prop_instance.cpp index 8b35ab3a6..213253fb0 100644 --- a/modules/props/prop_instance.cpp +++ b/modules/props/prop_instance.cpp @@ -4,6 +4,8 @@ #include "scene/3d/light.h" #include "scene/3d/physics_body.h" +#include "scene/resources/material/spatial_material.h" +#include "scene/resources/material/shader_material.h" #include "modules/modules_enabled.gen.h" diff --git a/modules/props/prop_instance_prop_job.cpp b/modules/props/prop_instance_prop_job.cpp index 65070eb64..1e42898ed 100644 --- a/modules/props/prop_instance_prop_job.cpp +++ b/modules/props/prop_instance_prop_job.cpp @@ -32,6 +32,8 @@ SOFTWARE. #include "scene/resources/world_3d.h" #include "core/servers/physics/physics_server.h" #include "singleton/prop_cache.h" +#include "scene/resources/material/spatial_material.h" +#include "scene/resources/material/shader_material.h" #include "modules/modules_enabled.gen.h" diff --git a/modules/props_2d/material_cache/prop_2d_material_cache_pcm.cpp b/modules/props_2d/material_cache/prop_2d_material_cache_pcm.cpp index eba29530f..9b96c5dfc 100644 --- a/modules/props_2d/material_cache/prop_2d_material_cache_pcm.cpp +++ b/modules/props_2d/material_cache/prop_2d_material_cache_pcm.cpp @@ -25,6 +25,7 @@ SOFTWARE. #include "../../texture_packer/texture_packer.h" #include "../singleton/prop_2d_cache.h" #include "scene/resources/texture.h" +#include "scene/resources/material/shader_material.h" int Prop2DMaterialCachePCM::get_texture_flags() const { return _packer->get_texture_flags(); diff --git a/modules/terraman/library/terrain_library_merger.cpp b/modules/terraman/library/terrain_library_merger.cpp index 4e0f5204e..3d8c47291 100644 --- a/modules/terraman/library/terrain_library_merger.cpp +++ b/modules/terraman/library/terrain_library_merger.cpp @@ -24,6 +24,8 @@ SOFTWARE. #include "scene/resources/packed_scene.h" #include "scene/resources/texture.h" +#include "scene/resources/material/spatial_material.h" +#include "scene/resources/material/shader_material.h" #include "modules/modules_enabled.gen.h" diff --git a/modules/terraman/library/terrain_library_merger_pcm.cpp b/modules/terraman/library/terrain_library_merger_pcm.cpp index f337f2991..81123214b 100644 --- a/modules/terraman/library/terrain_library_merger_pcm.cpp +++ b/modules/terraman/library/terrain_library_merger_pcm.cpp @@ -25,6 +25,8 @@ SOFTWARE. #include "../../texture_packer/texture_packer.h" #include "scene/resources/packed_scene.h" #include "scene/resources/texture.h" +#include "scene/resources/material/spatial_material.h" +#include "scene/resources/material/shader_material.h" #include "modules/modules_enabled.gen.h" diff --git a/modules/terraman/library/terrain_material_cache_pcm.cpp b/modules/terraman/library/terrain_material_cache_pcm.cpp index 0daa0107f..390cd7c79 100644 --- a/modules/terraman/library/terrain_material_cache_pcm.cpp +++ b/modules/terraman/library/terrain_material_cache_pcm.cpp @@ -26,6 +26,8 @@ SOFTWARE. #include "scene/resources/texture.h" #include "terrain_surface.h" #include "terrain_surface_merger.h" +#include "scene/resources/material/spatial_material.h" +#include "scene/resources/material/shader_material.h" int TerrainMaterialCachePCM::get_texture_flags() const { return _packer->get_texture_flags(); diff --git a/modules/terraman/world/jobs/terrain_prop_job.cpp b/modules/terraman/world/jobs/terrain_prop_job.cpp index 4536bb951..92029ac54 100644 --- a/modules/terraman/world/jobs/terrain_prop_job.cpp +++ b/modules/terraman/world/jobs/terrain_prop_job.cpp @@ -33,6 +33,8 @@ SOFTWARE. #include "../default/terrain_chunk_default.h" #include "scene/resources/world_3d.h" #include "core/servers/physics/physics_server.h" +#include "scene/resources/material/spatial_material.h" +#include "scene/resources/material/shader_material.h" #include "modules/modules_enabled.gen.h" diff --git a/modules/terraman/world/jobs/terrain_terrain_job.cpp b/modules/terraman/world/jobs/terrain_terrain_job.cpp index c55a48b4e..62748e5db 100644 --- a/modules/terraman/world/jobs/terrain_terrain_job.cpp +++ b/modules/terraman/world/jobs/terrain_terrain_job.cpp @@ -31,6 +31,8 @@ SOFTWARE. #include "../default/terrain_chunk_default.h" #include "core/servers/physics/physics_server.h" +#include "scene/resources/material/spatial_material.h" +#include "scene/resources/material/shader_material.h" #include "modules/modules_enabled.gen.h" diff --git a/modules/terraman_2d/library/terrain_2d_library_merger.cpp b/modules/terraman_2d/library/terrain_2d_library_merger.cpp index bdb43996f..ece086669 100644 --- a/modules/terraman_2d/library/terrain_2d_library_merger.cpp +++ b/modules/terraman_2d/library/terrain_2d_library_merger.cpp @@ -24,6 +24,7 @@ SOFTWARE. #include "scene/resources/packed_scene.h" #include "scene/resources/texture.h" +#include "scene/resources/material/shader_material.h" #include "modules/modules_enabled.gen.h" diff --git a/modules/terraman_2d/library/terrain_2d_material_cache_pcm.cpp b/modules/terraman_2d/library/terrain_2d_material_cache_pcm.cpp index 225633de5..436cb6b27 100644 --- a/modules/terraman_2d/library/terrain_2d_material_cache_pcm.cpp +++ b/modules/terraman_2d/library/terrain_2d_material_cache_pcm.cpp @@ -26,6 +26,7 @@ SOFTWARE. #include "scene/resources/texture.h" #include "terrain_2d_surface.h" #include "terrain_2d_surface_merger.h" +#include "scene/resources/material/shader_material.h" int Terrain2DMaterialCachePCM::get_texture_flags() const { return _packer->get_texture_flags(); diff --git a/modules/tile_map/tile_map.cpp b/modules/tile_map/tile_map.cpp index d3d21265e..6438a7ac5 100644 --- a/modules/tile_map/tile_map.cpp +++ b/modules/tile_map/tile_map.cpp @@ -39,6 +39,7 @@ #include "servers/navigation_2d_server.h" #include "core/servers/physics_2d/physics_2d_server.h" #include "servers/rendering/rendering_server_canvas_helper.h" +#include "scene/resources/material/shader_material.h" #ifdef DEBUG_ENABLED #include "servers/navigation_server.h" diff --git a/modules/tile_map/tile_set.h b/modules/tile_map/tile_set.h index 442057235..dccb7933d 100644 --- a/modules/tile_map/tile_set.h +++ b/modules/tile_map/tile_set.h @@ -40,6 +40,7 @@ #include "scene/resources/navigation_2d/navigation_polygon.h" #include "core/scene/resources/shapes_2d/shape_2d.h" #include "scene/resources/texture.h" +#include "scene/resources/material/shader_material.h" class TileSet : public Resource { GDCLASS(TileSet, Resource); diff --git a/modules/voxelman/library/voxel_library_merger.cpp b/modules/voxelman/library/voxel_library_merger.cpp index 9172b15dc..2a030970d 100644 --- a/modules/voxelman/library/voxel_library_merger.cpp +++ b/modules/voxelman/library/voxel_library_merger.cpp @@ -24,6 +24,8 @@ SOFTWARE. #include "scene/resources/packed_scene.h" #include "scene/resources/texture.h" +#include "scene/resources/material/spatial_material.h" +#include "scene/resources/material/shader_material.h" #include "modules/modules_enabled.gen.h" diff --git a/modules/voxelman/library/voxel_library_merger_pcm.cpp b/modules/voxelman/library/voxel_library_merger_pcm.cpp index c2a972425..118ab4b10 100644 --- a/modules/voxelman/library/voxel_library_merger_pcm.cpp +++ b/modules/voxelman/library/voxel_library_merger_pcm.cpp @@ -25,6 +25,8 @@ SOFTWARE. #include "../../texture_packer/texture_packer.h" #include "scene/resources/packed_scene.h" #include "scene/resources/texture.h" +#include "scene/resources/material/spatial_material.h" +#include "scene/resources/material/shader_material.h" #include "modules/modules_enabled.gen.h" diff --git a/modules/voxelman/library/voxel_material_cache_pcm.cpp b/modules/voxelman/library/voxel_material_cache_pcm.cpp index 9c6426daf..f87b03585 100644 --- a/modules/voxelman/library/voxel_material_cache_pcm.cpp +++ b/modules/voxelman/library/voxel_material_cache_pcm.cpp @@ -26,6 +26,8 @@ SOFTWARE. #include "scene/resources/texture.h" #include "voxel_surface.h" #include "voxel_surface_merger.h" +#include "scene/resources/material/spatial_material.h" +#include "scene/resources/material/shader_material.h" int VoxelMaterialCachePCM::get_texture_flags() const { return _packer->get_texture_flags(); diff --git a/modules/voxelman/world/jobs/voxel_prop_job.cpp b/modules/voxelman/world/jobs/voxel_prop_job.cpp index 446bd436e..74a843b89 100644 --- a/modules/voxelman/world/jobs/voxel_prop_job.cpp +++ b/modules/voxelman/world/jobs/voxel_prop_job.cpp @@ -34,6 +34,8 @@ SOFTWARE. #include "../default/voxel_chunk_default.h" #include "scene/resources/world_3d.h" #include "core/servers/physics/physics_server.h" +#include "scene/resources/material/spatial_material.h" +#include "scene/resources/material/shader_material.h" #include "modules/modules_enabled.gen.h" diff --git a/modules/voxelman/world/jobs/voxel_terrain_job.cpp b/modules/voxelman/world/jobs/voxel_terrain_job.cpp index 4559a6d94..8e1fbaca4 100644 --- a/modules/voxelman/world/jobs/voxel_terrain_job.cpp +++ b/modules/voxelman/world/jobs/voxel_terrain_job.cpp @@ -31,6 +31,8 @@ SOFTWARE. #include "../../library/voxel_material_cache.h" #include "../default/voxel_chunk_default.h" #include "core/servers/physics/physics_server.h" +#include "scene/resources/material/spatial_material.h" +#include "scene/resources/material/shader_material.h" #include "modules/modules_enabled.gen.h" diff --git a/scene/3d/cpu_particles.cpp b/scene/3d/cpu_particles.cpp index adcf580e7..50de3700c 100644 --- a/scene/3d/cpu_particles.cpp +++ b/scene/3d/cpu_particles.cpp @@ -37,6 +37,8 @@ #include "core/scene/resources/gradient.h" #include "scene/resources/mesh/mesh.h" #include "scene/resources/material/particles_material.h" +#include "scene/resources/material/spatial_material.h" +#include "scene/resources/material/shader_material.h" #include "core/servers/rendering/rendering_server.h" AABB CPUParticles::get_aabb() const { diff --git a/scene/3d/label_3d.h b/scene/3d/label_3d.h index eaae3ea92..6d6c0f95b 100644 --- a/scene/3d/label_3d.h +++ b/scene/3d/label_3d.h @@ -34,6 +34,7 @@ #include "scene/3d/visual_instance.h" #include "scene/resources/font/font.h" #include "scene/resources/material/material.h" +#include "scene/resources/material/spatial_material.h" class TriangleMesh; diff --git a/scene/3d/mesh_instance.cpp b/scene/3d/mesh_instance.cpp index 5b818aee2..0bf9d83a7 100644 --- a/scene/3d/mesh_instance.cpp +++ b/scene/3d/mesh_instance.cpp @@ -35,6 +35,7 @@ #include "core/core_string_names.h" #include "physics_body.h" #include "scene/resources/material/material.h" +#include "scene/resources/material/spatial_material.h" #include "scene/resources/mesh/mesh.h" #include "scene/main/scene_string_names.h" #include "servers/rendering/rendering_server_globals.h" diff --git a/scene/3d/navigation_agent.cpp b/scene/3d/navigation_agent.cpp index 6869767cf..f92a02158 100644 --- a/scene/3d/navigation_agent.cpp +++ b/scene/3d/navigation_agent.cpp @@ -35,6 +35,7 @@ #include "scene/3d/navigation.h" #include "scene/3d/navigation_link_3d.h" #include "scene/resources/material/material.h" +#include "scene/resources/material/spatial_material.h" #include "scene/resources/mesh/mesh.h" #include "scene/resources/world_3d.h" #include "servers/navigation/navigation_path_query_result_3d.h" diff --git a/scene/3d/navigation_link_3d.cpp b/scene/3d/navigation_link_3d.cpp index 97bd130da..7ad7a22fb 100644 --- a/scene/3d/navigation_link_3d.cpp +++ b/scene/3d/navigation_link_3d.cpp @@ -35,6 +35,7 @@ #include "scene/resources/mesh/mesh.h" #include "scene/resources/world_3d.h" #include "servers/navigation_server.h" +#include "scene/resources/material/spatial_material.h" #ifdef DEBUG_ENABLED void NavigationLink3D::_update_debug_mesh() { diff --git a/scene/3d/navigation_mesh_instance.cpp b/scene/3d/navigation_mesh_instance.cpp index 0792b39b3..9d7b5cc6e 100644 --- a/scene/3d/navigation_mesh_instance.cpp +++ b/scene/3d/navigation_mesh_instance.cpp @@ -40,6 +40,7 @@ #include "scene/resources/world_3d.h" #include "servers/navigation/navigation_mesh_generator.h" #include "servers/navigation_server.h" +#include "scene/resources/material/spatial_material.h" void NavigationMeshInstance::set_enabled(bool p_enabled) { if (enabled == p_enabled) { diff --git a/scene/3d/navigation_obstacle.cpp b/scene/3d/navigation_obstacle.cpp index c18d6184e..df9565800 100644 --- a/scene/3d/navigation_obstacle.cpp +++ b/scene/3d/navigation_obstacle.cpp @@ -36,6 +36,7 @@ #include "scene/3d/physics_body.h" #include "scene/main/spatial.h" #include "scene/resources/material/material.h" +#include "scene/resources/material/spatial_material.h" #include "scene/resources/mesh/mesh.h" #include "core/scene/resources/shapes/shape.h" #include "scene/resources/world_3d.h" diff --git a/scene/3d/ray_cast.cpp b/scene/3d/ray_cast.cpp index 97a14ef74..a977315da 100644 --- a/scene/3d/ray_cast.cpp +++ b/scene/3d/ray_cast.cpp @@ -34,6 +34,7 @@ #include "core/config/engine.h" #include "mesh_instance.h" #include "scene/resources/material/material.h" +#include "scene/resources/material/spatial_material.h" #include "scene/resources/mesh/mesh.h" #include "scene/resources/world_3d.h" #include "core/servers/physics/physics_server.h" diff --git a/scene/3d/shape_cast.cpp b/scene/3d/shape_cast.cpp index 7cf27c071..500b58697 100644 --- a/scene/3d/shape_cast.cpp +++ b/scene/3d/shape_cast.cpp @@ -35,6 +35,7 @@ #include "mesh_instance.h" #include "core/scene/resources/shapes/concave_polygon_shape.h" #include "scene/resources/material/material.h" +#include "scene/resources/material/spatial_material.h" #include "scene/resources/mesh/mesh.h" #include "scene/resources/world_3d.h" diff --git a/scene/3d/sprite_3d.h b/scene/3d/sprite_3d.h index 5f3bc1509..76df328e7 100644 --- a/scene/3d/sprite_3d.h +++ b/scene/3d/sprite_3d.h @@ -33,6 +33,7 @@ #include "core/object/reference.h" #include "scene/3d/visual_instance.h" #include "scene/resources/material/material.h" +#include "scene/resources/material/spatial_material.h" class TriangleMesh; class SpriteFrames; diff --git a/scene/animation/root_motion_view.cpp b/scene/animation/root_motion_view.cpp index 2ae3a2e3d..71e28a537 100644 --- a/scene/animation/root_motion_view.cpp +++ b/scene/animation/root_motion_view.cpp @@ -31,6 +31,8 @@ #include "root_motion_view.h" #include "scene/animation/animation_tree.h" #include "scene/resources/material/material.h" +#include "scene/resources/material/spatial_material.h" + void RootMotionView::set_animation_path(const NodePath &p_path) { path = p_path; first = true; diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index d0b4ec8e4..c4ce5a64f 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -48,6 +48,8 @@ #include "scene/main/control.h" #include "scene/resources/font/dynamic_font.h" #include "scene/resources/material/material.h" +#include "scene/resources/material/spatial_material.h" +#include "scene/resources/material/shader_material.h" #include "scene/resources/mesh/mesh.h" #include "scene/resources/packed_scene.h" #include "scene/main/scene_string_names.h" diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 36cb5b029..b8a041dcd 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -156,6 +156,8 @@ #include "scene/resources/mesh/immediate_mesh.h" #include "core/scene/resources/shapes_2d/line_shape_2d.h" #include "scene/resources/material/material.h" +#include "scene/resources/material/spatial_material.h" +#include "scene/resources/material/shader_material.h" #include "scene/resources/mesh/mesh.h" #include "scene/resources/mesh/mesh_data_tool.h" #include "scene/resources/mesh/multimesh.h" diff --git a/scene/resources/material/material.cpp b/scene/resources/material/material.cpp index 500cd41f7..38b786c13 100644 --- a/scene/resources/material/material.cpp +++ b/scene/resources/material/material.cpp @@ -30,14 +30,6 @@ #include "material.h" -#include "core/config/engine.h" -#include "core/config/project_settings.h" -#include "core/version.h" -#include "scene/resources/texture.h" -#include "servers/rendering/shader_language.h" - -#include "scene/main/scene_string_names.h" - void Material::set_next_pass(const Ref &p_pass) { for (Ref pass_child = p_pass; pass_child != nullptr; pass_child = pass_child->get_next_pass()) { ERR_FAIL_COND_MSG(pass_child == this, "Can't set as next_pass one of its parents to prevent crashes due to recursive loop."); @@ -101,2292 +93,3 @@ Material::Material() { Material::~Material() { RenderingServer::get_singleton()->free(material); } - -/////////////////////////////////// - -bool ShaderMaterial::_set(const StringName &p_name, const Variant &p_value) { - if (shader.is_valid()) { - StringName pr = shader->remap_param(p_name); - if (!pr) { - String n = p_name; - if (n.find("param/") == 0) { //backwards compatibility - pr = n.substr(6, n.length()); - } - if (n.find("shader_param/") == 0) { //backwards compatibility - pr = n.replace_first("shader_param/", ""); - } - } - if (pr) { - RenderingServer::get_singleton()->material_set_param(_get_material(), pr, p_value); - return true; - } - } - - return false; -} - -bool ShaderMaterial::_get(const StringName &p_name, Variant &r_ret) const { - if (shader.is_valid()) { - StringName pr = shader->remap_param(p_name); - if (!pr) { - String n = p_name; - if (n.find("param/") == 0) { //backwards compatibility - pr = n.substr(6, n.length()); - } - if (n.find("shader_param/") == 0) { //backwards compatibility - pr = n.replace_first("shader_param/", ""); - } - } - - if (pr) { - r_ret = RenderingServer::get_singleton()->material_get_param(_get_material(), pr); - return true; - } - } - - return false; -} - -void ShaderMaterial::_get_property_list(List *p_list) const { - if (!shader.is_null()) { - shader->get_param_list(p_list); - } -} - -bool ShaderMaterial::property_can_revert(const String &p_name) { - if (shader.is_valid()) { - StringName pr = shader->remap_param(p_name); - if (pr) { - Variant default_value = RenderingServer::get_singleton()->material_get_param_default(_get_material(), pr); - Variant current_value; - _get(p_name, current_value); - return default_value.get_type() != Variant::NIL && default_value != current_value; - } - } - return false; -} - -Variant ShaderMaterial::property_get_revert(const String &p_name) { - Variant r_ret; - if (shader.is_valid()) { - StringName pr = shader->remap_param(p_name); - if (pr) { - r_ret = RenderingServer::get_singleton()->material_get_param_default(_get_material(), pr); - } - } - return r_ret; -} - -void ShaderMaterial::set_shader(const Ref &p_shader) { - // Only connect/disconnect the signal when running in the editor. - // This can be a slow operation, and `_change_notify()` (which is called by `_shader_changed()`) - // does nothing in non-editor builds anyway. See GH-34741 for details. - if (shader.is_valid() && Engine::get_singleton()->is_editor_hint()) { - shader->disconnect("changed", this, "_shader_changed"); - } - - shader = p_shader; - - RID rid; - if (shader.is_valid()) { - rid = shader->get_rid(); - - if (Engine::get_singleton()->is_editor_hint()) { - shader->connect("changed", this, "_shader_changed"); - } - } - - RS::get_singleton()->material_set_shader(_get_material(), rid); - _change_notify(); //properties for shader exposed - emit_changed(); -} - -Ref ShaderMaterial::get_shader() const { - return shader; -} - -void ShaderMaterial::set_shader_param(const StringName &p_param, const Variant &p_value) { - RS::get_singleton()->material_set_param(_get_material(), p_param, p_value); -} - -Variant ShaderMaterial::get_shader_param(const StringName &p_param) const { - return RS::get_singleton()->material_get_param(_get_material(), p_param); -} - -void ShaderMaterial::_shader_changed() { - _change_notify(); //update all properties -} - -void ShaderMaterial::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_shader", "shader"), &ShaderMaterial::set_shader); - ClassDB::bind_method(D_METHOD("get_shader"), &ShaderMaterial::get_shader); - ClassDB::bind_method(D_METHOD("set_shader_param", "param", "value"), &ShaderMaterial::set_shader_param); - ClassDB::bind_method(D_METHOD("get_shader_param", "param"), &ShaderMaterial::get_shader_param); - ClassDB::bind_method(D_METHOD("_shader_changed"), &ShaderMaterial::_shader_changed); - ClassDB::bind_method(D_METHOD("property_can_revert", "name"), &ShaderMaterial::property_can_revert); - ClassDB::bind_method(D_METHOD("property_get_revert", "name"), &ShaderMaterial::property_get_revert); - - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shader", PROPERTY_HINT_RESOURCE_TYPE, "Shader"), "set_shader", "get_shader"); -} - -void ShaderMaterial::get_argument_options(const StringName &p_function, int p_idx, List *r_options, const String "e_style) const { - String f = p_function.operator String(); - if ((f == "get_shader_param" || f == "set_shader_param") && p_idx == 0) { - if (shader.is_valid()) { - List pl; - shader->get_param_list(&pl); - for (List::Element *E = pl.front(); E; E = E->next()) { - r_options->push_back(quote_style + E->get().name.replace_first("shader_param/", "") + quote_style); - } - } - } - Resource::get_argument_options(p_function, p_idx, r_options, quote_style); -} - -bool ShaderMaterial::_can_do_next_pass() const { - return shader.is_valid() && shader->get_mode() == Shader::MODE_SPATIAL; -} - -Shader::Mode ShaderMaterial::get_shader_mode() const { - if (shader.is_valid()) { - return shader->get_mode(); - } else { - return Shader::MODE_SPATIAL; - } -} - -ShaderMaterial::ShaderMaterial() { -} - -ShaderMaterial::~ShaderMaterial() { -} - -///////////////////////////////// - -Mutex SpatialMaterial::material_mutex; -SelfList::List *SpatialMaterial::dirty_materials = nullptr; -RBMap SpatialMaterial::shader_map; -SpatialMaterial::ShaderNames *SpatialMaterial::shader_names = nullptr; - -void SpatialMaterial::init_shaders() { - dirty_materials = memnew(SelfList::List); - - shader_names = memnew(ShaderNames); - - shader_names->albedo = "albedo"; - shader_names->specular = "specular"; - shader_names->roughness = "roughness"; - shader_names->metallic = "metallic"; - shader_names->emission = "emission"; - shader_names->emission_energy = "emission_energy"; - shader_names->normal_scale = "normal_scale"; - shader_names->rim = "rim"; - shader_names->rim_tint = "rim_tint"; - shader_names->clearcoat = "clearcoat"; - shader_names->clearcoat_gloss = "clearcoat_gloss"; - shader_names->anisotropy = "anisotropy_ratio"; - shader_names->depth_scale = "depth_scale"; - shader_names->subsurface_scattering_strength = "subsurface_scattering_strength"; - shader_names->transmission = "transmission"; - shader_names->refraction = "refraction"; - shader_names->point_size = "point_size"; - shader_names->uv1_scale = "uv1_scale"; - shader_names->uv1_offset = "uv1_offset"; - shader_names->uv2_scale = "uv2_scale"; - shader_names->uv2_offset = "uv2_offset"; - shader_names->uv1_blend_sharpness = "uv1_blend_sharpness"; - shader_names->uv2_blend_sharpness = "uv2_blend_sharpness"; - - shader_names->particles_anim_h_frames = "particles_anim_h_frames"; - shader_names->particles_anim_v_frames = "particles_anim_v_frames"; - shader_names->particles_anim_loop = "particles_anim_loop"; - shader_names->depth_min_layers = "depth_min_layers"; - shader_names->depth_max_layers = "depth_max_layers"; - shader_names->depth_flip = "depth_flip"; - - shader_names->grow = "grow"; - - shader_names->ao_light_affect = "ao_light_affect"; - - shader_names->proximity_fade_distance = "proximity_fade_distance"; - shader_names->distance_fade_min = "distance_fade_min"; - shader_names->distance_fade_max = "distance_fade_max"; - - shader_names->metallic_texture_channel = "metallic_texture_channel"; - shader_names->roughness_texture_channel = "roughness_texture_channel"; - shader_names->ao_texture_channel = "ao_texture_channel"; - shader_names->clearcoat_texture_channel = "clearcoat_texture_channel"; - shader_names->rim_texture_channel = "rim_texture_channel"; - shader_names->depth_texture_channel = "depth_texture_channel"; - shader_names->refraction_texture_channel = "refraction_texture_channel"; - shader_names->alpha_scissor_threshold = "alpha_scissor_threshold"; - - shader_names->texture_names[TEXTURE_ALBEDO] = "texture_albedo"; - shader_names->texture_names[TEXTURE_METALLIC] = "texture_metallic"; - shader_names->texture_names[TEXTURE_ROUGHNESS] = "texture_roughness"; - shader_names->texture_names[TEXTURE_EMISSION] = "texture_emission"; - shader_names->texture_names[TEXTURE_NORMAL] = "texture_normal"; - shader_names->texture_names[TEXTURE_RIM] = "texture_rim"; - shader_names->texture_names[TEXTURE_CLEARCOAT] = "texture_clearcoat"; - shader_names->texture_names[TEXTURE_FLOWMAP] = "texture_flowmap"; - shader_names->texture_names[TEXTURE_AMBIENT_OCCLUSION] = "texture_ambient_occlusion"; - shader_names->texture_names[TEXTURE_DEPTH] = "texture_depth"; - shader_names->texture_names[TEXTURE_SUBSURFACE_SCATTERING] = "texture_subsurface_scattering"; - shader_names->texture_names[TEXTURE_TRANSMISSION] = "texture_transmission"; - shader_names->texture_names[TEXTURE_REFRACTION] = "texture_refraction"; - shader_names->texture_names[TEXTURE_DETAIL_MASK] = "texture_detail_mask"; - shader_names->texture_names[TEXTURE_DETAIL_ALBEDO] = "texture_detail_albedo"; - shader_names->texture_names[TEXTURE_DETAIL_NORMAL] = "texture_detail_normal"; -} - -HashMap> SpatialMaterial::materials_for_2d; - -void SpatialMaterial::finish_shaders() { - materials_for_2d.clear(); - - memdelete(dirty_materials); - dirty_materials = nullptr; - - memdelete(shader_names); -} - -void SpatialMaterial::_update_shader() { - dirty_materials->remove(&element); - - MaterialKey mk = _compute_key(); - if (mk.key == current_key.key) { - return; //no update required in the end - } - - if (shader_map.has(current_key)) { - shader_map[current_key].users--; - if (shader_map[current_key].users == 0) { - //deallocate shader, as it's no longer in use - RS::get_singleton()->free(shader_map[current_key].shader); - shader_map.erase(current_key); - } - } - - current_key = mk; - - if (shader_map.has(mk)) { - RS::get_singleton()->material_set_shader(_get_material(), shader_map[mk].shader); - shader_map[mk].users++; - return; - } - - //must create a shader! - - // Add a comment to describe the shader origin (useful when converting to ShaderMaterial). - String code = "// NOTE: Shader automatically converted from " VERSION_NAME " " VERSION_FULL_CONFIG "'s SpatialMaterial.\n\n"; - - code += "shader_type spatial;\nrender_mode "; - switch (blend_mode) { - case BLEND_MODE_MIX: - code += "blend_mix"; - break; - case BLEND_MODE_ADD: - code += "blend_add"; - break; - case BLEND_MODE_SUB: - code += "blend_sub"; - break; - case BLEND_MODE_MUL: - code += "blend_mul"; - break; - } - - DepthDrawMode ddm = depth_draw_mode; - if (features[FEATURE_REFRACTION]) { - ddm = DEPTH_DRAW_ALWAYS; - } - - switch (ddm) { - case DEPTH_DRAW_OPAQUE_ONLY: - code += ",depth_draw_opaque"; - break; - case DEPTH_DRAW_ALWAYS: - code += ",depth_draw_always"; - break; - case DEPTH_DRAW_DISABLED: - code += ",depth_draw_never"; - break; - case DEPTH_DRAW_ALPHA_OPAQUE_PREPASS: - code += ",depth_draw_alpha_prepass"; - break; - } - - switch (cull_mode) { - case CULL_BACK: - code += ",cull_back"; - break; - case CULL_FRONT: - code += ",cull_front"; - break; - case CULL_DISABLED: - code += ",cull_disabled"; - break; - } - switch (diffuse_mode) { - case DIFFUSE_BURLEY: - code += ",diffuse_burley"; - break; - case DIFFUSE_LAMBERT: - code += ",diffuse_lambert"; - break; - case DIFFUSE_LAMBERT_WRAP: - code += ",diffuse_lambert_wrap"; - break; - case DIFFUSE_OREN_NAYAR: - code += ",diffuse_oren_nayar"; - break; - case DIFFUSE_TOON: - code += ",diffuse_toon"; - break; - } - switch (specular_mode) { - case SPECULAR_SCHLICK_GGX: - code += ",specular_schlick_ggx"; - break; - case SPECULAR_BLINN: - code += ",specular_blinn"; - break; - case SPECULAR_PHONG: - code += ",specular_phong"; - break; - case SPECULAR_TOON: - code += ",specular_toon"; - break; - case SPECULAR_DISABLED: - code += ",specular_disabled"; - break; - } - - if (flags[FLAG_UNSHADED]) { - code += ",unshaded"; - } - if (flags[FLAG_DISABLE_DEPTH_TEST]) { - code += ",depth_test_disable"; - } - if (flags[FLAG_USE_VERTEX_LIGHTING] || force_vertex_shading) { - code += ",vertex_lighting"; - } - if (flags[FLAG_TRIPLANAR_USE_WORLD] && (flags[FLAG_UV1_USE_TRIPLANAR] || flags[FLAG_UV2_USE_TRIPLANAR])) { - code += ",world_vertex_coords"; - } - if (flags[FLAG_DONT_RECEIVE_SHADOWS]) { - code += ",shadows_disabled"; - } - if (flags[FLAG_DISABLE_AMBIENT_LIGHT]) { - code += ",ambient_light_disabled"; - } - if (flags[FLAG_ENSURE_CORRECT_NORMALS]) { - code += ",ensure_correct_normals"; - } - if (flags[FLAG_USE_SHADOW_TO_OPACITY]) { - code += ",shadow_to_opacity"; - } - code += ";\n"; - - code += "uniform vec4 albedo : hint_color;\n"; - code += "uniform sampler2D texture_albedo : hint_albedo;\n"; - code += "uniform float specular;\n"; - code += "uniform float metallic;\n"; - if (grow_enabled) { - code += "uniform float grow;\n"; - } - - if (proximity_fade_enabled) { - code += "uniform float proximity_fade_distance;\n"; - } - if (distance_fade != DISTANCE_FADE_DISABLED) { - code += "uniform float distance_fade_min;\n"; - code += "uniform float distance_fade_max;\n"; - } - - if (flags[FLAG_USE_ALPHA_SCISSOR]) { - code += "uniform float alpha_scissor_threshold;\n"; - } - code += "uniform float roughness : hint_range(0,1);\n"; - code += "uniform float point_size : hint_range(0,128);\n"; - - if (textures[TEXTURE_METALLIC] != nullptr) { - code += "uniform sampler2D texture_metallic : hint_white;\n"; - code += "uniform vec4 metallic_texture_channel;\n"; - } - - if (textures[TEXTURE_ROUGHNESS] != nullptr) { - code += "uniform sampler2D texture_roughness : hint_white;\n"; - code += "uniform vec4 roughness_texture_channel;\n"; - } - if (billboard_mode == BILLBOARD_PARTICLES) { - code += "uniform int particles_anim_h_frames;\n"; - code += "uniform int particles_anim_v_frames;\n"; - code += "uniform bool particles_anim_loop;\n"; - } - - if (features[FEATURE_EMISSION]) { - code += "uniform sampler2D texture_emission : hint_black_albedo;\n"; - code += "uniform vec4 emission : hint_color;\n"; - code += "uniform float emission_energy;\n"; - } - - if (features[FEATURE_REFRACTION]) { - code += "uniform sampler2D texture_refraction;\n"; - code += "uniform float refraction : hint_range(-16,16);\n"; - code += "uniform vec4 refraction_texture_channel;\n"; - } - - if (features[FEATURE_NORMAL_MAPPING]) { - code += "uniform sampler2D texture_normal : hint_normal;\n"; - code += "uniform float normal_scale : hint_range(-16,16);\n"; - } - if (features[FEATURE_RIM]) { - code += "uniform float rim : hint_range(0,1);\n"; - code += "uniform float rim_tint : hint_range(0,1);\n"; - code += "uniform sampler2D texture_rim : hint_white;\n"; - } - if (features[FEATURE_CLEARCOAT]) { - code += "uniform float clearcoat : hint_range(0,1);\n"; - code += "uniform float clearcoat_gloss : hint_range(0,1);\n"; - code += "uniform sampler2D texture_clearcoat : hint_white;\n"; - } - if (features[FEATURE_ANISOTROPY]) { - code += "uniform float anisotropy_ratio : hint_range(0,256);\n"; - code += "uniform sampler2D texture_flowmap : hint_aniso;\n"; - } - if (features[FEATURE_AMBIENT_OCCLUSION]) { - code += "uniform sampler2D texture_ambient_occlusion : hint_white;\n"; - code += "uniform vec4 ao_texture_channel;\n"; - code += "uniform float ao_light_affect;\n"; - } - - if (features[FEATURE_DETAIL]) { - code += "uniform sampler2D texture_detail_albedo : hint_albedo;\n"; - code += "uniform sampler2D texture_detail_normal : hint_normal;\n"; - code += "uniform sampler2D texture_detail_mask : hint_white;\n"; - } - - if (features[FEATURE_SUBSURACE_SCATTERING]) { - code += "uniform float subsurface_scattering_strength : hint_range(0,1);\n"; - code += "uniform sampler2D texture_subsurface_scattering : hint_white;\n"; - } - - if (features[FEATURE_TRANSMISSION]) { - code += "uniform vec4 transmission : hint_color;\n"; - code += "uniform sampler2D texture_transmission : hint_black;\n"; - } - - if (features[FEATURE_DEPTH_MAPPING]) { - code += "uniform sampler2D texture_depth : hint_black;\n"; - code += "uniform float depth_scale;\n"; - code += "uniform int depth_min_layers;\n"; - code += "uniform int depth_max_layers;\n"; - code += "uniform vec2 depth_flip;\n"; - } - if (flags[FLAG_UV1_USE_TRIPLANAR]) { - code += "varying vec3 uv1_triplanar_pos;\n"; - } - if (flags[FLAG_UV2_USE_TRIPLANAR]) { - code += "varying vec3 uv2_triplanar_pos;\n"; - } - if (flags[FLAG_UV1_USE_TRIPLANAR]) { - code += "uniform float uv1_blend_sharpness;\n"; - code += "varying vec3 uv1_power_normal;\n"; - } - - if (flags[FLAG_UV2_USE_TRIPLANAR]) { - code += "uniform float uv2_blend_sharpness;\n"; - code += "varying vec3 uv2_power_normal;\n"; - } - - code += "uniform vec3 uv1_scale;\n"; - code += "uniform vec3 uv1_offset;\n"; - code += "uniform vec3 uv2_scale;\n"; - code += "uniform vec3 uv2_offset;\n"; - - code += "\n\n"; - - code += "void vertex() {\n"; - - if (flags[FLAG_SRGB_VERTEX_COLOR]) { - code += "\tif (!OUTPUT_IS_SRGB) {\n"; - code += "\t\tCOLOR.rgb = mix(pow((COLOR.rgb + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)), COLOR.rgb * (1.0 / 12.92), lessThan(COLOR.rgb, vec3(0.04045)));\n"; - code += "\t}\n"; - } - if (flags[FLAG_USE_POINT_SIZE]) { - code += "\tPOINT_SIZE=point_size;\n"; - } - - if (flags[FLAG_USE_VERTEX_LIGHTING] || force_vertex_shading) { - code += "\tROUGHNESS=roughness;\n"; - } - - if (!flags[FLAG_UV1_USE_TRIPLANAR]) { - code += "\tUV=UV*uv1_scale.xy+uv1_offset.xy;\n"; - } - - switch (billboard_mode) { - case BILLBOARD_DISABLED: { - } break; - case BILLBOARD_ENABLED: { - code += "\tMODELVIEW_MATRIX = INV_CAMERA_MATRIX * mat4(CAMERA_MATRIX[0],CAMERA_MATRIX[1],CAMERA_MATRIX[2],WORLD_MATRIX[3]);\n"; - - if (flags[FLAG_BILLBOARD_KEEP_SCALE]) { - code += "\tMODELVIEW_MATRIX = MODELVIEW_MATRIX * mat4(vec4(length(WORLD_MATRIX[0].xyz), 0.0, 0.0, 0.0),vec4(0.0, length(WORLD_MATRIX[1].xyz), 0.0, 0.0),vec4(0.0, 0.0, length(WORLD_MATRIX[2].xyz), 0.0),vec4(0.0, 0.0, 0.0, 1.0));\n"; - } - } break; - case BILLBOARD_FIXED_Y: { - code += "\tMODELVIEW_MATRIX = INV_CAMERA_MATRIX * mat4(vec4(normalize(cross(vec3(0.0, 1.0, 0.0), CAMERA_MATRIX[2].xyz)),0.0),vec4(0.0, 1.0, 0.0, 0.0),vec4(normalize(cross(CAMERA_MATRIX[0].xyz, vec3(0.0, 1.0, 0.0))),0.0),WORLD_MATRIX[3]);\n"; - - if (flags[FLAG_BILLBOARD_KEEP_SCALE]) { - code += "\tMODELVIEW_MATRIX = MODELVIEW_MATRIX * mat4(vec4(length(WORLD_MATRIX[0].xyz), 0.0, 0.0, 0.0),vec4(0.0, length(WORLD_MATRIX[1].xyz), 0.0, 0.0),vec4(0.0, 0.0, length(WORLD_MATRIX[2].xyz), 0.0),vec4(0.0, 0.0, 0.0, 1.0));\n"; - } - } break; - case BILLBOARD_PARTICLES: { - //make billboard - code += "\tmat4 mat_world = mat4(normalize(CAMERA_MATRIX[0])*length(WORLD_MATRIX[0]),normalize(CAMERA_MATRIX[1])*length(WORLD_MATRIX[0]),normalize(CAMERA_MATRIX[2])*length(WORLD_MATRIX[2]),WORLD_MATRIX[3]);\n"; - //rotate by rotation - code += "\tmat_world = mat_world * mat4( vec4(cos(INSTANCE_CUSTOM.x),-sin(INSTANCE_CUSTOM.x), 0.0, 0.0), vec4(sin(INSTANCE_CUSTOM.x), cos(INSTANCE_CUSTOM.x), 0.0, 0.0),vec4(0.0, 0.0, 1.0, 0.0),vec4(0.0, 0.0, 0.0, 1.0));\n"; - //set modelview - code += "\tMODELVIEW_MATRIX = INV_CAMERA_MATRIX * mat_world;\n"; - - //handle animation - code += "\tfloat h_frames = float(particles_anim_h_frames);\n"; - code += "\tfloat v_frames = float(particles_anim_v_frames);\n"; - code += "\tfloat particle_total_frames = float(particles_anim_h_frames * particles_anim_v_frames);\n"; - code += "\tfloat particle_frame = floor(INSTANCE_CUSTOM.z * float(particle_total_frames));\n"; - code += "\tif (!particles_anim_loop) {\n"; - code += "\t\tparticle_frame = clamp(particle_frame, 0.0, particle_total_frames - 1.0);\n"; - code += "\t} else {\n"; - code += "\t\tparticle_frame = mod(particle_frame, particle_total_frames);\n"; - code += "\t}"; - code += "\tUV /= vec2(h_frames, v_frames);\n"; - code += "\tUV += vec2(mod(particle_frame, h_frames) / h_frames, floor((particle_frame + 0.5) / h_frames) / v_frames);\n"; - } break; - } - - if (flags[FLAG_FIXED_SIZE]) { - code += "\tif (PROJECTION_MATRIX[3][3] != 0.0) {\n"; - //orthogonal matrix, try to do about the same - //with viewport size - code += "\t\tfloat h = abs(1.0 / (2.0 * PROJECTION_MATRIX[1][1]));\n"; - code += "\t\tfloat sc = (h * 2.0); //consistent with Y-fov\n"; - code += "\t\tMODELVIEW_MATRIX[0]*=sc;\n"; - code += "\t\tMODELVIEW_MATRIX[1]*=sc;\n"; - code += "\t\tMODELVIEW_MATRIX[2]*=sc;\n"; - code += "\t} else {\n"; - //just scale by depth - code += "\t\tfloat sc = -(MODELVIEW_MATRIX)[3].z;\n"; - code += "\t\tMODELVIEW_MATRIX[0]*=sc;\n"; - code += "\t\tMODELVIEW_MATRIX[1]*=sc;\n"; - code += "\t\tMODELVIEW_MATRIX[2]*=sc;\n"; - code += "\t}\n"; - } - - if (detail_uv == DETAIL_UV_2 && !flags[FLAG_UV2_USE_TRIPLANAR]) { - code += "\tUV2=UV2*uv2_scale.xy+uv2_offset.xy;\n"; - } - if (flags[FLAG_UV1_USE_TRIPLANAR] || flags[FLAG_UV2_USE_TRIPLANAR]) { - //generate tangent and binormal in world space - code += "\tTANGENT = vec3(0.0,0.0,-1.0) * abs(NORMAL.x);\n"; - code += "\tTANGENT+= vec3(1.0,0.0,0.0) * abs(NORMAL.y);\n"; - code += "\tTANGENT+= vec3(1.0,0.0,0.0) * abs(NORMAL.z);\n"; - code += "\tTANGENT = normalize(TANGENT);\n"; - - code += "\tBINORMAL = vec3(0.0,1.0,0.0) * abs(NORMAL.x);\n"; - code += "\tBINORMAL+= vec3(0.0,0.0,-1.0) * abs(NORMAL.y);\n"; - code += "\tBINORMAL+= vec3(0.0,1.0,0.0) * abs(NORMAL.z);\n"; - code += "\tBINORMAL = normalize(BINORMAL);\n"; - } - - if (flags[FLAG_UV1_USE_TRIPLANAR]) { - code += "\tuv1_power_normal=pow(abs(NORMAL),vec3(uv1_blend_sharpness));\n"; - code += "\tuv1_power_normal/=dot(uv1_power_normal,vec3(1.0));\n"; - code += "\tuv1_triplanar_pos = VERTEX * uv1_scale + uv1_offset;\n"; - code += "\tuv1_triplanar_pos *= vec3(1.0,-1.0, 1.0);\n"; - } - - if (flags[FLAG_UV2_USE_TRIPLANAR]) { - code += "\tuv2_power_normal=pow(abs(NORMAL), vec3(uv2_blend_sharpness));\n"; - code += "\tuv2_power_normal/=dot(uv2_power_normal,vec3(1.0));\n"; - code += "\tuv2_triplanar_pos = VERTEX * uv2_scale + uv2_offset;\n"; - code += "\tuv2_triplanar_pos *= vec3(1.0,-1.0, 1.0);\n"; - } - - if (grow_enabled) { - code += "\tVERTEX+=NORMAL*grow;\n"; - } - - code += "}\n"; - code += "\n\n"; - if (flags[FLAG_UV1_USE_TRIPLANAR] || flags[FLAG_UV2_USE_TRIPLANAR]) { - code += "vec4 triplanar_texture(sampler2D p_sampler,vec3 p_weights,vec3 p_triplanar_pos) {\n"; - code += "\tvec4 samp=vec4(0.0);\n"; - code += "\tsamp+= texture(p_sampler,p_triplanar_pos.xy) * p_weights.z;\n"; - code += "\tsamp+= texture(p_sampler,p_triplanar_pos.xz) * p_weights.y;\n"; - code += "\tsamp+= texture(p_sampler,p_triplanar_pos.zy * vec2(-1.0,1.0)) * p_weights.x;\n"; - code += "\treturn samp;\n"; - code += "}\n"; - } - code += "\n\n"; - code += "void fragment() {\n"; - - if (!flags[FLAG_UV1_USE_TRIPLANAR]) { - code += "\tvec2 base_uv = UV;\n"; - } - - if ((features[FEATURE_DETAIL] && detail_uv == DETAIL_UV_2) || (features[FEATURE_AMBIENT_OCCLUSION] && flags[FLAG_AO_ON_UV2]) || (features[FEATURE_EMISSION] && flags[FLAG_EMISSION_ON_UV2])) { - code += "\tvec2 base_uv2 = UV2;\n"; - } - - if (features[FEATURE_DEPTH_MAPPING] && flags[FLAG_UV1_USE_TRIPLANAR]) { - // Display both resource name and albedo texture name. - // Materials are often built-in to scenes, so displaying the resource name alone may not be meaningful. - // On the other hand, albedo textures are almost always external to the scene. - if (textures[TEXTURE_ALBEDO].is_valid()) { - WARN_PRINT(vformat("%s (albedo %s): Depth mapping is not supported on triplanar materials. Ignoring depth mapping in favor of triplanar mapping.", get_path(), textures[TEXTURE_ALBEDO]->get_path())); - } else if (!get_path().empty()) { - WARN_PRINT(vformat("%s: Depth mapping is not supported on triplanar materials. Ignoring depth mapping in favor of triplanar mapping.", get_path())); - } else { - // Resource wasn't saved yet. - WARN_PRINT("Depth mapping is not supported on triplanar materials. Ignoring depth mapping in favor of triplanar mapping."); - } - } - - if (!RenderingServer::get_singleton()->is_low_end() && features[FEATURE_DEPTH_MAPPING] && !flags[FLAG_UV1_USE_TRIPLANAR]) { //depthmap not supported with triplanar - code += "\t{\n"; - code += "\t\tvec3 view_dir = normalize(normalize(-VERTEX)*mat3(TANGENT*depth_flip.x,-BINORMAL*depth_flip.y,NORMAL));\n"; // binormal is negative due to mikktspace, flip 'unflips' it ;-) - - if (deep_parallax) { - code += "\t\tfloat num_layers = mix(float(depth_max_layers),float(depth_min_layers), abs(dot(vec3(0.0, 0.0, 1.0), view_dir)));\n"; - code += "\t\tfloat layer_depth = 1.0 / num_layers;\n"; - code += "\t\tfloat current_layer_depth = 0.0;\n"; - code += "\t\tvec2 P = view_dir.xy * depth_scale;\n"; - code += "\t\tvec2 delta = P / num_layers;\n"; - code += "\t\tvec2 ofs = base_uv;\n"; - code += "\t\tfloat depth = textureLod(texture_depth, ofs, 0.0).r;\n"; - code += "\t\tfloat current_depth = 0.0;\n"; - code += "\t\twhile(current_depth < depth) {\n"; - code += "\t\t\tofs -= delta;\n"; - code += "\t\t\tdepth = textureLod(texture_depth, ofs, 0.0).r;\n"; - code += "\t\t\tcurrent_depth += layer_depth;\n"; - code += "\t\t}\n"; - code += "\t\tvec2 prev_ofs = ofs + delta;\n"; - code += "\t\tfloat after_depth = depth - current_depth;\n"; - code += "\t\tfloat before_depth = textureLod(texture_depth, prev_ofs, 0.0).r - current_depth + layer_depth;\n"; - code += "\t\tfloat weight = after_depth / (after_depth - before_depth);\n"; - code += "\t\tofs = mix(ofs,prev_ofs,weight);\n"; - - } else { - code += "\t\tfloat depth = texture(texture_depth, base_uv).r;\n"; - // Use offset limiting to improve the appearance of non-deep parallax. - // This reduces the impression of depth, but avoids visible warping in the distance. - code += "\t\tvec2 ofs = base_uv - view_dir.xy * depth * depth_scale;\n"; - } - - code += "\t\tbase_uv=ofs;\n"; - if (features[FEATURE_DETAIL] && detail_uv == DETAIL_UV_2) { - code += "\t\tbase_uv2-=ofs;\n"; - } - - code += "\t}\n"; - } - - if (flags[FLAG_USE_POINT_SIZE]) { - code += "\tvec4 albedo_tex = texture(texture_albedo,POINT_COORD);\n"; - } else { - if (flags[FLAG_UV1_USE_TRIPLANAR]) { - code += "\tvec4 albedo_tex = triplanar_texture(texture_albedo,uv1_power_normal,uv1_triplanar_pos);\n"; - } else { - code += "\tvec4 albedo_tex = texture(texture_albedo,base_uv);\n"; - } - } - - if (flags[FLAG_ALBEDO_TEXTURE_SDF]) { - code += "\tconst float smoothing = 0.125;\n"; - code += "\tfloat dist = albedo_tex.a;\n"; - code += "\talbedo_tex.a = smoothstep(0.5 - smoothing, 0.5 + smoothing, dist);\n"; - code += "\talbedo_tex.rgb = vec3(1.0);\n"; - } else if (flags[FLAG_ALBEDO_TEXTURE_FORCE_SRGB]) { - code += "\talbedo_tex.rgb = mix(pow((albedo_tex.rgb + vec3(0.055)) * (1.0 / (1.0 + 0.055)),vec3(2.4)),albedo_tex.rgb.rgb * (1.0 / 12.92),lessThan(albedo_tex.rgb,vec3(0.04045)));\n"; - } - - if (flags[FLAG_ALBEDO_FROM_VERTEX_COLOR]) { - code += "\talbedo_tex *= COLOR;\n"; - } - code += "\tALBEDO = albedo.rgb * albedo_tex.rgb;\n"; - - if (textures[TEXTURE_METALLIC] != nullptr) { - if (flags[FLAG_UV1_USE_TRIPLANAR]) { - code += "\tfloat metallic_tex = dot(triplanar_texture(texture_metallic,uv1_power_normal,uv1_triplanar_pos),metallic_texture_channel);\n"; - } else { - code += "\tfloat metallic_tex = dot(texture(texture_metallic,base_uv),metallic_texture_channel);\n"; - } - code += "\tMETALLIC = metallic_tex * metallic;\n"; - } else { - code += "\tMETALLIC = metallic;\n"; - } - - if (textures[TEXTURE_ROUGHNESS] != nullptr) { - if (flags[FLAG_UV1_USE_TRIPLANAR]) { - code += "\tfloat roughness_tex = dot(triplanar_texture(texture_roughness,uv1_power_normal,uv1_triplanar_pos),roughness_texture_channel);\n"; - } else { - code += "\tfloat roughness_tex = dot(texture(texture_roughness,base_uv),roughness_texture_channel);\n"; - } - code += "\tROUGHNESS = roughness_tex * roughness;\n"; - } else { - code += "\tROUGHNESS = roughness;\n"; - } - - code += "\tSPECULAR = specular;\n"; - - if (features[FEATURE_NORMAL_MAPPING]) { - if (flags[FLAG_UV1_USE_TRIPLANAR]) { - code += "\tNORMALMAP = triplanar_texture(texture_normal,uv1_power_normal,uv1_triplanar_pos).rgb;\n"; - } else { - code += "\tNORMALMAP = texture(texture_normal,base_uv).rgb;\n"; - } - code += "\tNORMALMAP_DEPTH = normal_scale;\n"; - } - - if (features[FEATURE_EMISSION]) { - if (flags[FLAG_EMISSION_ON_UV2]) { - if (flags[FLAG_UV2_USE_TRIPLANAR]) { - code += "\tvec3 emission_tex = triplanar_texture(texture_emission,uv2_power_normal,uv2_triplanar_pos).rgb;\n"; - } else { - code += "\tvec3 emission_tex = texture(texture_emission,base_uv2).rgb;\n"; - } - } else { - if (flags[FLAG_UV1_USE_TRIPLANAR]) { - code += "\tvec3 emission_tex = triplanar_texture(texture_emission,uv1_power_normal,uv1_triplanar_pos).rgb;\n"; - } else { - code += "\tvec3 emission_tex = texture(texture_emission,base_uv).rgb;\n"; - } - } - - if (emission_op == EMISSION_OP_ADD) { - code += "\tEMISSION = (emission.rgb+emission_tex)*emission_energy;\n"; - } else { - code += "\tEMISSION = (emission.rgb*emission_tex)*emission_energy;\n"; - } - } - - if (features[FEATURE_REFRACTION]) { - if (features[FEATURE_NORMAL_MAPPING]) { - code += "\tvec3 unpacked_normal = NORMALMAP;\n"; - code += "\tunpacked_normal.xy = unpacked_normal.xy * 2.0 - 1.0;\n"; - code += "\tunpacked_normal.z = sqrt(max(0.0, 1.0 - dot(unpacked_normal.xy, unpacked_normal.xy)));\n"; - code += "\tvec3 ref_normal = normalize( mix(NORMAL,TANGENT * unpacked_normal.x + BINORMAL * unpacked_normal.y + NORMAL * unpacked_normal.z,NORMALMAP_DEPTH) );\n"; - } else { - code += "\tvec3 ref_normal = NORMAL;\n"; - } - if (flags[FLAG_UV1_USE_TRIPLANAR]) { - code += "\tvec2 ref_ofs = SCREEN_UV - ref_normal.xy * dot(triplanar_texture(texture_refraction,uv1_power_normal,uv1_triplanar_pos),refraction_texture_channel) * refraction;\n"; - } else { - code += "\tvec2 ref_ofs = SCREEN_UV - ref_normal.xy * dot(texture(texture_refraction,base_uv),refraction_texture_channel) * refraction;\n"; - } - code += "\tfloat ref_amount = 1.0 - albedo.a * albedo_tex.a;\n"; - code += "\tEMISSION += textureLod(SCREEN_TEXTURE,ref_ofs,ROUGHNESS * 8.0).rgb * ref_amount;\n"; - code += "\tALBEDO *= 1.0 - ref_amount;\n"; - code += "\tALPHA = 1.0;\n"; - - } else if (features[FEATURE_TRANSPARENT] || flags[FLAG_USE_ALPHA_SCISSOR] || flags[FLAG_USE_SHADOW_TO_OPACITY] || (distance_fade == DISTANCE_FADE_PIXEL_ALPHA) || proximity_fade_enabled) { - code += "\tALPHA = albedo.a * albedo_tex.a;\n"; - } - - if (proximity_fade_enabled) { - code += "\tfloat depth_tex = textureLod(DEPTH_TEXTURE,SCREEN_UV,0.0).r;\n"; - code += "\tvec4 world_pos = INV_PROJECTION_MATRIX * vec4(SCREEN_UV*2.0-1.0,depth_tex*2.0-1.0,1.0);\n"; - code += "\tworld_pos.xyz/=world_pos.w;\n"; - code += "\tALPHA*=clamp(1.0-smoothstep(world_pos.z+proximity_fade_distance,world_pos.z,VERTEX.z),0.0,1.0);\n"; - } - - if (distance_fade != DISTANCE_FADE_DISABLED) { - if ((distance_fade == DISTANCE_FADE_OBJECT_DITHER || distance_fade == DISTANCE_FADE_PIXEL_DITHER)) { - if (!RenderingServer::get_singleton()->is_low_end()) { - code += "\t{\n"; - - if (distance_fade == DISTANCE_FADE_OBJECT_DITHER) { - code += "\t\tfloat fade_distance = abs((INV_CAMERA_MATRIX * WORLD_MATRIX[3]).z);\n"; - - } else { - code += "\t\tfloat fade_distance = -VERTEX.z;\n"; - } - // Use interleaved gradient noise, which is fast but still looks good. - code += "\t\tconst vec3 magic = vec3(0.06711056f, 0.00583715f, 52.9829189f);"; - code += "\t\tfloat fade = clamp(smoothstep(distance_fade_min, distance_fade_max, fade_distance), 0.0, 1.0);\n"; - // Use a hard cap to prevent a few stray pixels from remaining when past the fade-out distance. - code += "\t\tif (fade < 0.001 || fade < fract(magic.z * fract(dot(FRAGCOORD.xy, magic.xy)))) {\n"; - code += "\t\t\tdiscard;\n"; - code += "\t\t}\n"; - - code += "\t}\n\n"; - } - - } else { - code += "\tALPHA*=clamp(smoothstep(distance_fade_min,distance_fade_max,-VERTEX.z),0.0,1.0);\n"; - } - } - - if (features[FEATURE_RIM]) { - if (flags[FLAG_UV1_USE_TRIPLANAR]) { - code += "\tvec2 rim_tex = triplanar_texture(texture_rim,uv1_power_normal,uv1_triplanar_pos).xy;\n"; - } else { - code += "\tvec2 rim_tex = texture(texture_rim,base_uv).xy;\n"; - } - code += "\tRIM = rim*rim_tex.x;"; - code += "\tRIM_TINT = rim_tint*rim_tex.y;\n"; - } - - if (features[FEATURE_CLEARCOAT]) { - if (flags[FLAG_UV1_USE_TRIPLANAR]) { - code += "\tvec2 clearcoat_tex = triplanar_texture(texture_clearcoat,uv1_power_normal,uv1_triplanar_pos).xy;\n"; - } else { - code += "\tvec2 clearcoat_tex = texture(texture_clearcoat,base_uv).xy;\n"; - } - code += "\tCLEARCOAT = clearcoat*clearcoat_tex.x;"; - code += "\tCLEARCOAT_GLOSS = clearcoat_gloss*clearcoat_tex.y;\n"; - } - - if (features[FEATURE_ANISOTROPY]) { - if (flags[FLAG_UV1_USE_TRIPLANAR]) { - code += "\tvec3 anisotropy_tex = triplanar_texture(texture_flowmap,uv1_power_normal,uv1_triplanar_pos).rga;\n"; - } else { - code += "\tvec3 anisotropy_tex = texture(texture_flowmap,base_uv).rga;\n"; - } - code += "\tANISOTROPY = anisotropy_ratio*anisotropy_tex.b;\n"; - code += "\tANISOTROPY_FLOW = anisotropy_tex.rg*2.0-1.0;\n"; - } - - if (features[FEATURE_AMBIENT_OCCLUSION]) { - if (flags[FLAG_AO_ON_UV2]) { - if (flags[FLAG_UV2_USE_TRIPLANAR]) { - code += "\tAO = dot(triplanar_texture(texture_ambient_occlusion,uv2_power_normal,uv2_triplanar_pos),ao_texture_channel);\n"; - } else { - code += "\tAO = dot(texture(texture_ambient_occlusion,base_uv2),ao_texture_channel);\n"; - } - } else { - if (flags[FLAG_UV1_USE_TRIPLANAR]) { - code += "\tAO = dot(triplanar_texture(texture_ambient_occlusion,uv1_power_normal,uv1_triplanar_pos),ao_texture_channel);\n"; - } else { - code += "\tAO = dot(texture(texture_ambient_occlusion,base_uv),ao_texture_channel);\n"; - } - } - - code += "\tAO_LIGHT_AFFECT = ao_light_affect;\n"; - } - - if (features[FEATURE_SUBSURACE_SCATTERING]) { - if (flags[FLAG_UV1_USE_TRIPLANAR]) { - code += "\tfloat sss_tex = triplanar_texture(texture_subsurface_scattering,uv1_power_normal,uv1_triplanar_pos).r;\n"; - } else { - code += "\tfloat sss_tex = texture(texture_subsurface_scattering,base_uv).r;\n"; - } - code += "\tSSS_STRENGTH=subsurface_scattering_strength*sss_tex;\n"; - } - - if (features[FEATURE_TRANSMISSION]) { - if (flags[FLAG_UV1_USE_TRIPLANAR]) { - code += "\tvec3 transmission_tex = triplanar_texture(texture_transmission,uv1_power_normal,uv1_triplanar_pos).rgb;\n"; - } else { - code += "\tvec3 transmission_tex = texture(texture_transmission,base_uv).rgb;\n"; - } - code += "\tTRANSMISSION = (transmission.rgb+transmission_tex);\n"; - } - - if (features[FEATURE_DETAIL]) { - bool triplanar = (flags[FLAG_UV1_USE_TRIPLANAR] && detail_uv == DETAIL_UV_1) || (flags[FLAG_UV2_USE_TRIPLANAR] && detail_uv == DETAIL_UV_2); - - if (triplanar) { - String tp_uv = detail_uv == DETAIL_UV_1 ? "uv1" : "uv2"; - code += "\tvec4 detail_tex = triplanar_texture(texture_detail_albedo," + tp_uv + "_power_normal," + tp_uv + "_triplanar_pos);\n"; - code += "\tvec4 detail_norm_tex = triplanar_texture(texture_detail_normal," + tp_uv + "_power_normal," + tp_uv + "_triplanar_pos);\n"; - - } else { - String det_uv = detail_uv == DETAIL_UV_1 ? "base_uv" : "base_uv2"; - code += "\tvec4 detail_tex = texture(texture_detail_albedo," + det_uv + ");\n"; - code += "\tvec4 detail_norm_tex = texture(texture_detail_normal," + det_uv + ");\n"; - } - - if (flags[FLAG_UV1_USE_TRIPLANAR]) { - code += "\tvec4 detail_mask_tex = triplanar_texture(texture_detail_mask,uv1_power_normal,uv1_triplanar_pos);\n"; - } else { - code += "\tvec4 detail_mask_tex = texture(texture_detail_mask,base_uv);\n"; - } - - switch (detail_blend_mode) { - case BLEND_MODE_MIX: { - code += "\tvec3 detail = mix(ALBEDO.rgb,detail_tex.rgb,detail_tex.a);\n"; - } break; - case BLEND_MODE_ADD: { - code += "\tvec3 detail = mix(ALBEDO.rgb,ALBEDO.rgb+detail_tex.rgb,detail_tex.a);\n"; - } break; - case BLEND_MODE_SUB: { - code += "\tvec3 detail = mix(ALBEDO.rgb,ALBEDO.rgb-detail_tex.rgb,detail_tex.a);\n"; - } break; - case BLEND_MODE_MUL: { - code += "\tvec3 detail = mix(ALBEDO.rgb,ALBEDO.rgb*detail_tex.rgb,detail_tex.a);\n"; - } break; - } - - code += "\tvec3 detail_norm = mix(NORMALMAP,detail_norm_tex.rgb,detail_tex.a);\n"; - code += "\tNORMALMAP = mix(NORMALMAP,detail_norm,detail_mask_tex.r);\n"; - code += "\tALBEDO.rgb = mix(ALBEDO.rgb,detail,detail_mask_tex.r);\n"; - } - - if (flags[FLAG_USE_ALPHA_SCISSOR]) { - code += "\tALPHA_SCISSOR=alpha_scissor_threshold;\n"; - } - - code += "}\n"; - - String fallback_mode_str; - switch (async_mode) { - case ASYNC_MODE_VISIBLE: { - fallback_mode_str = "async_visible"; - } break; - case ASYNC_MODE_HIDDEN: { - fallback_mode_str = "async_hidden"; - } break; - } - code = code.replace_first("render_mode ", "render_mode " + fallback_mode_str + ","); - - ShaderData shader_data; - shader_data.shader = RS::get_singleton()->shader_create(); - shader_data.users = 1; - - RS::get_singleton()->shader_set_code(shader_data.shader, code); - - shader_map[mk] = shader_data; - - RS::get_singleton()->material_set_shader(_get_material(), shader_data.shader); -} - -void SpatialMaterial::flush_changes() { - material_mutex.lock(); - - while (dirty_materials->first()) { - dirty_materials->first()->self()->_update_shader(); - } - - material_mutex.unlock(); -} - -void SpatialMaterial::_queue_shader_change() { - material_mutex.lock(); - - if (is_initialized && !element.in_list()) { - dirty_materials->add(&element); - } - - material_mutex.unlock(); -} - -bool SpatialMaterial::_is_shader_dirty() const { - bool dirty = false; - - material_mutex.lock(); - - dirty = element.in_list(); - - material_mutex.unlock(); - - return dirty; -} -void SpatialMaterial::set_albedo(const Color &p_albedo) { - albedo = p_albedo; - - RS::get_singleton()->material_set_param(_get_material(), shader_names->albedo, p_albedo); -} - -Color SpatialMaterial::get_albedo() const { - return albedo; -} - -void SpatialMaterial::set_specular(float p_specular) { - specular = p_specular; - RS::get_singleton()->material_set_param(_get_material(), shader_names->specular, p_specular); -} - -float SpatialMaterial::get_specular() const { - return specular; -} - -void SpatialMaterial::set_roughness(float p_roughness) { - roughness = p_roughness; - RS::get_singleton()->material_set_param(_get_material(), shader_names->roughness, p_roughness); -} - -float SpatialMaterial::get_roughness() const { - return roughness; -} - -void SpatialMaterial::set_metallic(float p_metallic) { - metallic = p_metallic; - RS::get_singleton()->material_set_param(_get_material(), shader_names->metallic, p_metallic); -} - -float SpatialMaterial::get_metallic() const { - return metallic; -} - -void SpatialMaterial::set_emission(const Color &p_emission) { - emission = p_emission; - RS::get_singleton()->material_set_param(_get_material(), shader_names->emission, p_emission); -} -Color SpatialMaterial::get_emission() const { - return emission; -} - -void SpatialMaterial::set_emission_energy(float p_emission_energy) { - emission_energy = p_emission_energy; - RS::get_singleton()->material_set_param(_get_material(), shader_names->emission_energy, p_emission_energy); -} -float SpatialMaterial::get_emission_energy() const { - return emission_energy; -} - -void SpatialMaterial::set_normal_scale(float p_normal_scale) { - normal_scale = p_normal_scale; - RS::get_singleton()->material_set_param(_get_material(), shader_names->normal_scale, p_normal_scale); -} -float SpatialMaterial::get_normal_scale() const { - return normal_scale; -} - -void SpatialMaterial::set_rim(float p_rim) { - rim = p_rim; - RS::get_singleton()->material_set_param(_get_material(), shader_names->rim, p_rim); -} -float SpatialMaterial::get_rim() const { - return rim; -} - -void SpatialMaterial::set_rim_tint(float p_rim_tint) { - rim_tint = p_rim_tint; - RS::get_singleton()->material_set_param(_get_material(), shader_names->rim_tint, p_rim_tint); -} -float SpatialMaterial::get_rim_tint() const { - return rim_tint; -} - -void SpatialMaterial::set_ao_light_affect(float p_ao_light_affect) { - ao_light_affect = p_ao_light_affect; - RS::get_singleton()->material_set_param(_get_material(), shader_names->ao_light_affect, p_ao_light_affect); -} -float SpatialMaterial::get_ao_light_affect() const { - return ao_light_affect; -} - -void SpatialMaterial::set_clearcoat(float p_clearcoat) { - clearcoat = p_clearcoat; - RS::get_singleton()->material_set_param(_get_material(), shader_names->clearcoat, p_clearcoat); -} - -float SpatialMaterial::get_clearcoat() const { - return clearcoat; -} - -void SpatialMaterial::set_clearcoat_gloss(float p_clearcoat_gloss) { - clearcoat_gloss = p_clearcoat_gloss; - RS::get_singleton()->material_set_param(_get_material(), shader_names->clearcoat_gloss, p_clearcoat_gloss); -} - -float SpatialMaterial::get_clearcoat_gloss() const { - return clearcoat_gloss; -} - -void SpatialMaterial::set_anisotropy(float p_anisotropy) { - anisotropy = p_anisotropy; - RS::get_singleton()->material_set_param(_get_material(), shader_names->anisotropy, p_anisotropy); -} -float SpatialMaterial::get_anisotropy() const { - return anisotropy; -} - -void SpatialMaterial::set_depth_scale(float p_depth_scale) { - depth_scale = p_depth_scale; - RS::get_singleton()->material_set_param(_get_material(), shader_names->depth_scale, p_depth_scale); -} - -float SpatialMaterial::get_depth_scale() const { - return depth_scale; -} - -void SpatialMaterial::set_subsurface_scattering_strength(float p_subsurface_scattering_strength) { - subsurface_scattering_strength = p_subsurface_scattering_strength; - RS::get_singleton()->material_set_param(_get_material(), shader_names->subsurface_scattering_strength, subsurface_scattering_strength); -} - -float SpatialMaterial::get_subsurface_scattering_strength() const { - return subsurface_scattering_strength; -} - -void SpatialMaterial::set_transmission(const Color &p_transmission) { - transmission = p_transmission; - RS::get_singleton()->material_set_param(_get_material(), shader_names->transmission, transmission); -} - -Color SpatialMaterial::get_transmission() const { - return transmission; -} - -void SpatialMaterial::set_refraction(float p_refraction) { - refraction = p_refraction; - RS::get_singleton()->material_set_param(_get_material(), shader_names->refraction, refraction); -} - -float SpatialMaterial::get_refraction() const { - return refraction; -} - -void SpatialMaterial::set_detail_uv(DetailUV p_detail_uv) { - if (detail_uv == p_detail_uv) { - return; - } - - detail_uv = p_detail_uv; - _queue_shader_change(); -} -SpatialMaterial::DetailUV SpatialMaterial::get_detail_uv() const { - return detail_uv; -} - -void SpatialMaterial::set_blend_mode(BlendMode p_mode) { - if (blend_mode == p_mode) { - return; - } - - blend_mode = p_mode; - _queue_shader_change(); -} -SpatialMaterial::BlendMode SpatialMaterial::get_blend_mode() const { - return blend_mode; -} - -void SpatialMaterial::set_detail_blend_mode(BlendMode p_mode) { - detail_blend_mode = p_mode; - _queue_shader_change(); -} -SpatialMaterial::BlendMode SpatialMaterial::get_detail_blend_mode() const { - return detail_blend_mode; -} - -void SpatialMaterial::set_depth_draw_mode(DepthDrawMode p_mode) { - if (depth_draw_mode == p_mode) { - return; - } - - depth_draw_mode = p_mode; - _queue_shader_change(); -} -SpatialMaterial::DepthDrawMode SpatialMaterial::get_depth_draw_mode() const { - return depth_draw_mode; -} - -void SpatialMaterial::set_cull_mode(CullMode p_mode) { - if (cull_mode == p_mode) { - return; - } - - cull_mode = p_mode; - _queue_shader_change(); -} -SpatialMaterial::CullMode SpatialMaterial::get_cull_mode() const { - return cull_mode; -} - -void SpatialMaterial::set_diffuse_mode(DiffuseMode p_mode) { - if (diffuse_mode == p_mode) { - return; - } - - diffuse_mode = p_mode; - _queue_shader_change(); -} -SpatialMaterial::DiffuseMode SpatialMaterial::get_diffuse_mode() const { - return diffuse_mode; -} - -void SpatialMaterial::set_specular_mode(SpecularMode p_mode) { - if (specular_mode == p_mode) { - return; - } - - specular_mode = p_mode; - _queue_shader_change(); -} -SpatialMaterial::SpecularMode SpatialMaterial::get_specular_mode() const { - return specular_mode; -} - -void SpatialMaterial::set_flag(Flags p_flag, bool p_enabled) { - ERR_FAIL_INDEX(p_flag, FLAG_MAX); - - if (flags[p_flag] == p_enabled) { - return; - } - - flags[p_flag] = p_enabled; - - if ( - p_flag == FLAG_USE_ALPHA_SCISSOR || - p_flag == FLAG_UNSHADED || - p_flag == FLAG_USE_SHADOW_TO_OPACITY || - p_flag == FLAG_UV1_USE_TRIPLANAR || - p_flag == FLAG_UV2_USE_TRIPLANAR) { - _change_notify(); - } - - _queue_shader_change(); -} - -bool SpatialMaterial::get_flag(Flags p_flag) const { - ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false); - return flags[p_flag]; -} - -void SpatialMaterial::set_feature(Feature p_feature, bool p_enabled) { - ERR_FAIL_INDEX(p_feature, FEATURE_MAX); - if (features[p_feature] == p_enabled) { - return; - } - - features[p_feature] = p_enabled; - _change_notify(); - _queue_shader_change(); -} - -bool SpatialMaterial::get_feature(Feature p_feature) const { - ERR_FAIL_INDEX_V(p_feature, FEATURE_MAX, false); - return features[p_feature]; -} - -void SpatialMaterial::set_texture(TextureParam p_param, const Ref &p_texture) { - ERR_FAIL_INDEX(p_param, TEXTURE_MAX); - textures[p_param] = p_texture; - RID rid = p_texture.is_valid() ? p_texture->get_rid() : RID(); - RS::get_singleton()->material_set_param(_get_material(), shader_names->texture_names[p_param], rid); - _change_notify(); - _queue_shader_change(); -} - -Ref SpatialMaterial::get_texture(TextureParam p_param) const { - ERR_FAIL_INDEX_V(p_param, TEXTURE_MAX, Ref()); - return textures[p_param]; -} - -Ref SpatialMaterial::get_texture_by_name(StringName p_name) const { - for (int i = 0; i < (int)SpatialMaterial::TEXTURE_MAX; i++) { - TextureParam param = TextureParam(i); - if (p_name == shader_names->texture_names[param]) { - return textures[param]; - } - } - return Ref(); -} - -void SpatialMaterial::_validate_feature(const String &text, Feature feature, PropertyInfo &property) const { - if (property.name.begins_with(text) && property.name != text + "_enabled" && !features[feature]) { - property.usage = 0; - } -} - -void SpatialMaterial::_validate_high_end(const String &text, PropertyInfo &property) const { - if (property.name.begins_with(text)) { - property.usage |= PROPERTY_USAGE_HIGH_END_GFX; - } -} - -void SpatialMaterial::_validate_property(PropertyInfo &property) const { - _validate_feature("normal", FEATURE_NORMAL_MAPPING, property); - _validate_feature("emission", FEATURE_EMISSION, property); - _validate_feature("rim", FEATURE_RIM, property); - _validate_feature("clearcoat", FEATURE_CLEARCOAT, property); - _validate_feature("anisotropy", FEATURE_ANISOTROPY, property); - _validate_feature("ao", FEATURE_AMBIENT_OCCLUSION, property); - _validate_feature("depth", FEATURE_DEPTH_MAPPING, property); - _validate_feature("subsurf_scatter", FEATURE_SUBSURACE_SCATTERING, property); - _validate_feature("transmission", FEATURE_TRANSMISSION, property); - _validate_feature("refraction", FEATURE_REFRACTION, property); - _validate_feature("detail", FEATURE_DETAIL, property); - - _validate_high_end("subsurf_scatter", property); - _validate_high_end("depth", property); - - if (property.name.begins_with("particles_anim_") && billboard_mode != BILLBOARD_PARTICLES) { - property.usage = 0; - } - - if (property.name == "params_grow_amount" && !grow_enabled) { - property.usage = 0; - } - - if (property.name == "proximity_fade_distance" && !proximity_fade_enabled) { - property.usage = 0; - } - - if ((property.name == "distance_fade_max_distance" || property.name == "distance_fade_min_distance") && distance_fade == DISTANCE_FADE_DISABLED) { - property.usage = 0; - } - - if (property.name == "uv1_triplanar_sharpness" && !flags[FLAG_UV1_USE_TRIPLANAR]) { - property.usage = 0; - } - - if (property.name == "uv2_triplanar_sharpness" && !flags[FLAG_UV2_USE_TRIPLANAR]) { - property.usage = 0; - } - - if (property.name == "params_alpha_scissor_threshold" && !flags[FLAG_USE_ALPHA_SCISSOR]) { - property.usage = 0; - } - - if ((property.name == "depth_min_layers" || property.name == "depth_max_layers") && !deep_parallax) { - property.usage = 0; - } - - if (flags[FLAG_UNSHADED]) { - if (property.name.begins_with("anisotropy")) { - property.usage = 0; - } - - if (property.name.begins_with("ao")) { - property.usage = 0; - } - - if (property.name.begins_with("clearcoat")) { - property.usage = 0; - } - - if (property.name.begins_with("emission")) { - property.usage = 0; - } - - if (property.name.begins_with("metallic")) { - property.usage = 0; - } - - if (property.name.begins_with("normal")) { - property.usage = 0; - } - - if (property.name.begins_with("rim")) { - property.usage = 0; - } - - if (property.name.begins_with("roughness")) { - property.usage = 0; - } - - if (property.name.begins_with("subsurf_scatter")) { - property.usage = 0; - } - - if (property.name.begins_with("transmission")) { - property.usage = 0; - } - } -} - -void SpatialMaterial::set_line_width(float p_line_width) { - line_width = p_line_width; - RS::get_singleton()->material_set_line_width(_get_material(), line_width); -} - -float SpatialMaterial::get_line_width() const { - return line_width; -} - -void SpatialMaterial::set_point_size(float p_point_size) { - point_size = p_point_size; - RS::get_singleton()->material_set_param(_get_material(), shader_names->point_size, p_point_size); -} - -float SpatialMaterial::get_point_size() const { - return point_size; -} - -void SpatialMaterial::set_uv1_scale(const Vector3 &p_scale) { - uv1_scale = p_scale; - RS::get_singleton()->material_set_param(_get_material(), shader_names->uv1_scale, p_scale); -} - -Vector3 SpatialMaterial::get_uv1_scale() const { - return uv1_scale; -} - -void SpatialMaterial::set_uv1_offset(const Vector3 &p_offset) { - uv1_offset = p_offset; - RS::get_singleton()->material_set_param(_get_material(), shader_names->uv1_offset, p_offset); -} -Vector3 SpatialMaterial::get_uv1_offset() const { - return uv1_offset; -} - -void SpatialMaterial::set_uv1_triplanar_blend_sharpness(float p_sharpness) { - uv1_triplanar_sharpness = p_sharpness; - RS::get_singleton()->material_set_param(_get_material(), shader_names->uv1_blend_sharpness, p_sharpness); -} - -float SpatialMaterial::get_uv1_triplanar_blend_sharpness() const { - return uv1_triplanar_sharpness; -} - -void SpatialMaterial::set_uv2_scale(const Vector3 &p_scale) { - uv2_scale = p_scale; - RS::get_singleton()->material_set_param(_get_material(), shader_names->uv2_scale, p_scale); -} - -Vector3 SpatialMaterial::get_uv2_scale() const { - return uv2_scale; -} - -void SpatialMaterial::set_uv2_offset(const Vector3 &p_offset) { - uv2_offset = p_offset; - RS::get_singleton()->material_set_param(_get_material(), shader_names->uv2_offset, p_offset); -} - -Vector3 SpatialMaterial::get_uv2_offset() const { - return uv2_offset; -} - -void SpatialMaterial::set_uv2_triplanar_blend_sharpness(float p_sharpness) { - uv2_triplanar_sharpness = p_sharpness; - RS::get_singleton()->material_set_param(_get_material(), shader_names->uv2_blend_sharpness, p_sharpness); -} - -float SpatialMaterial::get_uv2_triplanar_blend_sharpness() const { - return uv2_triplanar_sharpness; -} - -void SpatialMaterial::set_billboard_mode(BillboardMode p_mode) { - billboard_mode = p_mode; - _queue_shader_change(); - _change_notify(); -} - -SpatialMaterial::BillboardMode SpatialMaterial::get_billboard_mode() const { - return billboard_mode; -} - -void SpatialMaterial::set_particles_anim_h_frames(int p_frames) { - particles_anim_h_frames = p_frames; - RS::get_singleton()->material_set_param(_get_material(), shader_names->particles_anim_h_frames, p_frames); -} - -int SpatialMaterial::get_particles_anim_h_frames() const { - return particles_anim_h_frames; -} -void SpatialMaterial::set_particles_anim_v_frames(int p_frames) { - particles_anim_v_frames = p_frames; - RS::get_singleton()->material_set_param(_get_material(), shader_names->particles_anim_v_frames, p_frames); -} - -int SpatialMaterial::get_particles_anim_v_frames() const { - return particles_anim_v_frames; -} - -void SpatialMaterial::set_particles_anim_loop(bool p_loop) { - particles_anim_loop = p_loop; - RS::get_singleton()->material_set_param(_get_material(), shader_names->particles_anim_loop, particles_anim_loop); -} - -bool SpatialMaterial::get_particles_anim_loop() const { - return particles_anim_loop; -} - -void SpatialMaterial::set_depth_deep_parallax(bool p_enable) { - deep_parallax = p_enable; - _queue_shader_change(); - _change_notify(); -} - -bool SpatialMaterial::is_depth_deep_parallax_enabled() const { - return deep_parallax; -} - -void SpatialMaterial::set_depth_deep_parallax_min_layers(int p_layer) { - deep_parallax_min_layers = p_layer; - RS::get_singleton()->material_set_param(_get_material(), shader_names->depth_min_layers, p_layer); -} -int SpatialMaterial::get_depth_deep_parallax_min_layers() const { - return deep_parallax_min_layers; -} - -void SpatialMaterial::set_depth_deep_parallax_max_layers(int p_layer) { - deep_parallax_max_layers = p_layer; - RS::get_singleton()->material_set_param(_get_material(), shader_names->depth_max_layers, p_layer); -} -int SpatialMaterial::get_depth_deep_parallax_max_layers() const { - return deep_parallax_max_layers; -} - -void SpatialMaterial::set_depth_deep_parallax_flip_tangent(bool p_flip) { - depth_parallax_flip_tangent = p_flip; - RS::get_singleton()->material_set_param(_get_material(), shader_names->depth_flip, Vector2(depth_parallax_flip_tangent ? -1 : 1, depth_parallax_flip_binormal ? -1 : 1)); -} - -bool SpatialMaterial::get_depth_deep_parallax_flip_tangent() const { - return depth_parallax_flip_tangent; -} - -void SpatialMaterial::set_depth_deep_parallax_flip_binormal(bool p_flip) { - depth_parallax_flip_binormal = p_flip; - RS::get_singleton()->material_set_param(_get_material(), shader_names->depth_flip, Vector2(depth_parallax_flip_tangent ? -1 : 1, depth_parallax_flip_binormal ? -1 : 1)); -} - -bool SpatialMaterial::get_depth_deep_parallax_flip_binormal() const { - return depth_parallax_flip_binormal; -} - -void SpatialMaterial::set_grow_enabled(bool p_enable) { - grow_enabled = p_enable; - _queue_shader_change(); - _change_notify(); -} - -bool SpatialMaterial::is_grow_enabled() const { - return grow_enabled; -} - -void SpatialMaterial::set_alpha_scissor_threshold(float p_threshold) { - alpha_scissor_threshold = p_threshold; - RS::get_singleton()->material_set_param(_get_material(), shader_names->alpha_scissor_threshold, p_threshold); -} - -float SpatialMaterial::get_alpha_scissor_threshold() const { - return alpha_scissor_threshold; -} - -void SpatialMaterial::set_grow(float p_grow) { - grow = p_grow; - RS::get_singleton()->material_set_param(_get_material(), shader_names->grow, p_grow); -} - -float SpatialMaterial::get_grow() const { - return grow; -} - -static Plane _get_texture_mask(SpatialMaterial::TextureChannel p_channel) { - static const Plane masks[5] = { - Plane(1, 0, 0, 0), - Plane(0, 1, 0, 0), - Plane(0, 0, 1, 0), - Plane(0, 0, 0, 1), - Plane(0.3333333, 0.3333333, 0.3333333, 0), - }; - - return masks[p_channel]; -} - -void SpatialMaterial::set_metallic_texture_channel(TextureChannel p_channel) { - ERR_FAIL_INDEX(p_channel, 5); - metallic_texture_channel = p_channel; - RS::get_singleton()->material_set_param(_get_material(), shader_names->metallic_texture_channel, _get_texture_mask(p_channel)); -} - -SpatialMaterial::TextureChannel SpatialMaterial::get_metallic_texture_channel() const { - return metallic_texture_channel; -} - -void SpatialMaterial::set_roughness_texture_channel(TextureChannel p_channel) { - ERR_FAIL_INDEX(p_channel, 5); - roughness_texture_channel = p_channel; - RS::get_singleton()->material_set_param(_get_material(), shader_names->roughness_texture_channel, _get_texture_mask(p_channel)); -} - -SpatialMaterial::TextureChannel SpatialMaterial::get_roughness_texture_channel() const { - return roughness_texture_channel; -} - -void SpatialMaterial::set_ao_texture_channel(TextureChannel p_channel) { - ERR_FAIL_INDEX(p_channel, 5); - ao_texture_channel = p_channel; - RS::get_singleton()->material_set_param(_get_material(), shader_names->ao_texture_channel, _get_texture_mask(p_channel)); -} - -SpatialMaterial::TextureChannel SpatialMaterial::get_ao_texture_channel() const { - return ao_texture_channel; -} - -void SpatialMaterial::set_refraction_texture_channel(TextureChannel p_channel) { - ERR_FAIL_INDEX(p_channel, 5); - refraction_texture_channel = p_channel; - RS::get_singleton()->material_set_param(_get_material(), shader_names->refraction_texture_channel, _get_texture_mask(p_channel)); -} - -SpatialMaterial::TextureChannel SpatialMaterial::get_refraction_texture_channel() const { - return refraction_texture_channel; -} - -RID SpatialMaterial::get_material_rid_for_2d(bool p_shaded, bool p_transparent, bool p_double_sided, bool p_cut_alpha, bool p_opaque_prepass, bool p_billboard, bool p_billboard_y, bool p_no_depth_test, bool p_fixed_size, bool p_sdf) { - uint64_t hash = 0; - - if (p_shaded) { - hash |= 1 << 0; - } - if (p_transparent) { - hash |= 1 << 1; - } - if (p_cut_alpha) { - hash |= 1 << 2; - } - if (p_opaque_prepass) { - hash |= 1 << 3; - } - if (p_double_sided) { - hash |= 1 << 4; - } - if (p_billboard) { - hash |= 1 << 5; - } - if (p_billboard_y) { - hash |= 1 << 6; - } - if (p_no_depth_test) { - hash |= 1 << 7; - } - if (p_fixed_size) { - hash |= 1 << 8; - } - if (p_sdf) { - hash |= 1 << 9; - } - - if (materials_for_2d.has(hash)) { - return materials_for_2d[hash]->get_rid(); - } - - Ref material; - material.instance(); - - material->set_flag(FLAG_UNSHADED, !p_shaded); - material->set_feature(FEATURE_TRANSPARENT, p_transparent); - material->set_cull_mode(p_double_sided ? CULL_DISABLED : CULL_BACK); - material->set_depth_draw_mode(p_opaque_prepass ? DEPTH_DRAW_ALPHA_OPAQUE_PREPASS : DEPTH_DRAW_OPAQUE_ONLY); - material->set_flag(FLAG_SRGB_VERTEX_COLOR, true); - material->set_flag(FLAG_ALBEDO_FROM_VERTEX_COLOR, true); - material->set_flag(FLAG_USE_ALPHA_SCISSOR, p_cut_alpha); - material->set_flag(FLAG_DISABLE_DEPTH_TEST, p_no_depth_test); - material->set_flag(FLAG_FIXED_SIZE, p_fixed_size); - material->set_flag(FLAG_ALBEDO_TEXTURE_SDF, p_sdf); - if (p_billboard || p_billboard_y) { - material->set_flag(FLAG_BILLBOARD_KEEP_SCALE, true); - material->set_billboard_mode(p_billboard_y ? BILLBOARD_FIXED_Y : BILLBOARD_ENABLED); - } - - materials_for_2d[hash] = material; - // flush before using so we can access the shader right away - flush_changes(); - - return materials_for_2d[hash]->get_rid(); -} - -void SpatialMaterial::set_on_top_of_alpha() { - set_feature(FEATURE_TRANSPARENT, true); - set_render_priority(RENDER_PRIORITY_MAX); - set_flag(FLAG_DISABLE_DEPTH_TEST, true); -} - -void SpatialMaterial::set_proximity_fade(bool p_enable) { - proximity_fade_enabled = p_enable; - _queue_shader_change(); - _change_notify(); -} - -bool SpatialMaterial::is_proximity_fade_enabled() const { - return proximity_fade_enabled; -} - -void SpatialMaterial::set_proximity_fade_distance(float p_distance) { - proximity_fade_distance = p_distance; - RS::get_singleton()->material_set_param(_get_material(), shader_names->proximity_fade_distance, p_distance); -} -float SpatialMaterial::get_proximity_fade_distance() const { - return proximity_fade_distance; -} - -void SpatialMaterial::set_distance_fade(DistanceFadeMode p_mode) { - distance_fade = p_mode; - _queue_shader_change(); - _change_notify(); -} -SpatialMaterial::DistanceFadeMode SpatialMaterial::get_distance_fade() const { - return distance_fade; -} - -void SpatialMaterial::set_distance_fade_max_distance(float p_distance) { - distance_fade_max_distance = p_distance; - RS::get_singleton()->material_set_param(_get_material(), shader_names->distance_fade_max, distance_fade_max_distance); -} -float SpatialMaterial::get_distance_fade_max_distance() const { - return distance_fade_max_distance; -} - -void SpatialMaterial::set_distance_fade_min_distance(float p_distance) { - distance_fade_min_distance = p_distance; - RS::get_singleton()->material_set_param(_get_material(), shader_names->distance_fade_min, distance_fade_min_distance); -} - -float SpatialMaterial::get_distance_fade_min_distance() const { - return distance_fade_min_distance; -} - -void SpatialMaterial::set_emission_operator(EmissionOperator p_op) { - if (emission_op == p_op) { - return; - } - emission_op = p_op; - _queue_shader_change(); -} - -SpatialMaterial::EmissionOperator SpatialMaterial::get_emission_operator() const { - return emission_op; -} - -RID SpatialMaterial::get_shader_rid() const { - ERR_FAIL_COND_V(!shader_map.has(current_key), RID()); - return shader_map[current_key].shader; -} - -Shader::Mode SpatialMaterial::get_shader_mode() const { - return Shader::MODE_SPATIAL; -} - -void SpatialMaterial::set_async_mode(AsyncMode p_mode) { - async_mode = p_mode; - _queue_shader_change(); - _change_notify(); -} - -SpatialMaterial::AsyncMode SpatialMaterial::get_async_mode() const { - return async_mode; -} - -void SpatialMaterial::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_albedo", "albedo"), &SpatialMaterial::set_albedo); - ClassDB::bind_method(D_METHOD("get_albedo"), &SpatialMaterial::get_albedo); - - ClassDB::bind_method(D_METHOD("set_specular", "specular"), &SpatialMaterial::set_specular); - ClassDB::bind_method(D_METHOD("get_specular"), &SpatialMaterial::get_specular); - - ClassDB::bind_method(D_METHOD("set_metallic", "metallic"), &SpatialMaterial::set_metallic); - ClassDB::bind_method(D_METHOD("get_metallic"), &SpatialMaterial::get_metallic); - - ClassDB::bind_method(D_METHOD("set_roughness", "roughness"), &SpatialMaterial::set_roughness); - ClassDB::bind_method(D_METHOD("get_roughness"), &SpatialMaterial::get_roughness); - - ClassDB::bind_method(D_METHOD("set_emission", "emission"), &SpatialMaterial::set_emission); - ClassDB::bind_method(D_METHOD("get_emission"), &SpatialMaterial::get_emission); - - ClassDB::bind_method(D_METHOD("set_emission_energy", "emission_energy"), &SpatialMaterial::set_emission_energy); - ClassDB::bind_method(D_METHOD("get_emission_energy"), &SpatialMaterial::get_emission_energy); - - ClassDB::bind_method(D_METHOD("set_normal_scale", "normal_scale"), &SpatialMaterial::set_normal_scale); - ClassDB::bind_method(D_METHOD("get_normal_scale"), &SpatialMaterial::get_normal_scale); - - ClassDB::bind_method(D_METHOD("set_rim", "rim"), &SpatialMaterial::set_rim); - ClassDB::bind_method(D_METHOD("get_rim"), &SpatialMaterial::get_rim); - - ClassDB::bind_method(D_METHOD("set_rim_tint", "rim_tint"), &SpatialMaterial::set_rim_tint); - ClassDB::bind_method(D_METHOD("get_rim_tint"), &SpatialMaterial::get_rim_tint); - - ClassDB::bind_method(D_METHOD("set_clearcoat", "clearcoat"), &SpatialMaterial::set_clearcoat); - ClassDB::bind_method(D_METHOD("get_clearcoat"), &SpatialMaterial::get_clearcoat); - - ClassDB::bind_method(D_METHOD("set_clearcoat_gloss", "clearcoat_gloss"), &SpatialMaterial::set_clearcoat_gloss); - ClassDB::bind_method(D_METHOD("get_clearcoat_gloss"), &SpatialMaterial::get_clearcoat_gloss); - - ClassDB::bind_method(D_METHOD("set_anisotropy", "anisotropy"), &SpatialMaterial::set_anisotropy); - ClassDB::bind_method(D_METHOD("get_anisotropy"), &SpatialMaterial::get_anisotropy); - - ClassDB::bind_method(D_METHOD("set_depth_scale", "depth_scale"), &SpatialMaterial::set_depth_scale); - ClassDB::bind_method(D_METHOD("get_depth_scale"), &SpatialMaterial::get_depth_scale); - - ClassDB::bind_method(D_METHOD("set_subsurface_scattering_strength", "strength"), &SpatialMaterial::set_subsurface_scattering_strength); - ClassDB::bind_method(D_METHOD("get_subsurface_scattering_strength"), &SpatialMaterial::get_subsurface_scattering_strength); - - ClassDB::bind_method(D_METHOD("set_transmission", "transmission"), &SpatialMaterial::set_transmission); - ClassDB::bind_method(D_METHOD("get_transmission"), &SpatialMaterial::get_transmission); - - ClassDB::bind_method(D_METHOD("set_refraction", "refraction"), &SpatialMaterial::set_refraction); - ClassDB::bind_method(D_METHOD("get_refraction"), &SpatialMaterial::get_refraction); - - ClassDB::bind_method(D_METHOD("set_line_width", "line_width"), &SpatialMaterial::set_line_width); - ClassDB::bind_method(D_METHOD("get_line_width"), &SpatialMaterial::get_line_width); - - ClassDB::bind_method(D_METHOD("set_point_size", "point_size"), &SpatialMaterial::set_point_size); - ClassDB::bind_method(D_METHOD("get_point_size"), &SpatialMaterial::get_point_size); - - ClassDB::bind_method(D_METHOD("set_detail_uv", "detail_uv"), &SpatialMaterial::set_detail_uv); - ClassDB::bind_method(D_METHOD("get_detail_uv"), &SpatialMaterial::get_detail_uv); - - ClassDB::bind_method(D_METHOD("set_blend_mode", "blend_mode"), &SpatialMaterial::set_blend_mode); - ClassDB::bind_method(D_METHOD("get_blend_mode"), &SpatialMaterial::get_blend_mode); - - ClassDB::bind_method(D_METHOD("set_depth_draw_mode", "depth_draw_mode"), &SpatialMaterial::set_depth_draw_mode); - ClassDB::bind_method(D_METHOD("get_depth_draw_mode"), &SpatialMaterial::get_depth_draw_mode); - - ClassDB::bind_method(D_METHOD("set_cull_mode", "cull_mode"), &SpatialMaterial::set_cull_mode); - ClassDB::bind_method(D_METHOD("get_cull_mode"), &SpatialMaterial::get_cull_mode); - - ClassDB::bind_method(D_METHOD("set_diffuse_mode", "diffuse_mode"), &SpatialMaterial::set_diffuse_mode); - ClassDB::bind_method(D_METHOD("get_diffuse_mode"), &SpatialMaterial::get_diffuse_mode); - - ClassDB::bind_method(D_METHOD("set_specular_mode", "specular_mode"), &SpatialMaterial::set_specular_mode); - ClassDB::bind_method(D_METHOD("get_specular_mode"), &SpatialMaterial::get_specular_mode); - - ClassDB::bind_method(D_METHOD("set_flag", "flag", "enable"), &SpatialMaterial::set_flag); - ClassDB::bind_method(D_METHOD("get_flag", "flag"), &SpatialMaterial::get_flag); - - ClassDB::bind_method(D_METHOD("set_feature", "feature", "enable"), &SpatialMaterial::set_feature); - ClassDB::bind_method(D_METHOD("get_feature", "feature"), &SpatialMaterial::get_feature); - - ClassDB::bind_method(D_METHOD("set_texture", "param", "texture"), &SpatialMaterial::set_texture); - ClassDB::bind_method(D_METHOD("get_texture", "param"), &SpatialMaterial::get_texture); - - ClassDB::bind_method(D_METHOD("set_detail_blend_mode", "detail_blend_mode"), &SpatialMaterial::set_detail_blend_mode); - ClassDB::bind_method(D_METHOD("get_detail_blend_mode"), &SpatialMaterial::get_detail_blend_mode); - - ClassDB::bind_method(D_METHOD("set_uv1_scale", "scale"), &SpatialMaterial::set_uv1_scale); - ClassDB::bind_method(D_METHOD("get_uv1_scale"), &SpatialMaterial::get_uv1_scale); - - ClassDB::bind_method(D_METHOD("set_uv1_offset", "offset"), &SpatialMaterial::set_uv1_offset); - ClassDB::bind_method(D_METHOD("get_uv1_offset"), &SpatialMaterial::get_uv1_offset); - - ClassDB::bind_method(D_METHOD("set_uv1_triplanar_blend_sharpness", "sharpness"), &SpatialMaterial::set_uv1_triplanar_blend_sharpness); - ClassDB::bind_method(D_METHOD("get_uv1_triplanar_blend_sharpness"), &SpatialMaterial::get_uv1_triplanar_blend_sharpness); - - ClassDB::bind_method(D_METHOD("set_uv2_scale", "scale"), &SpatialMaterial::set_uv2_scale); - ClassDB::bind_method(D_METHOD("get_uv2_scale"), &SpatialMaterial::get_uv2_scale); - - ClassDB::bind_method(D_METHOD("set_uv2_offset", "offset"), &SpatialMaterial::set_uv2_offset); - ClassDB::bind_method(D_METHOD("get_uv2_offset"), &SpatialMaterial::get_uv2_offset); - - ClassDB::bind_method(D_METHOD("set_uv2_triplanar_blend_sharpness", "sharpness"), &SpatialMaterial::set_uv2_triplanar_blend_sharpness); - ClassDB::bind_method(D_METHOD("get_uv2_triplanar_blend_sharpness"), &SpatialMaterial::get_uv2_triplanar_blend_sharpness); - - ClassDB::bind_method(D_METHOD("set_billboard_mode", "mode"), &SpatialMaterial::set_billboard_mode); - ClassDB::bind_method(D_METHOD("get_billboard_mode"), &SpatialMaterial::get_billboard_mode); - - ClassDB::bind_method(D_METHOD("set_particles_anim_h_frames", "frames"), &SpatialMaterial::set_particles_anim_h_frames); - ClassDB::bind_method(D_METHOD("get_particles_anim_h_frames"), &SpatialMaterial::get_particles_anim_h_frames); - - ClassDB::bind_method(D_METHOD("set_particles_anim_v_frames", "frames"), &SpatialMaterial::set_particles_anim_v_frames); - ClassDB::bind_method(D_METHOD("get_particles_anim_v_frames"), &SpatialMaterial::get_particles_anim_v_frames); - - ClassDB::bind_method(D_METHOD("set_particles_anim_loop", "loop"), &SpatialMaterial::set_particles_anim_loop); - ClassDB::bind_method(D_METHOD("get_particles_anim_loop"), &SpatialMaterial::get_particles_anim_loop); - - ClassDB::bind_method(D_METHOD("set_depth_deep_parallax", "enable"), &SpatialMaterial::set_depth_deep_parallax); - ClassDB::bind_method(D_METHOD("is_depth_deep_parallax_enabled"), &SpatialMaterial::is_depth_deep_parallax_enabled); - - ClassDB::bind_method(D_METHOD("set_depth_deep_parallax_min_layers", "layer"), &SpatialMaterial::set_depth_deep_parallax_min_layers); - ClassDB::bind_method(D_METHOD("get_depth_deep_parallax_min_layers"), &SpatialMaterial::get_depth_deep_parallax_min_layers); - - ClassDB::bind_method(D_METHOD("set_depth_deep_parallax_max_layers", "layer"), &SpatialMaterial::set_depth_deep_parallax_max_layers); - ClassDB::bind_method(D_METHOD("get_depth_deep_parallax_max_layers"), &SpatialMaterial::get_depth_deep_parallax_max_layers); - - ClassDB::bind_method(D_METHOD("set_depth_deep_parallax_flip_tangent", "flip"), &SpatialMaterial::set_depth_deep_parallax_flip_tangent); - ClassDB::bind_method(D_METHOD("get_depth_deep_parallax_flip_tangent"), &SpatialMaterial::get_depth_deep_parallax_flip_tangent); - - ClassDB::bind_method(D_METHOD("set_depth_deep_parallax_flip_binormal", "flip"), &SpatialMaterial::set_depth_deep_parallax_flip_binormal); - ClassDB::bind_method(D_METHOD("get_depth_deep_parallax_flip_binormal"), &SpatialMaterial::get_depth_deep_parallax_flip_binormal); - - ClassDB::bind_method(D_METHOD("set_grow", "amount"), &SpatialMaterial::set_grow); - ClassDB::bind_method(D_METHOD("get_grow"), &SpatialMaterial::get_grow); - - ClassDB::bind_method(D_METHOD("set_emission_operator", "operator"), &SpatialMaterial::set_emission_operator); - ClassDB::bind_method(D_METHOD("get_emission_operator"), &SpatialMaterial::get_emission_operator); - - ClassDB::bind_method(D_METHOD("set_ao_light_affect", "amount"), &SpatialMaterial::set_ao_light_affect); - ClassDB::bind_method(D_METHOD("get_ao_light_affect"), &SpatialMaterial::get_ao_light_affect); - - ClassDB::bind_method(D_METHOD("set_alpha_scissor_threshold", "threshold"), &SpatialMaterial::set_alpha_scissor_threshold); - ClassDB::bind_method(D_METHOD("get_alpha_scissor_threshold"), &SpatialMaterial::get_alpha_scissor_threshold); - - ClassDB::bind_method(D_METHOD("set_grow_enabled", "enable"), &SpatialMaterial::set_grow_enabled); - ClassDB::bind_method(D_METHOD("is_grow_enabled"), &SpatialMaterial::is_grow_enabled); - - ClassDB::bind_method(D_METHOD("set_metallic_texture_channel", "channel"), &SpatialMaterial::set_metallic_texture_channel); - ClassDB::bind_method(D_METHOD("get_metallic_texture_channel"), &SpatialMaterial::get_metallic_texture_channel); - - ClassDB::bind_method(D_METHOD("set_roughness_texture_channel", "channel"), &SpatialMaterial::set_roughness_texture_channel); - ClassDB::bind_method(D_METHOD("get_roughness_texture_channel"), &SpatialMaterial::get_roughness_texture_channel); - - ClassDB::bind_method(D_METHOD("set_ao_texture_channel", "channel"), &SpatialMaterial::set_ao_texture_channel); - ClassDB::bind_method(D_METHOD("get_ao_texture_channel"), &SpatialMaterial::get_ao_texture_channel); - - ClassDB::bind_method(D_METHOD("set_refraction_texture_channel", "channel"), &SpatialMaterial::set_refraction_texture_channel); - ClassDB::bind_method(D_METHOD("get_refraction_texture_channel"), &SpatialMaterial::get_refraction_texture_channel); - - ClassDB::bind_method(D_METHOD("set_proximity_fade", "enabled"), &SpatialMaterial::set_proximity_fade); - ClassDB::bind_method(D_METHOD("is_proximity_fade_enabled"), &SpatialMaterial::is_proximity_fade_enabled); - - ClassDB::bind_method(D_METHOD("set_proximity_fade_distance", "distance"), &SpatialMaterial::set_proximity_fade_distance); - ClassDB::bind_method(D_METHOD("get_proximity_fade_distance"), &SpatialMaterial::get_proximity_fade_distance); - - ClassDB::bind_method(D_METHOD("set_distance_fade", "mode"), &SpatialMaterial::set_distance_fade); - ClassDB::bind_method(D_METHOD("get_distance_fade"), &SpatialMaterial::get_distance_fade); - - ClassDB::bind_method(D_METHOD("set_distance_fade_max_distance", "distance"), &SpatialMaterial::set_distance_fade_max_distance); - ClassDB::bind_method(D_METHOD("get_distance_fade_max_distance"), &SpatialMaterial::get_distance_fade_max_distance); - - ClassDB::bind_method(D_METHOD("set_distance_fade_min_distance", "distance"), &SpatialMaterial::set_distance_fade_min_distance); - ClassDB::bind_method(D_METHOD("get_distance_fade_min_distance"), &SpatialMaterial::get_distance_fade_min_distance); - - ClassDB::bind_method(D_METHOD("set_async_mode", "mode"), &SpatialMaterial::set_async_mode); - ClassDB::bind_method(D_METHOD("get_async_mode"), &SpatialMaterial::get_async_mode); - - ADD_GROUP("Flags", "flags_"); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_transparent"), "set_feature", "get_feature", FEATURE_TRANSPARENT); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_use_shadow_to_opacity"), "set_flag", "get_flag", FLAG_USE_SHADOW_TO_OPACITY); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_unshaded"), "set_flag", "get_flag", FLAG_UNSHADED); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_vertex_lighting"), "set_flag", "get_flag", FLAG_USE_VERTEX_LIGHTING); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_no_depth_test"), "set_flag", "get_flag", FLAG_DISABLE_DEPTH_TEST); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_use_point_size"), "set_flag", "get_flag", FLAG_USE_POINT_SIZE); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_world_triplanar"), "set_flag", "get_flag", FLAG_TRIPLANAR_USE_WORLD); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_fixed_size"), "set_flag", "get_flag", FLAG_FIXED_SIZE); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_albedo_tex_force_srgb"), "set_flag", "get_flag", FLAG_ALBEDO_TEXTURE_FORCE_SRGB); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_do_not_receive_shadows"), "set_flag", "get_flag", FLAG_DONT_RECEIVE_SHADOWS); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_disable_ambient_light"), "set_flag", "get_flag", FLAG_DISABLE_AMBIENT_LIGHT); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_ensure_correct_normals"), "set_flag", "get_flag", FLAG_ENSURE_CORRECT_NORMALS); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_albedo_tex_msdf"), "set_flag", "get_flag", FLAG_ALBEDO_TEXTURE_SDF); - ADD_GROUP("Vertex Color", "vertex_color"); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "vertex_color_use_as_albedo"), "set_flag", "get_flag", FLAG_ALBEDO_FROM_VERTEX_COLOR); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "vertex_color_is_srgb"), "set_flag", "get_flag", FLAG_SRGB_VERTEX_COLOR); - - ADD_GROUP("Parameters", "params_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "params_diffuse_mode", PROPERTY_HINT_ENUM, "Burley,Lambert,Lambert Wrap,Oren Nayar,Toon"), "set_diffuse_mode", "get_diffuse_mode"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "params_specular_mode", PROPERTY_HINT_ENUM, "SchlickGGX,Blinn,Phong,Toon,Disabled"), "set_specular_mode", "get_specular_mode"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "params_blend_mode", PROPERTY_HINT_ENUM, "Mix,Add,Sub,Mul"), "set_blend_mode", "get_blend_mode"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "params_cull_mode", PROPERTY_HINT_ENUM, "Back,Front,Disabled"), "set_cull_mode", "get_cull_mode"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "params_depth_draw_mode", PROPERTY_HINT_ENUM, "Opaque Only,Always,Never,Opaque Pre-Pass"), "set_depth_draw_mode", "get_depth_draw_mode"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "params_line_width", PROPERTY_HINT_RANGE, "0.1,128,0.1"), "set_line_width", "get_line_width"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "params_point_size", PROPERTY_HINT_RANGE, "0.1,128,0.1"), "set_point_size", "get_point_size"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "params_billboard_mode", PROPERTY_HINT_ENUM, "Disabled,Enabled,Y-Billboard,Particle Billboard"), "set_billboard_mode", "get_billboard_mode"); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "params_billboard_keep_scale"), "set_flag", "get_flag", FLAG_BILLBOARD_KEEP_SCALE); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "params_grow"), "set_grow_enabled", "is_grow_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "params_grow_amount", PROPERTY_HINT_RANGE, "-16,16,0.001"), "set_grow", "get_grow"); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "params_use_alpha_scissor"), "set_flag", "get_flag", FLAG_USE_ALPHA_SCISSOR); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "params_alpha_scissor_threshold", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_alpha_scissor_threshold", "get_alpha_scissor_threshold"); - ADD_GROUP("Particles Anim", "particles_anim_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "particles_anim_h_frames", PROPERTY_HINT_RANGE, "1,128,1"), "set_particles_anim_h_frames", "get_particles_anim_h_frames"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "particles_anim_v_frames", PROPERTY_HINT_RANGE, "1,128,1"), "set_particles_anim_v_frames", "get_particles_anim_v_frames"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "particles_anim_loop"), "set_particles_anim_loop", "get_particles_anim_loop"); - - ADD_GROUP("Albedo", "albedo_"); - ADD_PROPERTY(PropertyInfo(Variant::COLOR, "albedo_color"), "set_albedo", "get_albedo"); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "albedo_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_ALBEDO); - - ADD_GROUP("Metallic", "metallic_"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "metallic", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_metallic", "get_metallic"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "metallic_specular", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_specular", "get_specular"); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "metallic_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_METALLIC); - ADD_PROPERTY(PropertyInfo(Variant::INT, "metallic_texture_channel", PROPERTY_HINT_ENUM, "Red,Green,Blue,Alpha,Gray"), "set_metallic_texture_channel", "get_metallic_texture_channel"); - - ADD_GROUP("Roughness", "roughness_"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "roughness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_roughness", "get_roughness"); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "roughness_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_ROUGHNESS); - ADD_PROPERTY(PropertyInfo(Variant::INT, "roughness_texture_channel", PROPERTY_HINT_ENUM, "Red,Green,Blue,Alpha,Gray"), "set_roughness_texture_channel", "get_roughness_texture_channel"); - - ADD_GROUP("Emission", "emission_"); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "emission_enabled"), "set_feature", "get_feature", FEATURE_EMISSION); - ADD_PROPERTY(PropertyInfo(Variant::COLOR, "emission", PROPERTY_HINT_COLOR_NO_ALPHA), "set_emission", "get_emission"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "emission_energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_emission_energy", "get_emission_energy"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_operator", PROPERTY_HINT_ENUM, "Add,Multiply"), "set_emission_operator", "get_emission_operator"); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "emission_on_uv2"), "set_flag", "get_flag", FLAG_EMISSION_ON_UV2); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "emission_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_EMISSION); - - ADD_GROUP("NormalMap", "normal_"); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "normal_enabled"), "set_feature", "get_feature", FEATURE_NORMAL_MAPPING); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "normal_scale", PROPERTY_HINT_RANGE, "-16,16,0.01"), "set_normal_scale", "get_normal_scale"); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "normal_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_NORMAL); - - ADD_GROUP("Rim", "rim_"); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "rim_enabled"), "set_feature", "get_feature", FEATURE_RIM); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "rim", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_rim", "get_rim"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "rim_tint", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_rim_tint", "get_rim_tint"); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "rim_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_RIM); - - ADD_GROUP("Clearcoat", "clearcoat_"); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "clearcoat_enabled"), "set_feature", "get_feature", FEATURE_CLEARCOAT); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "clearcoat", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_clearcoat", "get_clearcoat"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "clearcoat_gloss", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_clearcoat_gloss", "get_clearcoat_gloss"); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "clearcoat_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_CLEARCOAT); - - ADD_GROUP("Anisotropy", "anisotropy_"); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "anisotropy_enabled"), "set_feature", "get_feature", FEATURE_ANISOTROPY); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "anisotropy", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_anisotropy", "get_anisotropy"); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "anisotropy_flowmap", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_FLOWMAP); - - ADD_GROUP("Ambient Occlusion", "ao_"); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "ao_enabled"), "set_feature", "get_feature", FEATURE_AMBIENT_OCCLUSION); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "ao_light_affect", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_ao_light_affect", "get_ao_light_affect"); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "ao_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_AMBIENT_OCCLUSION); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "ao_on_uv2"), "set_flag", "get_flag", FLAG_AO_ON_UV2); - ADD_PROPERTY(PropertyInfo(Variant::INT, "ao_texture_channel", PROPERTY_HINT_ENUM, "Red,Green,Blue,Alpha,Gray"), "set_ao_texture_channel", "get_ao_texture_channel"); - - ADD_GROUP("Depth", "depth_"); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "depth_enabled"), "set_feature", "get_feature", FEATURE_DEPTH_MAPPING); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "depth_scale", PROPERTY_HINT_RANGE, "-16,16,0.001"), "set_depth_scale", "get_depth_scale"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "depth_deep_parallax"), "set_depth_deep_parallax", "is_depth_deep_parallax_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "depth_min_layers", PROPERTY_HINT_RANGE, "1,64,1"), "set_depth_deep_parallax_min_layers", "get_depth_deep_parallax_min_layers"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "depth_max_layers", PROPERTY_HINT_RANGE, "1,64,1"), "set_depth_deep_parallax_max_layers", "get_depth_deep_parallax_max_layers"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "depth_flip_tangent"), "set_depth_deep_parallax_flip_tangent", "get_depth_deep_parallax_flip_tangent"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "depth_flip_binormal"), "set_depth_deep_parallax_flip_binormal", "get_depth_deep_parallax_flip_binormal"); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "depth_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_DEPTH); - - ADD_GROUP("Subsurf Scatter", "subsurf_scatter_"); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "subsurf_scatter_enabled"), "set_feature", "get_feature", FEATURE_SUBSURACE_SCATTERING); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "subsurf_scatter_strength", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_subsurface_scattering_strength", "get_subsurface_scattering_strength"); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "subsurf_scatter_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_SUBSURFACE_SCATTERING); - - ADD_GROUP("Transmission", "transmission_"); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "transmission_enabled"), "set_feature", "get_feature", FEATURE_TRANSMISSION); - ADD_PROPERTY(PropertyInfo(Variant::COLOR, "transmission", PROPERTY_HINT_COLOR_NO_ALPHA), "set_transmission", "get_transmission"); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "transmission_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_TRANSMISSION); - - ADD_GROUP("Refraction", "refraction_"); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "refraction_enabled"), "set_feature", "get_feature", FEATURE_REFRACTION); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "refraction_scale", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_refraction", "get_refraction"); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "refraction_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_REFRACTION); - ADD_PROPERTY(PropertyInfo(Variant::INT, "refraction_texture_channel", PROPERTY_HINT_ENUM, "Red,Green,Blue,Alpha,Gray"), "set_refraction_texture_channel", "get_refraction_texture_channel"); - - ADD_GROUP("Detail", "detail_"); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "detail_enabled"), "set_feature", "get_feature", FEATURE_DETAIL); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "detail_mask", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_DETAIL_MASK); - ADD_PROPERTY(PropertyInfo(Variant::INT, "detail_blend_mode", PROPERTY_HINT_ENUM, "Mix,Add,Sub,Mul"), "set_detail_blend_mode", "get_detail_blend_mode"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "detail_uv_layer", PROPERTY_HINT_ENUM, "UV1,UV2"), "set_detail_uv", "get_detail_uv"); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "detail_albedo", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_DETAIL_ALBEDO); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "detail_normal", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_DETAIL_NORMAL); - - ADD_GROUP("UV1", "uv1_"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "uv1_scale", PROPERTY_HINT_LINK), "set_uv1_scale", "get_uv1_scale"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "uv1_offset"), "set_uv1_offset", "get_uv1_offset"); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "uv1_triplanar"), "set_flag", "get_flag", FLAG_UV1_USE_TRIPLANAR); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "uv1_triplanar_sharpness", PROPERTY_HINT_EXP_EASING), "set_uv1_triplanar_blend_sharpness", "get_uv1_triplanar_blend_sharpness"); - - ADD_GROUP("UV2", "uv2_"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "uv2_scale", PROPERTY_HINT_LINK), "set_uv2_scale", "get_uv2_scale"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "uv2_offset"), "set_uv2_offset", "get_uv2_offset"); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "uv2_triplanar"), "set_flag", "get_flag", FLAG_UV2_USE_TRIPLANAR); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "uv2_triplanar_sharpness", PROPERTY_HINT_EXP_EASING), "set_uv2_triplanar_blend_sharpness", "get_uv2_triplanar_blend_sharpness"); - - ADD_GROUP("Proximity Fade", "proximity_fade_"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "proximity_fade_enable"), "set_proximity_fade", "is_proximity_fade_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "proximity_fade_distance", PROPERTY_HINT_RANGE, "0,4096,0.01"), "set_proximity_fade_distance", "get_proximity_fade_distance"); - ADD_GROUP("Distance Fade", "distance_fade_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "distance_fade_mode", PROPERTY_HINT_ENUM, "Disabled,PixelAlpha,PixelDither,ObjectDither"), "set_distance_fade", "get_distance_fade"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "distance_fade_min_distance", PROPERTY_HINT_RANGE, "0,4096,0.01"), "set_distance_fade_min_distance", "get_distance_fade_min_distance"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "distance_fade_max_distance", PROPERTY_HINT_RANGE, "0,4096,0.01"), "set_distance_fade_max_distance", "get_distance_fade_max_distance"); - - ADD_PROPERTY(PropertyInfo(Variant::INT, "async_mode", PROPERTY_HINT_ENUM, "Visible,Hidden"), "set_async_mode", "get_async_mode"); - - BIND_ENUM_CONSTANT(TEXTURE_ALBEDO); - BIND_ENUM_CONSTANT(TEXTURE_METALLIC); - BIND_ENUM_CONSTANT(TEXTURE_ROUGHNESS); - BIND_ENUM_CONSTANT(TEXTURE_EMISSION); - BIND_ENUM_CONSTANT(TEXTURE_NORMAL); - BIND_ENUM_CONSTANT(TEXTURE_RIM); - BIND_ENUM_CONSTANT(TEXTURE_CLEARCOAT); - BIND_ENUM_CONSTANT(TEXTURE_FLOWMAP); - BIND_ENUM_CONSTANT(TEXTURE_AMBIENT_OCCLUSION); - BIND_ENUM_CONSTANT(TEXTURE_DEPTH); - BIND_ENUM_CONSTANT(TEXTURE_SUBSURFACE_SCATTERING); - BIND_ENUM_CONSTANT(TEXTURE_TRANSMISSION); - BIND_ENUM_CONSTANT(TEXTURE_REFRACTION); - BIND_ENUM_CONSTANT(TEXTURE_DETAIL_MASK); - BIND_ENUM_CONSTANT(TEXTURE_DETAIL_ALBEDO); - BIND_ENUM_CONSTANT(TEXTURE_DETAIL_NORMAL); - BIND_ENUM_CONSTANT(TEXTURE_MAX); - - BIND_ENUM_CONSTANT(DETAIL_UV_1); - BIND_ENUM_CONSTANT(DETAIL_UV_2); - - BIND_ENUM_CONSTANT(FEATURE_TRANSPARENT); - BIND_ENUM_CONSTANT(FEATURE_EMISSION); - BIND_ENUM_CONSTANT(FEATURE_NORMAL_MAPPING); - BIND_ENUM_CONSTANT(FEATURE_RIM); - BIND_ENUM_CONSTANT(FEATURE_CLEARCOAT); - BIND_ENUM_CONSTANT(FEATURE_ANISOTROPY); - BIND_ENUM_CONSTANT(FEATURE_AMBIENT_OCCLUSION); - BIND_ENUM_CONSTANT(FEATURE_DEPTH_MAPPING); - BIND_ENUM_CONSTANT(FEATURE_SUBSURACE_SCATTERING); - BIND_ENUM_CONSTANT(FEATURE_TRANSMISSION); - BIND_ENUM_CONSTANT(FEATURE_REFRACTION); - BIND_ENUM_CONSTANT(FEATURE_DETAIL); - BIND_ENUM_CONSTANT(FEATURE_MAX); - - BIND_ENUM_CONSTANT(BLEND_MODE_MIX); - BIND_ENUM_CONSTANT(BLEND_MODE_ADD); - BIND_ENUM_CONSTANT(BLEND_MODE_SUB); - BIND_ENUM_CONSTANT(BLEND_MODE_MUL); - - BIND_ENUM_CONSTANT(DEPTH_DRAW_OPAQUE_ONLY); - BIND_ENUM_CONSTANT(DEPTH_DRAW_ALWAYS); - BIND_ENUM_CONSTANT(DEPTH_DRAW_DISABLED); - BIND_ENUM_CONSTANT(DEPTH_DRAW_ALPHA_OPAQUE_PREPASS); - - BIND_ENUM_CONSTANT(CULL_BACK); - BIND_ENUM_CONSTANT(CULL_FRONT); - BIND_ENUM_CONSTANT(CULL_DISABLED); - - BIND_ENUM_CONSTANT(FLAG_UNSHADED); - BIND_ENUM_CONSTANT(FLAG_USE_VERTEX_LIGHTING); - BIND_ENUM_CONSTANT(FLAG_DISABLE_DEPTH_TEST); - BIND_ENUM_CONSTANT(FLAG_ALBEDO_FROM_VERTEX_COLOR); - BIND_ENUM_CONSTANT(FLAG_SRGB_VERTEX_COLOR); - BIND_ENUM_CONSTANT(FLAG_USE_POINT_SIZE); - BIND_ENUM_CONSTANT(FLAG_FIXED_SIZE); - BIND_ENUM_CONSTANT(FLAG_BILLBOARD_KEEP_SCALE); - BIND_ENUM_CONSTANT(FLAG_UV1_USE_TRIPLANAR); - BIND_ENUM_CONSTANT(FLAG_UV2_USE_TRIPLANAR); - BIND_ENUM_CONSTANT(FLAG_AO_ON_UV2); - BIND_ENUM_CONSTANT(FLAG_EMISSION_ON_UV2); - BIND_ENUM_CONSTANT(FLAG_USE_ALPHA_SCISSOR); - BIND_ENUM_CONSTANT(FLAG_TRIPLANAR_USE_WORLD); - BIND_ENUM_CONSTANT(FLAG_ALBEDO_TEXTURE_FORCE_SRGB); - BIND_ENUM_CONSTANT(FLAG_DONT_RECEIVE_SHADOWS); - BIND_ENUM_CONSTANT(FLAG_DISABLE_AMBIENT_LIGHT); - BIND_ENUM_CONSTANT(FLAG_ENSURE_CORRECT_NORMALS); - BIND_ENUM_CONSTANT(FLAG_USE_SHADOW_TO_OPACITY); - BIND_ENUM_CONSTANT(FLAG_ALBEDO_TEXTURE_SDF); - BIND_ENUM_CONSTANT(FLAG_MAX); - - BIND_ENUM_CONSTANT(DIFFUSE_BURLEY); - BIND_ENUM_CONSTANT(DIFFUSE_LAMBERT); - BIND_ENUM_CONSTANT(DIFFUSE_LAMBERT_WRAP); - BIND_ENUM_CONSTANT(DIFFUSE_OREN_NAYAR); - BIND_ENUM_CONSTANT(DIFFUSE_TOON); - - BIND_ENUM_CONSTANT(SPECULAR_SCHLICK_GGX); - BIND_ENUM_CONSTANT(SPECULAR_BLINN); - BIND_ENUM_CONSTANT(SPECULAR_PHONG); - BIND_ENUM_CONSTANT(SPECULAR_TOON); - BIND_ENUM_CONSTANT(SPECULAR_DISABLED); - - BIND_ENUM_CONSTANT(BILLBOARD_DISABLED); - BIND_ENUM_CONSTANT(BILLBOARD_ENABLED); - BIND_ENUM_CONSTANT(BILLBOARD_FIXED_Y); - BIND_ENUM_CONSTANT(BILLBOARD_PARTICLES); - - BIND_ENUM_CONSTANT(TEXTURE_CHANNEL_RED); - BIND_ENUM_CONSTANT(TEXTURE_CHANNEL_GREEN); - BIND_ENUM_CONSTANT(TEXTURE_CHANNEL_BLUE); - BIND_ENUM_CONSTANT(TEXTURE_CHANNEL_ALPHA); - BIND_ENUM_CONSTANT(TEXTURE_CHANNEL_GRAYSCALE); - - BIND_ENUM_CONSTANT(EMISSION_OP_ADD); - BIND_ENUM_CONSTANT(EMISSION_OP_MULTIPLY); - - BIND_ENUM_CONSTANT(DISTANCE_FADE_DISABLED); - BIND_ENUM_CONSTANT(DISTANCE_FADE_PIXEL_ALPHA); - BIND_ENUM_CONSTANT(DISTANCE_FADE_PIXEL_DITHER); - BIND_ENUM_CONSTANT(DISTANCE_FADE_OBJECT_DITHER); - - BIND_ENUM_CONSTANT(ASYNC_MODE_VISIBLE); - BIND_ENUM_CONSTANT(ASYNC_MODE_HIDDEN); -} - -SpatialMaterial::SpatialMaterial() : - element(this) { - // Initialize to the same values as the shader - set_albedo(Color(1.0, 1.0, 1.0, 1.0)); - set_specular(0.5); - set_roughness(1.0); - set_metallic(0.0); - set_emission(Color(0, 0, 0)); - set_emission_energy(1.0); - set_normal_scale(1); - set_rim(1.0); - set_rim_tint(0.5); - set_clearcoat(1); - set_clearcoat_gloss(0.5); - set_anisotropy(0); - set_depth_scale(0.05); - set_subsurface_scattering_strength(0); - set_transmission(Color(0, 0, 0)); - set_refraction(0.05); - set_line_width(1); - set_point_size(1); - set_uv1_offset(Vector3(0, 0, 0)); - set_uv1_scale(Vector3(1, 1, 1)); - set_uv1_triplanar_blend_sharpness(1); - set_uv2_offset(Vector3(0, 0, 0)); - set_uv2_scale(Vector3(1, 1, 1)); - set_uv2_triplanar_blend_sharpness(1); - set_billboard_mode(BILLBOARD_DISABLED); - set_particles_anim_h_frames(1); - set_particles_anim_v_frames(1); - set_particles_anim_loop(false); - set_alpha_scissor_threshold(0.98); - emission_op = EMISSION_OP_ADD; - - proximity_fade_enabled = false; - distance_fade = DISTANCE_FADE_DISABLED; - set_proximity_fade_distance(1); - set_distance_fade_min_distance(0); - set_distance_fade_max_distance(10); - - set_ao_light_affect(0.0); - - set_metallic_texture_channel(TEXTURE_CHANNEL_RED); - set_roughness_texture_channel(TEXTURE_CHANNEL_RED); - set_ao_texture_channel(TEXTURE_CHANNEL_RED); - set_refraction_texture_channel(TEXTURE_CHANNEL_RED); - - grow_enabled = false; - set_grow(0.0); - - deep_parallax = false; - depth_parallax_flip_tangent = false; - depth_parallax_flip_binormal = false; - set_depth_deep_parallax_min_layers(8); - set_depth_deep_parallax_max_layers(32); - set_depth_deep_parallax_flip_tangent(false); //also sets binormal - - detail_uv = DETAIL_UV_1; - blend_mode = BLEND_MODE_MIX; - detail_blend_mode = BLEND_MODE_MIX; - depth_draw_mode = DEPTH_DRAW_OPAQUE_ONLY; - cull_mode = CULL_BACK; - for (int i = 0; i < FLAG_MAX; i++) { - flags[i] = false; - } - - force_vertex_shading = GLOBAL_GET("rendering/quality/shading/force_vertex_shading"); - - diffuse_mode = DIFFUSE_BURLEY; - specular_mode = SPECULAR_SCHLICK_GGX; - - async_mode = ASYNC_MODE_VISIBLE; - - for (int i = 0; i < FEATURE_MAX; i++) { - features[i] = false; - } - - current_key.key = 0; - current_key.invalid_key = 1; - is_initialized = true; - _queue_shader_change(); -} - -SpatialMaterial::~SpatialMaterial() { - material_mutex.lock(); - - if (shader_map.has(current_key)) { - shader_map[current_key].users--; - if (shader_map[current_key].users == 0) { - //deallocate shader, as it's no longer in use - RS::get_singleton()->free(shader_map[current_key].shader); - shader_map.erase(current_key); - } - - RS::get_singleton()->material_set_shader(_get_material(), RID()); - } - - material_mutex.unlock(); -} diff --git a/scene/resources/material/material.h b/scene/resources/material/material.h index 3543d99f5..849696b27 100644 --- a/scene/resources/material/material.h +++ b/scene/resources/material/material.h @@ -35,8 +35,6 @@ #include "scene/resources/shader.h" #include "core/servers/rendering/rendering_server.h" -class Texture; - class Material : public Resource { GDCLASS(Material, Resource); RES_BASE_EXTENSION("material") @@ -71,594 +69,4 @@ public: virtual ~Material(); }; -class ShaderMaterial : public Material { - GDCLASS(ShaderMaterial, Material); - Ref shader; - -protected: - bool _set(const StringName &p_name, const Variant &p_value); - bool _get(const StringName &p_name, Variant &r_ret) const; - void _get_property_list(List *p_list) const; - bool property_can_revert(const String &p_name); - Variant property_get_revert(const String &p_name); - - static void _bind_methods(); - - void get_argument_options(const StringName &p_function, int p_idx, List *r_options, const String "e_style) const; - - virtual bool _can_do_next_pass() const; - - void _shader_changed(); - -public: - void set_shader(const Ref &p_shader); - Ref get_shader() const; - - void set_shader_param(const StringName &p_param, const Variant &p_value); - Variant get_shader_param(const StringName &p_param) const; - - virtual Shader::Mode get_shader_mode() const; - - ShaderMaterial(); - ~ShaderMaterial(); -}; - -class SpatialMaterial : public Material { - GDCLASS(SpatialMaterial, Material); - -public: - enum TextureParam { - TEXTURE_ALBEDO, - TEXTURE_METALLIC, - TEXTURE_ROUGHNESS, - TEXTURE_EMISSION, - TEXTURE_NORMAL, - TEXTURE_RIM, - TEXTURE_CLEARCOAT, - TEXTURE_FLOWMAP, - TEXTURE_AMBIENT_OCCLUSION, - TEXTURE_DEPTH, - TEXTURE_SUBSURFACE_SCATTERING, - TEXTURE_TRANSMISSION, - TEXTURE_REFRACTION, - TEXTURE_DETAIL_MASK, - TEXTURE_DETAIL_ALBEDO, - TEXTURE_DETAIL_NORMAL, - TEXTURE_MAX - - }; - - enum DetailUV { - DETAIL_UV_1, - DETAIL_UV_2 - }; - - enum Feature { - FEATURE_TRANSPARENT, - FEATURE_EMISSION, - FEATURE_NORMAL_MAPPING, - FEATURE_RIM, - FEATURE_CLEARCOAT, - FEATURE_ANISOTROPY, - FEATURE_AMBIENT_OCCLUSION, - FEATURE_DEPTH_MAPPING, - FEATURE_SUBSURACE_SCATTERING, - FEATURE_TRANSMISSION, - FEATURE_REFRACTION, - FEATURE_DETAIL, - FEATURE_MAX - }; - - enum BlendMode { - BLEND_MODE_MIX, - BLEND_MODE_ADD, - BLEND_MODE_SUB, - BLEND_MODE_MUL, - }; - - enum DepthDrawMode { - DEPTH_DRAW_OPAQUE_ONLY, - DEPTH_DRAW_ALWAYS, - DEPTH_DRAW_DISABLED, - DEPTH_DRAW_ALPHA_OPAQUE_PREPASS - - }; - - enum CullMode { - CULL_BACK, - CULL_FRONT, - CULL_DISABLED - }; - - enum Flags { - FLAG_UNSHADED, - FLAG_USE_VERTEX_LIGHTING, - FLAG_DISABLE_DEPTH_TEST, - FLAG_ALBEDO_FROM_VERTEX_COLOR, - FLAG_SRGB_VERTEX_COLOR, - FLAG_USE_POINT_SIZE, - FLAG_FIXED_SIZE, - FLAG_BILLBOARD_KEEP_SCALE, - FLAG_UV1_USE_TRIPLANAR, - FLAG_UV2_USE_TRIPLANAR, - FLAG_TRIPLANAR_USE_WORLD, - FLAG_AO_ON_UV2, - FLAG_EMISSION_ON_UV2, - FLAG_USE_ALPHA_SCISSOR, - FLAG_ALBEDO_TEXTURE_FORCE_SRGB, - FLAG_DONT_RECEIVE_SHADOWS, - FLAG_ENSURE_CORRECT_NORMALS, - FLAG_DISABLE_AMBIENT_LIGHT, - FLAG_USE_SHADOW_TO_OPACITY, - FLAG_ALBEDO_TEXTURE_SDF, - FLAG_MAX - }; - - enum DiffuseMode { - DIFFUSE_BURLEY, - DIFFUSE_LAMBERT, - DIFFUSE_LAMBERT_WRAP, - DIFFUSE_OREN_NAYAR, - DIFFUSE_TOON, - }; - - enum SpecularMode { - SPECULAR_SCHLICK_GGX, - SPECULAR_BLINN, - SPECULAR_PHONG, - SPECULAR_TOON, - SPECULAR_DISABLED, - }; - - enum BillboardMode { - BILLBOARD_DISABLED, - BILLBOARD_ENABLED, - BILLBOARD_FIXED_Y, - BILLBOARD_PARTICLES, - }; - - enum TextureChannel { - TEXTURE_CHANNEL_RED, - TEXTURE_CHANNEL_GREEN, - TEXTURE_CHANNEL_BLUE, - TEXTURE_CHANNEL_ALPHA, - TEXTURE_CHANNEL_GRAYSCALE - }; - - enum EmissionOperator { - EMISSION_OP_ADD, - EMISSION_OP_MULTIPLY - }; - - enum DistanceFadeMode { - DISTANCE_FADE_DISABLED, - DISTANCE_FADE_PIXEL_ALPHA, - DISTANCE_FADE_PIXEL_DITHER, - DISTANCE_FADE_OBJECT_DITHER, - }; - - enum AsyncMode { - ASYNC_MODE_VISIBLE, - ASYNC_MODE_HIDDEN, - }; - -private: - union MaterialKey { - struct { - uint64_t feature_mask : 12; - uint64_t detail_uv : 1; - uint64_t blend_mode : 2; - uint64_t depth_draw_mode : 2; - uint64_t cull_mode : 2; - uint64_t flags : 20; - uint64_t detail_blend_mode : 2; - uint64_t diffuse_mode : 3; - uint64_t specular_mode : 3; - uint64_t invalid_key : 1; - uint64_t deep_parallax : 1; - uint64_t billboard_mode : 2; - uint64_t grow : 1; - uint64_t proximity_fade : 1; - uint64_t distance_fade : 2; - uint64_t emission_op : 1; - uint64_t texture_metallic : 1; - uint64_t texture_roughness : 1; - //uint64_t reserved : 6; - }; - - uint64_t key; - - bool operator<(const MaterialKey &p_key) const { - return key < p_key.key; - } - }; - - struct ShaderData { - RID shader; - int users; - }; - - static RBMap shader_map; - - MaterialKey current_key; - - _FORCE_INLINE_ MaterialKey _compute_key() const { - MaterialKey mk; - mk.key = 0; - for (int i = 0; i < FEATURE_MAX; i++) { - if (features[i]) { - mk.feature_mask |= ((uint64_t)1 << i); - } - } - mk.detail_uv = detail_uv; - mk.blend_mode = blend_mode; - mk.depth_draw_mode = depth_draw_mode; - mk.cull_mode = cull_mode; - for (int i = 0; i < FLAG_MAX; i++) { - if (flags[i]) { - mk.flags |= ((uint64_t)1 << i); - } - } - mk.detail_blend_mode = detail_blend_mode; - mk.diffuse_mode = diffuse_mode; - mk.specular_mode = specular_mode; - mk.billboard_mode = billboard_mode; - mk.deep_parallax = deep_parallax ? 1 : 0; - mk.grow = grow_enabled; - mk.proximity_fade = proximity_fade_enabled; - mk.distance_fade = distance_fade; - mk.emission_op = emission_op; - mk.texture_metallic = textures[TEXTURE_METALLIC].is_valid() ? 1 : 0; - mk.texture_roughness = textures[TEXTURE_ROUGHNESS].is_valid() ? 1 : 0; - - return mk; - } - - struct ShaderNames { - StringName albedo; - StringName specular; - StringName metallic; - StringName roughness; - StringName emission; - StringName emission_energy; - StringName normal_scale; - StringName rim; - StringName rim_tint; - StringName clearcoat; - StringName clearcoat_gloss; - StringName anisotropy; - StringName depth_scale; - StringName subsurface_scattering_strength; - StringName transmission; - StringName refraction; - StringName point_size; - StringName uv1_scale; - StringName uv1_offset; - StringName uv2_scale; - StringName uv2_offset; - StringName particles_anim_h_frames; - StringName particles_anim_v_frames; - StringName particles_anim_loop; - StringName depth_min_layers; - StringName depth_max_layers; - StringName depth_flip; - StringName uv1_blend_sharpness; - StringName uv2_blend_sharpness; - StringName grow; - StringName proximity_fade_distance; - StringName distance_fade_min; - StringName distance_fade_max; - StringName ao_light_affect; - - StringName metallic_texture_channel; - StringName roughness_texture_channel; - StringName ao_texture_channel; - StringName clearcoat_texture_channel; - StringName rim_texture_channel; - StringName depth_texture_channel; - StringName refraction_texture_channel; - StringName alpha_scissor_threshold; - - StringName texture_names[TEXTURE_MAX]; - }; - - static Mutex material_mutex; - static SelfList::List *dirty_materials; - static ShaderNames *shader_names; - - SelfList element; - - void _update_shader(); - _FORCE_INLINE_ void _queue_shader_change(); - _FORCE_INLINE_ bool _is_shader_dirty() const; - - bool is_initialized = false; - Color albedo; - float specular; - float metallic; - float roughness; - Color emission; - float emission_energy; - float normal_scale; - float rim; - float rim_tint; - float clearcoat; - float clearcoat_gloss; - float anisotropy; - float depth_scale; - float subsurface_scattering_strength; - Color transmission; - float refraction; - float line_width; - float point_size; - float alpha_scissor_threshold; - bool grow_enabled; - float ao_light_affect; - float grow; - int particles_anim_h_frames; - int particles_anim_v_frames; - bool particles_anim_loop; - - Vector3 uv1_scale; - Vector3 uv1_offset; - float uv1_triplanar_sharpness; - - Vector3 uv2_scale; - Vector3 uv2_offset; - float uv2_triplanar_sharpness; - - DetailUV detail_uv; - - bool deep_parallax; - int deep_parallax_min_layers; - int deep_parallax_max_layers; - bool depth_parallax_flip_tangent; - bool depth_parallax_flip_binormal; - - bool proximity_fade_enabled; - float proximity_fade_distance; - - DistanceFadeMode distance_fade; - float distance_fade_max_distance; - float distance_fade_min_distance; - - BlendMode blend_mode; - BlendMode detail_blend_mode; - DepthDrawMode depth_draw_mode; - CullMode cull_mode; - bool flags[FLAG_MAX]; - SpecularMode specular_mode; - DiffuseMode diffuse_mode; - BillboardMode billboard_mode; - EmissionOperator emission_op; - AsyncMode async_mode; - - TextureChannel metallic_texture_channel; - TextureChannel roughness_texture_channel; - TextureChannel ao_texture_channel; - TextureChannel refraction_texture_channel; - - bool features[FEATURE_MAX]; - - Ref textures[TEXTURE_MAX]; - - bool force_vertex_shading = false; - - _FORCE_INLINE_ void _validate_feature(const String &text, Feature feature, PropertyInfo &property) const; - - static HashMap> materials_for_2d; //used by Sprite3D and other stuff - - void _validate_high_end(const String &text, PropertyInfo &property) const; - -protected: - static void _bind_methods(); - void _validate_property(PropertyInfo &property) const; - virtual bool _can_do_next_pass() const { return true; } - -public: - void set_albedo(const Color &p_albedo); - Color get_albedo() const; - - void set_specular(float p_specular); - float get_specular() const; - - void set_metallic(float p_metallic); - float get_metallic() const; - - void set_roughness(float p_roughness); - float get_roughness() const; - - void set_emission(const Color &p_emission); - Color get_emission() const; - - void set_emission_energy(float p_emission_energy); - float get_emission_energy() const; - - void set_normal_scale(float p_normal_scale); - float get_normal_scale() const; - - void set_rim(float p_rim); - float get_rim() const; - - void set_rim_tint(float p_rim_tint); - float get_rim_tint() const; - - void set_ao_light_affect(float p_ao_light_affect); - float get_ao_light_affect() const; - - void set_clearcoat(float p_clearcoat); - float get_clearcoat() const; - - void set_clearcoat_gloss(float p_clearcoat_gloss); - float get_clearcoat_gloss() const; - - void set_anisotropy(float p_anisotropy); - float get_anisotropy() const; - - void set_depth_scale(float p_depth_scale); - float get_depth_scale() const; - - void set_depth_deep_parallax(bool p_enable); - bool is_depth_deep_parallax_enabled() const; - - void set_depth_deep_parallax_min_layers(int p_layer); - int get_depth_deep_parallax_min_layers() const; - - void set_depth_deep_parallax_max_layers(int p_layer); - int get_depth_deep_parallax_max_layers() const; - - void set_depth_deep_parallax_flip_tangent(bool p_flip); - bool get_depth_deep_parallax_flip_tangent() const; - - void set_depth_deep_parallax_flip_binormal(bool p_flip); - bool get_depth_deep_parallax_flip_binormal() const; - - void set_subsurface_scattering_strength(float p_subsurface_scattering_strength); - float get_subsurface_scattering_strength() const; - - void set_transmission(const Color &p_transmission); - Color get_transmission() const; - - void set_refraction(float p_refraction); - float get_refraction() const; - - void set_line_width(float p_line_width); - float get_line_width() const; - - void set_point_size(float p_point_size); - float get_point_size() const; - - void set_detail_uv(DetailUV p_detail_uv); - DetailUV get_detail_uv() const; - - void set_blend_mode(BlendMode p_mode); - BlendMode get_blend_mode() const; - - void set_detail_blend_mode(BlendMode p_mode); - BlendMode get_detail_blend_mode() const; - - void set_depth_draw_mode(DepthDrawMode p_mode); - DepthDrawMode get_depth_draw_mode() const; - - void set_cull_mode(CullMode p_mode); - CullMode get_cull_mode() const; - - void set_diffuse_mode(DiffuseMode p_mode); - DiffuseMode get_diffuse_mode() const; - - void set_specular_mode(SpecularMode p_mode); - SpecularMode get_specular_mode() const; - - void set_flag(Flags p_flag, bool p_enabled); - bool get_flag(Flags p_flag) const; - - void set_texture(TextureParam p_param, const Ref &p_texture); - Ref get_texture(TextureParam p_param) const; - // Used only for shader material conversion - Ref get_texture_by_name(StringName p_name) const; - - void set_feature(Feature p_feature, bool p_enabled); - bool get_feature(Feature p_feature) const; - - void set_uv1_scale(const Vector3 &p_scale); - Vector3 get_uv1_scale() const; - - void set_uv1_offset(const Vector3 &p_offset); - Vector3 get_uv1_offset() const; - - void set_uv1_triplanar_blend_sharpness(float p_sharpness); - float get_uv1_triplanar_blend_sharpness() const; - - void set_uv2_scale(const Vector3 &p_scale); - Vector3 get_uv2_scale() const; - - void set_uv2_offset(const Vector3 &p_offset); - Vector3 get_uv2_offset() const; - - void set_uv2_triplanar_blend_sharpness(float p_sharpness); - float get_uv2_triplanar_blend_sharpness() const; - - void set_billboard_mode(BillboardMode p_mode); - BillboardMode get_billboard_mode() const; - - void set_particles_anim_h_frames(int p_frames); - int get_particles_anim_h_frames() const; - void set_particles_anim_v_frames(int p_frames); - int get_particles_anim_v_frames() const; - - void set_particles_anim_loop(bool p_loop); - bool get_particles_anim_loop() const; - - void set_grow_enabled(bool p_enable); - bool is_grow_enabled() const; - - void set_grow(float p_grow); - float get_grow() const; - - void set_alpha_scissor_threshold(float p_threshold); - float get_alpha_scissor_threshold() const; - - void set_on_top_of_alpha(); - - void set_proximity_fade(bool p_enable); - bool is_proximity_fade_enabled() const; - - void set_proximity_fade_distance(float p_distance); - float get_proximity_fade_distance() const; - - void set_distance_fade(DistanceFadeMode p_mode); - DistanceFadeMode get_distance_fade() const; - - void set_distance_fade_max_distance(float p_distance); - float get_distance_fade_max_distance() const; - - void set_distance_fade_min_distance(float p_distance); - float get_distance_fade_min_distance() const; - - void set_emission_operator(EmissionOperator p_op); - EmissionOperator get_emission_operator() const; - - void set_metallic_texture_channel(TextureChannel p_channel); - TextureChannel get_metallic_texture_channel() const; - void set_roughness_texture_channel(TextureChannel p_channel); - TextureChannel get_roughness_texture_channel() const; - void set_ao_texture_channel(TextureChannel p_channel); - TextureChannel get_ao_texture_channel() const; - void set_refraction_texture_channel(TextureChannel p_channel); - TextureChannel get_refraction_texture_channel() const; - - void set_async_mode(AsyncMode p_mode); - AsyncMode get_async_mode() const; - - static void init_shaders(); - static void finish_shaders(); - static void flush_changes(); - - static RID get_material_rid_for_2d(bool p_shaded, bool p_transparent, bool p_double_sided, bool p_cut_alpha, bool p_opaque_prepass, bool p_billboard = false, bool p_billboard_y = false, bool p_no_depth_test = false, bool p_fixed_size = false, bool p_sdf = false); - - RID get_shader_rid() const; - - virtual Shader::Mode get_shader_mode() const; - - SpatialMaterial(); - virtual ~SpatialMaterial(); -}; - -VARIANT_ENUM_CAST(SpatialMaterial::TextureParam) -VARIANT_ENUM_CAST(SpatialMaterial::DetailUV) -VARIANT_ENUM_CAST(SpatialMaterial::Feature) -VARIANT_ENUM_CAST(SpatialMaterial::BlendMode) -VARIANT_ENUM_CAST(SpatialMaterial::DepthDrawMode) -VARIANT_ENUM_CAST(SpatialMaterial::CullMode) -VARIANT_ENUM_CAST(SpatialMaterial::Flags) -VARIANT_ENUM_CAST(SpatialMaterial::DiffuseMode) -VARIANT_ENUM_CAST(SpatialMaterial::SpecularMode) -VARIANT_ENUM_CAST(SpatialMaterial::BillboardMode) -VARIANT_ENUM_CAST(SpatialMaterial::TextureChannel) -VARIANT_ENUM_CAST(SpatialMaterial::EmissionOperator) -VARIANT_ENUM_CAST(SpatialMaterial::DistanceFadeMode) -VARIANT_ENUM_CAST(SpatialMaterial::AsyncMode) - -////////////////////// - #endif diff --git a/scene/resources/material/shader_material.cpp b/scene/resources/material/shader_material.cpp new file mode 100644 index 000000000..e21879c30 --- /dev/null +++ b/scene/resources/material/shader_material.cpp @@ -0,0 +1,196 @@ +/*************************************************************************/ +/* material.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "shader_material.h" + +#include "core/config/engine.h" +#include "core/config/project_settings.h" +#include "core/version.h" +#include "scene/resources/texture.h" +#include "servers/rendering/shader_language.h" + +#include "scene/main/scene_string_names.h" + +bool ShaderMaterial::_set(const StringName &p_name, const Variant &p_value) { + if (shader.is_valid()) { + StringName pr = shader->remap_param(p_name); + if (!pr) { + String n = p_name; + if (n.find("param/") == 0) { //backwards compatibility + pr = n.substr(6, n.length()); + } + if (n.find("shader_param/") == 0) { //backwards compatibility + pr = n.replace_first("shader_param/", ""); + } + } + if (pr) { + RenderingServer::get_singleton()->material_set_param(_get_material(), pr, p_value); + return true; + } + } + + return false; +} + +bool ShaderMaterial::_get(const StringName &p_name, Variant &r_ret) const { + if (shader.is_valid()) { + StringName pr = shader->remap_param(p_name); + if (!pr) { + String n = p_name; + if (n.find("param/") == 0) { //backwards compatibility + pr = n.substr(6, n.length()); + } + if (n.find("shader_param/") == 0) { //backwards compatibility + pr = n.replace_first("shader_param/", ""); + } + } + + if (pr) { + r_ret = RenderingServer::get_singleton()->material_get_param(_get_material(), pr); + return true; + } + } + + return false; +} + +void ShaderMaterial::_get_property_list(List *p_list) const { + if (!shader.is_null()) { + shader->get_param_list(p_list); + } +} + +bool ShaderMaterial::property_can_revert(const String &p_name) { + if (shader.is_valid()) { + StringName pr = shader->remap_param(p_name); + if (pr) { + Variant default_value = RenderingServer::get_singleton()->material_get_param_default(_get_material(), pr); + Variant current_value; + _get(p_name, current_value); + return default_value.get_type() != Variant::NIL && default_value != current_value; + } + } + return false; +} + +Variant ShaderMaterial::property_get_revert(const String &p_name) { + Variant r_ret; + if (shader.is_valid()) { + StringName pr = shader->remap_param(p_name); + if (pr) { + r_ret = RenderingServer::get_singleton()->material_get_param_default(_get_material(), pr); + } + } + return r_ret; +} + +void ShaderMaterial::set_shader(const Ref &p_shader) { + // Only connect/disconnect the signal when running in the editor. + // This can be a slow operation, and `_change_notify()` (which is called by `_shader_changed()`) + // does nothing in non-editor builds anyway. See GH-34741 for details. + if (shader.is_valid() && Engine::get_singleton()->is_editor_hint()) { + shader->disconnect("changed", this, "_shader_changed"); + } + + shader = p_shader; + + RID rid; + if (shader.is_valid()) { + rid = shader->get_rid(); + + if (Engine::get_singleton()->is_editor_hint()) { + shader->connect("changed", this, "_shader_changed"); + } + } + + RS::get_singleton()->material_set_shader(_get_material(), rid); + _change_notify(); //properties for shader exposed + emit_changed(); +} + +Ref ShaderMaterial::get_shader() const { + return shader; +} + +void ShaderMaterial::set_shader_param(const StringName &p_param, const Variant &p_value) { + RS::get_singleton()->material_set_param(_get_material(), p_param, p_value); +} + +Variant ShaderMaterial::get_shader_param(const StringName &p_param) const { + return RS::get_singleton()->material_get_param(_get_material(), p_param); +} + +void ShaderMaterial::_shader_changed() { + _change_notify(); //update all properties +} + +void ShaderMaterial::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_shader", "shader"), &ShaderMaterial::set_shader); + ClassDB::bind_method(D_METHOD("get_shader"), &ShaderMaterial::get_shader); + ClassDB::bind_method(D_METHOD("set_shader_param", "param", "value"), &ShaderMaterial::set_shader_param); + ClassDB::bind_method(D_METHOD("get_shader_param", "param"), &ShaderMaterial::get_shader_param); + ClassDB::bind_method(D_METHOD("_shader_changed"), &ShaderMaterial::_shader_changed); + ClassDB::bind_method(D_METHOD("property_can_revert", "name"), &ShaderMaterial::property_can_revert); + ClassDB::bind_method(D_METHOD("property_get_revert", "name"), &ShaderMaterial::property_get_revert); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shader", PROPERTY_HINT_RESOURCE_TYPE, "Shader"), "set_shader", "get_shader"); +} + +void ShaderMaterial::get_argument_options(const StringName &p_function, int p_idx, List *r_options, const String "e_style) const { + String f = p_function.operator String(); + if ((f == "get_shader_param" || f == "set_shader_param") && p_idx == 0) { + if (shader.is_valid()) { + List pl; + shader->get_param_list(&pl); + for (List::Element *E = pl.front(); E; E = E->next()) { + r_options->push_back(quote_style + E->get().name.replace_first("shader_param/", "") + quote_style); + } + } + } + Resource::get_argument_options(p_function, p_idx, r_options, quote_style); +} + +bool ShaderMaterial::_can_do_next_pass() const { + return shader.is_valid() && shader->get_mode() == Shader::MODE_SPATIAL; +} + +Shader::Mode ShaderMaterial::get_shader_mode() const { + if (shader.is_valid()) { + return shader->get_mode(); + } else { + return Shader::MODE_SPATIAL; + } +} + +ShaderMaterial::ShaderMaterial() { +} + +ShaderMaterial::~ShaderMaterial() { +} diff --git a/scene/resources/material/shader_material.h b/scene/resources/material/shader_material.h new file mode 100644 index 000000000..95c25bfdf --- /dev/null +++ b/scene/resources/material/shader_material.h @@ -0,0 +1,76 @@ +#ifndef SHADER_MATERIAL_H +#define SHADER_MATERIAL_H + +/*************************************************************************/ +/* material.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "core/object/resource.h" +#include "core/containers/self_list.h" + +#include "scene/resources/material/material.h" + +#include "scene/resources/shader.h" +#include "core/servers/rendering/rendering_server.h" + +class Texture; + +class ShaderMaterial : public Material { + GDCLASS(ShaderMaterial, Material); + Ref shader; + +protected: + bool _set(const StringName &p_name, const Variant &p_value); + bool _get(const StringName &p_name, Variant &r_ret) const; + void _get_property_list(List *p_list) const; + bool property_can_revert(const String &p_name); + Variant property_get_revert(const String &p_name); + + static void _bind_methods(); + + void get_argument_options(const StringName &p_function, int p_idx, List *r_options, const String "e_style) const; + + virtual bool _can_do_next_pass() const; + + void _shader_changed(); + +public: + void set_shader(const Ref &p_shader); + Ref get_shader() const; + + void set_shader_param(const StringName &p_param, const Variant &p_value); + Variant get_shader_param(const StringName &p_param) const; + + virtual Shader::Mode get_shader_mode() const; + + ShaderMaterial(); + ~ShaderMaterial(); +}; + +#endif diff --git a/scene/resources/material/spatial_material.cpp b/scene/resources/material/spatial_material.cpp new file mode 100644 index 000000000..afd27e697 --- /dev/null +++ b/scene/resources/material/spatial_material.cpp @@ -0,0 +1,2167 @@ +/*************************************************************************/ +/* material.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "spatial_material.h" + +#include "core/config/engine.h" +#include "core/config/project_settings.h" +#include "core/version.h" +#include "scene/resources/texture.h" +#include "servers/rendering/shader_language.h" + +#include "scene/main/scene_string_names.h" + +Mutex SpatialMaterial::material_mutex; +SelfList::List *SpatialMaterial::dirty_materials = nullptr; +RBMap SpatialMaterial::shader_map; +SpatialMaterial::ShaderNames *SpatialMaterial::shader_names = nullptr; + +void SpatialMaterial::init_shaders() { + dirty_materials = memnew(SelfList::List); + + shader_names = memnew(ShaderNames); + + shader_names->albedo = "albedo"; + shader_names->specular = "specular"; + shader_names->roughness = "roughness"; + shader_names->metallic = "metallic"; + shader_names->emission = "emission"; + shader_names->emission_energy = "emission_energy"; + shader_names->normal_scale = "normal_scale"; + shader_names->rim = "rim"; + shader_names->rim_tint = "rim_tint"; + shader_names->clearcoat = "clearcoat"; + shader_names->clearcoat_gloss = "clearcoat_gloss"; + shader_names->anisotropy = "anisotropy_ratio"; + shader_names->depth_scale = "depth_scale"; + shader_names->subsurface_scattering_strength = "subsurface_scattering_strength"; + shader_names->transmission = "transmission"; + shader_names->refraction = "refraction"; + shader_names->point_size = "point_size"; + shader_names->uv1_scale = "uv1_scale"; + shader_names->uv1_offset = "uv1_offset"; + shader_names->uv2_scale = "uv2_scale"; + shader_names->uv2_offset = "uv2_offset"; + shader_names->uv1_blend_sharpness = "uv1_blend_sharpness"; + shader_names->uv2_blend_sharpness = "uv2_blend_sharpness"; + + shader_names->particles_anim_h_frames = "particles_anim_h_frames"; + shader_names->particles_anim_v_frames = "particles_anim_v_frames"; + shader_names->particles_anim_loop = "particles_anim_loop"; + shader_names->depth_min_layers = "depth_min_layers"; + shader_names->depth_max_layers = "depth_max_layers"; + shader_names->depth_flip = "depth_flip"; + + shader_names->grow = "grow"; + + shader_names->ao_light_affect = "ao_light_affect"; + + shader_names->proximity_fade_distance = "proximity_fade_distance"; + shader_names->distance_fade_min = "distance_fade_min"; + shader_names->distance_fade_max = "distance_fade_max"; + + shader_names->metallic_texture_channel = "metallic_texture_channel"; + shader_names->roughness_texture_channel = "roughness_texture_channel"; + shader_names->ao_texture_channel = "ao_texture_channel"; + shader_names->clearcoat_texture_channel = "clearcoat_texture_channel"; + shader_names->rim_texture_channel = "rim_texture_channel"; + shader_names->depth_texture_channel = "depth_texture_channel"; + shader_names->refraction_texture_channel = "refraction_texture_channel"; + shader_names->alpha_scissor_threshold = "alpha_scissor_threshold"; + + shader_names->texture_names[TEXTURE_ALBEDO] = "texture_albedo"; + shader_names->texture_names[TEXTURE_METALLIC] = "texture_metallic"; + shader_names->texture_names[TEXTURE_ROUGHNESS] = "texture_roughness"; + shader_names->texture_names[TEXTURE_EMISSION] = "texture_emission"; + shader_names->texture_names[TEXTURE_NORMAL] = "texture_normal"; + shader_names->texture_names[TEXTURE_RIM] = "texture_rim"; + shader_names->texture_names[TEXTURE_CLEARCOAT] = "texture_clearcoat"; + shader_names->texture_names[TEXTURE_FLOWMAP] = "texture_flowmap"; + shader_names->texture_names[TEXTURE_AMBIENT_OCCLUSION] = "texture_ambient_occlusion"; + shader_names->texture_names[TEXTURE_DEPTH] = "texture_depth"; + shader_names->texture_names[TEXTURE_SUBSURFACE_SCATTERING] = "texture_subsurface_scattering"; + shader_names->texture_names[TEXTURE_TRANSMISSION] = "texture_transmission"; + shader_names->texture_names[TEXTURE_REFRACTION] = "texture_refraction"; + shader_names->texture_names[TEXTURE_DETAIL_MASK] = "texture_detail_mask"; + shader_names->texture_names[TEXTURE_DETAIL_ALBEDO] = "texture_detail_albedo"; + shader_names->texture_names[TEXTURE_DETAIL_NORMAL] = "texture_detail_normal"; +} + +HashMap> SpatialMaterial::materials_for_2d; + +void SpatialMaterial::finish_shaders() { + materials_for_2d.clear(); + + memdelete(dirty_materials); + dirty_materials = nullptr; + + memdelete(shader_names); +} + +void SpatialMaterial::_update_shader() { + dirty_materials->remove(&element); + + MaterialKey mk = _compute_key(); + if (mk.key == current_key.key) { + return; //no update required in the end + } + + if (shader_map.has(current_key)) { + shader_map[current_key].users--; + if (shader_map[current_key].users == 0) { + //deallocate shader, as it's no longer in use + RS::get_singleton()->free(shader_map[current_key].shader); + shader_map.erase(current_key); + } + } + + current_key = mk; + + if (shader_map.has(mk)) { + RS::get_singleton()->material_set_shader(_get_material(), shader_map[mk].shader); + shader_map[mk].users++; + return; + } + + //must create a shader! + + // Add a comment to describe the shader origin (useful when converting to ShaderMaterial). + String code = "// NOTE: Shader automatically converted from " VERSION_NAME " " VERSION_FULL_CONFIG "'s SpatialMaterial.\n\n"; + + code += "shader_type spatial;\nrender_mode "; + switch (blend_mode) { + case BLEND_MODE_MIX: + code += "blend_mix"; + break; + case BLEND_MODE_ADD: + code += "blend_add"; + break; + case BLEND_MODE_SUB: + code += "blend_sub"; + break; + case BLEND_MODE_MUL: + code += "blend_mul"; + break; + } + + DepthDrawMode ddm = depth_draw_mode; + if (features[FEATURE_REFRACTION]) { + ddm = DEPTH_DRAW_ALWAYS; + } + + switch (ddm) { + case DEPTH_DRAW_OPAQUE_ONLY: + code += ",depth_draw_opaque"; + break; + case DEPTH_DRAW_ALWAYS: + code += ",depth_draw_always"; + break; + case DEPTH_DRAW_DISABLED: + code += ",depth_draw_never"; + break; + case DEPTH_DRAW_ALPHA_OPAQUE_PREPASS: + code += ",depth_draw_alpha_prepass"; + break; + } + + switch (cull_mode) { + case CULL_BACK: + code += ",cull_back"; + break; + case CULL_FRONT: + code += ",cull_front"; + break; + case CULL_DISABLED: + code += ",cull_disabled"; + break; + } + switch (diffuse_mode) { + case DIFFUSE_BURLEY: + code += ",diffuse_burley"; + break; + case DIFFUSE_LAMBERT: + code += ",diffuse_lambert"; + break; + case DIFFUSE_LAMBERT_WRAP: + code += ",diffuse_lambert_wrap"; + break; + case DIFFUSE_OREN_NAYAR: + code += ",diffuse_oren_nayar"; + break; + case DIFFUSE_TOON: + code += ",diffuse_toon"; + break; + } + switch (specular_mode) { + case SPECULAR_SCHLICK_GGX: + code += ",specular_schlick_ggx"; + break; + case SPECULAR_BLINN: + code += ",specular_blinn"; + break; + case SPECULAR_PHONG: + code += ",specular_phong"; + break; + case SPECULAR_TOON: + code += ",specular_toon"; + break; + case SPECULAR_DISABLED: + code += ",specular_disabled"; + break; + } + + if (flags[FLAG_UNSHADED]) { + code += ",unshaded"; + } + if (flags[FLAG_DISABLE_DEPTH_TEST]) { + code += ",depth_test_disable"; + } + if (flags[FLAG_USE_VERTEX_LIGHTING] || force_vertex_shading) { + code += ",vertex_lighting"; + } + if (flags[FLAG_TRIPLANAR_USE_WORLD] && (flags[FLAG_UV1_USE_TRIPLANAR] || flags[FLAG_UV2_USE_TRIPLANAR])) { + code += ",world_vertex_coords"; + } + if (flags[FLAG_DONT_RECEIVE_SHADOWS]) { + code += ",shadows_disabled"; + } + if (flags[FLAG_DISABLE_AMBIENT_LIGHT]) { + code += ",ambient_light_disabled"; + } + if (flags[FLAG_ENSURE_CORRECT_NORMALS]) { + code += ",ensure_correct_normals"; + } + if (flags[FLAG_USE_SHADOW_TO_OPACITY]) { + code += ",shadow_to_opacity"; + } + code += ";\n"; + + code += "uniform vec4 albedo : hint_color;\n"; + code += "uniform sampler2D texture_albedo : hint_albedo;\n"; + code += "uniform float specular;\n"; + code += "uniform float metallic;\n"; + if (grow_enabled) { + code += "uniform float grow;\n"; + } + + if (proximity_fade_enabled) { + code += "uniform float proximity_fade_distance;\n"; + } + if (distance_fade != DISTANCE_FADE_DISABLED) { + code += "uniform float distance_fade_min;\n"; + code += "uniform float distance_fade_max;\n"; + } + + if (flags[FLAG_USE_ALPHA_SCISSOR]) { + code += "uniform float alpha_scissor_threshold;\n"; + } + code += "uniform float roughness : hint_range(0,1);\n"; + code += "uniform float point_size : hint_range(0,128);\n"; + + if (textures[TEXTURE_METALLIC] != nullptr) { + code += "uniform sampler2D texture_metallic : hint_white;\n"; + code += "uniform vec4 metallic_texture_channel;\n"; + } + + if (textures[TEXTURE_ROUGHNESS] != nullptr) { + code += "uniform sampler2D texture_roughness : hint_white;\n"; + code += "uniform vec4 roughness_texture_channel;\n"; + } + if (billboard_mode == BILLBOARD_PARTICLES) { + code += "uniform int particles_anim_h_frames;\n"; + code += "uniform int particles_anim_v_frames;\n"; + code += "uniform bool particles_anim_loop;\n"; + } + + if (features[FEATURE_EMISSION]) { + code += "uniform sampler2D texture_emission : hint_black_albedo;\n"; + code += "uniform vec4 emission : hint_color;\n"; + code += "uniform float emission_energy;\n"; + } + + if (features[FEATURE_REFRACTION]) { + code += "uniform sampler2D texture_refraction;\n"; + code += "uniform float refraction : hint_range(-16,16);\n"; + code += "uniform vec4 refraction_texture_channel;\n"; + } + + if (features[FEATURE_NORMAL_MAPPING]) { + code += "uniform sampler2D texture_normal : hint_normal;\n"; + code += "uniform float normal_scale : hint_range(-16,16);\n"; + } + if (features[FEATURE_RIM]) { + code += "uniform float rim : hint_range(0,1);\n"; + code += "uniform float rim_tint : hint_range(0,1);\n"; + code += "uniform sampler2D texture_rim : hint_white;\n"; + } + if (features[FEATURE_CLEARCOAT]) { + code += "uniform float clearcoat : hint_range(0,1);\n"; + code += "uniform float clearcoat_gloss : hint_range(0,1);\n"; + code += "uniform sampler2D texture_clearcoat : hint_white;\n"; + } + if (features[FEATURE_ANISOTROPY]) { + code += "uniform float anisotropy_ratio : hint_range(0,256);\n"; + code += "uniform sampler2D texture_flowmap : hint_aniso;\n"; + } + if (features[FEATURE_AMBIENT_OCCLUSION]) { + code += "uniform sampler2D texture_ambient_occlusion : hint_white;\n"; + code += "uniform vec4 ao_texture_channel;\n"; + code += "uniform float ao_light_affect;\n"; + } + + if (features[FEATURE_DETAIL]) { + code += "uniform sampler2D texture_detail_albedo : hint_albedo;\n"; + code += "uniform sampler2D texture_detail_normal : hint_normal;\n"; + code += "uniform sampler2D texture_detail_mask : hint_white;\n"; + } + + if (features[FEATURE_SUBSURACE_SCATTERING]) { + code += "uniform float subsurface_scattering_strength : hint_range(0,1);\n"; + code += "uniform sampler2D texture_subsurface_scattering : hint_white;\n"; + } + + if (features[FEATURE_TRANSMISSION]) { + code += "uniform vec4 transmission : hint_color;\n"; + code += "uniform sampler2D texture_transmission : hint_black;\n"; + } + + if (features[FEATURE_DEPTH_MAPPING]) { + code += "uniform sampler2D texture_depth : hint_black;\n"; + code += "uniform float depth_scale;\n"; + code += "uniform int depth_min_layers;\n"; + code += "uniform int depth_max_layers;\n"; + code += "uniform vec2 depth_flip;\n"; + } + if (flags[FLAG_UV1_USE_TRIPLANAR]) { + code += "varying vec3 uv1_triplanar_pos;\n"; + } + if (flags[FLAG_UV2_USE_TRIPLANAR]) { + code += "varying vec3 uv2_triplanar_pos;\n"; + } + if (flags[FLAG_UV1_USE_TRIPLANAR]) { + code += "uniform float uv1_blend_sharpness;\n"; + code += "varying vec3 uv1_power_normal;\n"; + } + + if (flags[FLAG_UV2_USE_TRIPLANAR]) { + code += "uniform float uv2_blend_sharpness;\n"; + code += "varying vec3 uv2_power_normal;\n"; + } + + code += "uniform vec3 uv1_scale;\n"; + code += "uniform vec3 uv1_offset;\n"; + code += "uniform vec3 uv2_scale;\n"; + code += "uniform vec3 uv2_offset;\n"; + + code += "\n\n"; + + code += "void vertex() {\n"; + + if (flags[FLAG_SRGB_VERTEX_COLOR]) { + code += "\tif (!OUTPUT_IS_SRGB) {\n"; + code += "\t\tCOLOR.rgb = mix(pow((COLOR.rgb + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)), COLOR.rgb * (1.0 / 12.92), lessThan(COLOR.rgb, vec3(0.04045)));\n"; + code += "\t}\n"; + } + if (flags[FLAG_USE_POINT_SIZE]) { + code += "\tPOINT_SIZE=point_size;\n"; + } + + if (flags[FLAG_USE_VERTEX_LIGHTING] || force_vertex_shading) { + code += "\tROUGHNESS=roughness;\n"; + } + + if (!flags[FLAG_UV1_USE_TRIPLANAR]) { + code += "\tUV=UV*uv1_scale.xy+uv1_offset.xy;\n"; + } + + switch (billboard_mode) { + case BILLBOARD_DISABLED: { + } break; + case BILLBOARD_ENABLED: { + code += "\tMODELVIEW_MATRIX = INV_CAMERA_MATRIX * mat4(CAMERA_MATRIX[0],CAMERA_MATRIX[1],CAMERA_MATRIX[2],WORLD_MATRIX[3]);\n"; + + if (flags[FLAG_BILLBOARD_KEEP_SCALE]) { + code += "\tMODELVIEW_MATRIX = MODELVIEW_MATRIX * mat4(vec4(length(WORLD_MATRIX[0].xyz), 0.0, 0.0, 0.0),vec4(0.0, length(WORLD_MATRIX[1].xyz), 0.0, 0.0),vec4(0.0, 0.0, length(WORLD_MATRIX[2].xyz), 0.0),vec4(0.0, 0.0, 0.0, 1.0));\n"; + } + } break; + case BILLBOARD_FIXED_Y: { + code += "\tMODELVIEW_MATRIX = INV_CAMERA_MATRIX * mat4(vec4(normalize(cross(vec3(0.0, 1.0, 0.0), CAMERA_MATRIX[2].xyz)),0.0),vec4(0.0, 1.0, 0.0, 0.0),vec4(normalize(cross(CAMERA_MATRIX[0].xyz, vec3(0.0, 1.0, 0.0))),0.0),WORLD_MATRIX[3]);\n"; + + if (flags[FLAG_BILLBOARD_KEEP_SCALE]) { + code += "\tMODELVIEW_MATRIX = MODELVIEW_MATRIX * mat4(vec4(length(WORLD_MATRIX[0].xyz), 0.0, 0.0, 0.0),vec4(0.0, length(WORLD_MATRIX[1].xyz), 0.0, 0.0),vec4(0.0, 0.0, length(WORLD_MATRIX[2].xyz), 0.0),vec4(0.0, 0.0, 0.0, 1.0));\n"; + } + } break; + case BILLBOARD_PARTICLES: { + //make billboard + code += "\tmat4 mat_world = mat4(normalize(CAMERA_MATRIX[0])*length(WORLD_MATRIX[0]),normalize(CAMERA_MATRIX[1])*length(WORLD_MATRIX[0]),normalize(CAMERA_MATRIX[2])*length(WORLD_MATRIX[2]),WORLD_MATRIX[3]);\n"; + //rotate by rotation + code += "\tmat_world = mat_world * mat4( vec4(cos(INSTANCE_CUSTOM.x),-sin(INSTANCE_CUSTOM.x), 0.0, 0.0), vec4(sin(INSTANCE_CUSTOM.x), cos(INSTANCE_CUSTOM.x), 0.0, 0.0),vec4(0.0, 0.0, 1.0, 0.0),vec4(0.0, 0.0, 0.0, 1.0));\n"; + //set modelview + code += "\tMODELVIEW_MATRIX = INV_CAMERA_MATRIX * mat_world;\n"; + + //handle animation + code += "\tfloat h_frames = float(particles_anim_h_frames);\n"; + code += "\tfloat v_frames = float(particles_anim_v_frames);\n"; + code += "\tfloat particle_total_frames = float(particles_anim_h_frames * particles_anim_v_frames);\n"; + code += "\tfloat particle_frame = floor(INSTANCE_CUSTOM.z * float(particle_total_frames));\n"; + code += "\tif (!particles_anim_loop) {\n"; + code += "\t\tparticle_frame = clamp(particle_frame, 0.0, particle_total_frames - 1.0);\n"; + code += "\t} else {\n"; + code += "\t\tparticle_frame = mod(particle_frame, particle_total_frames);\n"; + code += "\t}"; + code += "\tUV /= vec2(h_frames, v_frames);\n"; + code += "\tUV += vec2(mod(particle_frame, h_frames) / h_frames, floor((particle_frame + 0.5) / h_frames) / v_frames);\n"; + } break; + } + + if (flags[FLAG_FIXED_SIZE]) { + code += "\tif (PROJECTION_MATRIX[3][3] != 0.0) {\n"; + //orthogonal matrix, try to do about the same + //with viewport size + code += "\t\tfloat h = abs(1.0 / (2.0 * PROJECTION_MATRIX[1][1]));\n"; + code += "\t\tfloat sc = (h * 2.0); //consistent with Y-fov\n"; + code += "\t\tMODELVIEW_MATRIX[0]*=sc;\n"; + code += "\t\tMODELVIEW_MATRIX[1]*=sc;\n"; + code += "\t\tMODELVIEW_MATRIX[2]*=sc;\n"; + code += "\t} else {\n"; + //just scale by depth + code += "\t\tfloat sc = -(MODELVIEW_MATRIX)[3].z;\n"; + code += "\t\tMODELVIEW_MATRIX[0]*=sc;\n"; + code += "\t\tMODELVIEW_MATRIX[1]*=sc;\n"; + code += "\t\tMODELVIEW_MATRIX[2]*=sc;\n"; + code += "\t}\n"; + } + + if (detail_uv == DETAIL_UV_2 && !flags[FLAG_UV2_USE_TRIPLANAR]) { + code += "\tUV2=UV2*uv2_scale.xy+uv2_offset.xy;\n"; + } + if (flags[FLAG_UV1_USE_TRIPLANAR] || flags[FLAG_UV2_USE_TRIPLANAR]) { + //generate tangent and binormal in world space + code += "\tTANGENT = vec3(0.0,0.0,-1.0) * abs(NORMAL.x);\n"; + code += "\tTANGENT+= vec3(1.0,0.0,0.0) * abs(NORMAL.y);\n"; + code += "\tTANGENT+= vec3(1.0,0.0,0.0) * abs(NORMAL.z);\n"; + code += "\tTANGENT = normalize(TANGENT);\n"; + + code += "\tBINORMAL = vec3(0.0,1.0,0.0) * abs(NORMAL.x);\n"; + code += "\tBINORMAL+= vec3(0.0,0.0,-1.0) * abs(NORMAL.y);\n"; + code += "\tBINORMAL+= vec3(0.0,1.0,0.0) * abs(NORMAL.z);\n"; + code += "\tBINORMAL = normalize(BINORMAL);\n"; + } + + if (flags[FLAG_UV1_USE_TRIPLANAR]) { + code += "\tuv1_power_normal=pow(abs(NORMAL),vec3(uv1_blend_sharpness));\n"; + code += "\tuv1_power_normal/=dot(uv1_power_normal,vec3(1.0));\n"; + code += "\tuv1_triplanar_pos = VERTEX * uv1_scale + uv1_offset;\n"; + code += "\tuv1_triplanar_pos *= vec3(1.0,-1.0, 1.0);\n"; + } + + if (flags[FLAG_UV2_USE_TRIPLANAR]) { + code += "\tuv2_power_normal=pow(abs(NORMAL), vec3(uv2_blend_sharpness));\n"; + code += "\tuv2_power_normal/=dot(uv2_power_normal,vec3(1.0));\n"; + code += "\tuv2_triplanar_pos = VERTEX * uv2_scale + uv2_offset;\n"; + code += "\tuv2_triplanar_pos *= vec3(1.0,-1.0, 1.0);\n"; + } + + if (grow_enabled) { + code += "\tVERTEX+=NORMAL*grow;\n"; + } + + code += "}\n"; + code += "\n\n"; + if (flags[FLAG_UV1_USE_TRIPLANAR] || flags[FLAG_UV2_USE_TRIPLANAR]) { + code += "vec4 triplanar_texture(sampler2D p_sampler,vec3 p_weights,vec3 p_triplanar_pos) {\n"; + code += "\tvec4 samp=vec4(0.0);\n"; + code += "\tsamp+= texture(p_sampler,p_triplanar_pos.xy) * p_weights.z;\n"; + code += "\tsamp+= texture(p_sampler,p_triplanar_pos.xz) * p_weights.y;\n"; + code += "\tsamp+= texture(p_sampler,p_triplanar_pos.zy * vec2(-1.0,1.0)) * p_weights.x;\n"; + code += "\treturn samp;\n"; + code += "}\n"; + } + code += "\n\n"; + code += "void fragment() {\n"; + + if (!flags[FLAG_UV1_USE_TRIPLANAR]) { + code += "\tvec2 base_uv = UV;\n"; + } + + if ((features[FEATURE_DETAIL] && detail_uv == DETAIL_UV_2) || (features[FEATURE_AMBIENT_OCCLUSION] && flags[FLAG_AO_ON_UV2]) || (features[FEATURE_EMISSION] && flags[FLAG_EMISSION_ON_UV2])) { + code += "\tvec2 base_uv2 = UV2;\n"; + } + + if (features[FEATURE_DEPTH_MAPPING] && flags[FLAG_UV1_USE_TRIPLANAR]) { + // Display both resource name and albedo texture name. + // Materials are often built-in to scenes, so displaying the resource name alone may not be meaningful. + // On the other hand, albedo textures are almost always external to the scene. + if (textures[TEXTURE_ALBEDO].is_valid()) { + WARN_PRINT(vformat("%s (albedo %s): Depth mapping is not supported on triplanar materials. Ignoring depth mapping in favor of triplanar mapping.", get_path(), textures[TEXTURE_ALBEDO]->get_path())); + } else if (!get_path().empty()) { + WARN_PRINT(vformat("%s: Depth mapping is not supported on triplanar materials. Ignoring depth mapping in favor of triplanar mapping.", get_path())); + } else { + // Resource wasn't saved yet. + WARN_PRINT("Depth mapping is not supported on triplanar materials. Ignoring depth mapping in favor of triplanar mapping."); + } + } + + if (!RenderingServer::get_singleton()->is_low_end() && features[FEATURE_DEPTH_MAPPING] && !flags[FLAG_UV1_USE_TRIPLANAR]) { //depthmap not supported with triplanar + code += "\t{\n"; + code += "\t\tvec3 view_dir = normalize(normalize(-VERTEX)*mat3(TANGENT*depth_flip.x,-BINORMAL*depth_flip.y,NORMAL));\n"; // binormal is negative due to mikktspace, flip 'unflips' it ;-) + + if (deep_parallax) { + code += "\t\tfloat num_layers = mix(float(depth_max_layers),float(depth_min_layers), abs(dot(vec3(0.0, 0.0, 1.0), view_dir)));\n"; + code += "\t\tfloat layer_depth = 1.0 / num_layers;\n"; + code += "\t\tfloat current_layer_depth = 0.0;\n"; + code += "\t\tvec2 P = view_dir.xy * depth_scale;\n"; + code += "\t\tvec2 delta = P / num_layers;\n"; + code += "\t\tvec2 ofs = base_uv;\n"; + code += "\t\tfloat depth = textureLod(texture_depth, ofs, 0.0).r;\n"; + code += "\t\tfloat current_depth = 0.0;\n"; + code += "\t\twhile(current_depth < depth) {\n"; + code += "\t\t\tofs -= delta;\n"; + code += "\t\t\tdepth = textureLod(texture_depth, ofs, 0.0).r;\n"; + code += "\t\t\tcurrent_depth += layer_depth;\n"; + code += "\t\t}\n"; + code += "\t\tvec2 prev_ofs = ofs + delta;\n"; + code += "\t\tfloat after_depth = depth - current_depth;\n"; + code += "\t\tfloat before_depth = textureLod(texture_depth, prev_ofs, 0.0).r - current_depth + layer_depth;\n"; + code += "\t\tfloat weight = after_depth / (after_depth - before_depth);\n"; + code += "\t\tofs = mix(ofs,prev_ofs,weight);\n"; + + } else { + code += "\t\tfloat depth = texture(texture_depth, base_uv).r;\n"; + // Use offset limiting to improve the appearance of non-deep parallax. + // This reduces the impression of depth, but avoids visible warping in the distance. + code += "\t\tvec2 ofs = base_uv - view_dir.xy * depth * depth_scale;\n"; + } + + code += "\t\tbase_uv=ofs;\n"; + if (features[FEATURE_DETAIL] && detail_uv == DETAIL_UV_2) { + code += "\t\tbase_uv2-=ofs;\n"; + } + + code += "\t}\n"; + } + + if (flags[FLAG_USE_POINT_SIZE]) { + code += "\tvec4 albedo_tex = texture(texture_albedo,POINT_COORD);\n"; + } else { + if (flags[FLAG_UV1_USE_TRIPLANAR]) { + code += "\tvec4 albedo_tex = triplanar_texture(texture_albedo,uv1_power_normal,uv1_triplanar_pos);\n"; + } else { + code += "\tvec4 albedo_tex = texture(texture_albedo,base_uv);\n"; + } + } + + if (flags[FLAG_ALBEDO_TEXTURE_SDF]) { + code += "\tconst float smoothing = 0.125;\n"; + code += "\tfloat dist = albedo_tex.a;\n"; + code += "\talbedo_tex.a = smoothstep(0.5 - smoothing, 0.5 + smoothing, dist);\n"; + code += "\talbedo_tex.rgb = vec3(1.0);\n"; + } else if (flags[FLAG_ALBEDO_TEXTURE_FORCE_SRGB]) { + code += "\talbedo_tex.rgb = mix(pow((albedo_tex.rgb + vec3(0.055)) * (1.0 / (1.0 + 0.055)),vec3(2.4)),albedo_tex.rgb.rgb * (1.0 / 12.92),lessThan(albedo_tex.rgb,vec3(0.04045)));\n"; + } + + if (flags[FLAG_ALBEDO_FROM_VERTEX_COLOR]) { + code += "\talbedo_tex *= COLOR;\n"; + } + code += "\tALBEDO = albedo.rgb * albedo_tex.rgb;\n"; + + if (textures[TEXTURE_METALLIC] != nullptr) { + if (flags[FLAG_UV1_USE_TRIPLANAR]) { + code += "\tfloat metallic_tex = dot(triplanar_texture(texture_metallic,uv1_power_normal,uv1_triplanar_pos),metallic_texture_channel);\n"; + } else { + code += "\tfloat metallic_tex = dot(texture(texture_metallic,base_uv),metallic_texture_channel);\n"; + } + code += "\tMETALLIC = metallic_tex * metallic;\n"; + } else { + code += "\tMETALLIC = metallic;\n"; + } + + if (textures[TEXTURE_ROUGHNESS] != nullptr) { + if (flags[FLAG_UV1_USE_TRIPLANAR]) { + code += "\tfloat roughness_tex = dot(triplanar_texture(texture_roughness,uv1_power_normal,uv1_triplanar_pos),roughness_texture_channel);\n"; + } else { + code += "\tfloat roughness_tex = dot(texture(texture_roughness,base_uv),roughness_texture_channel);\n"; + } + code += "\tROUGHNESS = roughness_tex * roughness;\n"; + } else { + code += "\tROUGHNESS = roughness;\n"; + } + + code += "\tSPECULAR = specular;\n"; + + if (features[FEATURE_NORMAL_MAPPING]) { + if (flags[FLAG_UV1_USE_TRIPLANAR]) { + code += "\tNORMALMAP = triplanar_texture(texture_normal,uv1_power_normal,uv1_triplanar_pos).rgb;\n"; + } else { + code += "\tNORMALMAP = texture(texture_normal,base_uv).rgb;\n"; + } + code += "\tNORMALMAP_DEPTH = normal_scale;\n"; + } + + if (features[FEATURE_EMISSION]) { + if (flags[FLAG_EMISSION_ON_UV2]) { + if (flags[FLAG_UV2_USE_TRIPLANAR]) { + code += "\tvec3 emission_tex = triplanar_texture(texture_emission,uv2_power_normal,uv2_triplanar_pos).rgb;\n"; + } else { + code += "\tvec3 emission_tex = texture(texture_emission,base_uv2).rgb;\n"; + } + } else { + if (flags[FLAG_UV1_USE_TRIPLANAR]) { + code += "\tvec3 emission_tex = triplanar_texture(texture_emission,uv1_power_normal,uv1_triplanar_pos).rgb;\n"; + } else { + code += "\tvec3 emission_tex = texture(texture_emission,base_uv).rgb;\n"; + } + } + + if (emission_op == EMISSION_OP_ADD) { + code += "\tEMISSION = (emission.rgb+emission_tex)*emission_energy;\n"; + } else { + code += "\tEMISSION = (emission.rgb*emission_tex)*emission_energy;\n"; + } + } + + if (features[FEATURE_REFRACTION]) { + if (features[FEATURE_NORMAL_MAPPING]) { + code += "\tvec3 unpacked_normal = NORMALMAP;\n"; + code += "\tunpacked_normal.xy = unpacked_normal.xy * 2.0 - 1.0;\n"; + code += "\tunpacked_normal.z = sqrt(max(0.0, 1.0 - dot(unpacked_normal.xy, unpacked_normal.xy)));\n"; + code += "\tvec3 ref_normal = normalize( mix(NORMAL,TANGENT * unpacked_normal.x + BINORMAL * unpacked_normal.y + NORMAL * unpacked_normal.z,NORMALMAP_DEPTH) );\n"; + } else { + code += "\tvec3 ref_normal = NORMAL;\n"; + } + if (flags[FLAG_UV1_USE_TRIPLANAR]) { + code += "\tvec2 ref_ofs = SCREEN_UV - ref_normal.xy * dot(triplanar_texture(texture_refraction,uv1_power_normal,uv1_triplanar_pos),refraction_texture_channel) * refraction;\n"; + } else { + code += "\tvec2 ref_ofs = SCREEN_UV - ref_normal.xy * dot(texture(texture_refraction,base_uv),refraction_texture_channel) * refraction;\n"; + } + code += "\tfloat ref_amount = 1.0 - albedo.a * albedo_tex.a;\n"; + code += "\tEMISSION += textureLod(SCREEN_TEXTURE,ref_ofs,ROUGHNESS * 8.0).rgb * ref_amount;\n"; + code += "\tALBEDO *= 1.0 - ref_amount;\n"; + code += "\tALPHA = 1.0;\n"; + + } else if (features[FEATURE_TRANSPARENT] || flags[FLAG_USE_ALPHA_SCISSOR] || flags[FLAG_USE_SHADOW_TO_OPACITY] || (distance_fade == DISTANCE_FADE_PIXEL_ALPHA) || proximity_fade_enabled) { + code += "\tALPHA = albedo.a * albedo_tex.a;\n"; + } + + if (proximity_fade_enabled) { + code += "\tfloat depth_tex = textureLod(DEPTH_TEXTURE,SCREEN_UV,0.0).r;\n"; + code += "\tvec4 world_pos = INV_PROJECTION_MATRIX * vec4(SCREEN_UV*2.0-1.0,depth_tex*2.0-1.0,1.0);\n"; + code += "\tworld_pos.xyz/=world_pos.w;\n"; + code += "\tALPHA*=clamp(1.0-smoothstep(world_pos.z+proximity_fade_distance,world_pos.z,VERTEX.z),0.0,1.0);\n"; + } + + if (distance_fade != DISTANCE_FADE_DISABLED) { + if ((distance_fade == DISTANCE_FADE_OBJECT_DITHER || distance_fade == DISTANCE_FADE_PIXEL_DITHER)) { + if (!RenderingServer::get_singleton()->is_low_end()) { + code += "\t{\n"; + + if (distance_fade == DISTANCE_FADE_OBJECT_DITHER) { + code += "\t\tfloat fade_distance = abs((INV_CAMERA_MATRIX * WORLD_MATRIX[3]).z);\n"; + + } else { + code += "\t\tfloat fade_distance = -VERTEX.z;\n"; + } + // Use interleaved gradient noise, which is fast but still looks good. + code += "\t\tconst vec3 magic = vec3(0.06711056f, 0.00583715f, 52.9829189f);"; + code += "\t\tfloat fade = clamp(smoothstep(distance_fade_min, distance_fade_max, fade_distance), 0.0, 1.0);\n"; + // Use a hard cap to prevent a few stray pixels from remaining when past the fade-out distance. + code += "\t\tif (fade < 0.001 || fade < fract(magic.z * fract(dot(FRAGCOORD.xy, magic.xy)))) {\n"; + code += "\t\t\tdiscard;\n"; + code += "\t\t}\n"; + + code += "\t}\n\n"; + } + + } else { + code += "\tALPHA*=clamp(smoothstep(distance_fade_min,distance_fade_max,-VERTEX.z),0.0,1.0);\n"; + } + } + + if (features[FEATURE_RIM]) { + if (flags[FLAG_UV1_USE_TRIPLANAR]) { + code += "\tvec2 rim_tex = triplanar_texture(texture_rim,uv1_power_normal,uv1_triplanar_pos).xy;\n"; + } else { + code += "\tvec2 rim_tex = texture(texture_rim,base_uv).xy;\n"; + } + code += "\tRIM = rim*rim_tex.x;"; + code += "\tRIM_TINT = rim_tint*rim_tex.y;\n"; + } + + if (features[FEATURE_CLEARCOAT]) { + if (flags[FLAG_UV1_USE_TRIPLANAR]) { + code += "\tvec2 clearcoat_tex = triplanar_texture(texture_clearcoat,uv1_power_normal,uv1_triplanar_pos).xy;\n"; + } else { + code += "\tvec2 clearcoat_tex = texture(texture_clearcoat,base_uv).xy;\n"; + } + code += "\tCLEARCOAT = clearcoat*clearcoat_tex.x;"; + code += "\tCLEARCOAT_GLOSS = clearcoat_gloss*clearcoat_tex.y;\n"; + } + + if (features[FEATURE_ANISOTROPY]) { + if (flags[FLAG_UV1_USE_TRIPLANAR]) { + code += "\tvec3 anisotropy_tex = triplanar_texture(texture_flowmap,uv1_power_normal,uv1_triplanar_pos).rga;\n"; + } else { + code += "\tvec3 anisotropy_tex = texture(texture_flowmap,base_uv).rga;\n"; + } + code += "\tANISOTROPY = anisotropy_ratio*anisotropy_tex.b;\n"; + code += "\tANISOTROPY_FLOW = anisotropy_tex.rg*2.0-1.0;\n"; + } + + if (features[FEATURE_AMBIENT_OCCLUSION]) { + if (flags[FLAG_AO_ON_UV2]) { + if (flags[FLAG_UV2_USE_TRIPLANAR]) { + code += "\tAO = dot(triplanar_texture(texture_ambient_occlusion,uv2_power_normal,uv2_triplanar_pos),ao_texture_channel);\n"; + } else { + code += "\tAO = dot(texture(texture_ambient_occlusion,base_uv2),ao_texture_channel);\n"; + } + } else { + if (flags[FLAG_UV1_USE_TRIPLANAR]) { + code += "\tAO = dot(triplanar_texture(texture_ambient_occlusion,uv1_power_normal,uv1_triplanar_pos),ao_texture_channel);\n"; + } else { + code += "\tAO = dot(texture(texture_ambient_occlusion,base_uv),ao_texture_channel);\n"; + } + } + + code += "\tAO_LIGHT_AFFECT = ao_light_affect;\n"; + } + + if (features[FEATURE_SUBSURACE_SCATTERING]) { + if (flags[FLAG_UV1_USE_TRIPLANAR]) { + code += "\tfloat sss_tex = triplanar_texture(texture_subsurface_scattering,uv1_power_normal,uv1_triplanar_pos).r;\n"; + } else { + code += "\tfloat sss_tex = texture(texture_subsurface_scattering,base_uv).r;\n"; + } + code += "\tSSS_STRENGTH=subsurface_scattering_strength*sss_tex;\n"; + } + + if (features[FEATURE_TRANSMISSION]) { + if (flags[FLAG_UV1_USE_TRIPLANAR]) { + code += "\tvec3 transmission_tex = triplanar_texture(texture_transmission,uv1_power_normal,uv1_triplanar_pos).rgb;\n"; + } else { + code += "\tvec3 transmission_tex = texture(texture_transmission,base_uv).rgb;\n"; + } + code += "\tTRANSMISSION = (transmission.rgb+transmission_tex);\n"; + } + + if (features[FEATURE_DETAIL]) { + bool triplanar = (flags[FLAG_UV1_USE_TRIPLANAR] && detail_uv == DETAIL_UV_1) || (flags[FLAG_UV2_USE_TRIPLANAR] && detail_uv == DETAIL_UV_2); + + if (triplanar) { + String tp_uv = detail_uv == DETAIL_UV_1 ? "uv1" : "uv2"; + code += "\tvec4 detail_tex = triplanar_texture(texture_detail_albedo," + tp_uv + "_power_normal," + tp_uv + "_triplanar_pos);\n"; + code += "\tvec4 detail_norm_tex = triplanar_texture(texture_detail_normal," + tp_uv + "_power_normal," + tp_uv + "_triplanar_pos);\n"; + + } else { + String det_uv = detail_uv == DETAIL_UV_1 ? "base_uv" : "base_uv2"; + code += "\tvec4 detail_tex = texture(texture_detail_albedo," + det_uv + ");\n"; + code += "\tvec4 detail_norm_tex = texture(texture_detail_normal," + det_uv + ");\n"; + } + + if (flags[FLAG_UV1_USE_TRIPLANAR]) { + code += "\tvec4 detail_mask_tex = triplanar_texture(texture_detail_mask,uv1_power_normal,uv1_triplanar_pos);\n"; + } else { + code += "\tvec4 detail_mask_tex = texture(texture_detail_mask,base_uv);\n"; + } + + switch (detail_blend_mode) { + case BLEND_MODE_MIX: { + code += "\tvec3 detail = mix(ALBEDO.rgb,detail_tex.rgb,detail_tex.a);\n"; + } break; + case BLEND_MODE_ADD: { + code += "\tvec3 detail = mix(ALBEDO.rgb,ALBEDO.rgb+detail_tex.rgb,detail_tex.a);\n"; + } break; + case BLEND_MODE_SUB: { + code += "\tvec3 detail = mix(ALBEDO.rgb,ALBEDO.rgb-detail_tex.rgb,detail_tex.a);\n"; + } break; + case BLEND_MODE_MUL: { + code += "\tvec3 detail = mix(ALBEDO.rgb,ALBEDO.rgb*detail_tex.rgb,detail_tex.a);\n"; + } break; + } + + code += "\tvec3 detail_norm = mix(NORMALMAP,detail_norm_tex.rgb,detail_tex.a);\n"; + code += "\tNORMALMAP = mix(NORMALMAP,detail_norm,detail_mask_tex.r);\n"; + code += "\tALBEDO.rgb = mix(ALBEDO.rgb,detail,detail_mask_tex.r);\n"; + } + + if (flags[FLAG_USE_ALPHA_SCISSOR]) { + code += "\tALPHA_SCISSOR=alpha_scissor_threshold;\n"; + } + + code += "}\n"; + + String fallback_mode_str; + switch (async_mode) { + case ASYNC_MODE_VISIBLE: { + fallback_mode_str = "async_visible"; + } break; + case ASYNC_MODE_HIDDEN: { + fallback_mode_str = "async_hidden"; + } break; + } + code = code.replace_first("render_mode ", "render_mode " + fallback_mode_str + ","); + + ShaderData shader_data; + shader_data.shader = RS::get_singleton()->shader_create(); + shader_data.users = 1; + + RS::get_singleton()->shader_set_code(shader_data.shader, code); + + shader_map[mk] = shader_data; + + RS::get_singleton()->material_set_shader(_get_material(), shader_data.shader); +} + +void SpatialMaterial::flush_changes() { + material_mutex.lock(); + + while (dirty_materials->first()) { + dirty_materials->first()->self()->_update_shader(); + } + + material_mutex.unlock(); +} + +void SpatialMaterial::_queue_shader_change() { + material_mutex.lock(); + + if (is_initialized && !element.in_list()) { + dirty_materials->add(&element); + } + + material_mutex.unlock(); +} + +bool SpatialMaterial::_is_shader_dirty() const { + bool dirty = false; + + material_mutex.lock(); + + dirty = element.in_list(); + + material_mutex.unlock(); + + return dirty; +} +void SpatialMaterial::set_albedo(const Color &p_albedo) { + albedo = p_albedo; + + RS::get_singleton()->material_set_param(_get_material(), shader_names->albedo, p_albedo); +} + +Color SpatialMaterial::get_albedo() const { + return albedo; +} + +void SpatialMaterial::set_specular(float p_specular) { + specular = p_specular; + RS::get_singleton()->material_set_param(_get_material(), shader_names->specular, p_specular); +} + +float SpatialMaterial::get_specular() const { + return specular; +} + +void SpatialMaterial::set_roughness(float p_roughness) { + roughness = p_roughness; + RS::get_singleton()->material_set_param(_get_material(), shader_names->roughness, p_roughness); +} + +float SpatialMaterial::get_roughness() const { + return roughness; +} + +void SpatialMaterial::set_metallic(float p_metallic) { + metallic = p_metallic; + RS::get_singleton()->material_set_param(_get_material(), shader_names->metallic, p_metallic); +} + +float SpatialMaterial::get_metallic() const { + return metallic; +} + +void SpatialMaterial::set_emission(const Color &p_emission) { + emission = p_emission; + RS::get_singleton()->material_set_param(_get_material(), shader_names->emission, p_emission); +} +Color SpatialMaterial::get_emission() const { + return emission; +} + +void SpatialMaterial::set_emission_energy(float p_emission_energy) { + emission_energy = p_emission_energy; + RS::get_singleton()->material_set_param(_get_material(), shader_names->emission_energy, p_emission_energy); +} +float SpatialMaterial::get_emission_energy() const { + return emission_energy; +} + +void SpatialMaterial::set_normal_scale(float p_normal_scale) { + normal_scale = p_normal_scale; + RS::get_singleton()->material_set_param(_get_material(), shader_names->normal_scale, p_normal_scale); +} +float SpatialMaterial::get_normal_scale() const { + return normal_scale; +} + +void SpatialMaterial::set_rim(float p_rim) { + rim = p_rim; + RS::get_singleton()->material_set_param(_get_material(), shader_names->rim, p_rim); +} +float SpatialMaterial::get_rim() const { + return rim; +} + +void SpatialMaterial::set_rim_tint(float p_rim_tint) { + rim_tint = p_rim_tint; + RS::get_singleton()->material_set_param(_get_material(), shader_names->rim_tint, p_rim_tint); +} +float SpatialMaterial::get_rim_tint() const { + return rim_tint; +} + +void SpatialMaterial::set_ao_light_affect(float p_ao_light_affect) { + ao_light_affect = p_ao_light_affect; + RS::get_singleton()->material_set_param(_get_material(), shader_names->ao_light_affect, p_ao_light_affect); +} +float SpatialMaterial::get_ao_light_affect() const { + return ao_light_affect; +} + +void SpatialMaterial::set_clearcoat(float p_clearcoat) { + clearcoat = p_clearcoat; + RS::get_singleton()->material_set_param(_get_material(), shader_names->clearcoat, p_clearcoat); +} + +float SpatialMaterial::get_clearcoat() const { + return clearcoat; +} + +void SpatialMaterial::set_clearcoat_gloss(float p_clearcoat_gloss) { + clearcoat_gloss = p_clearcoat_gloss; + RS::get_singleton()->material_set_param(_get_material(), shader_names->clearcoat_gloss, p_clearcoat_gloss); +} + +float SpatialMaterial::get_clearcoat_gloss() const { + return clearcoat_gloss; +} + +void SpatialMaterial::set_anisotropy(float p_anisotropy) { + anisotropy = p_anisotropy; + RS::get_singleton()->material_set_param(_get_material(), shader_names->anisotropy, p_anisotropy); +} +float SpatialMaterial::get_anisotropy() const { + return anisotropy; +} + +void SpatialMaterial::set_depth_scale(float p_depth_scale) { + depth_scale = p_depth_scale; + RS::get_singleton()->material_set_param(_get_material(), shader_names->depth_scale, p_depth_scale); +} + +float SpatialMaterial::get_depth_scale() const { + return depth_scale; +} + +void SpatialMaterial::set_subsurface_scattering_strength(float p_subsurface_scattering_strength) { + subsurface_scattering_strength = p_subsurface_scattering_strength; + RS::get_singleton()->material_set_param(_get_material(), shader_names->subsurface_scattering_strength, subsurface_scattering_strength); +} + +float SpatialMaterial::get_subsurface_scattering_strength() const { + return subsurface_scattering_strength; +} + +void SpatialMaterial::set_transmission(const Color &p_transmission) { + transmission = p_transmission; + RS::get_singleton()->material_set_param(_get_material(), shader_names->transmission, transmission); +} + +Color SpatialMaterial::get_transmission() const { + return transmission; +} + +void SpatialMaterial::set_refraction(float p_refraction) { + refraction = p_refraction; + RS::get_singleton()->material_set_param(_get_material(), shader_names->refraction, refraction); +} + +float SpatialMaterial::get_refraction() const { + return refraction; +} + +void SpatialMaterial::set_detail_uv(DetailUV p_detail_uv) { + if (detail_uv == p_detail_uv) { + return; + } + + detail_uv = p_detail_uv; + _queue_shader_change(); +} +SpatialMaterial::DetailUV SpatialMaterial::get_detail_uv() const { + return detail_uv; +} + +void SpatialMaterial::set_blend_mode(BlendMode p_mode) { + if (blend_mode == p_mode) { + return; + } + + blend_mode = p_mode; + _queue_shader_change(); +} +SpatialMaterial::BlendMode SpatialMaterial::get_blend_mode() const { + return blend_mode; +} + +void SpatialMaterial::set_detail_blend_mode(BlendMode p_mode) { + detail_blend_mode = p_mode; + _queue_shader_change(); +} +SpatialMaterial::BlendMode SpatialMaterial::get_detail_blend_mode() const { + return detail_blend_mode; +} + +void SpatialMaterial::set_depth_draw_mode(DepthDrawMode p_mode) { + if (depth_draw_mode == p_mode) { + return; + } + + depth_draw_mode = p_mode; + _queue_shader_change(); +} +SpatialMaterial::DepthDrawMode SpatialMaterial::get_depth_draw_mode() const { + return depth_draw_mode; +} + +void SpatialMaterial::set_cull_mode(CullMode p_mode) { + if (cull_mode == p_mode) { + return; + } + + cull_mode = p_mode; + _queue_shader_change(); +} +SpatialMaterial::CullMode SpatialMaterial::get_cull_mode() const { + return cull_mode; +} + +void SpatialMaterial::set_diffuse_mode(DiffuseMode p_mode) { + if (diffuse_mode == p_mode) { + return; + } + + diffuse_mode = p_mode; + _queue_shader_change(); +} +SpatialMaterial::DiffuseMode SpatialMaterial::get_diffuse_mode() const { + return diffuse_mode; +} + +void SpatialMaterial::set_specular_mode(SpecularMode p_mode) { + if (specular_mode == p_mode) { + return; + } + + specular_mode = p_mode; + _queue_shader_change(); +} +SpatialMaterial::SpecularMode SpatialMaterial::get_specular_mode() const { + return specular_mode; +} + +void SpatialMaterial::set_flag(Flags p_flag, bool p_enabled) { + ERR_FAIL_INDEX(p_flag, FLAG_MAX); + + if (flags[p_flag] == p_enabled) { + return; + } + + flags[p_flag] = p_enabled; + + if ( + p_flag == FLAG_USE_ALPHA_SCISSOR || + p_flag == FLAG_UNSHADED || + p_flag == FLAG_USE_SHADOW_TO_OPACITY || + p_flag == FLAG_UV1_USE_TRIPLANAR || + p_flag == FLAG_UV2_USE_TRIPLANAR) { + _change_notify(); + } + + _queue_shader_change(); +} + +bool SpatialMaterial::get_flag(Flags p_flag) const { + ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false); + return flags[p_flag]; +} + +void SpatialMaterial::set_feature(Feature p_feature, bool p_enabled) { + ERR_FAIL_INDEX(p_feature, FEATURE_MAX); + if (features[p_feature] == p_enabled) { + return; + } + + features[p_feature] = p_enabled; + _change_notify(); + _queue_shader_change(); +} + +bool SpatialMaterial::get_feature(Feature p_feature) const { + ERR_FAIL_INDEX_V(p_feature, FEATURE_MAX, false); + return features[p_feature]; +} + +void SpatialMaterial::set_texture(TextureParam p_param, const Ref &p_texture) { + ERR_FAIL_INDEX(p_param, TEXTURE_MAX); + textures[p_param] = p_texture; + RID rid = p_texture.is_valid() ? p_texture->get_rid() : RID(); + RS::get_singleton()->material_set_param(_get_material(), shader_names->texture_names[p_param], rid); + _change_notify(); + _queue_shader_change(); +} + +Ref SpatialMaterial::get_texture(TextureParam p_param) const { + ERR_FAIL_INDEX_V(p_param, TEXTURE_MAX, Ref()); + return textures[p_param]; +} + +Ref SpatialMaterial::get_texture_by_name(StringName p_name) const { + for (int i = 0; i < (int)SpatialMaterial::TEXTURE_MAX; i++) { + TextureParam param = TextureParam(i); + if (p_name == shader_names->texture_names[param]) { + return textures[param]; + } + } + return Ref(); +} + +void SpatialMaterial::_validate_feature(const String &text, Feature feature, PropertyInfo &property) const { + if (property.name.begins_with(text) && property.name != text + "_enabled" && !features[feature]) { + property.usage = 0; + } +} + +void SpatialMaterial::_validate_high_end(const String &text, PropertyInfo &property) const { + if (property.name.begins_with(text)) { + property.usage |= PROPERTY_USAGE_HIGH_END_GFX; + } +} + +void SpatialMaterial::_validate_property(PropertyInfo &property) const { + _validate_feature("normal", FEATURE_NORMAL_MAPPING, property); + _validate_feature("emission", FEATURE_EMISSION, property); + _validate_feature("rim", FEATURE_RIM, property); + _validate_feature("clearcoat", FEATURE_CLEARCOAT, property); + _validate_feature("anisotropy", FEATURE_ANISOTROPY, property); + _validate_feature("ao", FEATURE_AMBIENT_OCCLUSION, property); + _validate_feature("depth", FEATURE_DEPTH_MAPPING, property); + _validate_feature("subsurf_scatter", FEATURE_SUBSURACE_SCATTERING, property); + _validate_feature("transmission", FEATURE_TRANSMISSION, property); + _validate_feature("refraction", FEATURE_REFRACTION, property); + _validate_feature("detail", FEATURE_DETAIL, property); + + _validate_high_end("subsurf_scatter", property); + _validate_high_end("depth", property); + + if (property.name.begins_with("particles_anim_") && billboard_mode != BILLBOARD_PARTICLES) { + property.usage = 0; + } + + if (property.name == "params_grow_amount" && !grow_enabled) { + property.usage = 0; + } + + if (property.name == "proximity_fade_distance" && !proximity_fade_enabled) { + property.usage = 0; + } + + if ((property.name == "distance_fade_max_distance" || property.name == "distance_fade_min_distance") && distance_fade == DISTANCE_FADE_DISABLED) { + property.usage = 0; + } + + if (property.name == "uv1_triplanar_sharpness" && !flags[FLAG_UV1_USE_TRIPLANAR]) { + property.usage = 0; + } + + if (property.name == "uv2_triplanar_sharpness" && !flags[FLAG_UV2_USE_TRIPLANAR]) { + property.usage = 0; + } + + if (property.name == "params_alpha_scissor_threshold" && !flags[FLAG_USE_ALPHA_SCISSOR]) { + property.usage = 0; + } + + if ((property.name == "depth_min_layers" || property.name == "depth_max_layers") && !deep_parallax) { + property.usage = 0; + } + + if (flags[FLAG_UNSHADED]) { + if (property.name.begins_with("anisotropy")) { + property.usage = 0; + } + + if (property.name.begins_with("ao")) { + property.usage = 0; + } + + if (property.name.begins_with("clearcoat")) { + property.usage = 0; + } + + if (property.name.begins_with("emission")) { + property.usage = 0; + } + + if (property.name.begins_with("metallic")) { + property.usage = 0; + } + + if (property.name.begins_with("normal")) { + property.usage = 0; + } + + if (property.name.begins_with("rim")) { + property.usage = 0; + } + + if (property.name.begins_with("roughness")) { + property.usage = 0; + } + + if (property.name.begins_with("subsurf_scatter")) { + property.usage = 0; + } + + if (property.name.begins_with("transmission")) { + property.usage = 0; + } + } +} + +void SpatialMaterial::set_line_width(float p_line_width) { + line_width = p_line_width; + RS::get_singleton()->material_set_line_width(_get_material(), line_width); +} + +float SpatialMaterial::get_line_width() const { + return line_width; +} + +void SpatialMaterial::set_point_size(float p_point_size) { + point_size = p_point_size; + RS::get_singleton()->material_set_param(_get_material(), shader_names->point_size, p_point_size); +} + +float SpatialMaterial::get_point_size() const { + return point_size; +} + +void SpatialMaterial::set_uv1_scale(const Vector3 &p_scale) { + uv1_scale = p_scale; + RS::get_singleton()->material_set_param(_get_material(), shader_names->uv1_scale, p_scale); +} + +Vector3 SpatialMaterial::get_uv1_scale() const { + return uv1_scale; +} + +void SpatialMaterial::set_uv1_offset(const Vector3 &p_offset) { + uv1_offset = p_offset; + RS::get_singleton()->material_set_param(_get_material(), shader_names->uv1_offset, p_offset); +} +Vector3 SpatialMaterial::get_uv1_offset() const { + return uv1_offset; +} + +void SpatialMaterial::set_uv1_triplanar_blend_sharpness(float p_sharpness) { + uv1_triplanar_sharpness = p_sharpness; + RS::get_singleton()->material_set_param(_get_material(), shader_names->uv1_blend_sharpness, p_sharpness); +} + +float SpatialMaterial::get_uv1_triplanar_blend_sharpness() const { + return uv1_triplanar_sharpness; +} + +void SpatialMaterial::set_uv2_scale(const Vector3 &p_scale) { + uv2_scale = p_scale; + RS::get_singleton()->material_set_param(_get_material(), shader_names->uv2_scale, p_scale); +} + +Vector3 SpatialMaterial::get_uv2_scale() const { + return uv2_scale; +} + +void SpatialMaterial::set_uv2_offset(const Vector3 &p_offset) { + uv2_offset = p_offset; + RS::get_singleton()->material_set_param(_get_material(), shader_names->uv2_offset, p_offset); +} + +Vector3 SpatialMaterial::get_uv2_offset() const { + return uv2_offset; +} + +void SpatialMaterial::set_uv2_triplanar_blend_sharpness(float p_sharpness) { + uv2_triplanar_sharpness = p_sharpness; + RS::get_singleton()->material_set_param(_get_material(), shader_names->uv2_blend_sharpness, p_sharpness); +} + +float SpatialMaterial::get_uv2_triplanar_blend_sharpness() const { + return uv2_triplanar_sharpness; +} + +void SpatialMaterial::set_billboard_mode(BillboardMode p_mode) { + billboard_mode = p_mode; + _queue_shader_change(); + _change_notify(); +} + +SpatialMaterial::BillboardMode SpatialMaterial::get_billboard_mode() const { + return billboard_mode; +} + +void SpatialMaterial::set_particles_anim_h_frames(int p_frames) { + particles_anim_h_frames = p_frames; + RS::get_singleton()->material_set_param(_get_material(), shader_names->particles_anim_h_frames, p_frames); +} + +int SpatialMaterial::get_particles_anim_h_frames() const { + return particles_anim_h_frames; +} +void SpatialMaterial::set_particles_anim_v_frames(int p_frames) { + particles_anim_v_frames = p_frames; + RS::get_singleton()->material_set_param(_get_material(), shader_names->particles_anim_v_frames, p_frames); +} + +int SpatialMaterial::get_particles_anim_v_frames() const { + return particles_anim_v_frames; +} + +void SpatialMaterial::set_particles_anim_loop(bool p_loop) { + particles_anim_loop = p_loop; + RS::get_singleton()->material_set_param(_get_material(), shader_names->particles_anim_loop, particles_anim_loop); +} + +bool SpatialMaterial::get_particles_anim_loop() const { + return particles_anim_loop; +} + +void SpatialMaterial::set_depth_deep_parallax(bool p_enable) { + deep_parallax = p_enable; + _queue_shader_change(); + _change_notify(); +} + +bool SpatialMaterial::is_depth_deep_parallax_enabled() const { + return deep_parallax; +} + +void SpatialMaterial::set_depth_deep_parallax_min_layers(int p_layer) { + deep_parallax_min_layers = p_layer; + RS::get_singleton()->material_set_param(_get_material(), shader_names->depth_min_layers, p_layer); +} +int SpatialMaterial::get_depth_deep_parallax_min_layers() const { + return deep_parallax_min_layers; +} + +void SpatialMaterial::set_depth_deep_parallax_max_layers(int p_layer) { + deep_parallax_max_layers = p_layer; + RS::get_singleton()->material_set_param(_get_material(), shader_names->depth_max_layers, p_layer); +} +int SpatialMaterial::get_depth_deep_parallax_max_layers() const { + return deep_parallax_max_layers; +} + +void SpatialMaterial::set_depth_deep_parallax_flip_tangent(bool p_flip) { + depth_parallax_flip_tangent = p_flip; + RS::get_singleton()->material_set_param(_get_material(), shader_names->depth_flip, Vector2(depth_parallax_flip_tangent ? -1 : 1, depth_parallax_flip_binormal ? -1 : 1)); +} + +bool SpatialMaterial::get_depth_deep_parallax_flip_tangent() const { + return depth_parallax_flip_tangent; +} + +void SpatialMaterial::set_depth_deep_parallax_flip_binormal(bool p_flip) { + depth_parallax_flip_binormal = p_flip; + RS::get_singleton()->material_set_param(_get_material(), shader_names->depth_flip, Vector2(depth_parallax_flip_tangent ? -1 : 1, depth_parallax_flip_binormal ? -1 : 1)); +} + +bool SpatialMaterial::get_depth_deep_parallax_flip_binormal() const { + return depth_parallax_flip_binormal; +} + +void SpatialMaterial::set_grow_enabled(bool p_enable) { + grow_enabled = p_enable; + _queue_shader_change(); + _change_notify(); +} + +bool SpatialMaterial::is_grow_enabled() const { + return grow_enabled; +} + +void SpatialMaterial::set_alpha_scissor_threshold(float p_threshold) { + alpha_scissor_threshold = p_threshold; + RS::get_singleton()->material_set_param(_get_material(), shader_names->alpha_scissor_threshold, p_threshold); +} + +float SpatialMaterial::get_alpha_scissor_threshold() const { + return alpha_scissor_threshold; +} + +void SpatialMaterial::set_grow(float p_grow) { + grow = p_grow; + RS::get_singleton()->material_set_param(_get_material(), shader_names->grow, p_grow); +} + +float SpatialMaterial::get_grow() const { + return grow; +} + +static Plane _get_texture_mask(SpatialMaterial::TextureChannel p_channel) { + static const Plane masks[5] = { + Plane(1, 0, 0, 0), + Plane(0, 1, 0, 0), + Plane(0, 0, 1, 0), + Plane(0, 0, 0, 1), + Plane(0.3333333, 0.3333333, 0.3333333, 0), + }; + + return masks[p_channel]; +} + +void SpatialMaterial::set_metallic_texture_channel(TextureChannel p_channel) { + ERR_FAIL_INDEX(p_channel, 5); + metallic_texture_channel = p_channel; + RS::get_singleton()->material_set_param(_get_material(), shader_names->metallic_texture_channel, _get_texture_mask(p_channel)); +} + +SpatialMaterial::TextureChannel SpatialMaterial::get_metallic_texture_channel() const { + return metallic_texture_channel; +} + +void SpatialMaterial::set_roughness_texture_channel(TextureChannel p_channel) { + ERR_FAIL_INDEX(p_channel, 5); + roughness_texture_channel = p_channel; + RS::get_singleton()->material_set_param(_get_material(), shader_names->roughness_texture_channel, _get_texture_mask(p_channel)); +} + +SpatialMaterial::TextureChannel SpatialMaterial::get_roughness_texture_channel() const { + return roughness_texture_channel; +} + +void SpatialMaterial::set_ao_texture_channel(TextureChannel p_channel) { + ERR_FAIL_INDEX(p_channel, 5); + ao_texture_channel = p_channel; + RS::get_singleton()->material_set_param(_get_material(), shader_names->ao_texture_channel, _get_texture_mask(p_channel)); +} + +SpatialMaterial::TextureChannel SpatialMaterial::get_ao_texture_channel() const { + return ao_texture_channel; +} + +void SpatialMaterial::set_refraction_texture_channel(TextureChannel p_channel) { + ERR_FAIL_INDEX(p_channel, 5); + refraction_texture_channel = p_channel; + RS::get_singleton()->material_set_param(_get_material(), shader_names->refraction_texture_channel, _get_texture_mask(p_channel)); +} + +SpatialMaterial::TextureChannel SpatialMaterial::get_refraction_texture_channel() const { + return refraction_texture_channel; +} + +RID SpatialMaterial::get_material_rid_for_2d(bool p_shaded, bool p_transparent, bool p_double_sided, bool p_cut_alpha, bool p_opaque_prepass, bool p_billboard, bool p_billboard_y, bool p_no_depth_test, bool p_fixed_size, bool p_sdf) { + uint64_t hash = 0; + + if (p_shaded) { + hash |= 1 << 0; + } + if (p_transparent) { + hash |= 1 << 1; + } + if (p_cut_alpha) { + hash |= 1 << 2; + } + if (p_opaque_prepass) { + hash |= 1 << 3; + } + if (p_double_sided) { + hash |= 1 << 4; + } + if (p_billboard) { + hash |= 1 << 5; + } + if (p_billboard_y) { + hash |= 1 << 6; + } + if (p_no_depth_test) { + hash |= 1 << 7; + } + if (p_fixed_size) { + hash |= 1 << 8; + } + if (p_sdf) { + hash |= 1 << 9; + } + + if (materials_for_2d.has(hash)) { + return materials_for_2d[hash]->get_rid(); + } + + Ref material; + material.instance(); + + material->set_flag(FLAG_UNSHADED, !p_shaded); + material->set_feature(FEATURE_TRANSPARENT, p_transparent); + material->set_cull_mode(p_double_sided ? CULL_DISABLED : CULL_BACK); + material->set_depth_draw_mode(p_opaque_prepass ? DEPTH_DRAW_ALPHA_OPAQUE_PREPASS : DEPTH_DRAW_OPAQUE_ONLY); + material->set_flag(FLAG_SRGB_VERTEX_COLOR, true); + material->set_flag(FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + material->set_flag(FLAG_USE_ALPHA_SCISSOR, p_cut_alpha); + material->set_flag(FLAG_DISABLE_DEPTH_TEST, p_no_depth_test); + material->set_flag(FLAG_FIXED_SIZE, p_fixed_size); + material->set_flag(FLAG_ALBEDO_TEXTURE_SDF, p_sdf); + if (p_billboard || p_billboard_y) { + material->set_flag(FLAG_BILLBOARD_KEEP_SCALE, true); + material->set_billboard_mode(p_billboard_y ? BILLBOARD_FIXED_Y : BILLBOARD_ENABLED); + } + + materials_for_2d[hash] = material; + // flush before using so we can access the shader right away + flush_changes(); + + return materials_for_2d[hash]->get_rid(); +} + +void SpatialMaterial::set_on_top_of_alpha() { + set_feature(FEATURE_TRANSPARENT, true); + set_render_priority(RENDER_PRIORITY_MAX); + set_flag(FLAG_DISABLE_DEPTH_TEST, true); +} + +void SpatialMaterial::set_proximity_fade(bool p_enable) { + proximity_fade_enabled = p_enable; + _queue_shader_change(); + _change_notify(); +} + +bool SpatialMaterial::is_proximity_fade_enabled() const { + return proximity_fade_enabled; +} + +void SpatialMaterial::set_proximity_fade_distance(float p_distance) { + proximity_fade_distance = p_distance; + RS::get_singleton()->material_set_param(_get_material(), shader_names->proximity_fade_distance, p_distance); +} +float SpatialMaterial::get_proximity_fade_distance() const { + return proximity_fade_distance; +} + +void SpatialMaterial::set_distance_fade(DistanceFadeMode p_mode) { + distance_fade = p_mode; + _queue_shader_change(); + _change_notify(); +} +SpatialMaterial::DistanceFadeMode SpatialMaterial::get_distance_fade() const { + return distance_fade; +} + +void SpatialMaterial::set_distance_fade_max_distance(float p_distance) { + distance_fade_max_distance = p_distance; + RS::get_singleton()->material_set_param(_get_material(), shader_names->distance_fade_max, distance_fade_max_distance); +} +float SpatialMaterial::get_distance_fade_max_distance() const { + return distance_fade_max_distance; +} + +void SpatialMaterial::set_distance_fade_min_distance(float p_distance) { + distance_fade_min_distance = p_distance; + RS::get_singleton()->material_set_param(_get_material(), shader_names->distance_fade_min, distance_fade_min_distance); +} + +float SpatialMaterial::get_distance_fade_min_distance() const { + return distance_fade_min_distance; +} + +void SpatialMaterial::set_emission_operator(EmissionOperator p_op) { + if (emission_op == p_op) { + return; + } + emission_op = p_op; + _queue_shader_change(); +} + +SpatialMaterial::EmissionOperator SpatialMaterial::get_emission_operator() const { + return emission_op; +} + +RID SpatialMaterial::get_shader_rid() const { + ERR_FAIL_COND_V(!shader_map.has(current_key), RID()); + return shader_map[current_key].shader; +} + +Shader::Mode SpatialMaterial::get_shader_mode() const { + return Shader::MODE_SPATIAL; +} + +void SpatialMaterial::set_async_mode(AsyncMode p_mode) { + async_mode = p_mode; + _queue_shader_change(); + _change_notify(); +} + +SpatialMaterial::AsyncMode SpatialMaterial::get_async_mode() const { + return async_mode; +} + +void SpatialMaterial::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_albedo", "albedo"), &SpatialMaterial::set_albedo); + ClassDB::bind_method(D_METHOD("get_albedo"), &SpatialMaterial::get_albedo); + + ClassDB::bind_method(D_METHOD("set_specular", "specular"), &SpatialMaterial::set_specular); + ClassDB::bind_method(D_METHOD("get_specular"), &SpatialMaterial::get_specular); + + ClassDB::bind_method(D_METHOD("set_metallic", "metallic"), &SpatialMaterial::set_metallic); + ClassDB::bind_method(D_METHOD("get_metallic"), &SpatialMaterial::get_metallic); + + ClassDB::bind_method(D_METHOD("set_roughness", "roughness"), &SpatialMaterial::set_roughness); + ClassDB::bind_method(D_METHOD("get_roughness"), &SpatialMaterial::get_roughness); + + ClassDB::bind_method(D_METHOD("set_emission", "emission"), &SpatialMaterial::set_emission); + ClassDB::bind_method(D_METHOD("get_emission"), &SpatialMaterial::get_emission); + + ClassDB::bind_method(D_METHOD("set_emission_energy", "emission_energy"), &SpatialMaterial::set_emission_energy); + ClassDB::bind_method(D_METHOD("get_emission_energy"), &SpatialMaterial::get_emission_energy); + + ClassDB::bind_method(D_METHOD("set_normal_scale", "normal_scale"), &SpatialMaterial::set_normal_scale); + ClassDB::bind_method(D_METHOD("get_normal_scale"), &SpatialMaterial::get_normal_scale); + + ClassDB::bind_method(D_METHOD("set_rim", "rim"), &SpatialMaterial::set_rim); + ClassDB::bind_method(D_METHOD("get_rim"), &SpatialMaterial::get_rim); + + ClassDB::bind_method(D_METHOD("set_rim_tint", "rim_tint"), &SpatialMaterial::set_rim_tint); + ClassDB::bind_method(D_METHOD("get_rim_tint"), &SpatialMaterial::get_rim_tint); + + ClassDB::bind_method(D_METHOD("set_clearcoat", "clearcoat"), &SpatialMaterial::set_clearcoat); + ClassDB::bind_method(D_METHOD("get_clearcoat"), &SpatialMaterial::get_clearcoat); + + ClassDB::bind_method(D_METHOD("set_clearcoat_gloss", "clearcoat_gloss"), &SpatialMaterial::set_clearcoat_gloss); + ClassDB::bind_method(D_METHOD("get_clearcoat_gloss"), &SpatialMaterial::get_clearcoat_gloss); + + ClassDB::bind_method(D_METHOD("set_anisotropy", "anisotropy"), &SpatialMaterial::set_anisotropy); + ClassDB::bind_method(D_METHOD("get_anisotropy"), &SpatialMaterial::get_anisotropy); + + ClassDB::bind_method(D_METHOD("set_depth_scale", "depth_scale"), &SpatialMaterial::set_depth_scale); + ClassDB::bind_method(D_METHOD("get_depth_scale"), &SpatialMaterial::get_depth_scale); + + ClassDB::bind_method(D_METHOD("set_subsurface_scattering_strength", "strength"), &SpatialMaterial::set_subsurface_scattering_strength); + ClassDB::bind_method(D_METHOD("get_subsurface_scattering_strength"), &SpatialMaterial::get_subsurface_scattering_strength); + + ClassDB::bind_method(D_METHOD("set_transmission", "transmission"), &SpatialMaterial::set_transmission); + ClassDB::bind_method(D_METHOD("get_transmission"), &SpatialMaterial::get_transmission); + + ClassDB::bind_method(D_METHOD("set_refraction", "refraction"), &SpatialMaterial::set_refraction); + ClassDB::bind_method(D_METHOD("get_refraction"), &SpatialMaterial::get_refraction); + + ClassDB::bind_method(D_METHOD("set_line_width", "line_width"), &SpatialMaterial::set_line_width); + ClassDB::bind_method(D_METHOD("get_line_width"), &SpatialMaterial::get_line_width); + + ClassDB::bind_method(D_METHOD("set_point_size", "point_size"), &SpatialMaterial::set_point_size); + ClassDB::bind_method(D_METHOD("get_point_size"), &SpatialMaterial::get_point_size); + + ClassDB::bind_method(D_METHOD("set_detail_uv", "detail_uv"), &SpatialMaterial::set_detail_uv); + ClassDB::bind_method(D_METHOD("get_detail_uv"), &SpatialMaterial::get_detail_uv); + + ClassDB::bind_method(D_METHOD("set_blend_mode", "blend_mode"), &SpatialMaterial::set_blend_mode); + ClassDB::bind_method(D_METHOD("get_blend_mode"), &SpatialMaterial::get_blend_mode); + + ClassDB::bind_method(D_METHOD("set_depth_draw_mode", "depth_draw_mode"), &SpatialMaterial::set_depth_draw_mode); + ClassDB::bind_method(D_METHOD("get_depth_draw_mode"), &SpatialMaterial::get_depth_draw_mode); + + ClassDB::bind_method(D_METHOD("set_cull_mode", "cull_mode"), &SpatialMaterial::set_cull_mode); + ClassDB::bind_method(D_METHOD("get_cull_mode"), &SpatialMaterial::get_cull_mode); + + ClassDB::bind_method(D_METHOD("set_diffuse_mode", "diffuse_mode"), &SpatialMaterial::set_diffuse_mode); + ClassDB::bind_method(D_METHOD("get_diffuse_mode"), &SpatialMaterial::get_diffuse_mode); + + ClassDB::bind_method(D_METHOD("set_specular_mode", "specular_mode"), &SpatialMaterial::set_specular_mode); + ClassDB::bind_method(D_METHOD("get_specular_mode"), &SpatialMaterial::get_specular_mode); + + ClassDB::bind_method(D_METHOD("set_flag", "flag", "enable"), &SpatialMaterial::set_flag); + ClassDB::bind_method(D_METHOD("get_flag", "flag"), &SpatialMaterial::get_flag); + + ClassDB::bind_method(D_METHOD("set_feature", "feature", "enable"), &SpatialMaterial::set_feature); + ClassDB::bind_method(D_METHOD("get_feature", "feature"), &SpatialMaterial::get_feature); + + ClassDB::bind_method(D_METHOD("set_texture", "param", "texture"), &SpatialMaterial::set_texture); + ClassDB::bind_method(D_METHOD("get_texture", "param"), &SpatialMaterial::get_texture); + + ClassDB::bind_method(D_METHOD("set_detail_blend_mode", "detail_blend_mode"), &SpatialMaterial::set_detail_blend_mode); + ClassDB::bind_method(D_METHOD("get_detail_blend_mode"), &SpatialMaterial::get_detail_blend_mode); + + ClassDB::bind_method(D_METHOD("set_uv1_scale", "scale"), &SpatialMaterial::set_uv1_scale); + ClassDB::bind_method(D_METHOD("get_uv1_scale"), &SpatialMaterial::get_uv1_scale); + + ClassDB::bind_method(D_METHOD("set_uv1_offset", "offset"), &SpatialMaterial::set_uv1_offset); + ClassDB::bind_method(D_METHOD("get_uv1_offset"), &SpatialMaterial::get_uv1_offset); + + ClassDB::bind_method(D_METHOD("set_uv1_triplanar_blend_sharpness", "sharpness"), &SpatialMaterial::set_uv1_triplanar_blend_sharpness); + ClassDB::bind_method(D_METHOD("get_uv1_triplanar_blend_sharpness"), &SpatialMaterial::get_uv1_triplanar_blend_sharpness); + + ClassDB::bind_method(D_METHOD("set_uv2_scale", "scale"), &SpatialMaterial::set_uv2_scale); + ClassDB::bind_method(D_METHOD("get_uv2_scale"), &SpatialMaterial::get_uv2_scale); + + ClassDB::bind_method(D_METHOD("set_uv2_offset", "offset"), &SpatialMaterial::set_uv2_offset); + ClassDB::bind_method(D_METHOD("get_uv2_offset"), &SpatialMaterial::get_uv2_offset); + + ClassDB::bind_method(D_METHOD("set_uv2_triplanar_blend_sharpness", "sharpness"), &SpatialMaterial::set_uv2_triplanar_blend_sharpness); + ClassDB::bind_method(D_METHOD("get_uv2_triplanar_blend_sharpness"), &SpatialMaterial::get_uv2_triplanar_blend_sharpness); + + ClassDB::bind_method(D_METHOD("set_billboard_mode", "mode"), &SpatialMaterial::set_billboard_mode); + ClassDB::bind_method(D_METHOD("get_billboard_mode"), &SpatialMaterial::get_billboard_mode); + + ClassDB::bind_method(D_METHOD("set_particles_anim_h_frames", "frames"), &SpatialMaterial::set_particles_anim_h_frames); + ClassDB::bind_method(D_METHOD("get_particles_anim_h_frames"), &SpatialMaterial::get_particles_anim_h_frames); + + ClassDB::bind_method(D_METHOD("set_particles_anim_v_frames", "frames"), &SpatialMaterial::set_particles_anim_v_frames); + ClassDB::bind_method(D_METHOD("get_particles_anim_v_frames"), &SpatialMaterial::get_particles_anim_v_frames); + + ClassDB::bind_method(D_METHOD("set_particles_anim_loop", "loop"), &SpatialMaterial::set_particles_anim_loop); + ClassDB::bind_method(D_METHOD("get_particles_anim_loop"), &SpatialMaterial::get_particles_anim_loop); + + ClassDB::bind_method(D_METHOD("set_depth_deep_parallax", "enable"), &SpatialMaterial::set_depth_deep_parallax); + ClassDB::bind_method(D_METHOD("is_depth_deep_parallax_enabled"), &SpatialMaterial::is_depth_deep_parallax_enabled); + + ClassDB::bind_method(D_METHOD("set_depth_deep_parallax_min_layers", "layer"), &SpatialMaterial::set_depth_deep_parallax_min_layers); + ClassDB::bind_method(D_METHOD("get_depth_deep_parallax_min_layers"), &SpatialMaterial::get_depth_deep_parallax_min_layers); + + ClassDB::bind_method(D_METHOD("set_depth_deep_parallax_max_layers", "layer"), &SpatialMaterial::set_depth_deep_parallax_max_layers); + ClassDB::bind_method(D_METHOD("get_depth_deep_parallax_max_layers"), &SpatialMaterial::get_depth_deep_parallax_max_layers); + + ClassDB::bind_method(D_METHOD("set_depth_deep_parallax_flip_tangent", "flip"), &SpatialMaterial::set_depth_deep_parallax_flip_tangent); + ClassDB::bind_method(D_METHOD("get_depth_deep_parallax_flip_tangent"), &SpatialMaterial::get_depth_deep_parallax_flip_tangent); + + ClassDB::bind_method(D_METHOD("set_depth_deep_parallax_flip_binormal", "flip"), &SpatialMaterial::set_depth_deep_parallax_flip_binormal); + ClassDB::bind_method(D_METHOD("get_depth_deep_parallax_flip_binormal"), &SpatialMaterial::get_depth_deep_parallax_flip_binormal); + + ClassDB::bind_method(D_METHOD("set_grow", "amount"), &SpatialMaterial::set_grow); + ClassDB::bind_method(D_METHOD("get_grow"), &SpatialMaterial::get_grow); + + ClassDB::bind_method(D_METHOD("set_emission_operator", "operator"), &SpatialMaterial::set_emission_operator); + ClassDB::bind_method(D_METHOD("get_emission_operator"), &SpatialMaterial::get_emission_operator); + + ClassDB::bind_method(D_METHOD("set_ao_light_affect", "amount"), &SpatialMaterial::set_ao_light_affect); + ClassDB::bind_method(D_METHOD("get_ao_light_affect"), &SpatialMaterial::get_ao_light_affect); + + ClassDB::bind_method(D_METHOD("set_alpha_scissor_threshold", "threshold"), &SpatialMaterial::set_alpha_scissor_threshold); + ClassDB::bind_method(D_METHOD("get_alpha_scissor_threshold"), &SpatialMaterial::get_alpha_scissor_threshold); + + ClassDB::bind_method(D_METHOD("set_grow_enabled", "enable"), &SpatialMaterial::set_grow_enabled); + ClassDB::bind_method(D_METHOD("is_grow_enabled"), &SpatialMaterial::is_grow_enabled); + + ClassDB::bind_method(D_METHOD("set_metallic_texture_channel", "channel"), &SpatialMaterial::set_metallic_texture_channel); + ClassDB::bind_method(D_METHOD("get_metallic_texture_channel"), &SpatialMaterial::get_metallic_texture_channel); + + ClassDB::bind_method(D_METHOD("set_roughness_texture_channel", "channel"), &SpatialMaterial::set_roughness_texture_channel); + ClassDB::bind_method(D_METHOD("get_roughness_texture_channel"), &SpatialMaterial::get_roughness_texture_channel); + + ClassDB::bind_method(D_METHOD("set_ao_texture_channel", "channel"), &SpatialMaterial::set_ao_texture_channel); + ClassDB::bind_method(D_METHOD("get_ao_texture_channel"), &SpatialMaterial::get_ao_texture_channel); + + ClassDB::bind_method(D_METHOD("set_refraction_texture_channel", "channel"), &SpatialMaterial::set_refraction_texture_channel); + ClassDB::bind_method(D_METHOD("get_refraction_texture_channel"), &SpatialMaterial::get_refraction_texture_channel); + + ClassDB::bind_method(D_METHOD("set_proximity_fade", "enabled"), &SpatialMaterial::set_proximity_fade); + ClassDB::bind_method(D_METHOD("is_proximity_fade_enabled"), &SpatialMaterial::is_proximity_fade_enabled); + + ClassDB::bind_method(D_METHOD("set_proximity_fade_distance", "distance"), &SpatialMaterial::set_proximity_fade_distance); + ClassDB::bind_method(D_METHOD("get_proximity_fade_distance"), &SpatialMaterial::get_proximity_fade_distance); + + ClassDB::bind_method(D_METHOD("set_distance_fade", "mode"), &SpatialMaterial::set_distance_fade); + ClassDB::bind_method(D_METHOD("get_distance_fade"), &SpatialMaterial::get_distance_fade); + + ClassDB::bind_method(D_METHOD("set_distance_fade_max_distance", "distance"), &SpatialMaterial::set_distance_fade_max_distance); + ClassDB::bind_method(D_METHOD("get_distance_fade_max_distance"), &SpatialMaterial::get_distance_fade_max_distance); + + ClassDB::bind_method(D_METHOD("set_distance_fade_min_distance", "distance"), &SpatialMaterial::set_distance_fade_min_distance); + ClassDB::bind_method(D_METHOD("get_distance_fade_min_distance"), &SpatialMaterial::get_distance_fade_min_distance); + + ClassDB::bind_method(D_METHOD("set_async_mode", "mode"), &SpatialMaterial::set_async_mode); + ClassDB::bind_method(D_METHOD("get_async_mode"), &SpatialMaterial::get_async_mode); + + ADD_GROUP("Flags", "flags_"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_transparent"), "set_feature", "get_feature", FEATURE_TRANSPARENT); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_use_shadow_to_opacity"), "set_flag", "get_flag", FLAG_USE_SHADOW_TO_OPACITY); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_unshaded"), "set_flag", "get_flag", FLAG_UNSHADED); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_vertex_lighting"), "set_flag", "get_flag", FLAG_USE_VERTEX_LIGHTING); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_no_depth_test"), "set_flag", "get_flag", FLAG_DISABLE_DEPTH_TEST); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_use_point_size"), "set_flag", "get_flag", FLAG_USE_POINT_SIZE); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_world_triplanar"), "set_flag", "get_flag", FLAG_TRIPLANAR_USE_WORLD); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_fixed_size"), "set_flag", "get_flag", FLAG_FIXED_SIZE); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_albedo_tex_force_srgb"), "set_flag", "get_flag", FLAG_ALBEDO_TEXTURE_FORCE_SRGB); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_do_not_receive_shadows"), "set_flag", "get_flag", FLAG_DONT_RECEIVE_SHADOWS); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_disable_ambient_light"), "set_flag", "get_flag", FLAG_DISABLE_AMBIENT_LIGHT); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_ensure_correct_normals"), "set_flag", "get_flag", FLAG_ENSURE_CORRECT_NORMALS); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_albedo_tex_msdf"), "set_flag", "get_flag", FLAG_ALBEDO_TEXTURE_SDF); + ADD_GROUP("Vertex Color", "vertex_color"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "vertex_color_use_as_albedo"), "set_flag", "get_flag", FLAG_ALBEDO_FROM_VERTEX_COLOR); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "vertex_color_is_srgb"), "set_flag", "get_flag", FLAG_SRGB_VERTEX_COLOR); + + ADD_GROUP("Parameters", "params_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "params_diffuse_mode", PROPERTY_HINT_ENUM, "Burley,Lambert,Lambert Wrap,Oren Nayar,Toon"), "set_diffuse_mode", "get_diffuse_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "params_specular_mode", PROPERTY_HINT_ENUM, "SchlickGGX,Blinn,Phong,Toon,Disabled"), "set_specular_mode", "get_specular_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "params_blend_mode", PROPERTY_HINT_ENUM, "Mix,Add,Sub,Mul"), "set_blend_mode", "get_blend_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "params_cull_mode", PROPERTY_HINT_ENUM, "Back,Front,Disabled"), "set_cull_mode", "get_cull_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "params_depth_draw_mode", PROPERTY_HINT_ENUM, "Opaque Only,Always,Never,Opaque Pre-Pass"), "set_depth_draw_mode", "get_depth_draw_mode"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "params_line_width", PROPERTY_HINT_RANGE, "0.1,128,0.1"), "set_line_width", "get_line_width"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "params_point_size", PROPERTY_HINT_RANGE, "0.1,128,0.1"), "set_point_size", "get_point_size"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "params_billboard_mode", PROPERTY_HINT_ENUM, "Disabled,Enabled,Y-Billboard,Particle Billboard"), "set_billboard_mode", "get_billboard_mode"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "params_billboard_keep_scale"), "set_flag", "get_flag", FLAG_BILLBOARD_KEEP_SCALE); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "params_grow"), "set_grow_enabled", "is_grow_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "params_grow_amount", PROPERTY_HINT_RANGE, "-16,16,0.001"), "set_grow", "get_grow"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "params_use_alpha_scissor"), "set_flag", "get_flag", FLAG_USE_ALPHA_SCISSOR); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "params_alpha_scissor_threshold", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_alpha_scissor_threshold", "get_alpha_scissor_threshold"); + ADD_GROUP("Particles Anim", "particles_anim_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "particles_anim_h_frames", PROPERTY_HINT_RANGE, "1,128,1"), "set_particles_anim_h_frames", "get_particles_anim_h_frames"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "particles_anim_v_frames", PROPERTY_HINT_RANGE, "1,128,1"), "set_particles_anim_v_frames", "get_particles_anim_v_frames"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "particles_anim_loop"), "set_particles_anim_loop", "get_particles_anim_loop"); + + ADD_GROUP("Albedo", "albedo_"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "albedo_color"), "set_albedo", "get_albedo"); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "albedo_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_ALBEDO); + + ADD_GROUP("Metallic", "metallic_"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "metallic", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_metallic", "get_metallic"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "metallic_specular", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_specular", "get_specular"); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "metallic_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_METALLIC); + ADD_PROPERTY(PropertyInfo(Variant::INT, "metallic_texture_channel", PROPERTY_HINT_ENUM, "Red,Green,Blue,Alpha,Gray"), "set_metallic_texture_channel", "get_metallic_texture_channel"); + + ADD_GROUP("Roughness", "roughness_"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "roughness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_roughness", "get_roughness"); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "roughness_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_ROUGHNESS); + ADD_PROPERTY(PropertyInfo(Variant::INT, "roughness_texture_channel", PROPERTY_HINT_ENUM, "Red,Green,Blue,Alpha,Gray"), "set_roughness_texture_channel", "get_roughness_texture_channel"); + + ADD_GROUP("Emission", "emission_"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "emission_enabled"), "set_feature", "get_feature", FEATURE_EMISSION); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "emission", PROPERTY_HINT_COLOR_NO_ALPHA), "set_emission", "get_emission"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "emission_energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_emission_energy", "get_emission_energy"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_operator", PROPERTY_HINT_ENUM, "Add,Multiply"), "set_emission_operator", "get_emission_operator"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "emission_on_uv2"), "set_flag", "get_flag", FLAG_EMISSION_ON_UV2); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "emission_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_EMISSION); + + ADD_GROUP("NormalMap", "normal_"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "normal_enabled"), "set_feature", "get_feature", FEATURE_NORMAL_MAPPING); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "normal_scale", PROPERTY_HINT_RANGE, "-16,16,0.01"), "set_normal_scale", "get_normal_scale"); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "normal_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_NORMAL); + + ADD_GROUP("Rim", "rim_"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "rim_enabled"), "set_feature", "get_feature", FEATURE_RIM); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "rim", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_rim", "get_rim"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "rim_tint", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_rim_tint", "get_rim_tint"); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "rim_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_RIM); + + ADD_GROUP("Clearcoat", "clearcoat_"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "clearcoat_enabled"), "set_feature", "get_feature", FEATURE_CLEARCOAT); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "clearcoat", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_clearcoat", "get_clearcoat"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "clearcoat_gloss", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_clearcoat_gloss", "get_clearcoat_gloss"); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "clearcoat_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_CLEARCOAT); + + ADD_GROUP("Anisotropy", "anisotropy_"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "anisotropy_enabled"), "set_feature", "get_feature", FEATURE_ANISOTROPY); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "anisotropy", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_anisotropy", "get_anisotropy"); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "anisotropy_flowmap", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_FLOWMAP); + + ADD_GROUP("Ambient Occlusion", "ao_"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "ao_enabled"), "set_feature", "get_feature", FEATURE_AMBIENT_OCCLUSION); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "ao_light_affect", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_ao_light_affect", "get_ao_light_affect"); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "ao_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_AMBIENT_OCCLUSION); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "ao_on_uv2"), "set_flag", "get_flag", FLAG_AO_ON_UV2); + ADD_PROPERTY(PropertyInfo(Variant::INT, "ao_texture_channel", PROPERTY_HINT_ENUM, "Red,Green,Blue,Alpha,Gray"), "set_ao_texture_channel", "get_ao_texture_channel"); + + ADD_GROUP("Depth", "depth_"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "depth_enabled"), "set_feature", "get_feature", FEATURE_DEPTH_MAPPING); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "depth_scale", PROPERTY_HINT_RANGE, "-16,16,0.001"), "set_depth_scale", "get_depth_scale"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "depth_deep_parallax"), "set_depth_deep_parallax", "is_depth_deep_parallax_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "depth_min_layers", PROPERTY_HINT_RANGE, "1,64,1"), "set_depth_deep_parallax_min_layers", "get_depth_deep_parallax_min_layers"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "depth_max_layers", PROPERTY_HINT_RANGE, "1,64,1"), "set_depth_deep_parallax_max_layers", "get_depth_deep_parallax_max_layers"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "depth_flip_tangent"), "set_depth_deep_parallax_flip_tangent", "get_depth_deep_parallax_flip_tangent"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "depth_flip_binormal"), "set_depth_deep_parallax_flip_binormal", "get_depth_deep_parallax_flip_binormal"); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "depth_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_DEPTH); + + ADD_GROUP("Subsurf Scatter", "subsurf_scatter_"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "subsurf_scatter_enabled"), "set_feature", "get_feature", FEATURE_SUBSURACE_SCATTERING); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "subsurf_scatter_strength", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_subsurface_scattering_strength", "get_subsurface_scattering_strength"); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "subsurf_scatter_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_SUBSURFACE_SCATTERING); + + ADD_GROUP("Transmission", "transmission_"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "transmission_enabled"), "set_feature", "get_feature", FEATURE_TRANSMISSION); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "transmission", PROPERTY_HINT_COLOR_NO_ALPHA), "set_transmission", "get_transmission"); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "transmission_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_TRANSMISSION); + + ADD_GROUP("Refraction", "refraction_"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "refraction_enabled"), "set_feature", "get_feature", FEATURE_REFRACTION); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "refraction_scale", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_refraction", "get_refraction"); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "refraction_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_REFRACTION); + ADD_PROPERTY(PropertyInfo(Variant::INT, "refraction_texture_channel", PROPERTY_HINT_ENUM, "Red,Green,Blue,Alpha,Gray"), "set_refraction_texture_channel", "get_refraction_texture_channel"); + + ADD_GROUP("Detail", "detail_"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "detail_enabled"), "set_feature", "get_feature", FEATURE_DETAIL); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "detail_mask", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_DETAIL_MASK); + ADD_PROPERTY(PropertyInfo(Variant::INT, "detail_blend_mode", PROPERTY_HINT_ENUM, "Mix,Add,Sub,Mul"), "set_detail_blend_mode", "get_detail_blend_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "detail_uv_layer", PROPERTY_HINT_ENUM, "UV1,UV2"), "set_detail_uv", "get_detail_uv"); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "detail_albedo", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_DETAIL_ALBEDO); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "detail_normal", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_DETAIL_NORMAL); + + ADD_GROUP("UV1", "uv1_"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "uv1_scale", PROPERTY_HINT_LINK), "set_uv1_scale", "get_uv1_scale"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "uv1_offset"), "set_uv1_offset", "get_uv1_offset"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "uv1_triplanar"), "set_flag", "get_flag", FLAG_UV1_USE_TRIPLANAR); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "uv1_triplanar_sharpness", PROPERTY_HINT_EXP_EASING), "set_uv1_triplanar_blend_sharpness", "get_uv1_triplanar_blend_sharpness"); + + ADD_GROUP("UV2", "uv2_"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "uv2_scale", PROPERTY_HINT_LINK), "set_uv2_scale", "get_uv2_scale"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "uv2_offset"), "set_uv2_offset", "get_uv2_offset"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "uv2_triplanar"), "set_flag", "get_flag", FLAG_UV2_USE_TRIPLANAR); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "uv2_triplanar_sharpness", PROPERTY_HINT_EXP_EASING), "set_uv2_triplanar_blend_sharpness", "get_uv2_triplanar_blend_sharpness"); + + ADD_GROUP("Proximity Fade", "proximity_fade_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "proximity_fade_enable"), "set_proximity_fade", "is_proximity_fade_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "proximity_fade_distance", PROPERTY_HINT_RANGE, "0,4096,0.01"), "set_proximity_fade_distance", "get_proximity_fade_distance"); + ADD_GROUP("Distance Fade", "distance_fade_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "distance_fade_mode", PROPERTY_HINT_ENUM, "Disabled,PixelAlpha,PixelDither,ObjectDither"), "set_distance_fade", "get_distance_fade"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "distance_fade_min_distance", PROPERTY_HINT_RANGE, "0,4096,0.01"), "set_distance_fade_min_distance", "get_distance_fade_min_distance"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "distance_fade_max_distance", PROPERTY_HINT_RANGE, "0,4096,0.01"), "set_distance_fade_max_distance", "get_distance_fade_max_distance"); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "async_mode", PROPERTY_HINT_ENUM, "Visible,Hidden"), "set_async_mode", "get_async_mode"); + + BIND_ENUM_CONSTANT(TEXTURE_ALBEDO); + BIND_ENUM_CONSTANT(TEXTURE_METALLIC); + BIND_ENUM_CONSTANT(TEXTURE_ROUGHNESS); + BIND_ENUM_CONSTANT(TEXTURE_EMISSION); + BIND_ENUM_CONSTANT(TEXTURE_NORMAL); + BIND_ENUM_CONSTANT(TEXTURE_RIM); + BIND_ENUM_CONSTANT(TEXTURE_CLEARCOAT); + BIND_ENUM_CONSTANT(TEXTURE_FLOWMAP); + BIND_ENUM_CONSTANT(TEXTURE_AMBIENT_OCCLUSION); + BIND_ENUM_CONSTANT(TEXTURE_DEPTH); + BIND_ENUM_CONSTANT(TEXTURE_SUBSURFACE_SCATTERING); + BIND_ENUM_CONSTANT(TEXTURE_TRANSMISSION); + BIND_ENUM_CONSTANT(TEXTURE_REFRACTION); + BIND_ENUM_CONSTANT(TEXTURE_DETAIL_MASK); + BIND_ENUM_CONSTANT(TEXTURE_DETAIL_ALBEDO); + BIND_ENUM_CONSTANT(TEXTURE_DETAIL_NORMAL); + BIND_ENUM_CONSTANT(TEXTURE_MAX); + + BIND_ENUM_CONSTANT(DETAIL_UV_1); + BIND_ENUM_CONSTANT(DETAIL_UV_2); + + BIND_ENUM_CONSTANT(FEATURE_TRANSPARENT); + BIND_ENUM_CONSTANT(FEATURE_EMISSION); + BIND_ENUM_CONSTANT(FEATURE_NORMAL_MAPPING); + BIND_ENUM_CONSTANT(FEATURE_RIM); + BIND_ENUM_CONSTANT(FEATURE_CLEARCOAT); + BIND_ENUM_CONSTANT(FEATURE_ANISOTROPY); + BIND_ENUM_CONSTANT(FEATURE_AMBIENT_OCCLUSION); + BIND_ENUM_CONSTANT(FEATURE_DEPTH_MAPPING); + BIND_ENUM_CONSTANT(FEATURE_SUBSURACE_SCATTERING); + BIND_ENUM_CONSTANT(FEATURE_TRANSMISSION); + BIND_ENUM_CONSTANT(FEATURE_REFRACTION); + BIND_ENUM_CONSTANT(FEATURE_DETAIL); + BIND_ENUM_CONSTANT(FEATURE_MAX); + + BIND_ENUM_CONSTANT(BLEND_MODE_MIX); + BIND_ENUM_CONSTANT(BLEND_MODE_ADD); + BIND_ENUM_CONSTANT(BLEND_MODE_SUB); + BIND_ENUM_CONSTANT(BLEND_MODE_MUL); + + BIND_ENUM_CONSTANT(DEPTH_DRAW_OPAQUE_ONLY); + BIND_ENUM_CONSTANT(DEPTH_DRAW_ALWAYS); + BIND_ENUM_CONSTANT(DEPTH_DRAW_DISABLED); + BIND_ENUM_CONSTANT(DEPTH_DRAW_ALPHA_OPAQUE_PREPASS); + + BIND_ENUM_CONSTANT(CULL_BACK); + BIND_ENUM_CONSTANT(CULL_FRONT); + BIND_ENUM_CONSTANT(CULL_DISABLED); + + BIND_ENUM_CONSTANT(FLAG_UNSHADED); + BIND_ENUM_CONSTANT(FLAG_USE_VERTEX_LIGHTING); + BIND_ENUM_CONSTANT(FLAG_DISABLE_DEPTH_TEST); + BIND_ENUM_CONSTANT(FLAG_ALBEDO_FROM_VERTEX_COLOR); + BIND_ENUM_CONSTANT(FLAG_SRGB_VERTEX_COLOR); + BIND_ENUM_CONSTANT(FLAG_USE_POINT_SIZE); + BIND_ENUM_CONSTANT(FLAG_FIXED_SIZE); + BIND_ENUM_CONSTANT(FLAG_BILLBOARD_KEEP_SCALE); + BIND_ENUM_CONSTANT(FLAG_UV1_USE_TRIPLANAR); + BIND_ENUM_CONSTANT(FLAG_UV2_USE_TRIPLANAR); + BIND_ENUM_CONSTANT(FLAG_AO_ON_UV2); + BIND_ENUM_CONSTANT(FLAG_EMISSION_ON_UV2); + BIND_ENUM_CONSTANT(FLAG_USE_ALPHA_SCISSOR); + BIND_ENUM_CONSTANT(FLAG_TRIPLANAR_USE_WORLD); + BIND_ENUM_CONSTANT(FLAG_ALBEDO_TEXTURE_FORCE_SRGB); + BIND_ENUM_CONSTANT(FLAG_DONT_RECEIVE_SHADOWS); + BIND_ENUM_CONSTANT(FLAG_DISABLE_AMBIENT_LIGHT); + BIND_ENUM_CONSTANT(FLAG_ENSURE_CORRECT_NORMALS); + BIND_ENUM_CONSTANT(FLAG_USE_SHADOW_TO_OPACITY); + BIND_ENUM_CONSTANT(FLAG_ALBEDO_TEXTURE_SDF); + BIND_ENUM_CONSTANT(FLAG_MAX); + + BIND_ENUM_CONSTANT(DIFFUSE_BURLEY); + BIND_ENUM_CONSTANT(DIFFUSE_LAMBERT); + BIND_ENUM_CONSTANT(DIFFUSE_LAMBERT_WRAP); + BIND_ENUM_CONSTANT(DIFFUSE_OREN_NAYAR); + BIND_ENUM_CONSTANT(DIFFUSE_TOON); + + BIND_ENUM_CONSTANT(SPECULAR_SCHLICK_GGX); + BIND_ENUM_CONSTANT(SPECULAR_BLINN); + BIND_ENUM_CONSTANT(SPECULAR_PHONG); + BIND_ENUM_CONSTANT(SPECULAR_TOON); + BIND_ENUM_CONSTANT(SPECULAR_DISABLED); + + BIND_ENUM_CONSTANT(BILLBOARD_DISABLED); + BIND_ENUM_CONSTANT(BILLBOARD_ENABLED); + BIND_ENUM_CONSTANT(BILLBOARD_FIXED_Y); + BIND_ENUM_CONSTANT(BILLBOARD_PARTICLES); + + BIND_ENUM_CONSTANT(TEXTURE_CHANNEL_RED); + BIND_ENUM_CONSTANT(TEXTURE_CHANNEL_GREEN); + BIND_ENUM_CONSTANT(TEXTURE_CHANNEL_BLUE); + BIND_ENUM_CONSTANT(TEXTURE_CHANNEL_ALPHA); + BIND_ENUM_CONSTANT(TEXTURE_CHANNEL_GRAYSCALE); + + BIND_ENUM_CONSTANT(EMISSION_OP_ADD); + BIND_ENUM_CONSTANT(EMISSION_OP_MULTIPLY); + + BIND_ENUM_CONSTANT(DISTANCE_FADE_DISABLED); + BIND_ENUM_CONSTANT(DISTANCE_FADE_PIXEL_ALPHA); + BIND_ENUM_CONSTANT(DISTANCE_FADE_PIXEL_DITHER); + BIND_ENUM_CONSTANT(DISTANCE_FADE_OBJECT_DITHER); + + BIND_ENUM_CONSTANT(ASYNC_MODE_VISIBLE); + BIND_ENUM_CONSTANT(ASYNC_MODE_HIDDEN); +} + +SpatialMaterial::SpatialMaterial() : + element(this) { + // Initialize to the same values as the shader + set_albedo(Color(1.0, 1.0, 1.0, 1.0)); + set_specular(0.5); + set_roughness(1.0); + set_metallic(0.0); + set_emission(Color(0, 0, 0)); + set_emission_energy(1.0); + set_normal_scale(1); + set_rim(1.0); + set_rim_tint(0.5); + set_clearcoat(1); + set_clearcoat_gloss(0.5); + set_anisotropy(0); + set_depth_scale(0.05); + set_subsurface_scattering_strength(0); + set_transmission(Color(0, 0, 0)); + set_refraction(0.05); + set_line_width(1); + set_point_size(1); + set_uv1_offset(Vector3(0, 0, 0)); + set_uv1_scale(Vector3(1, 1, 1)); + set_uv1_triplanar_blend_sharpness(1); + set_uv2_offset(Vector3(0, 0, 0)); + set_uv2_scale(Vector3(1, 1, 1)); + set_uv2_triplanar_blend_sharpness(1); + set_billboard_mode(BILLBOARD_DISABLED); + set_particles_anim_h_frames(1); + set_particles_anim_v_frames(1); + set_particles_anim_loop(false); + set_alpha_scissor_threshold(0.98); + emission_op = EMISSION_OP_ADD; + + proximity_fade_enabled = false; + distance_fade = DISTANCE_FADE_DISABLED; + set_proximity_fade_distance(1); + set_distance_fade_min_distance(0); + set_distance_fade_max_distance(10); + + set_ao_light_affect(0.0); + + set_metallic_texture_channel(TEXTURE_CHANNEL_RED); + set_roughness_texture_channel(TEXTURE_CHANNEL_RED); + set_ao_texture_channel(TEXTURE_CHANNEL_RED); + set_refraction_texture_channel(TEXTURE_CHANNEL_RED); + + grow_enabled = false; + set_grow(0.0); + + deep_parallax = false; + depth_parallax_flip_tangent = false; + depth_parallax_flip_binormal = false; + set_depth_deep_parallax_min_layers(8); + set_depth_deep_parallax_max_layers(32); + set_depth_deep_parallax_flip_tangent(false); //also sets binormal + + detail_uv = DETAIL_UV_1; + blend_mode = BLEND_MODE_MIX; + detail_blend_mode = BLEND_MODE_MIX; + depth_draw_mode = DEPTH_DRAW_OPAQUE_ONLY; + cull_mode = CULL_BACK; + for (int i = 0; i < FLAG_MAX; i++) { + flags[i] = false; + } + + force_vertex_shading = GLOBAL_GET("rendering/quality/shading/force_vertex_shading"); + + diffuse_mode = DIFFUSE_BURLEY; + specular_mode = SPECULAR_SCHLICK_GGX; + + async_mode = ASYNC_MODE_VISIBLE; + + for (int i = 0; i < FEATURE_MAX; i++) { + features[i] = false; + } + + current_key.key = 0; + current_key.invalid_key = 1; + is_initialized = true; + _queue_shader_change(); +} + +SpatialMaterial::~SpatialMaterial() { + material_mutex.lock(); + + if (shader_map.has(current_key)) { + shader_map[current_key].users--; + if (shader_map[current_key].users == 0) { + //deallocate shader, as it's no longer in use + RS::get_singleton()->free(shader_map[current_key].shader); + shader_map.erase(current_key); + } + + RS::get_singleton()->material_set_shader(_get_material(), RID()); + } + + material_mutex.unlock(); +} diff --git a/scene/resources/material/spatial_material.h b/scene/resources/material/spatial_material.h new file mode 100644 index 000000000..041abfc08 --- /dev/null +++ b/scene/resources/material/spatial_material.h @@ -0,0 +1,601 @@ +#ifndef SPATIAL_MATERIAL_H +#define SPATIAL_MATERIAL_H + +/*************************************************************************/ +/* material.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "core/containers/self_list.h" + +#include "scene/resources/material/material.h" + +#include "scene/resources/shader.h" +#include "core/servers/rendering/rendering_server.h" + +class Texture; + +class SpatialMaterial : public Material { + GDCLASS(SpatialMaterial, Material); + +public: + enum TextureParam { + TEXTURE_ALBEDO, + TEXTURE_METALLIC, + TEXTURE_ROUGHNESS, + TEXTURE_EMISSION, + TEXTURE_NORMAL, + TEXTURE_RIM, + TEXTURE_CLEARCOAT, + TEXTURE_FLOWMAP, + TEXTURE_AMBIENT_OCCLUSION, + TEXTURE_DEPTH, + TEXTURE_SUBSURFACE_SCATTERING, + TEXTURE_TRANSMISSION, + TEXTURE_REFRACTION, + TEXTURE_DETAIL_MASK, + TEXTURE_DETAIL_ALBEDO, + TEXTURE_DETAIL_NORMAL, + TEXTURE_MAX + + }; + + enum DetailUV { + DETAIL_UV_1, + DETAIL_UV_2 + }; + + enum Feature { + FEATURE_TRANSPARENT, + FEATURE_EMISSION, + FEATURE_NORMAL_MAPPING, + FEATURE_RIM, + FEATURE_CLEARCOAT, + FEATURE_ANISOTROPY, + FEATURE_AMBIENT_OCCLUSION, + FEATURE_DEPTH_MAPPING, + FEATURE_SUBSURACE_SCATTERING, + FEATURE_TRANSMISSION, + FEATURE_REFRACTION, + FEATURE_DETAIL, + FEATURE_MAX + }; + + enum BlendMode { + BLEND_MODE_MIX, + BLEND_MODE_ADD, + BLEND_MODE_SUB, + BLEND_MODE_MUL, + }; + + enum DepthDrawMode { + DEPTH_DRAW_OPAQUE_ONLY, + DEPTH_DRAW_ALWAYS, + DEPTH_DRAW_DISABLED, + DEPTH_DRAW_ALPHA_OPAQUE_PREPASS + + }; + + enum CullMode { + CULL_BACK, + CULL_FRONT, + CULL_DISABLED + }; + + enum Flags { + FLAG_UNSHADED, + FLAG_USE_VERTEX_LIGHTING, + FLAG_DISABLE_DEPTH_TEST, + FLAG_ALBEDO_FROM_VERTEX_COLOR, + FLAG_SRGB_VERTEX_COLOR, + FLAG_USE_POINT_SIZE, + FLAG_FIXED_SIZE, + FLAG_BILLBOARD_KEEP_SCALE, + FLAG_UV1_USE_TRIPLANAR, + FLAG_UV2_USE_TRIPLANAR, + FLAG_TRIPLANAR_USE_WORLD, + FLAG_AO_ON_UV2, + FLAG_EMISSION_ON_UV2, + FLAG_USE_ALPHA_SCISSOR, + FLAG_ALBEDO_TEXTURE_FORCE_SRGB, + FLAG_DONT_RECEIVE_SHADOWS, + FLAG_ENSURE_CORRECT_NORMALS, + FLAG_DISABLE_AMBIENT_LIGHT, + FLAG_USE_SHADOW_TO_OPACITY, + FLAG_ALBEDO_TEXTURE_SDF, + FLAG_MAX + }; + + enum DiffuseMode { + DIFFUSE_BURLEY, + DIFFUSE_LAMBERT, + DIFFUSE_LAMBERT_WRAP, + DIFFUSE_OREN_NAYAR, + DIFFUSE_TOON, + }; + + enum SpecularMode { + SPECULAR_SCHLICK_GGX, + SPECULAR_BLINN, + SPECULAR_PHONG, + SPECULAR_TOON, + SPECULAR_DISABLED, + }; + + enum BillboardMode { + BILLBOARD_DISABLED, + BILLBOARD_ENABLED, + BILLBOARD_FIXED_Y, + BILLBOARD_PARTICLES, + }; + + enum TextureChannel { + TEXTURE_CHANNEL_RED, + TEXTURE_CHANNEL_GREEN, + TEXTURE_CHANNEL_BLUE, + TEXTURE_CHANNEL_ALPHA, + TEXTURE_CHANNEL_GRAYSCALE + }; + + enum EmissionOperator { + EMISSION_OP_ADD, + EMISSION_OP_MULTIPLY + }; + + enum DistanceFadeMode { + DISTANCE_FADE_DISABLED, + DISTANCE_FADE_PIXEL_ALPHA, + DISTANCE_FADE_PIXEL_DITHER, + DISTANCE_FADE_OBJECT_DITHER, + }; + + enum AsyncMode { + ASYNC_MODE_VISIBLE, + ASYNC_MODE_HIDDEN, + }; + +private: + union MaterialKey { + struct { + uint64_t feature_mask : 12; + uint64_t detail_uv : 1; + uint64_t blend_mode : 2; + uint64_t depth_draw_mode : 2; + uint64_t cull_mode : 2; + uint64_t flags : 20; + uint64_t detail_blend_mode : 2; + uint64_t diffuse_mode : 3; + uint64_t specular_mode : 3; + uint64_t invalid_key : 1; + uint64_t deep_parallax : 1; + uint64_t billboard_mode : 2; + uint64_t grow : 1; + uint64_t proximity_fade : 1; + uint64_t distance_fade : 2; + uint64_t emission_op : 1; + uint64_t texture_metallic : 1; + uint64_t texture_roughness : 1; + //uint64_t reserved : 6; + }; + + uint64_t key; + + bool operator<(const MaterialKey &p_key) const { + return key < p_key.key; + } + }; + + struct ShaderData { + RID shader; + int users; + }; + + static RBMap shader_map; + + MaterialKey current_key; + + _FORCE_INLINE_ MaterialKey _compute_key() const { + MaterialKey mk; + mk.key = 0; + for (int i = 0; i < FEATURE_MAX; i++) { + if (features[i]) { + mk.feature_mask |= ((uint64_t)1 << i); + } + } + mk.detail_uv = detail_uv; + mk.blend_mode = blend_mode; + mk.depth_draw_mode = depth_draw_mode; + mk.cull_mode = cull_mode; + for (int i = 0; i < FLAG_MAX; i++) { + if (flags[i]) { + mk.flags |= ((uint64_t)1 << i); + } + } + mk.detail_blend_mode = detail_blend_mode; + mk.diffuse_mode = diffuse_mode; + mk.specular_mode = specular_mode; + mk.billboard_mode = billboard_mode; + mk.deep_parallax = deep_parallax ? 1 : 0; + mk.grow = grow_enabled; + mk.proximity_fade = proximity_fade_enabled; + mk.distance_fade = distance_fade; + mk.emission_op = emission_op; + mk.texture_metallic = textures[TEXTURE_METALLIC].is_valid() ? 1 : 0; + mk.texture_roughness = textures[TEXTURE_ROUGHNESS].is_valid() ? 1 : 0; + + return mk; + } + + struct ShaderNames { + StringName albedo; + StringName specular; + StringName metallic; + StringName roughness; + StringName emission; + StringName emission_energy; + StringName normal_scale; + StringName rim; + StringName rim_tint; + StringName clearcoat; + StringName clearcoat_gloss; + StringName anisotropy; + StringName depth_scale; + StringName subsurface_scattering_strength; + StringName transmission; + StringName refraction; + StringName point_size; + StringName uv1_scale; + StringName uv1_offset; + StringName uv2_scale; + StringName uv2_offset; + StringName particles_anim_h_frames; + StringName particles_anim_v_frames; + StringName particles_anim_loop; + StringName depth_min_layers; + StringName depth_max_layers; + StringName depth_flip; + StringName uv1_blend_sharpness; + StringName uv2_blend_sharpness; + StringName grow; + StringName proximity_fade_distance; + StringName distance_fade_min; + StringName distance_fade_max; + StringName ao_light_affect; + + StringName metallic_texture_channel; + StringName roughness_texture_channel; + StringName ao_texture_channel; + StringName clearcoat_texture_channel; + StringName rim_texture_channel; + StringName depth_texture_channel; + StringName refraction_texture_channel; + StringName alpha_scissor_threshold; + + StringName texture_names[TEXTURE_MAX]; + }; + + static Mutex material_mutex; + static SelfList::List *dirty_materials; + static ShaderNames *shader_names; + + SelfList element; + + void _update_shader(); + _FORCE_INLINE_ void _queue_shader_change(); + _FORCE_INLINE_ bool _is_shader_dirty() const; + + bool is_initialized = false; + Color albedo; + float specular; + float metallic; + float roughness; + Color emission; + float emission_energy; + float normal_scale; + float rim; + float rim_tint; + float clearcoat; + float clearcoat_gloss; + float anisotropy; + float depth_scale; + float subsurface_scattering_strength; + Color transmission; + float refraction; + float line_width; + float point_size; + float alpha_scissor_threshold; + bool grow_enabled; + float ao_light_affect; + float grow; + int particles_anim_h_frames; + int particles_anim_v_frames; + bool particles_anim_loop; + + Vector3 uv1_scale; + Vector3 uv1_offset; + float uv1_triplanar_sharpness; + + Vector3 uv2_scale; + Vector3 uv2_offset; + float uv2_triplanar_sharpness; + + DetailUV detail_uv; + + bool deep_parallax; + int deep_parallax_min_layers; + int deep_parallax_max_layers; + bool depth_parallax_flip_tangent; + bool depth_parallax_flip_binormal; + + bool proximity_fade_enabled; + float proximity_fade_distance; + + DistanceFadeMode distance_fade; + float distance_fade_max_distance; + float distance_fade_min_distance; + + BlendMode blend_mode; + BlendMode detail_blend_mode; + DepthDrawMode depth_draw_mode; + CullMode cull_mode; + bool flags[FLAG_MAX]; + SpecularMode specular_mode; + DiffuseMode diffuse_mode; + BillboardMode billboard_mode; + EmissionOperator emission_op; + AsyncMode async_mode; + + TextureChannel metallic_texture_channel; + TextureChannel roughness_texture_channel; + TextureChannel ao_texture_channel; + TextureChannel refraction_texture_channel; + + bool features[FEATURE_MAX]; + + Ref textures[TEXTURE_MAX]; + + bool force_vertex_shading = false; + + _FORCE_INLINE_ void _validate_feature(const String &text, Feature feature, PropertyInfo &property) const; + + static HashMap> materials_for_2d; //used by Sprite3D and other stuff + + void _validate_high_end(const String &text, PropertyInfo &property) const; + +protected: + static void _bind_methods(); + void _validate_property(PropertyInfo &property) const; + virtual bool _can_do_next_pass() const { return true; } + +public: + void set_albedo(const Color &p_albedo); + Color get_albedo() const; + + void set_specular(float p_specular); + float get_specular() const; + + void set_metallic(float p_metallic); + float get_metallic() const; + + void set_roughness(float p_roughness); + float get_roughness() const; + + void set_emission(const Color &p_emission); + Color get_emission() const; + + void set_emission_energy(float p_emission_energy); + float get_emission_energy() const; + + void set_normal_scale(float p_normal_scale); + float get_normal_scale() const; + + void set_rim(float p_rim); + float get_rim() const; + + void set_rim_tint(float p_rim_tint); + float get_rim_tint() const; + + void set_ao_light_affect(float p_ao_light_affect); + float get_ao_light_affect() const; + + void set_clearcoat(float p_clearcoat); + float get_clearcoat() const; + + void set_clearcoat_gloss(float p_clearcoat_gloss); + float get_clearcoat_gloss() const; + + void set_anisotropy(float p_anisotropy); + float get_anisotropy() const; + + void set_depth_scale(float p_depth_scale); + float get_depth_scale() const; + + void set_depth_deep_parallax(bool p_enable); + bool is_depth_deep_parallax_enabled() const; + + void set_depth_deep_parallax_min_layers(int p_layer); + int get_depth_deep_parallax_min_layers() const; + + void set_depth_deep_parallax_max_layers(int p_layer); + int get_depth_deep_parallax_max_layers() const; + + void set_depth_deep_parallax_flip_tangent(bool p_flip); + bool get_depth_deep_parallax_flip_tangent() const; + + void set_depth_deep_parallax_flip_binormal(bool p_flip); + bool get_depth_deep_parallax_flip_binormal() const; + + void set_subsurface_scattering_strength(float p_subsurface_scattering_strength); + float get_subsurface_scattering_strength() const; + + void set_transmission(const Color &p_transmission); + Color get_transmission() const; + + void set_refraction(float p_refraction); + float get_refraction() const; + + void set_line_width(float p_line_width); + float get_line_width() const; + + void set_point_size(float p_point_size); + float get_point_size() const; + + void set_detail_uv(DetailUV p_detail_uv); + DetailUV get_detail_uv() const; + + void set_blend_mode(BlendMode p_mode); + BlendMode get_blend_mode() const; + + void set_detail_blend_mode(BlendMode p_mode); + BlendMode get_detail_blend_mode() const; + + void set_depth_draw_mode(DepthDrawMode p_mode); + DepthDrawMode get_depth_draw_mode() const; + + void set_cull_mode(CullMode p_mode); + CullMode get_cull_mode() const; + + void set_diffuse_mode(DiffuseMode p_mode); + DiffuseMode get_diffuse_mode() const; + + void set_specular_mode(SpecularMode p_mode); + SpecularMode get_specular_mode() const; + + void set_flag(Flags p_flag, bool p_enabled); + bool get_flag(Flags p_flag) const; + + void set_texture(TextureParam p_param, const Ref &p_texture); + Ref get_texture(TextureParam p_param) const; + // Used only for shader material conversion + Ref get_texture_by_name(StringName p_name) const; + + void set_feature(Feature p_feature, bool p_enabled); + bool get_feature(Feature p_feature) const; + + void set_uv1_scale(const Vector3 &p_scale); + Vector3 get_uv1_scale() const; + + void set_uv1_offset(const Vector3 &p_offset); + Vector3 get_uv1_offset() const; + + void set_uv1_triplanar_blend_sharpness(float p_sharpness); + float get_uv1_triplanar_blend_sharpness() const; + + void set_uv2_scale(const Vector3 &p_scale); + Vector3 get_uv2_scale() const; + + void set_uv2_offset(const Vector3 &p_offset); + Vector3 get_uv2_offset() const; + + void set_uv2_triplanar_blend_sharpness(float p_sharpness); + float get_uv2_triplanar_blend_sharpness() const; + + void set_billboard_mode(BillboardMode p_mode); + BillboardMode get_billboard_mode() const; + + void set_particles_anim_h_frames(int p_frames); + int get_particles_anim_h_frames() const; + void set_particles_anim_v_frames(int p_frames); + int get_particles_anim_v_frames() const; + + void set_particles_anim_loop(bool p_loop); + bool get_particles_anim_loop() const; + + void set_grow_enabled(bool p_enable); + bool is_grow_enabled() const; + + void set_grow(float p_grow); + float get_grow() const; + + void set_alpha_scissor_threshold(float p_threshold); + float get_alpha_scissor_threshold() const; + + void set_on_top_of_alpha(); + + void set_proximity_fade(bool p_enable); + bool is_proximity_fade_enabled() const; + + void set_proximity_fade_distance(float p_distance); + float get_proximity_fade_distance() const; + + void set_distance_fade(DistanceFadeMode p_mode); + DistanceFadeMode get_distance_fade() const; + + void set_distance_fade_max_distance(float p_distance); + float get_distance_fade_max_distance() const; + + void set_distance_fade_min_distance(float p_distance); + float get_distance_fade_min_distance() const; + + void set_emission_operator(EmissionOperator p_op); + EmissionOperator get_emission_operator() const; + + void set_metallic_texture_channel(TextureChannel p_channel); + TextureChannel get_metallic_texture_channel() const; + void set_roughness_texture_channel(TextureChannel p_channel); + TextureChannel get_roughness_texture_channel() const; + void set_ao_texture_channel(TextureChannel p_channel); + TextureChannel get_ao_texture_channel() const; + void set_refraction_texture_channel(TextureChannel p_channel); + TextureChannel get_refraction_texture_channel() const; + + void set_async_mode(AsyncMode p_mode); + AsyncMode get_async_mode() const; + + static void init_shaders(); + static void finish_shaders(); + static void flush_changes(); + + static RID get_material_rid_for_2d(bool p_shaded, bool p_transparent, bool p_double_sided, bool p_cut_alpha, bool p_opaque_prepass, bool p_billboard = false, bool p_billboard_y = false, bool p_no_depth_test = false, bool p_fixed_size = false, bool p_sdf = false); + + RID get_shader_rid() const; + + virtual Shader::Mode get_shader_mode() const; + + SpatialMaterial(); + virtual ~SpatialMaterial(); +}; + +VARIANT_ENUM_CAST(SpatialMaterial::TextureParam) +VARIANT_ENUM_CAST(SpatialMaterial::DetailUV) +VARIANT_ENUM_CAST(SpatialMaterial::Feature) +VARIANT_ENUM_CAST(SpatialMaterial::BlendMode) +VARIANT_ENUM_CAST(SpatialMaterial::DepthDrawMode) +VARIANT_ENUM_CAST(SpatialMaterial::CullMode) +VARIANT_ENUM_CAST(SpatialMaterial::Flags) +VARIANT_ENUM_CAST(SpatialMaterial::DiffuseMode) +VARIANT_ENUM_CAST(SpatialMaterial::SpecularMode) +VARIANT_ENUM_CAST(SpatialMaterial::BillboardMode) +VARIANT_ENUM_CAST(SpatialMaterial::TextureChannel) +VARIANT_ENUM_CAST(SpatialMaterial::EmissionOperator) +VARIANT_ENUM_CAST(SpatialMaterial::DistanceFadeMode) +VARIANT_ENUM_CAST(SpatialMaterial::AsyncMode) + +////////////////////// + +#endif diff --git a/scene/resources/navigation/navigation_mesh.cpp b/scene/resources/navigation/navigation_mesh.cpp index d70db7a31..9c50153cf 100644 --- a/scene/resources/navigation/navigation_mesh.cpp +++ b/scene/resources/navigation/navigation_mesh.cpp @@ -31,6 +31,7 @@ #include "navigation_mesh.h" #include "servers/navigation_server.h" +#include "scene/resources/material/spatial_material.h" void NavigationMesh::create_from_mesh(const Ref &p_mesh) { ERR_FAIL_COND(p_mesh.is_null()); diff --git a/servers/navigation_server.cpp b/servers/navigation_server.cpp index d89a47dba..c014e0981 100644 --- a/servers/navigation_server.cpp +++ b/servers/navigation_server.cpp @@ -40,6 +40,7 @@ #include "core/config/engine.h" #include "core/config/project_settings.h" #include "scene/resources/material/material.h" +#include "scene/resources/material/spatial_material.h" #endif NavigationServer *NavigationServer::singleton = nullptr;