Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add transparency support for LightmapGI #90109

Closed
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/ProjectSettings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2730,6 +2730,9 @@
<member name="rendering/lightmapping/bake_performance/max_rays_per_probe_pass" type="int" setter="" getter="" default="64">
The maximum number of rays that can be thrown per pass when baking dynamic object lighting in [LightmapProbe]s with [LightmapGI]. Depending on the scene, adjusting this value may result in higher GPU utilization when baking lightmaps, leading to faster bake times.
</member>
<member name="rendering/lightmapping/bake_performance/max_transparency_rays" type="int" setter="" getter="" default="64">
The maximum number of retry rays that can be thrown per pass when hitting a transparent surface when baking lightmaps with [LightmapGI]. Depending on the scene, reducing this value may lead to faster bake times.
</member>
<member name="rendering/lightmapping/bake_performance/region_size" type="int" setter="" getter="" default="512">
The region size to use when baking lightmaps with [LightmapGI].
</member>
Expand Down
28 changes: 16 additions & 12 deletions drivers/gles3/rasterizer_scene_gles3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -977,7 +977,7 @@ void RasterizerSceneGLES3::_update_sky_radiance(RID p_env, const Projection &p_p
glBindFramebuffer(GL_FRAMEBUFFER, sky->radiance_framebuffer);

scene_state.reset_gl_state();
scene_state.set_gl_cull_mode(GLES3::SceneShaderData::CULL_DISABLED);
scene_state.set_gl_cull_mode(RS::CULL_MODE_DISABLED);
scene_state.enable_gl_blend(false);

for (int i = 0; i < 6; i++) {
Expand All @@ -1000,7 +1000,7 @@ void RasterizerSceneGLES3::_update_sky_radiance(RID p_env, const Projection &p_p
} else {
if (sky_mode == RS::SKY_MODE_INCREMENTAL && sky->processing_layer < max_processing_layer) {
scene_state.reset_gl_state();
scene_state.set_gl_cull_mode(GLES3::SceneShaderData::CULL_DISABLED);
scene_state.set_gl_cull_mode(RS::CULL_MODE_DISABLED);
scene_state.enable_gl_blend(false);

cubemap_filter->filter_radiance(sky->raw_radiance, sky->radiance, sky->radiance_framebuffer, sky->radiance_size, sky->mipmap_count, sky->processing_layer);
Expand Down Expand Up @@ -1433,6 +1433,10 @@ void RasterizerSceneGLES3::_fill_render_list(RenderListType p_render_list, const
if (surf->flags & GeometryInstanceSurface::FLAG_PASS_SHADOW) {
rl->add_element(surf);
}
} else if (p_pass_mode == PASS_MODE_MATERIAL) {
if (surf->flags & (GeometryInstanceSurface::FLAG_PASS_DEPTH | GeometryInstanceSurface::FLAG_PASS_OPAQUE | GeometryInstanceSurface::FLAG_PASS_ALPHA)) {
rl->add_element(surf);
}
} else {
if (surf->flags & (GeometryInstanceSurface::FLAG_PASS_DEPTH | GeometryInstanceSurface::FLAG_PASS_OPAQUE)) {
rl->add_element(surf);
Expand Down Expand Up @@ -2210,7 +2214,7 @@ void RasterizerSceneGLES3::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
scene_state.enable_gl_depth_test(false);
scene_state.enable_gl_depth_draw(true);
glDisable(GL_CULL_FACE);
scene_state.cull_mode = GLES3::SceneShaderData::CULL_DISABLED;
scene_state.cull_mode = RS::CULL_MODE_DISABLED;
glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
}

Expand Down Expand Up @@ -2587,7 +2591,7 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
scene_state.enable_gl_depth_draw(false);
scene_state.enable_gl_depth_test(false);
scene_state.enable_gl_blend(false);
scene_state.set_gl_cull_mode(GLES3::SceneShaderData::CULL_BACK);
scene_state.set_gl_cull_mode(RS::CULL_MODE_BACK);

Ref<CameraFeed> feed = CameraServer::get_singleton()->get_feed_by_id(camera_feed_id);

Expand Down Expand Up @@ -2615,7 +2619,7 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_

scene_state.enable_gl_depth_test(true);
scene_state.enable_gl_blend(false);
scene_state.set_gl_cull_mode(GLES3::SceneShaderData::CULL_BACK);
scene_state.set_gl_cull_mode(RS::CULL_MODE_BACK);

Transform3D transform = render_data.cam_transform;
Projection projection = render_data.cam_projection;
Expand Down Expand Up @@ -3099,19 +3103,19 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
}

// Find cull variant.
GLES3::SceneShaderData::Cull cull_mode = shader->cull_mode;
RS::CullMode cull_mode = shader->cull_mode;

if (p_pass_mode == PASS_MODE_MATERIAL || (surf->flags & GeometryInstanceSurface::FLAG_USES_DOUBLE_SIDED_SHADOWS)) {
cull_mode = GLES3::SceneShaderData::CULL_DISABLED;
cull_mode = RS::CULL_MODE_DISABLED;
} else {
bool mirror = inst->mirror;
if (p_params->reverse_cull) {
mirror = !mirror;
}
if (cull_mode == GLES3::SceneShaderData::CULL_FRONT && mirror) {
cull_mode = GLES3::SceneShaderData::CULL_BACK;
} else if (cull_mode == GLES3::SceneShaderData::CULL_BACK && mirror) {
cull_mode = GLES3::SceneShaderData::CULL_FRONT;
if (cull_mode == RS::CULL_MODE_FRONT && mirror) {
cull_mode = RS::CULL_MODE_BACK;
} else if (cull_mode == RS::CULL_MODE_BACK && mirror) {
cull_mode = RS::CULL_MODE_FRONT;
}
}

Expand Down Expand Up @@ -3832,7 +3836,7 @@ void RasterizerSceneGLES3::_render_buffers_debug_draw(Ref<RenderSceneBuffersGLES
glActiveTexture(GL_TEXTURE0);
scene_state.enable_gl_depth_draw(true);
glDepthFunc(GL_ALWAYS);
scene_state.set_gl_cull_mode(GLES3::SceneShaderData::CULL_DISABLED);
scene_state.set_gl_cull_mode(RS::CULL_MODE_DISABLED);

// Loop through quadrants and copy shadows over.
for (int quadrant = 0; quadrant < 4; quadrant++) {
Expand Down
12 changes: 6 additions & 6 deletions drivers/gles3/rasterizer_scene_gles3.h
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ class RasterizerSceneGLES3 : public RendererSceneRender {
bool used_depth_prepass = false;

GLES3::SceneShaderData::BlendMode current_blend_mode = GLES3::SceneShaderData::BLEND_MODE_MIX;
GLES3::SceneShaderData::Cull cull_mode = GLES3::SceneShaderData::CULL_BACK;
RS::CullMode cull_mode = RS::CULL_MODE_BACK;

bool current_blend_enabled = false;
bool current_depth_draw_enabled = false;
Expand All @@ -477,24 +477,24 @@ class RasterizerSceneGLES3 : public RendererSceneRender {

glCullFace(GL_BACK);
glEnable(GL_CULL_FACE);
cull_mode = GLES3::SceneShaderData::CULL_BACK;
cull_mode = RS::CULL_MODE_BACK;

glDepthMask(GL_FALSE);
current_depth_draw_enabled = false;
glDisable(GL_DEPTH_TEST);
current_depth_test_enabled = false;
}

void set_gl_cull_mode(GLES3::SceneShaderData::Cull p_mode) {
void set_gl_cull_mode(RS::CullMode p_mode) {
if (cull_mode != p_mode) {
if (p_mode == GLES3::SceneShaderData::CULL_DISABLED) {
if (p_mode == RS::CULL_MODE_DISABLED) {
glDisable(GL_CULL_FACE);
} else {
if (cull_mode == GLES3::SceneShaderData::CULL_DISABLED) {
if (cull_mode == RS::CULL_MODE_DISABLED) {
// Last time was disabled, so enable and set proper face.
glEnable(GL_CULL_FACE);
}
glCullFace(p_mode == GLES3::SceneShaderData::CULL_FRONT ? GL_FRONT : GL_BACK);
glCullFace(p_mode == RS::CULL_MODE_FRONT ? GL_FRONT : GL_BACK);
}
cull_mode = p_mode;
}
Expand Down
16 changes: 16 additions & 0 deletions drivers/gles3/shaders/scene.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -1882,10 +1882,18 @@ void main() {
#ifndef USE_SHADOW_TO_OPACITY

#if defined(ALPHA_SCISSOR_USED)
#ifdef RENDER_MATERIAL
if (alpha < alpha_scissor_threshold) {
alpha = 0.0;
} else {
alpha = 1.0;
}
#else
if (alpha < alpha_scissor_threshold) {
discard;
}
alpha = 1.0;
#endif // RENDER_MATERIAL
#else
#ifdef MODE_RENDER_DEPTH
#ifdef USE_OPAQUE_PREPASS
Expand Down Expand Up @@ -2215,9 +2223,17 @@ void main() {
alpha = min(alpha, clamp(length(ambient_light), 0.0, 1.0));

#if defined(ALPHA_SCISSOR_USED)
#ifdef RENDER_MATERIAL
if (alpha < alpha_scissor_threshold) {
alpha = 0.0;
} else {
alpha = 1.0;
}
#else
if (alpha < alpha_scissor_threshold) {
discard;
}
#endif // RENDER_MATERIAL
#endif // !ALPHA_SCISSOR_USED

#endif // !MODE_RENDER_DEPTH
Expand Down
24 changes: 19 additions & 5 deletions drivers/gles3/storage/material_storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/

#include "core/error/error_macros.h"
#ifdef GLES3_ENABLED

#include "core/config/project_settings.h"
Expand Down Expand Up @@ -2505,6 +2506,19 @@ bool MaterialStorage::material_casts_shadows(RID p_material) {
return true; //by default everything casts shadows
}

RS::CullMode MaterialStorage::material_get_cull_mode(RID p_material) const {
const GLES3::Material *material = material_owner.get_or_null(p_material);
ERR_FAIL_NULL_V(material, RS::CULL_MODE_DISABLED);
ERR_FAIL_NULL_V(material->shader, RS::CULL_MODE_DISABLED);
if (material->shader->data) {
SceneShaderData *data = dynamic_cast<SceneShaderData *>(material->shader->data);
if (data) {
return (RS::CullMode)data->cull_mode;
}
}
return RS::CULL_MODE_DISABLED;
}

void MaterialStorage::material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) {
GLES3::Material *material = material_owner.get_or_null(p_material);
ERR_FAIL_NULL(material);
Expand Down Expand Up @@ -2907,7 +2921,7 @@ void SceneShaderData::set_code(const String &p_code) {
int blend_modei = BLEND_MODE_MIX;
int depth_testi = DEPTH_TEST_ENABLED;
int alpha_antialiasing_modei = ALPHA_ANTIALIASING_OFF;
int cull_modei = CULL_BACK;
int cull_modei = RS::CULL_MODE_BACK;
int depth_drawi = DEPTH_DRAW_OPAQUE;

ShaderCompiler::IdentifierActions actions;
Expand All @@ -2930,9 +2944,9 @@ void SceneShaderData::set_code(const String &p_code) {

actions.render_mode_values["depth_test_disabled"] = Pair<int *, int>(&depth_testi, DEPTH_TEST_DISABLED);

actions.render_mode_values["cull_disabled"] = Pair<int *, int>(&cull_modei, CULL_DISABLED);
actions.render_mode_values["cull_front"] = Pair<int *, int>(&cull_modei, CULL_FRONT);
actions.render_mode_values["cull_back"] = Pair<int *, int>(&cull_modei, CULL_BACK);
actions.render_mode_values["cull_disabled"] = Pair<int *, int>(&cull_modei, RS::CULL_MODE_DISABLED);
actions.render_mode_values["cull_front"] = Pair<int *, int>(&cull_modei, RS::CULL_MODE_FRONT);
actions.render_mode_values["cull_back"] = Pair<int *, int>(&cull_modei, RS::CULL_MODE_BACK);

actions.render_mode_flags["unshaded"] = &unshaded;
actions.render_mode_flags["wireframe"] = &wireframe;
Expand Down Expand Up @@ -2990,7 +3004,7 @@ void SceneShaderData::set_code(const String &p_code) {
alpha_antialiasing_mode = AlphaAntiAliasing(alpha_antialiasing_modei);
depth_draw = DepthDraw(depth_drawi);
depth_test = DepthTest(depth_testi);
cull_mode = Cull(cull_modei);
cull_mode = RS::CullMode(cull_modei);

vertex_input_mask = RS::ARRAY_FORMAT_VERTEX | RS::ARRAY_FORMAT_NORMAL; // We can always read vertices and normals.
vertex_input_mask |= uses_tangent << RS::ARRAY_TANGENT;
Expand Down
9 changes: 2 additions & 7 deletions drivers/gles3/storage/material_storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -263,12 +263,6 @@ struct SceneShaderData : public ShaderData {
DEPTH_TEST_ENABLED
};

enum Cull {
CULL_DISABLED,
CULL_FRONT,
CULL_BACK
};

enum AlphaAntiAliasing {
ALPHA_ANTIALIASING_OFF,
ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE,
Expand All @@ -292,7 +286,7 @@ struct SceneShaderData : public ShaderData {
AlphaAntiAliasing alpha_antialiasing_mode;
DepthDraw depth_draw;
DepthTest depth_test;
Cull cull_mode;
RS::CullMode cull_mode;

bool uses_point_size;
bool uses_alpha;
Expand Down Expand Up @@ -618,6 +612,7 @@ class MaterialStorage : public RendererMaterialStorage {

virtual bool material_is_animated(RID p_material) override;
virtual bool material_casts_shadows(RID p_material) override;
virtual RS::CullMode material_get_cull_mode(RID p_material) const override;

virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override;

Expand Down
15 changes: 14 additions & 1 deletion modules/lightmapper_rd/lightmapper_rd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

#include "lightmapper_rd.h"

#include "core/string/print_string.h"
#include "lm_blendseams.glsl.gen.h"
#include "lm_compute.glsl.gen.h"
#include "lm_raster.glsl.gen.h"
Expand All @@ -40,6 +41,7 @@
#include "editor/editor_paths.h"
#include "editor/editor_settings.h"
#include "servers/rendering/rendering_device_binds.h"
#include "servers/rendering/rendering_server_globals.h"

#if defined(VULKAN_ENABLED)
#include "drivers/vulkan/rendering_context_driver_vulkan.h"
Expand Down Expand Up @@ -477,7 +479,16 @@ void LightmapperRD::_create_acceleration_structures(RenderingDevice *rd, Size2i
t.max_bounds[0] = taabb.position.x + MAX(taabb.size.x, 0.0001);
t.max_bounds[1] = taabb.position.y + MAX(taabb.size.y, 0.0001);
t.max_bounds[2] = taabb.position.z + MAX(taabb.size.z, 0.0001);
t.pad0 = t.pad1 = 0; //make valgrind not complain

t.cull_mode = RS::CULL_MODE_BACK;

RID material = mi.data.material[i];
if (material.is_valid()) {
t.cull_mode = RSG::material_storage->material_get_cull_mode(material);
} else {
print_line("No material for mesh with vertex count ", mi.data.points.size());
}
t.pad1 = 0; //make valgrind not complain
triangles.push_back(t);
slice_triangle_count.write[t.slice]++;
}
Expand Down Expand Up @@ -1319,6 +1330,8 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
bake_parameters.bounces = p_bounces;
bake_parameters.bounce_indirect_energy = p_bounce_indirect_energy;
bake_parameters.shadowmask_light_idx = shadowmask_light_idx;
// Same number of rays for transparency regardless of quality (it's more of a retry rather than shooting new ones).
bake_parameters.transparency_rays = GLOBAL_GET("rendering/lightmapping/bake_performance/max_transparency_rays");

bake_parameters_buffer = rd->uniform_buffer_create(sizeof(BakeParameters));
rd->buffer_update(bake_parameters_buffer, 0, sizeof(BakeParameters), &bake_parameters);
Expand Down
7 changes: 4 additions & 3 deletions modules/lightmapper_rd/lightmapper_rd.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,9 @@ class LightmapperRD : public Lightmapper {
uint32_t bounces = 0;

float bounce_indirect_energy = 0.0f;
int shadowmask_light_idx = 0;
uint32_t pad[2] = {};
uint32_t shadowmask_light_idx = 0;
uint32_t transparency_rays = 0;
uint32_t pad[1] = {};
};

struct MeshInstance {
Expand Down Expand Up @@ -185,7 +186,7 @@ class LightmapperRD : public Lightmapper {
uint32_t indices[3] = {};
uint32_t slice = 0;
float min_bounds[3] = {};
float pad0 = 0.0;
uint32_t cull_mode = 0;
float max_bounds[3] = {};
float pad1 = 0.0;
bool operator<(const Triangle &p_triangle) const {
Expand Down
9 changes: 6 additions & 3 deletions modules/lightmapper_rd/lm_common_inc.glsl
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* SET 0, static data that does not change between any call */

layout(set = 0, binding = 0) uniform BakeParameters {
vec3 world_size;
Expand All @@ -18,8 +17,8 @@ layout(set = 0, binding = 0) uniform BakeParameters {

float bounce_indirect_energy;
int shadowmask_light_idx;
uint transparency_rays;
uint pad0;
uint pad1;
}
bake_params;

Expand All @@ -35,11 +34,15 @@ layout(set = 0, binding = 1, std430) restrict readonly buffer Vertices {
}
vertices;

#define CULL_DISABLED 0
#define CULL_FRONT 1
#define CULL_BACK 2

struct Triangle {
uvec3 indices;
uint slice;
vec3 min_bounds;
uint pad0;
uint cull_mode;
vec3 max_bounds;
uint pad1;
};
Expand Down
Loading
Loading