Browse Source

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 years ago
parent
commit
6f0b4678e2
50 changed files with 2261 additions and 93 deletions
  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));;