Merge pull request #89919 from BlueCube3310/bicubic-lightmap
Implement bicubic sampling for lightmaps
This commit is contained in:
commit
8acd82f70e
|
@ -2604,6 +2604,10 @@
|
||||||
- Intel GPUs: SYCL libraries
|
- Intel GPUs: SYCL libraries
|
||||||
If no GPU acceleration is configured on the system, multi-threaded CPU-based denoising will be performed instead. This CPU-based denoising is significantly slower than the JNLM denoiser in most cases.
|
If no GPU acceleration is configured on the system, multi-threaded CPU-based denoising will be performed instead. This CPU-based denoising is significantly slower than the JNLM denoiser in most cases.
|
||||||
</member>
|
</member>
|
||||||
|
<member name="rendering/lightmapping/lightmap_gi/use_bicubic_filter" type="bool" setter="" getter="" default="true">
|
||||||
|
If [code]true[/code], applies a bicubic filter during lightmap sampling. This makes lightmaps look much smoother, at a moderate performance cost.
|
||||||
|
[b]Note:[/b] The bicubic filter exaggerates the 'bleeding' effect that occurs when a lightmap's resolution is low enough.
|
||||||
|
</member>
|
||||||
<member name="rendering/lightmapping/primitive_meshes/texel_size" type="float" setter="" getter="" default="0.2">
|
<member name="rendering/lightmapping/primitive_meshes/texel_size" type="float" setter="" getter="" default="0.2">
|
||||||
The texel_size that is used to calculate the [member Mesh.lightmap_size_hint] on [PrimitiveMesh] resources if [member PrimitiveMesh.add_uv2] is enabled.
|
The texel_size that is used to calculate the [member Mesh.lightmap_size_hint] on [PrimitiveMesh] resources if [member PrimitiveMesh.add_uv2] is enabled.
|
||||||
</member>
|
</member>
|
||||||
|
|
|
@ -2207,6 +2207,13 @@
|
||||||
Set the textures on the given [param lightmap] GI instance to the texture array pointed to by the [param light] RID. If the lightmap texture was baked with [member LightmapGI.directional] set to [code]true[/code], then [param uses_sh] must also be [code]true[/code].
|
Set the textures on the given [param lightmap] GI instance to the texture array pointed to by the [param light] RID. If the lightmap texture was baked with [member LightmapGI.directional] set to [code]true[/code], then [param uses_sh] must also be [code]true[/code].
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
<method name="lightmaps_set_bicubic_filter">
|
||||||
|
<return type="void" />
|
||||||
|
<param index="0" name="enable" type="bool" />
|
||||||
|
<description>
|
||||||
|
Toggles whether a bicubic filter should be used when lightmaps are sampled. This smoothens their appearance at a performance cost.
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
<method name="make_sphere_mesh">
|
<method name="make_sphere_mesh">
|
||||||
<return type="RID" />
|
<return type="RID" />
|
||||||
<param index="0" name="latitudes" type="int" />
|
<param index="0" name="latitudes" type="int" />
|
||||||
|
|
|
@ -3210,6 +3210,10 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
|
||||||
if (lm->uses_spherical_harmonics) {
|
if (lm->uses_spherical_harmonics) {
|
||||||
spec_constants |= SceneShaderGLES3::USE_SH_LIGHTMAP;
|
spec_constants |= SceneShaderGLES3::USE_SH_LIGHTMAP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lightmap_bicubic_upscale) {
|
||||||
|
spec_constants |= SceneShaderGLES3::LIGHTMAP_BICUBIC_FILTER;
|
||||||
|
}
|
||||||
} else if (inst->lightmap_sh) {
|
} else if (inst->lightmap_sh) {
|
||||||
spec_constants |= SceneShaderGLES3::USE_LIGHTMAP_CAPTURE;
|
spec_constants |= SceneShaderGLES3::USE_LIGHTMAP_CAPTURE;
|
||||||
} else {
|
} else {
|
||||||
|
@ -3352,6 +3356,11 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
|
||||||
Vector4 uv_scale(inst->lightmap_uv_scale.position.x, inst->lightmap_uv_scale.position.y, inst->lightmap_uv_scale.size.x, inst->lightmap_uv_scale.size.y);
|
Vector4 uv_scale(inst->lightmap_uv_scale.position.x, inst->lightmap_uv_scale.position.y, inst->lightmap_uv_scale.size.x, inst->lightmap_uv_scale.size.y);
|
||||||
material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::LIGHTMAP_UV_SCALE, uv_scale, shader->version, instance_variant, spec_constants);
|
material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::LIGHTMAP_UV_SCALE, uv_scale, shader->version, instance_variant, spec_constants);
|
||||||
|
|
||||||
|
if (lightmap_bicubic_upscale) {
|
||||||
|
Vector2 light_texture_size(lm->light_texture_size.x, lm->light_texture_size.y);
|
||||||
|
material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::LIGHTMAP_TEXTURE_SIZE, light_texture_size, shader->version, instance_variant, spec_constants);
|
||||||
|
}
|
||||||
|
|
||||||
float exposure_normalization = 1.0;
|
float exposure_normalization = 1.0;
|
||||||
if (p_render_data->camera_attributes.is_valid()) {
|
if (p_render_data->camera_attributes.is_valid()) {
|
||||||
float enf = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
|
float enf = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
|
||||||
|
@ -4047,6 +4056,10 @@ void RasterizerSceneGLES3::decals_set_filter(RS::DecalFilter p_filter) {
|
||||||
void RasterizerSceneGLES3::light_projectors_set_filter(RS::LightProjectorFilter p_filter) {
|
void RasterizerSceneGLES3::light_projectors_set_filter(RS::LightProjectorFilter p_filter) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RasterizerSceneGLES3::lightmaps_set_bicubic_filter(bool p_enable) {
|
||||||
|
lightmap_bicubic_upscale = p_enable;
|
||||||
|
}
|
||||||
|
|
||||||
RasterizerSceneGLES3::RasterizerSceneGLES3() {
|
RasterizerSceneGLES3::RasterizerSceneGLES3() {
|
||||||
singleton = this;
|
singleton = this;
|
||||||
|
|
||||||
|
@ -4060,6 +4073,7 @@ RasterizerSceneGLES3::RasterizerSceneGLES3() {
|
||||||
|
|
||||||
positional_soft_shadow_filter_set_quality((RS::ShadowQuality)(int)GLOBAL_GET("rendering/lights_and_shadows/positional_shadow/soft_shadow_filter_quality"));
|
positional_soft_shadow_filter_set_quality((RS::ShadowQuality)(int)GLOBAL_GET("rendering/lights_and_shadows/positional_shadow/soft_shadow_filter_quality"));
|
||||||
directional_soft_shadow_filter_set_quality((RS::ShadowQuality)(int)GLOBAL_GET("rendering/lights_and_shadows/directional_shadow/soft_shadow_filter_quality"));
|
directional_soft_shadow_filter_set_quality((RS::ShadowQuality)(int)GLOBAL_GET("rendering/lights_and_shadows/directional_shadow/soft_shadow_filter_quality"));
|
||||||
|
lightmaps_set_bicubic_filter(GLOBAL_GET("rendering/lightmapping/lightmap_gi/use_bicubic_filter"));
|
||||||
|
|
||||||
{
|
{
|
||||||
// Setup Lights
|
// Setup Lights
|
||||||
|
|
|
@ -680,6 +680,8 @@ protected:
|
||||||
bool glow_bicubic_upscale = false;
|
bool glow_bicubic_upscale = false;
|
||||||
RS::EnvironmentSSRRoughnessQuality ssr_roughness_quality = RS::ENV_SSR_ROUGHNESS_QUALITY_LOW;
|
RS::EnvironmentSSRRoughnessQuality ssr_roughness_quality = RS::ENV_SSR_ROUGHNESS_QUALITY_LOW;
|
||||||
|
|
||||||
|
bool lightmap_bicubic_upscale = false;
|
||||||
|
|
||||||
/* Sky */
|
/* Sky */
|
||||||
|
|
||||||
struct SkyGlobals {
|
struct SkyGlobals {
|
||||||
|
@ -863,6 +865,7 @@ public:
|
||||||
|
|
||||||
void decals_set_filter(RS::DecalFilter p_filter) override;
|
void decals_set_filter(RS::DecalFilter p_filter) override;
|
||||||
void light_projectors_set_filter(RS::LightProjectorFilter p_filter) override;
|
void light_projectors_set_filter(RS::LightProjectorFilter p_filter) override;
|
||||||
|
virtual void lightmaps_set_bicubic_filter(bool p_enable) override;
|
||||||
|
|
||||||
RasterizerSceneGLES3();
|
RasterizerSceneGLES3();
|
||||||
~RasterizerSceneGLES3();
|
~RasterizerSceneGLES3();
|
||||||
|
|
|
@ -36,6 +36,7 @@ ADDITIVE_OMNI = false
|
||||||
ADDITIVE_SPOT = false
|
ADDITIVE_SPOT = false
|
||||||
RENDER_MATERIAL = false
|
RENDER_MATERIAL = false
|
||||||
SECOND_REFLECTION_PROBE = false
|
SECOND_REFLECTION_PROBE = false
|
||||||
|
LIGHTMAP_BICUBIC_FILTER = false
|
||||||
|
|
||||||
|
|
||||||
#[vertex]
|
#[vertex]
|
||||||
|
@ -925,6 +926,10 @@ uniform lowp uint lightmap_slice;
|
||||||
uniform highp vec4 lightmap_uv_scale;
|
uniform highp vec4 lightmap_uv_scale;
|
||||||
uniform float lightmap_exposure_normalization;
|
uniform float lightmap_exposure_normalization;
|
||||||
|
|
||||||
|
#ifdef LIGHTMAP_BICUBIC_FILTER
|
||||||
|
uniform highp vec2 lightmap_texture_size;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef USE_SH_LIGHTMAP
|
#ifdef USE_SH_LIGHTMAP
|
||||||
uniform mediump mat3 lightmap_normal_xform;
|
uniform mediump mat3 lightmap_normal_xform;
|
||||||
#endif // USE_SH_LIGHTMAP
|
#endif // USE_SH_LIGHTMAP
|
||||||
|
@ -1417,6 +1422,67 @@ void reflection_process(samplerCube reflection_map,
|
||||||
|
|
||||||
#endif // !MODE_RENDER_DEPTH
|
#endif // !MODE_RENDER_DEPTH
|
||||||
|
|
||||||
|
#ifdef LIGHTMAP_BICUBIC_FILTER
|
||||||
|
// 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(sampler2DArray 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(tex, vec3(p0, uv.z)) + g1x * texture(tex, vec3(p1, uv.z)))) +
|
||||||
|
(g1(fuv.y) * (g0x * texture(tex, vec3(p2, uv.z)) + g1x * texture(tex, vec3(p3, uv.z))));
|
||||||
|
}
|
||||||
|
#endif //LIGHTMAP_BICUBIC_FILTER
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
//lay out everything, whatever is unused is optimized away anyway
|
//lay out everything, whatever is unused is optimized away anyway
|
||||||
vec3 vertex = vertex_interp;
|
vec3 vertex = vertex_interp;
|
||||||
|
@ -1732,10 +1798,18 @@ void main() {
|
||||||
|
|
||||||
#ifdef USE_SH_LIGHTMAP
|
#ifdef USE_SH_LIGHTMAP
|
||||||
uvw.z *= 4.0; // SH textures use 4 times more data.
|
uvw.z *= 4.0; // SH textures use 4 times more data.
|
||||||
|
|
||||||
|
#ifdef LIGHTMAP_BICUBIC_FILTER
|
||||||
|
vec3 lm_light_l0 = textureArray_bicubic(lightmap_textures, uvw + vec3(0.0, 0.0, 0.0), lightmap_texture_size).rgb;
|
||||||
|
vec3 lm_light_l1n1 = textureArray_bicubic(lightmap_textures, uvw + vec3(0.0, 0.0, 1.0), lightmap_texture_size).rgb;
|
||||||
|
vec3 lm_light_l1_0 = textureArray_bicubic(lightmap_textures, uvw + vec3(0.0, 0.0, 2.0), lightmap_texture_size).rgb;
|
||||||
|
vec3 lm_light_l1p1 = textureArray_bicubic(lightmap_textures, uvw + vec3(0.0, 0.0, 3.0), lightmap_texture_size).rgb;
|
||||||
|
#else
|
||||||
vec3 lm_light_l0 = textureLod(lightmap_textures, uvw + vec3(0.0, 0.0, 0.0), 0.0).rgb;
|
vec3 lm_light_l0 = textureLod(lightmap_textures, uvw + vec3(0.0, 0.0, 0.0), 0.0).rgb;
|
||||||
vec3 lm_light_l1n1 = textureLod(lightmap_textures, uvw + vec3(0.0, 0.0, 1.0), 0.0).rgb;
|
vec3 lm_light_l1n1 = textureLod(lightmap_textures, uvw + vec3(0.0, 0.0, 1.0), 0.0).rgb;
|
||||||
vec3 lm_light_l1_0 = textureLod(lightmap_textures, uvw + vec3(0.0, 0.0, 2.0), 0.0).rgb;
|
vec3 lm_light_l1_0 = textureLod(lightmap_textures, uvw + vec3(0.0, 0.0, 2.0), 0.0).rgb;
|
||||||
vec3 lm_light_l1p1 = textureLod(lightmap_textures, uvw + vec3(0.0, 0.0, 3.0), 0.0).rgb;
|
vec3 lm_light_l1p1 = textureLod(lightmap_textures, uvw + vec3(0.0, 0.0, 3.0), 0.0).rgb;
|
||||||
|
#endif
|
||||||
|
|
||||||
vec3 n = normalize(lightmap_normal_xform * normal);
|
vec3 n = normalize(lightmap_normal_xform * normal);
|
||||||
|
|
||||||
|
@ -1749,8 +1823,12 @@ void main() {
|
||||||
specular_light += lm_light_l1_0 * 0.32573 * r.z * lightmap_exposure_normalization;
|
specular_light += lm_light_l1_0 * 0.32573 * r.z * lightmap_exposure_normalization;
|
||||||
specular_light += lm_light_l1p1 * 0.32573 * r.x * lightmap_exposure_normalization;
|
specular_light += lm_light_l1p1 * 0.32573 * r.x * lightmap_exposure_normalization;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
#ifdef LIGHTMAP_BICUBIC_FILTER
|
||||||
|
ambient_light += textureArray_bicubic(lightmap_textures, uvw, lightmap_texture_size).rgb * lightmap_exposure_normalization;
|
||||||
#else
|
#else
|
||||||
ambient_light += textureLod(lightmap_textures, uvw, 0.0).rgb * lightmap_exposure_normalization;
|
ambient_light += textureLod(lightmap_textures, uvw, 0.0).rgb * lightmap_exposure_normalization;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif // USE_LIGHTMAP
|
#endif // USE_LIGHTMAP
|
||||||
|
|
|
@ -1046,6 +1046,9 @@ void LightStorage::lightmap_set_textures(RID p_lightmap, RID p_light, bool p_use
|
||||||
lightmap->light_texture = p_light;
|
lightmap->light_texture = p_light;
|
||||||
lightmap->uses_spherical_harmonics = p_uses_spherical_haromics;
|
lightmap->uses_spherical_harmonics = p_uses_spherical_haromics;
|
||||||
|
|
||||||
|
Vector3i light_texture_size = GLES3::TextureStorage::get_singleton()->texture_get_size(lightmap->light_texture);
|
||||||
|
lightmap->light_texture_size = Vector2i(light_texture_size.x, light_texture_size.y);
|
||||||
|
|
||||||
GLuint tex = GLES3::TextureStorage::get_singleton()->texture_get_texid(lightmap->light_texture);
|
GLuint tex = GLES3::TextureStorage::get_singleton()->texture_get_texid(lightmap->light_texture);
|
||||||
glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
|
glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
|
||||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
|
|
@ -180,6 +180,7 @@ struct Lightmap {
|
||||||
bool interior = false;
|
bool interior = false;
|
||||||
AABB bounds = AABB(Vector3(), Vector3(1, 1, 1));
|
AABB bounds = AABB(Vector3(), Vector3(1, 1, 1));
|
||||||
float baked_exposure = 1.0;
|
float baked_exposure = 1.0;
|
||||||
|
Vector2i light_texture_size;
|
||||||
int32_t array_index = -1; //unassigned
|
int32_t array_index = -1; //unassigned
|
||||||
PackedVector3Array points;
|
PackedVector3Array points;
|
||||||
PackedColorArray point_sh;
|
PackedColorArray point_sh;
|
||||||
|
|
|
@ -1680,6 +1680,14 @@ uint32_t TextureStorage::texture_get_texid(RID p_texture) const {
|
||||||
return texture->tex_id;
|
return texture->tex_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector3i TextureStorage::texture_get_size(RID p_texture) const {
|
||||||
|
Texture *texture = texture_owner.get_or_null(p_texture);
|
||||||
|
|
||||||
|
ERR_FAIL_NULL_V(texture, Vector3i(0, 0, 0));
|
||||||
|
|
||||||
|
return Vector3i(texture->width, texture->height, texture->depth);
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t TextureStorage::texture_get_width(RID p_texture) const {
|
uint32_t TextureStorage::texture_get_width(RID p_texture) const {
|
||||||
Texture *texture = texture_owner.get_or_null(p_texture);
|
Texture *texture = texture_owner.get_or_null(p_texture);
|
||||||
|
|
||||||
|
|
|
@ -553,6 +553,7 @@ public:
|
||||||
void texture_set_data(RID p_texture, const Ref<Image> &p_image, int p_layer = 0);
|
void texture_set_data(RID p_texture, const Ref<Image> &p_image, int p_layer = 0);
|
||||||
virtual Image::Format texture_get_format(RID p_texture) const override;
|
virtual Image::Format texture_get_format(RID p_texture) const override;
|
||||||
uint32_t texture_get_texid(RID p_texture) const;
|
uint32_t texture_get_texid(RID p_texture) const;
|
||||||
|
Vector3i texture_get_size(RID p_texture) const;
|
||||||
uint32_t texture_get_width(RID p_texture) const;
|
uint32_t texture_get_width(RID p_texture) const;
|
||||||
uint32_t texture_get_height(RID p_texture) const;
|
uint32_t texture_get_height(RID p_texture) const;
|
||||||
uint32_t texture_get_depth(RID p_texture) const;
|
uint32_t texture_get_depth(RID p_texture) const;
|
||||||
|
|
|
@ -429,6 +429,7 @@ void EditorNode::_update_from_settings() {
|
||||||
|
|
||||||
RS::get_singleton()->decals_set_filter(RS::DecalFilter(int(GLOBAL_GET("rendering/textures/decals/filter"))));
|
RS::get_singleton()->decals_set_filter(RS::DecalFilter(int(GLOBAL_GET("rendering/textures/decals/filter"))));
|
||||||
RS::get_singleton()->light_projectors_set_filter(RS::LightProjectorFilter(int(GLOBAL_GET("rendering/textures/light_projectors/filter"))));
|
RS::get_singleton()->light_projectors_set_filter(RS::LightProjectorFilter(int(GLOBAL_GET("rendering/textures/light_projectors/filter"))));
|
||||||
|
RS::get_singleton()->lightmaps_set_bicubic_filter(GLOBAL_GET("rendering/lightmapping/lightmap_gi/use_bicubic_filter"));
|
||||||
|
|
||||||
SceneTree *tree = get_tree();
|
SceneTree *tree = get_tree();
|
||||||
tree->set_debug_collisions_color(GLOBAL_GET("debug/shapes/collision/shape_color"));
|
tree->set_debug_collisions_color(GLOBAL_GET("debug/shapes/collision/shape_color"));
|
||||||
|
|
|
@ -186,6 +186,7 @@ public:
|
||||||
|
|
||||||
virtual void decals_set_filter(RS::DecalFilter p_filter) override {}
|
virtual void decals_set_filter(RS::DecalFilter p_filter) override {}
|
||||||
virtual void light_projectors_set_filter(RS::LightProjectorFilter p_filter) override {}
|
virtual void light_projectors_set_filter(RS::LightProjectorFilter p_filter) override {}
|
||||||
|
virtual void lightmaps_set_bicubic_filter(bool p_enable) override {}
|
||||||
|
|
||||||
RasterizerSceneDummy() {}
|
RasterizerSceneDummy() {}
|
||||||
~RasterizerSceneDummy() {}
|
~RasterizerSceneDummy() {}
|
||||||
|
|
|
@ -1103,9 +1103,17 @@ void RenderForwardClustered::_setup_lightmaps(const RenderDataRD *p_render_data,
|
||||||
|
|
||||||
RID lightmap = light_storage->lightmap_instance_get_lightmap(p_lightmaps[i]);
|
RID lightmap = light_storage->lightmap_instance_get_lightmap(p_lightmaps[i]);
|
||||||
|
|
||||||
|
// Transform (for directional lightmaps).
|
||||||
Basis to_lm = light_storage->lightmap_instance_get_transform(p_lightmaps[i]).basis.inverse() * p_cam_transform.basis;
|
Basis to_lm = light_storage->lightmap_instance_get_transform(p_lightmaps[i]).basis.inverse() * p_cam_transform.basis;
|
||||||
to_lm = to_lm.inverse().transposed(); //will transform normals
|
to_lm = to_lm.inverse().transposed(); //will transform normals
|
||||||
RendererRD::MaterialStorage::store_transform_3x3(to_lm, scene_state.lightmaps[i].normal_xform);
|
RendererRD::MaterialStorage::store_transform_3x3(to_lm, scene_state.lightmaps[i].normal_xform);
|
||||||
|
|
||||||
|
// Light texture size.
|
||||||
|
Vector2i lightmap_size = light_storage->lightmap_get_light_texture_size(lightmap);
|
||||||
|
scene_state.lightmaps[i].texture_size[0] = lightmap_size[0];
|
||||||
|
scene_state.lightmaps[i].texture_size[1] = lightmap_size[1];
|
||||||
|
|
||||||
|
// Exposure.
|
||||||
scene_state.lightmaps[i].exposure_normalization = 1.0;
|
scene_state.lightmaps[i].exposure_normalization = 1.0;
|
||||||
if (p_render_data->camera_attributes.is_valid()) {
|
if (p_render_data->camera_attributes.is_valid()) {
|
||||||
float baked_exposure = light_storage->lightmap_get_baked_exposure_normalization(lightmap);
|
float baked_exposure = light_storage->lightmap_get_baked_exposure_normalization(lightmap);
|
||||||
|
@ -4242,6 +4250,11 @@ void RenderForwardClustered::_update_shader_quality_settings() {
|
||||||
|
|
||||||
spec_constants.push_back(sc);
|
spec_constants.push_back(sc);
|
||||||
|
|
||||||
|
sc.constant_id = SPEC_CONSTANT_USE_LIGHTMAP_BICUBIC_FILTER;
|
||||||
|
sc.bool_value = lightmap_filter_bicubic_get();
|
||||||
|
|
||||||
|
spec_constants.push_back(sc);
|
||||||
|
|
||||||
scene_shader.set_default_specialization_constants(spec_constants);
|
scene_shader.set_default_specialization_constants(spec_constants);
|
||||||
|
|
||||||
base_uniforms_changed(); //also need this
|
base_uniforms_changed(); //also need this
|
||||||
|
|
|
@ -73,6 +73,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
|
||||||
SPEC_CONSTANT_DECAL_FILTER = 10,
|
SPEC_CONSTANT_DECAL_FILTER = 10,
|
||||||
SPEC_CONSTANT_PROJECTOR_FILTER = 11,
|
SPEC_CONSTANT_PROJECTOR_FILTER = 11,
|
||||||
SPEC_CONSTANT_USE_DEPTH_FOG = 12,
|
SPEC_CONSTANT_USE_DEPTH_FOG = 12,
|
||||||
|
SPEC_CONSTANT_USE_LIGHTMAP_BICUBIC_FILTER = 13,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
@ -235,8 +236,9 @@ class RenderForwardClustered : public RendererSceneRenderRD {
|
||||||
|
|
||||||
struct LightmapData {
|
struct LightmapData {
|
||||||
float normal_xform[12];
|
float normal_xform[12];
|
||||||
float pad[3];
|
float texture_size[2];
|
||||||
float exposure_normalization;
|
float exposure_normalization;
|
||||||
|
float pad;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LightmapCaptureData {
|
struct LightmapCaptureData {
|
||||||
|
|
|
@ -563,9 +563,17 @@ void RenderForwardMobile::_setup_lightmaps(const RenderDataRD *p_render_data, co
|
||||||
|
|
||||||
RID lightmap = light_storage->lightmap_instance_get_lightmap(p_lightmaps[i]);
|
RID lightmap = light_storage->lightmap_instance_get_lightmap(p_lightmaps[i]);
|
||||||
|
|
||||||
|
// Transform (for directional lightmaps).
|
||||||
Basis to_lm = light_storage->lightmap_instance_get_transform(p_lightmaps[i]).basis.inverse() * p_cam_transform.basis;
|
Basis to_lm = light_storage->lightmap_instance_get_transform(p_lightmaps[i]).basis.inverse() * p_cam_transform.basis;
|
||||||
to_lm = to_lm.inverse().transposed(); //will transform normals
|
to_lm = to_lm.inverse().transposed(); //will transform normals
|
||||||
RendererRD::MaterialStorage::store_transform_3x3(to_lm, scene_state.lightmaps[i].normal_xform);
|
RendererRD::MaterialStorage::store_transform_3x3(to_lm, scene_state.lightmaps[i].normal_xform);
|
||||||
|
|
||||||
|
// Light texture size.
|
||||||
|
Vector2i lightmap_size = light_storage->lightmap_get_light_texture_size(lightmap);
|
||||||
|
scene_state.lightmaps[i].texture_size[0] = lightmap_size[0];
|
||||||
|
scene_state.lightmaps[i].texture_size[1] = lightmap_size[1];
|
||||||
|
|
||||||
|
// Exposure.
|
||||||
scene_state.lightmaps[i].exposure_normalization = 1.0;
|
scene_state.lightmaps[i].exposure_normalization = 1.0;
|
||||||
if (p_render_data->camera_attributes.is_valid()) {
|
if (p_render_data->camera_attributes.is_valid()) {
|
||||||
float baked_exposure = light_storage->lightmap_get_baked_exposure_normalization(lightmap);
|
float baked_exposure = light_storage->lightmap_get_baked_exposure_normalization(lightmap);
|
||||||
|
@ -2781,6 +2789,11 @@ void RenderForwardMobile::_update_shader_quality_settings() {
|
||||||
|
|
||||||
spec_constants.push_back(sc);
|
spec_constants.push_back(sc);
|
||||||
|
|
||||||
|
sc.constant_id = SPEC_CONSTANT_USE_LIGHTMAP_BICUBIC_FILTER;
|
||||||
|
sc.bool_value = lightmap_filter_bicubic_get();
|
||||||
|
|
||||||
|
spec_constants.push_back(sc);
|
||||||
|
|
||||||
scene_shader.set_default_specialization_constants(spec_constants);
|
scene_shader.set_default_specialization_constants(spec_constants);
|
||||||
|
|
||||||
base_uniforms_changed(); //also need this
|
base_uniforms_changed(); //also need this
|
||||||
|
|
|
@ -82,7 +82,7 @@ private:
|
||||||
SPEC_CONSTANT_DISABLE_FOG = 14,
|
SPEC_CONSTANT_DISABLE_FOG = 14,
|
||||||
SPEC_CONSTANT_USE_DEPTH_FOG = 16,
|
SPEC_CONSTANT_USE_DEPTH_FOG = 16,
|
||||||
SPEC_CONSTANT_IS_MULTIMESH = 17,
|
SPEC_CONSTANT_IS_MULTIMESH = 17,
|
||||||
|
SPEC_CONSTANT_USE_LIGHTMAP_BICUBIC_FILTER = 18,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
@ -208,8 +208,9 @@ private:
|
||||||
|
|
||||||
struct LightmapData {
|
struct LightmapData {
|
||||||
float normal_xform[12];
|
float normal_xform[12];
|
||||||
float pad[3];
|
float texture_size[2];
|
||||||
float exposure_normalization;
|
float exposure_normalization;
|
||||||
|
float pad;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LightmapCaptureData {
|
struct LightmapCaptureData {
|
||||||
|
|
|
@ -1040,6 +1040,14 @@ void RendererSceneRenderRD::light_projectors_set_filter(RenderingServer::LightPr
|
||||||
_update_shader_quality_settings();
|
_update_shader_quality_settings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RendererSceneRenderRD::lightmaps_set_bicubic_filter(bool p_enable) {
|
||||||
|
if (lightmap_filter_bicubic == p_enable) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lightmap_filter_bicubic = p_enable;
|
||||||
|
_update_shader_quality_settings();
|
||||||
|
}
|
||||||
|
|
||||||
int RendererSceneRenderRD::get_roughness_layers() const {
|
int RendererSceneRenderRD::get_roughness_layers() const {
|
||||||
return sky.roughness_layers;
|
return sky.roughness_layers;
|
||||||
}
|
}
|
||||||
|
@ -1483,6 +1491,7 @@ void RendererSceneRenderRD::init() {
|
||||||
|
|
||||||
decals_set_filter(RS::DecalFilter(int(GLOBAL_GET("rendering/textures/decals/filter"))));
|
decals_set_filter(RS::DecalFilter(int(GLOBAL_GET("rendering/textures/decals/filter"))));
|
||||||
light_projectors_set_filter(RS::LightProjectorFilter(int(GLOBAL_GET("rendering/textures/light_projectors/filter"))));
|
light_projectors_set_filter(RS::LightProjectorFilter(int(GLOBAL_GET("rendering/textures/light_projectors/filter"))));
|
||||||
|
lightmaps_set_bicubic_filter(GLOBAL_GET("rendering/lightmapping/lightmap_gi/use_bicubic_filter"));
|
||||||
|
|
||||||
cull_argument.set_page_pool(&cull_argument_pool);
|
cull_argument.set_page_pool(&cull_argument_pool);
|
||||||
|
|
||||||
|
|
|
@ -133,6 +133,7 @@ private:
|
||||||
float *directional_soft_shadow_kernel = nullptr;
|
float *directional_soft_shadow_kernel = nullptr;
|
||||||
float *penumbra_shadow_kernel = nullptr;
|
float *penumbra_shadow_kernel = nullptr;
|
||||||
float *soft_shadow_kernel = nullptr;
|
float *soft_shadow_kernel = nullptr;
|
||||||
|
bool lightmap_filter_bicubic = false;
|
||||||
int directional_penumbra_shadow_samples = 0;
|
int directional_penumbra_shadow_samples = 0;
|
||||||
int directional_soft_shadow_samples = 0;
|
int directional_soft_shadow_samples = 0;
|
||||||
int penumbra_shadow_samples = 0;
|
int penumbra_shadow_samples = 0;
|
||||||
|
@ -262,6 +263,7 @@ public:
|
||||||
|
|
||||||
virtual void decals_set_filter(RS::DecalFilter p_filter) override;
|
virtual void decals_set_filter(RS::DecalFilter p_filter) override;
|
||||||
virtual void light_projectors_set_filter(RS::LightProjectorFilter p_filter) override;
|
virtual void light_projectors_set_filter(RS::LightProjectorFilter p_filter) override;
|
||||||
|
virtual void lightmaps_set_bicubic_filter(bool p_enable) override;
|
||||||
|
|
||||||
_FORCE_INLINE_ RS::ShadowQuality shadows_quality_get() const {
|
_FORCE_INLINE_ RS::ShadowQuality shadows_quality_get() const {
|
||||||
return shadows_quality;
|
return shadows_quality;
|
||||||
|
@ -292,6 +294,9 @@ public:
|
||||||
_FORCE_INLINE_ int directional_penumbra_shadow_samples_get() const {
|
_FORCE_INLINE_ int directional_penumbra_shadow_samples_get() const {
|
||||||
return directional_penumbra_shadow_samples;
|
return directional_penumbra_shadow_samples;
|
||||||
}
|
}
|
||||||
|
_FORCE_INLINE_ bool lightmap_filter_bicubic_get() const {
|
||||||
|
return lightmap_filter_bicubic;
|
||||||
|
}
|
||||||
_FORCE_INLINE_ int directional_soft_shadow_samples_get() const {
|
_FORCE_INLINE_ int directional_soft_shadow_samples_get() const {
|
||||||
return directional_soft_shadow_samples;
|
return directional_soft_shadow_samples;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 = 10) const bool sc_decal_use_mipmaps = true;
|
||||||
layout(constant_id = 11) const bool sc_projector_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 = 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.
|
// not used in clustered renderer but we share some code with the mobile renderer that requires this.
|
||||||
const float sc_luminance_multiplier = 1.0;
|
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;
|
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 USE_MULTIVIEW
|
||||||
#ifdef has_VK_KHR_multiview
|
#ifdef has_VK_KHR_multiview
|
||||||
#define ViewIndex gl_ViewIndex
|
#define ViewIndex gl_ViewIndex
|
||||||
|
@ -1449,10 +1511,23 @@ void fragment_shader(in SceneData scene_data) {
|
||||||
|
|
||||||
if (uses_sh) {
|
if (uses_sh) {
|
||||||
uvw.z *= 4.0; //SH textures use 4 times more data
|
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_l0;
|
||||||
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_l1n1;
|
||||||
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_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);
|
vec3 n = normalize(lightmaps.data[ofs].normal_xform * normal);
|
||||||
float en = lightmaps.data[ofs].exposure_normalization;
|
float en = lightmaps.data[ofs].exposure_normalization;
|
||||||
|
@ -1469,7 +1544,11 @@ void fragment_shader(in SceneData scene_data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} 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
|
#else
|
||||||
|
|
|
@ -94,8 +94,9 @@ directional_lights;
|
||||||
|
|
||||||
struct Lightmap {
|
struct Lightmap {
|
||||||
mat3 normal_xform;
|
mat3 normal_xform;
|
||||||
vec3 pad;
|
vec2 light_texture_size;
|
||||||
float exposure_normalization;
|
float exposure_normalization;
|
||||||
|
vec2 pad;
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(set = 0, binding = 7, std140) restrict readonly buffer Lightmaps {
|
layout(set = 0, binding = 7, std140) restrict readonly buffer Lightmaps {
|
||||||
|
|
|
@ -521,6 +521,7 @@ layout(constant_id = 9) const bool sc_disable_omni_lights = false;
|
||||||
layout(constant_id = 10) const bool sc_disable_spot_lights = false;
|
layout(constant_id = 10) const bool sc_disable_spot_lights = false;
|
||||||
layout(constant_id = 11) const bool sc_disable_reflection_probes = false;
|
layout(constant_id = 11) const bool sc_disable_reflection_probes = false;
|
||||||
layout(constant_id = 12) const bool sc_disable_directional_lights = false;
|
layout(constant_id = 12) const bool sc_disable_directional_lights = false;
|
||||||
|
layout(constant_id = 18) const bool sc_use_lightmap_bicubic_filter = false;
|
||||||
|
|
||||||
#endif //!MODE_UNSHADED
|
#endif //!MODE_UNSHADED
|
||||||
|
|
||||||
|
@ -567,6 +568,67 @@ layout(location = 9) highp in float dp_clip;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#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 USE_MULTIVIEW
|
||||||
#ifdef has_VK_KHR_multiview
|
#ifdef has_VK_KHR_multiview
|
||||||
#define ViewIndex gl_ViewIndex
|
#define ViewIndex gl_ViewIndex
|
||||||
|
@ -1209,10 +1271,22 @@ void main() {
|
||||||
|
|
||||||
if (uses_sh) {
|
if (uses_sh) {
|
||||||
uvw.z *= 4.0; //SH textures use 4 times more data
|
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_l0;
|
||||||
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_l1n1;
|
||||||
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_l1_0;
|
||||||
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_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);
|
vec3 n = normalize(lightmaps.data[ofs].normal_xform * normal);
|
||||||
float exposure_normalization = lightmaps.data[ofs].exposure_normalization;
|
float exposure_normalization = lightmaps.data[ofs].exposure_normalization;
|
||||||
|
@ -1229,7 +1303,11 @@ void main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,8 +71,9 @@ directional_lights;
|
||||||
|
|
||||||
struct Lightmap {
|
struct Lightmap {
|
||||||
mediump mat3 normal_xform;
|
mediump mat3 normal_xform;
|
||||||
vec3 pad;
|
vec2 light_texture_size;
|
||||||
float exposure_normalization;
|
float exposure_normalization;
|
||||||
|
float pad;
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(set = 0, binding = 7, std140) restrict readonly buffer Lightmaps {
|
layout(set = 0, binding = 7, std140) restrict readonly buffer Lightmaps {
|
||||||
|
|
|
@ -1813,6 +1813,7 @@ void LightStorage::lightmap_set_textures(RID p_lightmap, RID p_light, bool p_use
|
||||||
}
|
}
|
||||||
|
|
||||||
t->lightmap_users.insert(p_lightmap);
|
t->lightmap_users.insert(p_lightmap);
|
||||||
|
lm->light_texture_size = Vector2i(t->width, t->height);
|
||||||
|
|
||||||
if (using_lightmap_array) {
|
if (using_lightmap_array) {
|
||||||
if (lm->array_index < 0) {
|
if (lm->array_index < 0) {
|
||||||
|
|
|
@ -332,6 +332,7 @@ private:
|
||||||
bool interior = false;
|
bool interior = false;
|
||||||
AABB bounds = AABB(Vector3(), Vector3(1, 1, 1));
|
AABB bounds = AABB(Vector3(), Vector3(1, 1, 1));
|
||||||
float baked_exposure = 1.0;
|
float baked_exposure = 1.0;
|
||||||
|
Vector2i light_texture_size;
|
||||||
int32_t array_index = -1; //unassigned
|
int32_t array_index = -1; //unassigned
|
||||||
PackedVector3Array points;
|
PackedVector3Array points;
|
||||||
PackedColorArray point_sh;
|
PackedColorArray point_sh;
|
||||||
|
@ -985,6 +986,10 @@ public:
|
||||||
const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
|
const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
|
||||||
return lm->uses_spherical_harmonics;
|
return lm->uses_spherical_harmonics;
|
||||||
}
|
}
|
||||||
|
_FORCE_INLINE_ Vector2i lightmap_get_light_texture_size(RID p_lightmap) const {
|
||||||
|
const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
|
||||||
|
return lm->light_texture_size;
|
||||||
|
}
|
||||||
_FORCE_INLINE_ uint64_t lightmap_array_get_version() const {
|
_FORCE_INLINE_ uint64_t lightmap_array_get_version() const {
|
||||||
ERR_FAIL_COND_V(!using_lightmap_array, 0); //only for arrays
|
ERR_FAIL_COND_V(!using_lightmap_array, 0); //only for arrays
|
||||||
return lightmap_array_version;
|
return lightmap_array_version;
|
||||||
|
|
|
@ -73,6 +73,8 @@ public:
|
||||||
uint32_t directional_light_count = 0;
|
uint32_t directional_light_count = 0;
|
||||||
bool directional_light_soft_shadows = false;
|
bool directional_light_soft_shadows = false;
|
||||||
|
|
||||||
|
bool lightmap_bicubic_filter = false;
|
||||||
|
|
||||||
RenderingMethod::RenderInfo *render_info = nullptr;
|
RenderingMethod::RenderInfo *render_info = nullptr;
|
||||||
|
|
||||||
/* Viewport data */
|
/* Viewport data */
|
||||||
|
|
|
@ -1418,6 +1418,7 @@ public:
|
||||||
|
|
||||||
PASS1(decals_set_filter, RS::DecalFilter)
|
PASS1(decals_set_filter, RS::DecalFilter)
|
||||||
PASS1(light_projectors_set_filter, RS::LightProjectorFilter)
|
PASS1(light_projectors_set_filter, RS::LightProjectorFilter)
|
||||||
|
PASS1(lightmaps_set_bicubic_filter, bool)
|
||||||
|
|
||||||
virtual void update();
|
virtual void update();
|
||||||
|
|
||||||
|
|
|
@ -338,6 +338,7 @@ public:
|
||||||
|
|
||||||
virtual void decals_set_filter(RS::DecalFilter p_filter) = 0;
|
virtual void decals_set_filter(RS::DecalFilter p_filter) = 0;
|
||||||
virtual void light_projectors_set_filter(RS::LightProjectorFilter p_filter) = 0;
|
virtual void light_projectors_set_filter(RS::LightProjectorFilter p_filter) = 0;
|
||||||
|
virtual void lightmaps_set_bicubic_filter(bool p_enable) = 0;
|
||||||
|
|
||||||
virtual void update() = 0;
|
virtual void update() = 0;
|
||||||
virtual ~RendererSceneRender() {}
|
virtual ~RendererSceneRender() {}
|
||||||
|
|
|
@ -349,6 +349,7 @@ public:
|
||||||
|
|
||||||
virtual void decals_set_filter(RS::DecalFilter p_filter) = 0;
|
virtual void decals_set_filter(RS::DecalFilter p_filter) = 0;
|
||||||
virtual void light_projectors_set_filter(RS::LightProjectorFilter p_filter) = 0;
|
virtual void light_projectors_set_filter(RS::LightProjectorFilter p_filter) = 0;
|
||||||
|
virtual void lightmaps_set_bicubic_filter(bool p_enable) = 0;
|
||||||
|
|
||||||
virtual bool free(RID p_rid) = 0;
|
virtual bool free(RID p_rid) = 0;
|
||||||
|
|
||||||
|
|
|
@ -762,6 +762,7 @@ public:
|
||||||
FUNC1(directional_soft_shadow_filter_set_quality, ShadowQuality);
|
FUNC1(directional_soft_shadow_filter_set_quality, ShadowQuality);
|
||||||
FUNC1(decals_set_filter, RS::DecalFilter);
|
FUNC1(decals_set_filter, RS::DecalFilter);
|
||||||
FUNC1(light_projectors_set_filter, RS::LightProjectorFilter);
|
FUNC1(light_projectors_set_filter, RS::LightProjectorFilter);
|
||||||
|
FUNC1(lightmaps_set_bicubic_filter, bool);
|
||||||
|
|
||||||
/* CAMERA ATTRIBUTES */
|
/* CAMERA ATTRIBUTES */
|
||||||
|
|
||||||
|
|
|
@ -2477,6 +2477,7 @@ void RenderingServer::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("light_directional_set_sky_mode", "light", "mode"), &RenderingServer::light_directional_set_sky_mode);
|
ClassDB::bind_method(D_METHOD("light_directional_set_sky_mode", "light", "mode"), &RenderingServer::light_directional_set_sky_mode);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("light_projectors_set_filter", "filter"), &RenderingServer::light_projectors_set_filter);
|
ClassDB::bind_method(D_METHOD("light_projectors_set_filter", "filter"), &RenderingServer::light_projectors_set_filter);
|
||||||
|
ClassDB::bind_method(D_METHOD("lightmaps_set_bicubic_filter", "enable"), &RenderingServer::lightmaps_set_bicubic_filter);
|
||||||
|
|
||||||
BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_NEAREST);
|
BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_NEAREST);
|
||||||
BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_LINEAR);
|
BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_LINEAR);
|
||||||
|
@ -3618,6 +3619,7 @@ void RenderingServer::init() {
|
||||||
|
|
||||||
GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "rendering/lightmapping/probe_capture/update_speed", PROPERTY_HINT_RANGE, "0.001,256,0.001"), 15);
|
GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "rendering/lightmapping/probe_capture/update_speed", PROPERTY_HINT_RANGE, "0.001,256,0.001"), 15);
|
||||||
GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "rendering/lightmapping/primitive_meshes/texel_size", PROPERTY_HINT_RANGE, "0.001,100,0.001"), 0.2);
|
GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "rendering/lightmapping/primitive_meshes/texel_size", PROPERTY_HINT_RANGE, "0.001,100,0.001"), 0.2);
|
||||||
|
GLOBAL_DEF("rendering/lightmapping/lightmap_gi/use_bicubic_filter", true);
|
||||||
|
|
||||||
GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/global_illumination/sdfgi/probe_ray_count", PROPERTY_HINT_ENUM, "8 (Fastest),16,32,64,96,128 (Slowest)"), 1);
|
GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/global_illumination/sdfgi/probe_ray_count", PROPERTY_HINT_ENUM, "8 (Fastest),16,32,64,96,128 (Slowest)"), 1);
|
||||||
GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/global_illumination/sdfgi/frames_to_converge", PROPERTY_HINT_ENUM, "5 (Less Latency but Lower Quality),10,15,20,25,30 (More Latency but Higher Quality)"), 5);
|
GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/global_illumination/sdfgi/frames_to_converge", PROPERTY_HINT_ENUM, "5 (Less Latency but Lower Quality),10,15,20,25,30 (More Latency but Higher Quality)"), 5);
|
||||||
|
|
|
@ -687,6 +687,8 @@ public:
|
||||||
|
|
||||||
virtual void lightmap_set_probe_capture_update_speed(float p_speed) = 0;
|
virtual void lightmap_set_probe_capture_update_speed(float p_speed) = 0;
|
||||||
|
|
||||||
|
virtual void lightmaps_set_bicubic_filter(bool p_enable) = 0;
|
||||||
|
|
||||||
/* PARTICLES API */
|
/* PARTICLES API */
|
||||||
|
|
||||||
virtual RID particles_create() = 0;
|
virtual RID particles_create() = 0;
|
||||||
|
|
Loading…
Reference in New Issue