diff options
Diffstat (limited to 'scene/resources/material.cpp')
-rw-r--r-- | scene/resources/material.cpp | 118 |
1 files changed, 99 insertions, 19 deletions
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index 5e7569586a..4727526b68 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -34,6 +34,8 @@ void Material::set_next_pass(const Ref<Material> &p_pass) { + ERR_FAIL_COND(p_pass == this); + if (next_pass == p_pass) return; @@ -145,11 +147,17 @@ void ShaderMaterial::_get_property_list(List<PropertyInfo> *p_list) const { void ShaderMaterial::set_shader(const Ref<Shader> &p_shader) { + if (shader.is_valid()) { + shader->disconnect("changed", this, "_shader_changed"); + } + shader = p_shader; RID rid; - if (shader.is_valid()) + if (shader.is_valid()) { rid = shader->get_rid(); + shader->connect("changed", this, "_shader_changed"); + } VS::get_singleton()->material_set_shader(_get_material(), rid); _change_notify(); //properties for shader exposed @@ -171,12 +179,17 @@ Variant ShaderMaterial::get_shader_param(const StringName &p_param) const { return VS::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); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shader", PROPERTY_HINT_RESOURCE_TYPE, "Shader"), "set_shader", "get_shader"); } @@ -387,12 +400,20 @@ void SpatialMaterial::_update_shader() { if (flags[FLAG_USE_VERTEX_LIGHTING]) { code += ",vertex_lighting"; } + bool using_world = false; if (flags[FLAG_TRIPLANAR_USE_WORLD] && (flags[FLAG_UV1_USE_TRIPLANAR] || flags[FLAG_UV2_USE_TRIPLANAR])) { code += ",world_vertex_coords"; + using_world = true; } 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"; + } code += ";\n"; code += "uniform vec4 albedo : hint_color;\n"; @@ -406,7 +427,7 @@ void SpatialMaterial::_update_shader() { if (proximity_fade_enabled) { code += "uniform float proximity_fade_distance;\n"; } - if (distance_fade_enabled) { + if (distance_fade != DISTANCE_FADE_DISABLED) { code += "uniform float distance_fade_min;\n"; code += "uniform float distance_fade_max;\n"; } @@ -537,9 +558,20 @@ void SpatialMaterial::_update_shader() { 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),vec4(0,length(WORLD_MATRIX[1].xyz),0,0),vec4(0,0,length(WORLD_MATRIX[2].xyz),0),vec4(0,0,0,1));\n"; + } } break; case BILLBOARD_FIXED_Y: { + code += "\tMODELVIEW_MATRIX = INV_CAMERA_MATRIX * mat4(CAMERA_MATRIX[0],WORLD_MATRIX[1],vec4(normalize(cross(CAMERA_MATRIX[0].xyz,WORLD_MATRIX[1].xyz)),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),vec4(0,1,0,0),vec4(0,0,length(WORLD_MATRIX[2].xyz),0),vec4(0,0,0,1));\n"; + } else { + code += "\tMODELVIEW_MATRIX = MODELVIEW_MATRIX * mat4(vec4(1,0,0,0),vec4(0,1.0/length(WORLD_MATRIX[1].xyz),0,0),vec4(0,0,1,0),vec4(0,0,0,1));\n"; + } } break; case BILLBOARD_PARTICLES: { @@ -556,8 +588,6 @@ void SpatialMaterial::_update_shader() { code += "\tif (particles_anim_loop) particle_frame=clamp(particle_frame,0,particle_total_frames-1); else particle_frame=abs(particle_frame)%particle_total_frames;\n"; code += "\tUV /= vec2(float(particles_anim_h_frames),float(particles_anim_v_frames));\n"; code += "\tUV += vec2(float(particle_frame % particles_anim_h_frames) / float(particles_anim_h_frames),float(particle_frame / particles_anim_h_frames) / float(particles_anim_v_frames));\n"; - //handle rotation - // code += "\tmat4 rotation = mat4(" } break; } @@ -756,7 +786,7 @@ void SpatialMaterial::_update_shader() { code += "\tALBEDO *= 1.0 - ref_amount;\n"; code += "\tALPHA = 1.0;\n"; - } else if (features[FEATURE_TRANSPARENT] || flags[FLAG_USE_ALPHA_SCISSOR] || distance_fade_enabled || proximity_fade_enabled) { + } else if (features[FEATURE_TRANSPARENT] || flags[FLAG_USE_ALPHA_SCISSOR] || (distance_fade == DISTANCE_FADE_PIXEL_ALPHA) || proximity_fade_enabled) { code += "\tALPHA = albedo.a * albedo_tex.a;\n"; } @@ -767,8 +797,47 @@ void SpatialMaterial::_update_shader() { 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_enabled) { - code += "\tALPHA*=clamp(smoothstep(distance_fade_min,distance_fade_max,-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) { + + 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"; + } + + code += "\t\tfloat fade=clamp(smoothstep(distance_fade_min,distance_fade_max,fade_distance),0.0,1.0);\n"; + code += "\t\tint x = int(FRAGCOORD.x) % 4;\n"; + code += "\t\tint y = int(FRAGCOORD.y) % 4;\n"; + code += "\t\tint index = x + y * 4;\n"; + code += "\t\tfloat limit = 0.0;\n\n"; + code += "\t\tif (x < 8) {\n"; + code += "\t\t\tif (index == 0) limit = 0.0625;\n"; + code += "\t\t\tif (index == 1) limit = 0.5625;\n"; + code += "\t\t\tif (index == 2) limit = 0.1875;\n"; + code += "\t\t\tif (index == 3) limit = 0.6875;\n"; + code += "\t\t\tif (index == 4) limit = 0.8125;\n"; + code += "\t\t\tif (index == 5) limit = 0.3125;\n"; + code += "\t\t\tif (index == 6) limit = 0.9375;\n"; + code += "\t\t\tif (index == 7) limit = 0.4375;\n"; + code += "\t\t\tif (index == 8) limit = 0.25;\n"; + code += "\t\t\tif (index == 9) limit = 0.75;\n"; + code += "\t\t\tif (index == 10) limit = 0.125;\n"; + code += "\t\t\tif (index == 11) limit = 0.625;\n"; + code += "\t\t\tif (index == 12) limit = 1.0;\n"; + code += "\t\t\tif (index == 13) limit = 0.5;\n"; + code += "\t\t\tif (index == 14) limit = 0.875;\n"; + code += "\t\t\tif (index == 15) limit = 0.375;\n"; + code += "\t\t}\n\n"; + code += "\tif (fade < limit)\n"; + code += "\t\tdiscard;\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]) { @@ -855,7 +924,7 @@ void SpatialMaterial::_update_shader() { if (flags[FLAG_UV1_USE_TRIPLANAR]) { - code += "\tvec4 detail_mask_tex = triplanar_texture(texture_detail_mask,uv1_power_normal);\n"; + 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"; } @@ -1298,7 +1367,7 @@ void SpatialMaterial::_validate_property(PropertyInfo &property) const { property.usage = 0; } - if ((property.name == "distance_fade_max_distance" || property.name == "distance_fade_min_distance") && !distance_fade_enabled) { + if ((property.name == "distance_fade_max_distance" || property.name == "distance_fade_min_distance") && distance_fade == DISTANCE_FADE_DISABLED) { property.usage = 0; } @@ -1619,15 +1688,15 @@ float SpatialMaterial::get_proximity_fade_distance() const { return proximity_fade_distance; } -void SpatialMaterial::set_distance_fade(bool p_enable) { +void SpatialMaterial::set_distance_fade(DistanceFadeMode p_mode) { - distance_fade_enabled = p_enable; + distance_fade = p_mode; _queue_shader_change(); _change_notify(); } -bool SpatialMaterial::is_distance_fade_enabled() const { +SpatialMaterial::DistanceFadeMode SpatialMaterial::get_distance_fade() const { - return distance_fade_enabled; + return distance_fade; } void SpatialMaterial::set_distance_fade_max_distance(float p_distance) { @@ -1833,8 +1902,8 @@ void SpatialMaterial::_bind_methods() { 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", "enabled"), &SpatialMaterial::set_distance_fade); - ClassDB::bind_method(D_METHOD("is_distance_fade_enabled"), &SpatialMaterial::is_distance_fade_enabled); + 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); @@ -1852,6 +1921,8 @@ void SpatialMaterial::_bind_methods() { 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_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); @@ -1865,6 +1936,7 @@ void SpatialMaterial::_bind_methods() { 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,10,0.01"), "set_grow", "get_grow"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "params_use_alpha_scissor"), "set_flag", "get_flag", FLAG_USE_ALPHA_SCISSOR); @@ -1974,7 +2046,7 @@ void SpatialMaterial::_bind_methods() { 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.1"), "set_proximity_fade_distance", "get_proximity_fade_distance"); ADD_GROUP("Distance Fade", "distance_fade_"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "distance_fade_enable"), "set_distance_fade", "is_distance_fade_enabled"); + 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.1"), "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.1"), "set_distance_fade_max_distance", "get_distance_fade_max_distance"); @@ -2034,6 +2106,7 @@ void SpatialMaterial::_bind_methods() { 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); @@ -2042,6 +2115,8 @@ void SpatialMaterial::_bind_methods() { 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_MAX); BIND_ENUM_CONSTANT(DIFFUSE_BURLEY); @@ -2069,15 +2144,20 @@ void SpatialMaterial::_bind_methods() { 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); } SpatialMaterial::SpatialMaterial() : element(this) { - //initialize to right values + // 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(0.0); + set_roughness(1.0); set_metallic(0.0); set_emission(Color(0, 0, 0)); set_emission_energy(1.0); @@ -2107,7 +2187,7 @@ SpatialMaterial::SpatialMaterial() : emission_op = EMISSION_OP_ADD; proximity_fade_enabled = false; - distance_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); |