Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions doc/classes/ProjectSettings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2592,6 +2592,10 @@
- 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.
</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">
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>
Expand Down
7 changes: 7 additions & 0 deletions doc/classes/RenderingServer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2206,6 +2206,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].
</description>
</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">
<return type="RID" />
<param index="0" name="latitudes" type="int" />
Expand Down
14 changes: 14 additions & 0 deletions drivers/gles3/rasterizer_scene_gles3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3202,6 +3202,10 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
if (lm->uses_spherical_harmonics) {
spec_constants |= SceneShaderGLES3::USE_SH_LIGHTMAP;
}

if (lightmap_bicubic_upscale) {
spec_constants |= SceneShaderGLES3::LIGHTMAP_BICUBIC_FILTER;
}
} else if (inst->lightmap_sh) {
spec_constants |= SceneShaderGLES3::USE_LIGHTMAP_CAPTURE;
} else {
Expand Down Expand Up @@ -3344,6 +3348,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);
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;
if (p_render_data->camera_attributes.is_valid()) {
float enf = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
Expand Down Expand Up @@ -4039,6 +4048,10 @@ void RasterizerSceneGLES3::decals_set_filter(RS::DecalFilter 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() {
singleton = this;

Expand All @@ -4052,6 +4065,7 @@ RasterizerSceneGLES3::RasterizerSceneGLES3() {

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"));
lightmaps_set_bicubic_filter(GLOBAL_GET("rendering/lightmapping/lightmap_gi/use_bicubic_filter"));

{
// Setup Lights
Expand Down
3 changes: 3 additions & 0 deletions drivers/gles3/rasterizer_scene_gles3.h
Original file line number Diff line number Diff line change
Expand Up @@ -680,6 +680,8 @@ class RasterizerSceneGLES3 : public RendererSceneRender {
bool glow_bicubic_upscale = false;
RS::EnvironmentSSRRoughnessQuality ssr_roughness_quality = RS::ENV_SSR_ROUGHNESS_QUALITY_LOW;

bool lightmap_bicubic_upscale = false;

/* Sky */

struct SkyGlobals {
Expand Down Expand Up @@ -863,6 +865,7 @@ class RasterizerSceneGLES3 : public RendererSceneRender {

void decals_set_filter(RS::DecalFilter 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();
Expand Down
78 changes: 78 additions & 0 deletions drivers/gles3/shaders/scene.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ ADDITIVE_OMNI = false
ADDITIVE_SPOT = false
RENDER_MATERIAL = false
SECOND_REFLECTION_PROBE = false
LIGHTMAP_BICUBIC_FILTER = false


#[vertex]
Expand Down Expand Up @@ -923,6 +924,10 @@ uniform lowp uint lightmap_slice;
uniform highp vec4 lightmap_uv_scale;
uniform float lightmap_exposure_normalization;

#ifdef LIGHTMAP_BICUBIC_FILTER
uniform highp vec2 lightmap_texture_size;
#endif

#ifdef USE_SH_LIGHTMAP
uniform mediump mat3 lightmap_normal_xform;
#endif // USE_SH_LIGHTMAP
Expand Down Expand Up @@ -1414,6 +1419,67 @@ void reflection_process(samplerCube reflection_map,

#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() {
//lay out everything, whatever is unused is optimized away anyway
vec3 vertex = vertex_interp;
Expand Down Expand Up @@ -1721,10 +1787,18 @@ void main() {

#ifdef USE_SH_LIGHTMAP
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_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_l1p1 = textureLod(lightmap_textures, uvw + vec3(0.0, 0.0, 3.0), 0.0).rgb;
#endif

vec3 n = normalize(lightmap_normal_xform * normal);

Expand All @@ -1738,8 +1812,12 @@ void main() {
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;
}
#else
#ifdef LIGHTMAP_BICUBIC_FILTER
ambient_light += textureArray_bicubic(lightmap_textures, uvw, lightmap_texture_size).rgb * lightmap_exposure_normalization;
#else
ambient_light += textureLod(lightmap_textures, uvw, 0.0).rgb * lightmap_exposure_normalization;
#endif
#endif
}
#endif // USE_LIGHTMAP
Expand Down
3 changes: 3 additions & 0 deletions drivers/gles3/storage/light_storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1046,6 +1046,9 @@ void LightStorage::lightmap_set_textures(RID p_lightmap, RID p_light, bool p_use
lightmap->light_texture = p_light;
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);
glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
Expand Down
1 change: 1 addition & 0 deletions drivers/gles3/storage/light_storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ struct Lightmap {
bool interior = false;
AABB bounds = AABB(Vector3(), Vector3(1, 1, 1));
float baked_exposure = 1.0;
Vector2i light_texture_size;
int32_t array_index = -1; //unassigned
PackedVector3Array points;
PackedColorArray point_sh;
Expand Down
8 changes: 8 additions & 0 deletions drivers/gles3/storage/texture_storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1680,6 +1680,14 @@ uint32_t TextureStorage::texture_get_texid(RID p_texture) const {
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 {
Texture *texture = texture_owner.get_or_null(p_texture);

Expand Down
1 change: 1 addition & 0 deletions drivers/gles3/storage/texture_storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,7 @@ class TextureStorage : public RendererTextureStorage {
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;
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_height(RID p_texture) const;
uint32_t texture_get_depth(RID p_texture) const;
Expand Down
1 change: 1 addition & 0 deletions editor/editor_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()->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();
tree->set_debug_collisions_color(GLOBAL_GET("debug/shapes/collision/shape_color"));
Expand Down
1 change: 1 addition & 0 deletions servers/rendering/dummy/rasterizer_scene_dummy.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ class RasterizerSceneDummy : public RendererSceneRender {

virtual void decals_set_filter(RS::DecalFilter 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() {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1103,9 +1103,17 @@ void RenderForwardClustered::_setup_lightmaps(const RenderDataRD *p_render_data,

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;
to_lm = to_lm.inverse().transposed(); //will transform normals
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;
if (p_render_data->camera_attributes.is_valid()) {
float baked_exposure = light_storage->lightmap_get_baked_exposure_normalization(lightmap);
Expand Down Expand Up @@ -4242,6 +4250,11 @@ void RenderForwardClustered::_update_shader_quality_settings() {

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);

base_uniforms_changed(); //also need this
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
SPEC_CONSTANT_DECAL_FILTER = 10,
SPEC_CONSTANT_PROJECTOR_FILTER = 11,
SPEC_CONSTANT_USE_DEPTH_FOG = 12,
SPEC_CONSTANT_USE_LIGHTMAP_BICUBIC_FILTER = 13,
};

enum {
Expand Down Expand Up @@ -235,8 +236,9 @@ class RenderForwardClustered : public RendererSceneRenderRD {

struct LightmapData {
float normal_xform[12];
float pad[3];
float texture_size[2];
float exposure_normalization;
float pad;
};

struct LightmapCaptureData {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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]);

// Transform (for directional lightmaps).
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
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;
if (p_render_data->camera_attributes.is_valid()) {
float baked_exposure = light_storage->lightmap_get_baked_exposure_normalization(lightmap);
Expand Down Expand Up @@ -2781,6 +2789,11 @@ void RenderForwardMobile::_update_shader_quality_settings() {

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);

base_uniforms_changed(); //also need this
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ class RenderForwardMobile : public RendererSceneRenderRD {
SPEC_CONSTANT_DISABLE_FOG = 14,
SPEC_CONSTANT_USE_DEPTH_FOG = 16,
SPEC_CONSTANT_IS_MULTIMESH = 17,

SPEC_CONSTANT_USE_LIGHTMAP_BICUBIC_FILTER = 18,
};

enum {
Expand Down Expand Up @@ -208,8 +208,9 @@ class RenderForwardMobile : public RendererSceneRenderRD {

struct LightmapData {
float normal_xform[12];
float pad[3];
float texture_size[2];
float exposure_normalization;
float pad;
};

struct LightmapCaptureData {
Expand Down
9 changes: 9 additions & 0 deletions servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1040,6 +1040,14 @@ void RendererSceneRenderRD::light_projectors_set_filter(RenderingServer::LightPr
_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 {
return sky.roughness_layers;
}
Expand Down Expand Up @@ -1483,6 +1491,7 @@ void RendererSceneRenderRD::init() {

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"))));
lightmaps_set_bicubic_filter(GLOBAL_GET("rendering/lightmapping/lightmap_gi/use_bicubic_filter"));

cull_argument.set_page_pool(&cull_argument_pool);

Expand Down
Loading