Merge pull request #49157 from Chaosus/vs_billboard
Added Billboard Node to Visual Shaders
This commit is contained in:
commit
4e3d5148ff
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="VisualShaderNodeBillboard" inherits="VisualShaderNode" version="4.0">
|
||||
<brief_description>
|
||||
A node that controls how the object faces the camera to be used within the visual shader graph.
|
||||
</brief_description>
|
||||
<description>
|
||||
The output port of this node needs to be connected to [code]Model View Matrix[/code] port of [VisualShaderNodeOutput].
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<methods>
|
||||
</methods>
|
||||
<members>
|
||||
<member name="billboard_type" type="int" setter="set_billboard_type" getter="get_billboard_type" enum="VisualShaderNodeBillboard.BillboardType" default="1">
|
||||
Controls how the object faces the camera. See [enum BillboardType].
|
||||
</member>
|
||||
<member name="keep_scale" type="bool" setter="set_keep_scale_enabled" getter="is_keep_scale_enabled" default="false">
|
||||
If [code]true[/code], the shader will keep the scale set for the mesh. Otherwise, the scale is lost when billboarding.
|
||||
</member>
|
||||
</members>
|
||||
<constants>
|
||||
<constant name="BILLBOARD_TYPE_DISABLED" value="0" enum="BillboardType">
|
||||
Billboarding is disabled and the node does nothing.
|
||||
</constant>
|
||||
<constant name="BILLBOARD_TYPE_ENABLED" value="1" enum="BillboardType">
|
||||
A standard billboarding algorithm is enabled.
|
||||
</constant>
|
||||
<constant name="BILLBOARD_TYPE_FIXED_Y" value="2" enum="BillboardType">
|
||||
A billboarding algorithm to rotate around Y-axis is enabled.
|
||||
</constant>
|
||||
<constant name="BILLBOARD_TYPE_PARTICLES" value="3" enum="BillboardType">
|
||||
A billboarding algorithm designed to use on particles is enabled.
|
||||
</constant>
|
||||
<constant name="BILLBOARD_TYPE_MAX" value="4" enum="BillboardType">
|
||||
Represents the size of the [enum BillboardType] enum.
|
||||
</constant>
|
||||
</constants>
|
||||
</class>
|
|
@ -4260,6 +4260,7 @@ VisualShaderEditor::VisualShaderEditor() {
|
|||
add_options.push_back(AddOption("TransformDecompose", "Transform", "Composition", "VisualShaderNodeTransformDecompose", TTR("Decomposes transform to four vectors.")));
|
||||
|
||||
add_options.push_back(AddOption("Determinant", "Transform", "Functions", "VisualShaderNodeDeterminant", TTR("Calculates the determinant of a transform."), -1, VisualShaderNode::PORT_TYPE_SCALAR));
|
||||
add_options.push_back(AddOption("GetBillboardMatrix", "Transform", "Functions", "VisualShaderNodeBillboard", TTR("Calculates how the object should face the camera to be applied on Model View Matrix output port for 3D objects."), -1, VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
|
||||
add_options.push_back(AddOption("Inverse", "Transform", "Functions", "VisualShaderNodeTransformFunc", TTR("Calculates the inverse of a transform."), VisualShaderNodeTransformFunc::FUNC_INVERSE, VisualShaderNode::PORT_TYPE_TRANSFORM));
|
||||
add_options.push_back(AddOption("Transpose", "Transform", "Functions", "VisualShaderNodeTransformFunc", TTR("Calculates the transpose of a transform."), VisualShaderNodeTransformFunc::FUNC_TRANSPOSE, VisualShaderNode::PORT_TYPE_TRANSFORM));
|
||||
|
||||
|
|
|
@ -597,6 +597,7 @@ void register_scene_types() {
|
|||
ClassDB::register_class<VisualShaderNodeIs>();
|
||||
ClassDB::register_class<VisualShaderNodeCompare>();
|
||||
ClassDB::register_class<VisualShaderNodeMultiplyAdd>();
|
||||
ClassDB::register_class<VisualShaderNodeBillboard>();
|
||||
|
||||
ClassDB::register_class<VisualShaderNodeSDFToScreenUV>();
|
||||
ClassDB::register_class<VisualShaderNodeScreenUVToSDF>();
|
||||
|
|
|
@ -152,6 +152,14 @@ bool VisualShaderNode::is_use_prop_slots() const {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool VisualShaderNode::is_disabled() const {
|
||||
return disabled;
|
||||
}
|
||||
|
||||
void VisualShaderNode::set_disabled(bool p_disabled) {
|
||||
disabled = p_disabled;
|
||||
}
|
||||
|
||||
Vector<VisualShader::DefaultTextureParam> VisualShaderNode::get_default_texture_parameters(VisualShader::Type p_type, int p_id) const {
|
||||
return Vector<VisualShader::DefaultTextureParam>();
|
||||
}
|
||||
|
@ -1260,6 +1268,12 @@ void VisualShader::_get_property_list(List<PropertyInfo> *p_list) const {
|
|||
Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBuilder &global_code_per_node, Map<Type, StringBuilder> &global_code_per_func, StringBuilder &code, Vector<VisualShader::DefaultTextureParam> &def_tex_params, const VMap<ConnectionKey, const List<Connection>::Element *> &input_connections, const VMap<ConnectionKey, const List<Connection>::Element *> &output_connections, int node, Set<int> &processed, bool for_preview, Set<StringName> &r_classes) const {
|
||||
const Ref<VisualShaderNode> vsnode = graph[type].nodes[node].node;
|
||||
|
||||
if (vsnode->is_disabled()) {
|
||||
code += "// " + vsnode->get_caption() + ":" + itos(node) + "\n";
|
||||
code += "\t// Node is disabled and code is not generated.\n";
|
||||
return OK;
|
||||
}
|
||||
|
||||
//check inputs recursively first
|
||||
int input_count = vsnode->get_input_port_count();
|
||||
for (int i = 0; i < input_count; i++) {
|
||||
|
@ -1328,6 +1342,11 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui
|
|||
if (input_connections.has(ck)) {
|
||||
//connected to something, use that output
|
||||
int from_node = input_connections[ck]->get().from_node;
|
||||
|
||||
if (graph[type].nodes[from_node].node->is_disabled()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int from_port = input_connections[ck]->get().from_port;
|
||||
|
||||
VisualShaderNode::PortType in_type = vsnode->get_input_port_type(i);
|
||||
|
@ -2531,6 +2550,8 @@ const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = {
|
|||
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" },
|
||||
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
|
||||
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "roughness", "ROUGHNESS" },
|
||||
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "model_view_matrix", "MODELVIEW_MATRIX" },
|
||||
|
||||
// Spatial, Fragment
|
||||
|
||||
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "albedo", "ALBEDO" },
|
||||
|
@ -2670,9 +2691,13 @@ String VisualShaderNodeOutput::get_output_port_name(int p_port) const {
|
|||
}
|
||||
|
||||
bool VisualShaderNodeOutput::is_port_separator(int p_index) const {
|
||||
if (shader_mode == Shader::MODE_SPATIAL && shader_type == VisualShader::TYPE_VERTEX) {
|
||||
String name = get_input_port_name(p_index);
|
||||
return bool(name == "Model View Matrix");
|
||||
}
|
||||
if (shader_mode == Shader::MODE_SPATIAL && shader_type == VisualShader::TYPE_FRAGMENT) {
|
||||
String name = get_input_port_name(p_index);
|
||||
return (name == "Normal" || name == "Rim" || name == "Alpha Scissor Threshold");
|
||||
return bool(name == "Normal" || name == "Rim" || name == "Alpha Scissor Threshold");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -203,6 +203,8 @@ class VisualShaderNode : public Resource {
|
|||
|
||||
protected:
|
||||
bool simple_decl = true;
|
||||
bool disabled = false;
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
|
@ -257,6 +259,9 @@ public:
|
|||
virtual bool is_show_prop_names() const;
|
||||
virtual bool is_use_prop_slots() const;
|
||||
|
||||
bool is_disabled() const;
|
||||
void set_disabled(bool p_disabled = true);
|
||||
|
||||
virtual Vector<StringName> get_editable_properties() const;
|
||||
|
||||
virtual Vector<VisualShader::DefaultTextureParam> get_default_texture_parameters(VisualShader::Type p_type, int p_id) const;
|
||||
|
|
|
@ -5579,3 +5579,127 @@ VisualShaderNodeMultiplyAdd::VisualShaderNodeMultiplyAdd() {
|
|||
set_input_port_default_value(1, 0.0);
|
||||
set_input_port_default_value(2, 0.0);
|
||||
}
|
||||
|
||||
////////////// Billboard
|
||||
|
||||
String VisualShaderNodeBillboard::get_caption() const {
|
||||
return "GetBillboardMatrix";
|
||||
}
|
||||
|
||||
int VisualShaderNodeBillboard::get_input_port_count() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
VisualShaderNodeBillboard::PortType VisualShaderNodeBillboard::get_input_port_type(int p_port) const {
|
||||
return PORT_TYPE_SCALAR;
|
||||
}
|
||||
|
||||
String VisualShaderNodeBillboard::get_input_port_name(int p_port) const {
|
||||
return "";
|
||||
}
|
||||
|
||||
int VisualShaderNodeBillboard::get_output_port_count() const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
VisualShaderNodeBillboard::PortType VisualShaderNodeBillboard::get_output_port_type(int p_port) const {
|
||||
return PORT_TYPE_TRANSFORM;
|
||||
}
|
||||
|
||||
String VisualShaderNodeBillboard::get_output_port_name(int p_port) const {
|
||||
return "model_view_matrix";
|
||||
}
|
||||
|
||||
String VisualShaderNodeBillboard::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 {
|
||||
String code;
|
||||
|
||||
switch (billboard_type) {
|
||||
case BILLBOARD_TYPE_ENABLED:
|
||||
code += "\t{\n";
|
||||
code += "\t\tmat4 __mvm = INV_CAMERA_MATRIX * mat4(CAMERA_MATRIX[0], CAMERA_MATRIX[1], CAMERA_MATRIX[2], WORLD_MATRIX[3]);\n";
|
||||
if (keep_scale) {
|
||||
code += "\t\t__mvm = __mvm * mat4(vec4(length(WORLD_MATRIX[0].xyz), 0.0, 0.0, 0.0), vec4(0.0, length(WORLD_MATRIX[1].xyz), 0.0, 0.0), vec4(0.0, 0.0, length(WORLD_MATRIX[2].xyz), 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n";
|
||||
}
|
||||
code += "\t\t" + p_output_vars[0] + " = __mvm;\n";
|
||||
code += "\t}\n";
|
||||
break;
|
||||
case BILLBOARD_TYPE_FIXED_Y:
|
||||
code += "\t{\n";
|
||||
code += "\t\tmat4 __mvm = 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 (keep_scale) {
|
||||
code += "\t\t__mvm = __mvm * mat4(vec4(length(WORLD_MATRIX[0].xyz), 0.0, 0.0, 0.0), vec4(0.0, 1.0, 0.0, 0.0), vec4(0.0, 0.0, length(WORLD_MATRIX[2].xyz), 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n";
|
||||
} else {
|
||||
code += "\t\t__mvm = __mvm * mat4(vec4(1.0, 0.0, 0.0, 0.0), vec4(0.0, 1.0 / length(WORLD_MATRIX[1].xyz), 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n";
|
||||
}
|
||||
code += "\t\t" + p_output_vars[0] + " = __mvm;\n";
|
||||
code += "\t}\n";
|
||||
break;
|
||||
case BILLBOARD_TYPE_PARTICLES:
|
||||
code += "\t{\n";
|
||||
code += "\t\tmat4 __wm = mat4(normalize(CAMERA_MATRIX[0]) * length(WORLD_MATRIX[0]), normalize(CAMERA_MATRIX[1]) * length(WORLD_MATRIX[0]), normalize(CAMERA_MATRIX[2]) * length(WORLD_MATRIX[2]), WORLD_MATRIX[3]);\n";
|
||||
code += "\t\t__wm = __wm * mat4(vec4(cos(INSTANCE_CUSTOM.x), -sin(INSTANCE_CUSTOM.x), 0.0, 0.0), vec4(sin(INSTANCE_CUSTOM.x), cos(INSTANCE_CUSTOM.x), 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n";
|
||||
code += "\t\t" + p_output_vars[0] + " = INV_CAMERA_MATRIX * __wm;\n";
|
||||
code += "\t}\n";
|
||||
break;
|
||||
default:
|
||||
code += "\t" + p_output_vars[0] + " = mat4(1.0);\n";
|
||||
break;
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
bool VisualShaderNodeBillboard::is_show_prop_names() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void VisualShaderNodeBillboard::set_billboard_type(BillboardType p_billboard_type) {
|
||||
ERR_FAIL_INDEX((int)p_billboard_type, BILLBOARD_TYPE_MAX);
|
||||
billboard_type = p_billboard_type;
|
||||
simple_decl = bool(billboard_type == BILLBOARD_TYPE_DISABLED);
|
||||
set_disabled(simple_decl);
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
VisualShaderNodeBillboard::BillboardType VisualShaderNodeBillboard::get_billboard_type() const {
|
||||
return billboard_type;
|
||||
}
|
||||
|
||||
void VisualShaderNodeBillboard::set_keep_scale_enabled(bool p_enabled) {
|
||||
keep_scale = p_enabled;
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
bool VisualShaderNodeBillboard::is_keep_scale_enabled() const {
|
||||
return keep_scale;
|
||||
}
|
||||
|
||||
Vector<StringName> VisualShaderNodeBillboard::get_editable_properties() const {
|
||||
Vector<StringName> props;
|
||||
props.push_back("billboard_type");
|
||||
if (billboard_type == BILLBOARD_TYPE_ENABLED || billboard_type == BILLBOARD_TYPE_FIXED_Y) {
|
||||
props.push_back("keep_scale");
|
||||
}
|
||||
return props;
|
||||
}
|
||||
|
||||
void VisualShaderNodeBillboard::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_billboard_type", "billboard_type"), &VisualShaderNodeBillboard::set_billboard_type);
|
||||
ClassDB::bind_method(D_METHOD("get_billboard_type"), &VisualShaderNodeBillboard::get_billboard_type);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_keep_scale_enabled", "enabled"), &VisualShaderNodeBillboard::set_keep_scale_enabled);
|
||||
ClassDB::bind_method(D_METHOD("is_keep_scale_enabled"), &VisualShaderNodeBillboard::is_keep_scale_enabled);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "billboard_type", PROPERTY_HINT_ENUM, "Disabled,Enabled,Y-Billboard,Particles"), "set_billboard_type", "get_billboard_type");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "keep_scale"), "set_keep_scale_enabled", "is_keep_scale_enabled");
|
||||
|
||||
BIND_ENUM_CONSTANT(BILLBOARD_TYPE_DISABLED);
|
||||
BIND_ENUM_CONSTANT(BILLBOARD_TYPE_ENABLED);
|
||||
BIND_ENUM_CONSTANT(BILLBOARD_TYPE_FIXED_Y);
|
||||
BIND_ENUM_CONSTANT(BILLBOARD_TYPE_PARTICLES);
|
||||
BIND_ENUM_CONSTANT(BILLBOARD_TYPE_MAX);
|
||||
}
|
||||
|
||||
VisualShaderNodeBillboard::VisualShaderNodeBillboard() {
|
||||
simple_decl = false;
|
||||
}
|
||||
|
|
|
@ -2217,4 +2217,51 @@ public:
|
|||
|
||||
VARIANT_ENUM_CAST(VisualShaderNodeMultiplyAdd::OpType)
|
||||
|
||||
class VisualShaderNodeBillboard : public VisualShaderNode {
|
||||
GDCLASS(VisualShaderNodeBillboard, VisualShaderNode);
|
||||
|
||||
public:
|
||||
enum BillboardType {
|
||||
BILLBOARD_TYPE_DISABLED,
|
||||
BILLBOARD_TYPE_ENABLED,
|
||||
BILLBOARD_TYPE_FIXED_Y,
|
||||
BILLBOARD_TYPE_PARTICLES,
|
||||
BILLBOARD_TYPE_MAX,
|
||||
};
|
||||
|
||||
protected:
|
||||
BillboardType billboard_type = BILLBOARD_TYPE_ENABLED;
|
||||
bool keep_scale = false;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual String get_caption() const override;
|
||||
|
||||
virtual int get_input_port_count() const override;
|
||||
virtual PortType get_input_port_type(int p_port) const override;
|
||||
virtual String get_input_port_name(int p_port) const override;
|
||||
|
||||
virtual int get_output_port_count() const override;
|
||||
virtual PortType get_output_port_type(int p_port) const override;
|
||||
virtual String get_output_port_name(int p_port) const override;
|
||||
|
||||
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 override;
|
||||
|
||||
virtual bool is_show_prop_names() const override;
|
||||
|
||||
void set_billboard_type(BillboardType p_billboard_type);
|
||||
BillboardType get_billboard_type() const;
|
||||
|
||||
void set_keep_scale_enabled(bool p_enabled);
|
||||
bool is_keep_scale_enabled() const;
|
||||
|
||||
virtual Vector<StringName> get_editable_properties() const override;
|
||||
|
||||
VisualShaderNodeBillboard();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(VisualShaderNodeBillboard::BillboardType)
|
||||
|
||||
#endif // VISUAL_SHADER_NODES_H
|
||||
|
|
Loading…
Reference in New Issue