|
@@ -657,6 +657,7 @@ layout(constant_id = 9) const uint sc_directional_penumbra_shadow_samples = 4;
|
|
|
layout(constant_id = 10) const bool sc_decal_use_mipmaps = true;
|
|
|
layout(constant_id = 11) const bool sc_projector_use_mipmaps = true;
|
|
|
layout(constant_id = 12) const bool sc_use_depth_fog = false;
|
|
|
+layout(constant_id = 13) const bool sc_use_lightmap_bicubic_filter = false;
|
|
|
|
|
|
// not used in clustered renderer but we share some code with the mobile renderer that requires this.
|
|
|
const float sc_luminance_multiplier = 1.0;
|
|
@@ -701,6 +702,67 @@ layout(location = 9) in float dp_clip;
|
|
|
|
|
|
layout(location = 10) in flat uint instance_index_interp;
|
|
|
|
|
|
+#ifdef USE_LIGHTMAP
|
|
|
+// 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));
|
|
|
+}
|
|
|
+
|
|
|
+vec4 textureArray_bicubic(texture2DArray tex, vec3 uv, vec2 texture_size) {
|
|
|
+ vec2 texel_size = vec2(1.0) / texture_size;
|
|
|
+
|
|
|
+ uv.xy = uv.xy * texture_size + vec2(0.5);
|
|
|
+
|
|
|
+ vec2 iuv = floor(uv.xy);
|
|
|
+ vec2 fuv = fract(uv.xy);
|
|
|
+
|
|
|
+ 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 * texture(sampler2DArray(tex, SAMPLER_LINEAR_CLAMP), vec3(p0, uv.z)) + g1x * texture(sampler2DArray(tex, SAMPLER_LINEAR_CLAMP), vec3(p1, uv.z)))) +
|
|
|
+ (g1(fuv.y) * (g0x * texture(sampler2DArray(tex, SAMPLER_LINEAR_CLAMP), vec3(p2, uv.z)) + g1x * texture(sampler2DArray(tex, SAMPLER_LINEAR_CLAMP), vec3(p3, uv.z))));
|
|
|
+}
|
|
|
+#endif //USE_LIGHTMAP
|
|
|
+
|
|
|
#ifdef USE_MULTIVIEW
|
|
|
#ifdef has_VK_KHR_multiview
|
|
|
#define ViewIndex gl_ViewIndex
|
|
@@ -1449,10 +1511,23 @@ void fragment_shader(in SceneData scene_data) {
|
|
|
|
|
|
if (uses_sh) {
|
|
|
uvw.z *= 4.0; //SH textures use 4 times more data
|
|
|
- vec3 lm_light_l0 = textureLod(sampler2DArray(lightmap_textures[ofs], SAMPLER_LINEAR_CLAMP), uvw + vec3(0.0, 0.0, 0.0), 0.0).rgb;
|
|
|
- vec3 lm_light_l1n1 = textureLod(sampler2DArray(lightmap_textures[ofs], SAMPLER_LINEAR_CLAMP), uvw + vec3(0.0, 0.0, 1.0), 0.0).rgb;
|
|
|
- vec3 lm_light_l1_0 = textureLod(sampler2DArray(lightmap_textures[ofs], SAMPLER_LINEAR_CLAMP), uvw + vec3(0.0, 0.0, 2.0), 0.0).rgb;
|
|
|
- vec3 lm_light_l1p1 = textureLod(sampler2DArray(lightmap_textures[ofs], SAMPLER_LINEAR_CLAMP), uvw + vec3(0.0, 0.0, 3.0), 0.0).rgb;
|
|
|
+
|
|
|
+ vec3 lm_light_l0;
|
|
|
+ vec3 lm_light_l1n1;
|
|
|
+ vec3 lm_light_l1_0;
|
|
|
+ vec3 lm_light_l1p1;
|
|
|
+
|
|
|
+ if (sc_use_lightmap_bicubic_filter) {
|
|
|
+ lm_light_l0 = textureArray_bicubic(lightmap_textures[ofs], uvw + vec3(0.0, 0.0, 0.0), lightmaps.data[ofs].light_texture_size).rgb;
|
|
|
+ lm_light_l1n1 = textureArray_bicubic(lightmap_textures[ofs], uvw + vec3(0.0, 0.0, 1.0), lightmaps.data[ofs].light_texture_size).rgb;
|
|
|
+ lm_light_l1_0 = textureArray_bicubic(lightmap_textures[ofs], uvw + vec3(0.0, 0.0, 2.0), lightmaps.data[ofs].light_texture_size).rgb;
|
|
|
+ lm_light_l1p1 = textureArray_bicubic(lightmap_textures[ofs], uvw + vec3(0.0, 0.0, 3.0), lightmaps.data[ofs].light_texture_size).rgb;
|
|
|
+ } else {
|
|
|
+ lm_light_l0 = textureLod(sampler2DArray(lightmap_textures[ofs], SAMPLER_LINEAR_CLAMP), uvw + vec3(0.0, 0.0, 0.0), 0.0).rgb;
|
|
|
+ lm_light_l1n1 = textureLod(sampler2DArray(lightmap_textures[ofs], SAMPLER_LINEAR_CLAMP), uvw + vec3(0.0, 0.0, 1.0), 0.0).rgb;
|
|
|
+ lm_light_l1_0 = textureLod(sampler2DArray(lightmap_textures[ofs], SAMPLER_LINEAR_CLAMP), uvw + vec3(0.0, 0.0, 2.0), 0.0).rgb;
|
|
|
+ lm_light_l1p1 = textureLod(sampler2DArray(lightmap_textures[ofs], SAMPLER_LINEAR_CLAMP), uvw + vec3(0.0, 0.0, 3.0), 0.0).rgb;
|
|
|
+ }
|
|
|
|
|
|
vec3 n = normalize(lightmaps.data[ofs].normal_xform * normal);
|
|
|
float en = lightmaps.data[ofs].exposure_normalization;
|
|
@@ -1469,7 +1544,11 @@ void fragment_shader(in SceneData scene_data) {
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
- ambient_light += textureLod(sampler2DArray(lightmap_textures[ofs], SAMPLER_LINEAR_CLAMP), uvw, 0.0).rgb * lightmaps.data[ofs].exposure_normalization;
|
|
|
+ if (sc_use_lightmap_bicubic_filter) {
|
|
|
+ ambient_light += textureArray_bicubic(lightmap_textures[ofs], uvw, lightmaps.data[ofs].light_texture_size).rgb * lightmaps.data[ofs].exposure_normalization;
|
|
|
+ } else {
|
|
|
+ ambient_light += textureLod(sampler2DArray(lightmap_textures[ofs], SAMPLER_LINEAR_CLAMP), uvw, 0.0).rgb * lightmaps.data[ofs].exposure_normalization;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
#else
|