Prechádzať zdrojové kódy

back buffer copy node, to improve on texscreen()

back buffer copy node and respective demo
Juan Linietsky 10 rokov pred
rodič
commit
650e13f3cd

+ 4 - 0
demos/2d/isometric_light/engine.cfg

@@ -9,6 +9,10 @@ down=[key(S), key(Down)]
 left=[key(Left), key(A)]
 right=[key(Right), key(D)]
 
+[rasterizer]
+
+shadow_filter=0
+
 [render]
 
 default_clear_color=#ff000000

BIN
demos/2d/sprite_shaders/sprite_shaders.scn


BIN
demos/2d/texscreen/bubble.png


+ 17 - 0
demos/2d/texscreen/bubbles.gd

@@ -0,0 +1,17 @@
+
+extends Control
+
+# member variables here, example:
+# var a=2
+# var b="textvar"
+
+const MAX_BUBBLES=10
+
+func _ready():
+	# Initialization here
+	for i in range(MAX_BUBBLES):
+		var bubble = preload("res://lens.scn").instance()
+		add_child(bubble)
+	pass
+
+

BIN
demos/2d/texscreen/bubbles.scn


BIN
demos/2d/texscreen/burano.png


+ 4 - 0
demos/2d/texscreen/engine.cfg

@@ -0,0 +1,4 @@
+[application]
+
+name="Glass Bubbles (Texscreen)"
+main_scene="res://bubbles.scn"

+ 37 - 0
demos/2d/texscreen/lens.gd

@@ -0,0 +1,37 @@
+
+extends BackBufferCopy
+
+# member variables here, example:
+# var a=2
+# var b="textvar"
+const MOTION_SPEED=150
+
+var vsize;
+var dir;
+
+func _process(delta):
+	var pos = get_pos() + dir * delta * MOTION_SPEED
+	
+	if (pos.x<0):
+		dir.x=abs(dir.x)
+	elif (pos.x>vsize.x):
+		dir.x=-abs(dir.x)
+
+	if (pos.y<0):
+		dir.y=abs(dir.y)
+	elif (pos.y>vsize.y):
+		dir.y=-abs(dir.y)
+		
+	set_pos(pos)
+
+func _ready():
+	vsize = get_viewport_rect().size
+	var pos = vsize * Vector2(randf(),randf());
+	set_pos(pos);
+	dir = Vector2(randf()*2.0-1,randf()*2.0-1).normalized()
+	set_process(true)
+	
+	# Initialization here
+	pass
+
+

BIN
demos/2d/texscreen/lens.scn


+ 54 - 8
drivers/gles2/rasterizer_gles2.cpp

@@ -989,8 +989,14 @@ void RasterizerGLES2::texture_set_data(RID p_texture,const Image& p_image,VS::Cu
 
 	if (texture->flags&VS::TEXTURE_FLAG_MIPMAPS && !texture->ignore_mipmaps)
 		glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,use_fast_texture_filter?GL_LINEAR_MIPMAP_NEAREST:GL_LINEAR_MIPMAP_LINEAR);
-	else
-		glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+	else {
+		if (texture->flags&VS::TEXTURE_FLAG_FILTER) {
+			glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+		} else {
+			glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+
+		}
+	}
 
 	if (texture->flags&VS::TEXTURE_FLAG_FILTER) {
 
@@ -1283,8 +1289,14 @@ void RasterizerGLES2::texture_set_flags(RID p_texture,uint32_t p_flags) {
 
 	if (texture->flags&VS::TEXTURE_FLAG_MIPMAPS && !texture->ignore_mipmaps)
 		glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,use_fast_texture_filter?GL_LINEAR_MIPMAP_NEAREST:GL_LINEAR_MIPMAP_LINEAR);
-	else
-		glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+	else{
+		if (texture->flags&VS::TEXTURE_FLAG_FILTER) {
+			glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+		} else {
+			glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+
+		}
+	}
 
 	if (texture->flags&VS::TEXTURE_FLAG_FILTER) {
 
@@ -8554,7 +8566,7 @@ RID RasterizerGLES2::canvas_light_shadow_buffer_create(int p_width) {
 	//printf("errnum: %x\n",status);
 #ifdef GLEW_ENABLED
 	if (read_depth_supported) {
-		glDrawBuffer(GL_BACK);
+		//glDrawBuffer(GL_BACK);
 	}
 #endif
 	glBindFramebuffer(GL_FRAMEBUFFER, base_framebuffer);
@@ -8563,7 +8575,7 @@ RID RasterizerGLES2::canvas_light_shadow_buffer_create(int p_width) {
 
 #ifdef GLEW_ENABLED
 	if (read_depth_supported) {
-		glDrawBuffer(GL_BACK);
+		//glDrawBuffer(GL_BACK);
 	}
 #endif
 
@@ -9138,6 +9150,40 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
 			}
 		}
 
+		if (ci->copy_back_buffer && framebuffer.active && framebuffer.scale==1) {
+
+			Rect2 rect;
+			int x,y,w,h;
+
+			if (ci->copy_back_buffer->full) {
+
+				x = viewport.x;
+				y = window_size.height-(viewport.height+viewport.y);
+				w = viewport.width;
+				h = viewport.height;
+			} else {
+				x = viewport.x+ci->copy_back_buffer->screen_rect.pos.x;
+				y = window_size.height-(viewport.y+ci->copy_back_buffer->screen_rect.pos.y+ci->copy_back_buffer->screen_rect.size.y);
+				w = ci->copy_back_buffer->screen_rect.size.x;
+				h = ci->copy_back_buffer->screen_rect.size.y;
+			}
+			glActiveTexture(GL_TEXTURE0+max_texture_units-1);
+			glBindTexture(GL_TEXTURE_2D,framebuffer.sample_color);
+
+#ifdef GLEW_ENABLED
+			glReadBuffer(GL_COLOR_ATTACHMENT0);
+#endif
+			glCopyTexSubImage2D(GL_TEXTURE_2D,0,x,y,x,y,w,h);
+//			if (current_clip) {
+//			//	print_line(" a clip ");
+//			}
+
+			canvas_texscreen_used=true;
+			glActiveTexture(GL_TEXTURE0);
+		}
+
+
+
 
 		//begin rect
 		CanvasItem *material_owner = ci->material_owner?ci->material_owner:ci;
@@ -9904,7 +9950,7 @@ bool RasterizerGLES2::ShadowBuffer::init(int p_size,bool p_use_depth) {
 	//printf("errnum: %x\n",status);
 #ifdef GLEW_ENABLED
 	if (p_use_depth) {
-		glDrawBuffer(GL_BACK);
+		//glDrawBuffer(GL_BACK);
 	}
 #endif
 	glBindFramebuffer(GL_FRAMEBUFFER, 0);
@@ -9913,7 +9959,7 @@ bool RasterizerGLES2::ShadowBuffer::init(int p_size,bool p_use_depth) {
 
 #ifdef GLEW_ENABLED
 	if (p_use_depth) {
-		glDrawBuffer(GL_BACK);
+		//glDrawBuffer(GL_BACK);
 	}
 #endif
 

+ 75 - 0
scene/2d/back_buffer_copy.cpp

@@ -0,0 +1,75 @@
+#include "back_buffer_copy.h"
+
+void BackBufferCopy::_update_copy_mode() {
+
+	switch(copy_mode) {
+
+		case COPY_MODE_DISALED: {
+
+			VS::get_singleton()->canvas_item_set_copy_to_backbuffer(get_canvas_item(),false,Rect2());
+		} break;
+		case COPY_MODE_RECT: {
+
+			VS::get_singleton()->canvas_item_set_copy_to_backbuffer(get_canvas_item(),true,rect);
+		} break;
+		case COPY_MODE_VIEWPORT: {
+
+			VS::get_singleton()->canvas_item_set_copy_to_backbuffer(get_canvas_item(),true,Rect2());
+
+		} break;
+
+	}
+}
+
+Rect2 BackBufferCopy::get_item_rect() const {
+
+	return rect;
+}
+
+void BackBufferCopy::set_rect(const Rect2& p_rect) {
+
+	rect=p_rect;
+	_update_copy_mode();
+}
+
+Rect2 BackBufferCopy::get_rect() const{
+	return rect;
+}
+
+void BackBufferCopy::set_copy_mode(CopyMode p_mode){
+
+	copy_mode=p_mode;
+	_update_copy_mode();
+}
+BackBufferCopy::CopyMode BackBufferCopy::get_copy_mode() const{
+
+	return copy_mode;
+}
+
+
+void BackBufferCopy::_bind_methods() {
+
+	ObjectTypeDB::bind_method(_MD("set_rect","rect"),&BackBufferCopy::set_rect);
+	ObjectTypeDB::bind_method(_MD("get_rect"),&BackBufferCopy::get_rect);
+
+	ObjectTypeDB::bind_method(_MD("set_copy_mode","copy_mode"),&BackBufferCopy::set_copy_mode);
+	ObjectTypeDB::bind_method(_MD("get_copy_mode"),&BackBufferCopy::get_copy_mode);
+
+	ADD_PROPERTY( PropertyInfo(Variant::INT,"copy_mode",PROPERTY_HINT_ENUM,"Disabled,Rect,Viewport"),_SCS("set_copy_mode"),_SCS("get_copy_mode"));
+	ADD_PROPERTY( PropertyInfo(Variant::RECT2,"rect"),_SCS("set_rect"),_SCS("get_rect"));
+
+	BIND_CONSTANT( COPY_MODE_DISALED );
+	BIND_CONSTANT( COPY_MODE_RECT );
+	BIND_CONSTANT( COPY_MODE_VIEWPORT );
+
+}
+
+BackBufferCopy::BackBufferCopy(){
+
+	rect=Rect2(-100,-100,200,200);
+	copy_mode=COPY_MODE_RECT;
+	_update_copy_mode();
+}
+BackBufferCopy::~BackBufferCopy(){
+
+}

+ 41 - 0
scene/2d/back_buffer_copy.h

@@ -0,0 +1,41 @@
+#ifndef BACKBUFFERCOPY_H
+#define BACKBUFFERCOPY_H
+
+#include "scene/2d/node_2d.h"
+
+class BackBufferCopy : public Node2D {
+	OBJ_TYPE( BackBufferCopy,Node2D);
+public:
+	enum CopyMode {
+		COPY_MODE_DISALED,
+		COPY_MODE_RECT,
+		COPY_MODE_VIEWPORT
+	};
+private:
+
+	Rect2 rect;
+	CopyMode copy_mode;
+
+	void _update_copy_mode();
+
+protected:
+
+	static void _bind_methods();
+
+public:
+
+	void set_rect(const Rect2& p_rect);
+	Rect2 get_rect() const;
+
+	void set_copy_mode(CopyMode p_mode);
+	CopyMode get_copy_mode() const;
+
+	Rect2 BackBufferCopy::get_item_rect() const;
+
+	BackBufferCopy();
+	~BackBufferCopy();
+};
+
+VARIANT_ENUM_CAST(BackBufferCopy::CopyMode);
+
+#endif // BACKBUFFERCOPY_H

+ 0 - 1
scene/2d/canvas_item.cpp

@@ -44,7 +44,6 @@ bool CanvasItemMaterial::_set(const StringName& p_name, const Variant& p_value)
 		return true;
 	} else if (p_name==SceneStringNames::get_singleton()->shader_unshaded) {
 		set_unshaded(p_value);
-		print_line("set unshaded");
 		return true;
 	} else {
 

+ 2 - 0
scene/register_scene_types.cpp

@@ -86,6 +86,7 @@
 #include "scene/2d/sprite.h"
 #include "scene/2d/animated_sprite.h"
 #include "scene/2d/polygon_2d.h"
+#include "scene/2d/back_buffer_copy.h"
 
 
 #include "scene/2d/visibility_notifier_2d.h"
@@ -481,6 +482,7 @@ void register_scene_types() {
 	ObjectTypeDB::register_type<LightOccluder2D>();
 	ObjectTypeDB::register_type<OccluderPolygon2D>();
 	ObjectTypeDB::register_type<YSort>();
+	ObjectTypeDB::register_type<BackBufferCopy>();
 
 	ObjectTypeDB::set_type_enabled("CollisionShape2D",false);
 	ObjectTypeDB::set_type_enabled("CollisionPolygon2D",false);

+ 8 - 2
servers/visual/rasterizer.h

@@ -769,6 +769,12 @@ public:
 		mutable Rect2 rect;
 		CanvasItem*next;
 		CanvasItemMaterial* material;
+		struct CopyBackBuffer {
+			Rect2 rect;
+			Rect2 screen_rect;
+			bool full;
+		};
+		CopyBackBuffer *copy_back_buffer;
 
 
 		float final_opacity;
@@ -904,8 +910,8 @@ public:
 		}
 
 		void clear() { for (int i=0;i<commands.size();i++) memdelete( commands[i] ); commands.clear(); clip=false; rect_dirty=true; final_clip_owner=NULL;  material_owner=NULL;}
-		CanvasItem() { light_mask=1; vp_render=NULL; next=NULL; final_clip_owner=NULL; clip=false; final_opacity=1;  blend_mode=VS::MATERIAL_BLEND_MODE_MIX; visible=true; rect_dirty=true; custom_rect=false; ontop=true; material_owner=NULL; material=NULL; }
-		virtual ~CanvasItem() { clear(); }
+		CanvasItem() { light_mask=1; vp_render=NULL; next=NULL; final_clip_owner=NULL; clip=false; final_opacity=1;  blend_mode=VS::MATERIAL_BLEND_MODE_MIX; visible=true; rect_dirty=true; custom_rect=false; ontop=true; material_owner=NULL; material=NULL; copy_back_buffer=NULL; }
+		virtual ~CanvasItem() { clear(); if (copy_back_buffer) memdelete(copy_back_buffer); }
 	};
 
 

+ 26 - 1
servers/visual/visual_server_raster.cpp

@@ -3765,6 +3765,27 @@ void VisualServerRaster::canvas_item_set_z_as_relative_to_parent(RID p_item, boo
 
 }
 
+void VisualServerRaster::canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable, const Rect2& p_rect) {
+
+	VS_CHANGED;
+	CanvasItem *canvas_item = canvas_item_owner.get( p_item );
+	ERR_FAIL_COND(!canvas_item);
+	if (bool(canvas_item->copy_back_buffer!=NULL) !=p_enable) {
+		if (p_enable) {
+			canvas_item->copy_back_buffer = memnew( Rasterizer::CanvasItem::CopyBackBuffer );
+		} else {
+			memdelete(canvas_item->copy_back_buffer);
+			canvas_item->copy_back_buffer=NULL;
+		}
+	}
+
+	if (p_enable) {
+		canvas_item->copy_back_buffer->rect=p_rect;
+		canvas_item->copy_back_buffer->full=p_rect==Rect2();
+	}
+
+}
+
 void VisualServerRaster::canvas_item_set_use_parent_material(RID p_item, bool p_enable) {
 
 	VS_CHANGED;
@@ -6766,8 +6787,12 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat
 		_render_canvas_item(child_items[i],xform,p_clip_rect,opacity,p_z,z_list,z_last_list,(CanvasItem*)ci->final_clip_owner,p_material_owner);
 	}
 
+	if (ci->copy_back_buffer) {
+
+		ci->copy_back_buffer->screen_rect = xform.xform(ci->copy_back_buffer->rect).clip(p_clip_rect);
+	}
 
-	if ((!ci->commands.empty() && p_clip_rect.intersects(global_rect)) || ci->vp_render) {
+	if ((!ci->commands.empty() && p_clip_rect.intersects(global_rect)) || ci->vp_render || ci->copy_back_buffer) {
 		//something to draw?
 		ci->final_transform=xform;
 		ci->final_opacity=opacity * ci->self_opacity;

+ 1 - 0
servers/visual/visual_server_raster.h

@@ -1149,6 +1149,7 @@ public:
 	virtual void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable);
 	virtual void canvas_item_set_z(RID p_item, int p_z);
 	virtual void canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable);
+	virtual void canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable,const Rect2& p_rect);
 
 	virtual void canvas_item_set_material(RID p_item, RID p_material);
 	virtual void canvas_item_set_use_parent_material(RID p_item, bool p_enable);

+ 2 - 0
servers/visual/visual_server_wrap_mt.h

@@ -1138,6 +1138,8 @@ public:
 	FUNC2(canvas_item_set_sort_children_by_y,RID,bool);
 	FUNC2(canvas_item_set_z,RID,int);
 	FUNC2(canvas_item_set_z_as_relative_to_parent,RID,bool);
+	FUNC3(canvas_item_set_copy_to_backbuffer,RID,bool,const Rect2&);
+
 
 	FUNC2(canvas_item_set_material,RID, RID );
 

+ 1 - 0
servers/visual_server.h

@@ -994,6 +994,7 @@ public:
 	virtual void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable)=0;
 	virtual void canvas_item_set_z(RID p_item, int p_z)=0;
 	virtual void canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable)=0;
+	virtual void canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable,const Rect2& p_rect)=0;
 
 	virtual void canvas_item_clear(RID p_item)=0;
 	virtual void canvas_item_raise(RID p_item)=0;

BIN
tools/editor/icons/icon_back_buffer_copy.png