summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/SCsub2
-rw-r--r--drivers/backtrace/SCsub44
-rw-r--r--drivers/gles3/effects/copy_effects.cpp6
-rw-r--r--drivers/gles3/effects/post_effects.cpp4
-rw-r--r--drivers/gles3/effects/post_effects.h2
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp47
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.h5
-rw-r--r--drivers/gles3/shaders/canvas.glsl10
-rw-r--r--drivers/gles3/shaders/effects/post.glsl42
-rw-r--r--drivers/gles3/shaders/scene.glsl35
-rw-r--r--drivers/gles3/shaders/sky.glsl8
-rw-r--r--drivers/gles3/shaders/tonemap.glsl333
-rw-r--r--drivers/gles3/shaders/tonemap_inc.glsl67
-rw-r--r--drivers/gles3/storage/material_storage.cpp11
-rw-r--r--drivers/gles3/storage/material_storage.h1
-rw-r--r--drivers/gles3/storage/render_scene_buffers_gles3.cpp3
-rw-r--r--drivers/gles3/storage/texture_storage.cpp2
-rw-r--r--drivers/gles3/storage/utilities.cpp4
-rw-r--r--drivers/png/SCsub2
-rw-r--r--drivers/vulkan/rendering_device_driver_vulkan.cpp2
-rw-r--r--drivers/windows/dir_access_windows.cpp60
-rw-r--r--drivers/windows/dir_access_windows.h6
-rw-r--r--drivers/windows/file_access_windows.cpp65
23 files changed, 303 insertions, 458 deletions
diff --git a/drivers/SCsub b/drivers/SCsub
index 9c8b16d3e5..e77b96cc87 100644
--- a/drivers/SCsub
+++ b/drivers/SCsub
@@ -14,6 +14,8 @@ SConscript("coreaudio/SCsub")
SConscript("pulseaudio/SCsub")
if env["platform"] == "windows":
SConscript("wasapi/SCsub")
+ if not env.msvc:
+ SConscript("backtrace/SCsub")
if env["xaudio2"]:
SConscript("xaudio2/SCsub")
diff --git a/drivers/backtrace/SCsub b/drivers/backtrace/SCsub
new file mode 100644
index 0000000000..f61fb21581
--- /dev/null
+++ b/drivers/backtrace/SCsub
@@ -0,0 +1,44 @@
+#!/usr/bin/env python
+
+Import("env")
+
+env_backtrace = env.Clone()
+
+# Thirdparty source files
+
+thirdparty_obj = []
+
+thirdparty_dir = "#thirdparty/libbacktrace/"
+thirdparty_sources = [
+ "atomic.c",
+ "dwarf.c",
+ "fileline.c",
+ "posix.c",
+ "print.c",
+ "sort.c",
+ "state.c",
+ "backtrace.c",
+ "simple.c",
+ "pecoff.c",
+ "read.c",
+ "alloc.c",
+]
+thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
+
+env_backtrace.Prepend(CPPPATH=[thirdparty_dir])
+
+env_thirdparty = env_backtrace.Clone()
+env_thirdparty.disable_warnings()
+env_thirdparty.add_source_files(thirdparty_obj, thirdparty_sources)
+
+env.drivers_sources += thirdparty_obj
+
+# Godot source files
+
+driver_obj = []
+
+env_backtrace.add_source_files(driver_obj, "*.cpp")
+env.drivers_sources += driver_obj
+
+# Needed to force rebuilding the driver files when the thirdparty library is updated.
+env.Depends(driver_obj, thirdparty_obj)
diff --git a/drivers/gles3/effects/copy_effects.cpp b/drivers/gles3/effects/copy_effects.cpp
index 6e64652982..47ca832bd7 100644
--- a/drivers/gles3/effects/copy_effects.cpp
+++ b/drivers/gles3/effects/copy_effects.cpp
@@ -198,8 +198,7 @@ void CopyEffects::bilinear_blur(GLuint p_source_texture, int p_mipmap_count, con
for (int i = 1; i < p_mipmap_count; i++) {
dest_region.position.x >>= 1;
dest_region.position.y >>= 1;
- dest_region.size.x = MAX(1, dest_region.size.x >> 1);
- dest_region.size.y = MAX(1, dest_region.size.y >> 1);
+ dest_region.size = Size2i(dest_region.size.x >> 1, dest_region.size.y >> 1).maxi(1);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffers[i % 2]);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_source_texture, i);
glBlitFramebuffer(source_region.position.x, source_region.position.y, source_region.position.x + source_region.size.x, source_region.position.y + source_region.size.y,
@@ -238,8 +237,7 @@ void CopyEffects::gaussian_blur(GLuint p_source_texture, int p_mipmap_count, con
for (int i = 1; i < p_mipmap_count; i++) {
dest_region.position.x >>= 1;
dest_region.position.y >>= 1;
- dest_region.size.x = MAX(1, dest_region.size.x >> 1);
- dest_region.size.y = MAX(1, dest_region.size.y >> 1);
+ dest_region.size = Size2i(dest_region.size.x >> 1, dest_region.size.y >> 1).maxi(1);
base_size.x >>= 1;
base_size.y >>= 1;
diff --git a/drivers/gles3/effects/post_effects.cpp b/drivers/gles3/effects/post_effects.cpp
index 8ad872f319..105c8f6b71 100644
--- a/drivers/gles3/effects/post_effects.cpp
+++ b/drivers/gles3/effects/post_effects.cpp
@@ -87,7 +87,7 @@ void PostEffects::_draw_screen_triangle() {
glBindVertexArray(0);
}
-void PostEffects::post_copy(GLuint p_dest_framebuffer, Size2i p_dest_size, GLuint p_source_color, Size2i p_source_size, float p_luminance_multiplier, const Glow::GLOWLEVEL *p_glow_buffers, float p_glow_intensity, uint32_t p_view, bool p_use_multiview) {
+void PostEffects::post_copy(GLuint p_dest_framebuffer, Size2i p_dest_size, GLuint p_source_color, Size2i p_source_size, float p_luminance_multiplier, const Glow::GLOWLEVEL *p_glow_buffers, float p_glow_intensity, uint32_t p_view, bool p_use_multiview, uint64_t p_spec_constants) {
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
glDisable(GL_BLEND);
@@ -96,7 +96,7 @@ void PostEffects::post_copy(GLuint p_dest_framebuffer, Size2i p_dest_size, GLuin
glViewport(0, 0, p_dest_size.x, p_dest_size.y);
PostShaderGLES3::ShaderVariant mode = PostShaderGLES3::MODE_DEFAULT;
- uint64_t flags = 0;
+ uint64_t flags = p_spec_constants;
if (p_use_multiview) {
flags |= PostShaderGLES3::USE_MULTIVIEW;
}
diff --git a/drivers/gles3/effects/post_effects.h b/drivers/gles3/effects/post_effects.h
index b90c77d6c7..916d29a052 100644
--- a/drivers/gles3/effects/post_effects.h
+++ b/drivers/gles3/effects/post_effects.h
@@ -59,7 +59,7 @@ public:
PostEffects();
~PostEffects();
- void post_copy(GLuint p_dest_framebuffer, Size2i p_dest_size, GLuint p_source_color, Size2i p_source_size, float p_luminance_multiplier, const Glow::GLOWLEVEL *p_glow_buffers, float p_glow_intensity, uint32_t p_view = 0, bool p_use_multiview = false);
+ void post_copy(GLuint p_dest_framebuffer, Size2i p_dest_size, GLuint p_source_color, Size2i p_source_size, float p_luminance_multiplier, const Glow::GLOWLEVEL *p_glow_buffers, float p_glow_intensity, uint32_t p_view = 0, bool p_use_multiview = false, uint64_t p_spec_constants = 0);
};
} //namespace GLES3
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index bc1af86938..ee770be3da 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -788,7 +788,6 @@ void RasterizerSceneGLES3::_draw_sky(RID p_env, const Projection &p_projection,
}
if (!p_apply_color_adjustments_in_post) {
spec_constants |= SkyShaderGLES3::APPLY_TONEMAPPING;
- // TODO add BCS and color corrections once supported.
}
RS::EnvironmentBG background = environment_get_background(p_env);
@@ -2336,9 +2335,18 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
SceneState::TonemapUBO tonemap_ubo;
if (render_data.environment.is_valid()) {
+ bool use_bcs = environment_get_adjustments_enabled(render_data.environment);
+ if (use_bcs) {
+ apply_color_adjustments_in_post = true;
+ }
+
tonemap_ubo.exposure = environment_get_exposure(render_data.environment);
tonemap_ubo.white = environment_get_white(render_data.environment);
tonemap_ubo.tonemapper = int32_t(environment_get_tone_mapper(render_data.environment));
+
+ tonemap_ubo.brightness = environment_get_adjustments_brightness(render_data.environment);
+ tonemap_ubo.contrast = environment_get_adjustments_contrast(render_data.environment);
+ tonemap_ubo.saturation = environment_get_adjustments_saturation(render_data.environment);
}
if (scene_state.tonemap_buffer == 0) {
@@ -2558,8 +2566,6 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
if (!apply_color_adjustments_in_post) {
spec_constant_base_flags |= SceneShaderGLES3::APPLY_TONEMAPPING;
-
- // TODO add BCS and Color corrections here once supported.
}
}
// Render Opaque Objects.
@@ -2700,6 +2706,29 @@ void RasterizerSceneGLES3::_render_post_processing(const RenderDataGLES3 *p_rend
rb->check_glow_buffers();
}
+ bool use_bcs = environment_get_adjustments_enabled(p_render_data->environment);
+ uint64_t bcs_spec_constants = 0;
+ RID color_correction_texture = environment_get_color_correction(p_render_data->environment);
+ if (use_bcs && color_correction_texture.is_valid()) {
+ bcs_spec_constants |= PostShaderGLES3::USE_BCS;
+ bcs_spec_constants |= PostShaderGLES3::USE_COLOR_CORRECTION;
+
+ bool use_1d_lut = environment_get_use_1d_color_correction(p_render_data->environment);
+ GLenum texture_target = GL_TEXTURE_3D;
+ if (use_1d_lut) {
+ bcs_spec_constants |= PostShaderGLES3::USE_1D_LUT;
+ texture_target = GL_TEXTURE_2D;
+ }
+
+ glActiveTexture(GL_TEXTURE2);
+ glBindTexture(texture_target, texture_storage->texture_get_texid(color_correction_texture));
+ glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(texture_target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+ }
+
if (view_count == 1) {
// Resolve if needed.
if (fbo_msaa_3d != 0 && msaa3d_needs_resolve) {
@@ -2735,7 +2764,7 @@ void RasterizerSceneGLES3::_render_post_processing(const RenderDataGLES3 *p_rend
}
// Copy color buffer
- post_effects->post_copy(fbo_rt, target_size, color, internal_size, p_render_data->luminance_multiplier, glow_buffers, glow_intensity);
+ post_effects->post_copy(fbo_rt, target_size, color, internal_size, p_render_data->luminance_multiplier, glow_buffers, glow_intensity, 0, false, bcs_spec_constants);
// Copy depth buffer
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_int);
@@ -2803,7 +2832,7 @@ void RasterizerSceneGLES3::_render_post_processing(const RenderDataGLES3 *p_rend
glBindFramebuffer(GL_FRAMEBUFFER, fbos[2]);
glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, write_color, 0, v);
- post_effects->post_copy(fbos[2], target_size, source_color, internal_size, p_render_data->luminance_multiplier, glow_buffers, glow_intensity, v, true);
+ post_effects->post_copy(fbos[2], target_size, source_color, internal_size, p_render_data->luminance_multiplier, glow_buffers, glow_intensity, v, true, bcs_spec_constants);
}
// Copy depth
@@ -2824,6 +2853,9 @@ void RasterizerSceneGLES3::_render_post_processing(const RenderDataGLES3 *p_rend
glBindFramebuffer(GL_FRAMEBUFFER, fbo_rt);
glDeleteFramebuffers(3, fbos);
}
+
+ glActiveTexture(GL_TEXTURE2);
+ glBindTexture(GL_TEXTURE_2D, 0);
}
template <PassMode p_pass_mode>
@@ -3009,6 +3041,11 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
}
} break;
+ case GLES3::SceneShaderData::BLEND_MODE_PREMULT_ALPHA: {
+ glBlendEquation(GL_FUNC_ADD);
+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+
+ } break;
case GLES3::SceneShaderData::BLEND_MODE_ALPHA_TO_COVERAGE: {
// Do nothing for now.
} break;
diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h
index cc479bd4e9..c656ee3cc7 100644
--- a/drivers/gles3/rasterizer_scene_gles3.h
+++ b/drivers/gles3/rasterizer_scene_gles3.h
@@ -434,6 +434,11 @@ private:
float white = 1.0;
int32_t tonemapper = 0;
int32_t pad = 0;
+
+ int32_t pad2 = 0;
+ float brightness = 1.0;
+ float contrast = 1.0;
+ float saturation = 1.0;
};
static_assert(sizeof(TonemapUBO) % 16 == 0, "Tonemap UBO size must be a multiple of 16 bytes");
diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl
index efddbe9ad2..65332c06be 100644
--- a/drivers/gles3/shaders/canvas.glsl
+++ b/drivers/gles3/shaders/canvas.glsl
@@ -776,6 +776,12 @@ void main() {
vec2 tex_uv = (vec4(vertex, 0.0, 1.0) * mat4(light_array[light_base].texture_matrix[0], light_array[light_base].texture_matrix[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))).xy; //multiply inverse given its transposed. Optimizer removes useless operations.
vec2 tex_uv_atlas = tex_uv * light_array[light_base].atlas_rect.zw + light_array[light_base].atlas_rect.xy;
+
+ if (any(lessThan(tex_uv, vec2(0.0, 0.0))) || any(greaterThanEqual(tex_uv, vec2(1.0, 1.0)))) {
+ //if outside the light texture, light color is zero
+ continue;
+ }
+
vec4 light_color = textureLod(atlas_texture, tex_uv_atlas, 0.0);
vec4 light_base_color = light_array[light_base].color;
@@ -800,10 +806,6 @@ void main() {
light_color.rgb *= base_color.rgb;
}
#endif
- if (any(lessThan(tex_uv, vec2(0.0, 0.0))) || any(greaterThanEqual(tex_uv, vec2(1.0, 1.0)))) {
- //if outside the light texture, light color is zero
- light_color.a = 0.0;
- }
if (bool(light_array[light_base].flags & LIGHT_FLAGS_HAS_SHADOW)) {
vec2 shadow_pos = (vec4(shadow_vertex, 0.0, 1.0) * mat4(light_array[light_base].shadow_matrix[0], light_array[light_base].shadow_matrix[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))).xy; //multiply inverse given its transposed. Optimizer removes useless operations.
diff --git a/drivers/gles3/shaders/effects/post.glsl b/drivers/gles3/shaders/effects/post.glsl
index e61171c92a..1d17510c52 100644
--- a/drivers/gles3/shaders/effects/post.glsl
+++ b/drivers/gles3/shaders/effects/post.glsl
@@ -1,13 +1,15 @@
/* clang-format off */
#[modes]
-mode_default = #define MODE_DEFAULT
-// mode_glow = #define MODE_GLOW
+mode_default =
#[specializations]
USE_MULTIVIEW = false
USE_GLOW = false
USE_LUMINANCE_MULTIPLIER = false
+USE_BCS = false
+USE_COLOR_CORRECTION = false
+USE_1D_LUT = false
#[vertex]
layout(location = 0) in vec2 vertex_attrib;
@@ -25,6 +27,9 @@ void main() {
#[fragment]
/* clang-format on */
+// If we reach this code, we always tonemap.
+#define APPLY_TONEMAPPING
+
#include "../tonemap_inc.glsl"
#ifdef USE_MULTIVIEW
@@ -57,6 +62,35 @@ vec4 get_glow_color(vec2 uv) {
}
#endif // USE_GLOW
+#ifdef USE_COLOR_CORRECTION
+#ifdef USE_1D_LUT
+uniform sampler2D source_color_correction; //texunit:2
+
+vec3 apply_color_correction(vec3 color) {
+ color.r = texture(source_color_correction, vec2(color.r, 0.0f)).r;
+ color.g = texture(source_color_correction, vec2(color.g, 0.0f)).g;
+ color.b = texture(source_color_correction, vec2(color.b, 0.0f)).b;
+ return color;
+}
+#else
+uniform sampler3D source_color_correction; //texunit:2
+
+vec3 apply_color_correction(vec3 color) {
+ return textureLod(source_color_correction, color, 0.0).rgb;
+}
+#endif // USE_1D_LUT
+#endif // USE_COLOR_CORRECTION
+
+#ifdef USE_BCS
+vec3 apply_bcs(vec3 color) {
+ color = mix(vec3(0.0), color, brightness);
+ color = mix(vec3(0.5), color, contrast);
+ color = mix(vec3(dot(vec3(1.0), color) * 0.33333), color, saturation);
+
+ return color;
+}
+#endif
+
in vec2 uv_interp;
layout(location = 0) out vec4 frag_color;
@@ -85,11 +119,11 @@ void main() {
color.rgb = linear_to_srgb(color.rgb);
#ifdef USE_BCS
- color.rgb = apply_bcs(color.rgb, bcs);
+ color.rgb = apply_bcs(color.rgb);
#endif
#ifdef USE_COLOR_CORRECTION
- color.rgb = apply_color_correction(color.rgb, color_correction);
+ color.rgb = apply_color_correction(color.rgb);
#endif
frag_color = color;
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index 1973eb56c2..2b372cb88d 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -1442,6 +1442,9 @@ void main() {
float clearcoat_roughness = 0.0;
float anisotropy = 0.0;
vec2 anisotropy_flow = vec2(1.0, 0.0);
+#ifdef PREMUL_ALPHA_USED
+ float premul_alpha = 1.0;
+#endif // PREMUL_ALPHA_USED
#ifndef FOG_DISABLED
vec4 fog = vec4(0.0);
#endif // !FOG_DISABLED
@@ -1535,6 +1538,7 @@ void main() {
if (alpha < alpha_scissor_threshold) {
discard;
}
+ alpha = 1.0;
#else
#ifdef MODE_RENDER_DEPTH
#ifdef USE_OPAQUE_PREPASS
@@ -1858,23 +1862,16 @@ void main() {
#endif // !MODE_RENDER_DEPTH
#if defined(USE_SHADOW_TO_OPACITY)
+#ifndef MODE_RENDER_DEPTH
alpha = min(alpha, clamp(length(ambient_light), 0.0, 1.0));
#if defined(ALPHA_SCISSOR_USED)
if (alpha < alpha_scissor) {
discard;
}
-#else
-#ifdef MODE_RENDER_DEPTH
-#ifdef USE_OPAQUE_PREPASS
-
- if (alpha < opaque_prepass_threshold) {
- discard;
- }
-#endif // USE_OPAQUE_PREPASS
-#endif // MODE_RENDER_DEPTH
#endif // !ALPHA_SCISSOR_USED
+#endif // !MODE_RENDER_DEPTH
#endif // USE_SHADOW_TO_OPACITY
#ifdef MODE_RENDER_DEPTH
@@ -1934,13 +1931,6 @@ void main() {
#endif
frag_color.rgb = linear_to_srgb(frag_color.rgb);
-#ifdef USE_BCS
- frag_color.rgb = apply_bcs(frag_color.rgb, bcs);
-#endif
-
-#ifdef USE_COLOR_CORRECTION
- frag_color.rgb = apply_color_correction(frag_color.rgb, color_correction);
-#endif
#else // !BASE_PASS
frag_color = vec4(0.0, 0.0, 0.0, alpha);
#endif // !BASE_PASS
@@ -2152,19 +2142,14 @@ void main() {
#endif
additive_light_color = linear_to_srgb(additive_light_color);
-#ifdef USE_BCS
- additive_light_color = apply_bcs(additive_light_color, bcs);
-#endif
-
-#ifdef USE_COLOR_CORRECTION
- additive_light_color = apply_color_correction(additive_light_color, color_correction);
-#endif
-
frag_color.rgb += additive_light_color;
#endif // USE_ADDITIVE_LIGHTING
-
frag_color.rgb *= scene_data.luminance_multiplier;
#endif // !RENDER_MATERIAL
#endif // !MODE_RENDER_DEPTH
+
+#ifdef PREMUL_ALPHA_USED
+ frag_color.rgb *= premul_alpha;
+#endif // PREMUL_ALPHA_USED
}
diff --git a/drivers/gles3/shaders/sky.glsl b/drivers/gles3/shaders/sky.glsl
index 6c33bf7123..26549901a6 100644
--- a/drivers/gles3/shaders/sky.glsl
+++ b/drivers/gles3/shaders/sky.glsl
@@ -209,14 +209,6 @@ void main() {
#endif
color = linear_to_srgb(color);
-#ifdef USE_BCS
- color = apply_bcs(color, bcs);
-#endif
-
-#ifdef USE_COLOR_CORRECTION
- color = apply_color_correction(color, color_correction);
-#endif
-
frag_color.rgb = color * luminance_multiplier;
frag_color.a = alpha;
diff --git a/drivers/gles3/shaders/tonemap.glsl b/drivers/gles3/shaders/tonemap.glsl
deleted file mode 100644
index 0b769e77f2..0000000000
--- a/drivers/gles3/shaders/tonemap.glsl
+++ /dev/null
@@ -1,333 +0,0 @@
-/* clang-format off */
-[vertex]
-
-#ifdef USE_GLES_OVER_GL
-#define lowp
-#define mediump
-#define highp
-#else
-precision highp float;
-precision highp int;
-#endif
-
-layout(location = 0) in vec2 vertex_attrib;
-/* clang-format on */
-layout(location = 4) in vec2 uv_in;
-
-out vec2 uv_interp;
-
-void main() {
- gl_Position = vec4(vertex_attrib, 0.0, 1.0);
-
- uv_interp = uv_in;
-}
-
-/* clang-format off */
-[fragment]
-
-#ifdef USE_GLES_OVER_GL
-#define lowp
-#define mediump
-#define highp
-#else
-#if defined(USE_HIGHP_PRECISION)
-precision highp float;
-precision highp int;
-#else
-precision mediump float;
-precision mediump int;
-#endif
-#endif
-
-in vec2 uv_interp;
-/* clang-format on */
-
-layout(location = 0) out vec4 frag_color;
-
-#ifdef USE_MULTIVIEW
-uniform highp sampler2DArray source; //texunit:0
-#else
-uniform highp sampler2D source; //texunit:0
-#endif
-
-#if defined(USE_GLOW_LEVEL1) || defined(USE_GLOW_LEVEL2) || defined(USE_GLOW_LEVEL3) || defined(USE_GLOW_LEVEL4) || defined(USE_GLOW_LEVEL5) || defined(USE_GLOW_LEVEL6) || defined(USE_GLOW_LEVEL7)
-#define USING_GLOW // only use glow when at least one glow level is selected
-
-#ifdef USE_MULTI_TEXTURE_GLOW
-uniform highp sampler2D source_glow1; //texunit:2
-uniform highp sampler2D source_glow2; //texunit:3
-uniform highp sampler2D source_glow3; //texunit:4
-uniform highp sampler2D source_glow4; //texunit:5
-uniform highp sampler2D source_glow5; //texunit:6
-uniform highp sampler2D source_glow6; //texunit:7
-#ifdef USE_GLOW_LEVEL7
-uniform highp sampler2D source_glow7; //texunit:8
-#endif
-#else
-uniform highp sampler2D source_glow; //texunit:2
-#endif
-uniform highp float glow_intensity;
-#endif
-
-#ifdef USE_BCS
-uniform vec3 bcs;
-#endif
-
-#ifdef USE_FXAA
-uniform vec2 pixel_size;
-#endif
-
-#ifdef USE_COLOR_CORRECTION
-uniform sampler2D color_correction; //texunit:1
-#endif
-
-#ifdef USE_GLOW_FILTER_BICUBIC
-// w0, w1, w2, and w3 are the four cubic B-spline basis functions
-float w0(float a) {
- return (1.0 / 6.0) * (a * (a * (-a + 3.0) - 3.0) + 1.0);
-}
-
-float w1(float a) {
- return (1.0 / 6.0) * (a * a * (3.0 * a - 6.0) + 4.0);
-}
-
-float w2(float a) {
- return (1.0 / 6.0) * (a * (a * (-3.0 * a + 3.0) + 3.0) + 1.0);
-}
-
-float w3(float a) {
- return (1.0 / 6.0) * (a * a * a);
-}
-
-// g0 and g1 are the two amplitude functions
-float g0(float a) {
- return w0(a) + w1(a);
-}
-
-float g1(float a) {
- return w2(a) + w3(a);
-}
-
-// h0 and h1 are the two offset functions
-float h0(float a) {
- return -1.0 + w1(a) / (w0(a) + w1(a));
-}
-
-float h1(float a) {
- return 1.0 + w3(a) / (w2(a) + w3(a));
-}
-
-uniform ivec2 glow_texture_size;
-
-vec4 texture_bicubic(sampler2D tex, vec2 uv, int p_lod) {
- float lod = float(p_lod);
- vec2 tex_size = vec2(glow_texture_size >> p_lod);
- vec2 texel_size = vec2(1.0) / tex_size;
-
- uv = uv * tex_size + vec2(0.5);
-
- vec2 iuv = floor(uv);
- vec2 fuv = fract(uv);
-
- float g0x = g0(fuv.x);
- float g1x = g1(fuv.x);
- float h0x = h0(fuv.x);
- float h1x = h1(fuv.x);
- float h0y = h0(fuv.y);
- float h1y = h1(fuv.y);
-
- vec2 p0 = (vec2(iuv.x + h0x, iuv.y + h0y) - vec2(0.5)) * texel_size;
- vec2 p1 = (vec2(iuv.x + h1x, iuv.y + h0y) - vec2(0.5)) * texel_size;
- vec2 p2 = (vec2(iuv.x + h0x, iuv.y + h1y) - vec2(0.5)) * texel_size;
- vec2 p3 = (vec2(iuv.x + h1x, iuv.y + h1y) - vec2(0.5)) * texel_size;
-
- return (g0(fuv.y) * (g0x * textureLod(tex, p0, lod) + g1x * textureLod(tex, p1, lod))) +
- (g1(fuv.y) * (g0x * textureLod(tex, p2, lod) + g1x * textureLod(tex, p3, lod)));
-}
-
-#define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) texture_bicubic(m_tex, m_uv, m_lod)
-#else //!USE_GLOW_FILTER_BICUBIC
-#define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) textureLod(m_tex, m_uv, float(m_lod))
-#endif //USE_GLOW_FILTER_BICUBIC
-
-vec3 apply_glow(vec3 color, vec3 glow) { // apply glow using the selected blending mode
-#ifdef USE_GLOW_REPLACE
- color = glow;
-#endif
-
-#ifdef USE_GLOW_SCREEN
- color = max((color + glow) - (color * glow), vec3(0.0));
-#endif
-
-#ifdef USE_GLOW_SOFTLIGHT
- glow = glow * vec3(0.5) + vec3(0.5);
-
- color.r = (glow.r <= 0.5) ? (color.r - (1.0 - 2.0 * glow.r) * color.r * (1.0 - color.r)) : (((glow.r > 0.5) && (color.r <= 0.25)) ? (color.r + (2.0 * glow.r - 1.0) * (4.0 * color.r * (4.0 * color.r + 1.0) * (color.r - 1.0) + 7.0 * color.r)) : (color.r + (2.0 * glow.r - 1.0) * (sqrt(color.r) - color.r)));
- color.g = (glow.g <= 0.5) ? (color.g - (1.0 - 2.0 * glow.g) * color.g * (1.0 - color.g)) : (((glow.g > 0.5) && (color.g <= 0.25)) ? (color.g + (2.0 * glow.g - 1.0) * (4.0 * color.g * (4.0 * color.g + 1.0) * (color.g - 1.0) + 7.0 * color.g)) : (color.g + (2.0 * glow.g - 1.0) * (sqrt(color.g) - color.g)));
- color.b = (glow.b <= 0.5) ? (color.b - (1.0 - 2.0 * glow.b) * color.b * (1.0 - color.b)) : (((glow.b > 0.5) && (color.b <= 0.25)) ? (color.b + (2.0 * glow.b - 1.0) * (4.0 * color.b * (4.0 * color.b + 1.0) * (color.b - 1.0) + 7.0 * color.b)) : (color.b + (2.0 * glow.b - 1.0) * (sqrt(color.b) - color.b)));
-#endif
-
-#if !defined(USE_GLOW_SCREEN) && !defined(USE_GLOW_SOFTLIGHT) && !defined(USE_GLOW_REPLACE) // no other selected -> additive
- color += glow;
-#endif
-
- return color;
-}
-
-vec3 apply_bcs(vec3 color, vec3 bcs) {
- color = mix(vec3(0.0), color, bcs.x);
- color = mix(vec3(0.5), color, bcs.y);
- color = mix(vec3(dot(vec3(1.0), color) * 0.33333), color, bcs.z);
-
- return color;
-}
-
-vec3 apply_color_correction(vec3 color, sampler2D correction_tex) {
- color.r = texture(correction_tex, vec2(color.r, 0.0)).r;
- color.g = texture(correction_tex, vec2(color.g, 0.0)).g;
- color.b = texture(correction_tex, vec2(color.b, 0.0)).b;
-
- return color;
-}
-
-vec3 apply_fxaa(vec3 color, vec2 uv_interp, vec2 pixel_size) {
- const float FXAA_REDUCE_MIN = (1.0 / 128.0);
- const float FXAA_REDUCE_MUL = (1.0 / 8.0);
- const float FXAA_SPAN_MAX = 8.0;
-
-#ifdef USE_MULTIVIEW
- vec3 rgbNW = textureLod(source, vec3(uv_interp + vec2(-1.0, -1.0) * pixel_size, ViewIndex), 0.0).xyz;
- vec3 rgbNE = textureLod(source, vec3(uv_interp + vec2(1.0, -1.0) * pixel_size, ViewIndex), 0.0).xyz;
- vec3 rgbSW = textureLod(source, vec3(uv_interp + vec2(-1.0, 1.0) * pixel_size, ViewIndex), 0.0).xyz;
- vec3 rgbSE = textureLod(source, vec3(uv_interp + vec2(1.0, 1.0) * pixel_size, ViewIndex), 0.0).xyz;
-#else
- vec3 rgbNW = textureLod(source, uv_interp + vec2(-1.0, -1.0) * pixel_size, 0.0).xyz;
- vec3 rgbNE = textureLod(source, uv_interp + vec2(1.0, -1.0) * pixel_size, 0.0).xyz;
- vec3 rgbSW = textureLod(source, uv_interp + vec2(-1.0, 1.0) * pixel_size, 0.0).xyz;
- vec3 rgbSE = textureLod(source, uv_interp + vec2(1.0, 1.0) * pixel_size, 0.0).xyz;
-#endif
- vec3 rgbM = color;
- vec3 luma = vec3(0.299, 0.587, 0.114);
- float lumaNW = dot(rgbNW, luma);
- float lumaNE = dot(rgbNE, luma);
- float lumaSW = dot(rgbSW, luma);
- float lumaSE = dot(rgbSE, luma);
- float lumaM = dot(rgbM, luma);
- float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
- float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
-
- vec2 dir;
- dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));
- dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));
-
- float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) *
- (0.25 * FXAA_REDUCE_MUL),
- FXAA_REDUCE_MIN);
-
- float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce);
- dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX),
- max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),
- dir * rcpDirMin)) *
- pixel_size;
-
-#ifdef USE_MULTIVIEW
- vec3 rgbA = 0.5 * (textureLod(source, vec3(uv_interp + dir * (1.0 / 3.0 - 0.5), ViewIndex), 0.0).xyz + textureLod(source, vec3(uv_interp + dir * (2.0 / 3.0 - 0.5), ViewIndex), 0.0).xyz);
- vec3 rgbB = rgbA * 0.5 + 0.25 * (textureLod(source, vec3(uv_interp + dir * -0.5, ViewIndex), 0.0).xyz + textureLod(source, vec3(uv_interp + dir * 0.5, ViewIndex), 0.0).xyz);
-#else
- vec3 rgbA = 0.5 * (textureLod(source, uv_interp + dir * (1.0 / 3.0 - 0.5), 0.0).xyz + textureLod(source, uv_interp + dir * (2.0 / 3.0 - 0.5), 0.0).xyz);
- vec3 rgbB = rgbA * 0.5 + 0.25 * (textureLod(source, uv_interp + dir * -0.5, 0.0).xyz + textureLod(source, uv_interp + dir * 0.5, 0.0).xyz);
-#endif
-
- float lumaB = dot(rgbB, luma);
- if ((lumaB < lumaMin) || (lumaB > lumaMax)) {
- return rgbA;
- } else {
- return rgbB;
- }
-}
-
-void main() {
-#ifdef USE_MULTIVIEW
- vec4 color = textureLod(source, vec3(uv_interp, ViewIndex), 0.0);
-#else
- vec4 color = textureLod(source, uv_interp, 0.0);
-#endif
-
-#ifdef USE_FXAA
- color.rgb = apply_fxaa(color.rgb, uv_interp, pixel_size);
-#endif
-
- // Glow
-
-#ifdef USING_GLOW
- vec3 glow = vec3(0.0);
-#ifdef USE_MULTI_TEXTURE_GLOW
-#ifdef USE_GLOW_LEVEL1
- glow += GLOW_TEXTURE_SAMPLE(source_glow1, uv_interp, 0).rgb;
-#ifdef USE_GLOW_LEVEL2
- glow += GLOW_TEXTURE_SAMPLE(source_glow2, uv_interp, 0).rgb;
-#ifdef USE_GLOW_LEVEL3
- glow += GLOW_TEXTURE_SAMPLE(source_glow3, uv_interp, 0).rgb;
-#ifdef USE_GLOW_LEVEL4
- glow += GLOW_TEXTURE_SAMPLE(source_glow4, uv_interp, 0).rgb;
-#ifdef USE_GLOW_LEVEL5
- glow += GLOW_TEXTURE_SAMPLE(source_glow5, uv_interp, 0).rgb;
-#ifdef USE_GLOW_LEVEL6
- glow += GLOW_TEXTURE_SAMPLE(source_glow6, uv_interp, 0).rgb;
-#ifdef USE_GLOW_LEVEL7
- glow += GLOW_TEXTURE_SAMPLE(source_glow7, uv_interp, 0).rgb;
-#endif
-#endif
-#endif
-#endif
-#endif
-#endif
-#endif
-
-#else
-
-#ifdef USE_GLOW_LEVEL1
- glow += GLOW_TEXTURE_SAMPLE(source_glow, uv_interp, 1).rgb;
-#endif
-
-#ifdef USE_GLOW_LEVEL2
- glow += GLOW_TEXTURE_SAMPLE(source_glow, uv_interp, 2).rgb;
-#endif
-
-#ifdef USE_GLOW_LEVEL3
- glow += GLOW_TEXTURE_SAMPLE(source_glow, uv_interp, 3).rgb;
-#endif
-
-#ifdef USE_GLOW_LEVEL4
- glow += GLOW_TEXTURE_SAMPLE(source_glow, uv_interp, 4).rgb;
-#endif
-
-#ifdef USE_GLOW_LEVEL5
- glow += GLOW_TEXTURE_SAMPLE(source_glow, uv_interp, 5).rgb;
-#endif
-
-#ifdef USE_GLOW_LEVEL6
- glow += GLOW_TEXTURE_SAMPLE(source_glow, uv_interp, 6).rgb;
-#endif
-
-#ifdef USE_GLOW_LEVEL7
- glow += GLOW_TEXTURE_SAMPLE(source_glow, uv_interp, 7).rgb;
-#endif
-#endif //USE_MULTI_TEXTURE_GLOW
-
- glow *= glow_intensity;
- color.rgb = apply_glow(color.rgb, glow);
-#endif
-
- // Additional effects
-
-#ifdef USE_BCS
- color.rgb = apply_bcs(color.rgb, bcs);
-#endif
-
-#ifdef USE_COLOR_CORRECTION
- color.rgb = apply_color_correction(color.rgb, color_correction);
-#endif
-
- frag_color = color;
-}
diff --git a/drivers/gles3/shaders/tonemap_inc.glsl b/drivers/gles3/shaders/tonemap_inc.glsl
index f8f12760ec..fb915aeb38 100644
--- a/drivers/gles3/shaders/tonemap_inc.glsl
+++ b/drivers/gles3/shaders/tonemap_inc.glsl
@@ -1,43 +1,31 @@
-#ifdef USE_BCS
-uniform vec3 bcs;
-#endif
-
-#ifdef USE_COLOR_CORRECTION
-#ifdef USE_1D_LUT
-uniform sampler2D source_color_correction; //texunit:-1
-#else
-uniform sampler3D source_color_correction; //texunit:-1
-#endif
-#endif
-
layout(std140) uniform TonemapData { //ubo:0
float exposure;
float white;
int tonemapper;
int pad;
-};
-vec3 apply_bcs(vec3 color, vec3 bcs) {
- color = mix(vec3(0.0), color, bcs.x);
- color = mix(vec3(0.5), color, bcs.y);
- color = mix(vec3(dot(vec3(1.0), color) * 0.33333), color, bcs.z);
+ int pad2;
+ float brightness;
+ float contrast;
+ float saturation;
+};
- return color;
-}
-#ifdef USE_COLOR_CORRECTION
-#ifdef USE_1D_LUT
-vec3 apply_color_correction(vec3 color) {
- color.r = texture(source_color_correction, vec2(color.r, 0.0f)).r;
- color.g = texture(source_color_correction, vec2(color.g, 0.0f)).g;
- color.b = texture(source_color_correction, vec2(color.b, 0.0f)).b;
- return color;
+// This expects 0-1 range input.
+vec3 linear_to_srgb(vec3 color) {
+ //color = clamp(color, vec3(0.0), vec3(1.0));
+ //const vec3 a = vec3(0.055f);
+ //return mix((vec3(1.0f) + a) * pow(color.rgb, vec3(1.0f / 2.4f)) - a, 12.92f * color.rgb, lessThan(color.rgb, vec3(0.0031308f)));
+ // Approximation from http://chilliant.blogspot.com/2012/08/srgb-approximations-for-hlsl.html
+ return max(vec3(1.055) * pow(color, vec3(0.416666667)) - vec3(0.055), vec3(0.0));
}
-#else
-vec3 apply_color_correction(vec3 color) {
- return textureLod(source_color_correction, color, 0.0).rgb;
+
+// This expects 0-1 range input, outside that range it behaves poorly.
+vec3 srgb_to_linear(vec3 color) {
+ // Approximation from http://chilliant.blogspot.com/2012/08/srgb-approximations-for-hlsl.html
+ return color * (color * (color * 0.305306011 + 0.682171111) + 0.012522878);
}
-#endif
-#endif
+
+#ifdef APPLY_TONEMAPPING
vec3 tonemap_filmic(vec3 color, float p_white) {
// exposure bias: input scale (color *= bias, white *= bias) to make the brightness consistent with other tonemappers
@@ -92,21 +80,6 @@ vec3 tonemap_reinhard(vec3 color, float p_white) {
return (p_white * color + color) / (color * p_white + p_white);
}
-// This expects 0-1 range input.
-vec3 linear_to_srgb(vec3 color) {
- //color = clamp(color, vec3(0.0), vec3(1.0));
- //const vec3 a = vec3(0.055f);
- //return mix((vec3(1.0f) + a) * pow(color.rgb, vec3(1.0f / 2.4f)) - a, 12.92f * color.rgb, lessThan(color.rgb, vec3(0.0031308f)));
- // Approximation from http://chilliant.blogspot.com/2012/08/srgb-approximations-for-hlsl.html
- return max(vec3(1.055) * pow(color, vec3(0.416666667)) - vec3(0.055), vec3(0.0));
-}
-
-// This expects 0-1 range input, outside that range it behaves poorly.
-vec3 srgb_to_linear(vec3 color) {
- // Approximation from http://chilliant.blogspot.com/2012/08/srgb-approximations-for-hlsl.html
- return color * (color * (color * 0.305306011 + 0.682171111) + 0.012522878);
-}
-
#define TONEMAPPER_LINEAR 0
#define TONEMAPPER_REINHARD 1
#define TONEMAPPER_FILMIC 2
@@ -125,3 +98,5 @@ vec3 apply_tonemapping(vec3 color, float p_white) { // inputs are LINEAR, always
return tonemap_aces(max(vec3(0.0f), color), p_white);
}
}
+
+#endif // APPLY_TONEMAPPING
diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp
index 62d22dac4d..996c205042 100644
--- a/drivers/gles3/storage/material_storage.cpp
+++ b/drivers/gles3/storage/material_storage.cpp
@@ -1243,6 +1243,7 @@ MaterialStorage::MaterialStorage() {
actions.renames["NORMAL_MAP_DEPTH"] = "normal_map_depth";
actions.renames["ALBEDO"] = "albedo";
actions.renames["ALPHA"] = "alpha";
+ actions.renames["PREMUL_ALPHA_FACTOR"] = "premul_alpha";
actions.renames["METALLIC"] = "metallic";
actions.renames["SPECULAR"] = "specular";
actions.renames["ROUGHNESS"] = "roughness";
@@ -1327,6 +1328,7 @@ MaterialStorage::MaterialStorage() {
actions.usage_defines["ALPHA_HASH_SCALE"] = "#define ALPHA_HASH_USED\n";
actions.usage_defines["ALPHA_ANTIALIASING_EDGE"] = "#define ALPHA_ANTIALIASING_EDGE_USED\n";
actions.usage_defines["ALPHA_TEXTURE_COORDINATE"] = "@ALPHA_ANTIALIASING_EDGE";
+ actions.usage_defines["PREMULT_ALPHA_FACTOR"] = "#define PREMULT_ALPHA_USED";
actions.usage_defines["SSS_STRENGTH"] = "#define ENABLE_SSS\n";
actions.usage_defines["SSS_TRANSMITTANCE_DEPTH"] = "#define ENABLE_TRANSMITTANCE\n";
@@ -1964,13 +1966,9 @@ void MaterialStorage::global_shader_parameters_load_settings(bool p_load_texture
Variant value = d["value"];
if (gvtype >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) {
- //textire
- if (!p_load_textures) {
- continue;
- }
-
String path = value;
- if (path.is_empty()) {
+ // Don't load the textures, but still add the parameter so shaders compile correctly while loading.
+ if (!p_load_textures || path.is_empty()) {
value = RID();
} else {
Ref<Resource> resource = ResourceLoader::load(path);
@@ -2908,6 +2906,7 @@ void SceneShaderData::set_code(const String &p_code) {
actions.render_mode_values["blend_mix"] = Pair<int *, int>(&blend_modei, BLEND_MODE_MIX);
actions.render_mode_values["blend_sub"] = Pair<int *, int>(&blend_modei, BLEND_MODE_SUB);
actions.render_mode_values["blend_mul"] = Pair<int *, int>(&blend_modei, BLEND_MODE_MUL);
+ actions.render_mode_values["blend_premul_alpha"] = Pair<int *, int>(&blend_modei, BLEND_MODE_PREMULT_ALPHA);
actions.render_mode_values["alpha_to_coverage"] = Pair<int *, int>(&alpha_antialiasing_modei, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE);
actions.render_mode_values["alpha_to_coverage_and_one"] = Pair<int *, int>(&alpha_antialiasing_modei, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE);
diff --git a/drivers/gles3/storage/material_storage.h b/drivers/gles3/storage/material_storage.h
index 02aecf33d6..392ebcc570 100644
--- a/drivers/gles3/storage/material_storage.h
+++ b/drivers/gles3/storage/material_storage.h
@@ -248,6 +248,7 @@ struct SceneShaderData : public ShaderData {
BLEND_MODE_ADD,
BLEND_MODE_SUB,
BLEND_MODE_MUL,
+ BLEND_MODE_PREMULT_ALPHA,
BLEND_MODE_ALPHA_TO_COVERAGE
};
diff --git a/drivers/gles3/storage/render_scene_buffers_gles3.cpp b/drivers/gles3/storage/render_scene_buffers_gles3.cpp
index 6803c92dc9..cb194933ed 100644
--- a/drivers/gles3/storage/render_scene_buffers_gles3.cpp
+++ b/drivers/gles3/storage/render_scene_buffers_gles3.cpp
@@ -577,8 +577,7 @@ void RenderSceneBuffersGLES3::check_glow_buffers() {
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
Size2i level_size = internal_size;
for (int i = 0; i < 4; i++) {
- level_size.x = MAX(level_size.x >> 1, 4);
- level_size.y = MAX(level_size.y >> 1, 4);
+ level_size = Size2i(level_size.x >> 1, level_size.y >> 1).maxi(4);
glow.levels[i].size = level_size;
diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp
index 6f32e4d49d..373df8d8de 100644
--- a/drivers/gles3/storage/texture_storage.cpp
+++ b/drivers/gles3/storage/texture_storage.cpp
@@ -2812,7 +2812,7 @@ void TextureStorage::_render_target_allocate_sdf(RenderTarget *rt) {
}
rt->process_size = size * scale / 100;
- rt->process_size = rt->process_size.max(Size2i(1, 1));
+ rt->process_size = rt->process_size.maxi(1);
glGenTextures(2, rt->sdf_texture_process);
glBindTexture(GL_TEXTURE_2D, rt->sdf_texture_process[0]);
diff --git a/drivers/gles3/storage/utilities.cpp b/drivers/gles3/storage/utilities.cpp
index 7e2e3dfa2b..356dc06733 100644
--- a/drivers/gles3/storage/utilities.cpp
+++ b/drivers/gles3/storage/utilities.cpp
@@ -299,7 +299,7 @@ void Utilities::visibility_notifier_call(RID p_notifier, bool p_enter, bool p_de
ERR_FAIL_NULL(vn);
if (p_enter) {
- if (!vn->enter_callback.is_null()) {
+ if (vn->enter_callback.is_valid()) {
if (p_deferred) {
vn->enter_callback.call_deferred();
} else {
@@ -307,7 +307,7 @@ void Utilities::visibility_notifier_call(RID p_notifier, bool p_enter, bool p_de
}
}
} else {
- if (!vn->exit_callback.is_null()) {
+ if (vn->exit_callback.is_valid()) {
if (p_deferred) {
vn->exit_callback.call_deferred();
} else {
diff --git a/drivers/png/SCsub b/drivers/png/SCsub
index dd4777a19b..e38f3c4760 100644
--- a/drivers/png/SCsub
+++ b/drivers/png/SCsub
@@ -39,7 +39,7 @@ if env["builtin_libpng"]:
if env["arch"].startswith("arm"):
if env.msvc: # Can't compile assembly files with MSVC.
- env_thirdparty.Append(CPPDEFINES=[("PNG_ARM_NEON_OPT"), 0])
+ env_thirdparty.Append(CPPDEFINES=[("PNG_ARM_NEON_OPT", 0)])
else:
env_neon = env_thirdparty.Clone()
if "S_compiler" in env:
diff --git a/drivers/vulkan/rendering_device_driver_vulkan.cpp b/drivers/vulkan/rendering_device_driver_vulkan.cpp
index 1906d168fe..803555cb07 100644
--- a/drivers/vulkan/rendering_device_driver_vulkan.cpp
+++ b/drivers/vulkan/rendering_device_driver_vulkan.cpp
@@ -1008,7 +1008,7 @@ VkResult RenderingDeviceDriverVulkan::_create_render_pass(VkDevice p_device, con
const uint32_t depth_attachment_index = vector_base_index + 3;
_convert_subpass_attachments(p_create_info->pSubpasses[i].pInputAttachments, p_create_info->pSubpasses[i].inputAttachmentCount, subpasses_attachments[input_attachments_index]);
_convert_subpass_attachments(p_create_info->pSubpasses[i].pColorAttachments, p_create_info->pSubpasses[i].colorAttachmentCount, subpasses_attachments[color_attachments_index]);
- _convert_subpass_attachments(p_create_info->pSubpasses[i].pResolveAttachments, p_create_info->pSubpasses[i].colorAttachmentCount, subpasses_attachments[resolve_attachments_index]);
+ _convert_subpass_attachments(p_create_info->pSubpasses[i].pResolveAttachments, (p_create_info->pSubpasses[i].pResolveAttachments != nullptr) ? p_create_info->pSubpasses[i].colorAttachmentCount : 0, subpasses_attachments[resolve_attachments_index]);
_convert_subpass_attachments(p_create_info->pSubpasses[i].pDepthStencilAttachment, (p_create_info->pSubpasses[i].pDepthStencilAttachment != nullptr) ? 1 : 0, subpasses_attachments[depth_attachment_index]);
// Ignores sType and pNext from the subpass.
diff --git a/drivers/windows/dir_access_windows.cpp b/drivers/windows/dir_access_windows.cpp
index 43dd62cdf6..63ba6a6c96 100644
--- a/drivers/windows/dir_access_windows.cpp
+++ b/drivers/windows/dir_access_windows.cpp
@@ -396,6 +396,66 @@ bool DirAccessWindows::is_case_sensitive(const String &p_path) const {
}
}
+bool DirAccessWindows::is_link(String p_file) {
+ String f = p_file;
+
+ if (!f.is_absolute_path()) {
+ f = get_current_dir().path_join(f);
+ }
+ f = fix_path(f);
+
+ DWORD attr = GetFileAttributesW((LPCWSTR)(f.utf16().get_data()));
+ if (attr == INVALID_FILE_ATTRIBUTES) {
+ return false;
+ }
+
+ return (attr & FILE_ATTRIBUTE_REPARSE_POINT);
+}
+
+String DirAccessWindows::read_link(String p_file) {
+ String f = p_file;
+
+ if (!f.is_absolute_path()) {
+ f = get_current_dir().path_join(f);
+ }
+ f = fix_path(f);
+
+ HANDLE hfile = CreateFileW((LPCWSTR)(f.utf16().get_data()), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
+ if (hfile == INVALID_HANDLE_VALUE) {
+ return f;
+ }
+
+ DWORD ret = GetFinalPathNameByHandleW(hfile, nullptr, 0, VOLUME_NAME_DOS | FILE_NAME_NORMALIZED);
+ if (ret == 0) {
+ return f;
+ }
+ Char16String cs;
+ cs.resize(ret + 1);
+ GetFinalPathNameByHandleW(hfile, (LPWSTR)cs.ptrw(), ret, VOLUME_NAME_DOS | FILE_NAME_NORMALIZED);
+ CloseHandle(hfile);
+
+ return String::utf16((const char16_t *)cs.ptr(), ret).trim_prefix(R"(\\?\)");
+}
+
+Error DirAccessWindows::create_link(String p_source, String p_target) {
+ if (p_target.is_relative_path()) {
+ p_target = get_current_dir().path_join(p_target);
+ }
+
+ p_source = fix_path(p_source);
+ p_target = fix_path(p_target);
+
+ DWORD file_attr = GetFileAttributesW((LPCWSTR)(p_source.utf16().get_data()));
+ bool is_dir = (file_attr & FILE_ATTRIBUTE_DIRECTORY);
+
+ DWORD flags = ((is_dir) ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0) | SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
+ if (CreateSymbolicLinkW((LPCWSTR)p_target.utf16().get_data(), (LPCWSTR)p_source.utf16().get_data(), flags) != 0) {
+ return OK;
+ } else {
+ return FAILED;
+ }
+}
+
DirAccessWindows::DirAccessWindows() {
p = memnew(DirAccessWindowsPrivate);
p->h = INVALID_HANDLE_VALUE;
diff --git a/drivers/windows/dir_access_windows.h b/drivers/windows/dir_access_windows.h
index 576ba18d9a..46755cbf33 100644
--- a/drivers/windows/dir_access_windows.h
+++ b/drivers/windows/dir_access_windows.h
@@ -77,9 +77,9 @@ public:
virtual Error rename(String p_path, String p_new_path) override;
virtual Error remove(String p_path) override;
- virtual bool is_link(String p_file) override { return false; };
- virtual String read_link(String p_file) override { return p_file; };
- virtual Error create_link(String p_source, String p_target) override { return FAILED; };
+ virtual bool is_link(String p_file) override;
+ virtual String read_link(String p_file) override;
+ virtual Error create_link(String p_source, String p_target) override;
uint64_t get_space_left() override;
diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp
index 726e0fdc5a..9885d9d7ee 100644
--- a/drivers/windows/file_access_windows.cpp
+++ b/drivers/windows/file_access_windows.cpp
@@ -32,6 +32,7 @@
#include "file_access_windows.h"
+#include "core/config/project_settings.h"
#include "core/os/os.h"
#include "core/string/print_string.h"
@@ -121,19 +122,63 @@ Error FileAccessWindows::open_internal(const String &p_path, int p_mode_flags) {
// Windows is case insensitive, but all other platforms are sensitive to it
// To ease cross-platform development, we issue a warning if users try to access
// a file using the wrong case (which *works* on Windows, but won't on other
- // platforms).
- if (p_mode_flags == READ) {
- WIN32_FIND_DATAW d;
- HANDLE fnd = FindFirstFileW((LPCWSTR)(path.utf16().get_data()), &d);
- if (fnd != INVALID_HANDLE_VALUE) {
- String fname = String::utf16((const char16_t *)(d.cFileName));
- if (!fname.is_empty()) {
- String base_file = path.get_file();
- if (base_file != fname && base_file.findn(fname) == 0) {
- WARN_PRINT("Case mismatch opening requested file '" + base_file + "', stored as '" + fname + "' in the filesystem. This file will not open when exported to other case-sensitive platforms.");
+ // platforms), we only check for relative paths, or paths in res:// or user://,
+ // other paths aren't likely to be portable anyway.
+ if (p_mode_flags == READ && (p_path.is_relative_path() || get_access_type() != ACCESS_FILESYSTEM)) {
+ String base_path = path;
+ String working_path;
+ String proper_path;
+
+ if (get_access_type() == ACCESS_RESOURCES) {
+ if (ProjectSettings::get_singleton()) {
+ working_path = ProjectSettings::get_singleton()->get_resource_path();
+ if (!working_path.is_empty()) {
+ base_path = working_path.path_to_file(base_path);
}
}
+ proper_path = "res://";
+ } else if (get_access_type() == ACCESS_USERDATA) {
+ working_path = OS::get_singleton()->get_user_data_dir();
+ if (!working_path.is_empty()) {
+ base_path = working_path.path_to_file(base_path);
+ }
+ proper_path = "user://";
+ }
+
+ WIN32_FIND_DATAW d;
+ Vector<String> parts = base_path.split("/");
+
+ bool mismatch = false;
+
+ for (const String &part : parts) {
+ working_path = working_path.path_join(part);
+
+ // Skip if relative.
+ if (part == "." || part == "..") {
+ proper_path = proper_path.path_join(part);
+ continue;
+ }
+
+ HANDLE fnd = FindFirstFileW((LPCWSTR)(working_path.utf16().get_data()), &d);
+
+ if (fnd == INVALID_HANDLE_VALUE) {
+ mismatch = false;
+ break;
+ }
+
+ const String fname = String::utf16((const char16_t *)(d.cFileName));
+
FindClose(fnd);
+
+ if (!mismatch) {
+ mismatch = (part != fname && part.findn(fname) == 0);
+ }
+
+ proper_path = proper_path.path_join(fname);
+ }
+
+ if (mismatch) {
+ WARN_PRINT("Case mismatch opening requested file '" + p_path + "', stored as '" + proper_path + "' in the filesystem. This file will not open when exported to other case-sensitive platforms.");
}
}
#endif