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
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user