summaryrefslogtreecommitdiff
path: root/servers/visual/shader_language.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'servers/visual/shader_language.cpp')
-rw-r--r--servers/visual/shader_language.cpp175
1 files changed, 154 insertions, 21 deletions
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp
index ffb130048f..67a810bf1c 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -29,8 +29,8 @@
/*************************************************************************/
#include "shader_language.h"
-#include "os/os.h"
-#include "print_string.h"
+#include "core/os/os.h"
+#include "core/print_string.h"
static bool _is_text_char(CharType c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_';
@@ -1622,33 +1622,51 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "min", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID } },
{ "min", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
+ { "min", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID } },
{ "min", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
+ { "min", TYPE_VEC3, { TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
{ "min", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID } },
+ { "min", TYPE_VEC4, { TYPE_VEC4, TYPE_FLOAT, TYPE_VOID } },
{ "min", TYPE_INT, { TYPE_INT, TYPE_INT, TYPE_VOID } },
{ "min", TYPE_IVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID } },
+ { "min", TYPE_IVEC2, { TYPE_IVEC2, TYPE_INT, TYPE_VOID } },
{ "min", TYPE_IVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID } },
+ { "min", TYPE_IVEC3, { TYPE_IVEC3, TYPE_INT, TYPE_VOID } },
{ "min", TYPE_IVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID } },
+ { "min", TYPE_IVEC4, { TYPE_IVEC4, TYPE_INT, TYPE_VOID } },
{ "min", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_VOID } },
{ "min", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID } },
+ { "min", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID } },
{ "min", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID } },
+ { "min", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID } },
{ "min", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID } },
+ { "min", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_VOID } },
{ "max", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID } },
{ "max", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
+ { "max", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID } },
{ "max", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
+ { "max", TYPE_VEC3, { TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
{ "max", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID } },
+ { "max", TYPE_VEC4, { TYPE_VEC4, TYPE_FLOAT, TYPE_VOID } },
{ "max", TYPE_INT, { TYPE_INT, TYPE_INT, TYPE_VOID } },
{ "max", TYPE_IVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID } },
+ { "max", TYPE_IVEC2, { TYPE_IVEC2, TYPE_INT, TYPE_VOID } },
{ "max", TYPE_IVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID } },
+ { "max", TYPE_IVEC3, { TYPE_IVEC3, TYPE_INT, TYPE_VOID } },
{ "max", TYPE_IVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID } },
+ { "max", TYPE_IVEC4, { TYPE_IVEC4, TYPE_INT, TYPE_VOID } },
{ "max", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_VOID } },
{ "max", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID } },
+ { "max", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID } },
{ "max", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID } },
+ { "max", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID } },
{ "max", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID } },
+ { "max", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_VOID } },
{ "clamp", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID } },
{ "clamp", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
@@ -2005,10 +2023,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, OperatorNode *p
StringName name = static_cast<VariableNode *>(p_func->arguments[0])->name.operator String();
- bool all_const = true;
for (int i = 1; i < p_func->arguments.size(); i++) {
- if (p_func->arguments[i]->type != Node::TYPE_CONSTANT)
- all_const = false;
args.push_back(p_func->arguments[i]->get_datatype());
}
@@ -2273,6 +2288,105 @@ bool ShaderLanguage::is_sampler_type(DataType p_type) {
p_type == TYPE_SAMPLERCUBE;
}
+Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::ConstantNode::Value> &p_value, DataType p_type) {
+ if (p_value.size() > 0) {
+ Variant value;
+ switch (p_type) {
+ case ShaderLanguage::TYPE_BOOL:
+ value = Variant(p_value[0].boolean);
+ break;
+ case ShaderLanguage::TYPE_BVEC2:
+ case ShaderLanguage::TYPE_BVEC3:
+ case ShaderLanguage::TYPE_BVEC4:
+ case ShaderLanguage::TYPE_INT:
+ value = Variant(p_value[0].sint);
+ break;
+ case ShaderLanguage::TYPE_IVEC2:
+ value = Variant(Vector2(p_value[0].sint, p_value[1].sint));
+ break;
+ case ShaderLanguage::TYPE_IVEC3:
+ value = Variant(Vector3(p_value[0].sint, p_value[1].sint, p_value[2].sint));
+ break;
+ case ShaderLanguage::TYPE_IVEC4:
+ value = Variant(Plane(p_value[0].sint, p_value[1].sint, p_value[2].sint, p_value[3].sint));
+ break;
+ case ShaderLanguage::TYPE_UINT:
+ value = Variant(p_value[0].uint);
+ break;
+ case ShaderLanguage::TYPE_UVEC2:
+ value = Variant(Vector2(p_value[0].uint, p_value[1].uint));
+ break;
+ case ShaderLanguage::TYPE_UVEC3:
+ value = Variant(Vector3(p_value[0].uint, p_value[1].uint, p_value[2].uint));
+ break;
+ case ShaderLanguage::TYPE_UVEC4:
+ value = Variant(Plane(p_value[0].uint, p_value[1].uint, p_value[2].uint, p_value[3].uint));
+ break;
+ case ShaderLanguage::TYPE_FLOAT:
+ value = Variant(p_value[0].real);
+ break;
+ case ShaderLanguage::TYPE_VEC2:
+ value = Variant(Vector2(p_value[0].real, p_value[1].real));
+ break;
+ case ShaderLanguage::TYPE_VEC3:
+ value = Variant(Vector3(p_value[0].real, p_value[1].real, p_value[2].real));
+ break;
+ case ShaderLanguage::TYPE_VEC4:
+ value = Variant(Plane(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real));
+ break;
+ case ShaderLanguage::TYPE_MAT2:
+ value = Variant(Transform2D(p_value[0].real, p_value[2].real, p_value[1].real, p_value[3].real, 0.0, 0.0));
+ break;
+ case ShaderLanguage::TYPE_MAT3: {
+ Basis p;
+ p[0][0] = p_value[0].real;
+ p[0][1] = p_value[1].real;
+ p[0][2] = p_value[2].real;
+ p[1][0] = p_value[3].real;
+ p[1][1] = p_value[4].real;
+ p[1][2] = p_value[5].real;
+ p[2][0] = p_value[6].real;
+ p[2][1] = p_value[7].real;
+ p[2][2] = p_value[8].real;
+ value = Variant(p);
+ break;
+ }
+ case ShaderLanguage::TYPE_MAT4: {
+ Basis p;
+ p[0][0] = p_value[0].real;
+ p[0][1] = p_value[1].real;
+ p[0][2] = p_value[2].real;
+ p[1][0] = p_value[4].real;
+ p[1][1] = p_value[5].real;
+ p[1][2] = p_value[6].real;
+ p[2][0] = p_value[8].real;
+ p[2][1] = p_value[9].real;
+ p[2][2] = p_value[10].real;
+ Transform t = Transform(p, Vector3(p_value[3].real, p_value[7].real, p_value[11].real));
+ value = Variant(t);
+ break;
+ }
+ case ShaderLanguage::TYPE_ISAMPLER2DARRAY:
+ case ShaderLanguage::TYPE_ISAMPLER2D:
+ case ShaderLanguage::TYPE_ISAMPLER3D:
+ case ShaderLanguage::TYPE_SAMPLER2DARRAY:
+ case ShaderLanguage::TYPE_SAMPLER2D:
+ case ShaderLanguage::TYPE_SAMPLER3D:
+ case ShaderLanguage::TYPE_USAMPLER2DARRAY:
+ case ShaderLanguage::TYPE_USAMPLER2D:
+ case ShaderLanguage::TYPE_USAMPLER3D:
+ case ShaderLanguage::TYPE_SAMPLERCUBE: {
+ // Texture types, likely not relevant here.
+ break;
+ }
+ case ShaderLanguage::TYPE_VOID:
+ break;
+ }
+ return value;
+ }
+ return Variant();
+}
+
void ShaderLanguage::get_keyword_list(List<String> *r_keywords) {
Set<String> kws;
@@ -2368,9 +2482,9 @@ int ShaderLanguage::get_cardinality(DataType p_type) {
2,
3,
4,
- 2,
- 3,
4,
+ 9,
+ 16,
1,
1,
1,
@@ -2906,6 +3020,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
case TYPE_IVEC2: member_type = TYPE_INT; break;
case TYPE_UVEC2: member_type = TYPE_UINT; break;
case TYPE_MAT2: member_type = TYPE_VEC2; break;
+ default: break;
}
break;
@@ -2931,6 +3046,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
case TYPE_IVEC3: member_type = TYPE_INT; break;
case TYPE_UVEC3: member_type = TYPE_UINT; break;
case TYPE_MAT3: member_type = TYPE_VEC3; break;
+ default: break;
}
break;
case TYPE_BVEC4:
@@ -2955,6 +3071,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
case TYPE_IVEC4: member_type = TYPE_INT; break;
case TYPE_UVEC4: member_type = TYPE_UINT; break;
case TYPE_MAT4: member_type = TYPE_VEC4; break;
+ default: break;
}
break;
default: {
@@ -3307,7 +3424,9 @@ ShaderLanguage::Node *ShaderLanguage::_reduce_expression(BlockNode *p_block, Sha
ERR_FAIL_COND_V(op->arguments[0]->type != Node::TYPE_VARIABLE, p_node);
- DataType base = get_scalar_type(op->get_datatype());
+ DataType type = op->get_datatype();
+ DataType base = get_scalar_type(type);
+ int cardinality = get_cardinality(type);
Vector<ConstantNode::Value> values;
@@ -3318,19 +3437,9 @@ ShaderLanguage::Node *ShaderLanguage::_reduce_expression(BlockNode *p_block, Sha
ConstantNode *cn = static_cast<ConstantNode *>(op->arguments[i]);
if (get_scalar_type(cn->datatype) == base) {
-
- int cardinality = get_cardinality(op->arguments[i]->get_datatype());
- if (cn->values.size() == cardinality) {
-
- for (int j = 0; j < cn->values.size(); j++) {
- values.push_back(cn->values[j]);
- }
- } else if (cn->values.size() == 1) {
-
- for (int j = 0; j < cardinality; j++) {
- values.push_back(cn->values[0]);
- }
- } // else: should be filtered by the parser as it's an invalid constructor
+ for (int j = 0; j < cn->values.size(); j++) {
+ values.push_back(cn->values[j]);
+ }
} else if (get_scalar_type(cn->datatype) == cn->datatype) {
ConstantNode::Value v;
@@ -3347,6 +3456,30 @@ ShaderLanguage::Node *ShaderLanguage::_reduce_expression(BlockNode *p_block, Sha
}
}
+ if (values.size() == 1) {
+ if (type >= TYPE_MAT2 && type <= TYPE_MAT4) {
+ ConstantNode::Value value = values[0];
+ ConstantNode::Value zero;
+ zero.real = 0.0f;
+ int size = 2 + (type - TYPE_MAT2);
+
+ values.clear();
+ for (int i = 0; i < size; i++) {
+ for (int j = 0; j < size; j++) {
+ values.push_back(i == j ? value : zero);
+ }
+ }
+ } else {
+ ConstantNode::Value value = values[0];
+ for (int i = 1; i < cardinality; i++) {
+ values.push_back(value);
+ }
+ }
+ } else if (values.size() != cardinality) {
+ ERR_PRINT("Failed to reduce expression, values and cardinality mismatch.");
+ return p_node;
+ }
+
ConstantNode *cn = alloc_node<ConstantNode>();
cn->datatype = op->get_datatype();
cn->values = values;