فهرست منبع

WIP particle system
Ability to enable and change MSAA settings
Ability to change VCT quality
Ability to enable/disable HDR rendering

Juan Linietsky 8 سال پیش
والد
کامیت
c2a217c350

+ 15 - 1
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){

+ 89 - 35
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);
 
 
-	if (env->ssr_enabled) {
 		//blur diffuse into effect mipmaps using separatable convolution
 		//storage->shaders.copy.set_conditional(CopyShaderGLES3::GAUSSIAN_HORIZONTAL,true);
 		for(int i=0;i<storage->frame.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<GLenum> 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(){

+ 0 - 1
drivers/gles3/rasterizer_scene_gles3.h

@@ -53,7 +53,6 @@ public:
 	Vector<RasterizerStorageGLES3::RenderTarget::Exposure> exposure_shrink;
 	int exposure_shrink_size;
 
-
 	struct State {
 
 

+ 254 - 64
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;i<floats;i++) {
+		data[i]=0;
+	}
+
+
+	glBindBuffer(GL_ARRAY_BUFFER,particles->particle_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;i<tc;i++) {
+
+				glActiveTexture(GL_TEXTURE0+i);
+
+				GLenum target;
+				GLuint tex;
+
+				RasterizerStorageGLES3::Texture *t = texture_owner.getornull( textures[i] );
+
+				if (!t) {
+					//check hints
+					target=GL_TEXTURE_2D;
+
+					switch(texture_hints[i]) {
+						case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO:
+						case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: {
+							tex=resources.black_tex;
+						} break;
+						case ShaderLanguage::ShaderNode::Uniform::HINT_ANISO: {
+							tex=resources.aniso_tex;
+						} break;
+						case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: {
+							tex=resources.normal_tex;
+						} break;
+						default: {
+							tex=resources.white_tex;
+						} break;
+					}
+
+
+				} else {
+
+					target=t->target;
+					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);
 
-		//alpha fbo
-		glGenFramebuffers(1, &rt->buffers.alpha_fbo);
-		glBindFramebuffer(GL_FRAMEBUFFER, rt->buffers.alpha_fbo);
+		// effect resolver
 
-		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
-				       GL_TEXTURE_2D, rt->depth, 0);
+		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);
 
-		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->buffers.diffuse, 0);
 
-		status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+		if (status != GL_FRAMEBUFFER_COMPLETE) {
+			printf("err status: %x\n",status);
+			_render_target_clear(rt);
+			ERR_FAIL_COND( status != GL_FRAMEBUFFER_COMPLETE );
+		}
+
 		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;
 }
 

+ 49 - 4
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<Particles> 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<Particles>::List particle_update_list;
+
+	void update_particles();
+
+
 	mutable RID_Owner<Particles> 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;
 

+ 18 - 1
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<String> func_list;
 
 	ShaderLanguage::get_builtin_funcs(&func_list);

+ 87 - 34
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
 
-	}
+		{
+			VERTEX_SHADER_CODE
+		}
 
+#if !defined(DISABLE_FORCE)
 
-	if (apply_forces) {
+		{
 
-		vec3 force = gravity;
-		for(int i=0;i<attractor_count;i++) {
+			vec3 force = gravity;
+			for(int i=0;i<attractor_count;i++) {
 
-			vec3 rel_vec = out_pos_lifetime.xyz - attractors[i].pos;
-			float dist = rel_vec.length();
-			if (attractors[i].radius < dist)
-				continue;
-			if (attractors[i].eat_radius>0 &&  attractors[i].eat_radius > dist) {
-				rot_active.a=0.0;
-			}
+				vec3 rel_vec = out_pos_lifetime.xyz - attractors[i].pos;
+				float dist = rel_vec.length();
+				if (attractors[i].radius < dist)
+					continue;
+				if (attractors[i].eat_radius>0 &&  attractors[i].eat_radius > dist) {
+					out_velocity_active.a=0.0;
+				}
 
-			rel_vec = normalize(rel_vec);
+				rel_vec = normalize(rel_vec);
 
-			float attenuation = pow(dist / attractors[i].radius,attractors[i].attenuation);
+				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;
+				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
 
-		out_velocity_seed.xyz += force * delta;
-	}
+#if !defined(DISABLE_VELOCITY)
 
-	if (apply_velocity) {
+		{
 
-		out_pos_lifetime.xyz += out_velocity_seed.xyz * delta;
+			out_pos_lifetime.xyz += out_velocity_seed.xyz * delta;
+		}
+#endif
 	}
 
+	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];
+
+
 }
 
 [fragment]
 
+//any code here is never executed, stuff is filled just so it works
 
-void main() {
+FRAGMENT_SHADER_GLOBALS
+
+#if defined(USE_MATERIAL)
 
+layout(std140) uniform UniformData {
 
+MATERIAL_UNIFORMS
+
+};
+
+#endif
+
+void main() {
+
+	{
+		FRAGMENT_SHADER_CODE
+	}
 }

+ 3 - 3
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

+ 2 - 2
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:

+ 5 - 0
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);
 

+ 47 - 1
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;
 
 
 }

+ 20 - 2
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

+ 1 - 0
scene/register_scene_types.cpp

@@ -557,6 +557,7 @@ void register_scene_types() {
 	ObjectTypeDB::register_type<RoomBounds>();
 //	ObjectTypeDB::register_type<MaterialShaderGraph>();
 	ObjectTypeDB::register_type<SpatialShader>();
+	ObjectTypeDB::register_type<ParticlesShader>();
 	ObjectTypeDB::add_compatibility_type("Shader","MaterialShader");
 	ObjectTypeDB::add_compatibility_type("ParticleSystemMaterial","FixedSpatialMaterial");
 	ObjectTypeDB::add_compatibility_type("UnshadedMaterial","FixedSpatialMaterial");

+ 1 - 1
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 );
 
 }
 

+ 9 - 1
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

+ 2 - 0
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 */

+ 19 - 1
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");
 
 
 

+ 3 - 0
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 */
 

+ 16 - 0
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) {
 

+ 3 - 0
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);

+ 11 - 1
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 */
 

+ 11 - 0
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) {