summaryrefslogtreecommitdiffstats
path: root/servers/rendering/renderer_rd/shaders
diff options
context:
space:
mode:
Diffstat (limited to 'servers/rendering/renderer_rd/shaders')
-rw-r--r--servers/rendering/renderer_rd/shaders/blit.glsl18
-rw-r--r--servers/rendering/renderer_rd/shaders/canvas.glsl8
-rw-r--r--servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl8
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/cube_to_dp.glsl5
-rw-r--r--servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl44
-rw-r--r--servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl37
-rw-r--r--servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl328
-rw-r--r--servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl75
8 files changed, 244 insertions, 279 deletions
diff --git a/servers/rendering/renderer_rd/shaders/blit.glsl b/servers/rendering/renderer_rd/shaders/blit.glsl
index d451647bec..fe6416f03c 100644
--- a/servers/rendering/renderer_rd/shaders/blit.glsl
+++ b/servers/rendering/renderer_rd/shaders/blit.glsl
@@ -8,6 +8,10 @@ layout(push_constant, std140) uniform Pos {
vec4 src_rect;
vec4 dst_rect;
+ float rotation_sin;
+ float rotation_cos;
+ vec2 pad;
+
vec2 eye_center;
float k1;
float k2;
@@ -15,17 +19,23 @@ layout(push_constant, std140) uniform Pos {
float upscale;
float aspect_ratio;
uint layer;
- uint pad1;
+ bool convert_to_srgb;
}
data;
layout(location = 0) out vec2 uv;
void main() {
+ mat4 swapchain_transform = mat4(1.0);
+ swapchain_transform[0][0] = data.rotation_cos;
+ swapchain_transform[0][1] = -data.rotation_sin;
+ swapchain_transform[1][0] = data.rotation_sin;
+ swapchain_transform[1][1] = data.rotation_cos;
+
vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
uv = data.src_rect.xy + base_arr[gl_VertexIndex] * data.src_rect.zw;
vec2 vtx = data.dst_rect.xy + base_arr[gl_VertexIndex] * data.dst_rect.zw;
- gl_Position = vec4(vtx * 2.0 - 1.0, 0.0, 1.0);
+ gl_Position = swapchain_transform * vec4(vtx * 2.0 - 1.0, 0.0, 1.0);
}
#[fragment]
@@ -38,6 +48,10 @@ layout(push_constant, std140) uniform Pos {
vec4 src_rect;
vec4 dst_rect;
+ float rotation_sin;
+ float rotation_cos;
+ vec2 pad;
+
vec2 eye_center;
float k1;
float k2;
diff --git a/servers/rendering/renderer_rd/shaders/canvas.glsl b/servers/rendering/renderer_rd/shaders/canvas.glsl
index dafcce37ad..f665bc24a4 100644
--- a/servers/rendering/renderer_rd/shaders/canvas.glsl
+++ b/servers/rendering/renderer_rd/shaders/canvas.glsl
@@ -28,7 +28,7 @@ layout(location = 11) in vec4 weight_attrib;
layout(location = 4) out flat uint instance_index_interp;
-#endif // USE_ATTRIBUTES
+#endif // !USE_ATTRIBUTES
layout(location = 0) out vec2 uv_interp;
layout(location = 1) out vec4 color_interp;
@@ -322,11 +322,7 @@ vec4 light_compute(
#ifdef USE_NINEPATCH
float map_ninepatch_axis(float pixel, float draw_size, float tex_pixel_size, float margin_begin, float margin_end, int np_repeat, inout int draw_center) {
-#ifdef USE_ATTRIBUTES
- const InstanceData draw_data = instances.data[params.base_instance_index];
-#else
const InstanceData draw_data = instances.data[instance_index];
-#endif // USE_ATTRIBUTES
float tex_size = 1.0 / tex_pixel_size;
@@ -567,7 +563,7 @@ void main() {
if (specular_shininess_used || (using_light && normal_used && bool(draw_data.flags & FLAGS_DEFAULT_SPECULAR_MAP_USED))) {
specular_shininess = texture(sampler2D(specular_texture, texture_sampler), uv);
- specular_shininess *= unpackUnorm4x8(draw_data.specular_shininess);
+ specular_shininess *= unpackUnorm4x8(params.specular_shininess);
specular_shininess_used = true;
} else {
specular_shininess = vec4(1.0);
diff --git a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl
index ead8c459a4..84017a1fe1 100644
--- a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl
@@ -37,7 +37,7 @@ struct InstanceData {
vec2 world_y;
vec2 world_ofs;
uint flags;
- uint specular_shininess;
+ uint pad2;
#ifdef USE_PRIMITIVE
vec2 points[3];
vec2 uvs[3];
@@ -57,8 +57,8 @@ struct InstanceData {
layout(push_constant, std430) uniform Params {
uint base_instance_index; // base index to instance data
uint sc_packed_0;
- uint pad2;
- uint pad3;
+ uint specular_shininess;
+ uint pad;
}
params;
@@ -68,7 +68,7 @@ params;
// Pull the constants from the draw call's push constants.
uint sc_packed_0() {
- return draw_call.sc_packed_0;
+ return params.sc_packed_0;
}
#else
diff --git a/servers/rendering/renderer_rd/shaders/effects/cube_to_dp.glsl b/servers/rendering/renderer_rd/shaders/effects/cube_to_dp.glsl
index 3fb93dda35..b45e310b61 100644
--- a/servers/rendering/renderer_rd/shaders/effects/cube_to_dp.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/cube_to_dp.glsl
@@ -8,7 +8,6 @@ layout(push_constant, std430) uniform Params {
float z_far;
float z_near;
vec2 texel_size;
- vec4 screen_rect;
}
params;
@@ -17,8 +16,7 @@ layout(location = 0) out vec2 uv_interp;
void main() {
vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
uv_interp = base_arr[gl_VertexIndex];
- vec2 screen_pos = uv_interp * params.screen_rect.zw + params.screen_rect.xy;
- gl_Position = vec4(screen_pos * 2.0 - 1.0, 0.0, 1.0);
+ gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0);
}
#[fragment]
@@ -35,7 +33,6 @@ layout(push_constant, std430) uniform Params {
float z_far;
float z_near;
vec2 texel_size;
- vec4 screen_rect;
}
params;
diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl
index 72236dcd9f..81d3d87a22 100644
--- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl
+++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl
@@ -211,6 +211,13 @@ vec3 double_add_vec3(vec3 base_a, vec3 prec_a, vec3 base_b, vec3 prec_b, out vec
}
#endif
+uint multimesh_stride() {
+ uint stride = sc_multimesh_format_2d() ? 2 : 3;
+ stride += sc_multimesh_has_color() ? 1 : 0;
+ stride += sc_multimesh_has_custom_data() ? 1 : 0;
+ return stride;
+}
+
void vertex_shader(vec3 vertex_input,
#ifdef NORMAL_USED
in vec3 normal_input,
@@ -219,7 +226,7 @@ void vertex_shader(vec3 vertex_input,
in vec3 tangent_input,
in vec3 binormal_input,
#endif
- in uint instance_index, in bool is_multimesh, in uint multimesh_offset, in SceneData scene_data, in mat4 model_matrix, out vec4 screen_pos) {
+ in uint instance_index, in uint multimesh_offset, in SceneData scene_data, in mat4 model_matrix, out vec4 screen_pos) {
vec4 instance_custom = vec4(0.0);
#if defined(COLOR_USED)
color_interp = color_attrib;
@@ -248,7 +255,7 @@ void vertex_shader(vec3 vertex_input,
mat4 matrix;
mat4 read_model_matrix = model_matrix;
- if (is_multimesh) {
+ if (sc_multimesh()) {
//multimesh, instances are for it
#ifdef USE_PARTICLE_TRAILS
@@ -296,25 +303,10 @@ void vertex_shader(vec3 vertex_input,
#endif
#else
- uint stride = 0;
- {
- //TODO implement a small lookup table for the stride
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) {
- stride += 2;
- } else {
- stride += 3;
- }
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_COLOR)) {
- stride += 1;
- }
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA)) {
- stride += 1;
- }
- }
-
+ uint stride = multimesh_stride();
uint offset = stride * (gl_InstanceIndex + multimesh_offset);
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) {
+ if (sc_multimesh_format_2d()) {
matrix = mat4(transforms.data[offset + 0], transforms.data[offset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));
offset += 2;
} else {
@@ -322,14 +314,14 @@ void vertex_shader(vec3 vertex_input,
offset += 3;
}
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_COLOR)) {
+ if (sc_multimesh_has_color()) {
#ifdef COLOR_USED
color_interp *= transforms.data[offset];
#endif
offset += 1;
}
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA)) {
+ if (sc_multimesh_has_custom_data()) {
instance_custom = transforms.data[offset];
}
@@ -427,7 +419,7 @@ void vertex_shader(vec3 vertex_input,
// Then we combine the translations from the model matrix and the view matrix using emulated doubles.
// We add the result to the vertex and ignore the final lost precision.
vec3 model_origin = model_matrix[3].xyz;
- if (is_multimesh) {
+ if (sc_multimesh()) {
vertex = mat3(matrix) * vertex;
model_origin = double_add_vec3(model_origin, model_precision, matrix[3].xyz, vec3(0.0), model_precision);
}
@@ -708,9 +700,7 @@ void _unpack_vertex_attributes(vec4 p_vertex_in, vec3 p_compressed_aabb_position
void main() {
uint instance_index = draw_call.instance_index;
-
- bool is_multimesh = bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH);
- if (!is_multimesh) {
+ if (!sc_multimesh()) {
instance_index += gl_InstanceIndex;
}
@@ -753,7 +743,7 @@ void main() {
prev_tangent,
prev_binormal,
#endif
- instance_index, is_multimesh, draw_call.multimesh_motion_vectors_previous_offset, scene_data_block.prev_data, instances.data[instance_index].prev_transform, prev_screen_position);
+ instance_index, draw_call.multimesh_motion_vectors_previous_offset, scene_data_block.prev_data, instances.data[instance_index].prev_transform, prev_screen_position);
#else
// Unused output.
vec4 screen_position;
@@ -792,7 +782,7 @@ void main() {
tangent,
binormal,
#endif
- instance_index, is_multimesh, draw_call.multimesh_motion_vectors_current_offset, scene_data_block.data, model_matrix, screen_position);
+ instance_index, draw_call.multimesh_motion_vectors_current_offset, scene_data_block.data, model_matrix, screen_position);
}
#[fragment]
diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl
index 9f68d59be2..8f153f7ed5 100644
--- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl
@@ -59,6 +59,10 @@ uint sc_packed_0() {
return draw_call.sc_packed_0;
}
+uint sc_packed_1() {
+ return draw_call.sc_packed_1;
+}
+
uint uc_cull_mode() {
return (draw_call.uc_packed_0 >> 0) & 3U;
}
@@ -67,11 +71,16 @@ uint uc_cull_mode() {
// Pull the constants from the pipeline's specialization constants.
layout(constant_id = 0) const uint pso_sc_packed_0 = 0;
+layout(constant_id = 1) const uint pso_sc_packed_1 = 0;
uint sc_packed_0() {
return pso_sc_packed_0;
}
+uint sc_packed_1() {
+ return pso_sc_packed_1;
+}
+
#endif
bool sc_use_forward_gi() {
@@ -107,19 +116,35 @@ bool sc_use_lightmap_bicubic_filter() {
}
uint sc_soft_shadow_samples() {
- return (sc_packed_0() >> 8) & 15U;
+ return (sc_packed_0() >> 8) & 63U;
}
uint sc_penumbra_shadow_samples() {
- return (sc_packed_0() >> 12) & 15U;
+ return (sc_packed_0() >> 14) & 63U;
}
uint sc_directional_soft_shadow_samples() {
- return (sc_packed_0() >> 16) & 15U;
+ return (sc_packed_0() >> 20) & 63U;
}
uint sc_directional_penumbra_shadow_samples() {
- return (sc_packed_0() >> 20) & 15U;
+ return (sc_packed_0() >> 26) & 63U;
+}
+
+bool sc_multimesh() {
+ return ((sc_packed_1() >> 0) & 1U) != 0;
+}
+
+bool sc_multimesh_format_2d() {
+ return ((sc_packed_1() >> 1) & 1U) != 0;
+}
+
+bool sc_multimesh_has_color() {
+ return ((sc_packed_1() >> 2) & 1U) != 0;
+}
+
+bool sc_multimesh_has_custom_data() {
+ return ((sc_packed_1() >> 3) & 1U) != 0;
}
float sc_luminance_multiplier() {
@@ -144,10 +169,6 @@ layout(set = 0, binding = 2) uniform sampler shadow_sampler;
#define INSTANCE_FLAGS_USE_SH_LIGHTMAP (1 << 9)
#define INSTANCE_FLAGS_USE_VOXEL_GI (1 << 10)
#define INSTANCE_FLAGS_PARTICLES (1 << 11)
-#define INSTANCE_FLAGS_MULTIMESH (1 << 12)
-#define INSTANCE_FLAGS_MULTIMESH_FORMAT_2D (1 << 13)
-#define INSTANCE_FLAGS_MULTIMESH_HAS_COLOR (1 << 14)
-#define INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA (1 << 15)
#define INSTANCE_FLAGS_PARTICLE_TRAIL_SHIFT 16
#define INSTANCE_FLAGS_FADE_SHIFT 24
//3 bits of stride
diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl
index 2f0e4e0bea..404f658fa6 100644
--- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl
+++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl
@@ -178,6 +178,13 @@ vec3 double_add_vec3(vec3 base_a, vec3 prec_a, vec3 base_b, vec3 prec_b, out vec
}
#endif
+uint multimesh_stride() {
+ uint stride = sc_multimesh_format_2d() ? 2 : 3;
+ stride += sc_multimesh_has_color() ? 1 : 0;
+ stride += sc_multimesh_has_custom_data() ? 1 : 0;
+ return stride;
+}
+
void main() {
vec4 instance_custom = vec4(0.0);
#if defined(COLOR_USED)
@@ -208,7 +215,7 @@ void main() {
mat4 matrix;
mat4 read_model_matrix = model_matrix;
- if (sc_is_multimesh()) {
+ if (sc_multimesh()) {
//multimesh, instances are for it
#ifdef USE_PARTICLE_TRAILS
@@ -256,25 +263,10 @@ void main() {
#endif
#else
- uint stride = 0;
- {
- //TODO implement a small lookup table for the stride
- if (bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) {
- stride += 2;
- } else {
- stride += 3;
- }
- if (bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_COLOR)) {
- stride += 1;
- }
- if (bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA)) {
- stride += 1;
- }
- }
-
+ uint stride = multimesh_stride();
uint offset = stride * gl_InstanceIndex;
- if (bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) {
+ if (sc_multimesh_format_2d()) {
matrix = mat4(transforms.data[offset + 0], transforms.data[offset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));
offset += 2;
} else {
@@ -282,14 +274,14 @@ void main() {
offset += 3;
}
- if (bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_COLOR)) {
+ if (sc_multimesh_has_color()) {
#ifdef COLOR_USED
color_interp *= transforms.data[offset];
#endif
offset += 1;
}
- if (bool(instances.data[draw_call.instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA)) {
+ if (sc_multimesh_has_custom_data()) {
instance_custom = transforms.data[offset];
}
@@ -404,7 +396,7 @@ void main() {
// Then we combine the translations from the model matrix and the view matrix using emulated doubles.
// We add the result to the vertex and ignore the final lost precision.
vec3 model_origin = model_matrix[3].xyz;
- if (sc_is_multimesh()) {
+ if (sc_multimesh()) {
vertex = mat3(matrix) * vertex;
model_origin = double_add_vec3(model_origin, model_precision, matrix[3].xyz, vec3(0.0), model_precision);
}
@@ -461,50 +453,24 @@ void main() {
diffuse_light_interp = vec4(0.0);
specular_light_interp = vec4(0.0);
- if (!sc_disable_omni_lights()) {
- uint light_indices = instances.data[draw_call.instance_index].omni_lights.x;
- for (uint i = 0; i < 8; i++) {
- uint light_index = light_indices & 0xFF;
- if (i == 3) {
- light_indices = instances.data[draw_call.instance_index].omni_lights.y;
- } else {
- light_indices = light_indices >> 8;
- }
-
- if (light_index == 0xFF) {
- break;
- }
-
- light_process_omni_vertex(light_index, vertex, view, normal, roughness,
- diffuse_light_interp.rgb, specular_light_interp.rgb);
- }
+ uvec2 omni_light_indices = instances.data[draw_call.instance_index].omni_lights;
+ for (uint i = 0; i < sc_omni_lights(); i++) {
+ uint light_index = (i > 3) ? ((omni_light_indices.y >> ((i - 4) * 8)) & 0xFF) : ((omni_light_indices.x >> (i * 8)) & 0xFF);
+ light_process_omni_vertex(light_index, vertex, view, normal, roughness, diffuse_light_interp.rgb, specular_light_interp.rgb);
}
- if (!sc_disable_spot_lights()) {
- uint light_indices = instances.data[draw_call.instance_index].spot_lights.x;
- for (uint i = 0; i < 8; i++) {
- uint light_index = light_indices & 0xFF;
- if (i == 3) {
- light_indices = instances.data[draw_call.instance_index].spot_lights.y;
- } else {
- light_indices = light_indices >> 8;
- }
-
- if (light_index == 0xFF) {
- break;
- }
-
- light_process_spot_vertex(light_index, vertex, view, normal, roughness,
- diffuse_light_interp.rgb, specular_light_interp.rgb);
- }
+ uvec2 spot_light_indices = instances.data[draw_call.instance_index].spot_lights;
+ for (uint i = 0; i < sc_spot_lights(); i++) {
+ uint light_index = (i > 3) ? ((spot_light_indices.y >> ((i - 4) * 8)) & 0xFF) : ((spot_light_indices.x >> (i * 8)) & 0xFF);
+ light_process_spot_vertex(light_index, vertex, view, normal, roughness, diffuse_light_interp.rgb, specular_light_interp.rgb);
}
- if (!sc_disable_directional_lights()) {
+ if (sc_directional_lights() > 0) {
// We process the first directional light separately as it may have shadows.
vec3 directional_diffuse = vec3(0.0);
vec3 directional_specular = vec3(0.0);
- for (uint i = 0; i < scene_data.directional_light_count; i++) {
+ for (uint i = 0; i < sc_directional_lights(); i++) {
if (!bool(directional_lights.data[i].mask & instances.data[draw_call.instance_index].layer_mask)) {
continue; // Not masked, skip.
}
@@ -823,7 +789,7 @@ vec4 fog_process(vec3 vertex) {
float sun_total = 0.0;
vec3 view = normalize(vertex);
- for (uint i = 0; i < scene_data_block.data.directional_light_count; i++) {
+ for (uint i = 0; i < sc_directional_lights(); i++) {
vec3 light_color = directional_lights.data[i].color * directional_lights.data[i].energy;
float light_amount = pow(max(dot(view, directional_lights.data[i].direction), 0.0), 8.0);
fog_color += light_color * light_amount * scene_data_block.data.fog_sun_scatter;
@@ -1110,97 +1076,83 @@ void main() {
vec3 vertex_ddx = dFdx(vertex);
vec3 vertex_ddy = dFdy(vertex);
- if (!sc_disable_decals()) { //Decals
- // must implement
-
- uint decal_indices = instances.data[draw_call.instance_index].decals.x;
- for (uint i = 0; i < 8; i++) {
- uint decal_index = decal_indices & 0xFF;
- if (i == 3) {
- decal_indices = instances.data[draw_call.instance_index].decals.y;
- } else {
- decal_indices = decal_indices >> 8;
- }
+ uvec2 decal_indices = instances.data[draw_call.instance_index].decals;
+ for (uint i = 0; i < sc_decals(); i++) {
+ uint decal_index = (i > 3) ? ((decal_indices.y >> ((i - 4) * 8)) & 0xFF) : ((decal_indices.x >> (i * 8)) & 0xFF);
+ if (!bool(decals.data[decal_index].mask & instances.data[draw_call.instance_index].layer_mask)) {
+ continue; //not masked
+ }
- if (decal_index == 0xFF) {
- break;
- }
+ vec3 uv_local = (decals.data[decal_index].xform * vec4(vertex, 1.0)).xyz;
+ if (any(lessThan(uv_local, vec3(0.0, -1.0, 0.0))) || any(greaterThan(uv_local, vec3(1.0)))) {
+ continue; //out of decal
+ }
- if (!bool(decals.data[decal_index].mask & instances.data[draw_call.instance_index].layer_mask)) {
- continue; //not masked
- }
+ float fade = pow(1.0 - (uv_local.y > 0.0 ? uv_local.y : -uv_local.y), uv_local.y > 0.0 ? decals.data[decal_index].upper_fade : decals.data[decal_index].lower_fade);
- vec3 uv_local = (decals.data[decal_index].xform * vec4(vertex, 1.0)).xyz;
- if (any(lessThan(uv_local, vec3(0.0, -1.0, 0.0))) || any(greaterThan(uv_local, vec3(1.0)))) {
- continue; //out of decal
- }
+ if (decals.data[decal_index].normal_fade > 0.0) {
+ fade *= smoothstep(decals.data[decal_index].normal_fade, 1.0, dot(normal_interp, decals.data[decal_index].normal) * 0.5 + 0.5);
+ }
- float fade = pow(1.0 - (uv_local.y > 0.0 ? uv_local.y : -uv_local.y), uv_local.y > 0.0 ? decals.data[decal_index].upper_fade : decals.data[decal_index].lower_fade);
+ //we need ddx/ddy for mipmaps, so simulate them
+ vec2 ddx = (decals.data[decal_index].xform * vec4(vertex_ddx, 0.0)).xz;
+ vec2 ddy = (decals.data[decal_index].xform * vec4(vertex_ddy, 0.0)).xz;
- if (decals.data[decal_index].normal_fade > 0.0) {
- fade *= smoothstep(decals.data[decal_index].normal_fade, 1.0, dot(normal_interp, decals.data[decal_index].normal) * 0.5 + 0.5);
+ if (decals.data[decal_index].albedo_rect != vec4(0.0)) {
+ //has albedo
+ vec4 decal_albedo;
+ if (sc_decal_use_mipmaps()) {
+ decal_albedo = textureGrad(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].albedo_rect.zw + decals.data[decal_index].albedo_rect.xy, ddx * decals.data[decal_index].albedo_rect.zw, ddy * decals.data[decal_index].albedo_rect.zw);
+ } else {
+ decal_albedo = textureLod(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].albedo_rect.zw + decals.data[decal_index].albedo_rect.xy, 0.0);
}
+ decal_albedo *= decals.data[decal_index].modulate;
+ decal_albedo.a *= fade;
+ albedo = mix(albedo, decal_albedo.rgb, decal_albedo.a * decals.data[decal_index].albedo_mix);
- //we need ddx/ddy for mipmaps, so simulate them
- vec2 ddx = (decals.data[decal_index].xform * vec4(vertex_ddx, 0.0)).xz;
- vec2 ddy = (decals.data[decal_index].xform * vec4(vertex_ddy, 0.0)).xz;
-
- if (decals.data[decal_index].albedo_rect != vec4(0.0)) {
- //has albedo
- vec4 decal_albedo;
+ if (decals.data[decal_index].normal_rect != vec4(0.0)) {
+ vec3 decal_normal;
if (sc_decal_use_mipmaps()) {
- decal_albedo = textureGrad(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].albedo_rect.zw + decals.data[decal_index].albedo_rect.xy, ddx * decals.data[decal_index].albedo_rect.zw, ddy * decals.data[decal_index].albedo_rect.zw);
+ decal_normal = textureGrad(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].normal_rect.zw + decals.data[decal_index].normal_rect.xy, ddx * decals.data[decal_index].normal_rect.zw, ddy * decals.data[decal_index].normal_rect.zw).xyz;
} else {
- decal_albedo = textureLod(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].albedo_rect.zw + decals.data[decal_index].albedo_rect.xy, 0.0);
- }
- decal_albedo *= decals.data[decal_index].modulate;
- decal_albedo.a *= fade;
- albedo = mix(albedo, decal_albedo.rgb, decal_albedo.a * decals.data[decal_index].albedo_mix);
-
- if (decals.data[decal_index].normal_rect != vec4(0.0)) {
- vec3 decal_normal;
- if (sc_decal_use_mipmaps()) {
- decal_normal = textureGrad(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].normal_rect.zw + decals.data[decal_index].normal_rect.xy, ddx * decals.data[decal_index].normal_rect.zw, ddy * decals.data[decal_index].normal_rect.zw).xyz;
- } else {
- decal_normal = textureLod(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].normal_rect.zw + decals.data[decal_index].normal_rect.xy, 0.0).xyz;
- }
- decal_normal.xy = decal_normal.xy * vec2(2.0, -2.0) - vec2(1.0, -1.0); //users prefer flipped y normal maps in most authoring software
- decal_normal.z = sqrt(max(0.0, 1.0 - dot(decal_normal.xy, decal_normal.xy)));
- //convert to view space, use xzy because y is up
- decal_normal = (decals.data[decal_index].normal_xform * decal_normal.xzy).xyz;
-
- normal = normalize(mix(normal, decal_normal, decal_albedo.a));
+ decal_normal = textureLod(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].normal_rect.zw + decals.data[decal_index].normal_rect.xy, 0.0).xyz;
}
+ decal_normal.xy = decal_normal.xy * vec2(2.0, -2.0) - vec2(1.0, -1.0); //users prefer flipped y normal maps in most authoring software
+ decal_normal.z = sqrt(max(0.0, 1.0 - dot(decal_normal.xy, decal_normal.xy)));
+ //convert to view space, use xzy because y is up
+ decal_normal = (decals.data[decal_index].normal_xform * decal_normal.xzy).xyz;
- if (decals.data[decal_index].orm_rect != vec4(0.0)) {
- vec3 decal_orm;
- if (sc_decal_use_mipmaps()) {
- decal_orm = textureGrad(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].orm_rect.zw + decals.data[decal_index].orm_rect.xy, ddx * decals.data[decal_index].orm_rect.zw, ddy * decals.data[decal_index].orm_rect.zw).xyz;
- } else {
- decal_orm = textureLod(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].orm_rect.zw + decals.data[decal_index].orm_rect.xy, 0.0).xyz;
- }
- ao = mix(ao, decal_orm.r, decal_albedo.a);
- roughness = mix(roughness, decal_orm.g, decal_albedo.a);
- metallic = mix(metallic, decal_orm.b, decal_albedo.a);
- }
+ normal = normalize(mix(normal, decal_normal, decal_albedo.a));
}
- if (decals.data[decal_index].emission_rect != vec4(0.0)) {
- //emission is additive, so its independent from albedo
+ if (decals.data[decal_index].orm_rect != vec4(0.0)) {
+ vec3 decal_orm;
if (sc_decal_use_mipmaps()) {
- emission += textureGrad(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, ddx * decals.data[decal_index].emission_rect.zw, ddy * decals.data[decal_index].emission_rect.zw).xyz * decals.data[decal_index].emission_energy * fade;
+ decal_orm = textureGrad(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].orm_rect.zw + decals.data[decal_index].orm_rect.xy, ddx * decals.data[decal_index].orm_rect.zw, ddy * decals.data[decal_index].orm_rect.zw).xyz;
} else {
- emission += textureLod(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, 0.0).xyz * decals.data[decal_index].emission_energy * fade;
+ decal_orm = textureLod(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].orm_rect.zw + decals.data[decal_index].orm_rect.xy, 0.0).xyz;
}
+ ao = mix(ao, decal_orm.r, decal_albedo.a);
+ roughness = mix(roughness, decal_orm.g, decal_albedo.a);
+ metallic = mix(metallic, decal_orm.b, decal_albedo.a);
+ }
+ }
+
+ if (decals.data[decal_index].emission_rect != vec4(0.0)) {
+ //emission is additive, so its independent from albedo
+ if (sc_decal_use_mipmaps()) {
+ emission += textureGrad(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, ddx * decals.data[decal_index].emission_rect.zw, ddy * decals.data[decal_index].emission_rect.zw).xyz * decals.data[decal_index].emission_energy * fade;
+ } else {
+ emission += textureLod(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, 0.0).xyz * decals.data[decal_index].emission_energy * fade;
}
}
- } //Decals
+ }
#endif //!MODE_RENDER_DEPTH
/////////////////////// LIGHTING //////////////////////////////
#ifdef NORMAL_USED
- if (scene_data.roughness_limiter_enabled) {
+ if (sc_scene_roughness_limiter_enabled()) {
//https://www.jp.square-enix.com/tech/library/pdf/ImprovedGeometricSpecularAA.pdf
float roughness2 = roughness * roughness;
vec3 dndu = dFdx(normal), dndv = dFdy(normal);
@@ -1225,7 +1177,7 @@ void main() {
#ifndef AMBIENT_LIGHT_DISABLED
- if (scene_data.use_reflection_cubemap) {
+ if (sc_scene_use_reflection_cubemap()) {
#ifdef LIGHT_ANISOTROPY_USED
// https://google.github.io/filament/Filament.html#lighting/imagebasedlights/anisotropy
vec3 anisotropic_direction = anisotropy >= 0.0 ? binormal : tangent;
@@ -1266,7 +1218,7 @@ void main() {
if (scene_data.use_ambient_light) {
ambient_light = scene_data.ambient_light_color_energy.rgb;
- if (scene_data.use_ambient_cubemap) {
+ if (sc_scene_use_ambient_cubemap()) {
vec3 ambient_dir = scene_data.radiance_inverse_xform * normal;
#ifdef USE_RADIANCE_CUBEMAP_ARRAY
vec3 cubemap_ambient = texture(samplerCubeArray(radiance_cubemap, DEFAULT_SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP), vec4(ambient_dir, MAX_ROUGHNESS_LOD)).rgb;
@@ -1285,7 +1237,7 @@ void main() {
#endif // CUSTOM_IRRADIANCE_USED
#ifdef LIGHT_CLEARCOAT_USED
- if (scene_data.use_reflection_cubemap) {
+ if (sc_scene_use_reflection_cubemap()) {
vec3 n = normalize(normal_interp); // We want to use geometric normal, not normal_map
float NoV = max(dot(n, view), 0.0001);
vec3 ref_vec = reflect(-view, n);
@@ -1393,12 +1345,10 @@ void main() {
// skipping ssao, do we remove ssao totally?
- if (!sc_disable_reflection_probes()) { //Reflection probes
+ if (sc_reflection_probes() > 0) {
vec4 reflection_accum = vec4(0.0, 0.0, 0.0, 0.0);
vec4 ambient_accum = vec4(0.0, 0.0, 0.0, 0.0);
- uint reflection_indices = instances.data[draw_call.instance_index].reflection_probes.x;
-
#ifdef LIGHT_ANISOTROPY_USED
// https://google.github.io/filament/Filament.html#lighting/imagebasedlights/anisotropy
vec3 anisotropic_direction = anisotropy >= 0.0 ? binormal : tangent;
@@ -1411,18 +1361,9 @@ void main() {
vec3 ref_vec = normalize(reflect(-view, bent_normal));
ref_vec = mix(ref_vec, bent_normal, roughness * roughness);
- for (uint i = 0; i < 8; i++) {
- uint reflection_index = reflection_indices & 0xFF;
- if (i == 3) {
- reflection_indices = instances.data[draw_call.instance_index].reflection_probes.y;
- } else {
- reflection_indices = reflection_indices >> 8;
- }
-
- if (reflection_index == 0xFF) {
- break;
- }
-
+ uvec2 reflection_indices = instances.data[draw_call.instance_index].reflection_probes;
+ for (uint i = 0; i < sc_reflection_probes(); i++) {
+ uint reflection_index = (i > 3) ? ((reflection_indices.y >> ((i - 4) * 8)) & 0xFF) : ((reflection_indices.x >> (i * 8)) & 0xFF);
reflection_process(reflection_index, vertex, ref_vec, bent_normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum);
}
@@ -1487,7 +1428,7 @@ void main() {
specular_light += specular_light_interp.rgb * f0;
#endif
- if (!sc_disable_directional_lights()) { //directional light
+ if (sc_directional_lights() > 0) {
#ifndef SHADOWS_DISABLED
// Do shadow and lighting in two passes to reduce register pressure
uint shadow0 = 0;
@@ -1497,7 +1438,7 @@ void main() {
// Only process the first light's shadow for vertex lighting.
for (uint i = 0; i < 1; i++) {
#else
- for (uint i = 0; i < scene_data.directional_light_count; i++) {
+ for (uint i = 0; i < sc_directional_lights(); i++) {
#endif
if (!bool(directional_lights.data[i].mask & instances.data[draw_call.instance_index].layer_mask)) {
@@ -1612,7 +1553,7 @@ void main() {
#endif // SHADOWS_DISABLED
#ifndef USE_VERTEX_LIGHTING
- for (uint i = 0; i < scene_data.directional_light_count; i++) {
+ for (uint i = 0; i < sc_directional_lights(); i++) {
if (!bool(directional_lights.data[i].mask & instances.data[draw_call.instance_index].layer_mask)) {
continue; //not masked
}
@@ -1678,95 +1619,72 @@ void main() {
} //directional light
#ifndef USE_VERTEX_LIGHTING
- if (!sc_disable_omni_lights()) { //omni lights
- uint light_indices = instances.data[draw_call.instance_index].omni_lights.x;
- for (uint i = 0; i < 8; i++) {
- uint light_index = light_indices & 0xFF;
- if (i == 3) {
- light_indices = instances.data[draw_call.instance_index].omni_lights.y;
- } else {
- light_indices = light_indices >> 8;
- }
-
- if (light_index == 0xFF) {
- break;
- }
+ uvec2 omni_indices = instances.data[draw_call.instance_index].omni_lights;
+ for (uint i = 0; i < sc_omni_lights(); i++) {
+ uint light_index = (i > 3) ? ((omni_indices.y >> ((i - 4) * 8)) & 0xFF) : ((omni_indices.x >> (i * 8)) & 0xFF);
- float shadow = light_process_omni_shadow(light_index, vertex, normal, scene_data.taa_frame_count);
+ float shadow = light_process_omni_shadow(light_index, vertex, normal, scene_data.taa_frame_count);
- shadow = blur_shadow(shadow);
+ shadow = blur_shadow(shadow);
- // Fragment lighting
- light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha,
+ // Fragment lighting
+ light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha,
#ifdef LIGHT_BACKLIGHT_USED
- backlight,
+ backlight,
#endif
/*
#ifdef LIGHT_TRANSMITTANCE_USED
- transmittance_color,
- transmittance_depth,
- transmittance_boost,
+ transmittance_color,
+ transmittance_depth,
+ transmittance_boost,
#endif
*/
#ifdef LIGHT_RIM_USED
- rim,
- rim_tint,
+ rim,
+ rim_tint,
#endif
#ifdef LIGHT_CLEARCOAT_USED
- clearcoat, clearcoat_roughness, normalize(normal_interp),
+ clearcoat, clearcoat_roughness, normalize(normal_interp),
#endif
#ifdef LIGHT_ANISOTROPY_USED
- tangent,
- binormal, anisotropy,
+ tangent,
+ binormal, anisotropy,
#endif
- diffuse_light, specular_light);
- }
- } //omni lights
-
- if (!sc_disable_spot_lights()) { //spot lights
-
- uint light_indices = instances.data[draw_call.instance_index].spot_lights.x;
- for (uint i = 0; i < 8; i++) {
- uint light_index = light_indices & 0xFF;
- if (i == 3) {
- light_indices = instances.data[draw_call.instance_index].spot_lights.y;
- } else {
- light_indices = light_indices >> 8;
- }
+ diffuse_light, specular_light);
+ }
- if (light_index == 0xFF) {
- break;
- }
+ uvec2 spot_indices = instances.data[draw_call.instance_index].spot_lights;
+ for (uint i = 0; i < sc_spot_lights(); i++) {
+ uint light_index = (i > 3) ? ((spot_indices.y >> ((i - 4) * 8)) & 0xFF) : ((spot_indices.x >> (i * 8)) & 0xFF);
- float shadow = light_process_spot_shadow(light_index, vertex, normal, scene_data.taa_frame_count);
+ float shadow = light_process_spot_shadow(light_index, vertex, normal, scene_data.taa_frame_count);
- shadow = blur_shadow(shadow);
+ shadow = blur_shadow(shadow);
- light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha,
+ light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow, albedo, alpha,
#ifdef LIGHT_BACKLIGHT_USED
- backlight,
+ backlight,
#endif
/*
#ifdef LIGHT_TRANSMITTANCE_USED
- transmittance_color,
- transmittance_depth,
- transmittance_boost,
+ transmittance_color,
+ transmittance_depth,
+ transmittance_boost,
#endif
*/
#ifdef LIGHT_RIM_USED
- rim,
- rim_tint,
+ rim,
+ rim_tint,
#endif
#ifdef LIGHT_CLEARCOAT_USED
- clearcoat, clearcoat_roughness, normalize(normal_interp),
+ clearcoat, clearcoat_roughness, normalize(normal_interp),
#endif
#ifdef LIGHT_ANISOTROPY_USED
- tangent,
- binormal, anisotropy,
+ tangent,
+ binormal, anisotropy,
#endif
- diffuse_light, specular_light);
- }
- } //spot lights
+ diffuse_light, specular_light);
+ }
#endif // !VERTEX_LIGHTING
#endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl
index 495e52a29e..2cc86482f6 100644
--- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl
@@ -22,8 +22,8 @@ layout(push_constant, std430) uniform DrawCall {
uint pad;
#ifdef UBERSHADER
uint sc_packed_0;
- float sc_packed_1;
- uint sc_packed_2;
+ uint sc_packed_1;
+ float sc_packed_2;
uint uc_packed_0;
#endif
}
@@ -42,10 +42,14 @@ uint sc_packed_0() {
return draw_call.sc_packed_0;
}
-float sc_packed_1() {
+uint sc_packed_1() {
return draw_call.sc_packed_1;
}
+float sc_packed_2() {
+ return draw_call.sc_packed_2;
+}
+
uint uc_cull_mode() {
return (draw_call.uc_packed_0 >> 0) & 3U;
}
@@ -54,16 +58,21 @@ uint uc_cull_mode() {
// Pull the constants from the pipeline's specialization constants.
layout(constant_id = 0) const uint pso_sc_packed_0 = 0;
-layout(constant_id = 1) const float pso_sc_packed_1 = 2.0;
+layout(constant_id = 1) const uint pso_sc_packed_1 = 0;
+layout(constant_id = 2) const float pso_sc_packed_2 = 2.0;
uint sc_packed_0() {
return pso_sc_packed_0;
}
-float sc_packed_1() {
+uint sc_packed_1() {
return pso_sc_packed_1;
}
+float sc_packed_2() {
+ return pso_sc_packed_2;
+}
+
#endif
bool sc_use_light_projector() {
@@ -86,60 +95,84 @@ bool sc_projector_use_mipmaps() {
return ((sc_packed_0() >> 4) & 1U) != 0;
}
-bool sc_disable_omni_lights() {
+bool sc_disable_fog() {
return ((sc_packed_0() >> 5) & 1U) != 0;
}
-bool sc_disable_spot_lights() {
+bool sc_use_depth_fog() {
return ((sc_packed_0() >> 6) & 1U) != 0;
}
-bool sc_disable_reflection_probes() {
+bool sc_use_lightmap_bicubic_filter() {
return ((sc_packed_0() >> 7) & 1U) != 0;
}
-bool sc_disable_directional_lights() {
+bool sc_multimesh() {
return ((sc_packed_0() >> 8) & 1U) != 0;
}
-bool sc_disable_decals() {
+bool sc_multimesh_format_2d() {
return ((sc_packed_0() >> 9) & 1U) != 0;
}
-bool sc_disable_fog() {
+bool sc_multimesh_has_color() {
return ((sc_packed_0() >> 10) & 1U) != 0;
}
-bool sc_use_depth_fog() {
+bool sc_multimesh_has_custom_data() {
return ((sc_packed_0() >> 11) & 1U) != 0;
}
-bool sc_is_multimesh() {
+bool sc_scene_use_ambient_cubemap() {
return ((sc_packed_0() >> 12) & 1U) != 0;
}
-bool sc_use_lightmap_bicubic_filter() {
+bool sc_scene_use_reflection_cubemap() {
return ((sc_packed_0() >> 13) & 1U) != 0;
}
+bool sc_scene_roughness_limiter_enabled() {
+ return ((sc_packed_0() >> 14) & 1U) != 0;
+}
+
uint sc_soft_shadow_samples() {
- return (sc_packed_0() >> 16) & 15U;
+ return (sc_packed_0() >> 20) & 63U;
}
uint sc_penumbra_shadow_samples() {
- return (sc_packed_0() >> 20) & 15U;
+ return (sc_packed_0() >> 26) & 63U;
}
uint sc_directional_soft_shadow_samples() {
- return (sc_packed_0() >> 24) & 15U;
+ return (sc_packed_1() >> 0) & 63U;
}
uint sc_directional_penumbra_shadow_samples() {
- return (sc_packed_0() >> 28) & 15U;
+ return (sc_packed_1() >> 6) & 63U;
+}
+
+uint sc_omni_lights() {
+ return (sc_packed_1() >> 12) & 15U;
+}
+
+uint sc_spot_lights() {
+ return (sc_packed_1() >> 16) & 15U;
+}
+
+uint sc_reflection_probes() {
+ return (sc_packed_1() >> 20) & 15U;
+}
+
+uint sc_directional_lights() {
+ return (sc_packed_1() >> 24) & 15U;
+}
+
+uint sc_decals() {
+ return (sc_packed_1() >> 28) & 15U;
}
float sc_luminance_multiplier() {
- return sc_packed_1();
+ return sc_packed_2();
}
/* Set 0: Base Pass (never changes) */
@@ -157,10 +190,6 @@ layout(set = 0, binding = 2) uniform sampler shadow_sampler;
#define INSTANCE_FLAGS_USE_SH_LIGHTMAP (1 << 9)
#define INSTANCE_FLAGS_USE_VOXEL_GI (1 << 10)
#define INSTANCE_FLAGS_PARTICLES (1 << 11)
-#define INSTANCE_FLAGS_MULTIMESH (1 << 12)
-#define INSTANCE_FLAGS_MULTIMESH_FORMAT_2D (1 << 13)
-#define INSTANCE_FLAGS_MULTIMESH_HAS_COLOR (1 << 14)
-#define INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA (1 << 15)
#define INSTANCE_FLAGS_PARTICLE_TRAIL_SHIFT 16
//3 bits of stride
#define INSTANCE_FLAGS_PARTICLE_TRAIL_MASK 0xFF