Skip to content

Commit

Permalink
Add GLES3 infrastructure for lightmap baking in the compatibility bac…
Browse files Browse the repository at this point in the history
…kend
  • Loading branch information
clayjohn committed Jan 25, 2024
1 parent 4b6ad34 commit efb1cba
Show file tree
Hide file tree
Showing 11 changed files with 532 additions and 85 deletions.
2 changes: 1 addition & 1 deletion doc/classes/LightmapGI.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
[b]Performance:[/b] [LightmapGI] provides the best possible run-time performance for global illumination. It is suitable for low-end hardware including integrated graphics and mobile devices.
[b]Note:[/b] Due to how lightmaps work, most properties only have a visible effect once lightmaps are baked again.
[b]Note:[/b] Lightmap baking on [CSGShape3D]s and [PrimitiveMesh]es is not supported, as these cannot store UV2 data required for baking.
[b]Note:[/b] If no custom lightmappers are installed, [LightmapGI] can only be baked when using the Vulkan backend (Forward+ or Mobile), not OpenGL.
[b]Note:[/b] If no custom lightmappers are installed, [LightmapGI] can only be baked from devices that support the Forward+ or Mobile rendering backends.
</description>
<tutorials>
<link title="Using Lightmap global illumination">$DOCS_URL/tutorials/3d/global_illumination/using_lightmap_gi.html</link>
Expand Down
12 changes: 11 additions & 1 deletion drivers/gles3/effects/copy_effects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,17 @@ void CopyEffects::copy_cube_to_rect(const Rect2 &p_rect) {
return;
}

copy.shader.version_set_uniform(CopyShaderGLES3::COPY_SECTION, p_rect.position.x, p_rect.position.y, p_rect.size.x, p_rect.size.y, copy.shader_version, CopyShaderGLES3::MODE_COPY_SECTION);
copy.shader.version_set_uniform(CopyShaderGLES3::COPY_SECTION, p_rect.position.x, p_rect.position.y, p_rect.size.x, p_rect.size.y, copy.shader_version, CopyShaderGLES3::MODE_CUBE_TO_OCTAHEDRAL);
draw_screen_quad();
}

void CopyEffects::copy_cube_to_panorama(float p_mip_level) {
bool success = copy.shader.version_bind_shader(copy.shader_version, CopyShaderGLES3::MODE_CUBE_TO_PANORAMA);
if (!success) {
return;
}

copy.shader.version_set_uniform(CopyShaderGLES3::MIP_LEVEL, p_mip_level, copy.shader_version, CopyShaderGLES3::MODE_CUBE_TO_PANORAMA);
draw_screen_quad();
}

Expand Down
1 change: 1 addition & 0 deletions drivers/gles3/effects/copy_effects.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class CopyEffects {
void copy_to_and_from_rect(const Rect2 &p_rect);
void copy_screen();
void copy_cube_to_rect(const Rect2 &p_rect);
void copy_cube_to_panorama(float p_mip_level);
void bilinear_blur(GLuint p_source_texture, int p_mipmap_count, const Rect2i &p_region);
void gaussian_blur(GLuint p_source_texture, int p_mipmap_count, const Rect2i &p_region, const Size2i &p_size);
void set_color(const Color &p_color, const Rect2i &p_region);
Expand Down
490 changes: 421 additions & 69 deletions drivers/gles3/rasterizer_scene_gles3.cpp

Large diffs are not rendered by default.

12 changes: 10 additions & 2 deletions drivers/gles3/rasterizer_scene_gles3.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ enum PassMode {
PASS_MODE_COLOR_TRANSPARENT,
PASS_MODE_SHADOW,
PASS_MODE_DEPTH,
PASS_MODE_MATERIAL,
};

// These should share as much as possible with SkyUniform Location
Expand Down Expand Up @@ -375,7 +376,7 @@ class RasterizerSceneGLES3 : public RendererSceneRender {
float ambient_light_color_energy[4];

float ambient_color_sky_mix;
uint32_t material_uv2_mode;
uint32_t pad2;
float emissive_exposure_normalization;
uint32_t use_ambient_light = 0;

Expand Down Expand Up @@ -465,13 +466,15 @@ class RasterizerSceneGLES3 : public RendererSceneRender {
bool reverse_cull = false;
uint64_t spec_constant_base_flags = 0;
bool force_wireframe = false;
Vector2 uv_offset = Vector2(0, 0);

RenderListParameters(GeometryInstanceSurface **p_elements, int p_element_count, bool p_reverse_cull, uint64_t p_spec_constant_base_flags, bool p_force_wireframe = false) {
RenderListParameters(GeometryInstanceSurface **p_elements, int p_element_count, bool p_reverse_cull, uint64_t p_spec_constant_base_flags, bool p_force_wireframe = false, Vector2 p_uv_offset = Vector2()) {
elements = p_elements;
element_count = p_element_count;
reverse_cull = p_reverse_cull;
spec_constant_base_flags = p_spec_constant_base_flags;
force_wireframe = p_force_wireframe;
uv_offset = p_uv_offset;
}
};

Expand Down Expand Up @@ -647,6 +650,10 @@ class RasterizerSceneGLES3 : public RendererSceneRender {
void _draw_sky(RID p_env, const Projection &p_projection, const Transform3D &p_transform, float p_luminance_multiplier, bool p_use_multiview, bool p_flip_y);
void _free_sky_data(Sky *p_sky);

// Needed for a single argument calls (material and uv2).
PagedArrayPool<RenderGeometryInstance *> cull_argument_pool;
PagedArray<RenderGeometryInstance *> cull_argument;

public:
static RasterizerSceneGLES3 *get_singleton() { return singleton; }

Expand Down Expand Up @@ -747,6 +754,7 @@ class RasterizerSceneGLES3 : public RendererSceneRender {
void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) override;

TypedArray<Image> bake_render_uv2(RID p_base, const TypedArray<RID> &p_material_overrides, const Size2i &p_image_size) override;
void _render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, GLuint p_framebuffer, const Rect2i &p_region);

bool free(RID p_rid) override;
void update() override;
Expand Down
39 changes: 35 additions & 4 deletions drivers/gles3/shaders/copy.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ mode_gaussian_blur = #define MODE_GAUSSIAN_BLUR
mode_mipmap = #define MODE_MIPMAP
mode_simple_color = #define MODE_SIMPLE_COLOR \n#define USE_COPY_SECTION
mode_cube_to_octahedral = #define CUBE_TO_OCTAHEDRAL \n#define USE_COPY_SECTION
mode_cube_to_panorama = #define CUBE_TO_PANORAMA

#[specializations]

Expand Down Expand Up @@ -53,21 +54,34 @@ uniform highp vec2 pixel_size;
#endif

#ifdef CUBE_TO_OCTAHEDRAL
uniform samplerCube source_cube; // texunit:0

vec3 oct_to_vec3(vec2 e) {
vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));
float t = max(-v.z, 0.0);
v.xy += t * -sign(v.xy);
return normalize(v);
}
#else
uniform sampler2D source; // texunit:0
#endif

#ifdef CUBE_TO_PANORAMA
uniform lowp float mip_level;
#endif

#if defined(CUBE_TO_OCTAHEDRAL) || defined(CUBE_TO_PANORAMA)
uniform samplerCube source_cube; // texunit:0

#else // ~(defined(CUBE_TO_OCTAHEDRAL) || defined(CUBE_TO_PANORAMA))
uniform sampler2D source; // texunit:0

#endif // !(defined(CUBE_TO_OCTAHEDRAL) || defined(CUBE_TO_PANORAMA))

layout(location = 0) out vec4 frag_color;

// This expects 0-1 range input, outside that range it behaves poorly.
vec3 srgb_to_linear(vec3 color) {
// Approximation from http://chilliant.blogspot.com/2012/08/srgb-approximations-for-hlsl.html
return color * (color * (color * 0.305306011 + 0.682171111) + 0.012522878);
}

void main() {
#ifdef MODE_SIMPLE_COPY
vec4 color = texture(source, uv_interp);
Expand Down Expand Up @@ -110,5 +124,22 @@ void main() {
vec3 dir = oct_to_vec3(uv_interp * 2.0 - 1.0);
frag_color = texture(source_cube, dir);

#endif

#ifdef CUBE_TO_PANORAMA

const float PI = 3.14159265359;

float phi = uv_interp.x * 2.0 * PI;
float theta = uv_interp.y * PI;

vec3 normal;
normal.x = sin(phi) * sin(theta) * -1.0;
normal.y = cos(theta);
normal.z = cos(phi) * sin(theta) * -1.0;

vec3 color = srgb_to_linear(textureLod(source_cube, normal, mip_level).rgb);
frag_color = vec4(color, 1.0);

#endif
}
52 changes: 46 additions & 6 deletions drivers/gles3/shaders/scene.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ USE_ADDITIVE_LIGHTING = false
// these are false, we are doing a directional light pass.
ADDITIVE_OMNI = false
ADDITIVE_SPOT = false
RENDER_MATERIAL = false


#[vertex]
Expand Down Expand Up @@ -90,7 +91,7 @@ layout(location = 3) in vec4 color_attrib;
layout(location = 4) in vec2 uv_attrib;
#endif

#if defined(UV2_USED) || defined(USE_LIGHTMAP)
#if defined(UV2_USED) || defined(USE_LIGHTMAP) || defined(RENDER_MATERIAL)
layout(location = 5) in vec2 uv2_attrib;
#endif

Expand Down Expand Up @@ -160,12 +161,12 @@ layout(std140) uniform SceneData { // ubo:2
mediump vec4 ambient_light_color_energy;

mediump float ambient_color_sky_mix;
bool material_uv2_mode;
float pad2;
float emissive_exposure_normalization;
bool use_ambient_light;

bool use_ambient_cubemap;
bool use_reflection_cubemap;

float fog_aerial_perspective;
float time;

Expand Down Expand Up @@ -249,6 +250,10 @@ uniform highp vec4 uv_scale;

uniform highp uint model_flags;

#ifdef RENDER_MATERIAL
uniform mediump vec2 uv_offset;
#endif

/* Varyings */

out highp vec3 vertex_interp;
Expand Down Expand Up @@ -511,6 +516,12 @@ void main() {
#else
gl_Position = projection_matrix * vec4(vertex_interp, 1.0);
#endif

#ifdef RENDER_MATERIAL
gl_Position.xy = (uv2_attrib.xy + uv_offset) * 2.0 - 1.0;
gl_Position.z = 0.00001;
gl_Position.w = 1.0;
#endif
}

/* clang-format off */
Expand Down Expand Up @@ -632,12 +643,12 @@ layout(std140) uniform SceneData { // ubo:2
mediump vec4 ambient_light_color_energy;

mediump float ambient_color_sky_mix;
bool material_uv2_mode;
float pad2;
float emissive_exposure_normalization;
bool use_ambient_light;

bool use_ambient_cubemap;
bool use_reflection_cubemap;

float fog_aerial_perspective;
float time;

Expand Down Expand Up @@ -878,8 +889,20 @@ vec2 multiview_uv(vec2 uv) {
uniform highp mat4 world_transform;
uniform mediump float opaque_prepass_threshold;

#ifndef MODE_RENDER_DEPTH
#ifdef RENDER_MATERIAL
layout(location = 0) out vec4 albedo_output_buffer;
layout(location = 1) out vec4 normal_output_buffer;
layout(location = 2) out vec4 orm_output_buffer;
layout(location = 3) out vec4 emission_output_buffer;

#else // !RENDER_MATERIAL
// Normal color rendering.
layout(location = 0) out vec4 frag_color;

#endif // !RENDER_MATERIAL
#endif // !MODE_RENDER_DEPTH

vec3 F0(float metallic, float specular, vec3 albedo) {
float dielectric = 0.16 * specular * specular;
// use albedo * metallic as colored specular reflectance at 0 angle for metallic materials;
Expand Down Expand Up @@ -1660,6 +1683,23 @@ void main() {

// Nothing happens, so a tree-ssa optimizer will result in no fragment shader :)
#else // !MODE_RENDER_DEPTH

#ifdef RENDER_MATERIAL

albedo_output_buffer.rgb = albedo;
albedo_output_buffer.a = alpha;

normal_output_buffer.rgb = normal * 0.5 + 0.5;
normal_output_buffer.a = 0.0;

orm_output_buffer.r = ao;
orm_output_buffer.g = roughness;
orm_output_buffer.b = metallic;
orm_output_buffer.a = 1.0;

emission_output_buffer.rgb = emission;
emission_output_buffer.a = 0.0;
#else // !RENDER_MATERIAL
#ifdef BASE_PASS
#ifdef MODE_UNSHADED
frag_color = vec4(albedo, alpha);
Expand Down Expand Up @@ -1914,6 +1954,6 @@ void main() {

frag_color.rgb += additive_light_color;
#endif // USE_ADDITIVE_LIGHTING

#endif // !RENDER_MATERIAL
#endif //!MODE_RENDER_DEPTH
}
4 changes: 4 additions & 0 deletions drivers/gles3/storage/texture_storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,10 @@ class TextureStorage : public RendererTextureStorage {
};
bool owns_texture(RID p_rid) { return texture_owner.owns(p_rid); };

void texture_2d_initialize_from_texture(RID p_texture, Texture &p_tex) {
texture_owner.initialize_rid(p_texture, p_tex);
}

virtual bool can_create_resources_async() const override;

virtual RID texture_allocate() override;
Expand Down
1 change: 1 addition & 0 deletions drivers/gles3/storage/utilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ class Utilities : public RendererUtilities {
}

// Records that data was allocated for state tracking purposes.
// Size is measured in bytes.
_FORCE_INLINE_ void texture_allocated_data(GLuint p_id, uint32_t p_size, String p_name = "") {
texture_mem_cache += p_size;
#ifdef DEV_ENABLED
Expand Down
2 changes: 1 addition & 1 deletion modules/lightmapper_rd/lightmapper_rd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -769,7 +769,7 @@ LightmapperRD::BakeError LightmapperRD::_dilate(RenderingDevice *rd, Ref<RDShade

#ifdef DEBUG_TEXTURES
for (int i = 0; i < atlas_slices; i++) {
Vector<uint8_t> s = rd->texture_get_data(light_accum_tex, i);
Vector<uint8_t> s = rd->texture_get_data(source_light_tex, i);
Ref<Image> img = Image::create_from_data(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s);
img->convert(Image::FORMAT_RGBA8);
img->save_png("res://5_dilated_" + itos(i) + ".png");
Expand Down
2 changes: 1 addition & 1 deletion scene/3d/lightmap_gi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1532,7 +1532,7 @@ PackedStringArray LightmapGI::get_configuration_warnings() const {
PackedStringArray warnings = Node::get_configuration_warnings();

if (OS::get_singleton()->get_current_rendering_method() == "gl_compatibility") {
warnings.push_back(RTR("Lightmap cannot be baked when using the GL Compatibility backend yet. Support will be added in a future release."));
warnings.push_back(RTR("Lightmap can only be baked from a device that supports the RD backends. Lightmap baking may fail."));
return warnings;
}

Expand Down

0 comments on commit efb1cba

Please sign in to comment.