Skip to content
Open
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
3 changes: 3 additions & 0 deletions doc/classes/LightmapGIData.xml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@
<member name="lightmap_textures" type="TextureLayered[]" setter="set_lightmap_textures" getter="get_lightmap_textures" default="[]">
The lightmap atlas textures generated by the lightmapper.
</member>
<member name="modulate" type="Color" setter="set_modulate" getter="get_modulate" default="Color(1, 1, 1, 1)">
The color the lightmap is multiplied with. Gets applied in real-time without the need to re-bake the lightmap.
</member>
<member name="shadowmask_textures" type="TextureLayered[]" setter="set_shadowmask_textures" getter="get_shadowmask_textures" default="[]">
The shadowmask atlas textures generated by the lightmapper.
</member>
Expand Down
15 changes: 15 additions & 0 deletions doc/classes/RenderingServer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1973,6 +1973,13 @@
Sets the visibility range values for the given geometry instance. Equivalent to [member GeometryInstance3D.visibility_range_begin] and related properties.
</description>
</method>
<method name="instance_lightmap_update_geometries_captures">
<return type="void" />
<param index="0" name="lightmap" type="RID" />
<description>
Updates the lightmap spherical harmonics captures of all [GeometryInstance3D] instances affected by this lightmap.
</description>
</method>
<method name="instance_set_base">
<return type="void" />
<param index="0" name="instance" type="RID" />
Expand Down Expand Up @@ -2304,6 +2311,14 @@
Used to inform the renderer what exposure normalization value was used while baking the lightmap. This value will be used and modulated at run time to ensure that the lightmap maintains a consistent level of exposure even if the scene-wide exposure normalization is changed at run time. For more information see [method camera_attributes_set_exposure].
</description>
</method>
<method name="lightmap_set_modulate">
<return type="void" />
<param index="0" name="lightmap" type="RID" />
<param index="1" name="energy_color" type="Color" />
<description>
Sets a lightmap's modulate color.
</description>
</method>
<method name="lightmap_set_probe_bounds">
<return type="void" />
<param index="0" name="lightmap" type="RID" />
Expand Down
3 changes: 3 additions & 0 deletions drivers/gles3/rasterizer_scene_gles3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3799,6 +3799,9 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
}
material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::LIGHTMAP_EXPOSURE_NORMALIZATION, exposure_normalization, shader->version, instance_variant, spec_constants);

Vector3 lightmap_modulate(lm->modulate.r, lm->modulate.g, lm->modulate.b);
material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::LIGHTMAP_MODULATE, lightmap_modulate, shader->version, instance_variant, spec_constants);

if (lm->uses_spherical_harmonics) {
Basis to_lm = li->transform.basis.inverse() * p_render_data->cam_transform.basis;
to_lm = to_lm.inverse().transposed();
Expand Down
16 changes: 10 additions & 6 deletions drivers/gles3/shaders/scene.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -1441,6 +1441,7 @@ uniform lowp sampler2DArray shadowmask_textures; //texunit:-5
uniform lowp uint lightmap_slice;
uniform highp vec4 lightmap_uv_scale;
uniform float lightmap_exposure_normalization;
uniform vec3 lightmap_modulate;
uniform uint lightmap_shadowmask_mode;

#define SHADOWMASK_MODE_NONE uint(0)
Expand Down Expand Up @@ -2543,15 +2544,18 @@ void main() {

vec3 n = normalize(lightmap_normal_xform * indirect_normal);

ambient_light += lm_light_l0 * lightmap_exposure_normalization;
ambient_light += lm_light_l1n1 * n.y * (lm_light_l0 * lightmap_exposure_normalization * 4.0);
ambient_light += lm_light_l1_0 * n.z * (lm_light_l0 * lightmap_exposure_normalization * 4.0);
ambient_light += lm_light_l1p1 * n.x * (lm_light_l0 * lightmap_exposure_normalization * 4.0);
vec3 al = vec3(0.0, 0.0, 0.0);
al += lm_light_l0 * lightmap_exposure_normalization;
al += lm_light_l1n1 * n.y * (lm_light_l0 * lightmap_exposure_normalization * 4.0);
al += lm_light_l1_0 * n.z * (lm_light_l0 * lightmap_exposure_normalization * 4.0);
al += lm_light_l1p1 * n.x * (lm_light_l0 * lightmap_exposure_normalization * 4.0);

ambient_light += al * lightmap_modulate;
#else
#ifdef LIGHTMAP_BICUBIC_FILTER
ambient_light += textureArray_bicubic(lightmap_textures, uvw, lightmap_texture_size).rgb * lightmap_exposure_normalization;
ambient_light += textureArray_bicubic(lightmap_textures, uvw, lightmap_texture_size).rgb * lightmap_exposure_normalization * lightmap_modulate;
#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 * lightmap_modulate;
#endif
#endif
}
Expand Down
24 changes: 23 additions & 1 deletion drivers/gles3/storage/light_storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include "drivers/gles3/rasterizer_util_gles3.h"
#include "drivers/gles3/storage/render_scene_buffers_gles3.h"
#include "drivers/gles3/storage/utilities.h"
#include "servers/rendering/rendering_server.h"

using namespace GLES3;

Expand Down Expand Up @@ -1185,6 +1186,16 @@ void LightStorage::lightmap_set_baked_exposure_normalization(RID p_lightmap, flo
lightmap->baked_exposure = p_exposure;
}

void LightStorage::lightmap_set_modulate(RID p_lightmap, const Color &p_color) {
Lightmap *lightmap = lightmap_owner.get_or_null(p_lightmap);
ERR_FAIL_NULL(lightmap);

lightmap->modulate = p_color;
for (RID r : lightmap->lightmap_instances) {
RS::get_singleton()->instance_lightmap_update_geometries_captures(r);
}
}

PackedVector3Array LightStorage::lightmap_get_probe_capture_points(RID p_lightmap) const {
Lightmap *lightmap = lightmap_owner.get_or_null(p_lightmap);
ERR_FAIL_NULL_V(lightmap, PackedVector3Array());
Expand Down Expand Up @@ -1260,7 +1271,7 @@ void LightStorage::lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point,
for (int i = 0; i < 4; i++) {
float c = CLAMP(barycentric[i], 0.0, 1.0);
for (int j = 0; j < 9; j++) {
r_sh[j] += sh_colors[i][j] * c;
r_sh[j] += sh_colors[i][j] * c * lm->modulate;
}
}
}
Expand All @@ -1279,6 +1290,17 @@ float LightStorage::lightmap_get_probe_capture_update_speed() const {
return lightmap_probe_capture_update_speed;
}

void LightStorage::lightmap_insert_to_lightmap_instances(RID p_lightmap, RID p_instance) {
Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
ERR_FAIL_NULL(lm);
lm->lightmap_instances.insert(p_instance);
}
void LightStorage::lightmap_erase_from_lightmap_instances(RID p_lightmap, RID p_instance) {
Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
ERR_FAIL_NULL(lm);
lm->lightmap_instances.erase(p_instance);
}

void LightStorage::lightmap_set_shadowmask_textures(RID p_lightmap, RID p_shadow) {
Lightmap *lightmap = lightmap_owner.get_or_null(p_lightmap);
ERR_FAIL_NULL(lightmap);
Expand Down
6 changes: 6 additions & 0 deletions drivers/gles3/storage/light_storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,10 +179,12 @@ struct ReflectionProbeInstance {
struct Lightmap {
RID light_texture;
RID shadow_texture;
HashSet<RID> lightmap_instances;
bool uses_spherical_harmonics = false;
bool interior = false;
AABB bounds = AABB(Vector3(), Vector3(1, 1, 1));
float baked_exposure = 1.0;
Color modulate; // in linear space.
Vector2i light_texture_size;
int32_t array_index = -1; //unassigned
RSE::ShadowmaskMode shadowmask_mode = RSE::SHADOWMASK_MODE_NONE;
Expand Down Expand Up @@ -740,6 +742,7 @@ class LightStorage : public RendererLightStorage {
virtual void lightmap_set_probe_interior(RID p_lightmap, bool p_interior) override;
virtual void lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) override;
virtual void lightmap_set_baked_exposure_normalization(RID p_lightmap, float p_exposure) override;
virtual void lightmap_set_modulate(RID p_lightmap, const Color &p_color) override;
virtual PackedVector3Array lightmap_get_probe_capture_points(RID p_lightmap) const override;
virtual PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const override;
virtual PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const override;
Expand All @@ -750,6 +753,9 @@ class LightStorage : public RendererLightStorage {
virtual void lightmap_set_probe_capture_update_speed(float p_speed) override;
virtual float lightmap_get_probe_capture_update_speed() const override;

virtual void lightmap_insert_to_lightmap_instances(RID p_lightmap, RID p_instance) override;
virtual void lightmap_erase_from_lightmap_instances(RID p_lightmap, RID p_instance) override;

virtual void lightmap_set_shadowmask_textures(RID p_lightmap, RID p_shadow) override;
virtual RSE::ShadowmaskMode lightmap_get_shadowmask_mode(RID p_lightmap) override;
virtual void lightmap_set_shadowmask_mode(RID p_lightmap, RSE::ShadowmaskMode p_mode) override;
Expand Down
19 changes: 18 additions & 1 deletion scene/3d/lightmap_gi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#include "scene/resources/image_texture.h"
#include "scene/resources/sky.h"
#include "servers/rendering/rendering_server.h"
#include "servers/rendering/rendering_server_globals.h"

#include "modules/modules_enabled.gen.h" // IWYU pragma: keep. For lightmapper_rd.

Expand Down Expand Up @@ -287,6 +288,15 @@ float LightmapGIData::get_baked_exposure() const {
return baked_exposure;
}

void LightmapGIData::set_modulate(const Color &p_color) {
modulate = p_color;
RS::get_singleton()->lightmap_set_modulate(lightmap, p_color.srgb_to_linear());
}

Color LightmapGIData::get_modulate() const {
return modulate;
}

void LightmapGIData::_set_probe_data(const Dictionary &p_data) {
ERR_FAIL_COND(!p_data.has("bounds"));
ERR_FAIL_COND(!p_data.has("points"));
Expand Down Expand Up @@ -348,6 +358,9 @@ void LightmapGIData::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_shadowmask_textures", "shadowmask_textures"), &LightmapGIData::set_shadowmask_textures);
ClassDB::bind_method(D_METHOD("get_shadowmask_textures"), &LightmapGIData::get_shadowmask_textures);

ClassDB::bind_method(D_METHOD("set_modulate", "modulate"), &LightmapGIData::set_modulate);
ClassDB::bind_method(D_METHOD("get_modulate"), &LightmapGIData::get_modulate);

ClassDB::bind_method(D_METHOD("set_uses_spherical_harmonics", "uses_spherical_harmonics"), &LightmapGIData::set_uses_spherical_harmonics);
ClassDB::bind_method(D_METHOD("is_using_spherical_harmonics"), &LightmapGIData::is_using_spherical_harmonics);

Expand All @@ -362,6 +375,7 @@ void LightmapGIData::_bind_methods() {
ClassDB::bind_method(D_METHOD("_set_probe_data", "data"), &LightmapGIData::_set_probe_data);
ClassDB::bind_method(D_METHOD("_get_probe_data"), &LightmapGIData::_get_probe_data);

ADD_PROPERTY(PropertyInfo(Variant::COLOR, "modulate", PROPERTY_HINT_COLOR_NO_ALPHA), "set_modulate", "get_modulate");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "lightmap_textures", PROPERTY_HINT_ARRAY_TYPE, "TextureLayered", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_READ_ONLY), "set_lightmap_textures", "get_lightmap_textures");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "shadowmask_textures", PROPERTY_HINT_ARRAY_TYPE, "TextureLayered", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_READ_ONLY), "set_shadowmask_textures", "get_shadowmask_textures");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uses_spherical_harmonics", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_uses_spherical_harmonics", "is_using_spherical_harmonics");
Expand Down Expand Up @@ -1713,8 +1727,8 @@ void LightmapGI::_notification(int p_what) {
if (last_owner && last_owner != get_owner()) {
light_data->clear_users();
}

_assign_lightmaps();
RSG::light_storage->lightmap_insert_to_lightmap_instances(light_data->get_rid(), get_instance());
}
} break;

Expand All @@ -1723,6 +1737,7 @@ void LightmapGI::_notification(int p_what) {

if (light_data.is_valid()) {
_clear_lightmaps();
RSG::light_storage->lightmap_erase_from_lightmap_instances(light_data->get_rid(), get_instance());
}
} break;
}
Expand Down Expand Up @@ -1791,6 +1806,7 @@ void LightmapGI::set_light_data(const Ref<LightmapGIData> &p_data) {
_clear_lightmaps();
}
set_base(RID());
RSG::light_storage->lightmap_erase_from_lightmap_instances(light_data->get_rid(), get_instance());
}
light_data = p_data;

Expand All @@ -1800,6 +1816,7 @@ void LightmapGI::set_light_data(const Ref<LightmapGIData> &p_data) {
_assign_lightmaps();
}
light_data->update_shadowmask_mode(shadowmask_mode);
RSG::light_storage->lightmap_insert_to_lightmap_instances(light_data->get_rid(), get_instance());
}

update_gizmos();
Expand Down
4 changes: 4 additions & 0 deletions scene/3d/lightmap_gi.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ class LightmapGIData : public Resource {
RID lightmap;
AABB bounds;
float baked_exposure = 1.0;
Color modulate = Color(1, 1, 1, 1);
uint32_t lightprobe_hash = 0;

struct User {
Expand Down Expand Up @@ -121,6 +122,9 @@ class LightmapGIData : public Resource {
bool is_interior() const;
float get_baked_exposure() const;

void set_modulate(const Color &p_color);
Color get_modulate() const;

void set_capture_data(const AABB &p_bounds, bool p_interior, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree, float p_baked_exposure, uint32_t p_lightprobe_hash);
PackedVector3Array get_capture_points() const;
PackedColorArray get_capture_sh() const;
Expand Down
4 changes: 4 additions & 0 deletions servers/rendering/dummy/storage/light_storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ class LightStorage : public RendererLightStorage {
virtual void lightmap_set_probe_interior(RID p_lightmap, bool p_interior) override {}
virtual void lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) override {}
virtual void lightmap_set_baked_exposure_normalization(RID p_lightmap, float p_exposure) override {}
virtual void lightmap_set_modulate(RID p_lightmap, const Color &p_color) override {}
virtual PackedVector3Array lightmap_get_probe_capture_points(RID p_lightmap) const override { return PackedVector3Array(); }
virtual PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const override { return PackedColorArray(); }
virtual PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const override { return PackedInt32Array(); }
Expand All @@ -202,6 +203,9 @@ class LightStorage : public RendererLightStorage {
virtual void lightmap_set_probe_capture_update_speed(float p_speed) override {}
virtual float lightmap_get_probe_capture_update_speed() const override { return 0; }

virtual void lightmap_insert_to_lightmap_instances(RID p_lightmap, RID p_instance) override {}
virtual void lightmap_erase_from_lightmap_instances(RID p_lightmap, RID p_instance) override {}

virtual void lightmap_set_shadowmask_textures(RID p_lightmap, RID p_shadow) override {}
virtual RSE::ShadowmaskMode lightmap_get_shadowmask_mode(RID p_lightmap) override { return RSE::SHADOWMASK_MODE_NONE; }
virtual void lightmap_set_shadowmask_mode(RID p_lightmap, RSE::ShadowmaskMode p_mode) override {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1240,6 +1240,12 @@ void RenderForwardClustered::_setup_lightmaps(const RenderDataRD *p_render_data,
scene_state.lightmaps[i].exposure_normalization = enf / baked_exposure;
}

// Modulate
Color m = light_storage->lightmap_get_modulate(lightmap);
scene_state.lightmaps[i].modulate[0] = m.r;
scene_state.lightmaps[i].modulate[1] = m.g;
scene_state.lightmaps[i].modulate[2] = m.b;

scene_state.lightmap_ids[i] = p_lightmaps[i];
scene_state.lightmap_has_sh[i] = light_storage->lightmap_uses_spherical_harmonics(lightmap);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,8 @@ class RenderForwardClustered : public RendererSceneRenderRD {
float normal_xform[12];
float texture_size[2];
float exposure_normalization;
float pad;
float modulate[3];
uint32_t flags;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -754,6 +754,12 @@ void RenderForwardMobile::_setup_lightmaps(const RenderDataRD *p_render_data, co
scene_state.lightmaps[i].exposure_normalization = enf / baked_exposure;
}

// Modulate
Color m = light_storage->lightmap_get_modulate(lightmap);
scene_state.lightmaps[i].modulate[0] = m.r;
scene_state.lightmaps[i].modulate[1] = m.g;
scene_state.lightmaps[i].modulate[2] = m.b;

scene_state.lightmap_ids[i] = p_lightmaps[i];
scene_state.lightmap_has_sh[i] = light_storage->lightmap_uses_spherical_harmonics(lightmap);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,8 @@ class RenderForwardMobile : public RendererSceneRenderRD {
float normal_xform[12];
float texture_size[2];
float exposure_normalization;
float pad;
float modulate[3];
uint32_t flags;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1857,16 +1857,19 @@ void fragment_shader(in SceneData scene_data) {
vec3 n = normalize(lightmaps.data[ofs].normal_xform * indirect_normal);
float en = lightmaps.data[ofs].exposure_normalization;

ambient_light += lm_light_l0 * en;
ambient_light += lm_light_l1n1 * n.y * (lm_light_l0 * en * 4.0);
ambient_light += lm_light_l1_0 * n.z * (lm_light_l0 * en * 4.0);
ambient_light += lm_light_l1p1 * n.x * (lm_light_l0 * en * 4.0);
vec3 al = vec3(0.0, 0.0, 0.0);
al += lm_light_l0 * en;
al += lm_light_l1n1 * n.y * (lm_light_l0 * en * 4.0);
al += lm_light_l1_0 * n.z * (lm_light_l0 * en * 4.0);
al += lm_light_l1p1 * n.x * (lm_light_l0 * en * 4.0);

ambient_light += al * lightmaps.data[ofs].modulate;

} else {
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;
ambient_light += textureArray_bicubic(lightmap_textures[ofs], uvw, lightmaps.data[ofs].light_texture_size).rgb * lightmaps.data[ofs].exposure_normalization * lightmaps.data[ofs].modulate;
} else {
ambient_light += textureLod(sampler2DArray(lightmap_textures[ofs], SAMPLER_LINEAR_CLAMP), uvw, 0.0).rgb * lightmaps.data[ofs].exposure_normalization;
ambient_light += textureLod(sampler2DArray(lightmap_textures[ofs], SAMPLER_LINEAR_CLAMP), uvw, 0.0).rgb * lightmaps.data[ofs].exposure_normalization * lightmaps.data[ofs].modulate;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,8 @@ struct Lightmap {
mat3 normal_xform;
vec2 light_texture_size;
float exposure_normalization;
float pad;
vec3 modulate;
uint flags;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1745,15 +1745,19 @@ void main() {
hvec3 n = hvec3(normalize(lightmaps.data[ofs].normal_xform * indirect_normal));
half exposure_normalization = half(lightmaps.data[ofs].exposure_normalization);

ambient_light += lm_light_l0 * exposure_normalization;
ambient_light += lm_light_l1n1 * n.y * lm_light_l0 * exposure_normalization * half(4.0);
ambient_light += lm_light_l1_0 * n.z * lm_light_l0 * exposure_normalization * half(4.0);
ambient_light += lm_light_l1p1 * n.x * lm_light_l0 * exposure_normalization * half(4.0);
hvec3 al = hvec3(0.0, 0.0, 0.0);
al += lm_light_l0 * exposure_normalization;
al += lm_light_l1n1 * n.y * lm_light_l0 * exposure_normalization * half(4.0);
al += lm_light_l1_0 * n.z * lm_light_l0 * exposure_normalization * half(4.0);
al += lm_light_l1p1 * n.x * lm_light_l0 * exposure_normalization * half(4.0);

ambient_light += al * hvec3(lightmaps.data[ofs].modulate);

} else {
if (sc_use_lightmap_bicubic_filter()) {
ambient_light += hvec3(textureArray_bicubic(lightmap_textures[ofs], uvw, lightmaps.data[ofs].light_texture_size).rgb * lightmaps.data[ofs].exposure_normalization);
ambient_light += hvec3(textureArray_bicubic(lightmap_textures[ofs], uvw, lightmaps.data[ofs].light_texture_size).rgb * lightmaps.data[ofs].exposure_normalization * lightmaps.data[ofs].modulate);
} else {
ambient_light += hvec3(textureLod(sampler2DArray(lightmap_textures[ofs], SAMPLER_LINEAR_CLAMP), uvw, 0.0).rgb * lightmaps.data[ofs].exposure_normalization);
ambient_light += hvec3(textureLod(sampler2DArray(lightmap_textures[ofs], SAMPLER_LINEAR_CLAMP), uvw, 0.0).rgb * lightmaps.data[ofs].exposure_normalization * lightmaps.data[ofs].modulate);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,8 @@ struct Lightmap {
mat3 normal_xform;
vec2 light_texture_size;
float exposure_normalization;
float pad;
vec3 modulate;
uint flags;
};

Expand Down
Loading