瀏覽代碼

Add a metallic mode

Juan Linietsky 8 年之前
父節點
當前提交
741e038671
共有 2 個文件被更改,包括 82 次插入5 次删除
  1. 64 4
      scene/resources/material.cpp
  2. 18 1
      scene/resources/material.h

+ 64 - 4
scene/resources/material.cpp

@@ -63,6 +63,7 @@ void FixedSpatialMaterial::init_shaders() {
 	shader_names->albedo="albedo";
 	shader_names->albedo="albedo";
 	shader_names->specular="specular";
 	shader_names->specular="specular";
 	shader_names->roughness="roughness";
 	shader_names->roughness="roughness";
+	shader_names->metalness="metalness";
 	shader_names->emission="emission";
 	shader_names->emission="emission";
 	shader_names->emission_energy="emission_energy";
 	shader_names->emission_energy="emission_energy";
 	shader_names->normal_scale="normal_scale";
 	shader_names->normal_scale="normal_scale";
@@ -173,7 +174,12 @@ void FixedSpatialMaterial::_update_shader() {
 
 
 	code+="uniform vec4 albedo : hint_color;\n";
 	code+="uniform vec4 albedo : hint_color;\n";
 	code+="uniform sampler2D texture_albedo : hint_albedo;\n";
 	code+="uniform sampler2D texture_albedo : hint_albedo;\n";
-	code+="uniform vec4 specular : hint_color;\n";
+	if (specular_mode==SPECULAR_MODE_SPECULAR) {
+		code+="uniform vec4 specular : hint_color;\n";
+	} else {
+		code+="uniform float metalness;\n";
+	}
+
 	code+="uniform float roughness : hint_range(0,1);\n";
 	code+="uniform float roughness : hint_range(0,1);\n";
 	code+="uniform float point_size : hint_range(0,128);\n";
 	code+="uniform float point_size : hint_range(0,128);\n";
 	code+="uniform sampler2D texture_specular : hint_white;\n";
 	code+="uniform sampler2D texture_specular : hint_white;\n";
@@ -326,9 +332,17 @@ void FixedSpatialMaterial::_update_shader() {
 		code+="\tALBEDO.rgb = mix(ALBEDO.rgb,detail,detail_mask_tex.r);\n";
 		code+="\tALBEDO.rgb = mix(ALBEDO.rgb,detail,detail_mask_tex.r);\n";
 	}
 	}
 
 
-	code+="\tvec4 specular_tex = texture(texture_specular,UV);\n";
-	code+="\tSPECULAR = specular.rgb * specular_tex.rgb;\n";
-	code+="\tROUGHNESS = specular.a * roughness;\n";
+	if (specular_mode==SPECULAR_MODE_SPECULAR) {
+
+		code+="\tvec4 specular_tex = texture(texture_specular,UV);\n";
+		code+="\tSPECULAR = specular.rgb * specular_tex.rgb;\n";
+		code+="\tROUGHNESS = specular_tex.a * roughness;\n";
+	} else {
+		code+="\tvec4 specular_tex = texture(texture_specular,UV);\n";
+		code+="\tSPECULAR = vec3(metalness * specular_tex.r);\n";
+		code+="\tROUGHNESS = specular_tex.a * roughness;\n";
+	}
+
 	code+="}\n";
 	code+="}\n";
 
 
 	ShaderData shader_data;
 	ShaderData shader_data;
@@ -398,6 +412,17 @@ Color FixedSpatialMaterial::get_albedo() const{
 	return albedo;
 	return albedo;
 }
 }
 
 
+void FixedSpatialMaterial::set_specular_mode(SpecularMode p_mode) {
+	specular_mode=p_mode;
+	_change_notify();
+	_queue_shader_change();
+}
+
+FixedSpatialMaterial::SpecularMode FixedSpatialMaterial::get_specular_mode() const {
+
+	return specular_mode;
+}
+
 void FixedSpatialMaterial::set_specular(const Color& p_specular){
 void FixedSpatialMaterial::set_specular(const Color& p_specular){
 
 
 	specular=p_specular;
 	specular=p_specular;
@@ -415,11 +440,25 @@ void FixedSpatialMaterial::set_roughness(float p_roughness){
 	VS::get_singleton()->material_set_param(_get_material(),shader_names->roughness,p_roughness);
 	VS::get_singleton()->material_set_param(_get_material(),shader_names->roughness,p_roughness);
 
 
 }
 }
+
+
 float FixedSpatialMaterial::get_roughness() const{
 float FixedSpatialMaterial::get_roughness() const{
 
 
 	return roughness;
 	return roughness;
 }
 }
 
 
+void FixedSpatialMaterial::set_metalness(float p_metalness){
+
+	metalness=p_metalness;
+	VS::get_singleton()->material_set_param(_get_material(),shader_names->metalness,p_metalness);
+}
+
+
+float FixedSpatialMaterial::get_metalness() const{
+
+	return metalness;
+}
+
 void FixedSpatialMaterial::set_emission(const Color& p_emission){
 void FixedSpatialMaterial::set_emission(const Color& p_emission){
 
 
 	emission=p_emission;
 	emission=p_emission;
@@ -711,6 +750,13 @@ void FixedSpatialMaterial::_validate_property(PropertyInfo& property) const {
 	_validate_feature("refraction",FEATURE_REFRACTION,property);
 	_validate_feature("refraction",FEATURE_REFRACTION,property);
 	_validate_feature("detail",FEATURE_DETAIL,property);
 	_validate_feature("detail",FEATURE_DETAIL,property);
 
 
+	if (property.name=="specular/color" && specular_mode==SPECULAR_MODE_METALLIC) {
+		property.usage=0;
+	}
+	if (property.name=="specular/metalness" && specular_mode==SPECULAR_MODE_SPECULAR) {
+		property.usage=0;
+	}
+
 }
 }
 
 
 void FixedSpatialMaterial::set_line_width(float p_line_width) {
 void FixedSpatialMaterial::set_line_width(float p_line_width) {
@@ -788,9 +834,15 @@ void FixedSpatialMaterial::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("set_albedo","albedo"),&FixedSpatialMaterial::set_albedo);
 	ObjectTypeDB::bind_method(_MD("set_albedo","albedo"),&FixedSpatialMaterial::set_albedo);
 	ObjectTypeDB::bind_method(_MD("get_albedo"),&FixedSpatialMaterial::get_albedo);
 	ObjectTypeDB::bind_method(_MD("get_albedo"),&FixedSpatialMaterial::get_albedo);
 
 
+	ObjectTypeDB::bind_method(_MD("set_specular_mode","specular_mode"),&FixedSpatialMaterial::set_specular_mode);
+	ObjectTypeDB::bind_method(_MD("get_specular_mode"),&FixedSpatialMaterial::get_specular_mode);
+
 	ObjectTypeDB::bind_method(_MD("set_specular","specular"),&FixedSpatialMaterial::set_specular);
 	ObjectTypeDB::bind_method(_MD("set_specular","specular"),&FixedSpatialMaterial::set_specular);
 	ObjectTypeDB::bind_method(_MD("get_specular"),&FixedSpatialMaterial::get_specular);
 	ObjectTypeDB::bind_method(_MD("get_specular"),&FixedSpatialMaterial::get_specular);
 
 
+	ObjectTypeDB::bind_method(_MD("set_metalness","metalness"),&FixedSpatialMaterial::set_metalness);
+	ObjectTypeDB::bind_method(_MD("get_metalness"),&FixedSpatialMaterial::get_metalness);
+
 	ObjectTypeDB::bind_method(_MD("set_roughness","roughness"),&FixedSpatialMaterial::set_roughness);
 	ObjectTypeDB::bind_method(_MD("set_roughness","roughness"),&FixedSpatialMaterial::set_roughness);
 	ObjectTypeDB::bind_method(_MD("get_roughness"),&FixedSpatialMaterial::get_roughness);
 	ObjectTypeDB::bind_method(_MD("get_roughness"),&FixedSpatialMaterial::get_roughness);
 
 
@@ -892,7 +944,9 @@ void FixedSpatialMaterial::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::COLOR,"albedo/color"),_SCS("set_albedo"),_SCS("get_albedo"));
 	ADD_PROPERTY(PropertyInfo(Variant::COLOR,"albedo/color"),_SCS("set_albedo"),_SCS("get_albedo"));
 	ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"albedo/texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"),TEXTURE_ALBEDO);
 	ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"albedo/texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"),TEXTURE_ALBEDO);
 
 
+	ADD_PROPERTY(PropertyInfo(Variant::INT,"specular/mode",PROPERTY_HINT_ENUM,"Metallic,Specular"),_SCS("set_specular_mode"),_SCS("get_specular_mode"));
 	ADD_PROPERTY(PropertyInfo(Variant::COLOR,"specular/color",PROPERTY_HINT_COLOR_NO_ALPHA),_SCS("set_specular"),_SCS("get_specular"));
 	ADD_PROPERTY(PropertyInfo(Variant::COLOR,"specular/color",PROPERTY_HINT_COLOR_NO_ALPHA),_SCS("set_specular"),_SCS("get_specular"));
+	ADD_PROPERTY(PropertyInfo(Variant::REAL,"specular/metalness",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_metalness"),_SCS("get_metalness"));
 	ADD_PROPERTY(PropertyInfo(Variant::REAL,"specular/roughness",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_roughness"),_SCS("get_roughness"));
 	ADD_PROPERTY(PropertyInfo(Variant::REAL,"specular/roughness",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_roughness"),_SCS("get_roughness"));
 	ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"specular/texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"),TEXTURE_SPECULAR);
 	ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"specular/texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"),TEXTURE_SPECULAR);
 
 
@@ -1008,15 +1062,21 @@ void FixedSpatialMaterial::_bind_methods() {
 	BIND_CONSTANT( DIFFUSE_LAMBERT_WRAP );
 	BIND_CONSTANT( DIFFUSE_LAMBERT_WRAP );
 	BIND_CONSTANT( DIFFUSE_OREN_NAYAR );
 	BIND_CONSTANT( DIFFUSE_OREN_NAYAR );
 	BIND_CONSTANT( DIFFUSE_BURLEY );
 	BIND_CONSTANT( DIFFUSE_BURLEY );
+
+	BIND_CONSTANT( SPECULAR_MODE_METALLIC );
+	BIND_CONSTANT( SPECULAR_MODE_SPECULAR );
+
 }
 }
 
 
 
 
 FixedSpatialMaterial::FixedSpatialMaterial() : element(this) {
 FixedSpatialMaterial::FixedSpatialMaterial() : element(this) {
 
 
 	//initialize to right values
 	//initialize to right values
+	specular_mode=SPECULAR_MODE_METALLIC;
 	set_albedo(Color(0.7,0.7,0.7,1.0));
 	set_albedo(Color(0.7,0.7,0.7,1.0));
 	set_specular(Color(0.1,0.1,0.1));
 	set_specular(Color(0.1,0.1,0.1));
 	set_roughness(0.0);
 	set_roughness(0.0);
+	set_metalness(0.1);
 	set_emission(Color(0,0,0));
 	set_emission(Color(0,0,0));
 	set_emission_energy(1.0);
 	set_emission_energy(1.0);
 	set_normal_scale(1);
 	set_normal_scale(1);

+ 18 - 1
scene/resources/material.h

@@ -144,11 +144,16 @@ public:
 		DIFFUSE_BURLEY,
 		DIFFUSE_BURLEY,
 	};
 	};
 
 
+	enum SpecularMode {
+		SPECULAR_MODE_METALLIC,
+		SPECULAR_MODE_SPECULAR,
+	};
+
 private:
 private:
 	union MaterialKey {
 	union MaterialKey {
 
 
 		struct {
 		struct {
-			uint32_t feature_mask : 15;
+			uint32_t feature_mask : 14;
 			uint32_t detail_uv : 1;
 			uint32_t detail_uv : 1;
 			uint32_t blend_mode : 2;
 			uint32_t blend_mode : 2;
 			uint32_t depth_draw_mode : 2;
 			uint32_t depth_draw_mode : 2;
@@ -157,6 +162,7 @@ private:
 			uint32_t detail_blend_mode : 2;
 			uint32_t detail_blend_mode : 2;
 			uint32_t diffuse_mode : 2;
 			uint32_t diffuse_mode : 2;
 			uint32_t invalid_key : 1;
 			uint32_t invalid_key : 1;
+			uint32_t specular_mode : 1;
 		};
 		};
 
 
 		uint32_t key;
 		uint32_t key;
@@ -196,6 +202,7 @@ private:
 		}
 		}
 		mk.detail_blend_mode=detail_blend_mode;
 		mk.detail_blend_mode=detail_blend_mode;
 		mk.diffuse_mode=diffuse_mode;
 		mk.diffuse_mode=diffuse_mode;
+		mk.specular_mode=specular_mode;
 
 
 		return mk;
 		return mk;
 	}
 	}
@@ -203,6 +210,7 @@ private:
 	struct ShaderNames {
 	struct ShaderNames {
 		StringName albedo;
 		StringName albedo;
 		StringName specular;
 		StringName specular;
+		StringName metalness;
 		StringName roughness;
 		StringName roughness;
 		StringName emission;
 		StringName emission;
 		StringName emission_energy;
 		StringName emission_energy;
@@ -237,6 +245,7 @@ private:
 
 
 	Color albedo;
 	Color albedo;
 	Color specular;
 	Color specular;
+	float metalness;
 	float roughness;
 	float roughness;
 	Color emission;
 	Color emission;
 	float emission_energy;
 	float emission_energy;
@@ -267,6 +276,7 @@ private:
 	CullMode cull_mode;
 	CullMode cull_mode;
 	bool flags[FLAG_MAX];
 	bool flags[FLAG_MAX];
 	DiffuseMode diffuse_mode;
 	DiffuseMode diffuse_mode;
+	SpecularMode specular_mode;
 
 
 	bool features[FEATURE_MAX];
 	bool features[FEATURE_MAX];
 
 
@@ -285,9 +295,15 @@ public:
 	void set_albedo(const Color& p_albedo);
 	void set_albedo(const Color& p_albedo);
 	Color get_albedo() const;
 	Color get_albedo() const;
 
 
+	void set_specular_mode(SpecularMode p_mode);
+	SpecularMode get_specular_mode() const;
+
 	void set_specular(const Color& p_specular);
 	void set_specular(const Color& p_specular);
 	Color get_specular() const;
 	Color get_specular() const;
 
 
+	void set_metalness(float p_metalness);
+	float get_metalness() const;
+
 	void set_roughness(float p_roughness);
 	void set_roughness(float p_roughness);
 	float get_roughness() const;
 	float get_roughness() const;
 
 
@@ -388,6 +404,7 @@ VARIANT_ENUM_CAST( FixedSpatialMaterial::DepthDrawMode )
 VARIANT_ENUM_CAST( FixedSpatialMaterial::CullMode )
 VARIANT_ENUM_CAST( FixedSpatialMaterial::CullMode )
 VARIANT_ENUM_CAST( FixedSpatialMaterial::Flags )
 VARIANT_ENUM_CAST( FixedSpatialMaterial::Flags )
 VARIANT_ENUM_CAST( FixedSpatialMaterial::DiffuseMode )
 VARIANT_ENUM_CAST( FixedSpatialMaterial::DiffuseMode )
+VARIANT_ENUM_CAST( FixedSpatialMaterial::SpecularMode )
 
 
 //////////////////////
 //////////////////////