Просмотр исходного кода

Merge pull request #32674 from Chaosus/vs_fix_cubemaps

Makes cubemaps to be works in visual shaders
Rémi Verschelde 5 лет назад
Родитель
Сommit
220ee9281f

+ 1 - 1
doc/classes/VisualShaderNodeCubeMapUniform.xml

@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualShaderNodeCubeMapUniform" inherits="VisualShaderNode" category="Core" version="3.2">
+<class name="VisualShaderNodeCubeMapUniform" inherits="VisualShaderNodeTextureUniform" category="Core" version="3.2">
 	<brief_description>
 	</brief_description>
 	<description>

+ 19 - 1
scene/resources/visual_shader.cpp

@@ -1067,7 +1067,16 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui
 
 				VisualShaderNodeUniform *uniform = (VisualShaderNodeUniform *)graph[type].nodes[from_node].node.ptr();
 				if (uniform) {
-					inputs[i] = uniform->get_uniform_name();
+					inputs[i] = "";
+					switch (uniform->get_uniform_type()) {
+						case VisualShaderNodeUniform::UTYPE_CUBEMAP:
+							inputs[i] += "cube_";
+							break;
+						case VisualShaderNodeUniform::UTYPE_SAMPLER2D:
+							inputs[i] += "s2d_";
+							break;
+					}
+					inputs[i] += uniform->get_uniform_name();
 				} else {
 					inputs[i] = "";
 				}
@@ -1973,7 +1982,16 @@ void VisualShaderNodeUniform::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::STRING, "uniform_name"), "set_uniform_name", "get_uniform_name");
 }
 
+int VisualShaderNodeUniform::get_uniform_type() const {
+	return (int)uniform_type;
+}
+
+void VisualShaderNodeUniform::set_uniform_type(int p_type) {
+	uniform_type = (UniformType)p_type;
+}
+
 VisualShaderNodeUniform::VisualShaderNodeUniform() {
+	uniform_type = UTYPE_NONE;
 }
 
 ////////////// GroupBase

+ 12 - 0
scene/resources/visual_shader.h

@@ -353,7 +353,16 @@ public:
 class VisualShaderNodeUniform : public VisualShaderNode {
 	GDCLASS(VisualShaderNodeUniform, VisualShaderNode);
 
+public:
+	enum UniformType {
+		UTYPE_NONE,
+		UTYPE_CUBEMAP,
+		UTYPE_SAMPLER2D,
+	};
+
+private:
 	String uniform_name;
+	UniformType uniform_type;
 
 protected:
 	static void _bind_methods();
@@ -362,6 +371,9 @@ public:
 	void set_uniform_name(const String &p_name);
 	String get_uniform_name() const;
 
+	int get_uniform_type() const;
+	void set_uniform_type(int p_type);
+
 	VisualShaderNodeUniform();
 };
 

+ 90 - 18
scene/resources/visual_shader_nodes.cpp

@@ -468,19 +468,55 @@ String VisualShaderNodeTexture::generate_code(Shader::Mode p_mode, VisualShader:
 
 	if (source == SOURCE_PORT) {
 		String id = p_input_vars[2];
+
+		VisualShaderNodeUniform::UniformType utype = VisualShaderNodeUniform::UTYPE_NONE;
+		if (id.begins_with("cube_")) {
+			utype = VisualShaderNodeUniform::UTYPE_CUBEMAP;
+			id = id.substr(5);
+		} else if (id.begins_with("s2d_")) {
+			utype = VisualShaderNodeUniform::UTYPE_SAMPLER2D;
+			id = id.substr(4);
+		}
+
 		String code;
 		if (id == String()) {
 			code += "\tvec4 " + id + "_tex_read = vec4(0.0);\n";
 		} else {
 			if (p_input_vars[0] == String()) { // Use UV by default.
-
-				code += "\tvec4 " + id + "_tex_read = texture( " + id + " , UV.xy );\n";
-
+				switch (utype) {
+					case VisualShaderNodeUniform::UTYPE_CUBEMAP:
+						code += "\tvec4 " + id + "_tex_read = texture( " + id + " , vec3(UV, 0.0) );\n";
+						break;
+					case VisualShaderNodeUniform::UTYPE_SAMPLER2D:
+						code += "\tvec4 " + id + "_tex_read = texture( " + id + " , UV.xy );\n";
+						break;
+					default:
+						break;
+				}
 			} else if (p_input_vars[1] == String()) {
 				//no lod
-				code += "\tvec4 " + id + "_tex_read = texture( " + id + " , " + p_input_vars[0] + ".xy );\n";
+
+				switch (utype) {
+					case VisualShaderNodeUniform::UTYPE_CUBEMAP:
+						code += "\tvec4 " + id + "_tex_read = texture( " + id + " , " + p_input_vars[0] + " );\n";
+						break;
+					case VisualShaderNodeUniform::UTYPE_SAMPLER2D:
+						code += "\tvec4 " + id + "_tex_read = texture( " + id + " , " + p_input_vars[0] + ".xy );\n";
+						break;
+					default:
+						break;
+				}
 			} else {
-				code += "\tvec4 " + id + "_tex_read = textureLod( " + id + " , " + p_input_vars[0] + ".xy , " + p_input_vars[1] + " );\n";
+				switch (utype) {
+					case VisualShaderNodeUniform::UTYPE_CUBEMAP:
+						code += "\tvec4 " + id + "_tex_read = textureLod( " + id + " , " + p_input_vars[0] + " , " + p_input_vars[1] + " );\n";
+						break;
+					case VisualShaderNodeUniform::UTYPE_SAMPLER2D:
+						code += "\tvec4 " + id + "_tex_read = textureLod( " + id + " , " + p_input_vars[0] + ".xy , " + p_input_vars[1] + " );\n";
+						break;
+					default:
+						break;
+				}
 			}
 
 			code += "\t" + p_output_vars[0] + " = " + id + "_tex_read.rgb;\n";
@@ -738,7 +774,7 @@ Vector<VisualShader::DefaultTextureParam> VisualShaderNodeCubeMap::get_default_t
 
 String VisualShaderNodeCubeMap::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
 
-	String u = "uniform sampler2DCube " + make_unique_id(p_type, p_id, "cube");
+	String u = "uniform samplerCube " + make_unique_id(p_type, p_id, "cube");
 	switch (texture_type) {
 		case TYPE_DATA: break;
 		case TYPE_COLOR: u += " : hint_albedo"; break;
@@ -751,9 +787,9 @@ String VisualShaderNodeCubeMap::generate_code(Shader::Mode p_mode, VisualShader:
 
 	String id = make_unique_id(p_type, p_id, "cube");
 	String code;
-	if (p_input_vars[0] == String()) { //none bound, do nothing
+	if (p_input_vars[0] == String()) { // Use UV by default.
 
-		code += "\tvec4 " + id + "_read = vec4(0.0);\n";
+		code += "\tvec4 " + id + "_read = texture( " + id + " , vec3(UV, 0.0) );\n";
 
 	} else if (p_input_vars[1] == String()) {
 		//no lod
@@ -767,6 +803,13 @@ String VisualShaderNodeCubeMap::generate_code(Shader::Mode p_mode, VisualShader:
 	return code;
 }
 
+String VisualShaderNodeCubeMap::get_input_port_default_hint(int p_port) const {
+	if (p_port == 0) {
+		return "vec3(UV, 0.0)";
+	}
+	return "";
+}
+
 void VisualShaderNodeCubeMap::set_cube_map(Ref<CubeMap> p_value) {
 
 	cube_map = p_value;
@@ -3205,6 +3248,7 @@ String VisualShaderNodeTextureUniform::get_input_port_default_hint(int p_port) c
 VisualShaderNodeTextureUniform::VisualShaderNodeTextureUniform() {
 	texture_type = TYPE_DATA;
 	color_default = COLOR_DEFAULT_WHITE;
+	set_uniform_type(VisualShaderNodeUniform::UTYPE_SAMPLER2D);
 }
 
 ////////////// Texture Uniform (Triplanar)
@@ -3314,28 +3358,55 @@ String VisualShaderNodeCubeMapUniform::get_caption() const {
 	return "CubeMapUniform";
 }
 
+int VisualShaderNodeCubeMapUniform::get_output_port_count() const {
+	return 1;
+}
+
+VisualShaderNodeCubeMapUniform::PortType VisualShaderNodeCubeMapUniform::get_output_port_type(int p_port) const {
+	return PORT_TYPE_SAMPLER;
+}
+
+String VisualShaderNodeCubeMapUniform::get_output_port_name(int p_port) const {
+	return "sampler";
+}
+
 int VisualShaderNodeCubeMapUniform::get_input_port_count() const {
-	return 2;
+	return 0;
 }
 
 VisualShaderNodeCubeMapUniform::PortType VisualShaderNodeCubeMapUniform::get_input_port_type(int p_port) const {
-	return p_port == 0 ? PORT_TYPE_VECTOR : PORT_TYPE_SCALAR;
+	return PORT_TYPE_SCALAR;
 }
 
 String VisualShaderNodeCubeMapUniform::get_input_port_name(int p_port) const {
-	return p_port == 0 ? "normal" : "lod";
+	return "";
 }
 
-int VisualShaderNodeCubeMapUniform::get_output_port_count() const {
-	return 2;
+String VisualShaderNodeCubeMapUniform::get_input_port_default_hint(int p_port) const {
+	return "";
 }
 
-VisualShaderNodeCubeMapUniform::PortType VisualShaderNodeCubeMapUniform::get_output_port_type(int p_port) const {
-	return p_port == 0 ? PORT_TYPE_VECTOR : PORT_TYPE_SCALAR;
-}
+String VisualShaderNodeCubeMapUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
+	String code = "uniform samplerCube " + get_uniform_name();
 
-String VisualShaderNodeCubeMapUniform::get_output_port_name(int p_port) const {
-	return p_port == 0 ? "rgb" : "alpha";
+	switch (texture_type) {
+		case TYPE_DATA:
+			if (color_default == COLOR_DEFAULT_BLACK)
+				code += " : hint_black;\n";
+			else
+				code += ";\n";
+			break;
+		case TYPE_COLOR:
+			if (color_default == COLOR_DEFAULT_BLACK)
+				code += " : hint_black_albedo;\n";
+			else
+				code += " : hint_albedo;\n";
+			break;
+		case TYPE_NORMALMAP: code += " : hint_normal;\n"; break;
+		case TYPE_ANISO: code += " : hint_aniso;\n"; break;
+	}
+
+	return code;
 }
 
 String VisualShaderNodeCubeMapUniform::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
@@ -3343,6 +3414,7 @@ String VisualShaderNodeCubeMapUniform::generate_code(Shader::Mode p_mode, Visual
 }
 
 VisualShaderNodeCubeMapUniform::VisualShaderNodeCubeMapUniform() {
+	set_uniform_type(VisualShaderNodeUniform::UTYPE_CUBEMAP);
 }
 
 ////////////// If

+ 6 - 3
scene/resources/visual_shader_nodes.h

@@ -277,6 +277,7 @@ public:
 	virtual int get_input_port_count() const;
 	virtual PortType get_input_port_type(int p_port) const;
 	virtual String get_input_port_name(int p_port) const;
+	virtual String get_input_port_default_hint(int p_port) const;
 
 	virtual int get_output_port_count() const;
 	virtual PortType get_output_port_type(int p_port) const;
@@ -1412,7 +1413,7 @@ public:
 		COLOR_DEFAULT_BLACK
 	};
 
-private:
+protected:
 	TextureType texture_type;
 	ColorDefault color_default;
 
@@ -1471,8 +1472,8 @@ public:
 
 ///////////////////////////////////////
 
-class VisualShaderNodeCubeMapUniform : public VisualShaderNode {
-	GDCLASS(VisualShaderNodeCubeMapUniform, VisualShaderNode);
+class VisualShaderNodeCubeMapUniform : public VisualShaderNodeTextureUniform {
+	GDCLASS(VisualShaderNodeCubeMapUniform, VisualShaderNodeTextureUniform);
 
 public:
 	virtual String get_caption() const;
@@ -1485,6 +1486,8 @@ public:
 	virtual PortType get_output_port_type(int p_port) const;
 	virtual String get_output_port_name(int p_port) const;
 
+	virtual String get_input_port_default_hint(int p_port) const;
+	virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const;
 	virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty
 
 	VisualShaderNodeCubeMapUniform();