└── addons └── udim_material ├── plugin.cfg ├── plugin_entry_point.gd ├── inspector_plugins ├── udim_texture_mapper.gd └── udim_texture_mapper_interface.gd ├── icons ├── udim_shader_material.svg.import └── udim_shader_material.svg ├── LISCENSE ├── UDIMShaderMaterial.gdshader ├── UDIMTextureTileset.gd └── UDIMShaderMaterial.gd /addons/udim_material/plugin.cfg: -------------------------------------------------------------------------------- 1 | [plugin] 2 | 3 | name="UDIM Shader Material" 4 | description="Adds a material to render Meshes/UVs built using UDIM standards. Also adds an import utility to easily import appropriately named UDIM tile textures." 5 | author="pkmollman" 6 | version="0.2" 7 | script="plugin_entry_point.gd" 8 | -------------------------------------------------------------------------------- /addons/udim_material/plugin_entry_point.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends EditorPlugin 3 | 4 | var udim_mapper: UDIMTextureMapperPlugin = null 5 | 6 | func _enter_tree(): 7 | udim_mapper = UDIMTextureMapperPlugin.new() 8 | add_inspector_plugin(udim_mapper) 9 | 10 | func _exit_tree(): 11 | remove_inspector_plugin(udim_mapper) 12 | -------------------------------------------------------------------------------- /addons/udim_material/inspector_plugins/udim_texture_mapper.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | class_name UDIMTextureMapperPlugin 3 | extends EditorInspectorPlugin 4 | 5 | func _can_handle(object): 6 | if object is UDIMTextureTileset: 7 | return true 8 | return false 9 | 10 | 11 | func _parse_begin(object): 12 | # We handle properties of type integer. 13 | if object is UDIMTextureTileset: 14 | # Create an instance of the custom property editor and register 15 | # it to a specific property path. 16 | var mapper_button: UDIMTextureMapper = UDIMTextureMapper.new() 17 | mapper_button.tileset = object 18 | add_custom_control(mapper_button) 19 | # Inform the editor to remove the default property editor for 20 | # this property type. 21 | -------------------------------------------------------------------------------- /addons/udim_material/icons/udim_shader_material.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://3ceebegtfl78" 6 | path="res://.godot/imported/udim_shader_material.svg-b15b65c1a5fe79edea50c66202393fd3.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/udim_material/icons/udim_shader_material.svg" 14 | dest_files=["res://.godot/imported/udim_shader_material.svg-b15b65c1a5fe79edea50c66202393fd3.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=1.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | -------------------------------------------------------------------------------- /addons/udim_material/LISCENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 pkmollman 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /addons/udim_material/inspector_plugins/udim_texture_mapper_interface.gd: -------------------------------------------------------------------------------- 1 | class_name UDIMTextureMapper 2 | extends Button 3 | 4 | @export var tileset: UDIMTextureTileset = null 5 | 6 | # Called when the node enters the scene tree for the first time. 7 | func _ready(): 8 | text = "Import UDIM Texture Set" 9 | pressed.connect(open_select_dialog) 10 | 11 | 12 | func open_select_dialog(): 13 | var dialog = EditorFileDialog.new() 14 | dialog.file_mode = EditorFileDialog.FILE_MODE_OPEN_FILE 15 | dialog.size = Vector2(800, 600) 16 | dialog.initial_position = Window.WINDOW_INITIAL_POSITION_CENTER_MAIN_WINDOW_SCREEN 17 | dialog.file_selected.connect(udim_dir_selected) 18 | add_child(dialog) 19 | dialog.show() 20 | 21 | func udim_dir_selected(file_path: String): 22 | var path_split = file_path.split(("/")) 23 | if len(path_split) < 3 or path_split[0] != "res:": 24 | push_error("Invalid UDIM import path") 25 | return 26 | var dirr = "/".join(path_split.slice(0,len(path_split)-1)) 27 | var regex = RegEx.new() 28 | regex.compile('(.*)(\\d{4})(\\.\\w+)') 29 | var reg_matches = regex.search_all(path_split[len(path_split)-1]) 30 | if len(reg_matches) != 1 or len(reg_matches[0].strings) != 4: 31 | push_error("Invalid UDIM import path: " + file_path) 32 | return 33 | var filename = reg_matches[0].strings[1] 34 | var filetype = reg_matches[0].strings[3] 35 | var dir = DirAccess.open(dirr) 36 | if dir: 37 | dir.list_dir_begin() 38 | var file_name = dir.get_next() 39 | while file_name != "": 40 | if not dir.current_is_dir() and file_name.ends_with(filetype): 41 | var sregex = RegEx.new() 42 | sregex.compile(filename+'(\\d{4})'+filetype) 43 | if sregex.search(file_name): 44 | var texture = load(dirr + "/" + file_name) 45 | var udim_id = regex.search_all(file_name)[0].strings[2] 46 | tileset.set("tile_" + udim_id,texture) 47 | file_name = dir.get_next() 48 | else: 49 | push_error("An error occurred when trying to access the UDIM path: " + file_path) 50 | 51 | # Called every frame. 'delta' is the elapsed time since the previous frame. 52 | func _process(delta): 53 | pass 54 | -------------------------------------------------------------------------------- /addons/udim_material/icons/udim_shader_material.svg: -------------------------------------------------------------------------------- 1 | 2 | 14 | 16 | 35 | 40 | 44 | 47 | 51 | 54 | 58 | 61 | 65 | 68 | 72 | 75 | 79 | 82 | 83 | 92 | 93 | -------------------------------------------------------------------------------- /addons/udim_material/UDIMShaderMaterial.gdshader: -------------------------------------------------------------------------------- 1 | shader_type spatial; 2 | render_mode blend_mix,depth_draw_opaque,cull_back,diffuse_burley,specular_schlick_ggx; 3 | uniform float specular; 4 | 5 | uniform sampler2D t1001 : source_color,filter_nearest,repeat_enable; 6 | uniform sampler2D t1002 : source_color,filter_nearest,repeat_enable; 7 | uniform sampler2D t1003 : source_color,filter_nearest,repeat_enable; 8 | uniform sampler2D t1004 : source_color,filter_nearest,repeat_enable; 9 | uniform sampler2D t1005 : source_color,filter_nearest,repeat_enable; 10 | uniform sampler2D t1006 : source_color,filter_nearest,repeat_enable; 11 | uniform sampler2D t1007 : source_color,filter_nearest,repeat_enable; 12 | uniform sampler2D t1008 : source_color,filter_nearest,repeat_enable; 13 | uniform sampler2D t1009 : source_color,filter_nearest,repeat_enable; 14 | uniform sampler2D t1010 : source_color,filter_nearest,repeat_enable; 15 | uniform sampler2D t1011 : source_color,filter_nearest,repeat_enable; 16 | uniform sampler2D t1012 : source_color,filter_nearest,repeat_enable; 17 | uniform sampler2D t1013 : source_color,filter_nearest,repeat_enable; 18 | //uniform sampler2D t1014 : source_color,filter_nearest,repeat_enable; 19 | //uniform sampler2D t1015 : source_color,filter_nearest,repeat_enable; 20 | //uniform sampler2D t1016 : source_color,filter_nearest,repeat_enable; 21 | //uniform sampler2D t1017 : source_color,filter_nearest,repeat_enable; 22 | //uniform sampler2D t1018 : source_color,filter_nearest,repeat_enable; 23 | //uniform sampler2D t1019 : source_color,filter_nearest,repeat_enable; 24 | //uniform sampler2D t1020 : source_color,filter_nearest,repeat_enable; 25 | 26 | uniform sampler2DArray testarr : source_color,filter_nearest,repeat_enable; 27 | 28 | void vertex() { 29 | UV=UV; 30 | COLOR = COLOR; 31 | } 32 | 33 | vec3 map_to_udim_tile(sampler2D sampler, vec2 uv, vec2 x_thresholds, vec2 y_thresholds) { 34 | bvec2 ltx = lessThan(vec2(uv.x,uv.x), x_thresholds); 35 | bvec2 gtx = greaterThan(vec2(uv.x,uv.x), x_thresholds); 36 | 37 | bvec2 lty = lessThan(vec2(uv.y,uv.y), y_thresholds); 38 | bvec2 gty = greaterThan(vec2(uv.y,uv.y), y_thresholds); 39 | 40 | vec4 f_tex0x = texture(sampler,uv) * float((int(ltx.y) * int(gtx.x)) * (int(lty.y) * int(gty.x))); 41 | return f_tex0x.rgb; 42 | } 43 | 44 | void fragment() { 45 | ALBEDO = vec3(0.5,0,0); 46 | vec3 f_tex1001 = map_to_udim_tile(t1001,UV,vec2(0,1),vec2(0,1)); 47 | vec3 f_tex1002 = map_to_udim_tile(t1002,UV,vec2(1,2),vec2(0,1)); 48 | vec3 f_tex1003 = map_to_udim_tile(t1003,UV,vec2(2,3),vec2(0,1)); 49 | vec3 f_tex1004 = map_to_udim_tile(t1004,UV,vec2(3,4),vec2(0,1)); 50 | vec3 f_tex1005 = map_to_udim_tile(t1005,UV,vec2(4,5),vec2(0,1)); 51 | vec3 f_tex1006 = map_to_udim_tile(t1006,UV,vec2(5,6),vec2(0,1)); 52 | vec3 f_tex1007 = map_to_udim_tile(t1007,UV,vec2(6,7),vec2(0,1)); 53 | vec3 f_tex1008 = map_to_udim_tile(t1008,UV,vec2(7,8),vec2(0,1)); 54 | vec3 f_tex1009 = map_to_udim_tile(t1009,UV,vec2(8,9),vec2(0,1)); 55 | vec3 f_tex1010 = map_to_udim_tile(t1010,UV,vec2(9,10),vec2(0,1)); 56 | vec3 f_tex1011 = map_to_udim_tile(t1011,UV,vec2(0,1),vec2(-1,0)); 57 | vec3 f_tex1012 = map_to_udim_tile(t1012,UV,vec2(1,2),vec2(-1,0)); 58 | vec3 f_tex1013 = map_to_udim_tile(t1013,UV,vec2(2,3),vec2(-1,0)); 59 | 60 | vec3 final_texture = 61 | f_tex1001 + 62 | f_tex1002 + 63 | f_tex1003 + 64 | f_tex1004 + 65 | f_tex1005 + 66 | f_tex1006 + 67 | f_tex1007 + 68 | f_tex1008 + 69 | f_tex1009 + 70 | f_tex1010 + 71 | f_tex1011 + 72 | f_tex1012 + 73 | f_tex1013; 74 | 75 | 76 | 77 | ALBEDO = final_texture; 78 | SPECULAR = specular; 79 | } -------------------------------------------------------------------------------- /addons/udim_material/UDIMTextureTileset.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends Resource 3 | class_name UDIMTextureTileset 4 | 5 | @export_group("UDIM Textures", "tile_") 6 | @export_subgroup("Row 0") 7 | @export var tile_1001: Texture: 8 | set(value): 9 | tile_1001 = value 10 | changed.emit() 11 | @export var tile_1002: Texture: 12 | set(value): 13 | tile_1002 = value 14 | changed.emit() 15 | @export var tile_1003: Texture: 16 | set(value): 17 | tile_1003 = value 18 | changed.emit() 19 | @export var tile_1004: Texture: 20 | set(value): 21 | tile_1004 = value 22 | changed.emit() 23 | @export var tile_1005: Texture: 24 | set(value): 25 | tile_1005 = value 26 | changed.emit() 27 | @export var tile_1006: Texture: 28 | set(value): 29 | tile_1006 = value 30 | changed.emit() 31 | @export var tile_1007: Texture: 32 | set(value): 33 | tile_1007 = value 34 | changed.emit() 35 | @export var tile_1008: Texture: 36 | set(value): 37 | tile_1008 = value 38 | changed.emit() 39 | @export var tile_1009: Texture: 40 | set(value): 41 | tile_1009 = value 42 | changed.emit() 43 | @export var tile_1010: Texture: 44 | set(value): 45 | tile_1010 = value 46 | changed.emit() 47 | 48 | @export_subgroup("Row 1") 49 | @export var tile_1011: Texture: 50 | set(value): 51 | tile_1011 = value 52 | changed.emit() 53 | @export var tile_1012: Texture: 54 | set(value): 55 | tile_1012 = value 56 | changed.emit() 57 | @export var tile_1013: Texture: 58 | set(value): 59 | tile_1013 = value 60 | changed.emit() 61 | @export var tile_1014: Texture: 62 | set(value): 63 | tile_1014 = value 64 | changed.emit() 65 | @export var tile_1015: Texture: 66 | set(value): 67 | tile_1015 = value 68 | changed.emit() 69 | @export var tile_1016: Texture: 70 | set(value): 71 | tile_1016 = value 72 | changed.emit() 73 | @export var tile_1017: Texture: 74 | set(value): 75 | tile_1017 = value 76 | changed.emit() 77 | @export var tile_1018: Texture: 78 | set(value): 79 | tile_1018 = value 80 | changed.emit() 81 | @export var tile_1019: Texture: 82 | set(value): 83 | tile_1019 = value 84 | changed.emit() 85 | @export var tile_1020: Texture: 86 | set(value): 87 | tile_1020 = value 88 | changed.emit() 89 | 90 | @export_subgroup("Row 2") 91 | @export var tile_1021: Texture: 92 | set(value): 93 | tile_1021 = value 94 | changed.emit() 95 | @export var tile_1022: Texture: 96 | set(value): 97 | tile_1022 = value 98 | changed.emit() 99 | @export var tile_1023: Texture: 100 | set(value): 101 | tile_1023 = value 102 | changed.emit() 103 | @export var tile_1024: Texture: 104 | set(value): 105 | tile_1024 = value 106 | changed.emit() 107 | @export var tile_1025: Texture: 108 | set(value): 109 | tile_1025 = value 110 | changed.emit() 111 | @export var tile_1026: Texture: 112 | set(value): 113 | tile_1026 = value 114 | changed.emit() 115 | @export var tile_1027: Texture: 116 | set(value): 117 | tile_1027 = value 118 | changed.emit() 119 | @export var tile_1028: Texture: 120 | set(value): 121 | tile_1028 = value 122 | changed.emit() 123 | @export var tile_1029: Texture: 124 | set(value): 125 | tile_1029 = value 126 | changed.emit() 127 | @export var tile_1030: Texture: 128 | set(value): 129 | tile_1030 = value 130 | changed.emit() 131 | 132 | 133 | const tile_cordinate_map: Dictionary = { 134 | 'tile_1001': [Vector2(0, 1), Vector2(0, 1)], 135 | 'tile_1002': [Vector2(1, 2), Vector2(0, 1)], 136 | 'tile_1003': [Vector2(2, 3), Vector2(0, 1)], 137 | 'tile_1004': [Vector2(3, 4), Vector2(0, 1)], 138 | 'tile_1005': [Vector2(4, 5), Vector2(0, 1)], 139 | 'tile_1006': [Vector2(5, 6), Vector2(0, 1)], 140 | 'tile_1007': [Vector2(6, 7), Vector2(0, 1)], 141 | 'tile_1008': [Vector2(7, 8), Vector2(0, 1)], 142 | 'tile_1009': [Vector2(8, 9), Vector2(0, 1)], 143 | 'tile_1010': [Vector2(9, 10), Vector2(0, 1)], 144 | 'tile_1011': [Vector2(0, 1), Vector2(-1, 0)], 145 | 'tile_1012': [Vector2(1, 2), Vector2(-1, 0)], 146 | 'tile_1013': [Vector2(2, 3), Vector2(-1, 0)], 147 | 'tile_1014': [Vector2(3, 4), Vector2(-1, 0)], 148 | 'tile_1015': [Vector2(4, 5), Vector2(-1, 0)], 149 | 'tile_1016': [Vector2(5, 6), Vector2(-1, 0)], 150 | 'tile_1017': [Vector2(6, 7), Vector2(-1, 0)], 151 | 'tile_1018': [Vector2(7, 8), Vector2(-1, 0)], 152 | 'tile_1019': [Vector2(8, 9), Vector2(-1, 0)], 153 | 'tile_1020': [Vector2(9, 10), Vector2(-1, 0)], 154 | 'tile_1021': [Vector2(0, 1), Vector2(-2, -1)], 155 | 'tile_1022': [Vector2(1, 2), Vector2(-2, -1)], 156 | 'tile_1023': [Vector2(2, 3), Vector2(-2, -1)], 157 | 'tile_1024': [Vector2(3, 4), Vector2(-2, -1)], 158 | 'tile_1025': [Vector2(4, 5), Vector2(-2, -1)], 159 | 'tile_1026': [Vector2(5, 6), Vector2(-2, -1)], 160 | 'tile_1027': [Vector2(6, 7), Vector2(-2, -1)], 161 | 'tile_1028': [Vector2(7, 8), Vector2(-2, -1)], 162 | 'tile_1029': [Vector2(8, 9), Vector2(-2, -1)], 163 | 'tile_1030': [Vector2(9, 10), Vector2(-2, -1)], 164 | } 165 | 166 | func has_tiles() -> bool: 167 | for i in range(1001, 1031): 168 | var tile = "tile_" + str(i) 169 | if get(tile) != null: 170 | return true 171 | return false 172 | 173 | func get_tiles_status() -> Dictionary: 174 | var tiles = {} 175 | for i in range(1001, 1031): 176 | var tile = "tile_" + str(i) 177 | tiles[tile] = [ 178 | get(tile) != null, 179 | tile_cordinate_map[tile], 180 | ] 181 | return tiles 182 | -------------------------------------------------------------------------------- /addons/udim_material/UDIMShaderMaterial.gd: -------------------------------------------------------------------------------- 1 | @icon("res://addons/udim_material/icons/udim_shader_material.svg") 2 | @tool 3 | extends ShaderMaterial 4 | class_name UDIMShaderMaterial 5 | 6 | func int_to_str(int_str): 7 | if int_str < 10: 8 | return "00" + str(int_str) 9 | elif int_str < 100: 10 | return "0" + str(int_str) 11 | return str(int_str) 12 | 13 | 14 | const IGNORED_PROPERTIES = [ 15 | "shader", 16 | "use_custom_shader", 17 | ] 18 | 19 | func _validate_property(property): 20 | if property.name in IGNORED_PROPERTIES: 21 | property.usage = PROPERTY_USAGE_NO_EDITOR 22 | 23 | ## Allow using a custom shader script (Currently does nothing) 24 | @export() var use_custom_shader: bool = false: 25 | set(new_value): 26 | use_custom_shader = new_value 27 | _update_shader() 28 | 29 | # transparancy 30 | @export_subgroup("Transparency") 31 | @export var transparency: BaseMaterial3D.Transparency = BaseMaterial3D.TRANSPARENCY_DISABLED: 32 | set(new_value): 33 | transparency = new_value 34 | _update_shader() 35 | @export var blend_mode: BaseMaterial3D.BlendMode = BaseMaterial3D.BLEND_MODE_MIX: 36 | set(new_value): 37 | blend_mode = new_value 38 | _update_shader() 39 | @export var cull_mode: BaseMaterial3D.CullMode = BaseMaterial3D.CULL_BACK: 40 | set(new_value): 41 | cull_mode = new_value 42 | _update_shader() 43 | @export var depth_draw_mode: BaseMaterial3D.DepthDrawMode = BaseMaterial3D.DEPTH_DRAW_OPAQUE_ONLY: 44 | set(new_value): 45 | depth_draw_mode = new_value 46 | _update_shader() 47 | 48 | # shading 49 | @export_subgroup("Shading") 50 | @export var shading_mode: BaseMaterial3D.ShadingMode = BaseMaterial3D.SHADING_MODE_PER_PIXEL: 51 | set(new_value): 52 | shading_mode = new_value 53 | _update_shader() 54 | @export var diffuse_mode: BaseMaterial3D.DiffuseMode = BaseMaterial3D.DIFFUSE_BURLEY: 55 | set(new_value): 56 | diffuse_mode = new_value 57 | _update_shader() 58 | @export var specular_mode: BaseMaterial3D.SpecularMode = BaseMaterial3D.SPECULAR_SCHLICK_GGX: 59 | set(new_value): 60 | specular_mode = new_value 61 | _update_shader() 62 | @export var disable_ambient_light: bool = false: 63 | set(new_value): 64 | disable_ambient_light = new_value 65 | _update_shader() 66 | @export var disable_fog: bool = false: 67 | set(new_value): 68 | disable_fog = new_value 69 | _update_shader() 70 | 71 | 72 | # vertex color 73 | @export_subgroup("Vertex Color") 74 | @export var vertex_color_use_as_albedo: bool = false: 75 | set(new_value): 76 | vertex_color_use_as_albedo = new_value 77 | _update_shader() 78 | @export var vertex_color_is_srgb: bool = false: 79 | set(new_value): 80 | vertex_color_is_srgb = new_value 81 | _update_shader() 82 | 83 | # albedo 84 | @export_subgroup("Albedo") 85 | @export var albedo_color: Color = Color.WHITE: 86 | set(new_value): 87 | albedo_color = new_value 88 | _update_shader() 89 | @export var albedo_tileset: UDIMTextureTileset: 90 | set(value): 91 | albedo_tileset = value 92 | if albedo_tileset != null and not albedo_tileset.changed.is_connected(update_shader): 93 | albedo_tileset.changed.connect(_update_shader) 94 | _update_shader() 95 | @export var texture_force_srgb: bool: 96 | set(new_value): 97 | texture_force_srgb = new_value 98 | _update_shader() 99 | @export var texture_msdf: bool: 100 | set(new_value): 101 | texture_msdf = new_value 102 | _update_shader() 103 | 104 | # metallic 105 | @export_subgroup("Metallic") 106 | @export_range(0.0, 1.0) var metallic: float = 0.0: 107 | set(new_value): 108 | metallic = new_value 109 | _update_shader() 110 | @export_range(0.0, 1.0) var metallic_specular: float = 0.5: 111 | set(new_value): 112 | metallic_specular = new_value 113 | _update_shader() 114 | @export var metallic_texture: Texture: 115 | set(new_value): 116 | metallic_texture = new_value 117 | _update_shader() 118 | @export var metallic_texture_channel: BaseMaterial3D.TextureChannel: 119 | set(new_value): 120 | metallic_texture_channel = new_value 121 | _update_shader() 122 | 123 | # roughness 124 | @export_subgroup("Roughness") 125 | @export_range(0.0, 1.0) var roughness: float = 1.0: 126 | set(new_value): 127 | roughness = new_value 128 | _update_shader() 129 | @export var roughness_texture: Texture: 130 | set(new_value): 131 | roughness_texture = new_value 132 | _update_shader() 133 | @export var roughness_texture_channel: BaseMaterial3D.TextureChannel: 134 | set(new_value): 135 | roughness_texture_channel = new_value 136 | _update_shader() 137 | 138 | # emission 139 | @export_subgroup("Emission") 140 | @export var emission_enabled: bool = false: 141 | set(new_value): 142 | emission_enabled = new_value 143 | _update_shader() 144 | @export var emission_color: Color = Color.BLACK: 145 | set(new_value): 146 | emission_color = new_value 147 | _update_shader() 148 | @export_range(0.0, 16.0) var emission_multiplier: float = 1.0: 149 | set(new_value): 150 | emission_multiplier = new_value 151 | _update_shader() 152 | @export var emission_op: BaseMaterial3D.EmissionOperator = BaseMaterial3D.EMISSION_OP_ADD: 153 | set(new_value): 154 | emission_op = new_value 155 | _update_shader() 156 | @export var emission_on_uv2: bool = false: 157 | set(new_value): 158 | emission_on_uv2 = new_value 159 | _update_shader() 160 | @export var emission_texture: Texture: 161 | set(new_value): 162 | emission_texture = new_value 163 | _update_shader() 164 | 165 | # normal map 166 | @export_subgroup("Normal Map") 167 | @export var normal_enabled: bool = false: 168 | set(new_value): 169 | normal_enabled = new_value 170 | _update_shader() 171 | @export_range(-16.0, 16.0) var normal_scale: float = 1.0: 172 | set(new_value): 173 | normal_scale = new_value 174 | _update_shader() 175 | @export var normal_texture: Texture: 176 | set(new_value): 177 | normal_texture = new_value 178 | _update_shader() 179 | 180 | # rim 181 | @export_subgroup("Rim") 182 | @export var rim_enabled: bool = false: 183 | set(new_value): 184 | rim_enabled = new_value 185 | _update_shader() 186 | @export_range(0.0, 1.0) var rim: float = 1.0: 187 | set(new_value): 188 | rim = new_value 189 | _update_shader() 190 | @export_range(0.0, 1.0) var rim_tint: float = 0.5: 191 | set(new_value): 192 | rim_tint = new_value 193 | _update_shader() 194 | @export var rim_texture: Texture: 195 | set(new_value): 196 | rim_texture = new_value 197 | _update_shader() 198 | 199 | # clearcoat 200 | @export_subgroup("Clearcoat") 201 | @export var clearcoat_enabled: bool = false: 202 | set(new_value): 203 | clearcoat_enabled = new_value 204 | _update_shader() 205 | @export_range(0.0, 1.0) var clearcoat: float = 1.0: 206 | set(new_value): 207 | clearcoat = new_value 208 | _update_shader() 209 | @export_range(0.0, 1.0) var clearcoat_roughness: float = 0.5: 210 | set(new_value): 211 | clearcoat_roughness = new_value 212 | _update_shader() 213 | @export var clearcoat_texture: Texture: 214 | set(new_value): 215 | clearcoat_texture = new_value 216 | _update_shader() 217 | 218 | # anisotropy 219 | @export_subgroup("Anisotropy") 220 | @export var anisotropy_enabled: bool = false: 221 | set(new_value): 222 | anisotropy_enabled = new_value 223 | _update_shader() 224 | @export_range(-1.0, 1.0) var anisotropy: float = 0.0: 225 | set(new_value): 226 | anisotropy = new_value 227 | _update_shader() 228 | @export var anisotropy_flowmap: Texture: 229 | set(new_value): 230 | anisotropy_flowmap = new_value 231 | _update_shader() 232 | 233 | # ambient_occlusion 234 | @export_subgroup("Ambient Occlusion") 235 | @export var ao_enabled: bool = false: 236 | set(new_value): 237 | ao_enabled = new_value 238 | _update_shader() 239 | @export_range(0.0, 1.0) var ao_light_effect: float = 0.0: 240 | set(new_value): 241 | ao_light_effect = new_value 242 | _update_shader() 243 | @export var ao_texture: Texture: 244 | set(new_value): 245 | ao_texture = new_value 246 | _update_shader() 247 | @export var ao_on_uv2: bool = false: 248 | set(new_value): 249 | ao_on_uv2 = new_value 250 | _update_shader() 251 | @export var ao_texture_channel: BaseMaterial3D.TextureChannel: 252 | set(new_value): 253 | ao_texture_channel = new_value 254 | _update_shader() 255 | 256 | # heightmap 257 | @export_subgroup("Heightmap") 258 | @export var heightmap_enabled: bool = false: 259 | set(new_value): 260 | heightmap_enabled = new_value 261 | _update_shader() 262 | @export_range(-16.0, 16.0) var heightmap_scale: float = 5.0: 263 | set(new_value): 264 | heightmap_scale = new_value 265 | _update_shader() 266 | @export var heightmap_deep_parallax: bool = false: 267 | set(new_value): 268 | heightmap_deep_parallax = new_value 269 | _update_shader() 270 | @export var heightmap_flip_tangent: bool = false: 271 | set(new_value): 272 | heightmap_flip_tangent = new_value 273 | _update_shader() 274 | @export var heightmap_flip_binormal: bool = false: 275 | set(new_value): 276 | heightmap_flip_binormal = new_value 277 | _update_shader() 278 | @export var heightmap_texture: Texture: 279 | set(new_value): 280 | heightmap_texture = new_value 281 | _update_shader() 282 | @export var heightmap_flip_texture: bool = false: 283 | set(new_value): 284 | heightmap_flip_texture = new_value 285 | _update_shader() 286 | 287 | # subfur_scatter 288 | @export_subgroup("Subsurface Scattering") 289 | @export var subsurf_scatter_enabled: bool = false: 290 | set(new_value): 291 | subsurf_scatter_enabled = new_value 292 | _update_shader() 293 | @export_range(0.0, 1.0) var subsurf_scatter_strength: float = 0.0: 294 | set(new_value): 295 | subsurf_scatter_strength = new_value 296 | _update_shader() 297 | @export var subsurf_scatter_skin_mode: bool = false: 298 | set(new_value): 299 | subsurf_scatter_skin_mode = new_value 300 | _update_shader() 301 | @export var subsurf_scatter_texture: Texture: 302 | set(new_value): 303 | subsurf_scatter_texture = new_value 304 | _update_shader() 305 | @export var subsurf_scatter_transmittance_enabled: bool = false: 306 | set(new_value): 307 | subsurf_scatter_transmittance_enabled = new_value 308 | _update_shader() 309 | @export_range(0.001, 8.0) var subsurf_scatter_transmittance_depth: float = 0.1: 310 | set(new_value): 311 | subsurf_scatter_transmittance_depth = new_value 312 | _update_shader() 313 | @export_range(0.0, 1.0) var subsurf_scatter_transmittance_boost: float = 0.0: 314 | set(new_value): 315 | subsurf_scatter_transmittance_boost = new_value 316 | _update_shader() 317 | 318 | # backlight 319 | @export_subgroup("Backlight") 320 | @export var backlight_enabled: bool = false: 321 | set(new_value): 322 | backlight_enabled = new_value 323 | _update_shader() 324 | @export var backlight_backlight: Color = Color.BLACK: 325 | set(new_value): 326 | backlight_backlight = new_value 327 | _update_shader() 328 | @export var backlight_texture: Texture: 329 | set(new_value): 330 | backlight_texture = new_value 331 | _update_shader() 332 | 333 | # refraction 334 | @export_subgroup("Refraction") 335 | @export var refraction_enabled: bool = false: 336 | set(new_value): 337 | refraction_enabled = new_value 338 | _update_shader() 339 | @export_range(-1.0, 1.0) var refraction_scale: float = 0.05: 340 | set(new_value): 341 | refraction_scale = new_value 342 | _update_shader() 343 | @export var refraction_texture: Texture: 344 | set(new_value): 345 | refraction_texture = new_value 346 | _update_shader() 347 | @export var refraction_texture_channel: BaseMaterial3D.TextureChannel: 348 | set(new_value): 349 | refraction_texture_channel = new_value 350 | _update_shader() 351 | 352 | # detail 353 | @export_subgroup("Detail") 354 | @export var detail_enabled: bool = false: 355 | set(new_value): 356 | detail_enabled = new_value 357 | _update_shader() 358 | @export var detail_mask: Texture: 359 | set(new_value): 360 | detail_mask = new_value 361 | _update_shader() 362 | @export var detail_blend_mode: BaseMaterial3D.BlendMode: 363 | set(new_value): 364 | detail_blend_mode = new_value 365 | _update_shader() 366 | @export var detail_uv: BaseMaterial3D.DetailUV: 367 | set(new_value): 368 | detail_uv = new_value 369 | _update_shader() 370 | @export var detail_albedo: Texture: 371 | set(new_value): 372 | detail_albedo = new_value 373 | _update_shader() 374 | @export var detail_normal: Texture: 375 | set(new_value): 376 | detail_normal = new_value 377 | _update_shader() 378 | 379 | # sampling 380 | @export_subgroup("Sampling") 381 | @export var texture_filter: BaseMaterial3D.TextureFilter: 382 | set(new_value): 383 | texture_filter = new_value 384 | _update_shader() 385 | @export var texture_repeat: bool = true: 386 | set(new_value): 387 | texture_repeat = new_value 388 | _update_shader() 389 | 390 | # shadows 391 | @export_subgroup("Shadows") 392 | @export var disable_receive_shadows: bool = false: 393 | set(new_value): 394 | disable_receive_shadows = new_value 395 | _update_shader() 396 | @export var shadow_to_opacity: bool = false: 397 | set(new_value): 398 | shadow_to_opacity = new_value 399 | _update_shader() 400 | 401 | # billboard 402 | # pls no more 403 | @export_subgroup("Billboard") 404 | @export var billboard_mode: BaseMaterial3D.BillboardMode 405 | 406 | # grow 407 | @export_subgroup("Grow") 408 | @export var grow_enabled: bool: 409 | set(new_value): 410 | grow_enabled = new_value 411 | _update_shader() 412 | @export_range(-16.0, 16.0) var grow_amount: float = 0.0: 413 | set(new_value): 414 | grow_amount = new_value 415 | _update_shader() 416 | 417 | 418 | # transform 419 | @export_subgroup("Transform") 420 | @export var fixed_size: bool = false: 421 | set(new_value): 422 | fixed_size = new_value 423 | _update_shader() 424 | @export var use_point_size: bool = false: 425 | set(new_value): 426 | use_point_size = new_value 427 | _update_shader() 428 | @export_range(0.1, 128.0, 0.01, "suffix:px") var point_size: float = 1.0: 429 | set(new_value): 430 | point_size = new_value 431 | _update_shader() 432 | @export var use_particle_trails: bool = false: 433 | set(new_value): 434 | use_particle_trails = new_value 435 | _update_shader() 436 | 437 | # proximity fade 438 | @export_subgroup("Proximity Fade") 439 | @export var proximity_fade_enabled: bool: 440 | set(new_value): 441 | proximity_fade_enabled = new_value 442 | _update_shader() 443 | @export_range(0.1, 128.0, 0.01, "suffix:m") var proximity_fade_distance: float = 1.0: 444 | set(new_value): 445 | proximity_fade_distance = new_value 446 | _update_shader() 447 | 448 | 449 | # TODO skipping for now.... 450 | @export var distance_fade: BaseMaterial3D.DistanceFadeMode 451 | 452 | 453 | # TODO 454 | @export var alpha_antialiasing_mode: BaseMaterial3D.AlphaAntiAliasing 455 | 456 | 457 | 458 | var features = { 459 | BaseMaterial3D.FEATURE_EMISSION: false, 460 | BaseMaterial3D.FEATURE_NORMAL_MAPPING: false, 461 | BaseMaterial3D.FEATURE_RIM: false, 462 | BaseMaterial3D.FEATURE_CLEARCOAT: false, 463 | BaseMaterial3D.FEATURE_ANISOTROPY: false, 464 | BaseMaterial3D.FEATURE_AMBIENT_OCCLUSION: false, 465 | BaseMaterial3D.FEATURE_HEIGHT_MAPPING: false, 466 | BaseMaterial3D.FEATURE_SUBSURFACE_SCATTERING: false, 467 | BaseMaterial3D.FEATURE_SUBSURFACE_TRANSMITTANCE: false, 468 | BaseMaterial3D.FEATURE_BACKLIGHT: false, 469 | BaseMaterial3D.FEATURE_REFRACTION: false, 470 | BaseMaterial3D.FEATURE_DETAIL: false, 471 | BaseMaterial3D.FEATURE_MAX: false, 472 | } 473 | 474 | func _update_features(): 475 | features[BaseMaterial3D.FEATURE_EMISSION] = emission_enabled 476 | features[BaseMaterial3D.FEATURE_NORMAL_MAPPING] = normal_enabled 477 | features[BaseMaterial3D.FEATURE_RIM] = rim_enabled 478 | features[BaseMaterial3D.FEATURE_CLEARCOAT] = clearcoat_enabled 479 | features[BaseMaterial3D.FEATURE_ANISOTROPY] = anisotropy_enabled 480 | features[BaseMaterial3D.FEATURE_AMBIENT_OCCLUSION] = ao_enabled 481 | features[BaseMaterial3D.FEATURE_HEIGHT_MAPPING] = heightmap_enabled 482 | features[BaseMaterial3D.FEATURE_SUBSURFACE_SCATTERING] = subsurf_scatter_enabled 483 | features[BaseMaterial3D.FEATURE_SUBSURFACE_TRANSMITTANCE] = subsurf_scatter_transmittance_enabled 484 | features[BaseMaterial3D.FEATURE_BACKLIGHT] = backlight_enabled 485 | features[BaseMaterial3D.FEATURE_REFRACTION] = refraction_enabled 486 | features[BaseMaterial3D.FEATURE_DETAIL] = detail_enabled 487 | 488 | var flags = { 489 | BaseMaterial3D.FLAG_DISABLE_DEPTH_TEST: false, 490 | BaseMaterial3D.FLAG_ALBEDO_FROM_VERTEX_COLOR: false, 491 | BaseMaterial3D.FLAG_SRGB_VERTEX_COLOR: false, 492 | BaseMaterial3D.FLAG_USE_POINT_SIZE: false, 493 | BaseMaterial3D.FLAG_FIXED_SIZE: false, 494 | BaseMaterial3D.FLAG_BILLBOARD_KEEP_SCALE: false, 495 | BaseMaterial3D.FLAG_UV1_USE_TRIPLANAR: false, 496 | BaseMaterial3D.FLAG_UV2_USE_TRIPLANAR: false, 497 | BaseMaterial3D.FLAG_UV1_USE_WORLD_TRIPLANAR: false, 498 | BaseMaterial3D.FLAG_UV2_USE_WORLD_TRIPLANAR: false, 499 | BaseMaterial3D.FLAG_AO_ON_UV2: false, 500 | BaseMaterial3D.FLAG_EMISSION_ON_UV2: false, 501 | BaseMaterial3D.FLAG_ALBEDO_TEXTURE_FORCE_SRGB: false, 502 | BaseMaterial3D.FLAG_DONT_RECEIVE_SHADOWS: false, 503 | BaseMaterial3D.FLAG_DISABLE_AMBIENT_LIGHT: false, 504 | BaseMaterial3D.FLAG_USE_SHADOW_TO_OPACITY: false, 505 | BaseMaterial3D.FLAG_USE_TEXTURE_REPEAT: false, 506 | BaseMaterial3D.FLAG_INVERT_HEIGHTMAP: false, 507 | BaseMaterial3D.FLAG_SUBSURFACE_MODE_SKIN: false, 508 | BaseMaterial3D.FLAG_PARTICLE_TRAILS_MODE: false, 509 | BaseMaterial3D.FLAG_ALBEDO_TEXTURE_MSDF: false, 510 | BaseMaterial3D.FLAG_DISABLE_FOG: false, 511 | BaseMaterial3D.FLAG_MAX: false, 512 | } 513 | 514 | func _update_flags(): 515 | flags[BaseMaterial3D.FLAG_DISABLE_DEPTH_TEST] = false 516 | flags[BaseMaterial3D.FLAG_ALBEDO_FROM_VERTEX_COLOR] = vertex_color_use_as_albedo 517 | flags[BaseMaterial3D.FLAG_SRGB_VERTEX_COLOR] = vertex_color_is_srgb 518 | flags[BaseMaterial3D.FLAG_USE_POINT_SIZE] = use_point_size 519 | flags[BaseMaterial3D.FLAG_FIXED_SIZE] = fixed_size 520 | flags[BaseMaterial3D.FLAG_BILLBOARD_KEEP_SCALE] = false 521 | flags[BaseMaterial3D.FLAG_UV1_USE_TRIPLANAR] = false 522 | flags[BaseMaterial3D.FLAG_UV2_USE_TRIPLANAR] = false 523 | flags[BaseMaterial3D.FLAG_UV1_USE_WORLD_TRIPLANAR] = false 524 | flags[BaseMaterial3D.FLAG_UV2_USE_WORLD_TRIPLANAR] = false 525 | flags[BaseMaterial3D.FLAG_AO_ON_UV2] = ao_on_uv2 526 | flags[BaseMaterial3D.FLAG_EMISSION_ON_UV2] = emission_on_uv2 527 | flags[BaseMaterial3D.FLAG_ALBEDO_TEXTURE_FORCE_SRGB] = texture_force_srgb 528 | flags[BaseMaterial3D.FLAG_DONT_RECEIVE_SHADOWS] = disable_receive_shadows 529 | flags[BaseMaterial3D.FLAG_DISABLE_AMBIENT_LIGHT] = disable_ambient_light 530 | flags[BaseMaterial3D.FLAG_USE_SHADOW_TO_OPACITY] = shadow_to_opacity 531 | flags[BaseMaterial3D.FLAG_USE_TEXTURE_REPEAT] = texture_repeat 532 | flags[BaseMaterial3D.FLAG_INVERT_HEIGHTMAP] = heightmap_flip_texture 533 | flags[BaseMaterial3D.FLAG_SUBSURFACE_MODE_SKIN] = subsurf_scatter_skin_mode 534 | flags[BaseMaterial3D.FLAG_PARTICLE_TRAILS_MODE] = use_particle_trails 535 | flags[BaseMaterial3D.FLAG_ALBEDO_TEXTURE_MSDF] = texture_msdf 536 | flags[BaseMaterial3D.FLAG_DISABLE_FOG] = disable_fog 537 | 538 | func _init(): 539 | _update_shader() 540 | if albedo_tileset != null and not albedo_tileset.changed.is_connected(_update_shader): 541 | albedo_tileset.changed.connect(_update_shader) 542 | 543 | func update_shader(): 544 | if albedo_tileset != null: 545 | for tile_name in albedo_tileset.get_tiles_status().keys(): 546 | set_shader_parameter(tile_name, albedo_tileset.get(tile_name)) 547 | else: 548 | update_shader_null() 549 | 550 | func update_shader_null(): 551 | for tile_name in UDIMTextureTileset.tile_cordinate_map.keys(): 552 | set_shader_parameter(tile_name, null) 553 | 554 | func _update_shader_params(): 555 | update_shader() 556 | # handle features 557 | if features[BaseMaterial3D.FEATURE_EMISSION]: 558 | set_shader_parameter("emission_color", emission_color) 559 | set_shader_parameter("emission_energy", emission_multiplier) 560 | set_shader_parameter("emission_texture", emission_texture) 561 | set_shader_parameter("emission_op", emission_op) 562 | set_shader_parameter("emission_on_uv2", emission_on_uv2) 563 | 564 | if features[BaseMaterial3D.FEATURE_NORMAL_MAPPING]: 565 | set_shader_parameter("normal_scale", normal_scale) 566 | set_shader_parameter("normal_texture", normal_texture) 567 | 568 | if features[BaseMaterial3D.FEATURE_RIM]: 569 | set_shader_parameter("rim", rim) 570 | set_shader_parameter("rim_tint", rim_tint) 571 | set_shader_parameter("rim_texture", rim_texture) 572 | 573 | if features[BaseMaterial3D.FEATURE_CLEARCOAT]: 574 | set_shader_parameter("clearcoat", clearcoat) 575 | set_shader_parameter("clearcoat_roughness", clearcoat_roughness) 576 | set_shader_parameter("clearcoat_texture", clearcoat_texture) 577 | 578 | if features[BaseMaterial3D.FEATURE_ANISOTROPY]: 579 | set_shader_parameter("anisotropy", anisotropy) 580 | set_shader_parameter("anisotropy_flowmap", anisotropy_flowmap) 581 | 582 | if features[BaseMaterial3D.FEATURE_AMBIENT_OCCLUSION]: 583 | set_shader_parameter("ao_light_effect", ao_light_effect) 584 | set_shader_parameter("ao_texture", ao_texture) 585 | set_shader_parameter("ao_texture_channel", ao_texture_channel) 586 | set_shader_parameter("ao_on_uv2", ao_on_uv2) 587 | 588 | if features[BaseMaterial3D.FEATURE_HEIGHT_MAPPING]: 589 | set_shader_parameter("heightmap_scale", heightmap_scale) 590 | set_shader_parameter("heightmap_deep_parallax", heightmap_deep_parallax) 591 | set_shader_parameter("heightmap_flip_tangent", heightmap_flip_tangent) 592 | set_shader_parameter("heightmap_flip_binormal", heightmap_flip_binormal) 593 | set_shader_parameter("heightmap_texture", heightmap_texture) 594 | set_shader_parameter("heightmap_flip_texture", heightmap_flip_texture) 595 | 596 | if features[BaseMaterial3D.FEATURE_SUBSURFACE_SCATTERING]: 597 | set_shader_parameter("subsurf_scatter_strength", subsurf_scatter_strength) 598 | set_shader_parameter("subsurf_scatter_skin_mode", subsurf_scatter_skin_mode) 599 | set_shader_parameter("subsurf_scatter_texture", subsurf_scatter_texture) 600 | 601 | if features[BaseMaterial3D.FEATURE_SUBSURFACE_TRANSMITTANCE]: 602 | set_shader_parameter("subsurf_scatter_transmittance_depth", subsurf_scatter_transmittance_depth) 603 | set_shader_parameter("subsurf_scatter_transmittance_boost", subsurf_scatter_transmittance_boost) 604 | 605 | if features[BaseMaterial3D.FEATURE_BACKLIGHT]: 606 | set_shader_parameter("backlight", backlight_backlight) 607 | set_shader_parameter("backlight_texture", backlight_texture) 608 | 609 | if features[BaseMaterial3D.FEATURE_REFRACTION]: 610 | set_shader_parameter("refraction_scale", refraction_scale) 611 | set_shader_parameter("refraction_texture", refraction_texture) 612 | set_shader_parameter("refraction_texture_channel", refraction_texture_channel) 613 | 614 | if features[BaseMaterial3D.FEATURE_DETAIL]: 615 | set_shader_parameter("detail_mask", detail_mask) 616 | set_shader_parameter("detail_blend_mode", detail_blend_mode) 617 | set_shader_parameter("detail_uv", detail_uv) 618 | set_shader_parameter("detail_albedo", detail_albedo) 619 | set_shader_parameter("detail_normal", detail_normal) 620 | 621 | # handle thins that dont change 622 | set_shader_parameter("albedo", albedo_color) 623 | # set_shader_parameter("texture_albedo", albedo_texture) 624 | set_shader_parameter("metallic", metallic) 625 | set_shader_parameter("metallic_specular", metallic_specular) 626 | set_shader_parameter("metallic_texture", metallic_texture) 627 | set_shader_parameter("metallic_texture_channel", metallic_texture_channel) 628 | set_shader_parameter("roughness", roughness) 629 | set_shader_parameter("roughness_texture", roughness_texture) 630 | set_shader_parameter("roughness_texture_channel", roughness_texture_channel) 631 | set_shader_parameter("point_size", point_size) 632 | set_shader_parameter("grow", grow_amount) 633 | set_shader_parameter("proximity_fade_distance", proximity_fade_distance) 634 | set_shader 635 | 636 | 637 | func _update_shader(): 638 | _update_features() 639 | _update_flags() 640 | 641 | var texfilter_str: String 642 | var texfilter_height_str: String 643 | 644 | match texture_filter: 645 | BaseMaterial3D.TextureFilter.TEXTURE_FILTER_NEAREST: 646 | texfilter_str = "filter_nearest" 647 | texfilter_height_str = "filter_linear" 648 | BaseMaterial3D.TextureFilter.TEXTURE_FILTER_LINEAR: 649 | texfilter_str = "filter_linear" 650 | texfilter_height_str = "filter_linear" 651 | BaseMaterial3D.TextureFilter.TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: 652 | texfilter_str = "filter_nearest_mipmap" 653 | texfilter_height_str = "filter_linear_mipmap" 654 | BaseMaterial3D.TextureFilter.TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: 655 | texfilter_str = "filter_linear_mipmap" 656 | texfilter_height_str = "filter_linear_mipmap" 657 | BaseMaterial3D.TextureFilter.TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC: 658 | texfilter_str = "filter_nearest_mipmap_anisotropic" 659 | texfilter_height_str = "filter_linear_mipmap_anisotropic" 660 | BaseMaterial3D.TextureFilter.TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC: 661 | texfilter_str = "filter_linear_mipmap_anisotropic" 662 | texfilter_height_str = "filter_linear_mipmap_anisotropic" 663 | 664 | if flags[BaseMaterial3D.FLAG_USE_TEXTURE_REPEAT]: 665 | texfilter_str += ",repeat_enable" 666 | texfilter_height_str += ",repeat_enable" 667 | else: 668 | texfilter_str += ",repeat_disable" 669 | texfilter_height_str += ",repeat_disable" 670 | 671 | var code = "// NOTE: This UDIM Shader is automatically generated\n\n" 672 | 673 | code += "shader_type spatial;\nrender_mode " 674 | match blend_mode: 675 | BaseMaterial3D.BlendMode.BLEND_MODE_MIX: 676 | code += "blend_mix" 677 | BaseMaterial3D.BlendMode.BLEND_MODE_ADD: 678 | code += "blend_add" 679 | BaseMaterial3D.BlendMode.BLEND_MODE_SUB: 680 | code += "blend_sub" 681 | BaseMaterial3D.BlendMode.BLEND_MODE_MUL: 682 | code += "blend_mul" 683 | 684 | var ddm: BaseMaterial3D.DepthDrawMode = depth_draw_mode 685 | if features[BaseMaterial3D.FEATURE_REFRACTION]: 686 | ddm = BaseMaterial3D.DEPTH_DRAW_ALWAYS 687 | 688 | match ddm: 689 | BaseMaterial3D.DEPTH_DRAW_OPAQUE_ONLY: 690 | code += ",depth_draw_opaque" 691 | BaseMaterial3D.DEPTH_DRAW_ALWAYS: 692 | code += ",depth_draw_always" 693 | BaseMaterial3D.DEPTH_DRAW_DISABLED: 694 | code += ",depth_draw_never" 695 | 696 | match cull_mode: 697 | BaseMaterial3D.CULL_BACK: 698 | code += ",cull_back" 699 | BaseMaterial3D.CULL_FRONT: 700 | code += ",cull_front" 701 | BaseMaterial3D.CULL_DISABLED: 702 | code += ",cull_disabled" 703 | 704 | match diffuse_mode: 705 | BaseMaterial3D.DIFFUSE_BURLEY: 706 | code += ",diffuse_burley" 707 | BaseMaterial3D.DIFFUSE_LAMBERT: 708 | code += ",diffuse_lambert" 709 | BaseMaterial3D.DIFFUSE_LAMBERT_WRAP: 710 | code += ",diffuse_lambert_wrap" 711 | BaseMaterial3D.DIFFUSE_TOON: 712 | code += ",diffuse_toon" 713 | 714 | match specular_mode: 715 | BaseMaterial3D.SPECULAR_SCHLICK_GGX: 716 | code += ",specular_schlick_ggx" 717 | BaseMaterial3D.SPECULAR_TOON: 718 | code += ",specular_toon" 719 | BaseMaterial3D.SPECULAR_DISABLED: 720 | code += ",specular_disabled" 721 | 722 | if features[BaseMaterial3D.FEATURE_SUBSURFACE_SCATTERING] and flags[BaseMaterial3D.FLAG_SUBSURFACE_MODE_SKIN]: 723 | code += ",sss_mode_skin" 724 | 725 | if shading_mode == BaseMaterial3D.ShadingMode.SHADING_MODE_UNSHADED: 726 | code += ",unshaded" 727 | 728 | if flags[BaseMaterial3D.FLAG_DISABLE_DEPTH_TEST]: 729 | code += ",depth_test_disabled" 730 | 731 | if flags[BaseMaterial3D.FLAG_PARTICLE_TRAILS_MODE]: 732 | code += ",particle_trails" 733 | 734 | if shading_mode == BaseMaterial3D.ShadingMode.SHADING_MODE_PER_VERTEX: 735 | code += ",vertex_lighting" 736 | 737 | if flags[BaseMaterial3D.FLAG_DONT_RECEIVE_SHADOWS]: 738 | code += ",shadows_disabled" 739 | 740 | if flags[BaseMaterial3D.FLAG_DISABLE_AMBIENT_LIGHT]: 741 | code += ",ambient_light_disabled" 742 | 743 | if flags[BaseMaterial3D.FLAG_USE_SHADOW_TO_OPACITY]: 744 | code += ",shadow_to_opacity" 745 | 746 | if transparency == BaseMaterial3D.TRANSPARENCY_ALPHA_DEPTH_PRE_PASS: 747 | code += ",depth_prepass_alpha" 748 | 749 | if transparency == BaseMaterial3D.TRANSPARENCY_ALPHA_HASH or transparency == BaseMaterial3D.TRANSPARENCY_ALPHA_SCISSOR: 750 | if alpha_antialiasing_mode == BaseMaterial3D.ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE: 751 | code += ",alpha_to_coverage" 752 | elif alpha_antialiasing_mode == BaseMaterial3D.ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE: 753 | code += ",alpha_to_coverage_and_one" 754 | 755 | code += ";\n" 756 | 757 | code += "uniform vec4 albedo : source_color;\n" 758 | code += "uniform sampler2D texture_albedo : source_color," + texfilter_str + ";\n" 759 | 760 | if albedo_tileset != null and albedo_tileset.has_tiles(): 761 | var tile_stats = albedo_tileset.get_tiles_status() 762 | var valid_tiles = [] 763 | for tile_name in tile_stats.keys(): 764 | if tile_stats[tile_name][0]: 765 | valid_tiles.append(tile_name) 766 | for tile_name in valid_tiles: 767 | code += "uniform sampler2D " + tile_name + " : source_color," + texfilter_str + ";\n" 768 | 769 | if grow_enabled: 770 | code += "uniform float grow;\n" 771 | 772 | if proximity_fade_enabled: 773 | code += "uniform float proximity_fade_distance;\n" 774 | 775 | if distance_fade != BaseMaterial3D.DistanceFadeMode.DISTANCE_FADE_DISABLED: 776 | code += "uniform float distance_fade_min;\n" 777 | code += "uniform float distance_fade_max;\n" 778 | 779 | if flags[BaseMaterial3D.FLAG_ALBEDO_TEXTURE_MSDF]: 780 | code += "uniform float msdf_pixel_range;\n" 781 | code += "uniform float msdf_outline_size;\n" 782 | 783 | if transparency == BaseMaterial3D.TRANSPARENCY_ALPHA_SCISSOR: 784 | code += "uniform float alpha_scissor_threshold;\n" 785 | elif transparency == BaseMaterial3D.TRANSPARENCY_ALPHA_HASH: 786 | code += "uniform float alpha_hash_scale;\n" 787 | 788 | if alpha_antialiasing_mode != BaseMaterial3D.ALPHA_ANTIALIASING_OFF and (transparency == BaseMaterial3D.TRANSPARENCY_ALPHA_SCISSOR or transparency == BaseMaterial3D.TRANSPARENCY_ALPHA_HASH): 789 | code += "uniform float alpha_antialiasing_edge;\n" 790 | code += "uniform ivec2 albedo_texture_size;\n" 791 | 792 | code += "uniform float point_size : hint_range(0,128);\n" 793 | 794 | code += "uniform float roughness : hint_range(0,1);\n"; 795 | code += "uniform sampler2D texture_metallic : hint_default_white," + texfilter_str + ";\n"; 796 | 797 | code += "uniform vec4 metallic_texture_channel;\n"; 798 | match roughness_texture_channel: 799 | BaseMaterial3D.TextureChannel.TEXTURE_CHANNEL_RED: 800 | code += "uniform sampler2D texture_roughness : hint_roughness_r," + texfilter_str + ";\n" 801 | BaseMaterial3D.TextureChannel.TEXTURE_CHANNEL_GREEN: 802 | code += "uniform sampler2D texture_roughness : hint_roughness_g," + texfilter_str + ";\n" 803 | BaseMaterial3D.TextureChannel.TEXTURE_CHANNEL_BLUE: 804 | code += "uniform sampler2D texture_roughness : hint_roughness_b," + texfilter_str + ";\n" 805 | BaseMaterial3D.TextureChannel.TEXTURE_CHANNEL_ALPHA: 806 | code += "uniform sampler2D texture_roughness : hint_roughness_a," + texfilter_str + ";\n" 807 | BaseMaterial3D.TextureChannel.TEXTURE_CHANNEL_GRAYSCALE: 808 | code += "uniform sampler2D texture_roughness : hint_roughness_gray," + texfilter_str + ";\n" 809 | 810 | code += "uniform float specular;\n"; 811 | code += "uniform float metallic;\n"; 812 | 813 | if billboard_mode == BaseMaterial3D.BillboardMode.BILLBOARD_PARTICLES: 814 | code += "uniform int particles_anim_h_frames;\n" 815 | code += "uniform int particles_anim_v_frames;\n" 816 | code += "uniform bool particles_anim_loop;\n" 817 | 818 | if features[BaseMaterial3D.FEATURE_EMISSION]: 819 | code += "uniform sampler2D texture_emission : source_color, hint_default_black," + texfilter_str + ";\n" 820 | code += "uniform vec4 emission : source_color;\n" 821 | code += "uniform float emission_energy;\n" 822 | 823 | if features[BaseMaterial3D.FEATURE_REFRACTION]: 824 | code += "uniform sampler2D texture_refraction : " + texfilter_str + ";\n" 825 | code += "uniform float refraction : hint_range(-16,16);\n" 826 | code += "uniform vec4 refraction_texture_channel;\n" 827 | 828 | if features[BaseMaterial3D.FEATURE_REFRACTION]: 829 | code += "uniform sampler2D screen_texture : hint_screen_texture, repeat_disable, filter_linear_mipmap;" 830 | 831 | if proximity_fade_enabled: 832 | code += "uniform sampler2D depth_texture : hint_depth_texture, repeat_disable, filter_nearest;" 833 | 834 | if features[BaseMaterial3D.FEATURE_NORMAL_MAPPING]: 835 | code += "uniform sampler2D texture_normal : hint_roughness_normal," + texfilter_str + ";\n" 836 | code += "uniform float normal_scale : hint_range(-16,16);\n" 837 | 838 | if features[BaseMaterial3D.FEATURE_RIM]: 839 | code += "uniform float rim : hint_range(0,1);\n" 840 | code += "uniform float rim_tint : hint_range(0,1);\n" 841 | code += "uniform sampler2D texture_rim : hint_default_white," + texfilter_str + ";\n" 842 | 843 | if features[BaseMaterial3D.FEATURE_CLEARCOAT]: 844 | code += "uniform float clearcoat : hint_range(0,1);\n" 845 | code += "uniform float clearcoat_roughness : hint_range(0,1);\n" 846 | code += "uniform sampler2D texture_clearcoat : hint_default_white," + texfilter_str + ";\n" 847 | 848 | if features[BaseMaterial3D.FEATURE_ANISOTROPY]: 849 | code += "uniform float anisotropy_ratio : hint_range(0,256);\n" 850 | code += "uniform sampler2D texture_flowmap : hint_anisotropy," + texfilter_str + ";\n" 851 | 852 | if features[BaseMaterial3D.FEATURE_AMBIENT_OCCLUSION]: 853 | code += "uniform sampler2D texture_ambient_occlusion : hint_default_white, " + texfilter_str + ";\n" 854 | code += "uniform vec4 ao_texture_channel;\n" 855 | code += "uniform float ao_light_affect;\n" 856 | 857 | if features[BaseMaterial3D.FEATURE_DETAIL]: 858 | code += "uniform sampler2D texture_detail_albedo : source_color," + texfilter_str + ";\n" 859 | code += "uniform sampler2D texture_detail_normal : hint_normal," + texfilter_str + ";\n" 860 | code += "uniform sampler2D texture_detail_mask : hint_default_white," + texfilter_str + ";\n" 861 | 862 | if features[BaseMaterial3D.FEATURE_SUBSURFACE_SCATTERING]: 863 | code += "uniform float subsurface_scattering_strength : hint_range(0,1);\n" 864 | code += "uniform sampler2D texture_subsurface_scattering : hint_default_white," + texfilter_str + ";\n" 865 | 866 | if features[BaseMaterial3D.FEATURE_SUBSURFACE_TRANSMITTANCE]: 867 | code += "uniform vec4 transmittance_color : source_color;\n" 868 | code += "uniform float transmittance_depth;\n" 869 | code += "uniform sampler2D texture_subsurface_transmittance : hint_default_white," + texfilter_str + ";\n" 870 | code += "uniform float transmittance_boost;\n" 871 | 872 | if features[BaseMaterial3D.FEATURE_BACKLIGHT]: 873 | code += "uniform vec4 backlight : source_color;\n" 874 | code += "uniform sampler2D texture_backlight : hint_default_black," + texfilter_str + ";\n" 875 | 876 | if features[BaseMaterial3D.FEATURE_HEIGHT_MAPPING]: 877 | code += "uniform sampler2D texture_heightmap : hint_default_black," + texfilter_height_str + ";\n" 878 | code += "uniform float heightmap_scale;\n" 879 | code += "uniform int heightmap_min_layers;\n" 880 | code += "uniform int heightmap_max_layers;\n" 881 | code += "uniform vec2 heightmap_flip;\n" 882 | 883 | code += "uniform vec3 uv1_scale;\n" 884 | code += "uniform vec3 uv1_offset;\n" 885 | code += "uniform vec3 uv2_scale;\n" 886 | code += "uniform vec3 uv2_offset;\n" 887 | 888 | code += "\n\n" 889 | 890 | 891 | code += "vec4 map_to_udim_tile(sampler2D sampler, vec2 uv, vec2 x_thresholds, vec2 y_thresholds) {\n" 892 | code += " bvec2 ltx = lessThan(vec2(uv.x,uv.x), x_thresholds);\n" 893 | code += " bvec2 gtx = greaterThan(vec2(uv.x,uv.x), x_thresholds);\n" 894 | code += " bvec2 lty = lessThan(vec2(uv.y,uv.y), y_thresholds);\n" 895 | code += " bvec2 gty = greaterThan(vec2(uv.y,uv.y), y_thresholds);\n" 896 | code += " vec4 f_tex0x = texture(sampler,uv) * float((int(ltx.y) * int(gtx.x)) * (int(lty.y) * int(gty.x)));\n" 897 | code += " f_tex0x.a = 1.0;\n" 898 | code += " return f_tex0x;\n" 899 | code += "}\n" 900 | 901 | code += "\n\n" 902 | 903 | code += "void vertex() {\n" 904 | 905 | if flags[BaseMaterial3D.FLAG_SRGB_VERTEX_COLOR]: 906 | code += " if (!OUTPUT_IS_SRGB) {\n" 907 | code += " COLOR.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" 908 | code += " }\n" 909 | 910 | if flags[BaseMaterial3D.FLAG_USE_POINT_SIZE]: 911 | code += " POINT_SIZE=point_size;\n" 912 | 913 | if shading_mode == BaseMaterial3D.ShadingMode.SHADING_MODE_PER_VERTEX: 914 | code += " ROUGHNESS=roughness;\n" 915 | 916 | match billboard_mode: 917 | BaseMaterial3D.BillboardMode.BILLBOARD_DISABLED: 918 | pass 919 | 920 | BaseMaterial3D.BillboardMode.BILLBOARD_ENABLED: 921 | code += " MODELVIEW_MATRIX = VIEW_MATRIX * mat4(INV_VIEW_MATRIX[0], INV_VIEW_MATRIX[1], INV_VIEW_MATRIX[2], MODEL_MATRIX[3]);\n" 922 | if flags[BaseMaterial3D.FLAG_BILLBOARD_KEEP_SCALE]: 923 | code += " MODELVIEW_MATRIX = MODELVIEW_MATRIX * mat4(vec4(length(MODEL_MATRIX[0].xyz), 0.0, 0.0, 0.0), vec4(0.0, length(MODEL_MATRIX[1].xyz), 0.0, 0.0), vec4(0.0, 0.0, length(MODEL_MATRIX[2].xyz), 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n" 924 | code += " MODELVIEW_NORMAL_MATRIX = mat3(MODELVIEW_MATRIX);\n" 925 | 926 | BaseMaterial3D.BILLBOARD_FIXED_Y: 927 | code += " MODELVIEW_MATRIX = VIEW_MATRIX * mat4(vec4(normalize(cross(vec3(0.0, 1.0, 0.0), INV_VIEW_MATRIX[2].xyz)), 0.0), vec4(0.0, 1.0, 0.0, 0.0), vec4(normalize(cross(INV_VIEW_MATRIX[0].xyz, vec3(0.0, 1.0, 0.0))), 0.0), MODEL_MATRIX[3]);\n" 928 | if flags[BaseMaterial3D.FLAG_BILLBOARD_KEEP_SCALE]: 929 | code += " MODELVIEW_MATRIX = MODELVIEW_MATRIX * mat4(vec4(length(MODEL_MATRIX[0].xyz), 0.0, 0.0, 0.0),vec4(0.0, length(MODEL_MATRIX[1].xyz), 0.0, 0.0), vec4(0.0, 0.0, length(MODEL_MATRIX[2].xyz), 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n" 930 | code += " MODELVIEW_NORMAL_MATRIX = mat3(MODELVIEW_MATRIX);\n" 931 | 932 | BaseMaterial3D.BILLBOARD_PARTICLES: 933 | # make billboard 934 | code += " mat4 mat_world = mat4(normalize(INV_VIEW_MATRIX[0]), normalize(INV_VIEW_MATRIX[1]) ,normalize(INV_VIEW_MATRIX[2]), MODEL_MATRIX[3]);\n"; 935 | # rotate by rotation 936 | code += " mat_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"; 937 | # set modelview 938 | code += " MODELVIEW_MATRIX = VIEW_MATRIX * mat_world;\n"; 939 | if flags[BaseMaterial3D.FLAG_BILLBOARD_KEEP_SCALE]: 940 | code += " MODELVIEW_MATRIX = MODELVIEW_MATRIX * mat4(vec4(length(MODEL_MATRIX[0].xyz), 0.0, 0.0, 0.0),vec4(0.0, length(MODEL_MATRIX[1].xyz), 0.0, 0.0), vec4(0.0, 0.0, length(MODEL_MATRIX[2].xyz), 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n"; 941 | # set modelview normal 942 | code += " MODELVIEW_NORMAL_MATRIX = mat3(MODELVIEW_MATRIX);\n"; 943 | 944 | # handle animation 945 | code += " float h_frames = float(particles_anim_h_frames);\n"; 946 | code += " float v_frames = float(particles_anim_v_frames);\n"; 947 | code += " float particle_total_frames = float(particles_anim_h_frames * particles_anim_v_frames);\n"; 948 | code += " float particle_frame = floor(INSTANCE_CUSTOM.z * float(particle_total_frames));\n"; 949 | code += " if (!particles_anim_loop) {\n"; 950 | code += " particle_frame = clamp(particle_frame, 0.0, particle_total_frames - 1.0);\n"; 951 | code += " } else {\n"; 952 | code += " particle_frame = mod(particle_frame, particle_total_frames);\n"; 953 | code += " }\n"; 954 | code += " UV /= vec2(h_frames, v_frames);\n"; 955 | code += " UV += vec2(mod(particle_frame, h_frames) / h_frames, floor((particle_frame + 0.5) / h_frames) / v_frames);\n"; 956 | 957 | if flags[BaseMaterial3D.FLAG_FIXED_SIZE]: 958 | code += " if (PROJECTION_MATRIX[3][3] != 0.0) {\n" 959 | code += " float h = abs(1.0 / (2.0 * PROJECTION_MATRIX[1][1]));\n" 960 | code += " float sc = (h * 2.0); //consistent with Y-fov\n" 961 | code += " MODELVIEW_MATRIX[0]*=sc;\n" 962 | code += " MODELVIEW_MATRIX[1]*=sc;\n" 963 | code += " MODELVIEW_MATRIX[2]*=sc;\n" 964 | code += " } else {\n" 965 | code += " float sc = -(MODELVIEW_MATRIX)[3].z;\n" 966 | code += " MODELVIEW_MATRIX[0]*=sc;\n" 967 | code += " MODELVIEW_MATRIX[1]*=sc;\n" 968 | code += " MODELVIEW_MATRIX[2]*=sc;\n" 969 | code += " }\n" 970 | 971 | if detail_uv == BaseMaterial3D.DETAIL_UV_2: 972 | code += " UV2=UV2*uv2_scale.xy+uv2_offset.xy;\n" 973 | 974 | if grow_enabled: 975 | code += " VERTEX+=NORMAL*grow;\n" 976 | 977 | code += "}\n" 978 | code += "\n\n" 979 | 980 | if flags[BaseMaterial3D.FLAG_ALBEDO_TEXTURE_MSDF]: 981 | code += "float msdf_median(float r, float g, float b, float a) {\n" 982 | code += " return min(max(min(r, g), min(max(r, g), b)), a);\n" 983 | code += "}\n" 984 | 985 | 986 | code += "\n\n" 987 | code += "void fragment() {\n" 988 | 989 | code += " vec2 base_uv = UV;\n" 990 | 991 | if ((features[BaseMaterial3D.FEATURE_DETAIL] and detail_uv == BaseMaterial3D.DETAIL_UV_2) or (features[BaseMaterial3D.FEATURE_AMBIENT_OCCLUSION] and flags[BaseMaterial3D.FLAG_AO_ON_UV2]) or (features[BaseMaterial3D.FEATURE_EMISSION] and flags[BaseMaterial3D.FLAG_EMISSION_ON_UV2])): 992 | code += " vec2 base_uv2 = UV2;\n" 993 | 994 | if features[BaseMaterial3D.FEATURE_HEIGHT_MAPPING]: 995 | code += " {\n" 996 | code += " vec3 view_dir = normalize(normalize(-VERTEX + EYE_OFFSET) * mat3(TANGENT * heightmap_flip.x, -BINORMAL * heightmap_flip.y, NORMAL));\n" 997 | 998 | if heightmap_deep_parallax: 999 | code += " float num_layers = mix(float(heightmap_max_layers),float(heightmap_min_layers), abs(dot(vec3(0.0, 0.0, 1.0), view_dir)));\n" 1000 | code += " float layer_depth = 1.0 / num_layers;\n" 1001 | code += " float current_layer_depth = 0.0;\n" 1002 | code += " vec2 P = view_dir.xy * heightmap_scale * 0.01;\n" 1003 | code += " vec2 delta = P / num_layers;\n" 1004 | code += " vec2 ofs = base_uv;\n" 1005 | if flags[BaseMaterial3D.FLAG_INVERT_HEIGHTMAP]: 1006 | code += " float depth = texture(texture_heightmap, ofs).r;\n" 1007 | else: 1008 | code += " float depth = 1.0 - texture(texture_heightmap, ofs).r;\n" 1009 | code += " float current_depth = 0.0;\n" 1010 | code += " while(current_depth < depth) {\n" 1011 | code += " ofs -= delta;\n" 1012 | if flags[BaseMaterial3D.FLAG_INVERT_HEIGHTMAP]: 1013 | code += " depth = texture(texture_heightmap, ofs).r;\n" 1014 | else: 1015 | code += " depth = 1.0 - texture(texture_heightmap, ofs).r;\n" 1016 | code += " current_depth += layer_depth;\n" 1017 | code += " }\n" 1018 | code += " vec2 prev_ofs = ofs + delta;\n" 1019 | code += " float after_depth = depth - current_depth;\n" 1020 | if flags[BaseMaterial3D.FLAG_INVERT_HEIGHTMAP]: 1021 | code += " float before_depth = texture(texture_heightmap, prev_ofs).r - current_depth + layer_depth;\n" 1022 | else: 1023 | code += " float before_depth = ( 1.0 - texture(texture_heightmap, prev_ofs).r ) - current_depth + layer_depth;\n" 1024 | code += " float weight = after_depth / (after_depth - before_depth);\n" 1025 | code += " ofs = mix(ofs,prev_ofs,weight);\n" 1026 | 1027 | else: 1028 | if flags[BaseMaterial3D.FLAG_INVERT_HEIGHTMAP]: 1029 | code += " float depth = texture(texture_heightmap, base_uv).r;\n" 1030 | else: 1031 | code += " float depth = 1.0 - texture(texture_heightmap, base_uv).r;\n" 1032 | code += " vec2 ofs = base_uv - view_dir.xy * depth * heightmap_scale * 0.01;\n" 1033 | 1034 | code += " base_uv=ofs;\n" 1035 | if features[BaseMaterial3D.FEATURE_DETAIL] and detail_uv == BaseMaterial3D.DETAIL_UV_2: 1036 | code += " base_uv2-=ofs;\n" 1037 | 1038 | code += " }\n" 1039 | 1040 | if albedo_tileset != null and albedo_tileset.has_tiles(): 1041 | var tile_stats = albedo_tileset.get_tiles_status() 1042 | for tile_name in tile_stats.keys(): 1043 | if tile_stats[tile_name][0]: 1044 | code += " vec4 f_" + tile_name + " = map_to_udim_tile(" + tile_name + ",base_uv,vec2(" + str(tile_stats[tile_name][1][0].x) + "," + str(tile_stats[tile_name][1][0].y) + "),vec2(" + str(tile_stats[tile_name][1][1].x) + "," + str(tile_stats[tile_name][1][1].y) + "));\n" 1045 | 1046 | 1047 | code += " vec4 albedo_tex = " 1048 | 1049 | var valid_tiles = [] 1050 | for tile_name in tile_stats.keys(): 1051 | if tile_stats[tile_name][0]: 1052 | valid_tiles.append("f_" + tile_name) 1053 | 1054 | code += "+".join(valid_tiles) + ";\n" 1055 | 1056 | # for tile_name in tile_stats.keys(): 1057 | 1058 | # if tile_stats[tile_name][0]: 1059 | # if tile_name == tile_stats.keys()[len(tile_stats.keys())-1]: 1060 | # code += " f_" + tile_name + ";\n" 1061 | # else: 1062 | # code += " f_" + tile_name + " +\n" 1063 | code += " albedo_tex.a = 1.0;\n" 1064 | 1065 | if flags[BaseMaterial3D.FLAG_ALBEDO_TEXTURE_MSDF]: 1066 | code += " {\n"; 1067 | code += " albedo_tex.rgb = mix(vec3(1.0 + 0.055) * pow(albedo_tex.rgb, vec3(1.0 / 2.4)) - vec3(0.055), vec3(12.92) * albedo_tex.rgb.rgb, lessThan(albedo_tex.rgb, vec3(0.0031308)));\n"; 1068 | code += " vec2 msdf_size = vec2(msdf_pixel_range) / vec2(textureSize(texture_albedo, 0));\n"; 1069 | if flags[BaseMaterial3D.FLAG_USE_POINT_SIZE]: 1070 | code += " vec2 dest_size = vec2(1.0) / fwidth(POINT_COORD);\n"; 1071 | else: 1072 | code += " vec2 dest_size = vec2(1.0) / fwidth(base_uv);\n"; 1073 | 1074 | code += " float px_size = max(0.5 * dot(msdf_size, dest_size), 1.0);\n"; 1075 | code += " float d = msdf_median(albedo_tex.r, albedo_tex.g, albedo_tex.b, albedo_tex.a) - 0.5;\n"; 1076 | code += " if (msdf_outline_size > 0.0) {\n"; 1077 | code += " float cr = clamp(msdf_outline_size, 0.0, msdf_pixel_range / 2.0) / msdf_pixel_range;\n"; 1078 | code += " albedo_tex.a = clamp((d + cr) * px_size, 0.0, 1.0);\n"; 1079 | code += " } else {\n"; 1080 | code += " albedo_tex.a = clamp(d * px_size + 0.5, 0.0, 1.0);\n"; 1081 | code += " }\n"; 1082 | code += " albedo_tex.rgb = vec3(1.0);\n"; 1083 | code += " }\n"; 1084 | 1085 | elif flags[BaseMaterial3D.FLAG_ALBEDO_TEXTURE_FORCE_SRGB]: 1086 | code += " albedo_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" 1087 | 1088 | if flags[BaseMaterial3D.FLAG_ALBEDO_FROM_VERTEX_COLOR]: 1089 | code += " albedo_tex *= COLOR;\n" 1090 | 1091 | if albedo_tileset != null and albedo_tileset.has_tiles(): 1092 | code += " ALBEDO = albedo.rgb * albedo_tex.rgb;\n" 1093 | else: 1094 | code += " ALBEDO = albedo.rgb;\n" 1095 | 1096 | 1097 | code += " float metallic_tex = dot(texture(texture_metallic,base_uv),metallic_texture_channel);\n"; 1098 | 1099 | code += " METALLIC = metallic_tex * metallic;\n"; 1100 | 1101 | match roughness_texture_channel: 1102 | BaseMaterial3D.TEXTURE_CHANNEL_RED: 1103 | code += " vec4 roughness_texture_channel = vec4(1.0,0.0,0.0,0.0);\n"; 1104 | BaseMaterial3D.TEXTURE_CHANNEL_GREEN: 1105 | code += " vec4 roughness_texture_channel = vec4(0.0,1.0,0.0,0.0);\n"; 1106 | BaseMaterial3D.TEXTURE_CHANNEL_BLUE: 1107 | code += " vec4 roughness_texture_channel = vec4(0.0,0.0,1.0,0.0);\n"; 1108 | BaseMaterial3D.TEXTURE_CHANNEL_ALPHA: 1109 | code += " vec4 roughness_texture_channel = vec4(0.0,0.0,0.0,1.0);\n"; 1110 | BaseMaterial3D.TEXTURE_CHANNEL_GRAYSCALE: 1111 | code += " vec4 roughness_texture_channel = vec4(0.333333,0.333333,0.333333,0.0);\n"; 1112 | 1113 | 1114 | code += " float roughness_tex = dot(texture(texture_roughness,base_uv),roughness_texture_channel);\n"; 1115 | 1116 | code += " ROUGHNESS = roughness_tex * roughness;\n"; 1117 | code += " SPECULAR = specular;\n"; 1118 | 1119 | if features[BaseMaterial3D.FEATURE_NORMAL_MAPPING]: 1120 | code += " NORMAL_MAP = texture(texture_normal,base_uv).rgb;\n"; 1121 | code += " NORMAL_MAP_DEPTH = normal_scale;\n"; 1122 | 1123 | if features[BaseMaterial3D.FEATURE_EMISSION]: 1124 | if flags[BaseMaterial3D.FLAG_EMISSION_ON_UV2]: 1125 | code += " vec3 emission_tex = texture(texture_emission,base_uv2).rgb;\n"; 1126 | else: 1127 | code += " vec3 emission_tex = texture(texture_emission,base_uv).rgb;\n"; 1128 | 1129 | if emission_op == BaseMaterial3D.EMISSION_OP_ADD: 1130 | code += " EMISSION = (emission.rgb+emission_tex)*emission_energy;\n"; 1131 | else: 1132 | code += " EMISSION = (emission.rgb*emission_tex)*emission_energy;\n"; 1133 | 1134 | if features[BaseMaterial3D.FEATURE_REFRACTION]: 1135 | if features[BaseMaterial3D.FEATURE_NORMAL_MAPPING]: 1136 | code += " vec3 unpacked_normal = NORMAL_MAP;\n" 1137 | code += " unpacked_normal.xy = unpacked_normal.xy * 2.0 - 1.0;\n" 1138 | code += " unpacked_normal.z = sqrt(max(0.0, 1.0 - dot(unpacked_normal.xy, unpacked_normal.xy)));\n" 1139 | code += " vec3 ref_normal = normalize( mix(NORMAL,TANGENT * unpacked_normal.x + BINORMAL * unpacked_normal.y + NORMAL * unpacked_normal.z,NORMAL_MAP_DEPTH) );\n" 1140 | else: 1141 | code += " vec3 ref_normal = NORMAL;\n" 1142 | 1143 | 1144 | code += " vec2 ref_ofs = SCREEN_UV - ref_normal.xy * dot(texture(texture_refraction,base_uv),refraction_texture_channel) * refraction;\n" 1145 | 1146 | code += " float ref_amount = 1.0 - albedo.a * albedo_tex.a;\n" 1147 | code += " EMISSION += textureLod(screen_texture,ref_ofs,ROUGHNESS * 8.0).rgb * ref_amount * EXPOSURE;\n" 1148 | code += " ALBEDO *= 1.0 - ref_amount;\n" 1149 | code += " ALPHA = 1.0;\n" 1150 | 1151 | elif transparency != BaseMaterial3D.TRANSPARENCY_DISABLED or flags[BaseMaterial3D.FLAG_USE_SHADOW_TO_OPACITY] or (distance_fade == BaseMaterial3D.DISTANCE_FADE_PIXEL_ALPHA) or proximity_fade_enabled: 1152 | code += " ALPHA *= albedo.a * albedo_tex.a;\n" 1153 | 1154 | if transparency == BaseMaterial3D.TRANSPARENCY_ALPHA_HASH: 1155 | code += " ALPHA_HASH_SCALE = alpha_hash_scale;\n" 1156 | elif transparency == BaseMaterial3D.TRANSPARENCY_ALPHA_SCISSOR: 1157 | code += " ALPHA_SCISSOR_THRESHOLD = alpha_scissor_threshold;\n" 1158 | 1159 | if alpha_antialiasing_mode != BaseMaterial3D.ALPHA_ANTIALIASING_OFF and (transparency == BaseMaterial3D.TRANSPARENCY_ALPHA_HASH or transparency == BaseMaterial3D.TRANSPARENCY_ALPHA_SCISSOR): 1160 | code += " ALPHA_ANTIALIASING_EDGE = alpha_antialiasing_edge;\n" 1161 | code += " ALPHA_TEXTURE_COORDINATE = UV * vec2(albedo_texture_size);\n" 1162 | 1163 | if proximity_fade_enabled: 1164 | code += " float depth_tex = textureLod(depth_texture,SCREEN_UV,0.0).r;\n" 1165 | code += " vec4 world_pos = INV_PROJECTION_MATRIX * vec4(SCREEN_UV*2.0-1.0,depth_tex,1.0);\n" 1166 | code += " world_pos.xyz/=world_pos.w;\n" 1167 | code += " ALPHA*=clamp(1.0-smoothstep(world_pos.z+proximity_fade_distance,world_pos.z,VERTEX.z),0.0,1.0);\n" 1168 | 1169 | if distance_fade != BaseMaterial3D.DISTANCE_FADE_DISABLED: 1170 | if distance_fade == BaseMaterial3D.DISTANCE_FADE_OBJECT_DITHER or distance_fade == BaseMaterial3D.DISTANCE_FADE_PIXEL_DITHER: 1171 | code += " {\n" 1172 | if distance_fade == BaseMaterial3D.DISTANCE_FADE_OBJECT_DITHER: 1173 | code += " float fade_distance = length((VIEW_MATRIX * MODEL_MATRIX[3]));\n" 1174 | else: 1175 | code += " float fade_distance = length(VERTEX);\n" 1176 | code += " const vec3 magic = vec3(0.06711056f, 0.00583715f, 52.9829189f);" 1177 | code += " float fade = clamp(smoothstep(distance_fade_min, distance_fade_max, fade_distance), 0.0, 1.0);\n" 1178 | code += " if (fade < 0.001 || fade < fract(magic.z * fract(dot(FRAGCOORD.xy, magic.xy)))) {\n" 1179 | code += " discard;\n" 1180 | code += " }\n" 1181 | code += " }\n\n" 1182 | else: 1183 | code += " ALPHA *= clamp(smoothstep(distance_fade_min, distance_fade_max, length(VERTEX)), 0.0, 1.0);\n" 1184 | 1185 | if features[BaseMaterial3D.FEATURE_RIM]: 1186 | code += " vec2 rim_tex = texture(texture_rim,base_uv).xy;\n"; 1187 | code += " RIM = rim*rim_tex.x;" 1188 | code += " RIM_TINT = rim_tint*rim_tex.y;\n" 1189 | 1190 | if features[BaseMaterial3D.FEATURE_CLEARCOAT]: 1191 | code += " vec2 clearcoat_tex = texture(texture_clearcoat,base_uv).xy;\n"; 1192 | code += " CLEARCOAT = clearcoat*clearcoat_tex.x;" 1193 | code += " CLEARCOAT_ROUGHNESS = clearcoat_roughness*clearcoat_tex.y;\n" 1194 | 1195 | if features[BaseMaterial3D.FEATURE_ANISOTROPY]: 1196 | code += " vec3 anisotropy_tex = texture(texture_flowmap,base_uv).rga;\n"; 1197 | code += " ANISOTROPY = anisotropy_ratio*anisotropy_tex.b;\n" 1198 | code += " ANISOTROPY_FLOW = anisotropy_tex.rg*2.0-1.0;\n" 1199 | 1200 | if features[BaseMaterial3D.FEATURE_AMBIENT_OCCLUSION]: 1201 | if flags[BaseMaterial3D.FLAG_AO_ON_UV2]: 1202 | code += " AO = dot(texture(texture_ambient_occlusion,base_uv2),ao_texture_channel);\n"; 1203 | else: 1204 | code += " AO = dot(texture(texture_ambient_occlusion,base_uv),ao_texture_channel);\n"; 1205 | 1206 | code += " AO_LIGHT_AFFECT = ao_light_affect;\n"; 1207 | 1208 | 1209 | if features[BaseMaterial3D.FEATURE_SUBSURFACE_SCATTERING]: 1210 | code += " float sss_tex = texture(texture_subsurface_scattering,base_uv).r;\n"; 1211 | code += " SSS_STRENGTH=subsurface_scattering_strength*sss_tex;\n"; 1212 | 1213 | if features[BaseMaterial3D.FEATURE_SUBSURFACE_TRANSMITTANCE]: 1214 | code += " vec4 trans_color_tex = texture(texture_subsurface_transmittance,base_uv);\n"; 1215 | 1216 | code += " SSS_TRANSMITTANCE_COLOR=transmittance_color*trans_color_tex;\n"; 1217 | 1218 | code += " SSS_TRANSMITTANCE_DEPTH=transmittance_depth;\n"; 1219 | code += " SSS_TRANSMITTANCE_BOOST=transmittance_boost;\n"; 1220 | 1221 | if features[BaseMaterial3D.FEATURE_BACKLIGHT]: 1222 | code += " vec3 backlight_tex = texture(texture_backlight,base_uv).rgb;\n"; 1223 | code += " BACKLIGHT = (backlight.rgb+backlight_tex);\n"; 1224 | 1225 | 1226 | if features[BaseMaterial3D.FEATURE_DETAIL]: 1227 | 1228 | var det_uv = "base_uv" if detail_uv == BaseMaterial3D.DETAIL_UV_1 else "base_uv2" 1229 | code += " vec4 detail_tex = texture(texture_detail_albedo," + det_uv + ");\n" 1230 | code += " vec4 detail_norm_tex = texture(texture_detail_normal," + det_uv + ");\n" 1231 | 1232 | 1233 | code += " vec4 detail_mask_tex = texture(texture_detail_mask,base_uv);\n" 1234 | 1235 | match detail_blend_mode: 1236 | BaseMaterial3D.BLEND_MODE_MIX: 1237 | code += " vec3 detail = mix(ALBEDO.rgb,detail_tex.rgb,detail_tex.a);\n" 1238 | BaseMaterial3D.BLEND_MODE_ADD: 1239 | code += " vec3 detail = mix(ALBEDO.rgb,ALBEDO.rgb+detail_tex.rgb,detail_tex.a);\n" 1240 | BaseMaterial3D.BLEND_MODE_SUB: 1241 | code += " vec3 detail = mix(ALBEDO.rgb,ALBEDO.rgb-detail_tex.rgb,detail_tex.a);\n" 1242 | BaseMaterial3D.BLEND_MODE_MUL: 1243 | code += " vec3 detail = mix(ALBEDO.rgb,ALBEDO.rgb*detail_tex.rgb,detail_tex.a);\n" 1244 | 1245 | code += " vec3 detail_norm = mix(NORMAL_MAP,detail_norm_tex.rgb,detail_tex.a);\n" 1246 | code += " NORMAL_MAP = mix(NORMAL_MAP,detail_norm,detail_mask_tex.r);\n" 1247 | code += " ALBEDO.rgb = mix(ALBEDO.rgb,detail,detail_mask_tex.r);\n" 1248 | 1249 | code += "}\n" 1250 | 1251 | var new_shader = Shader.new() 1252 | new_shader.code = code 1253 | 1254 | # print(new_shader.get_mode()) 1255 | 1256 | shader = new_shader 1257 | # print(code) 1258 | _update_shader_params() 1259 | --------------------------------------------------------------------------------