Bläddra i källkod

Merge pull request #18677 from BastiaanOlij/add_no_blend

Add no-blend canvas item render_mode
Juan Linietsky 7 år sedan
förälder
incheckning
35322c0678

+ 3 - 0
doc/classes/CanvasItemMaterial.xml

@@ -36,6 +36,9 @@
 		<constant name="BLEND_MODE_PREMULT_ALPHA" value="4" enum="BlendMode">
 			Mix blending mode. Colors are assumed to be premultiplied by the alpha (opacity) value.
 		</constant>
+		<constant name="BLEND_MODE_DISABLED" value="5" enum="BlendMode">
+			Disable blending mode. Colors including alpha are written as is. Only applicable for render targets with a transparent background. No lighting will be applied.
+		</constant>
 		<constant name="LIGHT_MODE_NORMAL" value="0" enum="LightMode">
 			Render the material using both light and non-light sensitive material properties.
 		</constant>

+ 19 - 0
drivers/gles3/rasterizer_canvas_gles3.cpp

@@ -1210,6 +1210,9 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons
 				if (shader_ptr->canvas_item.uses_screen_texture && !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 != RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_DISABLED ? last_blend_mode : -1;
 				}
 
 				if (shader_ptr != shader_cache) {
@@ -1281,14 +1284,30 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons
 		}
 
 		int blend_mode = shader_cache ? shader_cache->canvas_item.blend_mode : RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX;
+		if (blend_mode == RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_DISABLED && (!storage->frame.current_rt || !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT])) {
+			blend_mode = RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX;
+		}
 		bool unshaded = shader_cache && (shader_cache->canvas_item.light_mode == RasterizerStorageGLES3::Shader::CanvasItem::LIGHT_MODE_UNSHADED || blend_mode != RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX);
 		bool reclip = false;
 
 		if (last_blend_mode != blend_mode) {
+			if (last_blend_mode == RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_DISABLED) {
+				// re-enable it
+				glEnable(GL_BLEND);
+			} else if (blend_mode == RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_DISABLED) {
+				// disable it
+				glDisable(GL_BLEND);
+			}
 
 			switch (blend_mode) {
 
+				case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_DISABLED: {
+
+					// nothing to do here
+
+				} break;
 				case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX: {
+
 					glBlendEquation(GL_FUNC_ADD);
 					if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
 						glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

+ 1 - 0
drivers/gles3/rasterizer_storage_gles3.cpp

@@ -1615,6 +1615,7 @@ void RasterizerStorageGLES3::_update_shader(Shader *p_shader) const {
 			shaders.actions_canvas.render_mode_values["blend_sub"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_SUB);
 			shaders.actions_canvas.render_mode_values["blend_mul"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_MUL);
 			shaders.actions_canvas.render_mode_values["blend_premul_alpha"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_PMALPHA);
+			shaders.actions_canvas.render_mode_values["blend_disabled"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_DISABLED);
 
 			shaders.actions_canvas.render_mode_values["unshaded"] = Pair<int *, int>(&p_shader->canvas_item.light_mode, Shader::CanvasItem::LIGHT_MODE_UNSHADED);
 			shaders.actions_canvas.render_mode_values["light_only"] = Pair<int *, int>(&p_shader->canvas_item.light_mode, Shader::CanvasItem::LIGHT_MODE_LIGHT_ONLY);

+ 1 - 0
drivers/gles3/rasterizer_storage_gles3.h

@@ -420,6 +420,7 @@ public:
 				BLEND_MODE_SUB,
 				BLEND_MODE_MUL,
 				BLEND_MODE_PMALPHA,
+				BLEND_MODE_DISABLED,
 			};
 
 			int blend_mode;

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

@@ -94,6 +94,7 @@ void CanvasItemMaterial::_update_shader() {
 		case BLEND_MODE_SUB: code += "blend_sub"; break;
 		case BLEND_MODE_MUL: code += "blend_mul"; break;
 		case BLEND_MODE_PREMULT_ALPHA: code += "blend_premul_alpha"; break;
+		case BLEND_MODE_DISABLED: code += "blend_disabled"; break;
 	}
 
 	switch (light_mode) {
@@ -1105,6 +1106,7 @@ void CanvasItem::_bind_methods() {
 	BIND_ENUM_CONSTANT(BLEND_MODE_SUB);
 	BIND_ENUM_CONSTANT(BLEND_MODE_MUL);
 	BIND_ENUM_CONSTANT(BLEND_MODE_PREMULT_ALPHA);
+	BIND_ENUM_CONSTANT(BLEND_MODE_DISABLED);
 
 	BIND_CONSTANT(NOTIFICATION_TRANSFORM_CHANGED);
 	BIND_CONSTANT(NOTIFICATION_DRAW);

+ 4 - 2
scene/2d/canvas_item.h

@@ -54,7 +54,8 @@ public:
 		BLEND_MODE_ADD,
 		BLEND_MODE_SUB,
 		BLEND_MODE_MUL,
-		BLEND_MODE_PREMULT_ALPHA
+		BLEND_MODE_PREMULT_ALPHA,
+		BLEND_MODE_DISABLED
 	};
 
 	enum LightMode {
@@ -145,7 +146,8 @@ public:
 		BLEND_MODE_ADD,
 		BLEND_MODE_SUB,
 		BLEND_MODE_MUL,
-		BLEND_MODE_PREMULT_ALPHA
+		BLEND_MODE_PREMULT_ALPHA,
+		BLEND_MODE_DISABLED
 	};
 
 private:

+ 1 - 0
servers/visual/shader_types.cpp

@@ -231,6 +231,7 @@ ShaderTypes::ShaderTypes() {
 	shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("blend_sub");
 	shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("blend_mul");
 	shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("blend_premul_alpha");
+	shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("blend_disabled");
 
 	shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("unshaded");
 	shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("light_only");