Skip to content

Commit

Permalink
Mask out shadows on CanvasItems that don't have a matching item_shado…
Browse files Browse the repository at this point in the history
…w_mask

This restores the behavior from 3.x
  • Loading branch information
clayjohn committed Nov 22, 2024
1 parent f952bfe commit 2b68c63
Show file tree
Hide file tree
Showing 8 changed files with 200 additions and 175 deletions.
54 changes: 33 additions & 21 deletions drivers/gles3/rasterizer_canvas_gles3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -720,11 +720,14 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou
}
}

bool success = GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(shader_version, variant, specialization);
bool success = material_storage->shaders.canvas_shader.version_bind_shader(shader_version, variant, specialization);
if (!success) {
continue;
}

// Bind per-batch uniforms.
material_storage->shaders.canvas_shader.version_set_uniform(CanvasShaderGLES3::BATCH_FLAGS, state.canvas_instance_batches[i].flags, shader_version, variant, specialization);

GLES3::CanvasShaderData::BlendMode blend_mode = state.canvas_instance_batches[i].blend_mode;
Color blend_color = state.canvas_instance_batches[i].blend_color;

Expand Down Expand Up @@ -847,6 +850,7 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend
uint32_t lights[4] = { 0, 0, 0, 0 };

uint16_t light_count = 0;
uint16_t shadow_mask = 0;

{
Light *light = p_lights;
Expand All @@ -856,6 +860,10 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend
uint32_t light_index = light->render_index_cache;
lights[light_count >> 2] |= light_index << ((light_count & 3) * 8);

if (p_item->light_mask & light->item_shadow_mask) {
shadow_mask |= 1 << light_count;
}

light_count++;

if (light_count == data.max_lights_per_item - 1) {
Expand All @@ -865,7 +873,8 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend
light = light->next_ptr;
}

base_flags |= light_count << FLAGS_LIGHT_COUNT_SHIFT;
base_flags |= light_count << INSTANCE_FLAGS_LIGHT_COUNT_SHIFT;
base_flags |= shadow_mask << INSTANCE_FLAGS_SHADOW_MASKED_SHIFT;
}

bool lights_disabled = light_count == 0 && !state.using_directional_lights;
Expand Down Expand Up @@ -906,7 +915,7 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend
state.instance_data_array[r_index].lights[2] = lights[2];
state.instance_data_array[r_index].lights[3] = lights[3];

state.instance_data_array[r_index].flags = base_flags | (state.instance_data_array[r_index == 0 ? 0 : r_index - 1].flags & (FLAGS_DEFAULT_NORMAL_MAP_USED | FLAGS_DEFAULT_SPECULAR_MAP_USED)); // Reset on each command for safety, keep canvastexture binding config.
state.instance_data_array[r_index].flags = base_flags;

Color blend_color = base_color;
GLES3::CanvasShaderData::BlendMode blend_mode = p_blend_mode;
Expand Down Expand Up @@ -939,6 +948,7 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend
state.canvas_instance_batches[state.current_batch_index].command_type = Item::Command::TYPE_RECT;
state.canvas_instance_batches[state.current_batch_index].command = c;
state.canvas_instance_batches[state.current_batch_index].specialization &= specialization_command_mask;
state.canvas_instance_batches[state.current_batch_index].flags = 0;
}

_prepare_canvas_texture(rect->texture, state.canvas_instance_batches[state.current_batch_index].filter, state.canvas_instance_batches[state.current_batch_index].repeat, r_index, texpixel_size);
Expand All @@ -961,20 +971,18 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend

if (rect->flags & CANVAS_RECT_FLIP_H) {
src_rect.size.x *= -1;
state.instance_data_array[r_index].flags |= FLAGS_FLIP_H;
}

if (rect->flags & CANVAS_RECT_FLIP_V) {
src_rect.size.y *= -1;
state.instance_data_array[r_index].flags |= FLAGS_FLIP_V;
}

if (rect->flags & CANVAS_RECT_TRANSPOSE) {
state.instance_data_array[r_index].flags |= FLAGS_TRANSPOSE_RECT;
state.instance_data_array[r_index].flags |= INSTANCE_FLAGS_TRANSPOSE_RECT;
}

if (rect->flags & CANVAS_RECT_CLIP_UV) {
state.instance_data_array[r_index].flags |= FLAGS_CLIP_RECT_UV;
state.instance_data_array[r_index].flags |= INSTANCE_FLAGS_CLIP_RECT_UV;
}

} else {
Expand All @@ -993,13 +1001,13 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend
}

if (rect->flags & CANVAS_RECT_MSDF) {
state.instance_data_array[r_index].flags |= FLAGS_USE_MSDF;
state.instance_data_array[r_index].flags |= INSTANCE_FLAGS_USE_MSDF;
state.instance_data_array[r_index].msdf[0] = rect->px_range; // Pixel range.
state.instance_data_array[r_index].msdf[1] = rect->outline; // Outline size.
state.instance_data_array[r_index].msdf[2] = 0.f; // Reserved.
state.instance_data_array[r_index].msdf[3] = 0.f; // Reserved.
} else if (rect->flags & CANVAS_RECT_LCD) {
state.instance_data_array[r_index].flags |= FLAGS_USE_LCD;
state.instance_data_array[r_index].flags |= INSTANCE_FLAGS_USE_LCD;
}

state.instance_data_array[r_index].modulation[0] = rect->modulate.r * base_color.r;
Expand Down Expand Up @@ -1030,6 +1038,7 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend
state.canvas_instance_batches[state.current_batch_index].command = c;
state.canvas_instance_batches[state.current_batch_index].specialization &= specialization_command_mask;
state.canvas_instance_batches[state.current_batch_index].specialization |= CanvasShaderGLES3::USE_NINEPATCH;
state.canvas_instance_batches[state.current_batch_index].flags = 0;
}

_prepare_canvas_texture(np->texture, state.canvas_instance_batches[state.current_batch_index].filter, state.canvas_instance_batches[state.current_batch_index].repeat, r_index, texpixel_size);
Expand Down Expand Up @@ -1067,11 +1076,11 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend
state.instance_data_array[r_index].dst_rect[2] = dst_rect.size.width;
state.instance_data_array[r_index].dst_rect[3] = dst_rect.size.height;

state.instance_data_array[r_index].flags |= int(np->axis_x) << FLAGS_NINEPATCH_H_MODE_SHIFT;
state.instance_data_array[r_index].flags |= int(np->axis_y) << FLAGS_NINEPATCH_V_MODE_SHIFT;
state.instance_data_array[r_index].flags |= int(np->axis_x) << INSTANCE_FLAGS_NINEPATCH_H_MODE_SHIFT;
state.instance_data_array[r_index].flags |= int(np->axis_y) << INSTANCE_FLAGS_NINEPATCH_V_MODE_SHIFT;

if (np->draw_center) {
state.instance_data_array[r_index].flags |= FLAGS_NINEPACH_DRAW_CENTER;
state.instance_data_array[r_index].flags |= INSTANCE_FLAGS_NINEPACH_DRAW_CENTER;
}

state.instance_data_array[r_index].ninepatch_margins[0] = np->margin[SIDE_LEFT];
Expand All @@ -1097,6 +1106,7 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend
state.canvas_instance_batches[state.current_batch_index].command = c;
state.canvas_instance_batches[state.current_batch_index].specialization &= specialization_command_mask;
state.canvas_instance_batches[state.current_batch_index].specialization |= CanvasShaderGLES3::USE_ATTRIBUTES;
state.canvas_instance_batches[state.current_batch_index].flags = 0;

_prepare_canvas_texture(polygon->texture, state.canvas_instance_batches[state.current_batch_index].filter, state.canvas_instance_batches[state.current_batch_index].repeat, r_index, texpixel_size);

Expand Down Expand Up @@ -1125,6 +1135,7 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend
state.canvas_instance_batches[state.current_batch_index].command = c;
state.canvas_instance_batches[state.current_batch_index].specialization &= specialization_command_mask;
state.canvas_instance_batches[state.current_batch_index].specialization |= CanvasShaderGLES3::USE_PRIMITIVE;
state.canvas_instance_batches[state.current_batch_index].flags = 0;
}

_prepare_canvas_texture(state.canvas_instance_batches[state.current_batch_index].tex, state.canvas_instance_batches[state.current_batch_index].filter, state.canvas_instance_batches[state.current_batch_index].repeat, r_index, texpixel_size);
Expand Down Expand Up @@ -1165,12 +1176,13 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend
case Item::Command::TYPE_MESH:
case Item::Command::TYPE_MULTIMESH:
case Item::Command::TYPE_PARTICLES: {
// Mesh's can't be batched, so always create a new batch
// Meshes can't be batched, so always create a new batch.
_new_batch(r_batch_broken);

Color modulate(1, 1, 1, 1);
state.canvas_instance_batches[state.current_batch_index].specialization &= specialization_command_mask;
state.canvas_instance_batches[state.current_batch_index].specialization |= CanvasShaderGLES3::USE_ATTRIBUTES;
state.canvas_instance_batches[state.current_batch_index].flags = 0;
if (c->type == Item::Command::TYPE_MESH) {
const Item::CommandMesh *m = static_cast<const Item::CommandMesh *>(c);
state.canvas_instance_batches[state.current_batch_index].tex = m->texture;
Expand All @@ -1183,10 +1195,10 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend
state.canvas_instance_batches[state.current_batch_index].specialization |= CanvasShaderGLES3::USE_INSTANCING;

if (GLES3::MeshStorage::get_singleton()->multimesh_uses_colors(mm->multimesh)) {
state.instance_data_array[r_index].flags |= FLAGS_INSTANCING_HAS_COLORS;
state.canvas_instance_batches[state.current_batch_index].flags |= BATCH_FLAGS_INSTANCING_HAS_COLORS;
}
if (GLES3::MeshStorage::get_singleton()->multimesh_uses_custom_data(mm->multimesh)) {
state.instance_data_array[r_index].flags |= FLAGS_INSTANCING_HAS_CUSTOM_DATA;
state.canvas_instance_batches[state.current_batch_index].flags |= BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA;
}
} else if (c->type == Item::Command::TYPE_PARTICLES) {
GLES3::ParticlesStorage *particles_storage = GLES3::ParticlesStorage::get_singleton();
Expand All @@ -1196,8 +1208,8 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_rend
RID particles = pt->particles;
state.canvas_instance_batches[state.current_batch_index].tex = pt->texture;
state.canvas_instance_batches[state.current_batch_index].specialization |= CanvasShaderGLES3::USE_INSTANCING;
state.instance_data_array[r_index].flags |= FLAGS_INSTANCING_HAS_COLORS;
state.instance_data_array[r_index].flags |= FLAGS_INSTANCING_HAS_CUSTOM_DATA;
state.canvas_instance_batches[state.current_batch_index].flags |= BATCH_FLAGS_INSTANCING_HAS_COLORS;
state.canvas_instance_batches[state.current_batch_index].flags |= BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA;

if (particles_storage->particles_has_collision(particles) && texture_storage->render_target_is_sdf_enabled(p_render_target)) {
// Pass collision information.
Expand Down Expand Up @@ -2364,15 +2376,15 @@ void RasterizerCanvasGLES3::_prepare_canvas_texture(RID p_texture, RS::CanvasIte
GLES3::Texture *normal_map = texture_storage->get_texture(ct->normal_map);

if (ct->specular_color.a < 0.999) {
state.instance_data_array[r_index].flags |= FLAGS_DEFAULT_SPECULAR_MAP_USED;
state.canvas_instance_batches[state.current_batch_index].flags |= BATCH_FLAGS_DEFAULT_SPECULAR_MAP_USED;
} else {
state.instance_data_array[r_index].flags &= ~FLAGS_DEFAULT_SPECULAR_MAP_USED;
state.canvas_instance_batches[state.current_batch_index].flags &= ~BATCH_FLAGS_DEFAULT_SPECULAR_MAP_USED;
}

if (normal_map) {
state.instance_data_array[r_index].flags |= FLAGS_DEFAULT_NORMAL_MAP_USED;
state.canvas_instance_batches[state.current_batch_index].flags |= BATCH_FLAGS_DEFAULT_NORMAL_MAP_USED;
} else {
state.instance_data_array[r_index].flags &= ~FLAGS_DEFAULT_NORMAL_MAP_USED;
state.canvas_instance_batches[state.current_batch_index].flags &= ~BATCH_FLAGS_DEFAULT_NORMAL_MAP_USED;
}

state.instance_data_array[r_index].specular_shininess = uint32_t(CLAMP(ct->specular_color.a * 255.0, 0, 255)) << 24;
Expand Down
36 changes: 18 additions & 18 deletions drivers/gles3/rasterizer_canvas_gles3.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,29 +54,27 @@ class RasterizerCanvasGLES3 : public RendererCanvasRender {
_FORCE_INLINE_ void _update_transform_to_mat4(const Transform3D &p_transform, float *p_mat4);

enum {
INSTANCE_FLAGS_LIGHT_COUNT_SHIFT = 0, // 4 bits for light count.

FLAGS_INSTANCING_MASK = 0x7F,
FLAGS_INSTANCING_HAS_COLORS = (1 << 7),
FLAGS_INSTANCING_HAS_CUSTOM_DATA = (1 << 8),
INSTANCE_FLAGS_CLIP_RECT_UV = (1 << 4),
INSTANCE_FLAGS_TRANSPOSE_RECT = (1 << 5),
INSTANCE_FLAGS_USE_MSDF = (1 << 6),
INSTANCE_FLAGS_USE_LCD = (1 << 7),

FLAGS_CLIP_RECT_UV = (1 << 9),
FLAGS_TRANSPOSE_RECT = (1 << 10),
INSTANCE_FLAGS_NINEPACH_DRAW_CENTER = (1 << 8),
INSTANCE_FLAGS_NINEPATCH_H_MODE_SHIFT = 9,
INSTANCE_FLAGS_NINEPATCH_V_MODE_SHIFT = 11,

FLAGS_NINEPACH_DRAW_CENTER = (1 << 12),

FLAGS_USE_SKELETON = (1 << 15),
FLAGS_NINEPATCH_H_MODE_SHIFT = 16,
FLAGS_NINEPATCH_V_MODE_SHIFT = 18,
FLAGS_LIGHT_COUNT_SHIFT = 20,

FLAGS_DEFAULT_NORMAL_MAP_USED = (1 << 26),
FLAGS_DEFAULT_SPECULAR_MAP_USED = (1 << 27),
INSTANCE_FLAGS_SHADOW_MASKED_SHIFT = 13, // 16 bits.
};

FLAGS_USE_MSDF = (1 << 28),
FLAGS_USE_LCD = (1 << 29),
enum {
BATCH_FLAGS_INSTANCING_MASK = 0x7F,
BATCH_FLAGS_INSTANCING_HAS_COLORS = (1 << 7),
BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA = (1 << 8),

FLAGS_FLIP_H = (1 << 30),
FLAGS_FLIP_V = (1 << 31),
BATCH_FLAGS_DEFAULT_NORMAL_MAP_USED = (1 << 9),
BATCH_FLAGS_DEFAULT_SPECULAR_MAP_USED = (1 << 10),
};

enum {
Expand Down Expand Up @@ -279,6 +277,8 @@ class RasterizerCanvasGLES3 : public RendererCanvasRender {
const Item::Command *command = nullptr;
Item::Command::Type command_type = Item::Command::TYPE_ANIMATION_SLICE; // Can default to any type that doesn't form a batch.
uint32_t primitive_points = 0;

uint32_t flags = 0;
};

// DataBuffer contains our per-frame data. I.e. the resources that are updated each frame.
Expand Down
Loading

0 comments on commit 2b68c63

Please sign in to comment.