1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-13 13:31:48 +00:00

Backport dd0874e "Allow passing varying from fragment to light shader function" to 3.4

This commit is contained in:
Lyuma
2021-04-21 17:55:27 -07:00
parent 0c028ad96e
commit fba6b62054
6 changed files with 262 additions and 33 deletions

View File

@@ -331,7 +331,7 @@ static String get_constant_text(SL::DataType p_type, const Vector<SL::ConstantNo
}
}
void ShaderCompilerGLES3::_dump_function_deps(SL::ShaderNode *p_node, const StringName &p_for_func, const Map<StringName, String> &p_func_code, String &r_to_add, Set<StringName> &added) {
void ShaderCompilerGLES3::_dump_function_deps(const SL::ShaderNode *p_node, const StringName &p_for_func, const Map<StringName, String> &p_func_code, String &r_to_add, Set<StringName> &added) {
int fidx = -1;
for (int i = 0; i < p_node->functions.size(); i++) {
@@ -388,7 +388,7 @@ void ShaderCompilerGLES3::_dump_function_deps(SL::ShaderNode *p_node, const Stri
}
}
String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions &p_actions, const DefaultIdentifierActions &p_default_actions, bool p_assigning, bool p_use_scope) {
String ShaderCompilerGLES3::_dump_node_code(const SL::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions &p_actions, const DefaultIdentifierActions &p_default_actions, bool p_assigning, bool p_use_scope) {
String code;
switch (p_node->type) {
@@ -521,7 +521,14 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
r_gen_code.uniform_total_size += r_gen_code.uniform_total_size % 16;
}
List<Pair<StringName, SL::ShaderNode::Varying>> var_frag_to_light;
for (Map<StringName, SL::ShaderNode::Varying>::Element *E = pnode->varyings.front(); E; E = E->next()) {
if (E->get().stage == SL::ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT || E->get().stage == SL::ShaderNode::Varying::STAGE_FRAGMENT) {
var_frag_to_light.push_back(Pair<StringName, SL::ShaderNode::Varying>(E->key(), E->get()));
fragment_varyings.insert(E->key());
continue;
}
String vcode;
String interp_mode = _interpstr(E->get().interpolation);
vcode += _prestr(E->get().precision);
@@ -537,6 +544,21 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
r_gen_code.fragment_global += interp_mode + "in " + vcode;
}
if (var_frag_to_light.size() > 0) {
String gcode = "\n\nstruct {\n";
for (List<Pair<StringName, SL::ShaderNode::Varying>>::Element *E = var_frag_to_light.front(); E; E = E->next()) {
gcode += "\t" + _prestr(E->get().second.precision) + _typestr(E->get().second.type) + " " + _mkid(E->get().first);
if (E->get().second.array_size > 0) {
gcode += "[";
gcode += itos(E->get().second.array_size);
gcode += "]";
}
gcode += ";\n";
}
gcode += "} frag_to_light;\n";
r_gen_code.fragment_global += gcode;
}
for (int i = 0; i < pnode->vconstants.size(); i++) {
String gcode;
gcode += "const ";
@@ -559,8 +581,10 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
//code for functions
for (int i = 0; i < pnode->functions.size(); i++) {
SL::FunctionNode *fnode = pnode->functions[i].function;
function = fnode;
current_func_name = fnode->name;
function_code[fnode->name] = _dump_node_code(fnode->body, p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning);
function = nullptr;
}
//place functions in actual code
@@ -571,6 +595,8 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
for (int i = 0; i < pnode->functions.size(); i++) {
SL::FunctionNode *fnode = pnode->functions[i].function;
function = fnode;
current_func_name = fnode->name;
if (fnode->name == vertex_name) {
@@ -587,6 +613,8 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
_dump_function_deps(pnode, fnode->name, function_code, r_gen_code.fragment_global, added_fragment);
r_gen_code.light = function_code[light_name];
}
function = nullptr;
}
//code+=dump_node_code(pnode->body,p_level);
@@ -647,6 +675,19 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
} break;
case SL::Node::TYPE_VARIABLE: {
SL::VariableNode *vnode = (SL::VariableNode *)p_node;
bool use_fragment_varying = false;
if (current_func_name != vertex_name) {
if (p_assigning) {
if (shader->varyings.has(vnode->name)) {
use_fragment_varying = true;
}
} else {
if (fragment_varyings.has(vnode->name)) {
use_fragment_varying = true;
}
}
}
if (p_assigning && p_actions.write_flag_pointers.has(vnode->name)) {
*p_actions.write_flag_pointers[vnode->name] = true;
@@ -668,6 +709,8 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
if (p_default_actions.renames.has(vnode->name)) {
code = p_default_actions.renames[vnode->name];
} else if (use_fragment_varying) {
code = "frag_to_light." + _mkid(vnode->name);
} else {
code = _mkid(vnode->name);
}
@@ -751,6 +794,23 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
} break;
case SL::Node::TYPE_ARRAY: {
SL::ArrayNode *anode = (SL::ArrayNode *)p_node;
bool use_fragment_varying = false;
if (current_func_name != vertex_name) {
if (anode->assign_expression != nullptr) {
use_fragment_varying = true;
} else {
if (p_assigning) {
if (shader->varyings.has(anode->name)) {
use_fragment_varying = true;
}
} else {
if (fragment_varyings.has(anode->name)) {
use_fragment_varying = true;
}
}
}
}
if (p_assigning && p_actions.write_flag_pointers.has(anode->name)) {
*p_actions.write_flag_pointers[anode->name] = true;
@@ -772,6 +832,8 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
if (p_default_actions.renames.has(anode->name)) {
code = p_default_actions.renames[anode->name];
} else if (use_fragment_varying) {
code = "frag_to_light." + _mkid(anode->name);
} else {
code = _mkid(anode->name);
}
@@ -783,7 +845,7 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
code += "[";
code += _dump_node_code(anode->index_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
code += "]";
} else if (anode->assign_expression != NULL) {
} else if (anode->assign_expression != nullptr) {
code += "=";
code += _dump_node_code(anode->assign_expression, p_level, r_gen_code, p_actions, p_default_actions, true, false);
}
@@ -949,7 +1011,7 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
case SL::Node::TYPE_MEMBER: {
SL::MemberNode *mnode = (SL::MemberNode *)p_node;
code = _dump_node_code(mnode->owner, p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + "." + mnode->name;
if (mnode->index_expression != NULL) {
if (mnode->index_expression != nullptr) {
code += "[";
code += _dump_node_code(mnode->index_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
code += "]";
@@ -988,8 +1050,11 @@ Error ShaderCompilerGLES3::compile(VS::ShaderMode p_mode, const String &p_code,
used_name_defines.clear();
used_rmode_defines.clear();
used_flag_pointers.clear();
fragment_varyings.clear();
_dump_node_code(parser.get_shader(), 1, r_gen_code, *p_actions, actions[p_mode], false);
shader = parser.get_shader();
function = nullptr;
_dump_node_code(shader, 1, r_gen_code, *p_actions, actions[p_mode], false);
if (r_gen_code.uniform_total_size) { //uniforms used?
int md = sizeof(float) * 4;