Bladeren bron

More 3D Improvements
-=-=-=-=-=-=-=-=-=-=

-Sprite3D and AnimatedSprite3D support.
-Opaque pre-pass works, is compatible with shadows
-Improved shadow map rendering (can differentiate between plain opaque and opaque with shaders/discard/etc)
-Added option to use alpha discard in FixedMaterial
-Improved Glow FX, many more options (three modes, Additive, Screen and SoftLight), strength and scale
-Ability for Background (image or cubemap) to send to glow buffer
-Dumb Deploy of clients now actually works in Android
-Many Many rendering fixes, 3D is much more usable now.

Juan Linietsky 11 jaren geleden
bovenliggende
commit
6f0b4678e2
50 gewijzigde bestanden met toevoegingen van 2261 en 93 verwijderingen
  1. BIN
      demos/3d/fixed_materials/fixed_materials.scn
  2. 12 3
      demos/3d/platformer/stage.xml
  3. BIN
      demos/3d/platformer/tiles.res
  4. 81 0
      drivers/gles1/rasterizer_gles1.cpp
  5. 28 0
      drivers/gles1/rasterizer_gles1.h
  6. 352 13
      drivers/gles2/rasterizer_gles2.cpp
  7. 65 2
      drivers/gles2/rasterizer_gles2.h
  8. 7 0
      drivers/gles2/shader_compiler_gles2.cpp
  9. 1 0
      drivers/gles2/shader_compiler_gles2.h
  10. 6 2
      drivers/gles2/shader_gles2.cpp
  11. 39 17
      drivers/gles2/shaders/copy.glsl
  12. 16 4
      drivers/gles2/shaders/material.glsl
  13. 48 26
      platform/android/export/export.cpp
  14. 5 0
      platform/android/java_bind.cpp
  15. 10 0
      platform/android/java_bind.h
  16. 4 4
      platform/bb10/export/export.cpp
  17. 4 4
      platform/javascript/export/export.cpp
  18. 4 4
      platform/osx/export/export.cpp
  19. 102 0
      scene/3d/immediate_geometry.cpp
  20. 41 0
      scene/3d/immediate_geometry.h
  21. 772 0
      scene/3d/sprite_3d.cpp
  22. 191 0
      scene/3d/sprite_3d.h
  23. 5 0
      scene/register_scene_types.cpp
  24. 15 0
      scene/resources/environment.cpp
  25. 10 0
      scene/resources/environment.h
  26. 7 2
      scene/resources/material.cpp
  27. 2 0
      scene/resources/material.h
  28. 43 0
      scene/resources/texture.cpp
  29. 2 0
      scene/resources/texture.h
  30. 2 0
      scene/scene_string_names.cpp
  31. 4 0
      scene/scene_string_names.h
  32. 6 0
      servers/visual/rasterizer.cpp
  33. 22 0
      servers/visual/rasterizer.h
  34. 80 0
      servers/visual/rasterizer_dummy.cpp
  35. 29 0
      servers/visual/rasterizer_dummy.h
  36. 1 1
      servers/visual/shader_language.cpp
  37. 77 0
      servers/visual/visual_server_raster.cpp
  38. 15 0
      servers/visual/visual_server_raster.h
  39. 16 0
      servers/visual/visual_server_wrap_mt.h
  40. 49 0
      servers/visual_server.cpp
  41. 41 2
      servers/visual_server.h
  42. 1 1
      tools/editor/editor_import_export.cpp
  43. 3 3
      tools/editor/editor_import_export.h
  44. 4 3
      tools/editor/editor_node.cpp
  45. 13 1
      tools/editor/editor_run_native.cpp
  46. 4 0
      tools/editor/editor_run_native.h
  47. 21 0
      tools/editor/fileserver/editor_file_server.cpp
  48. BIN
      tools/editor/icons/icon_animated_sprite_3d.png
  49. BIN
      tools/editor/icons/icon_sprite_3d.png
  50. 1 1
      tools/editor/project_export.cpp

BIN
demos/3d/fixed_materials/fixed_materials.scn


+ 12 - 3
demos/3d/platformer/stage.xml

@@ -6,14 +6,19 @@
 	<ext_resource path="res://player.xml" type="PackedScene"></ext_resource>
 	<ext_resource path="res://enemy.scn" type="PackedScene"></ext_resource>
 	<resource type="Environment" path="local://1">
+		<bool name="fxaa/enabled"> False </bool>
 		<int name="background/mode"> 4 </int>
 		<color name="background/color"> 0, 0, 0, 1 </color>
 		<nil name="background/texture">  </nil>
 		<resource name="background/cubemap" resource_type="CubeMap" path="res://sb.cube">  </resource>
 		<real name="background/energy"> 1 </real>
 		<real name="background/scale"> 1 </real>
+		<real name="background/glow"> 0.6 </real>
 		<bool name="glow/enabled"> True </bool>
 		<int name="glow/blur_passes"> 2 </int>
+		<real name="glow/blur_scale"> 1.3 </real>
+		<real name="glow/blur_strength"> 1.2 </real>
+		<int name="glow/blur_blend_mode"> 1 </int>
 		<real name="glow/bloom"> 0 </real>
 		<real name="glow/bloom_treshold"> 0.5 </real>
 		<bool name="dof_blur/enabled"> False </bool>
@@ -150,8 +155,12 @@
 							<bool> False </bool>
 							<string> "zoom" </string>
 							<real> 1 </real>
+							<string> "use_snap" </string>
+							<bool> False </bool>
 							<string> "ofs" </string>
 							<vector2> 1, 1 </vector2>
+							<string> "snap" </string>
+							<int> 10 </int>
 						</dictionary>
 						<string> "3D" </string>
 						<dictionary  shared="false">
@@ -165,15 +174,15 @@
 									<string> "distance" </string>
 									<real> 6.622579 </real>
 									<string> "x_rot" </string>
-									<real> 1.570796 </real>
+									<real> 0.358295 </real>
 									<string> "y_rot" </string>
-									<real> 0 </real>
+									<real> 0.45 </real>
 									<string> "use_orthogonal" </string>
 									<bool> False </bool>
 									<string> "use_environment" </string>
 									<bool> False </bool>
 									<string> "pos" </string>
-									<vector3> 8.30511, 0.427271, 15.7846 </vector3>
+									<vector3> 9.41795, 2.98588, 13.6496 </vector3>
 								</dictionary>
 								<dictionary  shared="false">
 									<string> "distance" </string>

BIN
demos/3d/platformer/tiles.res


+ 81 - 0
drivers/gles1/rasterizer_gles1.cpp

@@ -2165,6 +2165,74 @@ int RasterizerGLES1::multimesh_get_visible_instances(RID p_multimesh) const {
 
 }
 
+/* IMMEDIATE API */
+
+
+RID RasterizerGLES1::immediate_create() {
+
+	Immediate *im = memnew( Immediate );
+	return immediate_owner.make_rid(im);
+
+}
+
+void RasterizerGLES1::immediate_begin(RID p_immediate, VS::PrimitiveType p_rimitive, RID p_texture){
+
+
+}
+void RasterizerGLES1::immediate_vertex(RID p_immediate,const Vector3& p_vertex){
+
+
+}
+void RasterizerGLES1::immediate_normal(RID p_immediate,const Vector3& p_normal){
+
+
+}
+void RasterizerGLES1::immediate_tangent(RID p_immediate,const Plane& p_tangent){
+
+
+}
+void RasterizerGLES1::immediate_color(RID p_immediate,const Color& p_color){
+
+
+}
+void RasterizerGLES1::immediate_uv(RID p_immediate,const Vector2& tex_uv){
+
+
+}
+void RasterizerGLES1::immediate_uv2(RID p_immediate,const Vector2& tex_uv){
+
+
+}
+
+void RasterizerGLES1::immediate_end(RID p_immediate){
+
+
+}
+void RasterizerGLES1::immediate_clear(RID p_immediate) {
+
+
+}
+
+AABB RasterizerGLES1::immediate_get_aabb(RID p_immediate) const {
+
+	return AABB(Vector3(-1,-1,-1),Vector3(2,2,2));
+}
+
+void RasterizerGLES1::immediate_set_material(RID p_immediate,RID p_material) {
+
+	Immediate *im = immediate_owner.get(p_immediate);
+	ERR_FAIL_COND(!im);
+	im->material=p_material;
+}
+
+RID RasterizerGLES1::immediate_get_material(RID p_immediate) const {
+
+	const Immediate *im = immediate_owner.get(p_immediate);
+	ERR_FAIL_COND_V(!im,RID());
+	return im->material;
+
+}
+
 
 /* PARTICLES API */
 
@@ -5327,6 +5395,12 @@ bool RasterizerGLES1::is_mesh(const RID& p_rid) const {
 
 	return mesh_owner.owns(p_rid);
 }
+
+bool RasterizerGLES1::is_immediate(const RID& p_rid) const {
+
+	return immediate_owner.owns(p_rid);
+}
+
 bool RasterizerGLES1::is_multimesh(const RID& p_rid) const {
 
 	return multimesh_owner.owns(p_rid);
@@ -5447,6 +5521,13 @@ void RasterizerGLES1::free(const RID& p_rid) {
 
 		particles_owner.free(p_rid);
 		memdelete(particles);
+	} else if (immediate_owner.owns(p_rid)) {
+
+		Immediate *immediate = immediate_owner.get(p_rid);
+		ERR_FAIL_COND(!immediate);
+
+		immediate_owner.free(p_rid);
+		memdelete(immediate);
 	} else if (particles_instance_owner.owns(p_rid)) {
 
 		ParticlesInstance *particles_isntance = particles_instance_owner.get(p_rid);

+ 28 - 0
drivers/gles1/rasterizer_gles1.h

@@ -371,6 +371,15 @@ class RasterizerGLES1 : public Rasterizer {
 
 	mutable RID_Owner<MultiMesh> multimesh_owner;
 
+
+	struct Immediate {
+
+		RID material;
+		int empty;
+	};
+
+	mutable RID_Owner<Immediate> immediate_owner;
+
 	struct Particles : public Geometry {
 
 		ParticleSystemSW data; // software particle system
@@ -963,6 +972,23 @@ public:
 	virtual void multimesh_set_visible_instances(RID p_multimesh,int p_visible);
 	virtual int multimesh_get_visible_instances(RID p_multimesh) const;
 
+	/* IMMEDIATE API */
+
+	virtual RID immediate_create();
+	virtual void immediate_begin(RID p_immediate,VS::PrimitiveType p_rimitive,RID p_texture=RID());
+	virtual void immediate_vertex(RID p_immediate,const Vector3& p_vertex);
+	virtual void immediate_normal(RID p_immediate,const Vector3& p_normal);
+	virtual void immediate_tangent(RID p_immediate,const Plane& p_tangent);
+	virtual void immediate_color(RID p_immediate,const Color& p_color);
+	virtual void immediate_uv(RID p_immediate,const Vector2& tex_uv);
+	virtual void immediate_uv2(RID p_immediate,const Vector2& tex_uv);
+	virtual void immediate_end(RID p_immediate);
+	virtual void immediate_clear(RID p_immediate);
+	virtual AABB immediate_get_aabb(RID p_immediate) const;
+	virtual void immediate_set_material(RID p_immediate,RID p_material);
+	virtual RID immediate_get_material(RID p_immediate) const;
+
+
 	/* PARTICLES API */
 
 	virtual RID particles_create();
@@ -1120,6 +1146,7 @@ public:
 
 	virtual void add_mesh( const RID& p_mesh, const InstanceData *p_data);
 	virtual void add_multimesh( const RID& p_multimesh, const InstanceData *p_data);
+	virtual void add_immediate( const RID& p_immediate, const InstanceData *p_data) {}
 	virtual void add_particles( const RID& p_particle_instance, const InstanceData *p_data);
 
 	virtual void end_scene();
@@ -1176,6 +1203,7 @@ public:
 	virtual bool is_material(const RID& p_rid) const;
 	virtual bool is_mesh(const RID& p_rid) const;
 	virtual bool is_multimesh(const RID& p_rid) const;
+	virtual bool is_immediate(const RID& p_rid) const;
 	virtual bool is_particles(const RID &p_beam) const;
 
 	virtual bool is_light(const RID& p_rid) const;

+ 352 - 13
drivers/gles2/rasterizer_gles2.cpp

@@ -2489,6 +2489,156 @@ int RasterizerGLES2::multimesh_get_visible_instances(RID p_multimesh) const {
 
 }
 
+/* IMMEDIATE API */
+
+
+RID RasterizerGLES2::immediate_create() {
+
+	Immediate *im = memnew( Immediate );
+	return immediate_owner.make_rid(im);
+
+}
+
+void RasterizerGLES2::immediate_begin(RID p_immediate, VS::PrimitiveType p_rimitive, RID p_texture){
+
+	Immediate *im = immediate_owner.get(p_immediate);
+	ERR_FAIL_COND(!im);
+	ERR_FAIL_COND(im->building);
+
+	Immediate::Chunk ic;
+	ic.texture=p_texture;
+	ic.primitive=p_rimitive;
+	im->chunks.push_back(ic);
+	im->mask=0;
+	im->building=true;
+
+
+}
+void RasterizerGLES2::immediate_vertex(RID p_immediate,const Vector3& p_vertex){
+
+	Immediate *im = immediate_owner.get(p_immediate);
+	ERR_FAIL_COND(!im);
+	ERR_FAIL_COND(!im->building);
+
+	Immediate::Chunk *c = &im->chunks.back()->get();
+
+
+	if (c->vertices.empty() && im->chunks.size()==1) {
+
+		im->aabb.pos=p_vertex;
+		im->aabb.size=Vector3();
+	} else {
+		im->aabb.expand_to(p_vertex);
+	}
+
+	if (im->mask&VS::ARRAY_FORMAT_NORMAL)
+		c->normals.push_back(chunk_normal);
+	if (im->mask&VS::ARRAY_FORMAT_TANGENT)
+		c->tangents.push_back(chunk_tangent);
+	if (im->mask&VS::ARRAY_FORMAT_COLOR)
+		c->colors.push_back(chunk_color);
+	if (im->mask&VS::ARRAY_FORMAT_TEX_UV)
+		c->uvs.push_back(chunk_uv);
+	if (im->mask&VS::ARRAY_FORMAT_TEX_UV2)
+		c->uvs2.push_back(chunk_uv2);
+	im->mask|=VS::ARRAY_FORMAT_VERTEX;
+	c->vertices.push_back(p_vertex);
+
+}
+
+
+void RasterizerGLES2::immediate_normal(RID p_immediate,const Vector3& p_normal){
+
+	Immediate *im = immediate_owner.get(p_immediate);
+	ERR_FAIL_COND(!im);
+	ERR_FAIL_COND(!im->building);
+
+	im->mask|=VS::ARRAY_FORMAT_NORMAL;
+	chunk_normal=p_normal;
+
+}
+void RasterizerGLES2::immediate_tangent(RID p_immediate,const Plane& p_tangent){
+
+	Immediate *im = immediate_owner.get(p_immediate);
+	ERR_FAIL_COND(!im);
+	ERR_FAIL_COND(!im->building);
+
+	im->mask|=VS::ARRAY_FORMAT_TANGENT;
+	chunk_tangent=p_tangent;
+
+}
+void RasterizerGLES2::immediate_color(RID p_immediate,const Color& p_color){
+
+	Immediate *im = immediate_owner.get(p_immediate);
+	ERR_FAIL_COND(!im);
+	ERR_FAIL_COND(!im->building);
+
+	im->mask|=VS::ARRAY_FORMAT_COLOR;
+	chunk_color=p_color;
+
+}
+void RasterizerGLES2::immediate_uv(RID p_immediate,const Vector2& tex_uv){
+
+	Immediate *im = immediate_owner.get(p_immediate);
+	ERR_FAIL_COND(!im);
+	ERR_FAIL_COND(!im->building);
+
+	im->mask|=VS::ARRAY_FORMAT_TEX_UV;
+	chunk_uv=tex_uv;
+
+}
+void RasterizerGLES2::immediate_uv2(RID p_immediate,const Vector2& tex_uv){
+
+	Immediate *im = immediate_owner.get(p_immediate);
+	ERR_FAIL_COND(!im);
+	ERR_FAIL_COND(!im->building);
+
+	im->mask|=VS::ARRAY_FORMAT_TEX_UV2;
+	chunk_uv2=tex_uv;
+
+}
+
+void RasterizerGLES2::immediate_end(RID p_immediate){
+
+	Immediate *im = immediate_owner.get(p_immediate);
+	ERR_FAIL_COND(!im);
+	ERR_FAIL_COND(!im->building);
+
+	im->building=false;
+
+}
+void RasterizerGLES2::immediate_clear(RID p_immediate) {
+
+	Immediate *im = immediate_owner.get(p_immediate);
+	ERR_FAIL_COND(!im);
+	ERR_FAIL_COND(im->building);
+
+	im->chunks.clear();
+}
+
+AABB RasterizerGLES2::immediate_get_aabb(RID p_immediate) const {
+
+	Immediate *im = immediate_owner.get(p_immediate);
+	ERR_FAIL_COND_V(!im,AABB());
+	return im->aabb;
+}
+
+void RasterizerGLES2::immediate_set_material(RID p_immediate,RID p_material) {
+
+	Immediate *im = immediate_owner.get(p_immediate);
+	ERR_FAIL_COND(!im);
+	im->material=p_material;
+
+}
+
+RID RasterizerGLES2::immediate_get_material(RID p_immediate) const {
+
+	const Immediate *im = immediate_owner.get(p_immediate);
+	ERR_FAIL_COND_V(!im,RID());
+	return im->material;
+
+}
+
 
 /* PARTICLES API */
 
@@ -3793,9 +3943,16 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const {
 
 	//print_line("UCF: "+itos(p_shader->uniforms.size()));
 
+	int first_tex_index=0xFFFFF;
+	p_shader->first_texture=StringName();
+
 	for(Map<StringName,ShaderLanguage::Uniform>::Element *E=p_shader->uniforms.front();E;E=E->next()) {
 
 		uniform_names.push_back("_"+String(E->key()));
+		if (E->get().type==ShaderLanguage::TYPE_TEXTURE && E->get().order<first_tex_index) {
+			p_shader->first_texture=E->key();
+			first_tex_index=E->get().order;
+		}
 	}
 
 	if (p_shader->mode==VS::SHADER_MATERIAL) {
@@ -3819,6 +3976,9 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const {
 		if (flags.uses_screen_uv) {
 			enablers.push_back("#define ENABLE_SCREEN_UV\n");
 		}
+		if (flags.uses_discard) {
+			enablers.push_back("#define ENABLE_DISCARD\n");
+		}
 
 		material_shader.set_custom_shader_code(p_shader->custom_code_id,vertex_code, vertex_globals,fragment_code, fragment_globals,uniform_names,enablers);
 	} else {
@@ -3827,6 +3987,8 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const {
 
 	p_shader->valid=true;
 	p_shader->has_alpha=flags.uses_alpha || flags.uses_texscreen;
+	p_shader->writes_vertex=flags.vertex_code_writes_vertex;
+	p_shader->uses_discard=flags.uses_discard;
 	p_shader->has_texscreen=flags.uses_texscreen;
 	p_shader->has_screen_uv=flags.uses_screen_uv;
 	p_shader->can_zpass=!flags.uses_discard && !flags.vertex_code_writes_vertex;
@@ -3887,16 +4049,19 @@ void RasterizerGLES2::_add_geometry( const Geometry* p_geometry, const InstanceD
 
 	RenderList *render_list=NULL;
 
-	bool has_alpha = m->blend_mode!=VS::MATERIAL_BLEND_MODE_MIX || (m->shader_cache && m->shader_cache->has_alpha) || m->flags[VS::MATERIAL_FLAG_ONTOP];
+	bool has_base_alpha=(m->shader_cache && m->shader_cache->has_alpha);
+	bool has_blend_alpha=m->blend_mode!=VS::MATERIAL_BLEND_MODE_MIX || m->flags[VS::MATERIAL_FLAG_ONTOP];
+	bool has_alpha = has_base_alpha || has_blend_alpha;
 
 
 	if (shadow) {
 
-		if (has_alpha)
+		if (has_blend_alpha || (has_base_alpha && !m->hints[VS::MATERIAL_HINT_OPAQUE_PRE_PASS]))
 			return; //bye
 
-		if (true) {
-			m = shadow_mat_ptr; //for now do this always
+		if (m->shader_cache && !m->shader_cache->writes_vertex && !m->shader_cache->uses_discard && !m->hints[VS::MATERIAL_HINT_OPAQUE_PRE_PASS]) {
+			//shader does not use discard and does not write a vertex position, use generic material
+			m = shadow_mat_ptr;
 			if (m->last_pass!=frame) {
 
 				if (m->shader.is_valid()) {
@@ -3939,6 +4104,9 @@ void RasterizerGLES2::_add_geometry( const Geometry* p_geometry, const InstanceD
 
 	RenderList::Element *e = render_list->add_element();
 
+	if (!e)
+		return;
+
 	e->geometry=p_geometry;
 	e->geometry_cmp=p_geometry_cmp;
 	e->material=m;
@@ -3974,6 +4142,18 @@ void RasterizerGLES2::_add_geometry( const Geometry* p_geometry, const InstanceD
 	e->light_type=0xFF; // no lights!
 	e->light=0xFFFF;
 
+	if (!shadow && !has_blend_alpha && has_alpha && m->hints[VS::MATERIAL_HINT_OPAQUE_PRE_PASS]) {
+
+		//if nothing exists, add this element as opaque too
+		RenderList::Element *oe = opaque_render_list.add_element();
+
+		if (!oe)
+			return;
+
+		memcpy(oe,e,sizeof(RenderList::Element));
+		oe->additive_ptr=&oe->additive;
+	}
+
 	if (shadow || m->flags[VS::MATERIAL_FLAG_UNSHADED]) {
 
 		e->light_type=0x7F; //unshaded is zero
@@ -4098,6 +4278,17 @@ void RasterizerGLES2::add_multimesh( const RID& p_multimesh, const InstanceData
 
 }
 
+void RasterizerGLES2::add_immediate( const RID& p_immediate, const InstanceData *p_data) {
+
+
+	Immediate *immediate = immediate_owner.get(p_immediate);
+	ERR_FAIL_COND(!immediate);
+
+	_add_geometry(immediate,p_data,immediate,NULL);
+
+}
+
+
 void RasterizerGLES2::add_particles( const RID& p_particle_instance, const InstanceData *p_data){
 
 	//print_line("adding particles");
@@ -4169,7 +4360,7 @@ _FORCE_INLINE_ void RasterizerGLES2::_update_material_shader_params(Material *p_
 
 }
 
-bool RasterizerGLES2::_setup_material(const Geometry *p_geometry,const Material *p_material,bool p_no_const_light) {
+bool RasterizerGLES2::_setup_material(const Geometry *p_geometry,const Material *p_material,bool p_no_const_light,bool p_opaque_pass) {
 
 	if (p_material->flags[VS::MATERIAL_FLAG_DOUBLE_SIDED]) {
 		glDisable(GL_CULL_FACE);
@@ -4196,11 +4387,19 @@ bool RasterizerGLES2::_setup_material(const Geometry *p_geometry,const Material
 	material_shader.set_conditional(MaterialShaderGLES2::USE_SHADOW_PCF_HQ,shadow_filter>SHADOW_FILTER_PCF5);
 	//material_shader.set_conditional(MaterialShaderGLES2::USE_SHADOW_ESM,true);
 
+	if (p_opaque_pass && p_material->hints[VS::MATERIAL_HINT_OPAQUE_PRE_PASS] && p_material->shader_cache && p_material->shader_cache->has_alpha) {
+
+		material_shader.set_conditional(MaterialShaderGLES2::ENABLE_CLIP_ALPHA,true);
+	} else {
+		material_shader.set_conditional(MaterialShaderGLES2::ENABLE_CLIP_ALPHA,false);
+
+	}
+
 
 	if (!shadow) {
 
 		bool depth_test=!p_material->flags[VS::MATERIAL_FLAG_ONTOP];
-		bool depth_write=!p_material->hints[VS::MATERIAL_HINT_NO_DEPTH_DRAW];
+		bool depth_write=!p_material->hints[VS::MATERIAL_HINT_NO_DEPTH_DRAW] && (p_opaque_pass || !p_material->hints[VS::MATERIAL_HINT_NO_DEPTH_DRAW_FOR_ALPHA]);
 
 		if (current_depth_mask!=depth_write) {
 			current_depth_mask=depth_write;
@@ -4276,6 +4475,10 @@ bool RasterizerGLES2::_setup_material(const Geometry *p_geometry,const Material
 				if (t) {
 					if (t->render_target)
 						t->render_target->last_pass=frame;
+					if (E->key()==p_material->shader_cache->first_texture) {
+						tc0_idx=texcoord;
+						tc0_id_cache=t->tex_id;
+					}
 					glBindTexture(t->target,t->tex_id);
 				} else
 					glBindTexture(GL_TEXTURE_2D,white_tex); //no texture
@@ -5019,6 +5222,109 @@ void RasterizerGLES2::_render(const Geometry *p_geometry,const Material *p_mater
 				 };
 			}
 		 } break;
+		case Geometry::GEOMETRY_IMMEDIATE: {
+
+			bool restore_tex=false;
+			const Immediate *im = static_cast<const Immediate*>( p_geometry );
+			if (im->building) {
+				return;
+			}
+
+			glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+			for(const List<Immediate::Chunk>::Element *E=im->chunks.front();E;E=E->next()) {
+
+				const Immediate::Chunk &c=E->get();
+				if (c.vertices.empty()) {
+					continue;
+				}
+				for(int i=0;i<c.vertices.size();i++)
+
+				if (c.texture.is_valid() && texture_owner.owns(c.texture)) {
+
+					const Texture *t = texture_owner.get(c.texture);
+					glActiveTexture(GL_TEXTURE0+tc0_idx);
+					glBindTexture(t->target,t->tex_id);
+					restore_tex=true;
+
+
+				} else if (restore_tex) {
+
+					glActiveTexture(GL_TEXTURE0+tc0_idx);
+					glBindTexture(GL_TEXTURE_2D,tc0_id_cache);
+					restore_tex=false;
+				}
+
+				if (!c.normals.empty()) {
+
+					glEnableVertexAttribArray(VS::ARRAY_NORMAL);
+					glVertexAttribPointer(VS::ARRAY_NORMAL, 3, GL_FLOAT, false,sizeof(Vector3),c.normals.ptr());
+
+				} else {
+
+					glDisableVertexAttribArray(VS::ARRAY_NORMAL);
+				}
+
+				if (!c.tangents.empty()) {
+
+					glEnableVertexAttribArray(VS::ARRAY_TANGENT);
+					glVertexAttribPointer(VS::ARRAY_TANGENT, 4, GL_FLOAT, false,sizeof(Plane),c.tangents.ptr());
+
+				} else {
+
+					glDisableVertexAttribArray(VS::ARRAY_TANGENT);
+				}
+
+				if (!c.colors.empty()) {
+
+					glEnableVertexAttribArray(VS::ARRAY_COLOR);
+					glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, false,sizeof(Color),c.colors.ptr());
+
+				} else {
+
+					glDisableVertexAttribArray(VS::ARRAY_COLOR);
+					_set_color_attrib(Color(1, 1, 1,1));
+				}
+
+
+				if (!c.uvs.empty()) {
+
+					glEnableVertexAttribArray(VS::ARRAY_TEX_UV);
+					glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, false,sizeof(Vector2),c.uvs.ptr());
+
+				} else {
+
+					glDisableVertexAttribArray(VS::ARRAY_TEX_UV);
+				}
+
+				if (!c.uvs2.empty()) {
+
+					glEnableVertexAttribArray(VS::ARRAY_TEX_UV2);
+					glVertexAttribPointer(VS::ARRAY_TEX_UV2, 2, GL_FLOAT, false,sizeof(Vector2),c.uvs2.ptr());
+
+				} else {
+
+					glDisableVertexAttribArray(VS::ARRAY_TEX_UV2);
+				}
+
+
+				glEnableVertexAttribArray(VS::ARRAY_VERTEX);
+				glVertexAttribPointer(VS::ARRAY_VERTEX, 3, GL_FLOAT, false,sizeof(Vector3),c.vertices.ptr());
+				glDrawArrays(gl_primitive[c.primitive],0,c.vertices.size());
+
+
+			}
+
+
+			if (restore_tex) {
+
+				glActiveTexture(GL_TEXTURE0+tc0_idx);
+				glBindTexture(GL_TEXTURE_2D,tc0_id_cache);
+				restore_tex=false;
+			}
+
+
+		} break;
 		case Geometry::GEOMETRY_PARTICLES: {
 
 
@@ -5275,8 +5581,10 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans
 
 				if (desired_blend) {
 					glEnable(GL_BLEND);
+					glColorMask(1,1,1,0);
 				} else {
 					glDisable(GL_BLEND);
+					glColorMask(1,1,1,1);
 				}
 
 				prev_blend=desired_blend;
@@ -5337,7 +5645,7 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans
 
 		if (material!=prev_material || rebind) {
 
-			rebind = _setup_material(e->geometry,material,additive);
+			rebind = _setup_material(e->geometry,material,additive,!p_alpha_pass);
 
 			DEBUG_TEST_ERROR("Setup material");
 			_rinfo.mat_change_count++;
@@ -5530,9 +5838,12 @@ void RasterizerGLES2::_process_glow_bloom() {
 	_copy_screen_quad();
 
 	copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_COPY,false);
-	copy_shader.set_conditional(CopyShaderGLES2::USE_HDR,false);
+	copy_shader.set_conditional(CopyShaderGLES2::USE_HDR,false);	
 	int passes = current_env->fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_PASSES];
 	Vector2 psize(1.0/framebuffer.blur_size,1.0/framebuffer.blur_size);
+	float pscale = current_env->fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_SCALE];
+	float pmag = current_env->fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_STRENGTH];
+
 
 	for(int i=0;i<passes;i++) {
 
@@ -5555,6 +5866,8 @@ void RasterizerGLES2::_process_glow_bloom() {
 		copy_shader.set_conditional(CopyShaderGLES2::BLUR_H_PASS,false);
 		copy_shader.bind();
 		copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SIZE,psize);
+		copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SCALE,pscale);
+		copy_shader.set_uniform(CopyShaderGLES2::BLUR_MAGNITUDE,pmag);
 
 		_draw_gui_primitive(4,dst_pos,NULL,src_uv);
 
@@ -5565,6 +5878,8 @@ void RasterizerGLES2::_process_glow_bloom() {
 		copy_shader.set_conditional(CopyShaderGLES2::BLUR_H_PASS,true);
 		copy_shader.bind();
 		copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SIZE,psize);
+		copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SCALE,pscale);
+		copy_shader.set_uniform(CopyShaderGLES2::BLUR_MAGNITUDE,pmag);
 
 		_draw_gui_primitive(4,dst_pos,NULL,src_uv);
 
@@ -5693,6 +6008,8 @@ void RasterizerGLES2::_draw_tex_bg() {
 		copy_shader.set_conditional(CopyShaderGLES2::USE_RGBE,false);
 	}
 
+	copy_shader.set_conditional(CopyShaderGLES2::USE_CUSTOM_ALPHA,true);
+
 	copy_shader.bind();
 
 	if (current_env->bg_mode==VS::ENV_BG_TEXTURE || current_env->bg_mode==VS::ENV_BG_TEXTURE_RGBE) {
@@ -5705,6 +6022,7 @@ void RasterizerGLES2::_draw_tex_bg() {
 	if (current_env->fx_enabled[VS::ENV_FX_HDR])
 		nrg*=0.25; //go down a quarter for hdr
 	copy_shader.set_uniform(CopyShaderGLES2::ENERGY,nrg);
+	copy_shader.set_uniform(CopyShaderGLES2::CUSTOM_ALPHA,float(current_env->bg_param[VS::ENV_BG_PARAM_GLOW]));
 
 	Vector3 vertices[4]={
 		Vector3(-1,-1,1),
@@ -5774,6 +6092,7 @@ void RasterizerGLES2::_draw_tex_bg() {
 	copy_shader.set_conditional(CopyShaderGLES2::USE_ENERGY,false);
 	copy_shader.set_conditional(CopyShaderGLES2::USE_RGBE,false);
 	copy_shader.set_conditional(CopyShaderGLES2::USE_CUBEMAP,false);
+	copy_shader.set_conditional(CopyShaderGLES2::USE_CUSTOM_ALPHA,false);
 }
 
 void RasterizerGLES2::end_scene() {
@@ -5854,7 +6173,7 @@ void RasterizerGLES2::end_scene() {
 					bgcolor = current_env->bg_param[VS::ENV_BG_PARAM_COLOR];
 				else
 					bgcolor = Globals::get_singleton()->get("render/default_clear_color");
-				float a = use_fb ? 0.0 : 1.0;
+				float a = use_fb ? float(current_env->bg_param[VS::ENV_BG_PARAM_GLOW]) : 1.0;
 				glClearColor(bgcolor.r,bgcolor.g,bgcolor.b,a);
 				_glClearDepth(1.0);
 				glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
@@ -5923,7 +6242,7 @@ void RasterizerGLES2::end_scene() {
 	}
 
 	alpha_render_list.sort_z();
-	_render_list_forward(&alpha_render_list,camera_transform,camera_transform_inverse,camera_projection,false,false,true);
+	_render_list_forward(&alpha_render_list,camera_transform,camera_transform_inverse,camera_projection,false,fragment_lighting,true);
 	glColorMask(1,1,1,1);
 
 //	material_shader.set_conditional( MaterialShaderGLES2::USE_FOG,false);
@@ -5953,7 +6272,12 @@ void RasterizerGLES2::end_scene() {
 			_process_hdr();
 		}
 		if (current_env && current_env->fx_enabled[VS::ENV_FX_GLOW]) {
-			_process_glow_bloom();
+			_process_glow_bloom();			
+			int glow_transfer_mode=current_env->fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_BLEND_MODE];
+			if (glow_transfer_mode==1)
+				copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_SCREEN,true);
+			if (glow_transfer_mode==2)
+				copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_SOFTLIGHT,true);
 		}
 
 		glBindFramebuffer(GL_FRAMEBUFFER, current_rt?current_rt->fbo:base_framebuffer);
@@ -6024,6 +6348,8 @@ void RasterizerGLES2::end_scene() {
 		copy_shader.set_conditional(CopyShaderGLES2::USE_HDR,false);
 		copy_shader.set_conditional(CopyShaderGLES2::USE_NO_ALPHA,false);
 		copy_shader.set_conditional(CopyShaderGLES2::USE_FXAA,false);
+		copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_SCREEN,false);
+		copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_SOFTLIGHT,false);
 
 		material_shader.set_conditional(MaterialShaderGLES2::USE_HDR,false);
 
@@ -6216,8 +6542,8 @@ void RasterizerGLES2::end_shadow_map() {
 	//glDisable(GL_POLYGON_OFFSET_FILL);
 
 
-	if (!use_rgba_shadowmaps)
-		glColorMask(1, 1, 1, 1);
+	//if (!use_rgba_shadowmaps)
+	glColorMask(1, 1, 1, 1);
 
 	DEBUG_TEST_ERROR("Drawing Shadow");
 	shadow=NULL;
@@ -6950,6 +7276,10 @@ bool RasterizerGLES2::is_mesh(const RID& p_rid) const {
 
 	return mesh_owner.owns(p_rid);
 }
+bool RasterizerGLES2::is_immediate(const RID& p_rid) const {
+
+	return immediate_owner.owns(p_rid);
+}
 bool RasterizerGLES2::is_multimesh(const RID& p_rid) const {
 
 	return multimesh_owner.owns(p_rid);
@@ -7074,6 +7404,13 @@ void RasterizerGLES2::free(const RID& p_rid) {
 	       multimesh_owner.free(p_rid);
 	       memdelete(multimesh);
 
+	} else if (immediate_owner.owns(p_rid)) {
+
+		Immediate *immediate = immediate_owner.get(p_rid);
+		ERR_FAIL_COND(!immediate);
+
+		immediate_owner.free(p_rid);
+		memdelete(immediate);
 	} else if (particles_owner.owns(p_rid)) {
 
 		Particles *particles = particles_owner.get(p_rid);
@@ -8121,6 +8458,8 @@ RasterizerGLES2::RasterizerGLES2(bool p_compress_arrays,bool p_keep_ram_copy,boo
 	draw_next_frame=false;
 	use_framebuffers=true;
 	framebuffer.active=false;
+	tc0_id_cache=0;
+	tc0_idx=0;
 };
 
 RasterizerGLES2::~RasterizerGLES2() {

+ 65 - 2
drivers/gles2/rasterizer_gles2.h

@@ -173,8 +173,11 @@ class RasterizerGLES2 : public Rasterizer {
 		bool can_zpass;
 		bool has_texscreen;
 		bool has_screen_uv;
+		bool writes_vertex;
+		bool uses_discard;
 
 		Map<StringName,ShaderLanguage::Uniform> uniforms;
+		StringName first_texture;
 
 
 		SelfList<Shader> dirty_list;
@@ -190,6 +193,8 @@ class RasterizerGLES2 : public Rasterizer {
 			can_zpass=true;
 			has_texscreen=false;
 			has_screen_uv=false;
+			writes_vertex=false;
+			uses_discard=false;
 		}
 
 
@@ -235,6 +240,7 @@ class RasterizerGLES2 : public Rasterizer {
 			flags[VS::MATERIAL_FLAG_VISIBLE]=true;
 			for(int i=0;i<VS::MATERIAL_HINT_MAX;i++)
 				hints[i]=false;
+			hints[VS::MATERIAL_HINT_NO_DEPTH_DRAW_FOR_ALPHA]=true;
 
 			line_width=1;
 			has_alpha=false;
@@ -256,7 +262,7 @@ class RasterizerGLES2 : public Rasterizer {
 		enum Type {
 			GEOMETRY_INVALID,
 			GEOMETRY_SURFACE,
-			GEOMETRY_POLY,
+			GEOMETRY_IMMEDIATE,
 			GEOMETRY_PARTICLES,
 			GEOMETRY_MULTISURFACE,
 		};
@@ -457,6 +463,31 @@ class RasterizerGLES2 : public Rasterizer {
 	mutable RID_Owner<MultiMesh> multimesh_owner;
 	mutable SelfList<MultiMesh>::List _multimesh_dirty_list;
 
+	struct Immediate : public Geometry {
+
+		struct Chunk {
+
+			RID texture;
+			VS::PrimitiveType primitive;
+			Vector<Vector3> vertices;
+			Vector<Vector3> normals;
+			Vector<Plane> tangents;
+			Vector<Color> colors;
+			Vector<Vector2> uvs;
+			Vector<Vector2> uvs2;
+		};
+
+		List<Chunk> chunks;
+		bool building;
+		int mask;
+		AABB aabb;
+
+		Immediate() { type=GEOMETRY_IMMEDIATE; building=false;}
+
+	};
+
+	mutable RID_Owner<Immediate> immediate_owner;
+
 	struct Particles : public Geometry {
 
 		ParticleSystemSW data; // software particle system
@@ -585,11 +616,15 @@ class RasterizerGLES2 : public Rasterizer {
 			bg_param[VS::ENV_BG_PARAM_CUBEMAP]=RID();
 			bg_param[VS::ENV_BG_PARAM_ENERGY]=1.0;
 			bg_param[VS::ENV_BG_PARAM_SCALE]=1.0;
+			bg_param[VS::ENV_BG_PARAM_GLOW]=0.0;
 
 			for(int i=0;i<VS::ENV_FX_MAX;i++)
 				fx_enabled[i]=false;
 
 			fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_PASSES]=1;
+			fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_SCALE]=1.0;
+			fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_STRENGTH]=1.0;
+			fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_BLEND_MODE]=0;
 			fx_param[VS::ENV_FX_PARAM_GLOW_BLOOM]=0.0;
 			fx_param[VS::ENV_FX_PARAM_GLOW_BLOOM_TRESHOLD]=0.5;
 			fx_param[VS::ENV_FX_PARAM_DOF_BLUR_PASSES]=1;
@@ -932,7 +967,7 @@ class RasterizerGLES2 : public Rasterizer {
 	void _setup_light(uint16_t p_light);
 
 	_FORCE_INLINE_ void _setup_shader_params(const Material *p_material);
-	bool _setup_material(const Geometry *p_geometry,const Material *p_material,bool p_no_const_light);
+	bool _setup_material(const Geometry *p_geometry, const Material *p_material, bool p_no_const_light, bool p_opaque_pass);
 	void _setup_skeleton(const Skeleton *p_skeleton);
 
 
@@ -1096,6 +1131,16 @@ class RasterizerGLES2 : public Rasterizer {
 	void _copy_screen_quad();
 	void _copy_to_texscreen();
 
+
+	Vector3 chunk_vertex;
+	Vector3 chunk_normal;
+	Plane chunk_tangent;
+	Color chunk_color;
+	Vector2 chunk_uv;
+	Vector2 chunk_uv2;
+	GLuint tc0_id_cache;
+	GLuint tc0_idx;
+
 public:
 
 	/* TEXTURE API */
@@ -1205,6 +1250,22 @@ public:
 	virtual void multimesh_set_visible_instances(RID p_multimesh,int p_visible);
 	virtual int multimesh_get_visible_instances(RID p_multimesh) const;
 
+	/* IMMEDIATE API */
+
+	virtual RID immediate_create();
+	virtual void immediate_begin(RID p_immediate,VS::PrimitiveType p_rimitive,RID p_texture=RID());
+	virtual void immediate_vertex(RID p_immediate,const Vector3& p_vertex);
+	virtual void immediate_normal(RID p_immediate,const Vector3& p_normal);
+	virtual void immediate_tangent(RID p_immediate,const Plane& p_tangent);
+	virtual void immediate_color(RID p_immediate,const Color& p_color);
+	virtual void immediate_uv(RID p_immediate,const Vector2& tex_uv);
+	virtual void immediate_uv2(RID p_immediate,const Vector2& tex_uv);
+	virtual void immediate_end(RID p_immediate);
+	virtual void immediate_clear(RID p_immediate);
+	virtual AABB immediate_get_aabb(RID p_immediate) const;
+	virtual void immediate_set_material(RID p_immediate,RID p_material);
+	virtual RID immediate_get_material(RID p_immediate) const;
+
 	/* PARTICLES API */
 
 	virtual RID particles_create();
@@ -1364,6 +1425,7 @@ public:
 
 	virtual void add_mesh( const RID& p_mesh, const InstanceData *p_data);
 	virtual void add_multimesh( const RID& p_multimesh, const InstanceData *p_data);
+	virtual void add_immediate( const RID& p_immediate, const InstanceData *p_data);
 	virtual void add_particles( const RID& p_particle_instance, const InstanceData *p_data);
 
 	virtual void end_scene();
@@ -1411,6 +1473,7 @@ public:
 	virtual bool is_texture(const RID& p_rid) const;
 	virtual bool is_material(const RID& p_rid) const;
 	virtual bool is_mesh(const RID& p_rid) const;
+	virtual bool is_immediate(const RID& p_rid) const;
 	virtual bool is_multimesh(const RID& p_rid) const;
 	virtual bool is_particles(const RID &p_beam) const;
 

+ 7 - 0
drivers/gles2/shader_compiler_gles2.cpp

@@ -145,6 +145,12 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a
 		} break;
 		case SL::Node::TYPE_VARIABLE: {
 			SL::VariableNode *vnode=(SL::VariableNode*)p_node;
+			if (type==ShaderLanguage::SHADER_MATERIAL_VERTEX) {
+
+				if (vnode->name==vname_vertex && p_assign_left) {
+					vertex_code_writes_vertex=true;
+				}
+			}
 			if (type==ShaderLanguage::SHADER_MATERIAL_FRAGMENT) {
 
 				if (vnode->name==vname_discard) {
@@ -644,5 +650,6 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() {
 	vname_binormal_interp="BINORMAL";
 	vname_var1_interp="VAR1";
 	vname_var2_interp="VAR2";
+	vname_vertex="VERTEX";
 
 }

+ 1 - 0
drivers/gles2/shader_compiler_gles2.h

@@ -61,6 +61,7 @@ private:
 	StringName vname_binormal_interp;
 	StringName vname_var1_interp;
 	StringName vname_var2_interp;
+	StringName vname_vertex;
 
 	Map<StringName,ShaderLanguage::Uniform> *uniforms;
 

+ 6 - 2
drivers/gles2/shader_gles2.cpp

@@ -315,6 +315,7 @@ ShaderGLES2::Version* ShaderGLES2::get_current_version() {
 		for(int i=0;i<cc->custom_defines.size();i++) {
 
 			strings.push_back(cc->custom_defines[i]);
+			DEBUG_PRINT("CD #"+itos(i)+": "+String(cc->custom_defines[i]));
 		}
 	}
 
@@ -349,9 +350,11 @@ ShaderGLES2::Version* ShaderGLES2::get_current_version() {
 
 	strings.push_back(vertex_code2.get_data());
 #ifdef DEBUG_SHADER
+
+	DEBUG_PRINT("\nVertex Code:\n\n"+String(code_string.get_data()));
 	for(int i=0;i<strings.size();i++) {
 
-		print_line("vert strings "+itos(i)+":"+String(strings[i]));
+		//print_line("vert strings "+itos(i)+":"+String(strings[i]));
 	}
 #endif
 
@@ -435,9 +438,10 @@ ShaderGLES2::Version* ShaderGLES2::get_current_version() {
 
 	strings.push_back(fragment_code2.get_data());
 #ifdef DEBUG_SHADER
+	DEBUG_PRINT("\nFragment Code:\n\n"+String(code_string.get_data()));
 	for(int i=0;i<strings.size();i++) {
 
-		print_line("frag strings "+itos(i)+":"+String(strings[i]));
+		//print_line("frag strings "+itos(i)+":"+String(strings[i]));
 	}
 #endif
 

+ 39 - 17
drivers/gles2/shaders/copy.glsl

@@ -99,6 +99,8 @@ uniform float bloom_treshold;
 #if defined(BLUR_V_PASS) || defined(BLUR_H_PASS) || defined(USE_HDR_REDUCE)
 
 uniform vec2 pixel_size;
+uniform float pixel_scale;
+uniform float blur_magnitude;
 
 #ifdef USE_HDR_STORE
 
@@ -123,6 +125,10 @@ uniform highp float energy;
 
 #endif
 
+#ifdef USE_CUSTOM_ALPHA
+uniform float custom_alpha;
+#endif
+
 
 void main() {
 
@@ -195,28 +201,28 @@ void main() {
 
 #ifdef BLUR_V_PASS
 
-	color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*-3.0));
-	color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*-2.0));
-	color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*-1.0));
-	color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*1.0));
-	color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*2.0));
-	color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*3.0));
+	color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*-3.0)*pixel_scale);
+	color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*-2.0)*pixel_scale);
+	color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*-1.0)*pixel_scale);
+	color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*1.0)*pixel_scale);
+	color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*2.0)*pixel_scale);
+	color+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*3.0)*pixel_scale);
 
-	color*=(1.0/7.0);
+	color*=(1.0/7.0)*blur_magnitude;
 
 #endif
 
 #ifdef BLUR_H_PASS
 
 
-	color+=texture2D(source,uv_interp+vec2(pixel_size.x*-3.0,0.0));
-	color+=texture2D(source,uv_interp+vec2(pixel_size.x*-2.0,0.0));
-	color+=texture2D(source,uv_interp+vec2(pixel_size.x*-1.0,0.0));
-	color+=texture2D(source,uv_interp+vec2(pixel_size.x*1.0,0.0));
-	color+=texture2D(source,uv_interp+vec2(pixel_size.x*2.0,0.0));
-	color+=texture2D(source,uv_interp+vec2(pixel_size.x*3.0,0.0));
+	color+=texture2D(source,uv_interp+vec2(pixel_size.x*-3.0,0.0)*pixel_scale);
+	color+=texture2D(source,uv_interp+vec2(pixel_size.x*-2.0,0.0)*pixel_scale);
+	color+=texture2D(source,uv_interp+vec2(pixel_size.x*-1.0,0.0)*pixel_scale);
+	color+=texture2D(source,uv_interp+vec2(pixel_size.x*1.0,0.0)*pixel_scale);
+	color+=texture2D(source,uv_interp+vec2(pixel_size.x*2.0,0.0)*pixel_scale);
+	color+=texture2D(source,uv_interp+vec2(pixel_size.x*3.0,0.0)*pixel_scale);
 
-	color*=(1.0/7.0);
+	color*=(1.0/7.0)*blur_magnitude;
 
 #endif
 
@@ -249,12 +255,25 @@ void main() {
 
 	vec4 glow = texture2D( glow_source,  uv2_interp );
 
-#if 1
-//ifdef USE_GLOW_SCREEN
+#ifdef USE_GLOW_SCREEN
 
 	color.rgb = clamp((color.rgb + glow.rgb) - (color.rgb * glow.rgb), 0.0, 1.0);
 
-#else
+#endif
+
+#ifdef USE_GLOW_SOFTLIGHT
+
+	{
+
+		glow.rgb = (glow.rgb * 0.5) + 0.5;
+		color.r =  (glow.r <= 0.5) ? (color.r - (1.0 - 2.0 * glow.r) * color.r * (1.0 - color.r)) : (((glow.r > 0.5) && (color.r <= 0.25)) ? (color.r + (2.0 * glow.r - 1.0) * (4.0 * color.r * (4.0 * color.r + 1.0) * (color.r - 1.0) + 7.0 * color.r)) : (color.r + (2.0 * glow.r - 1.0) * (sqrt(color.r) - color.r)));
+		color.g =  (glow.g <= 0.5) ? (color.g - (1.0 - 2.0 * glow.g) * color.g * (1.0 - color.g)) : (((glow.g > 0.5) && (color.g <= 0.25)) ? (color.g + (2.0 * glow.g - 1.0) * (4.0 * color.g * (4.0 * color.g + 1.0) * (color.g - 1.0) + 7.0 * color.g)) : (color.g + (2.0 * glow.g - 1.0) * (sqrt(color.g) - color.g)));
+		color.b =  (glow.b <= 0.5) ? (color.b - (1.0 - 2.0 * glow.b) * color.b * (1.0 - color.b)) : (((glow.b > 0.5) && (color.b <= 0.25)) ? (color.b + (2.0 * glow.b - 1.0) * (4.0 * color.b * (4.0 * color.b + 1.0) * (color.b - 1.0) + 7.0 * color.b)) : (color.b + (2.0 * glow.b - 1.0) * (sqrt(color.b) - color.b)));
+	}
+
+#endif
+
+#if !defined(USE_GLOW_SCREEN) && !defined(USE_GLOW_SOFTLIGHT)
 	color.rgb+=glow.rgb;
 #endif
 
@@ -316,6 +335,9 @@ void main() {
         color.a=1.0;
 #endif
 
+#ifdef USE_CUSTOM_ALPHA
+	color.a=custom_alpha;
+#endif
         gl_FragColor = color;
 }
 

+ 16 - 4
drivers/gles2/shaders/material.glsl

@@ -386,6 +386,7 @@ VERTEX_SHADER_CODE
 			specular_interp=vec3(0.0);
 		}
 	}
+
 #else
 
 #ifdef SHADELESS
@@ -722,21 +723,28 @@ void main() {
 
 
 
-#ifdef FRAGMENT_SHADER_CODE_USE_DISCARD
-	float discard_=0.0;
+#if defined(ENABLE_DISCARD)
+	bool discard_=false;
 #endif
 
 
 FRAGMENT_SHADER_CODE
 
 
-#ifdef FRAGMENT_SHADER_CODE_USE_DISCARD
-	if (discard_>0.0) {
+#if defined(ENABLE_DISCARD)
+	if (discard_) {
 	//easy to eliminate dead code
 		discard;
 	}
 #endif
 
+#ifdef ENABLE_CLIP_ALPHA
+	if (diffuse.a<0.99) {
+		//used for doublepass and shadowmapping
+		discard;
+	}
+#endif
+
 
         float shadow_attenuation = 1.0;
 
@@ -902,7 +910,10 @@ FRAGMENT_SHADER_CODE
 
 # if !defined(LIGHT_TYPE_DIRECTIONAL) && !defined(LIGHT_TYPE_OMNI) && !defined (LIGHT_TYPE_SPOT)
 //none
+#ifndef SHADELESS
 	diffuse.rgb=vec3(0.0,0.0,0.0);
+#endif
+
 # endif
 
 	diffuse.rgb+=const_light_mult*emission;
@@ -959,6 +970,7 @@ FRAGMENT_SHADER_CODE
 #ifdef USE_HDR
 	diffuse.rgb*=0.25;
 #endif
+
 	gl_FragColor = diffuse;
 #endif
 }

+ 48 - 26
platform/android/export/export.cpp

@@ -189,6 +189,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
 	int orientation;
 
 	String release_keystore;
+	String release_password;
 	String release_username;
 
 	struct APKExportData {
@@ -241,11 +242,11 @@ public:
 	virtual int get_device_count() const;
 	virtual String get_device_name(int p_device) const;
 	virtual String get_device_info(int p_device) const;
-	virtual Error run(int p_device);
+	virtual Error run(int p_device,bool p_dumb=false);
 
 	virtual bool requieres_password(bool p_debug) const { return !p_debug; }
 	virtual String get_binary_extension() const { return "apk"; }
-	virtual Error export_project(const String& p_path,bool p_debug,const String& p_password="");
+	virtual Error export_project(const String& p_path,bool p_debug,bool p_dumb=false);
 
 	virtual bool can_export(String *r_error=NULL) const;
 
@@ -285,6 +286,8 @@ bool EditorExportPlatformAndroid::_set(const StringName& p_name, const Variant&
 		release_keystore=p_value;
 	else if (n=="keystore/release_user")
 		release_username=p_value;
+	else if (n=="keystore/release_password")
+		release_password=p_value;
 	else if (n=="apk_expansion/enable")
 		apk_expansion=p_value;
 	else if (n=="apk_expansion/SALT")
@@ -343,6 +346,8 @@ bool EditorExportPlatformAndroid::_get(const StringName& p_name,Variant &r_ret)
 		r_ret=release_keystore;
 	else if (n=="keystore/release_user")
 		r_ret=release_username;
+	else if (n=="keystore/release_password")
+		r_ret=release_password;
 	else if (n=="apk_expansion/enable")
 		r_ret=apk_expansion;
 	else if (n=="apk_expansion/SALT")
@@ -968,7 +973,7 @@ Error EditorExportPlatformAndroid::save_apk_file(void *p_userdata,const String&
 
 
 
-Error EditorExportPlatformAndroid::export_project(const String& p_path,bool p_debug,const String& p_password) {
+Error EditorExportPlatformAndroid::export_project(const String& p_path, bool p_debug, bool p_dumb) {
 
 	String src_apk;
 
@@ -1088,34 +1093,51 @@ Error EditorExportPlatformAndroid::export_project(const String& p_path,bool p_de
 
 
 	ep.step("Adding Files..",1);
-
 	Error err=OK;
 	Vector<String> cl = cmdline.strip_edges().split(" ");
-	if (apk_expansion) {
 
-		String apkfname="main."+itos(version_code)+"."+package+".obb";
-		String fullpath=p_path.get_base_dir().plus_file(apkfname);
-		FileAccess *pf = FileAccess::open(fullpath,FileAccess::WRITE);
-		if (!pf) {
-			EditorNode::add_io_error("Could not write expansion package file: "+apkfname);
-			return OK;
+	if (p_dumb) {
+
+		String host = EditorSettings::get_singleton()->get("file_server/host");
+		int port = EditorSettings::get_singleton()->get("file_server/post");
+		String passwd = EditorSettings::get_singleton()->get("file_server/password");
+		cl.push_back("-rfs");
+		cl.push_back(host+":"+itos(port));
+		if (passwd!="") {
+			cl.push_back("-rfs_pass");
+			cl.push_back(passwd);
 		}
-		err = save_pack(pf);
-		memdelete(pf);
-		cl.push_back("-main_pack");
-		cl.push_back(apkfname);
-		cl.push_back("-main_pack_md5");
-		cl.push_back(FileAccess::get_md5(fullpath));
-		cl.push_back("-main_pack_cfg");
-		cl.push_back(apk_expansion_salt+","+apk_expansion_pkey);
+
 
 	} else {
+		//all files
 
-		APKExportData ed;
-		ed.ep=&ep;
-		ed.apk=apk;
+		if (apk_expansion) {
 
-		err = export_project_files(save_apk_file,&ed,false);
+			String apkfname="main."+itos(version_code)+"."+package+".obb";
+			String fullpath=p_path.get_base_dir().plus_file(apkfname);
+			FileAccess *pf = FileAccess::open(fullpath,FileAccess::WRITE);
+			if (!pf) {
+				EditorNode::add_io_error("Could not write expansion package file: "+apkfname);
+				return OK;
+			}
+			err = save_pack(pf);
+			memdelete(pf);
+			cl.push_back("-main_pack");
+			cl.push_back(apkfname);
+			cl.push_back("-main_pack_md5");
+			cl.push_back(FileAccess::get_md5(fullpath));
+			cl.push_back("-main_pack_cfg");
+			cl.push_back(apk_expansion_salt+","+apk_expansion_pkey);
+
+		} else {
+
+			APKExportData ed;
+			ed.ep=&ep;
+			ed.apk=apk;
+
+			err = export_project_files(save_apk_file,&ed,false);
+		}
 	}
 
 	if (cl.size()) {
@@ -1179,7 +1201,7 @@ Error EditorExportPlatformAndroid::export_project(const String& p_path,bool p_de
 
 		} else {
 			keystore=release_keystore;
-			password=p_password;
+			password=release_password;
 			user=release_username;
 
 			ep.step("Signing Release APK..",103);
@@ -1388,7 +1410,7 @@ void EditorExportPlatformAndroid::_device_poll_thread(void *ud) {
 
 }
 
-Error EditorExportPlatformAndroid::run(int p_device) {
+Error EditorExportPlatformAndroid::run(int p_device, bool p_dumb) {
 
 	ERR_FAIL_INDEX_V(p_device,devices.size(),ERR_INVALID_PARAMETER);
 	device_lock->lock();
@@ -1407,7 +1429,7 @@ Error EditorExportPlatformAndroid::run(int p_device) {
 	ep.step("Exporting APK",0);
 
 	String export_to=EditorSettings::get_singleton()->get_settings_path()+"/tmp/tmpexport.apk";
-	Error err = export_project(export_to,true);
+	Error err = export_project(export_to,true,p_dumb);
 	if (err) {
 		device_lock->unlock();
 		return err;

+ 5 - 0
platform/android/java_bind.cpp

@@ -0,0 +1,5 @@
+#include "java_bind.h"
+
+JavaBind::JavaBind()
+{
+}

+ 10 - 0
platform/android/java_bind.h

@@ -0,0 +1,10 @@
+#ifndef JAVA_BIND_H
+#define JAVA_BIND_H
+
+class JavaBind
+{
+public:
+	JavaBind();
+};
+
+#endif // JAVA_BIND_H

+ 4 - 4
platform/bb10/export/export.cpp

@@ -67,11 +67,11 @@ public:
 	virtual int get_device_count() const;
 	virtual String get_device_name(int p_device) const;
 	virtual String get_device_info(int p_device) const;
-	virtual Error run(int p_device);
+	virtual Error run(int p_device,bool p_dumb=false);
 
 	virtual bool requieres_password(bool p_debug) const { return !p_debug; }
 	virtual String get_binary_extension() const { return "bar"; }
-	virtual Error export_project(const String& p_path,bool p_debug,const String& p_password="");
+	virtual Error export_project(const String& p_path,bool p_debug,bool p_dumb=false);
 
 	virtual bool can_export(String *r_error=NULL) const;
 
@@ -270,7 +270,7 @@ void EditorExportPlatformBB10::_fix_descriptor(Vector<uint8_t>& p_descriptor) {
 
 
 
-Error EditorExportPlatformBB10::export_project(const String& p_path,bool p_debug,const String& p_password) {
+Error EditorExportPlatformBB10::export_project(const String& p_path, bool p_debug, bool p_dumb) {
 
 
 	EditorProgress ep("export","Exporting for BlackBerry 10",104);
@@ -632,7 +632,7 @@ void EditorExportPlatformBB10::_device_poll_thread(void *ud) {
 
 }
 
-Error EditorExportPlatformBB10::run(int p_device) {
+Error EditorExportPlatformBB10::run(int p_device, bool p_dumb) {
 
 	ERR_FAIL_INDEX_V(p_device,devices.size(),ERR_INVALID_PARAMETER);
 

+ 4 - 4
platform/javascript/export/export.cpp

@@ -77,11 +77,11 @@ public:
 	virtual int get_device_count() const { return show_run?1:0; };
 	virtual String get_device_name(int p_device) const  { return "Run in Browser"; }
 	virtual String get_device_info(int p_device) const { return "Run exported HTML in the system's default browser."; }
-	virtual Error run(int p_device);
+	virtual Error run(int p_device,bool p_dumb=false);
 
 	virtual bool requieres_password(bool p_debug) const { return false; }
 	virtual String get_binary_extension() const { return "html"; }
-	virtual Error export_project(const String& p_path,bool p_debug,const String& p_password="");
+	virtual Error export_project(const String& p_path,bool p_debug,bool p_dumb=false);
 
 	virtual bool can_export(String *r_error=NULL) const;
 
@@ -194,7 +194,7 @@ struct JSExportData {
 
 
 
-Error EditorExportPlatformJavaScript::export_project(const String& p_path,bool p_debug,const String& p_password) {
+Error EditorExportPlatformJavaScript::export_project(const String& p_path, bool p_debug, bool p_dumb) {
 
 
 	String src_template;
@@ -299,7 +299,7 @@ Error EditorExportPlatformJavaScript::export_project(const String& p_path,bool p
 }
 
 
-Error EditorExportPlatformJavaScript::run(int p_device) {
+Error EditorExportPlatformJavaScript::run(int p_device, bool p_dumb) {
 
 	String path = EditorSettings::get_singleton()->get_settings_path()+"/tmp/tmp_export.html";
 	Error err = export_project(path,true,"");

+ 4 - 4
platform/osx/export/export.cpp

@@ -57,11 +57,11 @@ public:
 	virtual int get_device_count() const { return 0; };
 	virtual String get_device_name(int p_device) const  { return String(); }
 	virtual String get_device_info(int p_device) const { return String(); }
-	virtual Error run(int p_device);
+	virtual Error run(int p_device,bool p_dumb=false);
 
 	virtual bool requieres_password(bool p_debug) const { return false; }
 	virtual String get_binary_extension() const { return "zip"; }
-	virtual Error export_project(const String& p_path,bool p_debug,const String& p_password="");
+	virtual Error export_project(const String& p_path,bool p_debug,bool p_dumb=false);
 
 	virtual bool can_export(String *r_error=NULL) const;
 
@@ -245,7 +245,7 @@ void EditorExportPlatformOSX::_fix_plist(Vector<uint8_t>& plist,const String& p_
 	}
 }
 
-Error EditorExportPlatformOSX::export_project(const String& p_path,bool p_debug,const String& p_password) {
+Error EditorExportPlatformOSX::export_project(const String& p_path, bool p_debug, bool p_dumb) {
 
 	String src_pkg;
 
@@ -437,7 +437,7 @@ Error EditorExportPlatformOSX::export_project(const String& p_path,bool p_debug,
 }
 
 
-Error EditorExportPlatformOSX::run(int p_device) {
+Error EditorExportPlatformOSX::run(int p_device, bool p_dumb) {
 
 	return OK;
 }

+ 102 - 0
scene/3d/immediate_geometry.cpp

@@ -0,0 +1,102 @@
+#include "immediate_geometry.h"
+
+
+void ImmediateGeometry::begin(Mesh::PrimitiveType p_primitive,const Ref<Texture>& p_texture) {
+
+	VS::get_singleton()->immediate_begin(im,(VS::PrimitiveType)p_primitive,p_texture.is_valid()?p_texture->get_rid():RID());
+	if (p_texture.is_valid())
+		cached_textures.push_back(p_texture);
+
+}
+
+void ImmediateGeometry::set_normal(const Vector3& p_normal){
+
+	VS::get_singleton()->immediate_normal(im,p_normal);
+}
+
+void ImmediateGeometry::set_tangent(const Plane& p_tangent){
+
+	VS::get_singleton()->immediate_tangent(im,p_tangent);
+
+}
+
+void ImmediateGeometry::set_color(const Color& p_color){
+
+	VS::get_singleton()->immediate_color(im,p_color);
+
+}
+
+void ImmediateGeometry::set_uv(const Vector2& p_uv){
+
+	VS::get_singleton()->immediate_uv(im,p_uv);
+
+}
+
+void ImmediateGeometry::set_uv2(const Vector2& p_uv2){
+
+	VS::get_singleton()->immediate_uv2(im,p_uv2);
+
+}
+
+void ImmediateGeometry::add_vertex(const Vector3& p_vertex){
+
+	VS::get_singleton()->immediate_vertex(im,p_vertex);
+	if (empty) {
+		aabb.pos=p_vertex;
+		aabb.size=Vector3();
+	} else {
+		aabb.expand_to(p_vertex);
+	}
+}
+
+void ImmediateGeometry::end(){
+
+	VS::get_singleton()->immediate_end(im);
+
+}
+
+void ImmediateGeometry::clear(){
+
+	VS::get_singleton()->immediate_clear(im);
+	empty=true;
+	cached_textures.clear();
+
+}
+
+AABB ImmediateGeometry::get_aabb() const {
+
+	return aabb;
+}
+DVector<Face3> ImmediateGeometry::get_faces(uint32_t p_usage_flags) const {
+
+	return DVector<Face3>();
+}
+
+void ImmediateGeometry::_bind_methods() {
+
+	ObjectTypeDB::bind_method(_MD("begin","primitive","texture:Texture"),&ImmediateGeometry::begin);
+	ObjectTypeDB::bind_method(_MD("set_normal","normal"),&ImmediateGeometry::set_normal);
+	ObjectTypeDB::bind_method(_MD("set_tangent","tangent"),&ImmediateGeometry::set_tangent);
+	ObjectTypeDB::bind_method(_MD("set_color","color"),&ImmediateGeometry::set_color);
+	ObjectTypeDB::bind_method(_MD("set_uv","uv"),&ImmediateGeometry::set_uv);
+	ObjectTypeDB::bind_method(_MD("set_uv2","uv"),&ImmediateGeometry::set_uv2);
+	ObjectTypeDB::bind_method(_MD("add_vertex","color"),&ImmediateGeometry::add_vertex);
+	ObjectTypeDB::bind_method(_MD("end"),&ImmediateGeometry::end);
+	ObjectTypeDB::bind_method(_MD("clear"),&ImmediateGeometry::clear);
+
+}
+
+ImmediateGeometry::ImmediateGeometry() {
+
+	im = VisualServer::get_singleton()->immediate_create();
+	set_base(im);
+	empty=true;
+
+}
+
+
+ImmediateGeometry::~ImmediateGeometry() {
+
+	VisualServer::get_singleton()->free(im);
+
+}

+ 41 - 0
scene/3d/immediate_geometry.h

@@ -0,0 +1,41 @@
+#ifndef IMMEDIATE_GEOMETRY_H
+#define IMMEDIATE_GEOMETRY_H
+
+#include "scene/3d/visual_instance.h"
+#include "scene/resources/mesh.h"
+
+class ImmediateGeometry : public GeometryInstance {
+
+	OBJ_TYPE(ImmediateGeometry,GeometryInstance);
+
+
+	RID im;
+	List<Ref<Texture> > cached_textures;
+	bool empty;
+	AABB aabb;
+protected:
+
+	static void _bind_methods();
+public:
+
+
+	void begin(Mesh::PrimitiveType p_primitive,const Ref<Texture>& p_texture);
+	void set_normal(const Vector3& p_normal);
+	void set_tangent(const Plane& p_tangent);
+	void set_color(const Color& p_color);
+	void set_uv(const Vector2& tex_uv);
+	void set_uv2(const Vector2& tex_uv);
+
+	void add_vertex(const Vector3& p_vertex);
+
+	void end();
+	void clear();
+
+	virtual AABB get_aabb() const;
+	virtual DVector<Face3> get_faces(uint32_t p_usage_flags) const;
+
+	ImmediateGeometry();
+	~ImmediateGeometry();
+};
+
+#endif // IMMEDIATE_GEOMETRY_H

+ 772 - 0
scene/3d/sprite_3d.cpp

@@ -0,0 +1,772 @@
+#include "sprite_3d.h"
+#include "scene/scene_string_names.h"
+#include "core_string_names.h"
+
+
+Color SpriteBase3D::_get_color_accum() {
+
+	if (!color_dirty)
+		return color_accum;
+
+	if (parent_sprite)
+		color_accum=parent_sprite->_get_color_accum();
+	else
+		color_accum=Color(1,1,1,1);
+
+	color_accum.r*=modulate.r;
+	color_accum.g*=modulate.g;
+	color_accum.b*=modulate.b;
+	color_accum.a*=modulate.a;
+	color_dirty=false;
+	return color_accum;
+}
+
+void SpriteBase3D::_propagate_color_changed() {
+
+	if (color_dirty)
+		return;
+
+	color_dirty=true;
+	_queue_update();
+
+	for (List<SpriteBase3D*>::Element *E=children.front();E;E=E->next()) {
+
+		E->get()->_propagate_color_changed();
+	}
+}
+
+void SpriteBase3D::_notification(int p_what) {
+
+	if (p_what==NOTIFICATION_ENTER_SCENE) {
+
+		if (!pending_update)
+			_im_update();
+
+		Node *parent=get_parent();
+		if (parent) {
+
+			parent_sprite=parent->cast_to<SpriteBase3D>();
+			if (parent_sprite) {
+				pI=parent_sprite->children.push_back(this);
+			}
+		}
+	}
+
+	if (p_what==NOTIFICATION_EXIT_SCENE) {
+
+
+		if (parent_sprite) {
+
+			parent_sprite->children.erase(pI);
+			pI=NULL;
+			parent_sprite=NULL;
+		}
+	}
+
+}
+
+
+void SpriteBase3D::set_centered(bool p_center) {
+
+	centered=p_center;
+	_queue_update();
+
+}
+
+bool SpriteBase3D::is_centered() const {
+
+	return centered;
+}
+
+void SpriteBase3D::set_offset(const Point2& p_offset) {
+
+	offset=p_offset;
+	_queue_update();
+
+}
+Point2 SpriteBase3D::get_offset() const {
+
+	return offset;
+}
+
+void SpriteBase3D::set_flip_h(bool p_flip) {
+
+	hflip=p_flip;
+	_queue_update();
+}
+bool SpriteBase3D::is_flipped_h() const {
+
+	return hflip;
+}
+
+void SpriteBase3D::set_flip_v(bool p_flip) {
+
+	vflip=p_flip;
+	_queue_update();
+}
+bool SpriteBase3D::is_flipped_v() const {
+
+	return vflip;
+}
+
+
+
+void SpriteBase3D::set_modulate(const Color& p_color) {
+
+	modulate=p_color;
+	_propagate_color_changed();
+	_queue_update();
+}
+
+Color SpriteBase3D::get_modulate() const{
+
+	return modulate;
+}
+
+
+void SpriteBase3D::set_pixel_size(float p_amount) {
+
+	pixel_size=p_amount;
+	_queue_update();
+}
+float SpriteBase3D::get_pixel_size() const {
+
+	return pixel_size;
+}
+
+void SpriteBase3D::set_opacity(float p_amount) {
+
+	opacity=p_amount;
+	_queue_update();
+}
+float SpriteBase3D::get_opacity() const {
+
+	return opacity;
+}
+
+
+void SpriteBase3D::set_axis(Vector3::Axis p_axis) {
+
+	axis=p_axis;
+	_queue_update();
+}
+Vector3::Axis SpriteBase3D::get_axis() const {
+
+	return axis;
+}
+
+
+
+void SpriteBase3D::_im_update() {
+
+
+	_draw();
+
+
+	pending_update=false;
+
+	//texture->draw_rect_region(ci,dst_rect,src_rect,modulate);
+
+}
+
+void SpriteBase3D::_queue_update(){
+
+	if  (pending_update)
+		return;
+
+	pending_update=true;
+	call_deferred(SceneStringNames::get_singleton()->_im_update);
+}
+
+
+AABB SpriteBase3D::get_aabb() const {
+
+	return aabb;
+}
+DVector<Face3> SpriteBase3D::get_faces(uint32_t p_usage_flags) const {
+
+	return DVector<Face3>();
+
+}
+
+void SpriteBase3D::set_draw_flag(DrawFlags p_flag,bool p_enable) {
+
+	ERR_FAIL_INDEX(p_flag,FLAG_MAX);
+	flags[p_flag]=p_enable;
+	_queue_update();
+}
+
+bool SpriteBase3D::get_draw_flag(DrawFlags p_flag) const{
+	ERR_FAIL_INDEX_V(p_flag,FLAG_MAX,false);
+	return flags[p_flag];
+}
+
+void SpriteBase3D::set_alpha_cut_mode(AlphaCutMode p_mode){
+
+	ERR_FAIL_INDEX(p_mode,3);
+	alpha_cut=p_mode;
+	_queue_update();
+
+}
+
+SpriteBase3D::AlphaCutMode SpriteBase3D::get_alpha_cut_mode() const{
+
+	return alpha_cut;
+}
+
+
+void SpriteBase3D::_bind_methods() {
+
+
+	ObjectTypeDB::bind_method(_MD("set_centered","centered"),&SpriteBase3D::set_centered);
+	ObjectTypeDB::bind_method(_MD("is_centered"),&SpriteBase3D::is_centered);
+
+	ObjectTypeDB::bind_method(_MD("set_offset","offset"),&SpriteBase3D::set_offset);
+	ObjectTypeDB::bind_method(_MD("get_offset"),&SpriteBase3D::get_offset);
+
+	ObjectTypeDB::bind_method(_MD("set_flip_h","flip_h"),&SpriteBase3D::set_flip_h);
+	ObjectTypeDB::bind_method(_MD("is_flipped_h"),&SpriteBase3D::is_flipped_h);
+
+	ObjectTypeDB::bind_method(_MD("set_flip_v","flip_v"),&SpriteBase3D::set_flip_v);
+	ObjectTypeDB::bind_method(_MD("is_flipped_v"),&SpriteBase3D::is_flipped_v);
+
+
+	ObjectTypeDB::bind_method(_MD("set_modulate","modulate"),&SpriteBase3D::set_modulate);
+	ObjectTypeDB::bind_method(_MD("get_modulate"),&SpriteBase3D::get_modulate);
+
+	ObjectTypeDB::bind_method(_MD("set_opacity","opacity"),&SpriteBase3D::set_opacity);
+	ObjectTypeDB::bind_method(_MD("get_opacity"),&SpriteBase3D::get_opacity);
+
+	ObjectTypeDB::bind_method(_MD("set_pixel_size","pixel_size"),&SpriteBase3D::set_pixel_size);
+	ObjectTypeDB::bind_method(_MD("get_pixel_size"),&SpriteBase3D::get_pixel_size);
+
+	ObjectTypeDB::bind_method(_MD("set_axis","axis"),&SpriteBase3D::set_axis);
+	ObjectTypeDB::bind_method(_MD("get_axis"),&SpriteBase3D::get_axis);
+
+	ObjectTypeDB::bind_method(_MD("set_draw_flag","flag","enabled"),&SpriteBase3D::set_draw_flag);
+	ObjectTypeDB::bind_method(_MD("get_draw_flag","flag"),&SpriteBase3D::get_draw_flag);
+
+	ObjectTypeDB::bind_method(_MD("set_alpha_cut_mode","mode"),&SpriteBase3D::set_alpha_cut_mode);
+	ObjectTypeDB::bind_method(_MD("get_alpha_cut_mode"),&SpriteBase3D::get_alpha_cut_mode);
+
+	ObjectTypeDB::bind_method(_MD("get_item_rect"),&SpriteBase3D::get_item_rect);
+
+	ObjectTypeDB::bind_method(_MD("_queue_update"),&SpriteBase3D::_queue_update);
+	ObjectTypeDB::bind_method(_MD("_im_update"),&SpriteBase3D::_im_update);
+
+
+	ADD_PROPERTY( PropertyInfo( Variant::BOOL, "centered"), _SCS("set_centered"),_SCS("is_centered"));
+	ADD_PROPERTY( PropertyInfo( Variant::VECTOR2, "offset"), _SCS("set_offset"),_SCS("get_offset"));
+	ADD_PROPERTY( PropertyInfo( Variant::BOOL, "flip_h"), _SCS("set_flip_h"),_SCS("is_flipped_h"));
+	ADD_PROPERTY( PropertyInfo( Variant::BOOL, "flip_v"), _SCS("set_flip_v"),_SCS("is_flipped_v"));
+	ADD_PROPERTY( PropertyInfo( Variant::COLOR, "modulate"), _SCS("set_modulate"),_SCS("get_modulate"));
+	ADD_PROPERTY( PropertyInfo( Variant::REAL, "opacity",PROPERTY_HINT_RANGE,"0,1,0.01"), _SCS("set_opacity"),_SCS("get_opacity"));
+	ADD_PROPERTY( PropertyInfo( Variant::REAL, "pixel_size",PROPERTY_HINT_RANGE,"0.0001,128,0.0001"), _SCS("set_pixel_size"),_SCS("get_pixel_size"));
+	ADD_PROPERTY( PropertyInfo( Variant::INT, "axis",PROPERTY_HINT_ENUM,"X-Axis,Y-Axis,Z-Axis"), _SCS("set_axis"),_SCS("get_axis"));
+	ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "flags/transparent"), _SCS("set_draw_flag"),_SCS("get_draw_flag"),FLAG_TRANSPARENT);
+	ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "flags/shaded"), _SCS("set_draw_flag"),_SCS("get_draw_flag"),FLAG_SHADED);
+	ADD_PROPERTY( PropertyInfo( Variant::INT, "flags/alpha_cut",PROPERTY_HINT_ENUM,"Disabled,Discard,Opaque Pre-Pass"), _SCS("set_alpha_cut_mode"),_SCS("get_alpha_cut_mode"));
+
+
+	BIND_CONSTANT( FLAG_TRANSPARENT );
+	BIND_CONSTANT( FLAG_SHADED );
+	BIND_CONSTANT( FLAG_MAX );
+
+	BIND_CONSTANT( ALPHA_CUT_DISABLED );
+	BIND_CONSTANT( ALPHA_CUT_DISCARD );
+	BIND_CONSTANT( ALPHA_CUT_OPAQUE_PREPASS );
+}
+
+
+
+
+SpriteBase3D::SpriteBase3D() {
+
+	color_dirty=true;
+	centered=true;
+	hflip=false;
+	vflip=false;
+	parent_sprite=NULL;
+	pI=NULL;
+
+	for(int i=0;i<4;i++)
+		flags[i]=i==FLAG_TRANSPARENT;
+
+	axis=Vector3::AXIS_Z;
+	pixel_size=0.01;
+	modulate=Color(1,1,1,1);
+	pending_update=false;
+	opacity=1.0;
+	immediate = VisualServer::get_singleton()->immediate_create();
+	set_base(immediate);
+}
+
+
+SpriteBase3D::~SpriteBase3D() {
+
+	VisualServer::get_singleton()->free(immediate);
+}
+
+
+///////////////////////////////////////////
+
+
+void Sprite3D::_draw() {
+
+	RID immediate = get_immediate();
+
+	VS::get_singleton()->immediate_clear(immediate);
+	if (!texture.is_valid())
+		return; //no texuture no life
+	Vector2 tsize = texture->get_size();
+	if (tsize.x==0 || tsize.y==0)
+		return;
+
+	Size2i s;
+	Rect2i src_rect;
+
+	if (region) {
+
+		s=region_rect.size;
+		src_rect=region_rect;
+	} else {
+		s = texture->get_size();
+		s=s/Size2i(hframes,vframes);
+
+		src_rect.size=s;
+		src_rect.pos.x+=(frame%hframes)*s.x;
+		src_rect.pos.y+=(frame/hframes)*s.y;
+
+	}
+
+	Point2i ofs=get_offset();
+	if (is_centered())
+		ofs-=s/2;
+
+	Rect2i dst_rect(ofs,s);
+
+
+	Rect2 final_rect;
+	Rect2 final_src_rect;
+	if (!texture->get_rect_region(dst_rect,src_rect,final_rect,final_src_rect))
+		return;
+
+
+	if (final_rect.size.x==0 || final_rect.size.y==0)
+		return;
+
+	Color color=_get_color_accum();
+	color.a*=get_opacity();
+
+	float pixel_size=get_pixel_size();
+
+	Vector2 vertices[4]={
+
+		(final_rect.pos+Vector2(0,final_rect.size.y)) * pixel_size,
+		(final_rect.pos+final_rect.size) * pixel_size,
+		(final_rect.pos+Vector2(final_rect.size.x,0)) * pixel_size,
+		final_rect.pos * pixel_size,
+
+
+	};
+	Vector2 uvs[4]={
+		final_src_rect.pos / tsize,
+		(final_src_rect.pos+Vector2(final_src_rect.size.x,0)) / tsize,
+		(final_src_rect.pos+final_src_rect.size) / tsize,
+		(final_src_rect.pos+Vector2(0,final_src_rect.size.y)) / tsize,
+	};
+
+	if (is_flipped_h()) {
+		SWAP(uvs[0],uvs[1]);
+		SWAP(uvs[2],uvs[3]);
+	}
+	if (is_flipped_v()) {
+
+		SWAP(uvs[0],uvs[3]);
+		SWAP(uvs[1],uvs[2]);
+	}
+
+
+	Vector3 normal;
+	int axis = get_axis();
+	normal[axis]=1.0;
+
+	RID mat = VS::get_singleton()->material_2d_get(get_draw_flag(FLAG_SHADED),get_draw_flag(FLAG_TRANSPARENT),get_alpha_cut_mode()==ALPHA_CUT_DISCARD,get_alpha_cut_mode()==ALPHA_CUT_OPAQUE_PREPASS);
+	VS::get_singleton()->immediate_set_material(immediate,mat);
+
+	VS::get_singleton()->immediate_begin(immediate,VS::PRIMITIVE_TRIANGLE_FAN,texture->get_rid());
+
+	int x_axis = ((axis + 1) % 3);
+	int y_axis = ((axis + 2) % 3);
+
+	AABB aabb;
+
+	for(int i=0;i<4;i++) {
+		VS::get_singleton()->immediate_normal(immediate,normal);
+		VS::get_singleton()->immediate_color(immediate,color);
+		VS::get_singleton()->immediate_uv(immediate,uvs[i]);
+
+		Vector3 vtx;
+		vtx[x_axis]=vertices[i][x_axis];
+		vtx[y_axis]=vertices[i][y_axis];
+		VS::get_singleton()->immediate_vertex(immediate,vtx);
+		if (i==0) {
+			aabb.pos=vtx;
+			aabb.size=Vector3();
+		} else {
+			aabb.expand_to(vtx);
+		}
+	}
+	set_aabb(aabb);
+	VS::get_singleton()->immediate_end(immediate);
+
+
+}
+
+void Sprite3D::set_texture(const Ref<Texture>& p_texture) {
+
+	if (p_texture==texture)
+		return;
+	if (texture.is_valid()) {
+		texture->disconnect(CoreStringNames::get_singleton()->changed,this,SceneStringNames::get_singleton()->_queue_update);
+	}
+	texture=p_texture;
+	if (texture.is_valid()) {
+		texture->set_flags(texture->get_flags()); //remove repeat from texture, it looks bad in sprites
+		texture->connect(CoreStringNames::get_singleton()->changed,this,SceneStringNames::get_singleton()->_queue_update);
+	}
+	_queue_update();
+
+}
+
+Ref<Texture> Sprite3D::get_texture() const {
+
+	return texture;
+}
+
+void Sprite3D::set_region(bool p_region) {
+
+	if (p_region==region)
+		return;
+
+	region=p_region;
+	_queue_update();
+}
+
+bool Sprite3D::is_region() const{
+
+	return region;
+}
+
+void Sprite3D::set_region_rect(const Rect2& p_region_rect) {
+
+	bool changed=region_rect!=p_region_rect;
+	region_rect=p_region_rect;
+	if (region && changed) {
+		_queue_update();
+	}
+}
+
+Rect2 Sprite3D::get_region_rect() const {
+
+	return region_rect;
+}
+
+void Sprite3D::set_frame(int p_frame) {
+
+	ERR_FAIL_INDEX(p_frame,vframes*hframes);
+
+	if (frame != p_frame)
+
+	frame=p_frame;
+}
+
+int Sprite3D::get_frame() const {
+
+	return frame;
+}
+
+void Sprite3D::set_vframes(int p_amount) {
+
+	ERR_FAIL_COND(p_amount<1);
+	vframes=p_amount;
+	_queue_update();
+	_change_notify("frame");
+}
+int Sprite3D::get_vframes() const {
+
+	return vframes;
+}
+
+void Sprite3D::set_hframes(int p_amount) {
+
+	ERR_FAIL_COND(p_amount<1);
+	hframes=p_amount;
+	_queue_update();
+	_change_notify("frame");
+}
+int Sprite3D::get_hframes() const {
+
+	return hframes;
+}
+
+Rect2 Sprite3D::get_item_rect() const {
+
+	if (texture.is_null())
+		return Rect2(0,0,1,1);
+	//if (texture.is_null())
+	//	return CanvasItem::get_item_rect();
+
+	Size2i s;
+
+	if (region) {
+
+		s=region_rect.size;
+	} else {
+		s = texture->get_size();
+		s=s/Point2(hframes,vframes);
+	}
+
+	Point2i ofs=get_offset();
+	if (is_centered())
+		ofs-=s/2;
+
+	if (s==Size2(0,0))
+		s=Size2(1,1);
+
+	return Rect2(ofs,s);
+}
+
+void Sprite3D::_bind_methods() {
+
+	ObjectTypeDB::bind_method(_MD("set_texture","texture:Texture"),&Sprite3D::set_texture);
+	ObjectTypeDB::bind_method(_MD("get_texture:Texture"),&Sprite3D::get_texture);
+
+	ObjectTypeDB::bind_method(_MD("set_region","enabled"),&Sprite3D::set_region);
+	ObjectTypeDB::bind_method(_MD("is_region"),&Sprite3D::is_region);
+
+	ObjectTypeDB::bind_method(_MD("set_region_rect","rect"),&Sprite3D::set_region_rect);
+	ObjectTypeDB::bind_method(_MD("get_region_rect"),&Sprite3D::get_region_rect);
+
+	ObjectTypeDB::bind_method(_MD("set_frame","frame"),&Sprite3D::set_frame);
+	ObjectTypeDB::bind_method(_MD("get_frame"),&Sprite3D::get_frame);
+
+	ObjectTypeDB::bind_method(_MD("set_vframes","vframes"),&Sprite3D::set_vframes);
+	ObjectTypeDB::bind_method(_MD("get_vframes"),&Sprite3D::get_vframes);
+
+	ObjectTypeDB::bind_method(_MD("set_hframes","hframes"),&Sprite3D::set_hframes);
+	ObjectTypeDB::bind_method(_MD("get_hframes"),&Sprite3D::get_hframes);
+
+	ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_texture"),_SCS("get_texture"));
+	ADD_PROPERTY( PropertyInfo( Variant::INT, "vframes"), _SCS("set_vframes"),_SCS("get_vframes"));
+	ADD_PROPERTY( PropertyInfo( Variant::INT, "hframes"), _SCS("set_hframes"),_SCS("get_hframes"));
+	ADD_PROPERTY( PropertyInfo( Variant::INT, "frame"), _SCS("set_frame"),_SCS("get_frame"));
+	ADD_PROPERTY( PropertyInfo( Variant::BOOL, "region"), _SCS("set_region"),_SCS("is_region"));
+	ADD_PROPERTY( PropertyInfo( Variant::RECT2, "region_rect"), _SCS("set_region_rect"),_SCS("get_region_rect"));
+
+}
+
+Sprite3D::Sprite3D() {
+
+
+	region=false;
+	frame=0;
+	vframes=1;
+	hframes=1;
+
+}
+
+////////////////////////////////////////
+
+
+void AnimatedSprite3D::_draw() {
+
+	RID immediate = get_immediate();
+	VS::get_singleton()->immediate_clear(immediate);
+
+	if (!frames.is_valid() || !frames->get_frame_count() || frame<0 || frame>=frames->get_frame_count()) {
+		return;
+	}
+
+	Ref<Texture> texture = frames->get_frame(frame);
+	if (!texture.is_valid())
+		return; //no texuture no life
+	Vector2 tsize = texture->get_size();
+	if (tsize.x==0 || tsize.y==0)
+		return;
+
+	Size2i s=tsize;
+	Rect2i src_rect;
+
+	src_rect.size=s;
+
+	Point2i ofs=get_offset();
+	if (is_centered())
+		ofs-=s/2;
+
+	Rect2i dst_rect(ofs,s);
+
+
+	Rect2 final_rect;
+	Rect2 final_src_rect;
+	if (!texture->get_rect_region(dst_rect,src_rect,final_rect,final_src_rect))
+		return;
+
+
+	if (final_rect.size.x==0 || final_rect.size.y==0)
+		return;
+
+	Color color=_get_color_accum();
+	color.a*=get_opacity();
+
+	float pixel_size=get_pixel_size();
+
+	Vector2 vertices[4]={
+
+		(final_rect.pos+Vector2(0,final_rect.size.y)) * pixel_size,
+		(final_rect.pos+final_rect.size) * pixel_size,
+		(final_rect.pos+Vector2(final_rect.size.x,0)) * pixel_size,
+		final_rect.pos * pixel_size,
+
+
+	};
+	Vector2 uvs[4]={
+		final_src_rect.pos / tsize,
+		(final_src_rect.pos+Vector2(final_src_rect.size.x,0)) / tsize,
+		(final_src_rect.pos+final_src_rect.size) / tsize,
+		(final_src_rect.pos+Vector2(0,final_src_rect.size.y)) / tsize,
+	};
+
+	if (is_flipped_h()) {
+		SWAP(uvs[0],uvs[1]);
+		SWAP(uvs[2],uvs[3]);
+	}
+	if (is_flipped_v()) {
+
+		SWAP(uvs[0],uvs[3]);
+		SWAP(uvs[1],uvs[2]);
+	}
+
+
+	Vector3 normal;
+	int axis = get_axis();
+	normal[axis]=1.0;
+
+	RID mat = VS::get_singleton()->material_2d_get(get_draw_flag(FLAG_SHADED),get_draw_flag(FLAG_TRANSPARENT),get_alpha_cut_mode()==ALPHA_CUT_DISCARD,get_alpha_cut_mode()==ALPHA_CUT_OPAQUE_PREPASS);
+	VS::get_singleton()->immediate_set_material(immediate,mat);
+
+	VS::get_singleton()->immediate_begin(immediate,VS::PRIMITIVE_TRIANGLE_FAN,texture->get_rid());
+
+	int x_axis = ((axis + 1) % 3);
+	int y_axis = ((axis + 2) % 3);
+
+	AABB aabb;
+
+	for(int i=0;i<4;i++) {
+		VS::get_singleton()->immediate_normal(immediate,normal);
+		VS::get_singleton()->immediate_color(immediate,color);
+		VS::get_singleton()->immediate_uv(immediate,uvs[i]);
+
+		Vector3 vtx;
+		vtx[x_axis]=vertices[i][x_axis];
+		vtx[y_axis]=vertices[i][y_axis];
+		VS::get_singleton()->immediate_vertex(immediate,vtx);
+		if (i==0) {
+			aabb.pos=vtx;
+			aabb.size=Vector3();
+		} else {
+			aabb.expand_to(vtx);
+		}
+	}
+	set_aabb(aabb);
+	VS::get_singleton()->immediate_end(immediate);
+
+}
+
+void AnimatedSprite3D::_bind_methods(){
+
+	ObjectTypeDB::bind_method(_MD("set_sprite_frames","sprite_frames:SpriteFrames"),&AnimatedSprite3D::set_sprite_frames);
+	ObjectTypeDB::bind_method(_MD("get_sprite_frames:Texture"),&AnimatedSprite3D::get_sprite_frames);
+	ObjectTypeDB::bind_method(_MD("set_frame","frame"),&AnimatedSprite3D::set_frame);
+	ObjectTypeDB::bind_method(_MD("get_frame"),&AnimatedSprite3D::get_frame);
+
+	ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "frames", PROPERTY_HINT_RESOURCE_TYPE,"SpriteFrames"), _SCS("set_sprite_frames"),_SCS("get_sprite_frames"));
+	ADD_PROPERTY( PropertyInfo( Variant::INT, "frame"), _SCS("set_frame"),_SCS("get_frame"));
+
+}
+
+
+
+
+void AnimatedSprite3D::set_sprite_frames(const Ref<SpriteFrames>& p_sprite_frames) {
+
+
+	if (frames==p_sprite_frames)
+		return;
+
+	if (frames.is_valid())
+		frames->disconnect("changed",this,"_queue_update");
+	frames=p_sprite_frames;
+	if (frames.is_valid())
+		frames->connect("changed",this,"_queue_update");
+
+	if (!frames.is_valid() || frame >=frames->get_frame_count()) {
+		frame=0;
+
+	}
+	_queue_update();
+
+}
+
+Ref<SpriteFrames> AnimatedSprite3D::get_sprite_frames() const{
+
+	return frames;
+}
+
+void AnimatedSprite3D::set_frame(int p_frame){
+
+	if (frames.is_null())
+		return;
+
+	ERR_FAIL_INDEX(p_frame,frames->get_frame_count());
+
+	if (frame==p_frame)
+		return;
+
+	frame=p_frame;
+	_queue_update();
+
+}
+int AnimatedSprite3D::get_frame() const{
+
+	return frame;
+}
+
+Rect2 AnimatedSprite3D::get_item_rect() const {
+
+	if (!frames.is_valid() || !frames->get_frame_count() || frame<0 || frame>=frames->get_frame_count()) {
+		return Rect2(0,0,1,1);
+	}
+
+	Ref<Texture> t = frames->get_frame(frame);
+	if (t.is_null())
+		return Rect2(0,0,1,1);
+	Size2i s = t->get_size();
+
+	Point2i ofs=get_offset();
+	if (is_centered())
+		ofs-=s/2;
+
+	if (s==Size2(0,0))
+		s=Size2(1,1);
+
+	return Rect2(ofs,s);
+}
+
+
+
+AnimatedSprite3D::AnimatedSprite3D() {
+
+	frame=0;
+}
+

+ 191 - 0
scene/3d/sprite_3d.h

@@ -0,0 +1,191 @@
+#ifndef SPRITE_3D_H
+#define SPRITE_3D_H
+
+#include "scene/3d/visual_instance.h"
+#include "scene/2d/animated_sprite.h"
+
+
+class SpriteBase3D : public VisualInstance {
+
+	OBJ_TYPE(SpriteBase3D,VisualInstance);
+public:
+
+	enum DrawFlags {
+		FLAG_TRANSPARENT,
+		FLAG_SHADED,
+		FLAG_MAX
+
+	};
+
+	enum AlphaCutMode {
+		ALPHA_CUT_DISABLED,
+		ALPHA_CUT_DISCARD,
+		ALPHA_CUT_OPAQUE_PREPASS
+	};
+
+private:
+
+
+	bool color_dirty;
+	Color color_accum;
+
+	SpriteBase3D *parent_sprite;
+	List<SpriteBase3D*> children;
+	List<SpriteBase3D*>::Element *pI;
+
+	bool centered;
+	Point2 offset;
+
+	bool hflip;
+	bool vflip;
+
+
+	Color modulate;
+	float opacity;
+
+	Vector3::Axis axis;
+	float pixel_size;
+	AABB aabb;
+
+	RID immediate;
+
+	bool flags[FLAG_MAX];
+	AlphaCutMode alpha_cut;
+	bool pending_update;
+	void _im_update();
+
+
+	void _propagate_color_changed();
+
+protected:
+
+	Color _get_color_accum();
+	void _notification(int p_what);
+	static void _bind_methods();
+	virtual void _draw()=0;
+	_FORCE_INLINE_ void set_aabb(const AABB& p_aabb) { aabb=p_aabb; }
+	_FORCE_INLINE_ RID& get_immediate() { return immediate; }
+	void _queue_update();
+public:
+
+	void set_centered(bool p_center);
+	bool is_centered() const;
+
+	void set_offset(const Point2& p_offset);
+	Point2 get_offset() const;
+
+	void set_flip_h(bool p_flip);
+	bool is_flipped_h() const;
+
+	void set_flip_v(bool p_flip);
+	bool is_flipped_v() const;
+
+	void set_region(bool p_region);
+	bool is_region() const;
+
+	void set_region_rect(const Rect2& p_region_rect);
+	Rect2 get_region_rect() const;
+
+	void set_modulate(const Color& p_color);
+	Color get_modulate() const;
+
+	void set_opacity(float p_amount);
+	float get_opacity() const;
+
+	void set_pixel_size(float p_amount);
+	float get_pixel_size() const;
+
+	void set_axis(Vector3::Axis p_amount);
+	Vector3::Axis get_axis() const;
+
+	void set_draw_flag(DrawFlags p_flag,bool p_enable);
+	bool get_draw_flag(DrawFlags p_flag) const;
+
+	void set_alpha_cut_mode(AlphaCutMode p_mode);
+	AlphaCutMode get_alpha_cut_mode() const;
+
+	virtual Rect2 get_item_rect() const=0;
+
+	virtual AABB get_aabb() const;
+	virtual DVector<Face3> get_faces(uint32_t p_usage_flags) const;
+
+	SpriteBase3D();
+	~SpriteBase3D();
+};
+
+
+class Sprite3D : public SpriteBase3D {
+
+	OBJ_TYPE(Sprite3D,SpriteBase3D);
+	Ref<Texture> texture;
+
+
+	bool region;
+	Rect2 region_rect;
+
+	int frame;
+
+	int vframes;
+	int hframes;
+protected:
+	virtual void _draw();
+	static void _bind_methods();
+public:
+
+
+
+	void set_texture(const Ref<Texture>& p_texture);
+	Ref<Texture> get_texture() const;
+
+	void set_region(bool p_region);
+	bool is_region() const;
+
+	void set_region_rect(const Rect2& p_region_rect);
+	Rect2 get_region_rect() const;
+
+	void set_frame(int p_frame);
+	int get_frame() const;
+
+	void set_vframes(int p_amount);
+	int get_vframes() const;
+
+	void set_hframes(int p_amount);
+	int get_hframes() const;
+
+	virtual Rect2 get_item_rect() const;
+
+	Sprite3D();
+//	~Sprite3D();
+};
+
+class AnimatedSprite3D : public SpriteBase3D {
+
+	OBJ_TYPE(AnimatedSprite3D,SpriteBase3D);
+	Ref<SpriteFrames> frames;
+
+
+	int frame;
+
+protected:
+	virtual void _draw();
+	static void _bind_methods();
+public:
+
+
+
+	void set_sprite_frames(const Ref<SpriteFrames>& p_sprite_frames);
+	Ref<SpriteFrames> get_sprite_frames() const;
+
+	void set_frame(int p_frame);
+	int get_frame() const;
+
+
+	virtual Rect2 get_item_rect() const;
+
+	AnimatedSprite3D();
+//	~AnimatedSprite3D();
+};
+
+VARIANT_ENUM_CAST(SpriteBase3D::DrawFlags);
+VARIANT_ENUM_CAST(SpriteBase3D::AlphaCutMode);
+#endif // SPRITE_3D_H

+ 5 - 0
scene/register_scene_types.cpp

@@ -189,6 +189,8 @@
 #include "scene/3d/multimesh_instance.h"
 #include "scene/3d/baked_light.h"
 #include "scene/3d/ray_cast.h"
+#include "scene/3d/immediate_geometry.h"
+#include "scene/3d/sprite_3d.h"
 #include "scene/3d/spatial_sample_player.h"
 #include "scene/3d/spatial_stream_player.h"
 #include "scene/3d/proximity_group.h"
@@ -372,6 +374,9 @@ void register_scene_types() {
 	ObjectTypeDB::register_type<InterpolatedCamera>();
 	ObjectTypeDB::register_type<TestCube>();
 	ObjectTypeDB::register_type<MeshInstance>();
+	ObjectTypeDB::register_type<ImmediateGeometry>();
+	ObjectTypeDB::register_type<Sprite3D>();
+	ObjectTypeDB::register_type<AnimatedSprite3D>();
 	ObjectTypeDB::register_virtual_type<Light>();
 	ObjectTypeDB::register_type<DirectionalLight>();
 	ObjectTypeDB::register_type<OmniLight>();

+ 15 - 0
scene/resources/environment.cpp

@@ -109,9 +109,13 @@ void Environment::_bind_methods() {
 	ADD_PROPERTYI( PropertyInfo(Variant::OBJECT,"background/cubemap",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_background_param"),_SCS("get_background_param"), BG_PARAM_CUBEMAP);
 	ADD_PROPERTYI( PropertyInfo(Variant::REAL,"background/energy",PROPERTY_HINT_RANGE,"0,128,0.01"),_SCS("set_background_param"),_SCS("get_background_param"), BG_PARAM_ENERGY);
 	ADD_PROPERTYI( PropertyInfo(Variant::REAL,"background/scale",PROPERTY_HINT_RANGE,"0.001,16,0.001"),_SCS("set_background_param"),_SCS("get_background_param"), BG_PARAM_SCALE);
+	ADD_PROPERTYI( PropertyInfo(Variant::REAL,"background/glow",PROPERTY_HINT_RANGE,"0.00,8,0.01"),_SCS("set_background_param"),_SCS("get_background_param"), BG_PARAM_GLOW);
 
 	ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"glow/enabled"),_SCS("set_enable_fx"),_SCS("is_fx_enabled"), FX_GLOW);
 	ADD_PROPERTYI( PropertyInfo(Variant::INT,"glow/blur_passes",PROPERTY_HINT_RANGE,"1,4,1"),_SCS("fx_set_param"),_SCS("fx_get_param"), FX_PARAM_GLOW_BLUR_PASSES);
+	ADD_PROPERTYI( PropertyInfo(Variant::REAL,"glow/blur_scale",PROPERTY_HINT_RANGE,"0.01,4,0.01"),_SCS("fx_set_param"),_SCS("fx_get_param"), FX_PARAM_GLOW_BLUR_SCALE);
+	ADD_PROPERTYI( PropertyInfo(Variant::REAL,"glow/blur_strength",PROPERTY_HINT_RANGE,"0.01,4,0.01"),_SCS("fx_set_param"),_SCS("fx_get_param"), FX_PARAM_GLOW_BLUR_STRENGTH);
+	ADD_PROPERTYI( PropertyInfo(Variant::INT,"glow/blur_blend_mode",PROPERTY_HINT_ENUM,"Additive,Screen,SoftLight"),_SCS("fx_set_param"),_SCS("fx_get_param"), FX_PARAM_GLOW_BLUR_BLEND_MODE);
 	ADD_PROPERTYI( PropertyInfo(Variant::REAL,"glow/bloom",PROPERTY_HINT_RANGE,"0,8,0.01"),_SCS("fx_set_param"),_SCS("fx_get_param"), FX_PARAM_GLOW_BLOOM);
 	ADD_PROPERTYI( PropertyInfo(Variant::REAL,"glow/bloom_treshold",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("fx_set_param"),_SCS("fx_get_param"), FX_PARAM_GLOW_BLOOM_TRESHOLD);
 	ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"dof_blur/enabled"),_SCS("set_enable_fx"),_SCS("is_fx_enabled"), FX_DOF_BLUR);
@@ -180,6 +184,7 @@ void Environment::_bind_methods() {
 	BIND_CONSTANT( BG_PARAM_TEXTURE );
 	BIND_CONSTANT( BG_PARAM_CUBEMAP );
 	BIND_CONSTANT( BG_PARAM_ENERGY );
+	BIND_CONSTANT( BG_PARAM_GLOW );
 	BIND_CONSTANT( BG_PARAM_MAX );
 
 
@@ -193,7 +198,14 @@ void Environment::_bind_methods() {
 	BIND_CONSTANT( FX_MAX );
 
 
+	BIND_CONSTANT( FX_BLUR_BLEND_MODE_ADDITIVE );
+	BIND_CONSTANT( FX_BLUR_BLEND_MODE_SCREEN );
+	BIND_CONSTANT( FX_BLUR_BLEND_MODE_SOFTLIGHT );
+
 	BIND_CONSTANT( FX_PARAM_GLOW_BLUR_PASSES );
+	BIND_CONSTANT( FX_PARAM_GLOW_BLUR_SCALE );
+	BIND_CONSTANT( FX_PARAM_GLOW_BLUR_STRENGTH );
+	BIND_CONSTANT( FX_PARAM_GLOW_BLUR_BLEND_MODE );
 	BIND_CONSTANT( FX_PARAM_GLOW_BLOOM);
 	BIND_CONSTANT( FX_PARAM_GLOW_BLOOM_TRESHOLD);
 	BIND_CONSTANT( FX_PARAM_DOF_BLUR_PASSES );
@@ -229,11 +241,14 @@ Environment::Environment() {
 	set_background_param(BG_PARAM_CUBEMAP,Ref<CubeMap>());
 	set_background_param(BG_PARAM_ENERGY,1.0);
 	set_background_param(BG_PARAM_SCALE,1.0);
+	set_background_param(BG_PARAM_GLOW,0.0);
 
 	for(int i=0;i<FX_MAX;i++)
 		set_enable_fx(Fx(i),false);
 
 	fx_set_param(FX_PARAM_GLOW_BLUR_PASSES,1);
+	fx_set_param(FX_PARAM_GLOW_BLUR_SCALE,1);
+	fx_set_param(FX_PARAM_GLOW_BLUR_STRENGTH,1);
 	fx_set_param(FX_PARAM_GLOW_BLOOM,0.0);
 	fx_set_param(FX_PARAM_GLOW_BLOOM_TRESHOLD,0.5);
 	fx_set_param(FX_PARAM_DOF_BLUR_PASSES,1);

+ 10 - 0
scene/resources/environment.h

@@ -56,6 +56,7 @@ public:
 		BG_PARAM_CUBEMAP=VS::ENV_BG_PARAM_CUBEMAP,
 		BG_PARAM_ENERGY=VS::ENV_BG_PARAM_ENERGY,
 		BG_PARAM_SCALE=VS::ENV_BG_PARAM_SCALE,
+		BG_PARAM_GLOW=VS::ENV_BG_PARAM_GLOW,
 		BG_PARAM_MAX=VS::ENV_BG_PARAM_MAX
 	};
 
@@ -70,8 +71,17 @@ public:
 		FX_MAX=VS::ENV_FX_MAX,
 	};
 
+	enum FxBlurBlendMode {
+		FX_BLUR_BLEND_MODE_ADDITIVE,
+		FX_BLUR_BLEND_MODE_SCREEN,
+		FX_BLUR_BLEND_MODE_SOFTLIGHT,
+	};
+
 	enum FxParam {
 		FX_PARAM_GLOW_BLUR_PASSES=VS::ENV_FX_PARAM_GLOW_BLUR_PASSES,
+		FX_PARAM_GLOW_BLUR_SCALE=VS::ENV_FX_PARAM_GLOW_BLUR_SCALE,
+		FX_PARAM_GLOW_BLUR_STRENGTH=VS::ENV_FX_PARAM_GLOW_BLUR_STRENGTH,
+		FX_PARAM_GLOW_BLUR_BLEND_MODE=VS::ENV_FX_PARAM_GLOW_BLUR_BLEND_MODE,
 		FX_PARAM_GLOW_BLOOM=VS::ENV_FX_PARAM_GLOW_BLOOM,
 		FX_PARAM_GLOW_BLOOM_TRESHOLD=VS::ENV_FX_PARAM_GLOW_BLOOM_TRESHOLD,
 		FX_PARAM_DOF_BLUR_PASSES=VS::ENV_FX_PARAM_DOF_BLUR_PASSES,

+ 7 - 2
scene/resources/material.cpp

@@ -45,6 +45,7 @@ static const char*_hint_names[Material::HINT_MAX]={
 	"opaque_pre_zpass",
 	"no_shadow",
 	"no_depth_draw",
+	"no_alpha_depth_draw",
 };
 
 static const Material::Flag _flag_indices[Material::FLAG_MAX]={
@@ -175,6 +176,7 @@ void Material::_bind_methods() {
 	BIND_CONSTANT( HINT_OPAQUE_PRE_PASS );
 	BIND_CONSTANT( HINT_NO_SHADOW );
 	BIND_CONSTANT( HINT_NO_DEPTH_DRAW );
+	BIND_CONSTANT( HINT_NO_DEPTH_DRAW_FOR_ALPHA );
 	BIND_CONSTANT( HINT_MAX );
 
 	BIND_CONSTANT( SHADE_MODEL_LAMBERT );
@@ -208,6 +210,7 @@ Material::Material(const RID& p_material) {
 
 	for(int i=0;i<HINT_MAX;i++)
 		hints[i]=false;
+	hints[HINT_NO_DEPTH_DRAW_FOR_ALPHA]=true;
 
 	blend_mode=BLEND_MODE_MIX;
 	shade_model = SHADE_MODEL_LAMBERT;
@@ -365,14 +368,14 @@ Material::BlendMode FixedMaterial::get_detail_blend_mode() const {
 }
 
 void FixedMaterial::set_fixed_flag(FixedFlag p_flag, bool p_value) {
-	ERR_FAIL_INDEX(p_flag,3);
+	ERR_FAIL_INDEX(p_flag,4);
 	fixed_flags[p_flag]=p_value;
 	VisualServer::get_singleton()->fixed_material_set_flag(material,(VS::FixedMaterialFlags)p_flag,p_value);
 
 }
 
 bool FixedMaterial::get_fixed_flag(FixedFlag p_flag) const {
-	ERR_FAIL_INDEX_V(p_flag,3,false);
+	ERR_FAIL_INDEX_V(p_flag,4,false);
 	return fixed_flags[p_flag];
 }
 
@@ -419,6 +422,7 @@ void FixedMaterial::_bind_methods() {
 	ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "fixed_flags/use_alpha" ), _SCS("set_fixed_flag"), _SCS("get_fixed_flag"), FLAG_USE_ALPHA);
 	ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "fixed_flags/use_color_array" ), _SCS("set_fixed_flag"), _SCS("get_fixed_flag"), FLAG_USE_COLOR_ARRAY);
 	ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "fixed_flags/use_point_size" ), _SCS("set_fixed_flag"), _SCS("get_fixed_flag"), FLAG_USE_POINT_SIZE);
+	ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "fixed_flags/discard_alpha" ), _SCS("set_fixed_flag"), _SCS("get_fixed_flag"), FLAG_DISCARD_ALPHA);
 	ADD_PROPERTYI( PropertyInfo( Variant::COLOR, "params/diffuse" ), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_DIFFUSE);
 	ADD_PROPERTYI( PropertyInfo( Variant::COLOR, "params/specular", PROPERTY_HINT_COLOR_NO_ALPHA ), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SPECULAR );
 	ADD_PROPERTYI( PropertyInfo( Variant::COLOR, "params/emission", PROPERTY_HINT_COLOR_NO_ALPHA ), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_EMISSION );
@@ -457,6 +461,7 @@ void FixedMaterial::_bind_methods() {
 	BIND_CONSTANT( FLAG_USE_ALPHA );
 	BIND_CONSTANT( FLAG_USE_COLOR_ARRAY );
 	BIND_CONSTANT( FLAG_USE_POINT_SIZE );
+	BIND_CONSTANT( FLAG_DISCARD_ALPHA );
 
 }
 

+ 2 - 0
scene/resources/material.h

@@ -85,6 +85,7 @@ public:
 		HINT_OPAQUE_PRE_PASS=VS::MATERIAL_HINT_OPAQUE_PRE_PASS,
 		HINT_NO_SHADOW=VS::MATERIAL_HINT_NO_SHADOW,
 		HINT_NO_DEPTH_DRAW=VS::MATERIAL_HINT_NO_DEPTH_DRAW,
+		HINT_NO_DEPTH_DRAW_FOR_ALPHA=VS::MATERIAL_HINT_NO_DEPTH_DRAW_FOR_ALPHA,
 		HINT_MAX=VS::MATERIAL_HINT_MAX
 	};
 
@@ -159,6 +160,7 @@ public:
 		FLAG_USE_ALPHA=VS::FIXED_MATERIAL_FLAG_USE_ALPHA,
 		FLAG_USE_COLOR_ARRAY=VS::FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY,
 		FLAG_USE_POINT_SIZE=VS::FIXED_MATERIAL_FLAG_USE_POINT_SIZE,
+		FLAG_DISCARD_ALPHA=VS::FIXED_MATERIAL_FLAG_DISCARD_ALPHA
 	};
 
 private:

+ 43 - 0
scene/resources/texture.cpp

@@ -53,6 +53,13 @@ void Texture::draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect
 	VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item,p_rect,get_rid(),p_src_rect,p_modulate);
 }
 
+bool Texture::get_rect_region(const Rect2& p_rect, const Rect2& p_src_rect,Rect2& r_rect,Rect2& r_src_rect) const {
+
+	r_rect=p_rect;
+	r_src_rect=p_src_rect;
+
+	return true;
+}
 
 void Texture::_bind_methods() {
 
@@ -609,6 +616,42 @@ void AtlasTexture::draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const
 	VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item,dr,atlas->get_rid(),src_c,p_modulate);
 }
 
+bool AtlasTexture::get_rect_region(const Rect2& p_rect, const Rect2& p_src_rect,Rect2& r_rect,Rect2& r_src_rect) const {
+
+	Rect2 rc=region;
+
+	if (!atlas.is_valid())
+		return false;
+
+	Rect2 src=p_src_rect;
+	src.pos+=(rc.pos-margin.pos);
+	Rect2 src_c = rc.clip(src);
+	if (src_c.size==Size2())
+		return false;
+	Vector2 ofs = (src_c.pos-src.pos);
+
+	Vector2 scale = p_rect.size / p_src_rect.size;
+    if(scale.x < 0)
+    {
+	float mx = (margin.size.width - margin.pos.x);
+	mx -= margin.pos.x;
+	ofs.x = -(ofs.x + mx);
+    }
+    if(scale.y < 0)
+    {
+	float my = margin.size.height - margin.pos.y;
+	my -= margin.pos.y;
+	ofs.y = -(ofs.y + my);
+    }
+	Rect2 dr( p_rect.pos+ofs*scale,src_c.size*scale );
+
+
+
+	r_rect=dr;
+	r_src_rect=src_c;
+	return true;
+}
+
 
 AtlasTexture::AtlasTexture() {
 

+ 2 - 0
scene/resources/texture.h

@@ -70,6 +70,7 @@ public:
 	virtual void draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate=Color(1,1,1)) const;
 	virtual void draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile=false,const Color& p_modulate=Color(1,1,1)) const;
 	virtual void draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1)) const;
+	virtual bool get_rect_region(const Rect2& p_rect, const Rect2& p_src_rect,Rect2& r_rect,Rect2& r_src_rect) const;
 
 
 
@@ -191,6 +192,7 @@ public:
 	virtual void draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate=Color(1,1,1)) const;
 	virtual void draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile=false,const Color& p_modulate=Color(1,1,1)) const;
 	virtual void draw_rect_region(RID p_canvas_item,const Rect2& p_rect, const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1)) const;
+	virtual bool get_rect_region(const Rect2& p_rect, const Rect2& p_src_rect,Rect2& r_rect,Rect2& r_src_rect) const;
 
 
 	AtlasTexture();

+ 2 - 0
scene/scene_string_names.cpp

@@ -137,5 +137,7 @@ SceneStringNames::SceneStringNames() {
 	drop_data = StaticCString::create("drop_data");
 	can_drop_data = StaticCString::create("can_drop_data");
 
+	_im_update = StaticCString::create("_im_update");
+	_queue_update = StaticCString::create("_queue_update");
 
 }

+ 4 - 0
scene/scene_string_names.h

@@ -145,6 +145,10 @@ public:
 
 	StringName play_play;
 
+	StringName _im_update;
+	StringName _queue_update;
+
+
 };
 
 

+ 6 - 0
servers/visual/rasterizer.cpp

@@ -157,6 +157,9 @@ RID Rasterizer::_create_shader(const FixedMaterialShaderKey& p_key) {
 
 	if (p_key.use_alpha) {
 		code+="DIFFUSE_ALPHA=diffuse;\n";
+		if (p_key.discard_alpha) {
+			code+="DISCARD=diffuse.a<0.5;\n";
+		}
 	} else {
 		code+="DIFFUSE=diffuse.rgb;\n";
 	}
@@ -262,6 +265,7 @@ void Rasterizer::_free_shader(const FixedMaterialShaderKey& p_key) {
 
 void Rasterizer::fixed_material_set_flag(RID p_material, VS::FixedMaterialFlags p_flag, bool p_enabled) {
 
+
 	Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material);
 	ERR_FAIL_COND(!E);
 	FixedMaterial &fm=*E->get();
@@ -271,6 +275,7 @@ void Rasterizer::fixed_material_set_flag(RID p_material, VS::FixedMaterialFlags
 		case VS::FIXED_MATERIAL_FLAG_USE_ALPHA: fm.use_alpha=p_enabled; break;
 		case VS::FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY: fm.use_color_array=p_enabled; break;
 		case VS::FIXED_MATERIAL_FLAG_USE_POINT_SIZE: fm.use_pointsize=p_enabled; break;
+		case VS::FIXED_MATERIAL_FLAG_DISCARD_ALPHA: fm.discard_alpha=p_enabled; break;
 	}
 
 	if (!fm.dirty_list.in_list())
@@ -288,6 +293,7 @@ bool Rasterizer::fixed_material_get_flag(RID p_material, VS::FixedMaterialFlags
 		case VS::FIXED_MATERIAL_FLAG_USE_ALPHA: return fm.use_alpha;; break;
 		case VS::FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY: return fm.use_color_array;; break;
 		case VS::FIXED_MATERIAL_FLAG_USE_POINT_SIZE: return fm.use_pointsize;; break;
+		case VS::FIXED_MATERIAL_FLAG_DISCARD_ALPHA: return fm.discard_alpha;; break;
 	}
 
 

+ 22 - 0
servers/visual/rasterizer.h

@@ -55,6 +55,7 @@ protected:
 			bool use_alpha:1;
 			bool use_color_array:1;
 			bool use_pointsize:1;
+			bool discard_alpha:1;
 			bool valid:1;
 		};
 
@@ -80,6 +81,7 @@ protected:
 		RID self;
 		bool use_alpha;
 		bool use_color_array;
+		bool discard_alpha;
 		bool use_pointsize;
 		float point_size;
 		Transform uv_xform;
@@ -100,6 +102,7 @@ protected:
 			k.use_alpha=use_alpha;
 			k.use_color_array=use_color_array;
 			k.use_pointsize=use_pointsize;
+			k.discard_alpha=discard_alpha;
 			k.detail_blend=detail_blend;
 			k.valid=true;
 			for(int i=0;i<VS::FIXED_MATERIAL_PARAM_MAX;i++) {
@@ -119,6 +122,7 @@ protected:
 			use_alpha=false;
 			use_color_array=false;
 			use_pointsize=false;
+			discard_alpha=false;
 			point_size=1.0;
 			detail_blend=VS::MATERIAL_BLEND_MODE_MIX;
 			for(int i=0;i<VS::FIXED_MATERIAL_PARAM_MAX;i++) {
@@ -298,6 +302,22 @@ public:
 	virtual void multimesh_set_visible_instances(RID p_multimesh,int p_visible)=0;
 	virtual int multimesh_get_visible_instances(RID p_multimesh) const=0;
 
+	/* IMMEDIATE API */
+
+	virtual RID immediate_create()=0;
+	virtual void immediate_begin(RID p_immediate,VS::PrimitiveType p_rimitive,RID p_texture=RID())=0;
+	virtual void immediate_vertex(RID p_immediate,const Vector3& p_vertex)=0;
+	virtual void immediate_normal(RID p_immediate,const Vector3& p_normal)=0;
+	virtual void immediate_tangent(RID p_immediate,const Plane& p_tangent)=0;
+	virtual void immediate_color(RID p_immediate,const Color& p_color)=0;
+	virtual void immediate_uv(RID p_immediate,const Vector2& tex_uv)=0;
+	virtual void immediate_uv2(RID p_immediate,const Vector2& tex_uv)=0;
+	virtual void immediate_end(RID p_immediate)=0;
+	virtual void immediate_clear(RID p_immediate)=0;
+	virtual AABB immediate_get_aabb(RID p_immediate) const=0;
+	virtual void immediate_set_material(RID p_immediate,RID p_material)=0;
+	virtual RID immediate_get_material(RID p_immediate) const=0;
+
 	
 	/* PARTICLES API */
 	
@@ -487,6 +507,7 @@ public:
 
 	virtual void add_mesh( const RID& p_mesh, const InstanceData *p_data)=0;
 	virtual void add_multimesh( const RID& p_multimesh, const InstanceData *p_data)=0;
+	virtual void add_immediate( const RID& p_immediate, const InstanceData *p_data)=0;
 	virtual void add_particles( const RID& p_particle_instance, const InstanceData *p_data)=0;
 
 
@@ -544,6 +565,7 @@ public:
 	virtual bool is_material(const RID& p_rid) const=0;
 	virtual bool is_mesh(const RID& p_rid) const=0;
 	virtual bool is_multimesh(const RID& p_rid) const=0;
+	virtual bool is_immediate(const RID& p_rid) const=0;
 	virtual bool is_particles(const RID &p_beam) const=0;
 
 	virtual bool is_light(const RID& p_rid) const=0;

+ 80 - 0
servers/visual/rasterizer_dummy.cpp

@@ -709,6 +709,74 @@ int RasterizerDummy::multimesh_get_visible_instances(RID p_multimesh) const {
 
 }
 
+/* IMMEDIATE API */
+
+
+RID RasterizerDummy::immediate_create() {
+
+	Immediate *im = memnew( Immediate );
+	return immediate_owner.make_rid(im);
+
+}
+
+void RasterizerDummy::immediate_begin(RID p_immediate,VS::PrimitiveType p_rimitive,RID p_texture){
+
+
+}
+void RasterizerDummy::immediate_vertex(RID p_immediate,const Vector3& p_vertex){
+
+
+}
+void RasterizerDummy::immediate_normal(RID p_immediate,const Vector3& p_normal){
+
+
+}
+void RasterizerDummy::immediate_tangent(RID p_immediate,const Plane& p_tangent){
+
+
+}
+void RasterizerDummy::immediate_color(RID p_immediate,const Color& p_color){
+
+
+}
+void RasterizerDummy::immediate_uv(RID p_immediate,const Vector2& tex_uv){
+
+
+}
+void RasterizerDummy::immediate_uv2(RID p_immediate,const Vector2& tex_uv){
+
+
+}
+
+void RasterizerDummy::immediate_end(RID p_immediate){
+
+
+}
+void RasterizerDummy::immediate_clear(RID p_immediate) {
+
+
+}
+
+AABB RasterizerDummy::immediate_get_aabb(RID p_immediate) const {
+
+	return AABB(Vector3(-1,-1,-1),Vector3(2,2,2));
+}
+
+void RasterizerDummy::immediate_set_material(RID p_immediate,RID p_material) {
+
+	Immediate *im = immediate_owner.get(p_immediate);
+	ERR_FAIL_COND(!im);
+	im->material=p_material;
+
+}
+
+RID RasterizerDummy::immediate_get_material(RID p_immediate) const {
+
+	const Immediate *im = immediate_owner.get(p_immediate);
+	ERR_FAIL_COND_V(!im,RID());
+	return im->material;
+
+}
 
 /* PARTICLES API */
 
@@ -1627,6 +1695,12 @@ bool RasterizerDummy::is_mesh(const RID& p_rid) const {
 
 	return mesh_owner.owns(p_rid);
 }
+
+bool RasterizerDummy::is_immediate(const RID& p_rid) const {
+
+	return immediate_owner.owns(p_rid);
+}
+
 bool RasterizerDummy::is_multimesh(const RID& p_rid) const {
 
 	return multimesh_owner.owns(p_rid);
@@ -1703,6 +1777,12 @@ void RasterizerDummy::free(const RID& p_rid) {
 	       multimesh_owner.free(p_rid);
 	       memdelete(multimesh);
 
+	} else if (immediate_owner.owns(p_rid)) {
+
+		Immediate *immediate = immediate_owner.get(p_rid);
+		immediate_owner.free(p_rid);
+		memdelete(immediate);
+
 	} else if (particles_owner.owns(p_rid)) {
 
 		Particles *particles = particles_owner.get(p_rid);

+ 29 - 0
servers/visual/rasterizer_dummy.h

@@ -231,8 +231,18 @@ class RasterizerDummy : public Rasterizer {
 
 	};
 
+
 	mutable RID_Owner<MultiMesh> multimesh_owner;
 
+	struct Immediate {
+
+
+		RID material;
+		int empty;
+	};
+
+	mutable RID_Owner<Immediate> immediate_owner;
+
 	struct Particles : public Geometry {
 
 		ParticleSystemSW data; // software particle system
@@ -490,6 +500,23 @@ public:
 	virtual void multimesh_set_visible_instances(RID p_multimesh,int p_visible);
 	virtual int multimesh_get_visible_instances(RID p_multimesh) const;
 
+	/* IMMEDIATE API */
+
+	virtual RID immediate_create();
+	virtual void immediate_begin(RID p_immediate,VS::PrimitiveType p_rimitive,RID p_texture=RID());
+	virtual void immediate_vertex(RID p_immediate,const Vector3& p_vertex);
+	virtual void immediate_normal(RID p_immediate,const Vector3& p_normal);
+	virtual void immediate_tangent(RID p_immediate,const Plane& p_tangent);
+	virtual void immediate_color(RID p_immediate,const Color& p_color);
+	virtual void immediate_uv(RID p_immediate,const Vector2& tex_uv);
+	virtual void immediate_uv2(RID p_immediate,const Vector2& tex_uv);
+	virtual void immediate_end(RID p_immediate);
+	virtual void immediate_clear(RID p_immediate);
+	virtual void immediate_set_material(RID p_immediate,RID p_material);
+	virtual RID immediate_get_material(RID p_immediate) const;
+
+	virtual AABB immediate_get_aabb(RID p_mesh) const;
+
 	/* PARTICLES API */
 
 	virtual RID particles_create();
@@ -647,6 +674,7 @@ public:
 
 	virtual void add_mesh( const RID& p_mesh, const InstanceData *p_data);
 	virtual void add_multimesh( const RID& p_multimesh, const InstanceData *p_data);
+	virtual void add_immediate( const RID& p_immediate, const InstanceData *p_data) {}
 	virtual void add_particles( const RID& p_particle_instance, const InstanceData *p_data);
 
 	virtual void end_scene();
@@ -692,6 +720,7 @@ public:
 	virtual bool is_texture(const RID& p_rid) const;
 	virtual bool is_material(const RID& p_rid) const;
 	virtual bool is_mesh(const RID& p_rid) const;
+	virtual bool is_immediate(const RID& p_rid) const;
 	virtual bool is_multimesh(const RID& p_rid) const;
 	virtual bool is_particles(const RID &p_beam) const;
 

+ 1 - 1
servers/visual/shader_language.cpp

@@ -1034,7 +1034,7 @@ const ShaderLanguage::BuiltinsDef ShaderLanguage::fragment_builtins_defs[]={
 	{ "SPEC_EXP", TYPE_FLOAT},
 	{ "GLOW", TYPE_FLOAT},
 	{ "SHADE_PARAM", TYPE_FLOAT},
-	{ "DISCARD", TYPE_FLOAT},
+	{ "DISCARD", TYPE_BOOL},
 	{ "SCREEN_UV", TYPE_VEC2},
 	{ "POINT_COORD", TYPE_VEC2},
 	{ "INV_CAMERA_MATRIX", TYPE_MAT4},

+ 77 - 0
servers/visual/visual_server_raster.cpp

@@ -519,6 +519,72 @@ int VisualServerRaster::multimesh_get_visible_instances(RID p_multimesh) const {
 }
 
 
+/* IMMEDIATE API */
+
+
+RID VisualServerRaster::immediate_create() {
+
+	return rasterizer->immediate_create();
+}
+
+void VisualServerRaster::immediate_begin(RID p_immediate,PrimitiveType p_primitive,RID p_texture){
+
+	rasterizer->immediate_begin(p_immediate,p_primitive,p_texture);
+}
+void VisualServerRaster::immediate_vertex(RID p_immediate,const Vector3& p_vertex){
+
+	rasterizer->immediate_vertex(p_immediate,p_vertex);
+
+}
+void VisualServerRaster::immediate_normal(RID p_immediate,const Vector3& p_normal){
+
+	rasterizer->immediate_normal(p_immediate,p_normal);
+
+}
+void VisualServerRaster::immediate_tangent(RID p_immediate,const Plane& p_tangent){
+
+	rasterizer->immediate_tangent(p_immediate,p_tangent);
+
+}
+void VisualServerRaster::immediate_color(RID p_immediate,const Color& p_color){
+
+	rasterizer->immediate_color(p_immediate,p_color);
+
+}
+void VisualServerRaster::immediate_uv(RID p_immediate,const Vector2& p_uv){
+
+	rasterizer->immediate_uv(p_immediate,p_uv);
+
+}
+void VisualServerRaster::immediate_uv2(RID p_immediate,const Vector2& p_uv2){
+
+	rasterizer->immediate_uv2(p_immediate,p_uv2);
+
+}
+void VisualServerRaster::immediate_end(RID p_immediate){
+
+	VS_CHANGED;
+	_dependency_queue_update(p_immediate,true);
+	rasterizer->immediate_end(p_immediate);
+
+}
+void VisualServerRaster::immediate_clear(RID p_immediate){
+
+	VS_CHANGED;
+	_dependency_queue_update(p_immediate,true);
+	rasterizer->immediate_clear(p_immediate);
+
+}
+
+void VisualServerRaster::immediate_set_material(RID p_immediate,RID p_material) {
+
+	rasterizer->immediate_set_material(p_immediate,p_material);
+}
+
+RID VisualServerRaster::immediate_get_material(RID p_immediate) const {
+
+	return rasterizer->immediate_get_material(p_immediate);
+}
 
 
 /* PARTICLES API */
@@ -1705,6 +1771,8 @@ void VisualServerRaster::instance_set_base(RID p_instance, RID p_base) {
 			instance->data.morph_values.resize( rasterizer->mesh_get_morph_target_count(p_base));
 		} else if (rasterizer->is_multimesh(p_base)) {
 			instance->base_type=INSTANCE_MULTIMESH;
+		} else if (rasterizer->is_immediate(p_base)) {
+			instance->base_type=INSTANCE_IMMEDIATE;
 		} else if (rasterizer->is_particles(p_base)) {
 			instance->base_type=INSTANCE_PARTICLES;
 			instance->particles_info=memnew( Instance::ParticlesInfo );
@@ -2467,6 +2535,12 @@ void VisualServerRaster::_update_instance_aabb(Instance *p_instance) {
 
 			new_aabb = rasterizer->multimesh_get_aabb(p_instance->base_rid);
 
+		} break;
+		case VisualServer::INSTANCE_IMMEDIATE: {
+
+			new_aabb = rasterizer->immediate_get_aabb(p_instance->base_rid);
+
+
 		} break;
 		case VisualServer::INSTANCE_PARTICLES: {
 		
@@ -3498,6 +3572,9 @@ void VisualServerRaster::_instance_draw(Instance *p_instance) {
 		case INSTANCE_MULTIMESH: {
 			rasterizer->add_multimesh(p_instance->base_rid, &p_instance->data);
 		} break;
+		case INSTANCE_IMMEDIATE: {
+			rasterizer->add_immediate(p_instance->base_rid, &p_instance->data);
+		} break;
 		case INSTANCE_PARTICLES: {
 			rasterizer->add_particles(p_instance->particles_info->instance, &p_instance->data);
 		} break;

+ 15 - 0
servers/visual/visual_server_raster.h

@@ -766,6 +766,21 @@ public:
 	virtual void multimesh_set_visible_instances(RID p_multimesh,int p_visible);
 	virtual int multimesh_get_visible_instances(RID p_multimesh) const;
 
+	/* IMMEDIATE API */
+
+	virtual RID immediate_create();
+	virtual void immediate_begin(RID p_immediate,PrimitiveType p_rimitive,RID p_texture=RID());
+	virtual void immediate_vertex(RID p_immediate,const Vector3& p_vertex);
+	virtual void immediate_normal(RID p_immediate,const Vector3& p_normal);
+	virtual void immediate_tangent(RID p_immediate,const Plane& p_tangent);
+	virtual void immediate_color(RID p_immediate,const Color& p_color);
+	virtual void immediate_uv(RID p_immediate, const Vector2& p_uv);
+	virtual void immediate_uv2(RID p_immediate,const Vector2& tex_uv);
+	virtual void immediate_end(RID p_immediate);
+	virtual void immediate_clear(RID p_immediate);
+	virtual void immediate_set_material(RID p_immediate,RID p_material);
+	virtual RID immediate_get_material(RID p_immediate) const;
+
 	
 	/* PARTICLES API */
 	

+ 16 - 0
servers/visual/visual_server_wrap_mt.h

@@ -741,6 +741,22 @@ public:
 	FUNC2(multimesh_set_visible_instances,RID,int);
 	FUNC1RC(int,multimesh_get_visible_instances,RID);
 
+	/* IMMEDIATE API */
+
+
+	FUNC0R(RID,immediate_create);
+	FUNC3(immediate_begin,RID,PrimitiveType,RID);
+	FUNC2(immediate_vertex,RID,const Vector3&);
+	FUNC2(immediate_normal,RID,const Vector3&);
+	FUNC2(immediate_tangent,RID,const Plane&);
+	FUNC2(immediate_color,RID,const Color&);
+	FUNC2(immediate_uv,RID,const Vector2&);
+	FUNC2(immediate_uv2,RID,const Vector2&);
+	FUNC1(immediate_end,RID);
+	FUNC1(immediate_clear,RID);
+	FUNC2(immediate_set_material,RID,RID);
+	FUNC1RC(RID,immediate_get_material,RID);
+
 
 	/* PARTICLES API */
 

+ 49 - 0
servers/visual_server.cpp

@@ -274,6 +274,55 @@ RID VisualServer::make_sphere_mesh(int p_lats,int p_lons,float p_radius) {
 	return mesh;
 }
 
+
+RID VisualServer::material_2d_get(bool p_shaded, bool p_transparent, bool p_cut_alpha, bool p_opaque_prepass) {
+
+	int version=0;
+	if (p_shaded)
+		version=1;
+	if (p_transparent)
+		version|=2;
+	if (p_cut_alpha)
+		version|=4;
+	if (p_opaque_prepass)
+		version|=8;
+	if (material_2d[version].is_valid())
+		return material_2d[version];
+
+	//not valid, make
+
+	material_2d[version]=fixed_material_create();
+	fixed_material_set_flag(material_2d[version],FIXED_MATERIAL_FLAG_USE_ALPHA,p_transparent);
+	fixed_material_set_flag(material_2d[version],FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY,true);	
+	fixed_material_set_flag(material_2d[version],FIXED_MATERIAL_FLAG_DISCARD_ALPHA,p_cut_alpha);
+	material_set_flag(material_2d[version],MATERIAL_FLAG_UNSHADED,!p_shaded);
+	material_set_flag(material_2d[version],MATERIAL_FLAG_DOUBLE_SIDED,true);
+	material_set_hint(material_2d[version],MATERIAL_HINT_OPAQUE_PRE_PASS,p_opaque_prepass);
+	fixed_material_set_texture(material_2d[version],FIXED_MATERIAL_PARAM_DIFFUSE,get_white_texture());
+	//material cut alpha?
+	return material_2d[version];
+}
+
+RID VisualServer::get_white_texture() {
+
+	if (white_texture.is_valid())
+		return white_texture;
+
+	DVector<uint8_t> wt;
+	wt.resize(16*3);
+	{
+		DVector<uint8_t>::Write w =wt.write();
+		for(int i=0;i<16*3;i++)
+			w[i]=255;
+	}
+	Image white(4,4,0,Image::FORMAT_RGB,wt);
+	white_texture=texture_create();
+	texture_allocate(white_texture,4,4,Image::FORMAT_RGB);
+	texture_set_data(white_texture,white);
+	return white_texture;
+
+}
+
 void VisualServer::_bind_methods() {
 
 

+ 41 - 2
servers/visual_server.h

@@ -56,6 +56,8 @@ class VisualServer : public Object {
 protected:	
 	RID _make_test_cube();
 	RID test_texture;
+	RID white_texture;
+	RID material_2d[16];
 	
 	static VisualServer* (*create_func)();
 	static void _bind_methods();	
@@ -189,6 +191,7 @@ public:
 		MATERIAL_HINT_OPAQUE_PRE_PASS,
 		MATERIAL_HINT_NO_SHADOW,
 		MATERIAL_HINT_NO_DEPTH_DRAW,
+		MATERIAL_HINT_NO_DEPTH_DRAW_FOR_ALPHA,
 		MATERIAL_HINT_MAX
 	};
 
@@ -241,6 +244,7 @@ public:
 		FIXED_MATERIAL_FLAG_USE_ALPHA,
 		FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY,
 		FIXED_MATERIAL_FLAG_USE_POINT_SIZE,
+		FIXED_MATERIAL_FLAG_DISCARD_ALPHA,
 		FIXED_MATERIAL_FLAG_MAX,
 	};
 
@@ -360,7 +364,22 @@ public:
 	virtual void multimesh_set_visible_instances(RID p_multimesh,int p_visible)=0;
 	virtual int multimesh_get_visible_instances(RID p_multimesh) const=0;
 
-		
+	/* IMMEDIATE API */
+
+	virtual RID immediate_create()=0;
+	virtual void immediate_begin(RID p_immediate,PrimitiveType p_rimitive,RID p_texture=RID())=0;
+	virtual void immediate_vertex(RID p_immediate,const Vector3& p_vertex)=0;
+	virtual void immediate_normal(RID p_immediate,const Vector3& p_normal)=0;
+	virtual void immediate_tangent(RID p_immediate,const Plane& p_tangent)=0;
+	virtual void immediate_color(RID p_immediate,const Color& p_color)=0;
+	virtual void immediate_uv(RID p_immediate,const Vector2& tex_uv)=0;
+	virtual void immediate_uv2(RID p_immediate,const Vector2& tex_uv)=0;
+	virtual void immediate_end(RID p_immediate)=0;
+	virtual void immediate_clear(RID p_immediate)=0;
+	virtual void immediate_set_material(RID p_immediate,RID p_material)=0;
+	virtual RID immediate_get_material(RID p_immediate) const=0;
+
+
 	/* PARTICLES API */
 		
 	virtual RID particles_create()=0;
@@ -556,6 +575,8 @@ public:
 	virtual void portal_set_connect_range(RID p_portal, float p_range) =0;
 	virtual float portal_get_connect_range(RID p_portal) const =0;
 
+
+
 	/* CAMERA API */
 	
 	virtual RID camera_create()=0;
@@ -675,6 +696,7 @@ public:
 		ENV_BG_PARAM_CUBEMAP,
 		ENV_BG_PARAM_ENERGY,
 		ENV_BG_PARAM_SCALE,
+		ENV_BG_PARAM_GLOW,
 		ENV_BG_PARAM_MAX
 	};
 
@@ -698,8 +720,17 @@ public:
 	virtual void environment_set_enable_fx(RID p_env,EnvironmentFx p_effect,bool p_enabled)=0;
 	virtual bool environment_is_fx_enabled(RID p_env,EnvironmentFx p_mode) const=0;
 
+	enum EnvironmentFxBlurBlendMode {
+		ENV_FX_BLUR_BLEND_MODE_ADDITIVE,
+		ENV_FX_BLUR_BLEND_MODE_SCREEN,
+		ENV_FX_BLUR_BLEND_MODE_SOFTLIGHT,
+	};
+
 	enum EnvironmentFxParam {
 		ENV_FX_PARAM_GLOW_BLUR_PASSES,
+		ENV_FX_PARAM_GLOW_BLUR_SCALE,
+		ENV_FX_PARAM_GLOW_BLUR_STRENGTH,
+		ENV_FX_PARAM_GLOW_BLUR_BLEND_MODE,
 		ENV_FX_PARAM_GLOW_BLOOM,
 		ENV_FX_PARAM_GLOW_BLOOM_TRESHOLD,
 		ENV_FX_PARAM_DOF_BLUR_PASSES,
@@ -756,12 +787,13 @@ public:
 		INSTANCE_NONE,
 		INSTANCE_MESH,
 		INSTANCE_MULTIMESH,
+		INSTANCE_IMMEDIATE,
 		INSTANCE_PARTICLES,
 		INSTANCE_LIGHT,
 		INSTANCE_ROOM,
 		INSTANCE_PORTAL,
 		
-		INSTANCE_GEOMETRY_MASK=(1<<INSTANCE_MESH)|(1<<INSTANCE_MULTIMESH)|(1<<INSTANCE_PARTICLES)
+		INSTANCE_GEOMETRY_MASK=(1<<INSTANCE_MESH)|(1<<INSTANCE_MULTIMESH)|(1<<INSTANCE_IMMEDIATE)|(1<<INSTANCE_PARTICLES)
 	};
 	
 
@@ -931,6 +963,12 @@ public:
 	};
 
 	virtual int get_render_info(RenderInfo p_info)=0;
+
+
+	/* Materials for 2D on 3D */
+
+
+	RID material_2d_get(bool p_shaded, bool p_transparent, bool p_cut_alpha,bool p_opaque_prepass);
 	
 
 	/* TESTING */
@@ -938,6 +976,7 @@ public:
 	virtual RID get_test_cube()=0;
 
 	virtual RID get_test_texture();
+	virtual RID get_white_texture();
 
 	virtual RID make_sphere_mesh(int p_lats,int p_lons,float p_radius);
 

+ 1 - 1
tools/editor/editor_import_export.cpp

@@ -994,7 +994,7 @@ Error EditorExportPlatform::save_pack(FileAccess *dst,bool p_make_bundles) {
 	return OK;
 }
 
-Error EditorExportPlatformPC::export_project(const String& p_path,bool p_debug,const String& p_password) {
+Error EditorExportPlatformPC::export_project(const String& p_path, bool p_debug, bool p_dumb) {
 
 
 

+ 3 - 3
tools/editor/editor_import_export.h

@@ -130,14 +130,14 @@ public:
 	virtual int get_device_count() const { return 0; }
 	virtual String get_device_name(int p_device) const { return ""; }
 	virtual String get_device_info(int p_device) const { return ""; }
-	virtual Error run(int p_device) { return OK; }
+	virtual Error run(int p_device,bool p_dumb=false) { return OK; }
 
 	virtual bool can_export(String *r_error=NULL) const=0;
 
 
 	virtual bool requieres_password(bool p_debug) const { return false; }
 	virtual String get_binary_extension() const=0;
-	virtual Error export_project(const String& p_path,bool p_debug,const String& p_password="")=0;
+	virtual Error export_project(const String& p_path,bool p_debug,bool p_dumb=false)=0;
 
 	EditorExportPlatform() {};
 };
@@ -187,7 +187,7 @@ public:
 	virtual ImageCompression get_image_compression() const { return IMAGE_COMPRESSION_BC; }
 
 	virtual String get_binary_extension() const { return binary_extension; }
-	virtual Error export_project(const String& p_path,bool p_debug,const String& p_password="");
+	virtual Error export_project(const String& p_path,bool p_debug,bool p_dumb=false);
 	virtual void set_release_binary32(const String& p_binary) { release_binary32=p_binary; }
 	virtual void set_debug_binary32(const String& p_binary) { debug_binary32=p_binary; }
 	virtual void set_release_binary64(const String& p_binary) { release_binary64=p_binary; }

+ 4 - 3
tools/editor/editor_node.cpp

@@ -2204,8 +2204,9 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
 		} break;
 		case RUN_DEPLOY_DUMB_CLIENTS: {
 
-		bool ischecked = fileserver_menu->get_popup()->is_item_checked( fileserver_menu->get_popup()->get_item_index(RUN_DEPLOY_DUMB_CLIENTS));
-		fileserver_menu->get_popup()->set_item_checked( fileserver_menu->get_popup()->get_item_index(RUN_DEPLOY_DUMB_CLIENTS),!ischecked);
+			bool ischecked = fileserver_menu->get_popup()->is_item_checked( fileserver_menu->get_popup()->get_item_index(RUN_DEPLOY_DUMB_CLIENTS));
+			fileserver_menu->get_popup()->set_item_checked( fileserver_menu->get_popup()->get_item_index(RUN_DEPLOY_DUMB_CLIENTS),!ischecked);
+			run_native->set_deploy_dumb(!ischecked);
 
 		} break;
 		case SETTINGS_UPDATE_ALWAYS: {
@@ -3612,7 +3613,7 @@ EditorNode::EditorNode() {
 	p->set_item_tooltip(p->get_item_index(RUN_FILE_SERVER),"Enable/Disable the File Server.");
 	p->add_separator();
 	p->add_check_item("Deploy Dumb Clients",RUN_DEPLOY_DUMB_CLIENTS);
-	p->set_item_checked( p->get_item_index(RUN_DEPLOY_DUMB_CLIENTS),true );
+	//p->set_item_checked( p->get_item_index(RUN_DEPLOY_DUMB_CLIENTS),true );
 	p->set_item_tooltip(p->get_item_index(RUN_DEPLOY_DUMB_CLIENTS),"Deploy dumb clients when the File Server is active.");
 	p->connect("item_pressed",this,"_menu_option");
 

+ 13 - 1
tools/editor/editor_run_native.cpp

@@ -101,7 +101,7 @@ void EditorRunNative::_run_native(int p_idx,const String& p_platform) {
 
 	Ref<EditorExportPlatform> eep = EditorImportExport::get_singleton()->get_export_platform(p_platform);
 	ERR_FAIL_COND(eep.is_null());
-	eep->run(p_idx);
+	eep->run(p_idx,deploy_dumb);
 }
 
 void EditorRunNative::_bind_methods() {
@@ -109,8 +109,20 @@ void EditorRunNative::_bind_methods() {
 	ObjectTypeDB::bind_method("_run_native",&EditorRunNative::_run_native);
 }
 
+void EditorRunNative::set_deploy_dumb(bool p_enabled) {
+
+	deploy_dumb=p_enabled;
+}
+
+bool EditorRunNative::is_deploy_dumb_enabled() const{
+
+	return deploy_dumb;
+}
+
+
 EditorRunNative::EditorRunNative()
 {
 	set_process(true);
 	first=true;
+	deploy_dumb=false;
 }

+ 4 - 0
tools/editor/editor_run_native.h

@@ -38,6 +38,7 @@ class EditorRunNative : public HBoxContainer {
 
 	Map<StringName,MenuButton*> menus;
 	bool first;
+	bool deploy_dumb;
 
 	void _run_native(int p_idx,const String& p_platform);
 
@@ -46,6 +47,9 @@ protected:
 	static void _bind_methods();
 	void _notification(int p_what);
 public:
+
+	void set_deploy_dumb(bool p_enabled);
+	bool is_deploy_dumb_enabled() const;
 	EditorRunNative();
 };
 

+ 21 - 0
tools/editor/fileserver/editor_file_server.cpp

@@ -317,12 +317,33 @@ EditorFileServer::EditorFileServer() {
 	cmd=CMD_NONE;
 	thread=Thread::create(_thread_start,this);
 
+	List<IP_Address> local_ip;
+	IP::get_singleton()->get_local_addresses(&local_ip);
 	EDITOR_DEF("file_server/port",6010);
+	String lip;
+	String hint;
+	for(List<IP_Address>::Element *E=local_ip.front();E;E=E->next()) {
+
+		String ip = E->get();
+		if (ip=="127.0.0.1")
+			continue;
+
+		if (lip!="")
+			lip=ip;
+		if (hint!="")
+			hint+=",";
+		hint+=ip;
+
+	}
+
+	EDITOR_DEF("file_server/host",lip);
+	EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING,"file_server/host",PROPERTY_HINT_ENUM,hint));
 	EDITOR_DEF("file_server/password","");
 }
 
 EditorFileServer::~EditorFileServer() {
 
+
 	quit=true;
 	Thread::wait_to_finish(thread);
 	memdelete(wait_mutex);

BIN
tools/editor/icons/icon_animated_sprite_3d.png


BIN
tools/editor/icons/icon_sprite_3d.png


+ 1 - 1
tools/editor/project_export.cpp

@@ -449,7 +449,7 @@ Error ProjectExportDialog::export_platform(const String& p_platform, const Strin
 		ERR_PRINT("Invalid platform for export");
 		return ERR_INVALID_PARAMETER;
 	}
-	Error err = exporter->export_project(p_path,p_debug,p_password);
+	Error err = exporter->export_project(p_path,p_debug);
 	if (err!=OK) {
 		error->set_text("Error exporting project!");
 		error->popup_centered(Size2(300,70));;