summaryrefslogtreecommitdiff
path: root/scene/resources/material.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'scene/resources/material.cpp')
-rw-r--r--scene/resources/material.cpp118
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);