[Bf-blender-cvs] [177623dd404] master: Implement Stencil Mask Drawing for Texture Painting

Jeroen Bakker noreply at git.blender.org
Fri Mar 22 08:22:38 CET 2019


Commit: 177623dd40431b25b34fcfea368024eb66767228
Author: Jeroen Bakker
Date:   Thu Mar 21 16:44:01 2019 +0100
Branches: master
https://developer.blender.org/rB177623dd40431b25b34fcfea368024eb66767228

Implement Stencil Mask Drawing for Texture Painting

Stencil mask drawing was not implemented yet. This commit will implement this for texture painting.
It brings the state back to how it was for B279.

Reviewed By: fclem

Maniphest Tasks: T58727

Differential Revision: https://developer.blender.org/D4570

===================================================================

M	source/blender/draw/intern/draw_cache_impl_mesh.c
M	source/blender/draw/modes/paint_texture_mode.c
M	source/blender/draw/modes/shaders/paint_texture_frag.glsl
M	source/blender/draw/modes/shaders/paint_texture_vert.glsl
M	source/blender/gpu/GPU_vertex_format.h
M	source/blender/makesrna/intern/rna_mesh.c

===================================================================

diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c
index 89972d03758..c00a639028f 100644
--- a/source/blender/draw/intern/draw_cache_impl_mesh.c
+++ b/source/blender/draw/intern/draw_cache_impl_mesh.c
@@ -237,6 +237,7 @@ typedef struct MeshRenderData {
 			MLoopUV **uv;
 			int       uv_len;
 			int       uv_active;
+			int       uv_mask_active;
 
 			MLoopCol **vcol;
 			int        vcol_len;
@@ -389,6 +390,17 @@ static void mesh_cd_calc_active_uv_layer(
 	}
 }
 
+static void mesh_cd_calc_active_mask_uv_layer(
+        const Mesh *me, ushort cd_lused[CD_NUMTYPES])
+{
+	const CustomData *cd_ldata = (me->edit_mesh) ? &me->edit_mesh->bm->ldata : &me->ldata;
+
+	int layer = CustomData_get_stencil_layer(cd_ldata, CD_MLOOPUV);
+	if (layer != -1) {
+		cd_lused[CD_MLOOPUV] |= (1 << layer);
+	}
+}
+
 static void mesh_cd_calc_active_vcol_layer(
         const Mesh *me, ushort cd_lused[CD_NUMTYPES])
 {
@@ -839,6 +851,7 @@ static MeshRenderData *mesh_render_data_create_ex(
 		}
 
 		rdata->cd.layers.uv_active = CustomData_get_active_layer(cd_ldata, CD_MLOOPUV);
+		rdata->cd.layers.uv_mask_active = CustomData_get_stencil_layer(cd_ldata, CD_MLOOPUV);
 		rdata->cd.layers.vcol_active = CustomData_get_active_layer(cd_ldata, CD_MLOOPCOL);
 		rdata->cd.layers.tangent_active = rdata->cd.layers.uv_active;
 
@@ -848,6 +861,7 @@ static MeshRenderData *mesh_render_data_create_ex(
 		} ((void)0)
 
 		CD_VALIDATE_ACTIVE_LAYER(rdata->cd.layers.uv_active, cd_lused[CD_MLOOPUV]);
+		CD_VALIDATE_ACTIVE_LAYER(rdata->cd.layers.uv_mask_active, cd_lused[CD_MLOOPUV]);
 		CD_VALIDATE_ACTIVE_LAYER(rdata->cd.layers.tangent_active, cd_lused[CD_TANGENT]);
 		CD_VALIDATE_ACTIVE_LAYER(rdata->cd.layers.vcol_active, cd_lused[CD_MLOOPCOL]);
 
@@ -2987,6 +3001,9 @@ static void mesh_create_loop_uv_and_tan(MeshRenderData *rdata, GPUVertBuf *vbo)
 		if (i == rdata->cd.layers.uv_active) {
 			GPU_vertformat_alias_add(&format, "u");
 		}
+		if (i == rdata->cd.layers.uv_mask_active) {
+			GPU_vertformat_alias_add(&format, "mu");
+		}
 	}
 
 	for (uint i = 0; i < tangent_len; i++) {
@@ -3959,6 +3976,7 @@ static void texpaint_request_active_uv(MeshBatchCache *cache, Mesh *me)
 		/* This should not happen. */
 		BLI_assert(!"No uv layer available in texpaint, but batches requested anyway!");
 	}
+	mesh_cd_calc_active_mask_uv_layer(me, cd_lneeded);
 	bool cd_overlap = mesh_cd_layers_type_overlap(cache->cd_vused, cache->cd_lused,
 	                                              cd_vneeded, cd_lneeded);
 	if (cd_overlap == false) {
diff --git a/source/blender/draw/modes/paint_texture_mode.c b/source/blender/draw/modes/paint_texture_mode.c
index 0a9746b3de5..7696ce4707b 100644
--- a/source/blender/draw/modes/paint_texture_mode.c
+++ b/source/blender/draw/modes/paint_texture_mode.c
@@ -106,6 +106,7 @@ static struct {
 	 * free in PAINT_TEXTURE_engine_free(); */
 	struct GPUShader *fallback_sh;
 	struct GPUShader *image_sh;
+	struct GPUShader *image_masking_sh;
 
 	struct GPUShader *wire_overlay_shader;
 	struct GPUShader *face_overlay_shader;
@@ -136,6 +137,12 @@ static void PAINT_TEXTURE_engine_init(void *UNUSED(vedata))
 		        datatoc_paint_texture_frag_glsl,
 		        datatoc_common_globals_lib_glsl, NULL);
 
+		e_data.image_masking_sh = DRW_shader_create_with_lib(
+		        datatoc_paint_texture_vert_glsl, NULL,
+		        datatoc_paint_texture_frag_glsl,
+		        datatoc_common_globals_lib_glsl,
+		        "#define TEXTURE_PAINT_MASK\n");
+
 		e_data.wire_overlay_shader = DRW_shader_create_with_lib(
 		        datatoc_paint_wire_vert_glsl, NULL,
 		        datatoc_paint_wire_frag_glsl,
@@ -148,6 +155,28 @@ static void PAINT_TEXTURE_engine_init(void *UNUSED(vedata))
 	}
 }
 
+static DRWShadingGroup* create_texture_paint_shading_group(PAINT_TEXTURE_PassList *psl, const struct GPUTexture *texture, const DRWContextState *draw_ctx, const bool nearest_interp)
+{
+	Scene *scene = draw_ctx->scene;
+	const ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
+	const bool masking_enabled = imapaint->flag & IMAGEPAINT_PROJECT_LAYER_STENCIL && imapaint->stencil != NULL;
+
+	DRWShadingGroup *grp = DRW_shgroup_create(masking_enabled?e_data.image_masking_sh:e_data.image_sh, psl->image_faces);
+	DRW_shgroup_uniform_texture(grp, "image", texture);
+	DRW_shgroup_uniform_float(grp, "alpha", &draw_ctx->v3d->overlay.texture_paint_mode_opacity, 1);
+	DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
+	DRW_shgroup_uniform_bool_copy(grp, "nearestInterp", nearest_interp);
+
+	if (masking_enabled) {
+		const bool masking_inverted = (imapaint->flag & IMAGEPAINT_PROJECT_LAYER_STENCIL_INV) > 0;
+		GPUTexture *stencil = GPU_texture_from_blender(imapaint->stencil, NULL, GL_TEXTURE_2D, false);
+		DRW_shgroup_uniform_texture(grp, "maskingImage", stencil);
+		DRW_shgroup_uniform_vec3(grp, "maskingColor", imapaint->stencil_col, 1);
+		DRW_shgroup_uniform_bool_copy(grp, "maskingInvertStencil", masking_inverted);
+	}
+	return grp;
+}
+
 /* Here init all passes and shading groups
  * Assume that all Passes are NULL */
 static void PAINT_TEXTURE_cache_init(void *vedata)
@@ -192,15 +221,10 @@ static void PAINT_TEXTURE_cache_init(void *vedata)
 					Material *ma = give_current_material(ob, i + 1);
 					Image *ima = (ma && ma->texpaintslot) ? ma->texpaintslot[ma->paint_active_slot].ima : NULL;
 					int interp = (ma && ma->texpaintslot) ? ma->texpaintslot[ma->paint_active_slot].interp : 0;
-					GPUTexture *tex = ima ?
-					        GPU_texture_from_blender(ima, NULL, GL_TEXTURE_2D, false) : NULL;
+					GPUTexture *tex = GPU_texture_from_blender(ima, NULL, GL_TEXTURE_2D, false);
 
 					if (tex) {
-						DRWShadingGroup *grp = DRW_shgroup_create(e_data.image_sh, psl->image_faces);
-						DRW_shgroup_uniform_texture(grp, "image", tex);
-						DRW_shgroup_uniform_float(grp, "alpha", &draw_ctx->v3d->overlay.texture_paint_mode_opacity, 1);
-						DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
-						DRW_shgroup_uniform_bool_copy(grp, "nearestInterp", interp == SHD_INTERP_CLOSEST);
+						DRWShadingGroup *grp = create_texture_paint_shading_group(psl, tex, draw_ctx, interp == SHD_INTERP_CLOSEST);
 						stl->g_data->shgroup_image_array[i] = grp;
 					}
 					else {
@@ -210,15 +234,10 @@ static void PAINT_TEXTURE_cache_init(void *vedata)
 			}
 			else {
 				Image *ima = imapaint->canvas;
-				GPUTexture *tex = ima ?
-				        GPU_texture_from_blender(ima, NULL, GL_TEXTURE_2D, false) : NULL;
+				GPUTexture *tex = GPU_texture_from_blender(ima, NULL, GL_TEXTURE_2D, false);
 
 				if (tex) {
-					DRWShadingGroup *grp = DRW_shgroup_create(e_data.image_sh, psl->image_faces);
-					DRW_shgroup_uniform_texture(grp, "image", tex);
-					DRW_shgroup_uniform_float(grp, "alpha", &draw_ctx->v3d->overlay.texture_paint_mode_opacity, 1);
-					DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
-					DRW_shgroup_uniform_bool_copy(grp, "nearestInterp", imapaint->interp == IMAGEPAINT_INTERP_CLOSEST);
+					DRWShadingGroup *grp = create_texture_paint_shading_group(psl, tex, draw_ctx, imapaint->interp == IMAGEPAINT_INTERP_CLOSEST);
 					stl->g_data->shgroup_image_array[0] = grp;
 				}
 				else {
@@ -345,6 +364,7 @@ static void PAINT_TEXTURE_draw_scene(void *vedata)
 static void PAINT_TEXTURE_engine_free(void)
 {
 	DRW_SHADER_FREE_SAFE(e_data.image_sh);
+	DRW_SHADER_FREE_SAFE(e_data.image_masking_sh);
 	DRW_SHADER_FREE_SAFE(e_data.wire_overlay_shader);
 	DRW_SHADER_FREE_SAFE(e_data.face_overlay_shader);
 }
diff --git a/source/blender/draw/modes/shaders/paint_texture_frag.glsl b/source/blender/draw/modes/shaders/paint_texture_frag.glsl
index 68fd1be0886..aadbf8c58c0 100644
--- a/source/blender/draw/modes/shaders/paint_texture_frag.glsl
+++ b/source/blender/draw/modes/shaders/paint_texture_frag.glsl
@@ -1,11 +1,21 @@
 
 in vec2 uv_interp;
+#ifdef TEXTURE_PAINT_MASK
+in vec2 masking_uv_interp;
+#endif
+
 out vec4 fragColor;
 
 uniform sampler2D image;
 uniform float alpha = 1.0;
 uniform bool nearestInterp;
 
+#ifdef TEXTURE_PAINT_MASK
+uniform sampler2D maskingImage;
+uniform vec3 maskingColor;
+uniform bool maskingInvertStencil;
+#endif
+
 void main()
 {
 	vec2 uv = uv_interp;
@@ -13,5 +23,19 @@ void main()
 		vec2 tex_size = vec2(textureSize(image, 0).xy);
 		uv = (floor(uv_interp * tex_size) + 0.5) / tex_size;
 	}
-	fragColor = vec4(texture(image, uv).rgb, alpha);
+
+	vec4 color = texture(image, uv);
+	color.a *= alpha;
+
+#ifdef TEXTURE_PAINT_MASK
+	vec4 mask = vec4(texture(maskingImage, masking_uv_interp).rgb, 1.0);
+	if (maskingInvertStencil) {
+		mask.rgb = 1.0 - mask.rgb;
+	}
+	float mask_step = smoothstep(0, 3.0, mask.r+mask.g+mask.b);
+	mask.rgb *= maskingColor;
+	color = mix(color, mask, mask_step);
+#endif
+
+	fragColor = color;
 }
diff --git a/source/blender/draw/modes/shaders/paint_texture_vert.glsl b/source/blender/draw/modes/shaders/paint_texture_vert.glsl
index c53439f46a0..43a353f0278 100644
--- a/source/blender/draw/modes/shaders/paint_texture_vert.glsl
+++ b/source/blender/draw/modes/shaders/paint_texture_vert.glsl
@@ -5,15 +5,27 @@ uniform mat4 ModelMatrix;
 in vec2 u; /* active uv map */
 in vec3 pos;
 
+#ifdef TEXTURE_PAINT_MASK
+in vec2 mu; /* masking uv map */
+#endif
+
 out vec2 uv_interp;
 
+#ifdef TEXTURE_PAINT_MASK
+out vec2 masking_uv_interp;
+#endif
+
 void main()
 {
 	gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
 
 	uv_interp = u;
 
+#ifdef TEXTURE_PAINT_MASK
+	masking_uv_interp = mu;
+#endif
+
 #ifdef USE_WORLD_CLIP_PLANES
-		world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz);
+	world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz);
 #endif
 }
diff --git a/source/blender/gpu/GPU_vertex_format.h b/source/blender/gpu/GPU_vertex_format.h
index 515fa545b0e..63ff430033b 100644
--- a/source/blender/gpu/GPU_vertex_format.h
+++ b/source/blender/gpu/GPU_vertex_format.h
@@ -29,7 +29,7 @@
 #include "GPU_common.h"
 
 #define GPU_VERT_ATTR_MAX_LEN 16
-#define GPU_VERT_ATTR_MAX_NAMES 3
+#define GPU_VERT_ATTR_MAX_NAMES 4
 #define GPU_VERT_ATTR_NAME_AVERAGE_LEN 11
 #define GPU_VERT_ATTR_NAMES_BUF_LEN ((GPU_VERT_ATTR_NAME_AVERAGE_LEN + 1) * GPU_VERT_ATTR_MAX_LEN

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list