diff options
Diffstat (limited to 'drivers/gles3/rasterizer_storage_gles3.cpp')
-rw-r--r-- | drivers/gles3/rasterizer_storage_gles3.cpp | 268 |
1 files changed, 190 insertions, 78 deletions
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 4fcd09ed58..d6c8b3b35b 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -1338,12 +1338,12 @@ void RasterizerStorageGLES3::skybox_set_texture(RID p_skybox, RID p_cube_map, in /* SHADER API */ -RID RasterizerStorageGLES3::shader_create(VS::ShaderMode p_mode) { +RID RasterizerStorageGLES3::shader_create() { Shader *shader = memnew(Shader); - shader->mode = p_mode; + shader->mode = VS::SHADER_SPATIAL; + shader->shader = &scene->state.scene_shader; RID rid = shader_owner.make_rid(shader); - shader_set_mode(rid, p_mode); _shader_make_dirty(shader); shader->self = rid; @@ -1358,22 +1358,30 @@ void RasterizerStorageGLES3::_shader_make_dirty(Shader *p_shader) { _shader_dirty_list.add(&p_shader->dirty_list); } -void RasterizerStorageGLES3::shader_set_mode(RID p_shader, VS::ShaderMode p_mode) { +void RasterizerStorageGLES3::shader_set_code(RID p_shader, const String &p_code) { - ERR_FAIL_INDEX(p_mode, VS::SHADER_MAX); Shader *shader = shader_owner.get(p_shader); ERR_FAIL_COND(!shader); - if (shader->custom_code_id && p_mode == shader->mode) - return; + shader->code = p_code; + + String mode_string = ShaderLanguage::get_shader_type(p_code); + VS::ShaderMode mode; - if (shader->custom_code_id) { + if (mode_string == "canvas_item") + mode = VS::SHADER_CANVAS_ITEM; + else if (mode_string == "particles") + mode = VS::SHADER_PARTICLES; + else + mode = VS::SHADER_SPATIAL; + + if (shader->custom_code_id && mode != shader->mode) { shader->shader->free_custom_shader(shader->custom_code_id); shader->custom_code_id = 0; } - shader->mode = p_mode; + shader->mode = mode; ShaderGLES3 *shaders[VS::SHADER_MAX] = { &scene->state.scene_shader, @@ -1382,25 +1390,12 @@ void RasterizerStorageGLES3::shader_set_mode(RID p_shader, VS::ShaderMode p_mode }; - shader->shader = shaders[p_mode]; - - shader->custom_code_id = shader->shader->create_custom_shader(); - - _shader_make_dirty(shader); -} -VS::ShaderMode RasterizerStorageGLES3::shader_get_mode(RID p_shader) const { - - const Shader *shader = shader_owner.get(p_shader); - ERR_FAIL_COND_V(!shader, VS::SHADER_MAX); - - return shader->mode; -} -void RasterizerStorageGLES3::shader_set_code(RID p_shader, const String &p_code) { + shader->shader = shaders[mode]; - Shader *shader = shader_owner.get(p_shader); - ERR_FAIL_COND(!shader); + if (shader->custom_code_id == 0) { + shader->custom_code_id = shader->shader->create_custom_shader(); + } - shader->code = p_code; _shader_make_dirty(shader); } String RasterizerStorageGLES3::shader_get_code(RID p_shader) const { @@ -1453,6 +1448,7 @@ void RasterizerStorageGLES3::_update_shader(Shader *p_shader) const { p_shader->spatial.ontop = false; p_shader->spatial.uses_sss = false; p_shader->spatial.uses_vertex = false; + p_shader->spatial.writes_modelview_or_projection = false; shaders.actions_scene.render_mode_values["blend_add"] = Pair<int *, int>(&p_shader->spatial.blend_mode, Shader::Spatial::BLEND_MODE_ADD); shaders.actions_scene.render_mode_values["blend_mix"] = Pair<int *, int>(&p_shader->spatial.blend_mode, Shader::Spatial::BLEND_MODE_MIX); @@ -1477,6 +1473,9 @@ void RasterizerStorageGLES3::_update_shader(Shader *p_shader) const { shaders.actions_scene.usage_flag_pointers["SSS_STRENGTH"] = &p_shader->spatial.uses_sss; shaders.actions_scene.usage_flag_pointers["DISCARD"] = &p_shader->spatial.uses_discard; + shaders.actions_scene.write_flag_pointers["MODELVIEW_MATRIX"] = &p_shader->spatial.writes_modelview_or_projection; + shaders.actions_scene.write_flag_pointers["PROJECTION_MATRIX"] = &p_shader->spatial.writes_modelview_or_projection; + actions = &shaders.actions_scene; actions->uniforms = &p_shader->uniforms; @@ -4861,6 +4860,8 @@ void RasterizerStorageGLES3::particles_set_amount(RID p_particles, int p_amount) Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); + particles->amount = p_amount; + int floats = p_amount * 24; float *data = memnew_arr(float, floats); @@ -4868,17 +4869,25 @@ void RasterizerStorageGLES3::particles_set_amount(RID p_particles, int p_amount) data[i] = 0; } - glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[0]); - glBufferData(GL_ARRAY_BUFFER, floats * sizeof(float), data, GL_DYNAMIC_DRAW); + for (int i = 0; i < 2; i++) { - glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[1]); - glBufferData(GL_ARRAY_BUFFER, floats * sizeof(float), data, GL_DYNAMIC_DRAW); + glBindVertexArray(particles->particle_vaos[i]); - glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[i]); + glBufferData(GL_ARRAY_BUFFER, floats * sizeof(float), data, GL_DYNAMIC_DRAW); + + for (int i = 0; i < 6; i++) { + glEnableVertexAttribArray(i); + glVertexAttribPointer(i, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 4 * 6, ((uint8_t *)0) + (i * 16)); + } + } + + glBindVertexArray(0); particles->prev_ticks = 0; particles->phase = 0; particles->prev_phase = 0; + particles->clear = true; memdelete_arr(data); } @@ -4927,41 +4936,29 @@ void RasterizerStorageGLES3::particles_set_use_local_coordinates(RID p_particles particles->use_local_coords = p_enable; } -void RasterizerStorageGLES3::particles_set_process_material(RID p_particles, RID p_material) { - - Particles *particles = particles_owner.getornull(p_particles); - ERR_FAIL_COND(!particles); - particles->process_material = p_material; -} - -void RasterizerStorageGLES3::particles_set_emission_shape(RID p_particles, VS::ParticlesEmissionShape p_shape) { +void RasterizerStorageGLES3::particles_set_fixed_fps(RID p_particles, int p_fps) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); - particles->emission_shape = p_shape; + particles->fixed_fps = p_fps; } -void RasterizerStorageGLES3::particles_set_emission_sphere_radius(RID p_particles, float p_radius) { - Particles *particles = particles_owner.getornull(p_particles); - ERR_FAIL_COND(!particles); - - particles->emission_sphere_radius = p_radius; -} -void RasterizerStorageGLES3::particles_set_emission_box_extents(RID p_particles, const Vector3 &p_extents) { +void RasterizerStorageGLES3::particles_set_fractional_delta(RID p_particles, bool p_enable) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); - particles->emission_box_extents = p_extents; + particles->fractional_delta = p_enable; } -void RasterizerStorageGLES3::particles_set_emission_points(RID p_particles, const PoolVector<Vector3> &p_points) { + +void RasterizerStorageGLES3::particles_set_process_material(RID p_particles, RID p_material) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); - particles->emission_points = p_points; + particles->process_material = p_material; } void RasterizerStorageGLES3::particles_set_draw_order(RID p_particles, VS::ParticlesDrawOrder p_order) { @@ -4972,26 +4969,30 @@ void RasterizerStorageGLES3::particles_set_draw_order(RID p_particles, VS::Parti particles->draw_order = p_order; } -void RasterizerStorageGLES3::particles_set_draw_passes(RID p_particles, int p_count) { +void RasterizerStorageGLES3::particles_set_draw_passes(RID p_particles, int p_passes) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); - particles->draw_passes.resize(p_count); + particles->draw_passes.resize(p_passes); } -void RasterizerStorageGLES3::particles_set_draw_pass_material(RID p_particles, int p_pass, RID p_material) { + +void RasterizerStorageGLES3::particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); ERR_FAIL_INDEX(p_pass, particles->draw_passes.size()); - particles->draw_passes[p_pass].material = p_material; + particles->draw_passes[p_pass] = p_mesh; } -void RasterizerStorageGLES3::particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) { + +void RasterizerStorageGLES3::particles_request_process(RID p_particles) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); - ERR_FAIL_INDEX(p_pass, particles->draw_passes.size()); - particles->draw_passes[p_pass].mesh = p_mesh; + + if (!particles->particle_element.in_list()) { + particle_update_list.add(&particles->particle_element); + } } Rect3 RasterizerStorageGLES3::particles_get_current_aabb(RID p_particles) { @@ -5002,10 +5003,86 @@ Rect3 RasterizerStorageGLES3::particles_get_current_aabb(RID p_particles) { return particles->computed_aabb; } +Rect3 RasterizerStorageGLES3::particles_get_aabb(RID p_particles) const { + + const Particles *particles = particles_owner.getornull(p_particles); + ERR_FAIL_COND_V(!particles, Rect3()); + + return Rect3(Vector3(-1, -1, -1), Vector3(2, 2, 2)); +} + +void RasterizerStorageGLES3::particles_set_emission_transform(RID p_particles, const Transform &p_transform) { + + Particles *particles = particles_owner.getornull(p_particles); + ERR_FAIL_COND(!particles); + + particles->emission_transform = p_transform; +} + +void RasterizerStorageGLES3::_particles_process(Particles *particles, float p_delta) { + + float new_phase = Math::fmod((float)particles->phase + (p_delta / particles->lifetime), (float)1.0); + + if (particles->clear) { + particles->cycle_number = 0; + } else if (new_phase < particles->phase) { + particles->cycle_number++; + } + + shaders.particles.set_uniform(ParticlesShaderGLES3::SYSTEM_PHASE, new_phase); + shaders.particles.set_uniform(ParticlesShaderGLES3::PREV_SYSTEM_PHASE, particles->phase); + particles->phase = new_phase; + + shaders.particles.set_uniform(ParticlesShaderGLES3::DELTA, p_delta); + shaders.particles.set_uniform(ParticlesShaderGLES3::CLEAR, particles->clear); + if (particles->use_local_coords) + shaders.particles.set_uniform(ParticlesShaderGLES3::EMISSION_TRANSFORM, Transform()); + else + shaders.particles.set_uniform(ParticlesShaderGLES3::EMISSION_TRANSFORM, particles->emission_transform); + + glUniform1ui(shaders.particles.get_uniform(ParticlesShaderGLES3::CYCLE), particles->cycle_number); + + particles->clear = false; + + glBindVertexArray(particles->particle_vaos[0]); + + glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, particles->particle_buffers[1]); + + // GLint size = 0; + // glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &size); + + glBeginTransformFeedback(GL_POINTS); + glDrawArrays(GL_POINTS, 0, particles->amount); + glEndTransformFeedback(); + + SWAP(particles->particle_buffers[0], particles->particle_buffers[1]); + SWAP(particles->particle_vaos[0], particles->particle_vaos[1]); + + glBindVertexArray(0); + /* //debug particles :D + glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[0]); + + float *data = (float *)glMapBufferRange(GL_ARRAY_BUFFER, 0, particles->amount * 16 * 6, GL_MAP_READ_BIT); + for (int i = 0; i < particles->amount; i++) { + int ofs = i * 24; + print_line(itos(i) + ":"); + print_line("\tColor: " + Color(data[ofs + 0], data[ofs + 1], data[ofs + 2], data[ofs + 3])); + print_line("\tVelocity: " + Vector3(data[ofs + 4], data[ofs + 5], data[ofs + 6])); + print_line("\tActive: " + itos(data[ofs + 7])); + print_line("\tCustom: " + Color(data[ofs + 8], data[ofs + 9], data[ofs + 10], data[ofs + 11])); + print_line("\tXF X: " + Color(data[ofs + 12], data[ofs + 13], data[ofs + 14], data[ofs + 15])); + print_line("\tXF Y: " + Color(data[ofs + 16], data[ofs + 17], data[ofs + 18], data[ofs + 19])); + print_line("\tXF Z: " + Color(data[ofs + 20], data[ofs + 21], data[ofs + 22], data[ofs + 23])); + } + + glUnmapBuffer(GL_ARRAY_BUFFER); + glBindBuffer(GL_ARRAY_BUFFER, 0); + //*/ +} + void RasterizerStorageGLES3::update_particles() { glEnable(GL_RASTERIZER_DISCARD); - glBindVertexArray(0); while (particle_update_list.first()) { @@ -5068,38 +5145,61 @@ void RasterizerStorageGLES3::update_particles() { } } - shaders.particles.bind(); - - shaders.particles.set_uniform(ParticlesShaderGLES3::ORIGIN, particles->origin); - - float new_phase = Math::fmod((float)particles->phase + (frame.delta / particles->lifetime), (float)1.0); + shaders.particles.set_conditional(ParticlesShaderGLES3::USE_FRACTIONAL_DELTA, particles->fractional_delta); - shaders.particles.set_uniform(ParticlesShaderGLES3::SYSTEM_PHASE, new_phase); - shaders.particles.set_uniform(ParticlesShaderGLES3::PREV_SYSTEM_PHASE, particles->phase); - particles->phase = new_phase; + shaders.particles.bind(); shaders.particles.set_uniform(ParticlesShaderGLES3::TOTAL_PARTICLES, particles->amount); - shaders.particles.set_uniform(ParticlesShaderGLES3::TIME, 0.0); + shaders.particles.set_uniform(ParticlesShaderGLES3::TIME, Color(frame.time[0], frame.time[1], frame.time[2], frame.time[3])); shaders.particles.set_uniform(ParticlesShaderGLES3::EXPLOSIVENESS, particles->explosiveness); - shaders.particles.set_uniform(ParticlesShaderGLES3::DELTA, frame.delta); + shaders.particles.set_uniform(ParticlesShaderGLES3::LIFETIME, particles->lifetime); shaders.particles.set_uniform(ParticlesShaderGLES3::GRAVITY, particles->gravity); shaders.particles.set_uniform(ParticlesShaderGLES3::ATTRACTOR_COUNT, 0); + shaders.particles.set_uniform(ParticlesShaderGLES3::EMITTING, particles->emitting); + shaders.particles.set_uniform(ParticlesShaderGLES3::RANDOMNESS, particles->randomness); - glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[0]); - glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, particles->particle_buffers[1]); + if (particles->clear && particles->pre_process_time > 0.0) { - for (int i = 0; i < 6; i++) { - glEnableVertexAttribArray(i); - glVertexAttribPointer(i, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 4 * 6, ((uint8_t *)0) + (i * 16)); + float frame_time; + if (particles->fixed_fps > 0) + frame_time = 1.0 / particles->fixed_fps; + else + frame_time = 1.0 / 30.0; + + float delta = particles->pre_process_time; + if (delta > 0.1) { //avoid recursive stalls if fps goes below 10 + delta = 0.1; + } + float todo = delta; + + while (todo >= frame_time) { + _particles_process(particles, frame_time); + todo -= frame_time; + } } - glBeginTransformFeedback(GL_POINTS); - glDrawArrays(GL_POINTS, 0, particles->amount); - glEndTransformFeedback(); + if (particles->fixed_fps > 0) { + float frame_time = 1.0 / particles->fixed_fps; + float delta = frame.delta; + if (delta > 0.1) { //avoid recursive stalls if fps goes below 10 + delta = 0.1; + } else if (delta <= 0.0) { //unlikely but.. + delta = 0.001; + } + float todo = particles->frame_remainder + delta; - particle_update_list.remove(particle_update_list.first()); + while (todo >= frame_time) { + _particles_process(particles, frame_time); + todo -= frame_time; + } + + particles->frame_remainder = todo; + + } else { + _particles_process(particles, frame.delta); + } - SWAP(particles->particle_buffers[0], particles->particle_buffers[1]); + particle_update_list.remove(particle_update_list.first()); } glDisable(GL_RASTERIZER_DISCARD); @@ -5143,6 +5243,10 @@ void RasterizerStorageGLES3::instance_add_dependency(RID p_base, RasterizerScene inst = immediate_owner.getornull(p_base); ERR_FAIL_COND(!inst); } break; + case VS::INSTANCE_PARTICLES: { + inst = particles_owner.getornull(p_base); + ERR_FAIL_COND(!inst); + } break; case VS::INSTANCE_REFLECTION_PROBE: { inst = reflection_probe_owner.getornull(p_base); ERR_FAIL_COND(!inst); @@ -5182,6 +5286,10 @@ void RasterizerStorageGLES3::instance_remove_dependency(RID p_base, RasterizerSc inst = immediate_owner.getornull(p_base); ERR_FAIL_COND(!inst); } break; + case VS::INSTANCE_PARTICLES: { + inst = particles_owner.getornull(p_base); + ERR_FAIL_COND(!inst); + } break; case VS::INSTANCE_REFLECTION_PROBE: { inst = reflection_probe_owner.getornull(p_base); ERR_FAIL_COND(!inst); @@ -5856,6 +5964,10 @@ VS::InstanceType RasterizerStorageGLES3::get_base_type(RID p_rid) const { return VS::INSTANCE_IMMEDIATE; } + if (particles_owner.owns(p_rid)) { + return VS::INSTANCE_PARTICLES; + } + if (light_owner.owns(p_rid)) { return VS::INSTANCE_LIGHT; } |