diff options
-rw-r--r-- | source/blender/draw/intern/draw_cache_impl_mesh.c | 18 | ||||
-rw-r--r-- | source/blender/draw/modes/paint_texture_mode.c | 48 | ||||
-rw-r--r-- | source/blender/draw/modes/shaders/paint_texture_frag.glsl | 26 | ||||
-rw-r--r-- | source/blender/draw/modes/shaders/paint_texture_vert.glsl | 14 | ||||
-rw-r--r-- | source/blender/gpu/GPU_vertex_format.h | 2 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_mesh.c | 1 |
6 files changed, 92 insertions, 17 deletions
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 --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index c9a8da51e40..158f4535303 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -2642,6 +2642,7 @@ static void rna_def_mesh(BlenderRNA *brna) RNA_def_property_int_funcs(prop, "rna_Mesh_uv_layer_stencil_index_get", "rna_Mesh_uv_layer_stencil_index_set", "rna_Mesh_uv_layer_index_range"); RNA_def_property_ui_text(prop, "Mask UV loop layer Index", "Mask UV loop layer index"); + RNA_def_property_update(prop, 0, "rna_Mesh_update_data"); /* Vertex colors */ |