Browse Source

Makes screen texture work in GLES2 (2D for now), fixes #23604

Juan Linietsky 6 years ago
parent
commit
7fa41f17a6

+ 72 - 2
drivers/gles2/rasterizer_canvas_gles2.cpp

@@ -1162,7 +1162,65 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
 
 void RasterizerCanvasGLES2::_copy_texscreen(const Rect2 &p_rect) {
 
-	// This isn't really working yet, so disabling for now.
+	if (storage->frame.current_rt->copy_screen_effect.color == 0) {
+		ERR_EXPLAIN("Can't use screen texture copying in a render target configured without copy buffers");
+		ERR_FAIL();
+	}
+
+	glDisable(GL_BLEND);
+
+	state.canvas_texscreen_used = true;
+
+	Vector2 wh(storage->frame.current_rt->width, storage->frame.current_rt->height);
+
+	Color copy_section(p_rect.position.x / wh.x, p_rect.position.y / wh.y, p_rect.size.x / wh.x, p_rect.size.y / wh.y);
+
+	if (p_rect != Rect2()) {
+		storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_COPY_SECTION, true);
+	}
+
+	glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->copy_screen_effect.fbo);
+	glActiveTexture(GL_TEXTURE0);
+	glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color);
+
+	glClearColor(1, 0, 1, 1);
+	glClear(GL_COLOR_BUFFER_BIT);
+
+	storage->shaders.copy.bind();
+	storage->shaders.copy.set_uniform(CopyShaderGLES2::COPY_SECTION, copy_section);
+
+	const Vector2 vertpos[4] = {
+		Vector2(-1, -1),
+		Vector2(-1, 1),
+		Vector2(1, 1),
+		Vector2(1, -1),
+	};
+
+	const Vector2 uvpos[4] = {
+		Vector2(0, 0),
+		Vector2(0, 1),
+		Vector2(1, 1),
+		Vector2(1, 0)
+	};
+
+	const int indexpos[6] = {
+		0, 1, 2,
+		2, 3, 0
+	};
+
+	_draw_polygon(indexpos, 6, 4, vertpos, uvpos, NULL, false);
+
+	storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_COPY_SECTION, false);
+
+	glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); //back to front
+
+	// back to canvas, force rebind
+	state.using_texture_rect = false;
+	state.canvas_shader.bind();
+	_bind_canvas_texture(state.current_tex, state.current_normal);
+	_set_uniforms();
+
+	glEnable(GL_BLEND);
 }
 
 void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light, const Transform2D &p_base_transform) {
@@ -1178,6 +1236,7 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons
 	state.current_tex = RID();
 	state.current_tex_ptr = NULL;
 	state.current_normal = RID();
+	state.canvas_texscreen_used = false;
 
 	glActiveTexture(GL_TEXTURE0);
 	glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
@@ -1265,7 +1324,18 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons
 
 			if (shader_ptr) {
 				if (shader_ptr->canvas_item.uses_screen_texture) {
-					_copy_texscreen(Rect2());
+					if (!state.canvas_texscreen_used) {
+						//copy if not copied before
+						_copy_texscreen(Rect2());
+
+						// blend mode will have been enabled so make sure we disable it again later on
+						//last_blend_mode = last_blend_mode != RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_DISABLED ? last_blend_mode : -1;
+					}
+
+					if (storage->frame.current_rt->copy_screen_effect.color) {
+						glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4);
+						glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->copy_screen_effect.color);
+					}
 				}
 
 				if (shader_ptr != shader_cache) {

+ 10 - 2
drivers/gles2/rasterizer_storage_gles2.cpp

@@ -4251,7 +4251,8 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) {
 	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
 	// copy texscreen buffers
-	{
+	if (!(rt->flags[RasterizerStorage::RENDER_TARGET_NO_SAMPLING])) {
+
 		int w = rt->width;
 		int h = rt->height;
 
@@ -4259,10 +4260,17 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) {
 		glBindTexture(GL_TEXTURE_2D, rt->copy_screen_effect.color);
 
 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 
 		glGenFramebuffers(1, &rt->copy_screen_effect.fbo);
 		glBindFramebuffer(GL_FRAMEBUFFER, rt->copy_screen_effect.fbo);
-		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0);
+		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->copy_screen_effect.color, 0);
+
+		glClearColor(0, 0, 0, 0);
+		glClear(GL_COLOR_BUFFER_BIT);
 
 		GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
 		if (status != GL_FRAMEBUFFER_COMPLETE) {

+ 2 - 0
drivers/gles2/shader_gles2.h

@@ -465,6 +465,8 @@ public:
 	void set_custom_shader(uint32_t p_code_id);
 	void free_custom_shader(uint32_t p_code_id);
 
+	uint32_t get_version_key() const { return conditional_version.version; }
+
 	void set_uniform_default(int p_idx, const Variant &p_value) {
 
 		if (p_value.get_type() == Variant::NIL) {

+ 1 - 1
drivers/gles2/shaders/copy.glsl

@@ -29,7 +29,7 @@ varying vec2 uv_interp;
 varying vec2 uv2_interp;
 
 #ifdef USE_COPY_SECTION
-uniform vec4 copy_section;
+uniform highp vec4 copy_section;
 #endif
 
 void main() {