From c2a217c3501b8006a3d2cdf2c678e33def15f275 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sun, 1 Jan 2017 22:16:52 -0300 Subject: [PATCH] WIP particle system Ability to enable and change MSAA settings Ability to change VCT quality Ability to enable/disable HDR rendering --- drivers/gles3/rasterizer_gles3.cpp | 16 +- drivers/gles3/rasterizer_scene_gles3.cpp | 128 +++++-- drivers/gles3/rasterizer_scene_gles3.h | 1 - drivers/gles3/rasterizer_storage_gles3.cpp | 322 ++++++++++++++---- drivers/gles3/rasterizer_storage_gles3.h | 53 ++- drivers/gles3/shader_compiler_gles3.cpp | 19 +- drivers/gles3/shaders/particles.glsl | 139 +++++--- drivers/gles3/shaders/scene.glsl | 6 +- drivers/gles3/shaders/subsurf_scattering.glsl | 4 +- scene/main/scene_main_loop.cpp | 5 + scene/main/viewport.cpp | 48 ++- scene/main/viewport.h | 22 +- scene/register_scene_types.cpp | 1 + scene/resources/shader.cpp | 2 +- scene/resources/shader.h | 10 +- servers/visual/rasterizer.h | 2 + servers/visual/shader_types.cpp | 18 + servers/visual/visual_server_raster.h | 3 + servers/visual/visual_server_viewport.cpp | 16 + servers/visual/visual_server_viewport.h | 3 + servers/visual_server.h | 12 +- .../editor/plugins/spatial_editor_plugin.cpp | 11 + 22 files changed, 677 insertions(+), 164 deletions(-) diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index ccc5c70c97a..0998d9c423c 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -163,18 +163,30 @@ void RasterizerGLES3::initialize() { void RasterizerGLES3::begin_frame(){ - double time_total = double(OS::get_singleton()->get_ticks_usec())/1000000.0; + uint64_t tick = OS::get_singleton()->get_ticks_usec(); + + double time_total = double(tick)/1000000.0; storage->frame.time[0]=time_total; storage->frame.time[1]=Math::fmod(time_total,3600); storage->frame.time[2]=Math::fmod(time_total,900); storage->frame.time[3]=Math::fmod(time_total,60); storage->frame.count++; + storage->frame.delta = double(tick-storage->frame.prev_tick)/1000000.0; + if (storage->frame.prev_tick==0) { + //to avoid hiccups + storage->frame.delta=0.001; + } + + storage->frame.prev_tick=tick; + + storage->update_dirty_multimeshes(); storage->update_dirty_skeletons(); storage->update_dirty_shaders(); storage->update_dirty_materials(); + storage->update_particles(); storage->info.render_object_count=0; storage->info.render_material_switch_count=0; @@ -186,6 +198,8 @@ void RasterizerGLES3::begin_frame(){ scene->iteration(); + + } void RasterizerGLES3::set_current_render_target(RID p_render_target){ diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 1b080a1216d..17e429657bf 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -2880,10 +2880,17 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c glDisable(GL_CULL_FACE); glDisable(GL_BLEND); - bool diffuse_copied=false; if (env->ssao_enabled) { - //ssao + //copy diffuse to front buffer + glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo); + glReadBuffer(GL_COLOR_ATTACHMENT0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->fbo); + glBlitFramebuffer(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, 0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + //copy from depth, convert to linear GLint ss[2]; @@ -2960,7 +2967,7 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.ssao.linear_depth); glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.normal_rough); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.effect); glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.ssao.blur_fbo[0]); //copy to front first Color white(1,1,1,1); @@ -3001,23 +3008,36 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c state.effect_blur_shader.bind(); state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::SSAO_COLOR,env->ssao_color); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse); //previous level, since mipmaps[0] starts one level bigger + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->color); //previous level, since mipmaps[0] starts one level bigger glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.ssao.blur_red[0]); //previous level, since mipmaps[0] starts one level bigger glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); // copy to base level _copy_screen(); state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::SSAO_MERGE,false); + } else { + //copy diffuse to effect buffer + glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo); + glReadBuffer(GL_COLOR_ATTACHMENT0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); + glBlitFramebuffer(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, 0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - diffuse_copied=true; } if (state.used_sss) {//sss enabled //copy diffuse while performing sss + //copy normal and roughness to effect buffer + glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo); + glReadBuffer(GL_COLOR_ATTACHMENT3); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->buffers.effect_fbo); + glBlitFramebuffer(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, 0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, GL_COLOR_BUFFER_BIT , GL_NEAREST); + state.sss_shader.set_conditional(SubsurfScatteringShaderGLES3::USE_11_SAMPLES,subsurface_scatter_quality==SSS_QUALITY_LOW); state.sss_shader.set_conditional(SubsurfScatteringShaderGLES3::USE_17_SAMPLES,subsurface_scatter_quality==SSS_QUALITY_MEDIUM); state.sss_shader.set_conditional(SubsurfScatteringShaderGLES3::USE_25_SAMPLES,subsurface_scatter_quality==SSS_QUALITY_HIGH); @@ -3030,15 +3050,10 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c state.sss_shader.set_uniform(SubsurfScatteringShaderGLES3::DIR,Vector2(1,0)); glActiveTexture(GL_TEXTURE0); - if (diffuse_copied) { - glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.mip_maps[0].color); - } else { - glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse); - diffuse_copied=true; - } + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.mip_maps[0].color); glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.motion_sss); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.effect); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->depth); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); @@ -3056,19 +3071,16 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c } - if (!diffuse_copied) { - // just copy diffuse - storage->shaders.copy.bind(); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse); - glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); // copy to base level - _copy_screen(); - - } - - if (env->ssr_enabled) { + + //copy normal and roughness to effect buffer + glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo); + glReadBuffer(GL_COLOR_ATTACHMENT2); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->buffers.effect_fbo); + glBlitFramebuffer(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, 0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, GL_COLOR_BUFFER_BIT , GL_NEAREST); + + //blur diffuse into effect mipmaps using separatable convolution //storage->shaders.copy.set_conditional(CopyShaderGLES3::GAUSSIAN_HORIZONTAL,true); for(int i=0;iframe.current_rt->effects.mip_maps[1].sizes.size();i++) { @@ -3127,14 +3139,12 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.mip_maps[0].color); glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.normal_rough); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.effect); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->depth); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); - glActiveTexture(GL_TEXTURE3); - glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.mip_maps[0].color); glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.mip_maps[1].sizes[0].fbo); glViewport(0,0,ssr_w,ssr_h); @@ -3145,11 +3155,22 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c } + + glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo); + glReadBuffer(GL_COLOR_ATTACHMENT1); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->fbo); + //glDrawBuffer(GL_COLOR_ATTACHMENT0); + glBlitFramebuffer(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, 0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, GL_COLOR_BUFFER_BIT, GL_NEAREST); + glReadBuffer(GL_COLOR_ATTACHMENT0); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + //copy reflection over diffuse, resolving SSR if needed state.resolve_shader.set_conditional(ResolveShaderGLES3::USE_SSR,env->ssr_enabled); state.resolve_shader.bind(); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.specular); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->color); if (env->ssr_enabled) { glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.mip_maps[1].color); @@ -3169,7 +3190,12 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c state.effect_blur_shader.bind(); state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LOD,float(0)); - glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.alpha_fbo); + { + GLuint db = GL_COLOR_ATTACHMENT0; + glDrawBuffers(1,&db); + } + + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.fbo); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.mip_maps[0].color); @@ -3193,11 +3219,23 @@ void RasterizerSceneGLES3::_post_process(Environment *env,const CameraMatrix &p_ //turn off everything used + //copy specular to front buffer + //copy diffuse to effect buffer + + + glReadBuffer(GL_COLOR_ATTACHMENT0); + glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); + glBlitFramebuffer(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, 0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, GL_COLOR_BUFFER_BIT, GL_NEAREST); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + if (!env) { //no environment, simply return and convert to SRGB glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->fbo); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.mip_maps[0].color); storage->shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB,true); storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA,true); storage->shaders.copy.bind(); @@ -3219,7 +3257,7 @@ void RasterizerSceneGLES3::_post_process(Environment *env,const CameraMatrix &p_ //4) Tonemap //5) Adjustments - GLuint composite_from = storage->frame.current_rt->buffers.diffuse; + GLuint composite_from = storage->frame.current_rt->effects.mip_maps[0].color; if (env->dof_blur_far_enabled) { @@ -3701,11 +3739,15 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C if (storage->frame.current_rt && true) { //pre z pass + + glDisable(GL_BLEND); glDepthMask(GL_TRUE); glEnable(GL_DEPTH_TEST); glDisable(GL_SCISSOR_TEST); - glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->fbo); + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.fbo); + glDrawBuffers(0,NULL); + glViewport(0,0,storage->frame.current_rt->width,storage->frame.current_rt->height); glColorMask(0,0,0,0); @@ -3808,10 +3850,15 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C } else { - current_fbo = storage->frame.current_rt->buffers.alpha_fbo; - glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.alpha_fbo); + + + current_fbo = storage->frame.current_rt->buffers.fbo; + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.fbo); state.scene_shader.set_conditional(SceneShaderGLES3::USE_MULTIPLE_RENDER_TARGETS,false); + Vector draw_buffers; + draw_buffers.push_back(GL_COLOR_ATTACHMENT0); + glDrawBuffers(draw_buffers.size(),draw_buffers.ptr()); } } @@ -3902,9 +3949,9 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C if (env && env->bg_mode==VS::ENV_BG_SKYBOX) { - if (use_mrt) { - glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.alpha_fbo); //switch to alpha fbo for skybox, only diffuse/ambient matters - } + //if (use_mrt) { + // glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.fbo); //switch to alpha fbo for skybox, only diffuse/ambient matters + // _draw_skybox(skybox,p_cam_projection,p_cam_transform,storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP],env->skybox_scale); } @@ -4902,6 +4949,10 @@ void RasterizerSceneGLES3::initialize() { GLOBAL_DEF("rendering/gles3/subsurface_scattering/max_size",1.0); Globals::get_singleton()->set_custom_property_info("rendering/gles3/subsurface_scattering/max_size",PropertyInfo(Variant::INT,"rendering/gles3/subsurface_scattering/max_size",PROPERTY_HINT_RANGE,"0.01,8,0.01")); GLOBAL_DEF("rendering/gles3/subsurface_scattering/follow_surface",false); + + GLOBAL_DEF("rendering/gles3/high_quality_vct_gi",true); + + } exposure_shrink_size=243; @@ -4940,6 +4991,9 @@ void RasterizerSceneGLES3::iteration() { subsurface_scatter_follow_surface=Globals::get_singleton()->get("rendering/gles3/subsurface_scattering/follow_surface"); subsurface_scatter_quality=SubSurfaceScatterQuality(int(Globals::get_singleton()->get("rendering/gles3/subsurface_scattering/quality"))); subsurface_scatter_size=Globals::get_singleton()->get("rendering/gles3/subsurface_scattering/max_size"); + + + state.scene_shader.set_conditional(SceneShaderGLES3::VCT_QUALITY_HIGH,Globals::get_singleton()->get("rendering/gles3/high_quality_vct_gi")); } void RasterizerSceneGLES3::finalize(){ diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 3fdbdb95d0a..7838345e593 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -53,7 +53,6 @@ public: Vector exposure_shrink; int exposure_shrink_size; - struct State { diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 2875c1f7885..c632d1c2daf 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -1401,7 +1401,7 @@ void RasterizerStorageGLES3::shader_set_mode(RID p_shader,VS::ShaderMode p_mode) ShaderGLES3* shaders[VS::SHADER_MAX]={ &scene->state.scene_shader, &canvas->state.canvas_shader, - &canvas->state.canvas_shader, + &this->shaders.particles, }; @@ -1510,6 +1510,11 @@ void RasterizerStorageGLES3::_update_shader(Shader* p_shader) const { } + case VS::SHADER_PARTICLES: { + + actions=&shaders.actions_particles; + actions->uniforms=&p_shader->uniforms; + } } @@ -4998,6 +5003,7 @@ void RasterizerStorageGLES3::gi_probe_dynamic_data_update(RID p_gi_probe_data, i /////// + RID RasterizerStorageGLES3::particles_create() { Particles *particles = memnew( Particles ); @@ -5018,7 +5024,30 @@ void RasterizerStorageGLES3::particles_set_amount(RID p_particles,int p_amount) Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); + int floats = p_amount*24; + float * data = memnew_arr(float,floats); + + for(int i=0;iparticle_buffers[0]); + glBufferData(GL_ARRAY_BUFFER,floats*sizeof(float),data,GL_DYNAMIC_DRAW); + + glBindBuffer(GL_ARRAY_BUFFER,particles->particle_buffers[1]); + glBufferData(GL_ARRAY_BUFFER,floats*sizeof(float),data,GL_DYNAMIC_DRAW); + + glBindBuffer(GL_ARRAY_BUFFER,0); + + particles->prev_ticks=0; + particles->phase=0; + particles->prev_phase=0; + + memdelete_arr(data); + } + void RasterizerStorageGLES3::particles_set_lifetime(RID p_particles,float p_lifetime){ Particles *particles = particles_owner.getornull(p_particles); @@ -5125,7 +5154,7 @@ void RasterizerStorageGLES3::particles_set_draw_pass_material(RID p_particles,in Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); ERR_FAIL_INDEX(p_pass,particles->draw_passes.size()); - p_pass,particles->draw_passes[p_pass].material=p_material; + particles->draw_passes[p_pass].material=p_material; } void RasterizerStorageGLES3::particles_set_draw_pass_mesh(RID p_particles,int p_pass, RID p_mesh) { @@ -5133,7 +5162,7 @@ void RasterizerStorageGLES3::particles_set_draw_pass_mesh(RID p_particles,int p_ Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); ERR_FAIL_INDEX(p_pass,particles->draw_passes.size()); - p_pass,particles->draw_passes[p_pass].mesh=p_mesh; + particles->draw_passes[p_pass].mesh=p_mesh; } @@ -5145,6 +5174,124 @@ AABB RasterizerStorageGLES3::particles_get_current_aabb(RID p_particles) { return particles->computed_aabb; } +void RasterizerStorageGLES3::update_particles() { + + glEnable(GL_RASTERIZER_DISCARD); + glBindVertexArray(0); + + + while (particle_update_list.first()) { + + //use transform feedback to process particles + + Particles *particles = particle_update_list.first()->self(); + + + Material *material = material_owner.getornull(particles->process_material); + if (!material || !material->shader || material->shader->mode!=VS::SHADER_PARTICLES) { + + shaders.particles.set_custom_shader(0); + } else { + shaders.particles.set_custom_shader( material->shader->custom_code_id ); + + if (material->ubo_id) { + + glBindBufferBase(GL_UNIFORM_BUFFER,0,material->ubo_id); + } + + int tc = material->textures.size(); + RID* textures = material->textures.ptr(); + ShaderLanguage::ShaderNode::Uniform::Hint* texture_hints = material->shader->texture_hints.ptr(); + + + for(int i=0;itarget; + tex = t->tex_id; + + } + + glBindTexture(target,tex); + } + + } + + shaders.particles.bind(); + + shaders.particles.set_uniform(ParticlesShaderGLES3::ORIGIN,particles->origin); + + float new_phase = Math::fmod(particles->phase+(frame.delta/particles->lifetime),1.0); + + 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::TOTAL_PARTICLES,particles->amount); + shaders.particles.set_uniform(ParticlesShaderGLES3::TIME,0.0); + shaders.particles.set_uniform(ParticlesShaderGLES3::EXPLOSIVENESS,particles->explosiveness); + shaders.particles.set_uniform(ParticlesShaderGLES3::DELTA,frame.delta); + shaders.particles.set_uniform(ParticlesShaderGLES3::GRAVITY,particles->gravity); + shaders.particles.set_uniform(ParticlesShaderGLES3::ATTRACTOR_COUNT,0); + + + + + glBindBuffer(GL_ARRAY_BUFFER,particles->particle_buffers[0]); + glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, particles->particle_buffers[1]); + + 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)); + } + + + glBeginTransformFeedback(GL_POINTS); + glDrawArrays(GL_POINTS,0,particles->amount); + glEndTransformFeedback(); + + particle_update_list.remove(particle_update_list.first()); + + SWAP(particles->particle_buffers[0],particles->particle_buffers[1]); + } + + glDisable(GL_RASTERIZER_DISCARD); + + for(int i=0;i<6;i++) { + glDisableVertexAttribArray(i); + } + +} + //////// void RasterizerStorageGLES3::instance_add_skeleton(RID p_skeleton,RasterizerScene::InstanceBase *p_instance) { @@ -5258,13 +5405,15 @@ void RasterizerStorageGLES3::_render_target_clear(RenderTarget *rt) { if (rt->buffers.fbo) { glDeleteFramebuffers(1,&rt->buffers.fbo); - glDeleteFramebuffers(1,&rt->buffers.alpha_fbo); - glDeleteTextures(1,&rt->buffers.diffuse); - glDeleteTextures(1,&rt->buffers.specular); - glDeleteTextures(1,&rt->buffers.normal_rough); - glDeleteTextures(1,&rt->buffers.motion_sss); + glDeleteRenderbuffers(1,&rt->buffers.depth); + glDeleteRenderbuffers(1,&rt->buffers.diffuse); + glDeleteRenderbuffers(1,&rt->buffers.specular); + glDeleteRenderbuffers(1,&rt->buffers.normal_rough); + glDeleteRenderbuffers(1,&rt->buffers.motion_sss); + glDeleteFramebuffers(1,&rt->buffers.effect_fbo); + glDeleteTextures(1,&rt->buffers.effect); + rt->buffers.fbo=0; - rt->buffers.alpha_fbo=0; } if (rt->depth) { @@ -5327,19 +5476,12 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){ - if (config.render_arch==RENDER_ARCH_MOBILE || rt->flags[RENDER_TARGET_NO_3D]) { + if (!rt->flags[RENDER_TARGET_HDR] || rt->flags[RENDER_TARGET_NO_3D]) { - if (rt->flags[RENDER_TARGET_TRANSPARENT]) { - color_internal_format=GL_RGBA8; - color_format=GL_RGBA; - color_type=GL_UNSIGNED_BYTE; - image_format=Image::FORMAT_RGBA8; - } else { - color_internal_format=GL_RGB10_A2; - color_format=GL_RGBA; - color_type=GL_UNSIGNED_INT_2_10_10_10_REV; - image_format=Image::FORMAT_RGBA8;//todo - } + color_internal_format=GL_RGBA8; + color_format=GL_RGBA; + color_type=GL_UNSIGNED_BYTE; + image_format=Image::FORMAT_RGBA8; } else { color_internal_format=GL_RGBA16F; color_format=GL_RGBA; @@ -5347,6 +5489,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){ image_format=Image::FORMAT_RGBAH; } + { /* FRONT FBO */ @@ -5407,69 +5550,99 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){ + static const int msaa_value[]={0,2,4,8,16}; + int msaa=msaa_value[rt->msaa]; + //regular fbo glGenFramebuffers(1, &rt->buffers.fbo); glBindFramebuffer(GL_FRAMEBUFFER, rt->buffers.fbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, - GL_TEXTURE_2D, rt->depth, 0); + glGenRenderbuffers(1, &rt->buffers.depth); + glBindRenderbuffer(GL_RENDERBUFFER, rt->buffers.depth); + if (msaa==0) + glRenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH24_STENCIL8,rt->width,rt->height); + else + glRenderbufferStorageMultisample(GL_RENDERBUFFER,msaa,GL_DEPTH24_STENCIL8,rt->width,rt->height); - glGenTextures(1, &rt->buffers.diffuse); - glBindTexture(GL_TEXTURE_2D, rt->buffers.diffuse); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, rt->width, rt->height, 0, GL_RGBA, GL_HALF_FLOAT, NULL); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->buffers.diffuse, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_RENDERBUFFER,rt->buffers.depth); + + glGenRenderbuffers(1, &rt->buffers.diffuse); + glBindRenderbuffer(GL_RENDERBUFFER, rt->buffers.diffuse); - glGenTextures(1, &rt->buffers.specular); - glBindTexture(GL_TEXTURE_2D, rt->buffers.specular); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, rt->width, rt->height, 0, GL_RGBA, GL_HALF_FLOAT, NULL); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, rt->buffers.specular, 0); + if (msaa==0) + glRenderbufferStorage(GL_RENDERBUFFER,color_internal_format,rt->width,rt->height); + else + glRenderbufferStorageMultisample(GL_RENDERBUFFER,msaa,GL_RGBA16F,rt->width,rt->height); - glGenTextures(1, &rt->buffers.normal_rough); - glBindTexture(GL_TEXTURE_2D, rt->buffers.normal_rough); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, rt->width, rt->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, rt->buffers.normal_rough, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_RENDERBUFFER,rt->buffers.diffuse); + + glGenRenderbuffers(1, &rt->buffers.specular); + glBindRenderbuffer(GL_RENDERBUFFER, rt->buffers.specular); + + if (msaa==0) + glRenderbufferStorage(GL_RENDERBUFFER,GL_RGBA16F,rt->width,rt->height); + else + glRenderbufferStorageMultisample(GL_RENDERBUFFER,msaa,color_internal_format,rt->width,rt->height); + + glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT1,GL_RENDERBUFFER,rt->buffers.specular); + + glGenRenderbuffers(1, &rt->buffers.normal_rough); + glBindRenderbuffer(GL_RENDERBUFFER, rt->buffers.normal_rough); + + if (msaa==0) + glRenderbufferStorage(GL_RENDERBUFFER,GL_RGBA8,rt->width,rt->height); + else + glRenderbufferStorageMultisample(GL_RENDERBUFFER,msaa,GL_RGBA8,rt->width,rt->height); + + glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT2,GL_RENDERBUFFER,rt->buffers.normal_rough); + + + glGenRenderbuffers(1, &rt->buffers.motion_sss); + glBindRenderbuffer(GL_RENDERBUFFER, rt->buffers.motion_sss); + + if (msaa==0) + glRenderbufferStorage(GL_RENDERBUFFER,GL_RGBA8,rt->width,rt->height); + else + glRenderbufferStorageMultisample(GL_RENDERBUFFER,msaa,GL_RGBA8,rt->width,rt->height); + + glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT3,GL_RENDERBUFFER,rt->buffers.motion_sss); - glGenTextures(1, &rt->buffers.motion_sss); - glBindTexture(GL_TEXTURE_2D, rt->buffers.motion_sss); - glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, rt->width, rt->height, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, rt->buffers.motion_sss, 0); GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); glBindFramebuffer(GL_FRAMEBUFFER, config.system_fbo); if (status != GL_FRAMEBUFFER_COMPLETE) { + printf("err status: %x\n",status); _render_target_clear(rt); ERR_FAIL_COND( status != GL_FRAMEBUFFER_COMPLETE ); - } + } + + glBindRenderbuffer(GL_RENDERBUFFER,0); + + // effect resolver + + glGenFramebuffers(1, &rt->buffers.effect_fbo); + glBindFramebuffer(GL_FRAMEBUFFER, rt->buffers.effect_fbo); + + glGenTextures(1, &rt->buffers.effect); + glBindTexture(GL_TEXTURE_2D, rt->buffers.effect); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, rt->width, rt->height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, rt->buffers.effect, 0); - //alpha fbo - glGenFramebuffers(1, &rt->buffers.alpha_fbo); - glBindFramebuffer(GL_FRAMEBUFFER, rt->buffers.alpha_fbo); + if (status != GL_FRAMEBUFFER_COMPLETE) { + printf("err status: %x\n",status); + _render_target_clear(rt); + ERR_FAIL_COND( status != GL_FRAMEBUFFER_COMPLETE ); + } - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, - GL_TEXTURE_2D, rt->depth, 0); - - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->buffers.diffuse, 0); - - status = glCheckFramebufferStatus(GL_FRAMEBUFFER); glBindFramebuffer(GL_FRAMEBUFFER, config.system_fbo); if (status != GL_FRAMEBUFFER_COMPLETE) { @@ -5499,7 +5672,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){ RenderTarget::Effects::MipMaps::Size mm; - glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA16F, w, h, 0, GL_RGBA, GL_HALF_FLOAT, NULL); + glTexImage2D(GL_TEXTURE_2D, level, color_internal_format, w, h, 0, color_format, color_type, NULL); mm.width=w; mm.height=h; rt->effects.mip_maps[i].sizes.push_back(mm); @@ -5711,6 +5884,20 @@ bool RasterizerStorageGLES3::render_target_renedered_in_frame(RID p_render_targe return false; } +void RasterizerStorageGLES3::render_target_set_msaa(RID p_render_target,VS::ViewportMSAA p_msaa) { + + RenderTarget *rt = render_target_owner.getornull(p_render_target); + ERR_FAIL_COND(!rt); + + if (rt->msaa==p_msaa) + return; + + _render_target_clear(rt); + rt->msaa=p_msaa; + _render_target_allocate(rt); + +} + /* CANVAS SHADOW */ @@ -6283,10 +6470,13 @@ void RasterizerStorageGLES3::initialize() { } shaders.cubemap_filter.init(); + shaders.particles.init(); glEnable(_EXT_TEXTURE_CUBE_MAP_SEAMLESS); frame.count=0; + frame.prev_tick=0; + frame.delta=0; config.keep_original_textures=false; } diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index 690a169ca26..357b69183e5 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -8,6 +8,7 @@ #include "shaders/canvas.glsl.h" #include "shaders/blend_shape.glsl.h" #include "shaders/cubemap_filter.glsl.h" +#include "shaders/particles.glsl.h" #include "self_list.h" #include "shader_compiler_gles3.h" @@ -70,8 +71,11 @@ public: BlendShapeShaderGLES3 blend_shapes; + ParticlesShaderGLES3 particles; + ShaderCompilerGLES3::IdentifierActions actions_canvas; ShaderCompilerGLES3::IdentifierActions actions_scene; + ShaderCompilerGLES3::IdentifierActions actions_particles; } shaders; struct Resources { @@ -385,6 +389,12 @@ public: } spatial; + struct Particles { + + + } particles; + + bool uses_vertex_time; bool uses_fragment_time; @@ -988,7 +998,17 @@ public: AABB computed_aabb; - Particles() { + GLuint particle_buffers[2]; + + SelfList particle_element; + + float phase; + float prev_phase; + uint64_t prev_ticks; + + Transform origin; + + Particles() : particle_element(this) { emitting=false; amount=0; lifetime=1.0;; @@ -1000,13 +1020,29 @@ public: draw_order=VS::PARTICLES_DRAW_ORDER_INDEX; emission_shape=VS::PARTICLES_EMSSION_POINT; emission_sphere_radius=1.0; - float emission_sphere_radius; emission_box_extents=Vector3(1,1,1); emission_point_texture=0; + particle_buffers[0]=0; + particle_buffers[1]=0; + + prev_ticks=0; + + glGenBuffers(2,particle_buffers); } + ~Particles() { + + glDeleteBuffers(2,particle_buffers); + } + + }; + SelfList::List particle_update_list; + + void update_particles(); + + mutable RID_Owner particles_owner; virtual RID particles_create(); @@ -1054,11 +1090,15 @@ public: struct Buffers { GLuint fbo; - GLuint alpha_fbo; //single buffer, just diffuse (for alpha pass) + GLuint depth; GLuint specular; GLuint diffuse; GLuint normal_rough; GLuint motion_sss; + + GLuint effect_fbo; + GLuint effect; + } buffers; struct Effects { @@ -1110,22 +1150,24 @@ public: bool flags[RENDER_TARGET_FLAG_MAX]; bool used_in_frame; + VS::ViewportMSAA msaa; RID texture; RenderTarget() { + msaa=VS::VIEWPORT_MSAA_DISABLED; width=0; height=0; depth=0; fbo=0; buffers.fbo=0; - buffers.alpha_fbo=0; used_in_frame=false; flags[RENDER_TARGET_VFLIP]=false; flags[RENDER_TARGET_TRANSPARENT]=false; flags[RENDER_TARGET_NO_3D]=false; + flags[RENDER_TARGET_HDR]=true; flags[RENDER_TARGET_NO_SAMPLING]=false; last_exposure_tick=0; @@ -1143,6 +1185,7 @@ public: virtual void render_target_set_flag(RID p_render_target,RenderTargetFlags p_flag,bool p_value); virtual bool render_target_renedered_in_frame(RID p_render_target); + virtual void render_target_set_msaa(RID p_render_target,VS::ViewportMSAA p_msaa); /* CANVAS SHADOW */ @@ -1187,6 +1230,8 @@ public: Color clear_request_color; int canvas_draw_commands; float time[4]; + float delta; + uint64_t prev_tick; uint64_t count; } frame; diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp index 336cf7b34ba..26b9aeada4f 100644 --- a/drivers/gles3/shader_compiler_gles3.cpp +++ b/drivers/gles3/shader_compiler_gles3.cpp @@ -703,6 +703,24 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() { actions[VS::SHADER_SPATIAL].render_mode_defines["skip_transform"]="#define SKIP_TRANSFORM_USED\n"; + /* PARTICLES SHADER */ + + actions[VS::SHADER_PARTICLES].renames["COLOR"]="color"; + actions[VS::SHADER_PARTICLES].renames["VELOCITY"]="out_velocity_active.xyz"; + actions[VS::SHADER_PARTICLES].renames["MASS"]="mass"; + actions[VS::SHADER_PARTICLES].renames["ACTIVE"]="active"; + actions[VS::SHADER_PARTICLES].renames["RESTART"]="restart"; + actions[VS::SHADER_PARTICLES].renames["CUSTOM"]="out_custom"; + actions[VS::SHADER_PARTICLES].renames["TRANSFORM"]="xform"; + actions[VS::SHADER_PARTICLES].renames["TIME"]="time"; + actions[VS::SHADER_PARTICLES].renames["LIFETIME"]="lifetime"; + actions[VS::SHADER_PARTICLES].renames["DELTA"]="delta"; + actions[VS::SHADER_PARTICLES].renames["SEED"]="seed"; + actions[VS::SHADER_PARTICLES].renames["ORIGIN"]="origin"; + actions[VS::SHADER_PARTICLES].renames["INDEX"]="index"; + + actions[VS::SHADER_SPATIAL].render_mode_defines["disable_force"]="#define DISABLE_FORCE\n"; + actions[VS::SHADER_SPATIAL].render_mode_defines["disable_velocity"]="#define DISABLE_VELOCITY\n"; vertex_name="vertex"; @@ -710,7 +728,6 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() { time_name="TIME"; - List func_list; ShaderLanguage::get_builtin_funcs(&func_list); diff --git a/drivers/gles3/shaders/particles.glsl b/drivers/gles3/shaders/particles.glsl index fb6060957e5..e72f12cc5e0 100644 --- a/drivers/gles3/shaders/particles.glsl +++ b/drivers/gles3/shaders/particles.glsl @@ -2,10 +2,12 @@ -layout(location=0) in highp vec4 pos_lifetime; -layout(location=1) in highp vec4 color; -layout(location=2) in highp vec4 velocity_seed; -layout(location=3) in highp vec4 rot_active; +layout(location=0) in highp vec4 color; +layout(location=1) in highp vec4 velocity_active; +layout(location=2) in highp vec4 custom; +layout(location=3) in highp vec4 xform_1; +layout(location=4) in highp vec4 xform_2; +layout(location=5) in highp vec4 xform_3; struct Attractor { @@ -32,10 +34,24 @@ uniform int attractor_count; uniform Attractor attractors[MAX_ATTRACTORS]; -out highp vec4 out_pos_lifetime; //tfb: out highp vec4 out_color; //tfb: -out highp vec4 out_velocity_seed; //tfb: -out highp vec4 out_rot_active; //tfb: +out highp vec4 out_velocity_active; //tfb: +out highp vec4 out_custom; //tfb: +out highp vec4 out_xform_1; //tfb: +out highp vec4 out_xform_2; //tfb: +out highp vec4 out_xform_3; //tfb: + +VERTEX_SHADER_GLOBALS + +#if defined(USE_MATERIAL) + +layout(std140) uniform UniformData { //ubo:0 + +MATERIAL_UNIFORMS + +}; + +#endif void main() { @@ -47,6 +63,7 @@ void main() { float restart_phase = float(gl_InstanceID)/total_particles; restart_phase*= explosiveness; bool restart=false; + bool active = out_velocity_active.a > 0.5; if (system_phase > prev_system_phase) { restart = prev_system_phase < restart_phase && system_phase >= restart_phase; @@ -55,60 +72,96 @@ void main() { } if (restart) { - out_rot_active.a=1.0; + active=true; } - out_pos_lifetime=pos_lifetime; out_color=color; - out_velocity_seed=velocity_seed; + out_velocity_active=velocity_active; + out_custom=custom; + + mat4 xform = transpose(mat4(xform_1,xform_2,xform_3,vec4(vec3(0.0),1.0))); + + out_rot_active=rot_active; - if (out_rot_active.a) { + if (active) { //execute shader - } - - - if (apply_forces) { - - vec3 force = gravity; - for(int i=0;i0 && attractors[i].eat_radius > dist) { - rot_active.a=0.0; - } - - rel_vec = normalize(rel_vec); - - float attenuation = pow(dist / attractors[i].radius,attractors[i].attenuation); - - if (attractors[i].dir==vec3(0.0)) { - //towards center - force+=attractors[i].strength * rel_vec * attenuation * mass; - } else { - force+=attractors[i].strength * attractors[i].dir * attenuation *mass; - - } + { + VERTEX_SHADER_CODE } - out_velocity_seed.xyz += force * delta; +#if !defined(DISABLE_FORCE) + + { + + vec3 force = gravity; + for(int i=0;i0 && attractors[i].eat_radius > dist) { + out_velocity_active.a=0.0; + } + + rel_vec = normalize(rel_vec); + + float attenuation = pow(dist / attractors[i].radius,attractors[i].attenuation); + + if (attractors[i].dir==vec3(0.0)) { + //towards center + force+=attractors[i].strength * rel_vec * attenuation * mass; + } else { + force+=attractors[i].strength * attractors[i].dir * attenuation *mass; + + } + } + + out_velocity_seed.xyz += force * delta; + } +#endif + +#if !defined(DISABLE_VELOCITY) + + { + + out_pos_lifetime.xyz += out_velocity_seed.xyz * delta; + } +#endif } - if (apply_velocity) { + xform = transpose(xform); + + out_velocity_active.a = mix(0.0,1.0,active); + + out_xform_1 = xform[0]; + out_xform_2 = xform[1]; + out_xform_3 = xform[2]; - out_pos_lifetime.xyz += out_velocity_seed.xyz * delta; - } } [fragment] +//any code here is never executed, stuff is filled just so it works + +FRAGMENT_SHADER_GLOBALS + +#if defined(USE_MATERIAL) + +layout(std140) uniform UniformData { + +MATERIAL_UNIFORMS + +}; + +#endif void main() { - + { + FRAGMENT_SHADER_CODE + } } diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index c18a356a546..c5af010c965 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -484,7 +484,7 @@ layout(location=0) out vec4 diffuse_buffer; layout(location=1) out vec4 specular_buffer; layout(location=2) out vec4 normal_mr_buffer; #if defined (ENABLE_SSS_MOTION) -layout(location=3) out uint motion_ssr_buffer; +layout(location=3) out vec4 motion_ssr_buffer; #endif #else @@ -902,7 +902,7 @@ void gi_probe_compute(sampler3D probe, mat4 probe_xform, vec3 bounds,vec3 cell_s float max_distance = length(bounds); //radiance -#ifndef VCT_QUALITY_HIGH +#ifdef VCT_QUALITY_HIGH #define MAX_CONE_DIRS 6 vec3 cone_dirs[MAX_CONE_DIRS] = vec3[] ( @@ -1407,7 +1407,7 @@ LIGHT_SHADER_CODE normal_mr_buffer=vec4(normalize(normal)*0.5+0.5,roughness); #if defined (ENABLE_SSS_MOTION) - motion_ssr_buffer = uint(clamp(sqrt(sss_strength)*255.0,0.0,255))<<24; + motion_ssr_buffer = vec4(vec3(0.0),sss_strength); #endif #else diff --git a/drivers/gles3/shaders/subsurf_scattering.glsl b/drivers/gles3/shaders/subsurf_scattering.glsl index 89e618b66c0..eb329dbaedd 100644 --- a/drivers/gles3/shaders/subsurf_scattering.glsl +++ b/drivers/gles3/shaders/subsurf_scattering.glsl @@ -107,14 +107,14 @@ uniform vec2 dir; in vec2 uv_interp; uniform sampler2D source_diffuse; //texunit:0 -uniform highp usampler2D source_motion_ss; //texunit:1 +uniform sampler2D source_motion_ss; //texunit:1 uniform sampler2D source_depth; //texunit:2 layout(location = 0) out vec4 frag_color; void main() { - float strength = float(texture(source_motion_ss,uv_interp).r>>24)*(1.0/255.0); + float strength = texture(source_motion_ss,uv_interp).a; strength*=strength; //stored as sqrt // Fetch color of current pixel: diff --git a/scene/main/scene_main_loop.cpp b/scene/main/scene_main_loop.cpp index abc4bf3fe2e..3145be1dbf0 100644 --- a/scene/main/scene_main_loop.cpp +++ b/scene/main/scene_main_loop.cpp @@ -2322,6 +2322,11 @@ SceneTree::SceneTree() { int ref_atlas_size = GLOBAL_DEF("rendering/reflections/atlas_size",2048); int ref_atlas_subdiv = GLOBAL_DEF("rendering/reflections/atlas_subdiv",8); + int msaa_mode = GLOBAL_DEF("rendering/antialias/msaa",0); + Globals::get_singleton()->set_custom_property_info("rendering/antialias/msaa",PropertyInfo(Variant::INT,"rendering/antialias/msaa",PROPERTY_HINT_ENUM,"Disabled,2x,4x,8x,16x")); + root->set_msaa(Viewport::MSAA(msaa_mode)); + bool hdr = GLOBAL_DEF("rendering/dynamic_range/hdr",true); + root->set_hdr(hdr); VS::get_singleton()->scenario_set_reflection_atlas_size(root->get_world()->get_scenario(),ref_atlas_size,ref_atlas_subdiv); diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 8dec34a4cde..29b18c090ba 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -2593,6 +2593,36 @@ int Viewport::gui_get_canvas_sort_index() { return gui.canvas_sort_index++; } +void Viewport::set_msaa(MSAA p_msaa) { + + ERR_FAIL_INDEX(p_msaa,5); + if (msaa==p_msaa) + return; + msaa=p_msaa; + VS::get_singleton()->viewport_set_msaa(viewport,VS::ViewportMSAA(p_msaa)); +} + +Viewport::MSAA Viewport::get_msaa() const { + + return msaa; +} + +void Viewport::set_hdr(bool p_hdr) { + + if (hdr==p_hdr) + return; + + hdr=p_hdr; + VS::get_singleton()->viewport_set_hdr(viewport,p_hdr); + +} + +bool Viewport::get_hdr() const{ + + return hdr; +} + + void Viewport::_bind_methods() { @@ -2643,6 +2673,12 @@ void Viewport::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_update_mode","mode"), &Viewport::set_update_mode); ObjectTypeDB::bind_method(_MD("get_update_mode"), &Viewport::get_update_mode); + ObjectTypeDB::bind_method(_MD("set_msaa","msaa"), &Viewport::set_msaa); + ObjectTypeDB::bind_method(_MD("get_msaa"), &Viewport::get_msaa); + + ObjectTypeDB::bind_method(_MD("set_hdr","enable"), &Viewport::set_hdr); + ObjectTypeDB::bind_method(_MD("get_hdr"), &Viewport::get_hdr); + ObjectTypeDB::bind_method(_MD("get_texture:ViewportTexture"), &Viewport::get_texture); ObjectTypeDB::bind_method(_MD("set_physics_object_picking","enable"), &Viewport::set_physics_object_picking); @@ -2692,6 +2728,8 @@ void Viewport::_bind_methods() { ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"world",PROPERTY_HINT_RESOURCE_TYPE,"World"), _SCS("set_world"), _SCS("get_world") ); // ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"world_2d",PROPERTY_HINT_RESOURCE_TYPE,"World2D"), _SCS("set_world_2d"), _SCS("get_world_2d") ); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"transparent_bg"), _SCS("set_transparent_background"), _SCS("has_transparent_background") ); + ADD_PROPERTY( PropertyInfo(Variant::INT,"msaa",PROPERTY_HINT_ENUM,"Disabled,2x,4x,8x,16x"), _SCS("set_msaa"), _SCS("get_msaa") ); + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"hdr"), _SCS("set_hdr"), _SCS("get_hdr") ); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"render_target/v_flip"), _SCS("set_vflip"), _SCS("get_vflip") ); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"render_target/clear_on_new_frame"), _SCS("set_clear_on_new_frame"), _SCS("get_clear_on_new_frame") ); ADD_PROPERTY( PropertyInfo(Variant::INT,"render_target/update_mode",PROPERTY_HINT_ENUM,"Disabled,Once,When Visible,Always"), _SCS("set_update_mode"), _SCS("get_update_mode") ); @@ -2721,6 +2759,13 @@ void Viewport::_bind_methods() { BIND_CONSTANT( SHADOW_ATLAS_QUADRANT_SUBDIV_256 ); BIND_CONSTANT( SHADOW_ATLAS_QUADRANT_SUBDIV_1024 ); BIND_CONSTANT( SHADOW_ATLAS_QUADRANT_SUBDIV_MAX ); + + BIND_CONSTANT( MSAA_DISABLED ); + BIND_CONSTANT( MSAA_2X ); + BIND_CONSTANT( MSAA_4X ); + BIND_CONSTANT( MSAA_8X ); + BIND_CONSTANT( MSAA_16X ); + } @@ -2790,7 +2835,8 @@ Viewport::Viewport() { gui.canvas_sort_index=0; - + msaa=MSAA_DISABLED; + hdr=false; } diff --git a/scene/main/viewport.h b/scene/main/viewport.h index 462ecff93ee..46e88e068e5 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -98,6 +98,14 @@ public: }; + enum MSAA { + MSAA_DISABLED, + MSAA_2X, + MSAA_4X, + MSAA_8X, + MSAA_16X, + }; + private: friend class ViewportTexture; @@ -188,6 +196,9 @@ friend class ViewportTexture; int shadow_atlas_size; ShadowAtlasQuadrantSubdiv shadow_atlas_quadrant_subdiv[4]; + MSAA msaa; + bool hdr; + struct GUI { // info used when this is a window @@ -366,6 +377,12 @@ public: void set_shadow_atlas_quadrant_subdiv(int p_quadrant,ShadowAtlasQuadrantSubdiv p_subdiv); ShadowAtlasQuadrantSubdiv get_shadow_atlas_quadrant_subdiv(int p_quadrant) const; + void set_msaa(MSAA p_msaa); + MSAA get_msaa() const; + + void set_hdr(bool p_hdr); + bool get_hdr() const; + Vector2 get_camera_coords(const Vector2& p_viewport_coords) const; Vector2 get_camera_rect_size() const; @@ -410,7 +427,8 @@ public: }; -VARIANT_ENUM_CAST(Viewport::UpdateMode); -VARIANT_ENUM_CAST(Viewport::ShadowAtlasQuadrantSubdiv); +VARIANT_ENUM_CAST( Viewport::UpdateMode ); +VARIANT_ENUM_CAST( Viewport::ShadowAtlasQuadrantSubdiv ); +VARIANT_ENUM_CAST( Viewport::MSAA ); #endif diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 1c2620ec9ae..26b5def5b50 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -557,6 +557,7 @@ void register_scene_types() { ObjectTypeDB::register_type(); // ObjectTypeDB::register_type(); ObjectTypeDB::register_type(); + ObjectTypeDB::register_type(); ObjectTypeDB::add_compatibility_type("Shader","MaterialShader"); ObjectTypeDB::add_compatibility_type("ParticleSystemMaterial","FixedSpatialMaterial"); ObjectTypeDB::add_compatibility_type("UnshadedMaterial","FixedSpatialMaterial"); diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp index 8889d1b6f87..fd64bfe8fab 100644 --- a/scene/resources/shader.cpp +++ b/scene/resources/shader.cpp @@ -133,7 +133,7 @@ void Shader::_bind_methods() { BIND_CONSTANT( MODE_SPATIAL); BIND_CONSTANT( MODE_CANVAS_ITEM ); - BIND_CONSTANT( MODE_POST_PROCESS ); + BIND_CONSTANT( MODE_PARTICLES ); } diff --git a/scene/resources/shader.h b/scene/resources/shader.h index eddb98333d0..4ed50fd61ea 100644 --- a/scene/resources/shader.h +++ b/scene/resources/shader.h @@ -44,7 +44,7 @@ public: MODE_SPATIAL, MODE_CANVAS_ITEM, - MODE_POST_PROCESS, + MODE_PARTICLES, MODE_MAX }; private: @@ -119,6 +119,14 @@ public: }; +class ParticlesShader : public Shader { + + OBJ_TYPE(ParticlesShader,Shader); + +public: + + ParticlesShader() : Shader(MODE_PARTICLES) {}; +}; #endif // SHADER_H diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index 7452985522d..7c6f6111c23 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -484,6 +484,7 @@ public: RENDER_TARGET_TRANSPARENT, RENDER_TARGET_NO_3D, RENDER_TARGET_NO_SAMPLING, + RENDER_TARGET_HDR, RENDER_TARGET_FLAG_MAX }; @@ -492,6 +493,7 @@ public: virtual RID render_target_get_texture(RID p_render_target) const=0; virtual void render_target_set_flag(RID p_render_target,RenderTargetFlags p_flag,bool p_value)=0; virtual bool render_target_renedered_in_frame(RID p_render_target)=0; + virtual void render_target_set_msaa(RID p_render_target,VS::ViewportMSAA p_msaa)=0; /* CANVAS SHADOW */ diff --git a/servers/visual/shader_types.cpp b/servers/visual/shader_types.cpp index 4872135e2ac..0eb3e0fc5a7 100644 --- a/servers/visual/shader_types.cpp +++ b/servers/visual/shader_types.cpp @@ -156,7 +156,25 @@ ShaderTypes::ShaderTypes() shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("light_only"); + /************ PARTICLES **************************/ + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["COLOR"]=ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["VELOCITY"]=ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["MASS"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["ACTIVE"]=ShaderLanguage::TYPE_BOOL; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["RESTART"]=ShaderLanguage::TYPE_BOOL; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["CUSTOM"]=ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["TRANSFORM"]=ShaderLanguage::TYPE_MAT4; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["TIME"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["LIFETIME"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["DELTA"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["SEED"]=ShaderLanguage::TYPE_BOOL; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["ORIGIN"]=ShaderLanguage::TYPE_MAT4; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["INDEX"]=ShaderLanguage::TYPE_INT; + + shader_modes[VS::SHADER_PARTICLES].modes.insert("billboard"); + shader_modes[VS::SHADER_PARTICLES].modes.insert("disable_force"); + shader_modes[VS::SHADER_PARTICLES].modes.insert("disable_velocity"); diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index e67c140b2d5..300924e3b28 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -919,6 +919,9 @@ public: BIND3(viewport_set_canvas_layer,RID ,RID ,int ) BIND2(viewport_set_shadow_atlas_size,RID ,int ) BIND3(viewport_set_shadow_atlas_quadrant_subdivision,RID ,int, int ) + BIND2(viewport_set_msaa,RID ,ViewportMSAA ) + BIND2(viewport_set_hdr,RID ,bool ) + /* ENVIRONMENT API */ diff --git a/servers/visual/visual_server_viewport.cpp b/servers/visual/visual_server_viewport.cpp index fa2c461f36c..558a3e4c239 100644 --- a/servers/visual/visual_server_viewport.cpp +++ b/servers/visual/visual_server_viewport.cpp @@ -517,6 +517,22 @@ void VisualServerViewport::viewport_set_shadow_atlas_quadrant_subdivision(RID p_ } +void VisualServerViewport::viewport_set_msaa(RID p_viewport,VS::ViewportMSAA p_msaa) { + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + VSG::storage->render_target_set_msaa(viewport->render_target,p_msaa); +} + +void VisualServerViewport::viewport_set_hdr(RID p_viewport,bool p_enabled) { + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + VSG::storage->render_target_set_flag(viewport->render_target,RasterizerStorage::RENDER_TARGET_HDR,p_enabled); + +} bool VisualServerViewport::free(RID p_rid) { diff --git a/servers/visual/visual_server_viewport.h b/servers/visual/visual_server_viewport.h index 2eb0ea46790..3b14ee2b1cb 100644 --- a/servers/visual/visual_server_viewport.h +++ b/servers/visual/visual_server_viewport.h @@ -137,6 +137,9 @@ public: void viewport_set_shadow_atlas_size(RID p_viewport,int p_size); void viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport,int p_quadrant,int p_subdiv); + void viewport_set_msaa(RID p_viewport,VS::ViewportMSAA p_msaa); + void viewport_set_hdr(RID p_viewport,bool p_enabled); + void draw_viewports(); bool free(RID p_rid); diff --git a/servers/visual_server.h b/servers/visual_server.h index f4848ff34e5..4f7d0e2ac67 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -152,7 +152,7 @@ public: SHADER_SPATIAL, SHADER_CANVAS_ITEM, - SHADER_LIGHT, + SHADER_PARTICLES, SHADER_MAX }; @@ -593,6 +593,16 @@ public: virtual void viewport_set_shadow_atlas_size(RID p_viewport,int p_size)=0; virtual void viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport,int p_quadrant,int p_subdiv)=0; + enum ViewportMSAA { + VIEWPORT_MSAA_DISABLED, + VIEWPORT_MSAA_2X, + VIEWPORT_MSAA_4X, + VIEWPORT_MSAA_8X, + VIEWPORT_MSAA_16X, + }; + + virtual void viewport_set_msaa(RID p_viewport,ViewportMSAA p_msaa)=0; + virtual void viewport_set_hdr(RID p_viewport,bool p_enabled)=0; /* ENVIRONMENT API */ diff --git a/tools/editor/plugins/spatial_editor_plugin.cpp b/tools/editor/plugins/spatial_editor_plugin.cpp index e5e8668df63..282a2748da6 100644 --- a/tools/editor/plugins/spatial_editor_plugin.cpp +++ b/tools/editor/plugins/spatial_editor_plugin.cpp @@ -1823,6 +1823,7 @@ void SpatialEditorViewport::_notification(int p_what) { surface->update(); } + //update shadow atlas if changed int shadowmap_size = Globals::get_singleton()->get("rendering/shadow_atlas/size"); int atlas_q0 = Globals::get_singleton()->get("rendering/shadow_atlas/quadrant_0_subdiv"); @@ -1830,12 +1831,22 @@ void SpatialEditorViewport::_notification(int p_what) { int atlas_q2 = Globals::get_singleton()->get("rendering/shadow_atlas/quadrant_2_subdiv"); int atlas_q3 = Globals::get_singleton()->get("rendering/shadow_atlas/quadrant_3_subdiv"); + viewport->set_shadow_atlas_size(shadowmap_size); viewport->set_shadow_atlas_quadrant_subdiv(0,Viewport::ShadowAtlasQuadrantSubdiv(atlas_q0)); viewport->set_shadow_atlas_quadrant_subdiv(1,Viewport::ShadowAtlasQuadrantSubdiv(atlas_q1)); viewport->set_shadow_atlas_quadrant_subdiv(2,Viewport::ShadowAtlasQuadrantSubdiv(atlas_q2)); viewport->set_shadow_atlas_quadrant_subdiv(3,Viewport::ShadowAtlasQuadrantSubdiv(atlas_q3)); + //update msaa if changed + + int msaa_mode = Globals::get_singleton()->get("rendering/antialias/msaa"); + viewport->set_msaa(Viewport::MSAA(msaa_mode)); + + bool hdr = Globals::get_singleton()->get("rendering/dynamic_range/hdr"); + viewport->set_hdr(hdr); + + } if (p_what==NOTIFICATION_ENTER_TREE) {