Browse Source

Add distance based dithering to the default material.

Juan Linietsky 7 years ago
parent
commit
334acc017f
2 changed files with 72 additions and 18 deletions
  1. 59 13
      scene/resources/material.cpp
  2. 13 5
      scene/resources/material.h

+ 59 - 13
scene/resources/material.cpp

@@ -400,8 +400,10 @@ void SpatialMaterial::_update_shader() {
 	if (flags[FLAG_USE_VERTEX_LIGHTING]) {
 	if (flags[FLAG_USE_VERTEX_LIGHTING]) {
 		code += ",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])) {
 	if (flags[FLAG_TRIPLANAR_USE_WORLD] && (flags[FLAG_UV1_USE_TRIPLANAR] || flags[FLAG_UV2_USE_TRIPLANAR])) {
 		code += ",world_vertex_coords";
 		code += ",world_vertex_coords";
+		using_world = true;
 	}
 	}
 	if (flags[FLAG_DONT_RECEIVE_SHADOWS]) {
 	if (flags[FLAG_DONT_RECEIVE_SHADOWS]) {
 		code += ",shadows_disabled";
 		code += ",shadows_disabled";
@@ -425,7 +427,7 @@ void SpatialMaterial::_update_shader() {
 	if (proximity_fade_enabled) {
 	if (proximity_fade_enabled) {
 		code += "uniform float proximity_fade_distance;\n";
 		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_min;\n";
 		code += "uniform float distance_fade_max;\n";
 		code += "uniform float distance_fade_max;\n";
 	}
 	}
@@ -784,7 +786,7 @@ void SpatialMaterial::_update_shader() {
 		code += "\tALBEDO *= 1.0 - ref_amount;\n";
 		code += "\tALBEDO *= 1.0 - ref_amount;\n";
 		code += "\tALPHA = 1.0;\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";
 		code += "\tALPHA = albedo.a * albedo_tex.a;\n";
 	}
 	}
 
 
@@ -795,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";
 		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]) {
 	if (features[FEATURE_RIM]) {
@@ -1326,7 +1367,7 @@ void SpatialMaterial::_validate_property(PropertyInfo &property) const {
 		property.usage = 0;
 		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;
 		property.usage = 0;
 	}
 	}
 
 
@@ -1647,15 +1688,15 @@ float SpatialMaterial::get_proximity_fade_distance() const {
 	return proximity_fade_distance;
 	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();
 	_queue_shader_change();
 	_change_notify();
 	_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) {
 void SpatialMaterial::set_distance_fade_max_distance(float p_distance) {
@@ -1861,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("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("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("set_distance_fade_max_distance", "distance"), &SpatialMaterial::set_distance_fade_max_distance);
 	ClassDB::bind_method(D_METHOD("get_distance_fade_max_distance"), &SpatialMaterial::get_distance_fade_max_distance);
 	ClassDB::bind_method(D_METHOD("get_distance_fade_max_distance"), &SpatialMaterial::get_distance_fade_max_distance);
@@ -2005,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::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_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_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_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");
 	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");
 
 
@@ -2103,6 +2144,11 @@ void SpatialMaterial::_bind_methods() {
 
 
 	BIND_ENUM_CONSTANT(EMISSION_OP_ADD);
 	BIND_ENUM_CONSTANT(EMISSION_OP_ADD);
 	BIND_ENUM_CONSTANT(EMISSION_OP_MULTIPLY);
 	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() :
 SpatialMaterial::SpatialMaterial() :
@@ -2141,7 +2187,7 @@ SpatialMaterial::SpatialMaterial() :
 	emission_op = EMISSION_OP_ADD;
 	emission_op = EMISSION_OP_ADD;
 
 
 	proximity_fade_enabled = false;
 	proximity_fade_enabled = false;
-	distance_fade_enabled = false;
+	distance_fade = DISTANCE_FADE_DISABLED;
 	set_proximity_fade_distance(1);
 	set_proximity_fade_distance(1);
 	set_distance_fade_min_distance(0);
 	set_distance_fade_min_distance(0);
 	set_distance_fade_max_distance(10);
 	set_distance_fade_max_distance(10);

+ 13 - 5
scene/resources/material.h

@@ -233,6 +233,13 @@ public:
 		EMISSION_OP_MULTIPLY
 		EMISSION_OP_MULTIPLY
 	};
 	};
 
 
+	enum DistanceFadeMode {
+		DISTANCE_FADE_DISABLED,
+		DISTANCE_FADE_PIXEL_ALPHA,
+		DISTANCE_FADE_PIXEL_DITHER,
+		DISTANCE_FADE_OBJECT_DITHER,
+	};
+
 private:
 private:
 	union MaterialKey {
 	union MaterialKey {
 
 
@@ -251,7 +258,7 @@ private:
 			uint64_t billboard_mode : 2;
 			uint64_t billboard_mode : 2;
 			uint64_t grow : 1;
 			uint64_t grow : 1;
 			uint64_t proximity_fade : 1;
 			uint64_t proximity_fade : 1;
-			uint64_t distance_fade : 1;
+			uint64_t distance_fade : 2;
 			uint64_t emission_op : 1;
 			uint64_t emission_op : 1;
 		};
 		};
 
 
@@ -296,7 +303,7 @@ private:
 		mk.deep_parallax = deep_parallax ? 1 : 0;
 		mk.deep_parallax = deep_parallax ? 1 : 0;
 		mk.grow = grow_enabled;
 		mk.grow = grow_enabled;
 		mk.proximity_fade = proximity_fade_enabled;
 		mk.proximity_fade = proximity_fade_enabled;
-		mk.distance_fade = distance_fade_enabled;
+		mk.distance_fade = distance_fade;
 		mk.emission_op = emission_op;
 		mk.emission_op = emission_op;
 
 
 		return mk;
 		return mk;
@@ -402,7 +409,7 @@ private:
 	bool proximity_fade_enabled;
 	bool proximity_fade_enabled;
 	float proximity_fade_distance;
 	float proximity_fade_distance;
 
 
-	bool distance_fade_enabled;
+	DistanceFadeMode distance_fade;
 	float distance_fade_max_distance;
 	float distance_fade_max_distance;
 	float distance_fade_min_distance;
 	float distance_fade_min_distance;
 
 
@@ -583,8 +590,8 @@ public:
 	void set_proximity_fade_distance(float p_distance);
 	void set_proximity_fade_distance(float p_distance);
 	float get_proximity_fade_distance() const;
 	float get_proximity_fade_distance() const;
 
 
-	void set_distance_fade(bool p_enable);
-	bool is_distance_fade_enabled() const;
+	void set_distance_fade(DistanceFadeMode p_mode);
+	DistanceFadeMode get_distance_fade() const;
 
 
 	void set_distance_fade_max_distance(float p_distance);
 	void set_distance_fade_max_distance(float p_distance);
 	float get_distance_fade_max_distance() const;
 	float get_distance_fade_max_distance() const;
@@ -630,6 +637,7 @@ VARIANT_ENUM_CAST(SpatialMaterial::SpecularMode)
 VARIANT_ENUM_CAST(SpatialMaterial::BillboardMode)
 VARIANT_ENUM_CAST(SpatialMaterial::BillboardMode)
 VARIANT_ENUM_CAST(SpatialMaterial::TextureChannel)
 VARIANT_ENUM_CAST(SpatialMaterial::TextureChannel)
 VARIANT_ENUM_CAST(SpatialMaterial::EmissionOperator)
 VARIANT_ENUM_CAST(SpatialMaterial::EmissionOperator)
+VARIANT_ENUM_CAST(SpatialMaterial::DistanceFadeMode)
 
 
 //////////////////////
 //////////////////////