summaryrefslogtreecommitdiff
path: root/servers/rendering
diff options
context:
space:
mode:
Diffstat (limited to 'servers/rendering')
-rw-r--r--servers/rendering/renderer_rd/environment/sky.cpp14
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp14
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h1
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp12
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp29
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.h1
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp10
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl18
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl18
-rw-r--r--servers/rendering/renderer_rd/shaders/skeleton.glsl64
-rw-r--r--servers/rendering/renderer_rd/storage_rd/material_storage.cpp14
-rw-r--r--servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp36
-rw-r--r--servers/rendering/shader_compiler.cpp43
-rw-r--r--servers/rendering/shader_compiler.h1
-rw-r--r--servers/rendering/shader_language.cpp37
-rw-r--r--servers/rendering/shader_language.h6
-rw-r--r--servers/rendering/shader_preprocessor.cpp214
-rw-r--r--servers/rendering/shader_preprocessor.h15
20 files changed, 447 insertions, 104 deletions
diff --git a/servers/rendering/renderer_rd/environment/sky.cpp b/servers/rendering/renderer_rd/environment/sky.cpp
index 6433a39863..d3601274b5 100644
--- a/servers/rendering/renderer_rd/environment/sky.cpp
+++ b/servers/rendering/renderer_rd/environment/sky.cpp
@@ -114,12 +114,16 @@ void SkyRD::SkyShaderData::set_code(const String &p_code) {
for (int i = 0; i < gen_code.defines.size(); i++) {
print_line(gen_code.defines[i]);
}
+
+ HashMap<String, String>::Iterator el = gen_code.code.begin();
+ while (el) {
+ print_line("\n**code " + el->key + ":\n" + el->value);
+ ++el;
+ }
+
print_line("\n**uniforms:\n" + gen_code.uniforms);
- // print_line("\n**vertex_globals:\n" + gen_code.vertex_global);
- // print_line("\n**vertex_code:\n" + gen_code.vertex);
- print_line("\n**fragment_globals:\n" + gen_code.fragment_global);
- print_line("\n**fragment_code:\n" + gen_code.fragment);
- print_line("\n**light_code:\n" + gen_code.light);
+ print_line("\n**vertex_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX]);
+ print_line("\n**fragment_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT]);
#endif
scene_singleton->sky.sky_shader.shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines);
diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
index 556db086b2..0911ee595f 100644
--- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
@@ -150,6 +150,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
depth_draw = DepthDraw(depth_drawi);
depth_test = DepthTest(depth_testi);
cull_mode = Cull(cull_modei);
+ uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps;
#if 0
print_line("**compiling shader:");
@@ -158,11 +159,10 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
print_line(gen_code.defines[i]);
}
- RBMap<String, String>::Element *el = gen_code.code.front();
+ HashMap<String, String>::Iterator el = gen_code.code.begin();
while (el) {
- print_line("\n**code " + el->key() + ":\n" + el->value());
-
- el = el->next();
+ print_line("\n**code " + el->key + ":\n" + el->value);
+ ++el;
}
print_line("\n**uniforms:\n" + gen_code.uniforms);
@@ -396,7 +396,11 @@ void SceneShaderForwardClustered::ShaderData::get_shader_uniform_list(List<Prope
HashMap<int, StringName> order;
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
- if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) {
+ if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
+ // Don't expose any of these.
continue;
}
diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
index fa9ebde1b2..d6b526fa4a 100644
--- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
@@ -174,6 +174,7 @@ public:
bool uses_time = false;
bool writes_modelview_or_projection = false;
bool uses_world_coordinates = false;
+ bool uses_screen_texture_mipmaps = false;
Cull cull_mode = CULL_DISABLED;
uint64_t last_pass = 0;
diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
index 01b54607bc..85c9e1db2a 100644
--- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
@@ -158,11 +158,10 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
print_line(gen_code.defines[i]);
}
- RBMap<String, String>::Element * el = gen_code.code.front();
+ HashMap<String, String>::Iterator el = gen_code.code.begin();
while (el) {
- print_line("\n**code " + el->key() + ":\n" + el->value());
-
- el = el->next();
+ print_line("\n**code " + el->key + ":\n" + el->value);
+ ++el;
}
print_line("\n**uniforms:\n" + gen_code.uniforms);
@@ -353,7 +352,10 @@ void SceneShaderForwardMobile::ShaderData::get_shader_uniform_list(List<Property
HashMap<int, StringName> order;
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
- if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) {
+ if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
continue;
}
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
index c1b08ee4c9..38a2340d40 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -1361,6 +1361,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
Item *ci = p_item_list;
Rect2 back_buffer_rect;
bool backbuffer_copy = false;
+ bool backbuffer_gen_mipmaps = false;
Item *canvas_group_owner = nullptr;
@@ -1389,6 +1390,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
if (!material_screen_texture_found) {
backbuffer_copy = true;
back_buffer_rect = Rect2();
+ backbuffer_gen_mipmaps = md->shader_data->uses_screen_texture_mipmaps;
}
}
@@ -1474,9 +1476,10 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list);
item_count = 0;
- texture_storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect, true);
+ texture_storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect, backbuffer_gen_mipmaps);
backbuffer_copy = false;
+ backbuffer_gen_mipmaps = false;
material_screen_texture_found = true; //after a backbuffer copy, screen texture makes no further copies
}
@@ -1980,6 +1983,7 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
ubo_size = 0;
uniforms.clear();
uses_screen_texture = false;
+ uses_screen_texture_mipmaps = false;
uses_sdf = false;
uses_time = false;
@@ -1990,7 +1994,6 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
ShaderCompiler::GeneratedCode gen_code;
int blend_mode = BLEND_MODE_MIX;
- uses_screen_texture = false;
ShaderCompiler::IdentifierActions actions;
actions.entry_point_stages["vertex"] = ShaderCompiler::STAGE_VERTEX;
@@ -2015,6 +2018,8 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
Error err = canvas_singleton->shader.compiler.compile(RS::SHADER_CANVAS_ITEM, code, &actions, path, gen_code);
ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed.");
+ uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps;
+
if (version.is_null()) {
version = canvas_singleton->shader.canvas_shader.version_create();
}
@@ -2025,12 +2030,16 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
for (int i = 0; i < gen_code.defines.size(); i++) {
print_line(gen_code.defines[i]);
}
+
+ HashMap<String, String>::Iterator el = gen_code.code.begin();
+ while (el) {
+ print_line("\n**code " + el->key + ":\n" + el->value);
+ ++el;
+ }
+
print_line("\n**uniforms:\n" + gen_code.uniforms);
- print_line("\n**vertex_globals:\n" + gen_code.vertex_global);
- print_line("\n**vertex_code:\n" + gen_code.vertex);
- print_line("\n**fragment_globals:\n" + gen_code.fragment_global);
- print_line("\n**fragment_code:\n" + gen_code.fragment);
- print_line("\n**light_code:\n" + gen_code.light);
+ print_line("\n**vertex_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX]);
+ print_line("\n**fragment_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT]);
#endif
canvas_singleton->shader.canvas_shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines);
ERR_FAIL_COND(!canvas_singleton->shader.canvas_shader.version_is_valid(version));
@@ -2175,7 +2184,11 @@ void RendererCanvasRenderRD::CanvasShaderData::get_shader_uniform_list(List<Prop
HashMap<int, StringName> order;
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
- if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) {
+ if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
+ // Don't expose any of these.
continue;
}
if (E.value.texture_order >= 0) {
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
index 5eb4cee4c6..bcbbbaa1a0 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
@@ -174,6 +174,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
HashMap<StringName, HashMap<int, RID>> default_texture_params;
bool uses_screen_texture = false;
+ bool uses_screen_texture_mipmaps = false;
bool uses_sdf = false;
bool uses_time = false;
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index 6c219933b0..d8499681ad 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -2868,7 +2868,9 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
WARN_PRINT_ONCE("The DirectionalLight3D PSSM splits debug draw mode is not reimplemented yet.");
}
- light_data.shadow_opacity = p_using_shadows && light_storage->light_has_shadow(base) ? light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_OPACITY) : 0.0;
+ light_data.shadow_opacity = (p_using_shadows && light_storage->light_has_shadow(base))
+ ? light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_OPACITY)
+ : 0.0;
float angular_diameter = light_storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
if (angular_diameter > 0.0) {
@@ -3122,7 +3124,11 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
light_data.projector_rect[3] = 0;
}
- const bool needs_shadow = shadow_atlas && shadow_atlas->shadow_owners.has(li->self);
+ const bool needs_shadow =
+ shadow_atlas &&
+ shadow_atlas->shadow_owners.has(li->self) &&
+ p_using_shadows &&
+ light_storage->light_has_shadow(base);
bool in_shadow_range = true;
if (needs_shadow && light_storage->light_is_distance_fade_enabled(li->light)) {
diff --git a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl
index 0438671dd2..0b43af7738 100644
--- a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl
@@ -30,7 +30,7 @@ layout(set = 1, binding = 0) uniform sampler2D source_bokeh;
#ifdef MODE_GEN_BLUR_SIZE
float get_depth_at_pos(vec2 uv) {
- float depth = textureLod(source_depth, uv, 0.0).x;
+ float depth = textureLod(source_depth, uv, 0.0).x * 2.0 - 1.0;
if (params.orthogonal) {
depth = ((depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0;
} else {
diff --git a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl
index a3b3938ee9..a06cacfabe 100644
--- a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl
@@ -52,7 +52,7 @@ layout(set = 2, binding = 0) uniform sampler2D original_weight;
#ifdef MODE_GEN_BLUR_SIZE
float get_depth_at_pos(vec2 uv) {
- float depth = textureLod(source_depth, uv, 0.0).x;
+ float depth = textureLod(source_depth, uv, 0.0).x * 2.0 - 1.0;
if (params.orthogonal) {
depth = ((depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0;
} else {
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
index e9515c7670..6b4e4a5a16 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
@@ -15,11 +15,11 @@ layout(location = 0) in vec3 vertex_attrib;
//only for pure render depth when normal is not used
#ifdef NORMAL_USED
-layout(location = 1) in vec3 normal_attrib;
+layout(location = 1) in vec2 normal_attrib;
#endif
#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
-layout(location = 2) in vec4 tangent_attrib;
+layout(location = 2) in vec2 tangent_attrib;
#endif
#if defined(COLOR_USED)
@@ -58,6 +58,13 @@ layout(location = 10) in uvec4 bone_attrib;
layout(location = 11) in vec4 weight_attrib;
#endif
+vec3 oct_to_vec3(vec2 e) {
+ vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));
+ float t = max(-v.z, 0.0);
+ v.xy += t * -sign(v.xy);
+ return v;
+}
+
/* Varyings */
layout(location = 0) out vec3 vertex_interp;
@@ -231,12 +238,13 @@ void vertex_shader(in uint instance_index, in bool is_multimesh, in SceneData sc
vec3 vertex = vertex_attrib;
#ifdef NORMAL_USED
- vec3 normal = normal_attrib * 2.0 - 1.0;
+ vec3 normal = oct_to_vec3(normal_attrib * 2.0 - 1.0);
#endif
#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
- vec3 tangent = tangent_attrib.xyz * 2.0 - 1.0;
- float binormalf = tangent_attrib.a * 2.0 - 1.0;
+ vec2 signed_tangent_attrib = tangent_attrib * 2.0 - 1.0;
+ vec3 tangent = oct_to_vec3(vec2(signed_tangent_attrib.x, abs(signed_tangent_attrib.y) * 2.0 - 1.0));
+ float binormalf = sign(signed_tangent_attrib.y);
vec3 binormal = normalize(cross(normal, tangent) * binormalf);
#endif
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
index 6548793bee..0960533917 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
@@ -16,11 +16,11 @@ layout(location = 0) in vec3 vertex_attrib;
//only for pure render depth when normal is not used
#ifdef NORMAL_USED
-layout(location = 1) in vec3 normal_attrib;
+layout(location = 1) in vec2 normal_attrib;
#endif
#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
-layout(location = 2) in vec4 tangent_attrib;
+layout(location = 2) in vec2 tangent_attrib;
#endif
#if defined(COLOR_USED)
@@ -59,6 +59,13 @@ layout(location = 10) in uvec4 bone_attrib;
layout(location = 11) in vec4 weight_attrib;
#endif
+vec3 oct_to_vec3(vec2 e) {
+ vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));
+ float t = max(-v.z, 0.0);
+ v.xy += t * -sign(v.xy);
+ return v;
+}
+
/* Varyings */
layout(location = 0) highp out vec3 vertex_interp;
@@ -229,12 +236,13 @@ void main() {
vec3 vertex = vertex_attrib;
#ifdef NORMAL_USED
- vec3 normal = normal_attrib * 2.0 - 1.0;
+ vec3 normal = oct_to_vec3(normal_attrib * 2.0 - 1.0);
#endif
#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
- vec3 tangent = tangent_attrib.xyz * 2.0 - 1.0;
- float binormalf = tangent_attrib.a * 2.0 - 1.0;
+ vec3 signed_tangent_attrib = tangent_attrib * 2.0 - 1.0;
+ vec3 tangent = oct_to_vec3(vec2(signed_tangent_attrib.x, abs(signed_tangent_attrib.y) * 2.0 - 1.0));
+ float binormalf = sign(signed_tangent_attrib.y);
vec3 binormal = normalize(cross(normal, tangent) * binormalf);
#endif
diff --git a/servers/rendering/renderer_rd/shaders/skeleton.glsl b/servers/rendering/renderer_rd/shaders/skeleton.glsl
index a893a66c94..75bea9300b 100644
--- a/servers/rendering/renderer_rd/shaders/skeleton.glsl
+++ b/servers/rendering/renderer_rd/shaders/skeleton.glsl
@@ -54,14 +54,54 @@ layout(push_constant, std430) uniform Params {
}
params;
-vec4 decode_abgr_2_10_10_10(uint base) {
- uvec4 abgr_2_10_10_10 = (uvec4(base) >> uvec4(0, 10, 20, 30)) & uvec4(0x3FF, 0x3FF, 0x3FF, 0x3);
- return vec4(abgr_2_10_10_10) / vec4(1023.0, 1023.0, 1023.0, 3.0) * 2.0 - 1.0;
+vec2 uint_to_vec2(uint base) {
+ uvec2 decode = (uvec2(base) >> uvec2(0, 16)) & uvec2(0xFFFF, 0xFFFF);
+ return vec2(decode) / vec2(65535.0, 65535.0) * 2.0 - 1.0;
}
-uint encode_abgr_2_10_10_10(vec4 base) {
- uvec4 abgr_2_10_10_10 = uvec4(clamp(ivec4((base * 0.5 + 0.5) * vec4(1023.0, 1023.0, 1023.0, 3.0)), ivec4(0), ivec4(0x3FF, 0x3FF, 0x3FF, 0x3))) << uvec4(0, 10, 20, 30);
- return abgr_2_10_10_10.x | abgr_2_10_10_10.y | abgr_2_10_10_10.z | abgr_2_10_10_10.w;
+vec3 oct_to_vec3(vec2 oct) {
+ vec3 v = vec3(oct.xy, 1.0 - abs(oct.x) - abs(oct.y));
+ float t = max(-v.z, 0.0);
+ v.xy += t * -sign(v.xy);
+ return v;
+}
+
+vec3 decode_uint_oct_to_norm(uint base) {
+ return oct_to_vec3(uint_to_vec2(base));
+}
+
+vec4 decode_uint_oct_to_tang(uint base) {
+ vec2 oct_sign_encoded = uint_to_vec2(base);
+ // Binormal sign encoded in y component
+ vec2 oct = vec2(oct_sign_encoded.x, abs(oct_sign_encoded.y) * 2.0 - 1.0);
+ return vec4(oct_to_vec3(oct), sign(oct_sign_encoded.y));
+}
+
+vec2 signNotZero(vec2 v) {
+ return mix(vec2(-1.0), vec2(1.0), greaterThanEqual(v.xy, vec2(0.0)));
+}
+
+uint vec2_to_uint(vec2 base) {
+ uvec2 enc = uvec2(clamp(ivec2(base * vec2(65535, 65535)), ivec2(0), ivec2(0xFFFF, 0xFFFF))) << uvec2(0, 16);
+ return enc.x | enc.y;
+}
+
+vec2 vec3_to_oct(vec3 e) {
+ e /= abs(e.x) + abs(e.y) + abs(e.z);
+ vec2 oct = e.z >= 0.0f ? e.xy : (vec2(1.0f) - abs(e.yx)) * signNotZero(e.xy);
+ return oct * 0.5f + 0.5f;
+}
+
+uint encode_norm_to_uint_oct(vec3 base) {
+ return vec2_to_uint(vec3_to_oct(base));
+}
+
+uint encode_tang_to_uint_oct(vec4 base) {
+ vec2 oct = vec3_to_oct(base.xyz);
+ // Encode binormal sign in y component
+ oct.y = oct.y * 0.5f + 0.5f;
+ oct.y = base.w >= 0.0f ? oct.y : 1 - oct.y;
+ return vec2_to_uint(oct);
}
void main() {
@@ -131,12 +171,12 @@ void main() {
src_offset += 3;
if (params.has_normal) {
- normal = decode_abgr_2_10_10_10(src_vertices.data[src_offset]).rgb;
+ normal = decode_uint_oct_to_norm(src_vertices.data[src_offset]);
src_offset++;
}
if (params.has_tangent) {
- tangent = decode_abgr_2_10_10_10(src_vertices.data[src_offset]);
+ tangent = decode_uint_oct_to_tang(src_vertices.data[src_offset]);
}
if (params.has_blend_shape) {
@@ -155,12 +195,12 @@ void main() {
base_offset += 3;
if (params.has_normal) {
- blend_normal += decode_abgr_2_10_10_10(src_blend_shapes.data[base_offset]).rgb * w;
+ blend_normal += decode_uint_oct_to_norm(src_blend_shapes.data[base_offset]) * w;
base_offset++;
}
if (params.has_tangent) {
- blend_tangent += decode_abgr_2_10_10_10(src_blend_shapes.data[base_offset]).rgb * w;
+ blend_tangent += decode_uint_oct_to_tang(src_blend_shapes.data[base_offset]).rgb * w;
}
blend_total += w;
@@ -234,12 +274,12 @@ void main() {
dst_offset += 3;
if (params.has_normal) {
- dst_vertices.data[dst_offset] = encode_abgr_2_10_10_10(vec4(normal, 0.0));
+ dst_vertices.data[dst_offset] = encode_norm_to_uint_oct(normal);
dst_offset++;
}
if (params.has_tangent) {
- dst_vertices.data[dst_offset] = encode_abgr_2_10_10_10(tangent);
+ dst_vertices.data[dst_offset] = encode_tang_to_uint_oct(tangent);
}
#endif
diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
index 41dd1ccc40..fa8406e7a1 100644
--- a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
@@ -941,6 +941,12 @@ void MaterialStorage::MaterialData::update_uniform_buffer(const HashMap<StringNa
continue; //instance uniforms don't appear in the buffer
}
+ if (E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
+ continue;
+ }
+
if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) {
//this is a global variable, get the index to it
GlobalShaderUniforms::Variable *gv = material_storage->global_shader_uniforms.variables.getptr(E.key);
@@ -1052,6 +1058,12 @@ void MaterialStorage::MaterialData::update_textures(const HashMap<StringName, Va
Vector<RID> textures;
+ if (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
+ p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
+ p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
+ continue;
+ }
+
if (p_texture_uniforms[i].global) {
uses_global_textures = true;
@@ -1307,7 +1319,7 @@ bool MaterialStorage::MaterialData::update_parameters_uniform_set(const HashMap<
update_textures(p_parameters, p_default_texture_params, p_texture_uniforms, texture_cache.ptrw(), true);
}
- if (p_ubo_size == 0 && p_texture_uniforms.size() == 0) {
+ if (p_ubo_size == 0 && (p_texture_uniforms.size() == 0)) {
// This material does not require an uniform set, so don't create it.
return false;
}
diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
index 585c42b2d8..49d7198ec2 100644
--- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
@@ -327,8 +327,10 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
bool use_as_storage = (p_surface.skin_data.size() || mesh->blend_shape_count > 0);
- s->vertex_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.vertex_data.size(), p_surface.vertex_data, use_as_storage);
- s->vertex_buffer_size = p_surface.vertex_data.size();
+ if (p_surface.vertex_data.size()) {
+ s->vertex_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.vertex_data.size(), p_surface.vertex_data, use_as_storage);
+ s->vertex_buffer_size = p_surface.vertex_data.size();
+ }
if (p_surface.attribute_data.size()) {
s->attribute_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.attribute_data.size(), p_surface.attribute_data);
@@ -345,7 +347,7 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
}
if (p_surface.index_count) {
- bool is_index_16 = p_surface.vertex_count <= 65536;
+ bool is_index_16 = p_surface.vertex_count <= 65536 && p_surface.vertex_count > 0;
s->index_buffer = RD::get_singleton()->index_buffer_create(p_surface.index_count, is_index_16 ? RD::INDEX_BUFFER_FORMAT_UINT16 : RD::INDEX_BUFFER_FORMAT_UINT32, p_surface.index_data, false);
s->index_count = p_surface.index_count;
@@ -364,6 +366,8 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
}
}
+ ERR_FAIL_COND_MSG(!p_surface.index_count && !p_surface.vertex_count, "Meshes must contain a vertex array, an index array, or both");
+
s->aabb = p_surface.aabb;
s->bone_aabbs = p_surface.bone_aabbs; //only really useful for returning them.
@@ -377,7 +381,11 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
RD::Uniform u;
u.binding = 0;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.append_id(s->vertex_buffer);
+ if (s->vertex_buffer.is_valid()) {
+ u.append_id(s->vertex_buffer);
+ } else {
+ u.append_id(default_rd_storage_buffer);
+ }
uniforms.push_back(u);
}
{
@@ -470,6 +478,7 @@ void MeshStorage::mesh_surface_update_vertex_region(RID p_mesh, int p_surface, i
ERR_FAIL_COND(!mesh);
ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
ERR_FAIL_COND(p_data.size() == 0);
+ ERR_FAIL_COND(mesh->surfaces[p_surface]->vertex_buffer.is_null());
uint64_t data_size = p_data.size();
const uint8_t *r = p_data.ptr();
@@ -527,7 +536,9 @@ RS::SurfaceData MeshStorage::mesh_get_surface(RID p_mesh, int p_surface) const {
RS::SurfaceData sd;
sd.format = s.format;
- sd.vertex_data = RD::get_singleton()->buffer_get_data(s.vertex_buffer);
+ if (s.vertex_buffer.is_valid()) {
+ sd.vertex_data = RD::get_singleton()->buffer_get_data(s.vertex_buffer);
+ }
if (s.attribute_buffer.is_valid()) {
sd.attribute_data = RD::get_singleton()->buffer_get_data(s.attribute_buffer);
}
@@ -705,7 +716,9 @@ void MeshStorage::mesh_clear(RID p_mesh) {
ERR_FAIL_COND(!mesh);
for (uint32_t i = 0; i < mesh->surface_count; i++) {
Mesh::Surface &s = *mesh->surfaces[i];
- RD::get_singleton()->free(s.vertex_buffer); //clears arrays as dependency automatically, including all versions
+ if (s.vertex_buffer.is_valid()) {
+ RD::get_singleton()->free(s.vertex_buffer); //clears arrays as dependency automatically, including all versions
+ }
if (s.attribute_buffer.is_valid()) {
RD::get_singleton()->free(s.attribute_buffer);
}
@@ -851,7 +864,7 @@ void MeshStorage::_mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint3
}
MeshInstance::Surface s;
- if (mesh->blend_shape_count > 0 || (mesh->surfaces[p_surface]->format & RS::ARRAY_FORMAT_BONES)) {
+ if ((mesh->blend_shape_count > 0 || (mesh->surfaces[p_surface]->format & RS::ARRAY_FORMAT_BONES)) && mesh->surfaces[p_surface]->vertex_buffer_size > 0) {
//surface warrants transform
s.vertex_buffer = RD::get_singleton()->vertex_buffer_create(mesh->surfaces[p_surface]->vertex_buffer_size, Vector<uint8_t>(), true);
@@ -1060,10 +1073,9 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V
} break;
case RS::ARRAY_NORMAL: {
vd.offset = stride;
+ vd.format = RD::DATA_FORMAT_R16G16_UNORM;
+ stride += sizeof(uint16_t) * 2;
- vd.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32;
-
- stride += sizeof(uint32_t);
if (mis) {
buffer = mis->vertex_buffer;
} else {
@@ -1072,9 +1084,9 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V
} break;
case RS::ARRAY_TANGENT: {
vd.offset = stride;
+ vd.format = RD::DATA_FORMAT_R16G16_UNORM;
+ stride += sizeof(uint16_t) * 2;
- vd.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32;
- stride += sizeof(uint32_t);
if (mis) {
buffer = mis->vertex_buffer;
} else {
diff --git a/servers/rendering/shader_compiler.cpp b/servers/rendering/shader_compiler.cpp
index c2cf08812c..f14350305a 100644
--- a/servers/rendering/shader_compiler.cpp
+++ b/servers/rendering/shader_compiler.cpp
@@ -498,6 +498,11 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
for (const KeyValue<StringName, SL::ShaderNode::Uniform> &E : pnode->uniforms) {
if (SL::is_sampler_type(E.value.type)) {
+ if (E.value.hint == SL::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
+ E.value.hint == SL::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
+ E.value.hint == SL::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
+ continue; // Don't create uniforms in the generated code for these.
+ }
max_texture_uniforms++;
} else {
if (E.value.scope == SL::ShaderNode::Uniform::SCOPE_INSTANCE) {
@@ -537,6 +542,13 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
p_actions.uniforms->insert(uniform_name, uniform);
continue; // Instances are indexed directly, don't need index uniforms.
}
+
+ if (uniform.hint == SL::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
+ uniform.hint == SL::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
+ uniform.hint == SL::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
+ continue; // Don't create uniforms in the generated code for these.
+ }
+
if (SL::is_sampler_type(uniform.type)) {
// Texture layouts are different for OpenGL GLSL and Vulkan GLSL
if (!RS::get_singleton()->is_low_end()) {
@@ -892,12 +904,39 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
if (p_default_actions.renames.has(vnode->name)) {
code = p_default_actions.renames[vnode->name];
+ if (vnode->name == "SCREEN_TEXTURE") {
+ r_gen_code.uses_screen_texture_mipmaps = true;
+ }
} else {
if (shader->uniforms.has(vnode->name)) {
//its a uniform!
const ShaderLanguage::ShaderNode::Uniform &u = shader->uniforms[vnode->name];
if (u.texture_order >= 0) {
- code = _mkid(vnode->name); //texture, use as is
+ StringName name = vnode->name;
+ if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE) {
+ name = "SCREEN_TEXTURE";
+ if (u.filter >= ShaderLanguage::FILTER_NEAREST_MIPMAP) {
+ r_gen_code.uses_screen_texture_mipmaps = true;
+ }
+ } else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE) {
+ name = "NORMAL_ROUGHNESS_TEXTURE";
+ } else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
+ name = "DEPTH_TEXTURE";
+ } else {
+ name = _mkid(vnode->name); //texture, use as is
+ }
+
+ if (p_default_actions.renames.has(name)) {
+ code = p_default_actions.renames[name];
+ } else {
+ code = name;
+ }
+
+ if (p_actions.usage_flag_pointers.has(name) && !used_flag_pointers.has(name)) {
+ *p_actions.usage_flag_pointers[name] = true;
+ used_flag_pointers.insert(name);
+ }
+
} else {
//a scalar or vector
if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) {
@@ -1155,6 +1194,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
}
if (correct_texture_uniform) {
+ //TODO Needs to detect screen_texture hint as well
is_screen_texture = (texture_uniform == "SCREEN_TEXTURE");
String sampler_name;
@@ -1404,6 +1444,7 @@ Error ShaderCompiler::compile(RS::ShaderMode p_mode, const String &p_code, Ident
r_gen_code.uses_fragment_time = false;
r_gen_code.uses_vertex_time = false;
r_gen_code.uses_global_textures = false;
+ r_gen_code.uses_screen_texture_mipmaps = false;
used_name_defines.clear();
used_rmode_defines.clear();
diff --git a/servers/rendering/shader_compiler.h b/servers/rendering/shader_compiler.h
index 06f42e9f0f..1ad43daf5f 100644
--- a/servers/rendering/shader_compiler.h
+++ b/servers/rendering/shader_compiler.h
@@ -80,6 +80,7 @@ public:
bool uses_global_textures;
bool uses_fragment_time;
bool uses_vertex_time;
+ bool uses_screen_texture_mipmaps;
};
struct DefaultIdentifierActions {
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index 81e4d5e217..cab92e6e20 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -200,6 +200,9 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
"HINT_ANISOTROPY_TEXTURE",
"HINT_RANGE",
"HINT_INSTANCE_INDEX",
+ "HINT_SCREEN_TEXTURE",
+ "HINT_NORMAL_ROUGHNESS_TEXTURE",
+ "HINT_DEPTH_TEXTURE",
"FILTER_NEAREST",
"FILTER_LINEAR",
"FILTER_NEAREST_MIPMAP",
@@ -363,6 +366,10 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
{ TK_HINT_ROUGHNESS_A, "hint_roughness_a", CF_UNSPECIFIED, {}, {} },
{ TK_HINT_ROUGHNESS_NORMAL_TEXTURE, "hint_roughness_normal", CF_UNSPECIFIED, {}, {} },
{ TK_HINT_ROUGHNESS_GRAY, "hint_roughness_gray", CF_UNSPECIFIED, {}, {} },
+ { TK_HINT_SCREEN_TEXTURE, "hint_screen_texture", CF_UNSPECIFIED, {}, {} },
+ { TK_HINT_NORMAL_ROUGHNESS_TEXTURE, "hint_normal_roughness_texture", CF_UNSPECIFIED, {}, {} },
+ { TK_HINT_DEPTH_TEXTURE, "hint_depth_texture", CF_UNSPECIFIED, {}, {} },
+
{ TK_FILTER_NEAREST, "filter_nearest", CF_UNSPECIFIED, {}, {} },
{ TK_FILTER_LINEAR, "filter_linear", CF_UNSPECIFIED, {}, {} },
{ TK_FILTER_NEAREST_MIPMAP, "filter_nearest_mipmap", CF_UNSPECIFIED, {}, {} },
@@ -1096,6 +1103,15 @@ String ShaderLanguage::get_uniform_hint_name(ShaderNode::Uniform::Hint p_hint) {
case ShaderNode::Uniform::HINT_ANISOTROPY: {
result = "hint_anisotropy";
} break;
+ case ShaderNode::Uniform::HINT_SCREEN_TEXTURE: {
+ result = "hint_screen_texture";
+ } break;
+ case ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE: {
+ result = "hint_normal_roughness_texture";
+ } break;
+ case ShaderNode::Uniform::HINT_DEPTH_TEXTURE: {
+ result = "hint_depth_texture";
+ } break;
default:
break;
}
@@ -8605,6 +8621,15 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
return ERR_PARSE_ERROR;
}
} break;
+ case TK_HINT_SCREEN_TEXTURE: {
+ new_hint = ShaderNode::Uniform::HINT_SCREEN_TEXTURE;
+ } break;
+ case TK_HINT_NORMAL_ROUGHNESS_TEXTURE: {
+ new_hint = ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE;
+ } break;
+ case TK_HINT_DEPTH_TEXTURE: {
+ new_hint = ShaderNode::Uniform::HINT_DEPTH_TEXTURE;
+ } break;
case TK_FILTER_NEAREST: {
new_filter = FILTER_NEAREST;
} break;
@@ -8629,6 +8654,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
case TK_REPEAT_ENABLE: {
new_repeat = REPEAT_ENABLE;
} break;
+
default:
break;
}
@@ -8653,9 +8679,9 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
if (new_filter != FILTER_DEFAULT) {
if (uniform.filter != FILTER_DEFAULT) {
if (uniform.filter == new_filter) {
- _set_error(vformat(RTR("Duplicated hint: '%s'."), get_texture_filter_name(new_filter)));
+ _set_error(vformat(RTR("Duplicated filter mode: '%s'."), get_texture_filter_name(new_filter)));
} else {
- _set_error(vformat(RTR("Redefinition of hint: '%s'. The filter mode has already been set to '%s'."), get_texture_filter_name(new_filter), get_texture_filter_name(uniform.filter)));
+ _set_error(vformat(RTR("Redefinition of filter mode: '%s'. The filter mode has already been set to '%s'."), get_texture_filter_name(new_filter), get_texture_filter_name(uniform.filter)));
}
return ERR_PARSE_ERROR;
} else {
@@ -8666,9 +8692,9 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
if (new_repeat != REPEAT_DEFAULT) {
if (uniform.repeat != REPEAT_DEFAULT) {
if (uniform.repeat == new_repeat) {
- _set_error(vformat(RTR("Duplicated hint: '%s'."), get_texture_repeat_name(new_repeat)));
+ _set_error(vformat(RTR("Duplicated repeat mode: '%s'."), get_texture_repeat_name(new_repeat)));
} else {
- _set_error(vformat(RTR("Redefinition of hint: '%s'. The repeat mode has already been set to '%s'."), get_texture_repeat_name(new_repeat), get_texture_repeat_name(uniform.repeat)));
+ _set_error(vformat(RTR("Redefinition of repeat mode: '%s'. The repeat mode has already been set to '%s'."), get_texture_repeat_name(new_repeat), get_texture_repeat_name(uniform.repeat)));
}
return ERR_PARSE_ERROR;
} else {
@@ -10309,6 +10335,9 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
options.push_back("hint_roughness_gray");
options.push_back("hint_roughness_normal");
options.push_back("hint_roughness_r");
+ options.push_back("hint_screen_texture");
+ options.push_back("hint_normal_roughness_texture");
+ options.push_back("hint_depth_texture");
options.push_back("source_color");
options.push_back("repeat_enable");
options.push_back("repeat_disable");
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index bfec6e1df6..75b713d167 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -176,6 +176,9 @@ public:
TK_HINT_SOURCE_COLOR,
TK_HINT_RANGE,
TK_HINT_INSTANCE_INDEX,
+ TK_HINT_SCREEN_TEXTURE,
+ TK_HINT_NORMAL_ROUGHNESS_TEXTURE,
+ TK_HINT_DEPTH_TEXTURE,
TK_FILTER_NEAREST,
TK_FILTER_LINEAR,
TK_FILTER_NEAREST_MIPMAP,
@@ -667,6 +670,9 @@ public:
HINT_DEFAULT_WHITE,
HINT_DEFAULT_TRANSPARENT,
HINT_ANISOTROPY,
+ HINT_SCREEN_TEXTURE,
+ HINT_NORMAL_ROUGHNESS_TEXTURE,
+ HINT_DEPTH_TEXTURE,
HINT_MAX
};
diff --git a/servers/rendering/shader_preprocessor.cpp b/servers/rendering/shader_preprocessor.cpp
index 8755ee61cc..3766477070 100644
--- a/servers/rendering/shader_preprocessor.cpp
+++ b/servers/rendering/shader_preprocessor.cpp
@@ -434,7 +434,12 @@ void ShaderPreprocessor::process_elif(Tokenizer *p_tokenizer) {
return;
}
- Error error = expand_macros(body, line, body);
+ Error error = expand_condition(body, line, body);
+ if (error != OK) {
+ return;
+ }
+
+ error = expand_macros(body, line, body);
if (error != OK) {
return;
}
@@ -528,7 +533,12 @@ void ShaderPreprocessor::process_if(Tokenizer *p_tokenizer) {
return;
}
- Error error = expand_macros(body, line, body);
+ Error error = expand_condition(body, line, body);
+ if (error != OK) {
+ return;
+ }
+
+ error = expand_macros(body, line, body);
if (error != OK) {
return;
}
@@ -777,47 +787,173 @@ void ShaderPreprocessor::expand_output_macros(int p_start, int p_line_number) {
add_to_output(line);
}
-Error ShaderPreprocessor::expand_macros(const String &p_string, int p_line, String &r_expanded) {
- Vector<Pair<String, Define *>> active_defines;
- active_defines.resize(state->defines.size());
- int index = 0;
- for (const RBMap<String, Define *>::Element *E = state->defines.front(); E; E = E->next()) {
- active_defines.set(index++, Pair<String, Define *>(E->key(), E->get()));
+Error ShaderPreprocessor::expand_condition(const String &p_string, int p_line, String &r_expanded) {
+ // Checks bracket count to be even + check the cursor position.
+ {
+ int bracket_start_count = 0;
+ int bracket_end_count = 0;
+
+ for (int i = 0; i < p_string.size(); i++) {
+ switch (p_string[i]) {
+ case CURSOR:
+ state->completion_type = COMPLETION_TYPE_CONDITION;
+ break;
+ case '(':
+ bracket_start_count++;
+ break;
+ case ')':
+ bracket_end_count++;
+ break;
+ }
+ }
+ if (bracket_start_count > bracket_end_count) {
+ _set_expected_error(")", p_line);
+ return FAILED;
+ }
+ if (bracket_end_count > bracket_start_count) {
+ _set_expected_error("(", p_line);
+ return FAILED;
+ }
}
- return expand_macros(p_string, p_line, active_defines, r_expanded);
+ String result = p_string;
+
+ int index = 0;
+ int index_start = 0;
+ int index_end = 0;
+
+ while (find_match(result, "defined", index, index_start)) {
+ bool open_bracket = false;
+ bool found_word = false;
+ bool word_completed = false;
+
+ LocalVector<char32_t> text;
+ int post_bracket_index = -1;
+ int size = result.size();
+
+ for (int i = (index_start - 1); i < size; i++) {
+ char32_t c = result[i];
+ if (c == 0) {
+ if (found_word) {
+ word_completed = true;
+ }
+ break;
+ }
+ char32_t cs[] = { c, '\0' };
+ String s = String(cs);
+ bool is_space = is_char_space(c);
+
+ if (word_completed) {
+ if (c == ')') {
+ continue;
+ }
+ if (c == '|' || c == '&') {
+ if (open_bracket) {
+ _set_unexpected_token_error(s, p_line);
+ return FAILED;
+ }
+ break;
+ } else if (!is_space) {
+ _set_unexpected_token_error(s, p_line);
+ return FAILED;
+ }
+ } else if (is_space) {
+ if (found_word && !open_bracket) {
+ index_end = i;
+ word_completed = true;
+ }
+ } else if (c == '(') {
+ if (open_bracket) {
+ _set_unexpected_token_error(s, p_line);
+ return FAILED;
+ }
+ open_bracket = true;
+ } else if (c == ')') {
+ if (open_bracket) {
+ if (!found_word) {
+ _set_unexpected_token_error(s, p_line);
+ return FAILED;
+ }
+ open_bracket = false;
+ post_bracket_index = i + 1;
+ } else {
+ index_end = i;
+ }
+ word_completed = true;
+ } else if (is_char_word(c)) {
+ text.push_back(c);
+ found_word = true;
+ } else {
+ _set_unexpected_token_error(s, p_line);
+ return FAILED;
+ }
+ }
+
+ if (word_completed) {
+ if (open_bracket) {
+ _set_expected_error(")", p_line);
+ return FAILED;
+ }
+ if (post_bracket_index != -1) {
+ index_end = post_bracket_index;
+ }
+
+ String body = state->defines.has(vector_to_string(text)) ? "true" : "false";
+ String temp = result;
+
+ result = result.substr(0, index) + body;
+ index_start = result.length();
+ if (index_end > 0) {
+ result += temp.substr(index_end);
+ }
+ } else {
+ set_error(RTR("Invalid macro name."), p_line);
+ return FAILED;
+ }
+ }
+ r_expanded = result;
+ return OK;
}
-Error ShaderPreprocessor::expand_macros(const String &p_string, int p_line, Vector<Pair<String, Define *>> p_defines, String &r_expanded) {
- r_expanded = p_string;
- // When expanding macros we must only evaluate them once.
- // Later we continue expanding but with the already
- // evaluated macros removed.
- for (int i = 0; i < p_defines.size(); i++) {
- Pair<String, Define *> define_pair = p_defines[i];
-
- Error error = expand_macros_once(r_expanded, p_line, define_pair, r_expanded);
- if (error != OK) {
- return error;
+Error ShaderPreprocessor::expand_macros(const String &p_string, int p_line, String &r_expanded) {
+ String iterative = p_string;
+ int pass_count = 0;
+ bool expanded = true;
+
+ while (expanded) {
+ expanded = false;
+
+ // As long as we find something to expand, keep going.
+ for (const RBMap<String, Define *>::Element *E = state->defines.front(); E; E = E->next()) {
+ if (expand_macros_once(iterative, p_line, E, iterative)) {
+ expanded = true;
+ }
}
- // Remove expanded macro and recursively replace remaining.
- p_defines.remove_at(i);
- return expand_macros(r_expanded, p_line, p_defines, r_expanded);
+ pass_count++;
+ if (pass_count > 50) {
+ set_error(RTR("Macro expansion limit exceeded."), p_line);
+ break;
+ }
}
+ r_expanded = iterative;
+
+ if (!state->error.is_empty()) {
+ return FAILED;
+ }
return OK;
}
-Error ShaderPreprocessor::expand_macros_once(const String &p_line, int p_line_number, Pair<String, Define *> p_define_pair, String &r_expanded) {
+bool ShaderPreprocessor::expand_macros_once(const String &p_line, int p_line_number, const RBMap<String, Define *>::Element *p_define_pair, String &r_expanded) {
String result = p_line;
- const String &key = p_define_pair.first;
- const Define *define = p_define_pair.second;
+ const String &key = p_define_pair->key();
+ const Define *define = p_define_pair->value();
int index_start = 0;
int index = 0;
- while (find_match(result, key, index, index_start)) {
+ if (find_match(result, key, index, index_start)) {
String body = define->body;
if (define->arguments.size() > 0) {
// Complex macro with arguments.
@@ -825,14 +961,14 @@ Error ShaderPreprocessor::expand_macros_once(const String &p_line, int p_line_nu
int args_end = p_line.find(")", args_start);
if (args_start == -1 || args_end == -1) {
set_error(RTR("Missing macro argument parenthesis."), p_line_number);
- return FAILED;
+ return false;
}
String values = result.substr(args_start + 1, args_end - (args_start + 1));
Vector<String> args = values.split(",");
if (args.size() != define->arguments.size()) {
set_error(RTR("Invalid macro argument count."), p_line_number);
- return FAILED;
+ return false;
}
// Insert macro arguments into the body.
@@ -854,11 +990,13 @@ Error ShaderPreprocessor::expand_macros_once(const String &p_line, int p_line_nu
// Manually reset index_start to where the body value of the define finishes.
// This ensures we don't skip another instance of this macro in the string.
index_start = index + body.length() + 1;
- break;
}
+
+ r_expanded = result;
+ return true;
}
- r_expanded = result;
- return OK;
+
+ return false;
}
bool ShaderPreprocessor::find_match(const String &p_string, const String &p_value, int &r_index, int &r_index_start) {
@@ -1064,7 +1202,7 @@ Error ShaderPreprocessor::preprocess(const String &p_code, const String &p_filen
switch (pp_state.completion_type) {
case COMPLETION_TYPE_DIRECTIVE: {
List<String> options;
- get_keyword_list(&options, true);
+ get_keyword_list(&options, true, true);
for (const String &E : options) {
ScriptLanguage::CodeCompletionOption option(E, ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
@@ -1083,6 +1221,11 @@ Error ShaderPreprocessor::preprocess(const String &p_code, const String &p_filen
}
} break;
+ case COMPLETION_TYPE_CONDITION: {
+ ScriptLanguage::CodeCompletionOption option("defined", ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
+ r_completion_options->push_back(option);
+
+ } break;
case COMPLETION_TYPE_INCLUDE_PATH: {
if (p_include_completion_func && r_completion_options) {
p_include_completion_func(r_completion_options);
@@ -1096,8 +1239,11 @@ Error ShaderPreprocessor::preprocess(const String &p_code, const String &p_filen
return err;
}
-void ShaderPreprocessor::get_keyword_list(List<String> *r_keywords, bool p_include_shader_keywords) {
+void ShaderPreprocessor::get_keyword_list(List<String> *r_keywords, bool p_include_shader_keywords, bool p_ignore_context_keywords) {
r_keywords->push_back("define");
+ if (!p_ignore_context_keywords) {
+ r_keywords->push_back("defined");
+ }
r_keywords->push_back("elif");
if (p_include_shader_keywords) {
r_keywords->push_back("else");
diff --git a/servers/rendering/shader_preprocessor.h b/servers/rendering/shader_preprocessor.h
index 71dd9a6ca8..b4e7c7199f 100644
--- a/servers/rendering/shader_preprocessor.h
+++ b/servers/rendering/shader_preprocessor.h
@@ -50,6 +50,7 @@ public:
COMPLETION_TYPE_DIRECTIVE,
COMPLETION_TYPE_PRAGMA_DIRECTIVE,
COMPLETION_TYPE_PRAGMA,
+ COMPLETION_TYPE_CONDITION,
COMPLETION_TYPE_INCLUDE_PATH,
};
@@ -175,6 +176,14 @@ private:
static String vector_to_string(const LocalVector<char32_t> &p_v, int p_start = 0, int p_end = -1);
static String tokens_to_string(const LocalVector<Token> &p_tokens);
+ void _set_expected_error(const String &p_what, int p_line) {
+ set_error(vformat(RTR("Expected a '%s'."), p_what), p_line);
+ }
+
+ void _set_unexpected_token_error(const String &p_what, int p_line) {
+ set_error(vformat(RTR("Unexpected token '%s'."), p_what), p_line);
+ }
+
void process_directive(Tokenizer *p_tokenizer);
void process_define(Tokenizer *p_tokenizer);
void process_elif(Tokenizer *p_tokenizer);
@@ -190,10 +199,10 @@ private:
void add_region(int p_line, bool p_enabled, Region *p_parent_region);
void start_branch_condition(Tokenizer *p_tokenizer, bool p_success, bool p_continue = false);
+ Error expand_condition(const String &p_string, int p_line, String &r_result);
void expand_output_macros(int p_start, int p_line);
Error expand_macros(const String &p_string, int p_line, String &r_result);
- Error expand_macros(const String &p_string, int p_line, Vector<Pair<String, Define *>> p_defines, String &r_result);
- Error expand_macros_once(const String &p_line, int p_line_number, Pair<String, Define *> p_define_pair, String &r_expanded);
+ bool expand_macros_once(const String &p_line, int p_line_number, const RBMap<String, Define *>::Element *p_define_pair, String &r_expanded);
bool find_match(const String &p_string, const String &p_value, int &r_index, int &r_index_start);
String next_directive(Tokenizer *p_tokenizer, const Vector<String> &p_directives);
@@ -211,7 +220,7 @@ public:
Error preprocess(const String &p_code, const String &p_filename, String &r_result, String *r_error_text = nullptr, List<FilePosition> *r_error_position = nullptr, List<Region> *r_regions = nullptr, HashSet<Ref<ShaderInclude>> *r_includes = nullptr, List<ScriptLanguage::CodeCompletionOption> *r_completion_options = nullptr, IncludeCompletionFunction p_include_completion_func = nullptr);
- static void get_keyword_list(List<String> *r_keywords, bool p_include_shader_keywords);
+ static void get_keyword_list(List<String> *r_keywords, bool p_include_shader_keywords, bool p_ignore_context_keywords = false);
static void get_pragma_list(List<String> *r_pragmas);
ShaderPreprocessor();