mirror of
https://github.com/godotengine/godot.git
synced 2025-10-27 11:44:21 +00:00
Backport dd0874e "Allow passing varying from fragment to light shader function" to 3.4
This commit is contained in:
parent
0c028ad96e
commit
fba6b62054
6 changed files with 262 additions and 33 deletions
|
|
@ -2761,6 +2761,72 @@ bool ShaderLanguage::_is_operator_assign(Operator p_op) const {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool ShaderLanguage::_validate_varying_assign(ShaderNode::Varying &p_varying, String *r_message) {
|
||||
if (current_function == String("light")) {
|
||||
*r_message = RTR("Varying may not be assigned in the 'light' function.");
|
||||
return false;
|
||||
}
|
||||
switch (p_varying.stage) {
|
||||
case ShaderNode::Varying::STAGE_UNKNOWN: // first assign
|
||||
if (current_function == String("vertex")) {
|
||||
p_varying.stage = ShaderNode::Varying::STAGE_VERTEX;
|
||||
} else if (current_function == String("fragment")) {
|
||||
p_varying.stage = ShaderNode::Varying::STAGE_FRAGMENT;
|
||||
}
|
||||
break;
|
||||
case ShaderNode::Varying::STAGE_VERTEX:
|
||||
if (current_function == String("fragment")) {
|
||||
*r_message = RTR("Varyings which assigned in 'vertex' function may not be reassigned in 'fragment' or 'light'.");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case ShaderNode::Varying::STAGE_FRAGMENT:
|
||||
if (current_function == String("vertex")) {
|
||||
*r_message = RTR("Varyings which assigned in 'fragment' function may not be reassigned in 'vertex' or 'light'.");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ShaderLanguage::_validate_varying_using(ShaderNode::Varying &p_varying, String *r_message) {
|
||||
switch (p_varying.stage) {
|
||||
case ShaderNode::Varying::STAGE_UNKNOWN:
|
||||
*r_message = RTR("Varying must be assigned before using!");
|
||||
return false;
|
||||
case ShaderNode::Varying::STAGE_VERTEX:
|
||||
if (current_function == String("fragment")) {
|
||||
p_varying.stage = ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT;
|
||||
} else if (current_function == String("light")) {
|
||||
p_varying.stage = ShaderNode::Varying::STAGE_VERTEX_TO_LIGHT;
|
||||
}
|
||||
break;
|
||||
case ShaderNode::Varying::STAGE_FRAGMENT:
|
||||
if (current_function == String("light")) {
|
||||
p_varying.stage = ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT;
|
||||
}
|
||||
break;
|
||||
case ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT:
|
||||
if (current_function == String("light")) {
|
||||
*r_message = RTR("Varying must only be used in two different stages, which can be 'vertex' 'fragment' and 'light'");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case ShaderNode::Varying::STAGE_VERTEX_TO_LIGHT:
|
||||
if (current_function == String("fragment")) {
|
||||
*r_message = RTR("Varying must only be used in two different stages, which can be 'vertex' 'fragment' and 'light'");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ShaderLanguage::_validate_assign(Node *p_node, const Map<StringName, BuiltInInfo> &p_builtin_types, String *r_message) {
|
||||
if (p_node->type == Node::TYPE_OPERATOR) {
|
||||
OperatorNode *op = static_cast<OperatorNode *>(p_node);
|
||||
|
|
@ -2793,13 +2859,6 @@ bool ShaderLanguage::_validate_assign(Node *p_node, const Map<StringName, BuiltI
|
|||
return false;
|
||||
}
|
||||
|
||||
if (shader->varyings.has(var->name) && current_function != String("vertex")) {
|
||||
if (r_message) {
|
||||
*r_message = RTR("Varyings can only be assigned in vertex function.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (shader->constants.has(var->name) || var->is_const) {
|
||||
if (r_message) {
|
||||
*r_message = RTR("Constants cannot be modified.");
|
||||
|
|
@ -2820,13 +2879,6 @@ bool ShaderLanguage::_validate_assign(Node *p_node, const Map<StringName, BuiltI
|
|||
return false;
|
||||
}
|
||||
|
||||
if (shader->varyings.has(arr->name) && current_function != String("vertex")) {
|
||||
if (r_message) {
|
||||
*r_message = RTR("Varyings can only be assigned in vertex function.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -3419,6 +3471,23 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
|
|||
return nullptr;
|
||||
}
|
||||
last_const = is_const;
|
||||
if (ident_type == IDENTIFIER_VARYING) {
|
||||
TkPos prev_pos = _get_tkpos();
|
||||
Token next_token = _get_token();
|
||||
_set_tkpos(prev_pos);
|
||||
String error;
|
||||
if (next_token.type == TK_OP_ASSIGN) {
|
||||
if (!_validate_varying_assign(shader->varyings[identifier], &error)) {
|
||||
_set_error(error);
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
if (!_validate_varying_using(shader->varyings[identifier], &error)) {
|
||||
_set_error(error);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ident_type == IDENTIFIER_FUNCTION) {
|
||||
_set_error("Can't use function as identifier: " + String(identifier));
|
||||
|
|
@ -5695,6 +5764,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
|
|||
return ERR_PARSE_ERROR;
|
||||
}
|
||||
|
||||
TkPos name_pos = _get_tkpos();
|
||||
name = tk.text;
|
||||
|
||||
if (_find_identifier(nullptr, Map<StringName, BuiltInInfo>(), name)) {
|
||||
|
|
@ -5867,11 +5937,12 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
|
|||
_set_error("Expected ';'");
|
||||
return ERR_PARSE_ERROR;
|
||||
}
|
||||
} else {
|
||||
} else { // varying
|
||||
ShaderNode::Varying varying;
|
||||
varying.type = type;
|
||||
varying.precision = precision;
|
||||
varying.interpolation = interpolation;
|
||||
varying.tkpos = name_pos;
|
||||
|
||||
tk = _get_token();
|
||||
if (tk.type != TK_SEMICOLON && tk.type != TK_BRACKET_OPEN) {
|
||||
|
|
@ -6238,6 +6309,14 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
|
|||
tk = _get_token();
|
||||
}
|
||||
|
||||
for (Map<StringName, ShaderNode::Varying>::Element *E = shader->varyings.front(); E; E = E->next()) {
|
||||
if (E->get().stage == ShaderNode::Varying::STAGE_VERTEX || E->get().stage == ShaderNode::Varying::STAGE_FRAGMENT) {
|
||||
_set_tkpos(E->get().tkpos);
|
||||
_set_error(RTR("Varying must only be used in two different stages, which can be 'vertex' 'fragment' and 'light'"));
|
||||
return ERR_PARSE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue