diff options
author | RĂ©mi Verschelde <rverschelde@gmail.com> | 2020-04-17 18:36:06 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-17 18:36:06 +0200 |
commit | 17304f1aaed434b0547606ff22721d65292d8cf1 (patch) | |
tree | 8b52f567244fe41a2776a49099ee8c7f300bfe40 /scene/main/shader_globals_override.cpp | |
parent | cfda0e377004a9399255105132ccb1a906e9f12e (diff) | |
parent | 0e1c66d9fced8f9d3a8fbd87ddfd2c29a9ed2679 (diff) |
Merge pull request #37949 from reduz/implement-global-shader-uniforms
Implement global and per instance shader uniforms.
Diffstat (limited to 'scene/main/shader_globals_override.cpp')
-rw-r--r-- | scene/main/shader_globals_override.cpp | 257 |
1 files changed, 257 insertions, 0 deletions
diff --git a/scene/main/shader_globals_override.cpp b/scene/main/shader_globals_override.cpp new file mode 100644 index 0000000000..13582cf655 --- /dev/null +++ b/scene/main/shader_globals_override.cpp @@ -0,0 +1,257 @@ +#include "shader_globals_override.h" + +#include "core/core_string_names.h" +#include "scene/main/window.h" +#include "scene/scene_string_names.h" + +StringName *ShaderGlobalsOverride::_remap(const StringName &p_name) const { + + StringName *r = param_remaps.getptr(p_name); + if (!r) { + //not cached, do caching + String p = p_name; + if (p.begins_with("params/")) { + String q = p.replace_first("params/", ""); + param_remaps[p] = q; + r = param_remaps.getptr(q); + } + } + + return r; +} +bool ShaderGlobalsOverride::_set(const StringName &p_name, const Variant &p_value) { + + StringName *r = _remap(p_name); + + if (r) { + Override *o = overrides.getptr(*r); + if (!o) { + Override ov; + ov.in_use = false; + overrides[*r] = ov; + o = overrides.getptr(*r); + } + if (o) { + o->override = p_value; + if (active) { + RS::get_singleton()->global_variable_set_override(*r, p_value); + } + o->in_use = p_value.get_type() != Variant::NIL; + return true; + } + } + + return false; +} + +bool ShaderGlobalsOverride::_get(const StringName &p_name, Variant &r_ret) const { + + StringName *r = _remap(p_name); + + if (r) { + const Override *o = overrides.getptr(*r); + if (o) { + r_ret = o->override; + return true; + } + } + + return false; +} + +void ShaderGlobalsOverride::_get_property_list(List<PropertyInfo> *p_list) const { + + Vector<StringName> variables; + variables = RS::get_singleton()->global_variable_get_list(); + for (int i = 0; i < variables.size(); i++) { + PropertyInfo pinfo; + pinfo.name = "params/" + variables[i]; + pinfo.usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE; + + switch (RS::get_singleton()->global_variable_get_type(variables[i])) { + case RS::GLOBAL_VAR_TYPE_BOOL: { + pinfo.type = Variant::BOOL; + } break; + case RS::GLOBAL_VAR_TYPE_BVEC2: { + pinfo.type = Variant::INT; + pinfo.hint = PROPERTY_HINT_FLAGS; + pinfo.hint_string = "x,y"; + } break; + case RS::GLOBAL_VAR_TYPE_BVEC3: { + pinfo.type = Variant::INT; + pinfo.hint = PROPERTY_HINT_FLAGS; + pinfo.hint_string = "x,y,z"; + } break; + case RS::GLOBAL_VAR_TYPE_BVEC4: { + pinfo.type = Variant::INT; + pinfo.hint = PROPERTY_HINT_FLAGS; + pinfo.hint_string = "x,y,z,w"; + } break; + case RS::GLOBAL_VAR_TYPE_INT: { + pinfo.type = Variant::INT; + } break; + case RS::GLOBAL_VAR_TYPE_IVEC2: { + pinfo.type = Variant::VECTOR2I; + } break; + case RS::GLOBAL_VAR_TYPE_IVEC3: { + pinfo.type = Variant::VECTOR3I; + } break; + case RS::GLOBAL_VAR_TYPE_IVEC4: { + pinfo.type = Variant::PACKED_INT32_ARRAY; + } break; + case RS::GLOBAL_VAR_TYPE_RECT2I: { + pinfo.type = Variant::RECT2I; + } break; + case RS::GLOBAL_VAR_TYPE_UINT: { + pinfo.type = Variant::INT; + } break; + case RS::GLOBAL_VAR_TYPE_UVEC2: { + pinfo.type = Variant::VECTOR2I; + } break; + case RS::GLOBAL_VAR_TYPE_UVEC3: { + pinfo.type = Variant::VECTOR3I; + } break; + case RS::GLOBAL_VAR_TYPE_UVEC4: { + pinfo.type = Variant::PACKED_INT32_ARRAY; + } break; + case RS::GLOBAL_VAR_TYPE_FLOAT: { + pinfo.type = Variant::FLOAT; + } break; + case RS::GLOBAL_VAR_TYPE_VEC2: { + pinfo.type = Variant::VECTOR2; + } break; + case RS::GLOBAL_VAR_TYPE_VEC3: { + pinfo.type = Variant::VECTOR3; + } break; + case RS::GLOBAL_VAR_TYPE_VEC4: { + pinfo.type = Variant::PLANE; + } break; + case RS::GLOBAL_VAR_TYPE_RECT2: { + pinfo.type = Variant::RECT2; + } break; + case RS::GLOBAL_VAR_TYPE_COLOR: { + pinfo.type = Variant::COLOR; + } break; + case RS::GLOBAL_VAR_TYPE_MAT2: { + pinfo.type = Variant::PACKED_INT32_ARRAY; + } break; + case RS::GLOBAL_VAR_TYPE_MAT3: { + pinfo.type = Variant::BASIS; + } break; + case RS::GLOBAL_VAR_TYPE_TRANSFORM_2D: { + pinfo.type = Variant::TRANSFORM2D; + } break; + case RS::GLOBAL_VAR_TYPE_TRANSFORM: { + pinfo.type = Variant::TRANSFORM; + } break; + case RS::GLOBAL_VAR_TYPE_MAT4: { + pinfo.type = Variant::PACKED_INT32_ARRAY; + } break; + case RS::GLOBAL_VAR_TYPE_SAMPLER2D: { + pinfo.type = Variant::OBJECT; + pinfo.hint = PROPERTY_HINT_RESOURCE_TYPE; + pinfo.hint_string = "Texture2D"; + } break; + case RS::GLOBAL_VAR_TYPE_SAMPLER2DARRAY: { + pinfo.type = Variant::OBJECT; + pinfo.hint = PROPERTY_HINT_RESOURCE_TYPE; + pinfo.hint_string = "Texture2DArray"; + } break; + case RS::GLOBAL_VAR_TYPE_SAMPLER3D: { + pinfo.type = Variant::OBJECT; + pinfo.hint = PROPERTY_HINT_RESOURCE_TYPE; + pinfo.hint_string = "Texture3D"; + } break; + case RS::GLOBAL_VAR_TYPE_SAMPLERCUBE: { + pinfo.type = Variant::OBJECT; + pinfo.hint = PROPERTY_HINT_RESOURCE_TYPE; + pinfo.hint_string = "Cubemap"; + } break; + default: { + + } break; + } + + if (!overrides.has(variables[i])) { + Override o; + o.in_use = false; + Callable::CallError ce; + o.override = Variant::construct(pinfo.type, NULL, 0, ce); + overrides[variables[i]] = o; + } + + Override *o = overrides.getptr(variables[i]); + if (o->in_use && o->override.get_type() != Variant::NIL) { + pinfo.usage |= PROPERTY_USAGE_CHECKED; + pinfo.usage |= PROPERTY_USAGE_STORAGE; + } + + p_list->push_back(pinfo); + } +} + +void ShaderGlobalsOverride::_activate() { + + List<Node *> nodes; + get_tree()->get_nodes_in_group(SceneStringNames::get_singleton()->shader_overrides_group_active, &nodes); + if (nodes.size() == 0) { + //good we are the only override, enable all + active = true; + add_to_group(SceneStringNames::get_singleton()->shader_overrides_group_active); + + const StringName *K = nullptr; + while ((K = overrides.next(K))) { + Override *o = overrides.getptr(*K); + if (o->in_use && o->override.get_type() != Variant::NIL) { + RS::get_singleton()->global_variable_set_override(*K, o->override); + } + } + + update_configuration_warning(); //may have activated + } +} + +void ShaderGlobalsOverride::_notification(int p_what) { + + if (p_what == Node3D::NOTIFICATION_ENTER_TREE) { + + add_to_group(SceneStringNames::get_singleton()->shader_overrides_group); + _activate(); + + } else if (p_what == Node3D::NOTIFICATION_EXIT_TREE) { + + if (active) { + //remove overrides + const StringName *K = nullptr; + while ((K = overrides.next(K))) { + Override *o = overrides.getptr(*K); + if (o->in_use) { + RS::get_singleton()->global_variable_set_override(*K, Variant()); + } + } + } + + remove_from_group(SceneStringNames::get_singleton()->shader_overrides_group_active); + remove_from_group(SceneStringNames::get_singleton()->shader_overrides_group); + get_tree()->call_group(SceneStringNames::get_singleton()->shader_overrides_group, "_activate"); //another may want to activate when this is removed + active = false; + } +} + +String ShaderGlobalsOverride::get_configuration_warning() const { + + if (!active) { + return TTR("ShaderGlobalsOverride is not active because another node of the same type is in the scene."); + } + + return String(); +} + +void ShaderGlobalsOverride::_bind_methods() { + + ClassDB::bind_method(D_METHOD("_activate"), &ShaderGlobalsOverride::_activate); +} + +ShaderGlobalsOverride::ShaderGlobalsOverride() { + active = false; +} |