Skip to content

Commit 9ce5705

Browse files
committed
Add GPUParticles to the OpenGL3 renderer.
This includes collision (2D SDF, Box, Sphere, Heightmap), attraction (Box, Sphere), and all sorting modes. This does not include 3D SDF collisions, trails, or manual emission.
1 parent 98e0d59 commit 9ce5705

31 files changed

+2841
-252
lines changed

drivers/gles3/effects/copy_effects.cpp

+15-3
Original file line numberDiff line numberDiff line change
@@ -115,13 +115,21 @@ CopyEffects::~CopyEffects() {
115115
}
116116

117117
void CopyEffects::copy_to_rect(const Rect2 &p_rect) {
118-
copy.shader.version_bind_shader(copy.shader_version, CopyShaderGLES3::MODE_COPY_SECTION);
118+
bool success = copy.shader.version_bind_shader(copy.shader_version, CopyShaderGLES3::MODE_COPY_SECTION);
119+
if (!success) {
120+
return;
121+
}
122+
119123
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);
120124
draw_screen_quad();
121125
}
122126

123127
void CopyEffects::copy_screen() {
124-
copy.shader.version_bind_shader(copy.shader_version, CopyShaderGLES3::MODE_DEFAULT);
128+
bool success = copy.shader.version_bind_shader(copy.shader_version, CopyShaderGLES3::MODE_DEFAULT);
129+
if (!success) {
130+
return;
131+
}
132+
125133
draw_screen_triangle();
126134
}
127135

@@ -151,7 +159,11 @@ void CopyEffects::bilinear_blur(GLuint p_source_texture, int p_mipmap_count, con
151159
}
152160

153161
void CopyEffects::set_color(const Color &p_color, const Rect2i &p_region) {
154-
copy.shader.version_bind_shader(copy.shader_version, CopyShaderGLES3::MODE_SIMPLE_COLOR);
162+
bool success = copy.shader.version_bind_shader(copy.shader_version, CopyShaderGLES3::MODE_SIMPLE_COLOR);
163+
if (!success) {
164+
return;
165+
}
166+
155167
copy.shader.version_set_uniform(CopyShaderGLES3::COPY_SECTION, p_region.position.x, p_region.position.y, p_region.size.x, p_region.size.y, copy.shader_version, CopyShaderGLES3::MODE_SIMPLE_COLOR);
156168
copy.shader.version_set_uniform(CopyShaderGLES3::COLOR_IN, p_color, copy.shader_version, CopyShaderGLES3::MODE_SIMPLE_COLOR);
157169
draw_screen_quad();

drivers/gles3/rasterizer_canvas_gles3.cpp

+104-33
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include "storage/config.h"
4242
#include "storage/material_storage.h"
4343
#include "storage/mesh_storage.h"
44+
#include "storage/particles_storage.h"
4445
#include "storage/texture_storage.h"
4546

4647
void RasterizerCanvasGLES3::_update_transform_2d_to_mat4(const Transform2D &p_transform, float *p_mat4) {
@@ -578,7 +579,7 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou
578579

579580
GLES3::CanvasShaderData::BlendMode blend_mode = shader_data_cache ? shader_data_cache->blend_mode : GLES3::CanvasShaderData::BLEND_MODE_MIX;
580581

581-
_record_item_commands(ci, p_canvas_transform_inverse, current_clip, blend_mode, p_lights, index, batch_broken);
582+
_record_item_commands(ci, p_to_render_target, p_canvas_transform_inverse, current_clip, blend_mode, p_lights, index, batch_broken);
582583
}
583584

584585
if (index == 0) {
@@ -623,7 +624,10 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou
623624
uint64_t specialization = 0;
624625
specialization |= uint64_t(state.canvas_instance_batches[i].lights_disabled);
625626
specialization |= uint64_t(!GLES3::Config::get_singleton()->float_texture_supported) << 1;
626-
_bind_material(material_data, variant, specialization);
627+
bool success = _bind_material(material_data, variant, specialization);
628+
if (!success) {
629+
continue;
630+
}
627631

628632
GLES3::CanvasShaderData::BlendMode blend_mode = state.canvas_instance_batches[i].blend_mode;
629633

@@ -707,7 +711,7 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou
707711
r_last_index += index;
708712
}
709713

710-
void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, GLES3::CanvasShaderData::BlendMode p_blend_mode, Light *p_lights, uint32_t &r_index, bool &r_batch_broken) {
714+
void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, RID p_render_target, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, GLES3::CanvasShaderData::BlendMode p_blend_mode, Light *p_lights, uint32_t &r_index, bool &r_batch_broken) {
711715
RenderingServer::CanvasItemTextureFilter texture_filter = p_item->texture_filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT ? state.default_filter : p_item->texture_filter;
712716

713717
if (texture_filter != state.canvas_instance_batches[state.current_batch_index].filter) {
@@ -1064,15 +1068,45 @@ void RasterizerCanvasGLES3::_record_item_commands(const Item *p_item, const Tran
10641068
state.canvas_instance_batches[state.current_batch_index].tex = m->texture;
10651069
_update_transform_2d_to_mat2x3(base_transform * draw_transform * m->transform, state.instance_data_array[r_index].world);
10661070
modulate = m->modulate;
1071+
10671072
} else if (c->type == Item::Command::TYPE_MULTIMESH) {
10681073
const Item::CommandMultiMesh *mm = static_cast<const Item::CommandMultiMesh *>(c);
10691074
state.canvas_instance_batches[state.current_batch_index].tex = mm->texture;
1070-
uint32_t instance_count = GLES3::MeshStorage::get_singleton()->multimesh_get_instances_to_draw(mm->multimesh);
1071-
if (instance_count > 1) {
1072-
state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_INSTANCED;
1073-
}
1075+
state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_INSTANCED;
1076+
10741077
} else if (c->type == Item::Command::TYPE_PARTICLES) {
1075-
WARN_PRINT_ONCE("Particles not supported yet, sorry :(");
1078+
GLES3::ParticlesStorage *particles_storage = GLES3::ParticlesStorage::get_singleton();
1079+
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
1080+
1081+
const Item::CommandParticles *pt = static_cast<const Item::CommandParticles *>(c);
1082+
RID particles = pt->particles;
1083+
state.canvas_instance_batches[state.current_batch_index].tex = pt->texture;
1084+
state.canvas_instance_batches[state.current_batch_index].shader_variant = CanvasShaderGLES3::MODE_INSTANCED;
1085+
bool local_coords = particles_storage->particles_is_using_local_coords(particles);
1086+
1087+
if (particles_storage->particles_has_collision(particles) && texture_storage->render_target_is_sdf_enabled(p_render_target)) {
1088+
// Pass collision information.
1089+
Transform2D xform;
1090+
if (local_coords) {
1091+
xform = p_item->final_transform;
1092+
} else {
1093+
xform = p_canvas_transform_inverse;
1094+
}
1095+
1096+
GLuint sdf_texture = texture_storage->render_target_get_sdf_texture(p_render_target);
1097+
1098+
Rect2 to_screen;
1099+
{
1100+
Rect2 sdf_rect = texture_storage->render_target_get_sdf_rect(p_render_target);
1101+
1102+
to_screen.size = Vector2(1.0 / sdf_rect.size.width, 1.0 / sdf_rect.size.height);
1103+
to_screen.position = -sdf_rect.position * to_screen.size;
1104+
}
1105+
1106+
particles_storage->particles_set_canvas_sdf_collision(pt->particles, true, xform, to_screen, sdf_texture);
1107+
} else {
1108+
particles_storage->particles_set_canvas_sdf_collision(pt->particles, false, Transform2D(), Rect2(), 0);
1109+
}
10761110
}
10771111

10781112
state.canvas_instance_batches[state.current_batch_index].command = c;
@@ -1209,20 +1243,21 @@ void RasterizerCanvasGLES3::_render_batch(Light *p_lights, uint32_t p_index) {
12091243
case Item::Command::TYPE_MULTIMESH:
12101244
case Item::Command::TYPE_PARTICLES: {
12111245
GLES3::MeshStorage *mesh_storage = GLES3::MeshStorage::get_singleton();
1246+
GLES3::ParticlesStorage *particles_storage = GLES3::ParticlesStorage::get_singleton();
12121247
RID mesh;
12131248
RID mesh_instance;
1214-
RID texture;
12151249
uint32_t instance_count = 1;
1216-
GLuint multimesh_buffer = 0;
1217-
uint32_t multimesh_stride = 0;
1218-
uint32_t multimesh_color_offset = 0;
1219-
bool multimesh_uses_color = false;
1220-
bool multimesh_uses_custom_data = false;
1250+
GLuint instance_buffer = 0;
1251+
uint32_t instance_stride = 0;
1252+
uint32_t instance_color_offset = 0;
1253+
bool instance_uses_color = false;
1254+
bool instance_uses_custom_data = false;
12211255

12221256
if (state.canvas_instance_batches[p_index].command_type == Item::Command::TYPE_MESH) {
12231257
const Item::CommandMesh *m = static_cast<const Item::CommandMesh *>(state.canvas_instance_batches[p_index].command);
12241258
mesh = m->mesh;
12251259
mesh_instance = m->mesh_instance;
1260+
12261261
} else if (state.canvas_instance_batches[p_index].command_type == Item::Command::TYPE_MULTIMESH) {
12271262
const Item::CommandMultiMesh *mm = static_cast<const Item::CommandMultiMesh *>(state.canvas_instance_batches[p_index].command);
12281263
RID multimesh = mm->multimesh;
@@ -1238,13 +1273,41 @@ void RasterizerCanvasGLES3::_render_batch(Light *p_lights, uint32_t p_index) {
12381273
break;
12391274
}
12401275

1241-
multimesh_buffer = mesh_storage->multimesh_get_gl_buffer(multimesh);
1242-
multimesh_stride = mesh_storage->multimesh_get_stride(multimesh);
1243-
multimesh_color_offset = mesh_storage->multimesh_get_color_offset(multimesh);
1244-
multimesh_uses_color = mesh_storage->multimesh_uses_colors(multimesh);
1245-
multimesh_uses_custom_data = mesh_storage->multimesh_uses_custom_data(multimesh);
1276+
instance_buffer = mesh_storage->multimesh_get_gl_buffer(multimesh);
1277+
instance_stride = mesh_storage->multimesh_get_stride(multimesh);
1278+
instance_color_offset = mesh_storage->multimesh_get_color_offset(multimesh);
1279+
instance_uses_color = mesh_storage->multimesh_uses_colors(multimesh);
1280+
instance_uses_custom_data = mesh_storage->multimesh_uses_custom_data(multimesh);
1281+
12461282
} else if (state.canvas_instance_batches[p_index].command_type == Item::Command::TYPE_PARTICLES) {
1247-
// Do nothing for now.
1283+
const Item::CommandParticles *pt = static_cast<const Item::CommandParticles *>(state.canvas_instance_batches[p_index].command);
1284+
RID particles = pt->particles;
1285+
mesh = particles_storage->particles_get_draw_pass_mesh(particles, 0);
1286+
1287+
ERR_BREAK(particles_storage->particles_get_mode(particles) != RS::PARTICLES_MODE_2D);
1288+
particles_storage->particles_request_process(particles);
1289+
1290+
if (particles_storage->particles_is_inactive(particles)) {
1291+
break;
1292+
}
1293+
1294+
RenderingServerDefault::redraw_request(); // Active particles means redraw request.
1295+
1296+
int dpc = particles_storage->particles_get_draw_passes(particles);
1297+
if (dpc == 0) {
1298+
break; // Nothing to draw.
1299+
}
1300+
1301+
instance_count = particles_storage->particles_get_amount(particles);
1302+
instance_buffer = particles_storage->particles_get_gl_buffer(particles);
1303+
instance_stride = 12; // 8 bytes for instance transform and 4 bytes for packed color and custom.
1304+
instance_color_offset = 8; // 8 bytes for instance transform.
1305+
instance_uses_color = true;
1306+
instance_uses_custom_data = true;
1307+
}
1308+
1309+
if (instance_buffer == 0) {
1310+
break;
12481311
}
12491312

12501313
ERR_FAIL_COND(mesh.is_null());
@@ -1277,17 +1340,17 @@ void RasterizerCanvasGLES3::_render_batch(Light *p_lights, uint32_t p_index) {
12771340

12781341
if (instance_count > 1) {
12791342
// Bind instance buffers.
1280-
glBindBuffer(GL_ARRAY_BUFFER, multimesh_buffer);
1343+
glBindBuffer(GL_ARRAY_BUFFER, instance_buffer);
12811344
glEnableVertexAttribArray(1);
1282-
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(0));
1345+
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, instance_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(0));
12831346
glVertexAttribDivisor(1, 1);
12841347
glEnableVertexAttribArray(2);
1285-
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(4 * 4));
1348+
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, instance_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(4 * 4));
12861349
glVertexAttribDivisor(2, 1);
12871350

1288-
if (multimesh_uses_color || multimesh_uses_custom_data) {
1351+
if (instance_uses_color || instance_uses_custom_data) {
12891352
glEnableVertexAttribArray(5);
1290-
glVertexAttribIPointer(5, 4, GL_UNSIGNED_INT, multimesh_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(multimesh_color_offset * sizeof(float)));
1353+
glVertexAttribIPointer(5, 4, GL_UNSIGNED_INT, instance_stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(instance_color_offset * sizeof(float)));
12911354
glVertexAttribDivisor(5, 1);
12921355
}
12931356
}
@@ -1361,17 +1424,17 @@ void RasterizerCanvasGLES3::_new_batch(bool &r_batch_broken, uint32_t &r_index)
13611424
_align_instance_data_buffer(r_index);
13621425
}
13631426

1364-
void RasterizerCanvasGLES3::_bind_material(GLES3::CanvasMaterialData *p_material_data, CanvasShaderGLES3::ShaderVariant p_variant, uint64_t p_specialization) {
1427+
bool RasterizerCanvasGLES3::_bind_material(GLES3::CanvasMaterialData *p_material_data, CanvasShaderGLES3::ShaderVariant p_variant, uint64_t p_specialization) {
13651428
if (p_material_data) {
13661429
if (p_material_data->shader_data->version.is_valid() && p_material_data->shader_data->valid) {
13671430
// Bind uniform buffer and textures
13681431
p_material_data->bind_uniforms();
1369-
GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(p_material_data->shader_data->version, p_variant, p_specialization);
1432+
return GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(p_material_data->shader_data->version, p_variant, p_specialization);
13701433
} else {
1371-
GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(data.canvas_shader_default_version, p_variant, p_specialization);
1434+
return GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(data.canvas_shader_default_version, p_variant, p_specialization);
13721435
}
13731436
} else {
1374-
GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(data.canvas_shader_default_version, p_variant, p_specialization);
1437+
return GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(data.canvas_shader_default_version, p_variant, p_specialization);
13751438
}
13761439
}
13771440

@@ -1435,7 +1498,10 @@ void RasterizerCanvasGLES3::light_update_shadow(RID p_rid, int p_shadow_index, c
14351498
RS::CanvasOccluderPolygonCullMode cull_mode = RS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED;
14361499

14371500
CanvasOcclusionShaderGLES3::ShaderVariant variant = config->float_texture_supported ? CanvasOcclusionShaderGLES3::MODE_SHADOW : CanvasOcclusionShaderGLES3::MODE_SHADOW_RGBA;
1438-
shadow_render.shader.version_bind_shader(shadow_render.shader_version, variant);
1501+
bool success = shadow_render.shader.version_bind_shader(shadow_render.shader_version, variant);
1502+
if (!success) {
1503+
return;
1504+
}
14391505

14401506
for (int i = 0; i < 4; i++) {
14411507
glViewport((state.shadow_texture_size / 4) * i, p_shadow_index * 2, (state.shadow_texture_size / 4), 2);
@@ -1553,7 +1619,10 @@ void RasterizerCanvasGLES3::light_update_directional_shadow(RID p_rid, int p_sha
15531619
RS::CanvasOccluderPolygonCullMode cull_mode = RS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED;
15541620

15551621
CanvasOcclusionShaderGLES3::ShaderVariant variant = config->float_texture_supported ? CanvasOcclusionShaderGLES3::MODE_SHADOW : CanvasOcclusionShaderGLES3::MODE_SHADOW_RGBA;
1556-
shadow_render.shader.version_bind_shader(shadow_render.shader_version, variant);
1622+
bool success = shadow_render.shader.version_bind_shader(shadow_render.shader_version, variant);
1623+
if (!success) {
1624+
return;
1625+
}
15571626

15581627
Projection projection;
15591628
projection.set_orthogonal(-half_size, half_size, -0.5, 0.5, 0.0, distance);
@@ -1685,7 +1754,10 @@ void RasterizerCanvasGLES3::render_sdf(RID p_render_target, LightOccluderInstanc
16851754
glClear(GL_COLOR_BUFFER_BIT);
16861755

16871756
CanvasOcclusionShaderGLES3::ShaderVariant variant = CanvasOcclusionShaderGLES3::MODE_SDF;
1688-
shadow_render.shader.version_bind_shader(shadow_render.shader_version, variant);
1757+
bool success = shadow_render.shader.version_bind_shader(shadow_render.shader_version, variant);
1758+
if (!success) {
1759+
return;
1760+
}
16891761

16901762
shadow_render.shader.version_set_uniform(CanvasOcclusionShaderGLES3::PROJECTION, Projection(), shadow_render.shader_version, variant);
16911763
shadow_render.shader.version_set_uniform(CanvasOcclusionShaderGLES3::DIRECTION, 0.0, 0.0, shadow_render.shader_version, variant);
@@ -2555,7 +2627,6 @@ RasterizerCanvasGLES3::RasterizerCanvasGLES3() {
25552627

25562628
GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.initialize(global_defines);
25572629
data.canvas_shader_default_version = GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_create();
2558-
GLES3::MaterialStorage::get_singleton()->shaders.canvas_shader.version_bind_shader(data.canvas_shader_default_version, CanvasShaderGLES3::MODE_QUAD);
25592630

25602631
shadow_render.shader.initialize();
25612632
shadow_render.shader_version = shadow_render.shader.version_create();

drivers/gles3/rasterizer_canvas_gles3.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -352,9 +352,9 @@ class RasterizerCanvasGLES3 : public RendererCanvasRender {
352352

353353
void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used) override;
354354
void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, uint32_t &r_last_index, bool p_to_backbuffer = false);
355-
void _record_item_commands(const Item *p_item, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, GLES3::CanvasShaderData::BlendMode p_blend_mode, Light *p_lights, uint32_t &r_index, bool &r_break_batch);
355+
void _record_item_commands(const Item *p_item, RID p_render_target, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, GLES3::CanvasShaderData::BlendMode p_blend_mode, Light *p_lights, uint32_t &r_index, bool &r_break_batch);
356356
void _render_batch(Light *p_lights, uint32_t p_index);
357-
void _bind_material(GLES3::CanvasMaterialData *p_material_data, CanvasShaderGLES3::ShaderVariant p_variant, uint64_t p_specialization);
357+
bool _bind_material(GLES3::CanvasMaterialData *p_material_data, CanvasShaderGLES3::ShaderVariant p_variant, uint64_t p_specialization);
358358
void _new_batch(bool &r_batch_broken, uint32_t &r_index);
359359
void _add_to_batch(uint32_t &r_index, bool &r_batch_broken);
360360
void _allocate_instance_data_buffer();

0 commit comments

Comments
 (0)