Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/draw/engines/workbench/workbench_deferred.c94
-rw-r--r--source/blender/draw/engines/workbench/workbench_forward.c114
-rw-r--r--source/blender/draw/engines/workbench/workbench_materials.c53
-rw-r--r--source/blender/draw/engines/workbench/workbench_private.h46
-rw-r--r--source/blender/draw/modes/paint_texture_mode.c210
-rw-r--r--source/blender/draw/modes/shaders/paint_texture_frag.glsl23
-rw-r--r--source/blender/draw/modes/shaders/paint_texture_vert.glsl12
-rw-r--r--source/blender/makesdna/DNA_view3d_types.h4
-rw-r--r--source/blender/makesrna/intern/rna_space.c3
9 files changed, 292 insertions, 267 deletions
diff --git a/source/blender/draw/engines/workbench/workbench_deferred.c b/source/blender/draw/engines/workbench/workbench_deferred.c
index 31549c6f752..8c9dc43afa8 100644
--- a/source/blender/draw/engines/workbench/workbench_deferred.c
+++ b/source/blender/draw/engines/workbench/workbench_deferred.c
@@ -215,13 +215,16 @@ static GPUShader *workbench_cavity_shader_get(bool cavity, bool curvature)
static GPUShader *ensure_deferred_prepass_shader(WORKBENCH_PrivateData *wpd,
bool is_uniform_color,
bool is_hair,
+ bool is_texture_painting,
eGPUShaderConfig sh_cfg)
{
WORKBENCH_DEFERRED_Shaders *sh_data = &e_data.sh_data[sh_cfg];
- int index = workbench_material_get_prepass_shader_index(wpd, is_uniform_color, is_hair);
+ int index = workbench_material_get_prepass_shader_index(
+ wpd, is_uniform_color, is_hair, is_texture_painting);
if (sh_data->prepass_sh_cache[index] == NULL) {
const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[sh_cfg];
- char *defines = workbench_material_build_defines(wpd, is_uniform_color, is_hair);
+ char *defines = workbench_material_build_defines(
+ wpd, is_uniform_color, is_hair, is_texture_painting);
char *prepass_vert = workbench_build_prepass_vert(is_hair);
char *prepass_frag = workbench_build_prepass_frag();
sh_data->prepass_sh_cache[index] = GPU_shader_create_from_arrays({
@@ -240,7 +243,7 @@ static GPUShader *ensure_deferred_composite_shader(WORKBENCH_PrivateData *wpd)
{
int index = workbench_material_get_composite_shader_index(wpd);
if (e_data.composite_sh_cache[index] == NULL) {
- char *defines = workbench_material_build_defines(wpd, false, false);
+ char *defines = workbench_material_build_defines(wpd, false, false, false);
char *composite_frag = workbench_build_composite_frag(wpd);
e_data.composite_sh_cache[index] = DRW_shader_create_fullscreen(composite_frag, defines);
MEM_freeN(composite_frag);
@@ -267,10 +270,11 @@ static GPUShader *ensure_background_shader(WORKBENCH_PrivateData *wpd)
static void select_deferred_shaders(WORKBENCH_PrivateData *wpd, eGPUShaderConfig sh_cfg)
{
- wpd->prepass_sh = ensure_deferred_prepass_shader(wpd, false, false, sh_cfg);
- wpd->prepass_hair_sh = ensure_deferred_prepass_shader(wpd, false, true, sh_cfg);
- wpd->prepass_uniform_sh = ensure_deferred_prepass_shader(wpd, true, false, sh_cfg);
- wpd->prepass_uniform_hair_sh = ensure_deferred_prepass_shader(wpd, true, true, sh_cfg);
+ wpd->prepass_sh = ensure_deferred_prepass_shader(wpd, false, false, false, sh_cfg);
+ wpd->prepass_hair_sh = ensure_deferred_prepass_shader(wpd, false, true, false, sh_cfg);
+ wpd->prepass_uniform_sh = ensure_deferred_prepass_shader(wpd, true, false, false, sh_cfg);
+ wpd->prepass_uniform_hair_sh = ensure_deferred_prepass_shader(wpd, true, true, false, sh_cfg);
+ wpd->prepass_textured_sh = ensure_deferred_prepass_shader(wpd, false, false, true, sh_cfg);
wpd->composite_sh = ensure_deferred_composite_shader(wpd);
wpd->background_sh = ensure_background_shader(wpd);
}
@@ -483,7 +487,7 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata)
e_data.composite_buffer_tx = DRW_texture_pool_query_2d(
size[0], size[1], comp_tex_format, &draw_engine_workbench_solid);
- if (MATDATA_PASS_ENABLED(wpd) || GPU_unused_fb_slot_workaround()) {
+ if (workbench_is_matdata_pass_enabled(wpd) || GPU_unused_fb_slot_workaround()) {
e_data.color_buffer_tx = DRW_texture_pool_query_2d(
size[0], size[1], col_tex_format, &draw_engine_workbench_solid);
}
@@ -523,7 +527,7 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata)
GPU_ATTACHMENT_TEXTURE(e_data.composite_buffer_tx),
});
- if (!MATDATA_PASS_ENABLED(wpd) && !GPU_unused_fb_slot_workaround()) {
+ if (!workbench_is_matdata_pass_enabled(wpd) && !GPU_unused_fb_slot_workaround()) {
e_data.color_buffer_tx = DRW_texture_pool_query_2d(
size[0], size[1], col_tex_format, &draw_engine_workbench_solid);
}
@@ -675,7 +679,7 @@ void workbench_deferred_engine_free(void)
static void workbench_composite_uniforms(WORKBENCH_PrivateData *wpd, DRWShadingGroup *grp)
{
DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo);
- if (MATDATA_PASS_ENABLED(wpd)) {
+ if (workbench_is_matdata_pass_enabled(wpd)) {
DRW_shgroup_uniform_texture_ref(grp, "materialBuffer", &e_data.color_buffer_tx);
}
else {
@@ -714,7 +718,6 @@ void workbench_deferred_cache_init(WORKBENCH_Data *vedata)
Scene *scene = draw_ctx->scene;
workbench_volume_cache_init(vedata);
-
select_deferred_shaders(wpd, draw_ctx->sh_cfg);
/* Background Pass */
@@ -869,7 +872,7 @@ static WORKBENCH_MaterialData *get_or_create_material_data(WORKBENCH_Data *vedat
const bool is_ghost = (ob->dtx & OB_DRAWXRAY);
/* Solid */
- workbench_material_update_data(wpd, ob, mat, &material_template);
+ workbench_material_update_data(wpd, ob, mat, &material_template, color_type);
material_template.object_id = OBJECT_ID_PASS_ENABLED(wpd) ? engine_object_data->object_id : 1;
material_template.color_type = color_type;
material_template.ima = ima;
@@ -880,9 +883,14 @@ static WORKBENCH_MaterialData *get_or_create_material_data(WORKBENCH_Data *vedat
material = BLI_ghash_lookup(wpd->material_hash, POINTER_FROM_UINT(hash));
if (material == NULL) {
material = MEM_mallocN(sizeof(WORKBENCH_MaterialData), __func__);
+ /* select the correct prepass shader */
+ GPUShader *shader = (wpd->shading.color_type == color_type) ? wpd->prepass_sh :
+ wpd->prepass_uniform_sh;
+ if (color_type == V3D_SHADING_TEXTURE_COLOR) {
+ shader = wpd->prepass_textured_sh;
+ }
material->shgrp = DRW_shgroup_create(
- (wpd->shading.color_type == color_type) ? wpd->prepass_sh : wpd->prepass_uniform_sh,
- (ob->dtx & OB_DRAWXRAY) ? psl->ghost_prepass_pass : psl->prepass_pass);
+ shader, (ob->dtx & OB_DRAWXRAY) ? psl->ghost_prepass_pass : psl->prepass_pass);
workbench_material_copy(material, &material_template);
DRW_shgroup_stencil_mask(material->shgrp, (ob->dtx & OB_DRAWXRAY) ? 0x00 : 0xFF);
DRW_shgroup_uniform_int(material->shgrp, "object_id", &material->object_id, 1);
@@ -935,6 +943,49 @@ static void workbench_cache_populate_particles(WORKBENCH_Data *vedata, Object *o
}
}
+static void workbench_cache_populate_texture_paint_mode(WORKBENCH_Data *vedata, Object *ob)
+{
+ WORKBENCH_StorageList *stl = vedata->stl;
+ WORKBENCH_PrivateData *wpd = stl->g_data;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+
+ Scene *scene = draw_ctx->scene;
+ const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d);
+ WORKBENCH_MaterialData *material;
+
+ /* Force workbench to render active object textured when in texture paint mode */
+ const ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
+
+ /* Single Image mode */
+ if (imapaint->mode == IMAGEPAINT_MODE_IMAGE) {
+ Image *image = imapaint->canvas;
+ int interp = (imapaint->interp == IMAGEPAINT_INTERP_LINEAR) ? SHD_INTERP_LINEAR :
+ SHD_INTERP_CLOSEST;
+ int color_type = workbench_material_determine_color_type(wpd, image, ob, use_sculpt_pbvh);
+ struct GPUBatch *geom = DRW_cache_mesh_surface_texpaint_single_get(ob);
+ material = get_or_create_material_data(vedata, ob, NULL, image, NULL, color_type, interp);
+
+ DRW_shgroup_call(material->shgrp, geom, ob);
+ }
+ else {
+ /* IMAGEPAINT_MODE_MATERIAL */
+ const int materials_len = MAX2(1, ob->totcol);
+ struct GPUBatch **geom_array = DRW_cache_mesh_surface_texpaint_get(ob);
+ for (int i = 0; i < materials_len; i++) {
+ if (geom_array != NULL && geom_array[i] != NULL) {
+ Material *mat;
+ Image *image;
+ ImageUser *iuser;
+ int interp;
+ workbench_material_get_image_and_mat(ob, i + 1, &image, &iuser, &interp, &mat);
+ int color_type = workbench_material_determine_color_type(wpd, image, ob, use_sculpt_pbvh);
+ material = get_or_create_material_data(vedata, ob, mat, image, iuser, color_type, interp);
+ DRW_shgroup_call(material->shgrp, geom_array[i], ob);
+ }
+ }
+ }
+}
+
void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
{
WORKBENCH_StorageList *stl = vedata->stl;
@@ -975,8 +1026,13 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
const int materials_len = MAX2(1, ob->totcol);
const Mesh *me = (ob->type == OB_MESH) ? ob->data : NULL;
bool has_transp_mat = false;
+ const bool use_texture_paint_drawing = workbench_is_object_in_texture_paint_mode(ob) && me &&
+ me->mloopuv;
- if (!use_sculpt_pbvh && TEXTURE_DRAWING_ENABLED(wpd) && me && me->mloopuv) {
+ if (use_texture_paint_drawing) {
+ workbench_cache_populate_texture_paint_mode(vedata, ob);
+ }
+ else if (!use_sculpt_pbvh && TEXTURE_DRAWING_ENABLED(wpd) && me && me->mloopuv) {
/* Draw textured */
struct GPUBatch **geom_array = DRW_cache_mesh_surface_texpaint_get(ob);
for (int i = 0; i < materials_len; i++) {
@@ -990,7 +1046,7 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
wpd, image, ob, use_sculpt_pbvh);
if (color_type == V3D_SHADING_MATERIAL_COLOR && mat && mat->a < 1.0) {
material = workbench_forward_get_or_create_material_data(
- vedata, ob, mat, image, iuser, color_type, 0, use_sculpt_pbvh);
+ vedata, ob, mat, image, iuser, color_type, 0);
has_transp_mat = true;
}
else {
@@ -1010,7 +1066,7 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
if ((ob->color[3] < 1.0f) && (color_type == V3D_SHADING_OBJECT_COLOR)) {
material = workbench_forward_get_or_create_material_data(
- vedata, ob, NULL, NULL, NULL, color_type, 0, use_sculpt_pbvh);
+ vedata, ob, NULL, NULL, NULL, color_type, 0);
has_transp_mat = true;
}
else {
@@ -1045,7 +1101,7 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
struct Material *mat = give_current_material(ob, i + 1);
if (mat != NULL && mat->a < 1.0f) {
material = workbench_forward_get_or_create_material_data(
- vedata, ob, mat, NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0, use_sculpt_pbvh);
+ vedata, ob, mat, NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0);
has_transp_mat = true;
}
else {
@@ -1068,7 +1124,7 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
Material *mat = give_current_material(ob, i + 1);
if (mat != NULL && mat->a < 1.0f) {
material = workbench_forward_get_or_create_material_data(
- vedata, ob, mat, NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0, use_sculpt_pbvh);
+ vedata, ob, mat, NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0);
has_transp_mat = true;
}
else {
diff --git a/source/blender/draw/engines/workbench/workbench_forward.c b/source/blender/draw/engines/workbench/workbench_forward.c
index 9245d13eab0..5e8cbf71c1e 100644
--- a/source/blender/draw/engines/workbench/workbench_forward.c
+++ b/source/blender/draw/engines/workbench/workbench_forward.c
@@ -141,8 +141,7 @@ WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_
Image *ima,
ImageUser *iuser,
int color_type,
- int interp,
- bool use_sculpt_pbvh)
+ int interp)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
WORKBENCH_FORWARD_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
@@ -160,7 +159,7 @@ WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_
DRWShadingGroup *grp;
/* Solid */
- workbench_material_update_data(wpd, ob, mat, &material_template);
+ workbench_material_update_data(wpd, ob, mat, &material_template, color_type);
material_template.object_id = OBJECT_ID_PASS_ENABLED(wpd) ? engine_object_data->object_id : 1;
material_template.color_type = color_type;
material_template.ima = ima;
@@ -173,10 +172,15 @@ WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_
material = MEM_mallocN(sizeof(WORKBENCH_MaterialData), __func__);
/* transparent accum */
- grp = DRW_shgroup_create(wpd->shading.color_type == color_type ?
- wpd->transparent_accum_sh :
- wpd->transparent_accum_uniform_sh,
- psl->transparent_accum_pass);
+ /* select the correct transparent accum shader */
+ GPUShader *shader = (wpd->shading.color_type == color_type) ?
+ wpd->transparent_accum_sh :
+ wpd->transparent_accum_uniform_sh;
+ if (color_type == V3D_SHADING_TEXTURE_COLOR) {
+ shader = wpd->transparent_accum_textured_sh;
+ }
+
+ grp = DRW_shgroup_create(shader, psl->transparent_accum_pass);
DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo);
DRW_shgroup_uniform_float_copy(grp, "alpha", material_template.alpha);
DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)wpd->viewvecs, 3);
@@ -199,8 +203,7 @@ WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_
material->shgrp = grp;
/* Depth */
- if (workbench_material_determine_color_type(wpd, material->ima, ob, use_sculpt_pbvh) ==
- V3D_SHADING_TEXTURE_COLOR) {
+ if (color_type == V3D_SHADING_TEXTURE_COLOR) {
material->shgrp_object_outline = DRW_shgroup_create(sh_data->object_outline_texture_sh,
psl->object_outline_pass);
GPUTexture *tex = GPU_texture_from_blender(material->ima, material->iuser, GL_TEXTURE_2D);
@@ -223,13 +226,16 @@ WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_
static GPUShader *ensure_forward_accum_shaders(WORKBENCH_PrivateData *wpd,
bool is_uniform_color,
bool is_hair,
+ bool is_texture_painting,
eGPUShaderConfig sh_cfg)
{
WORKBENCH_FORWARD_Shaders *sh_data = &e_data.sh_data[sh_cfg];
- int index = workbench_material_get_accum_shader_index(wpd, is_uniform_color, is_hair);
+ int index = workbench_material_get_accum_shader_index(
+ wpd, is_uniform_color, is_hair, is_texture_painting);
if (sh_data->transparent_accum_sh_cache[index] == NULL) {
const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[sh_cfg];
- char *defines = workbench_material_build_defines(wpd, is_uniform_color, is_hair);
+ char *defines = workbench_material_build_defines(
+ wpd, is_uniform_color, is_hair, is_texture_painting);
char *transparent_accum_vert = workbench_build_forward_vert(is_hair);
char *transparent_accum_frag = workbench_build_forward_transparent_accum_frag();
sh_data->transparent_accum_sh_cache[index] = GPU_shader_create_from_arrays({
@@ -248,7 +254,7 @@ static GPUShader *ensure_forward_composite_shaders(WORKBENCH_PrivateData *wpd)
{
int index = OBJECT_OUTLINE_ENABLED(wpd) ? 1 : 0;
if (e_data.composite_sh_cache[index] == NULL) {
- char *defines = workbench_material_build_defines(wpd, false, false);
+ char *defines = workbench_material_build_defines(wpd, false, false, false);
char *composite_frag = workbench_build_forward_composite_frag();
e_data.composite_sh_cache[index] = DRW_shader_create_fullscreen(composite_frag, defines);
MEM_freeN(composite_frag);
@@ -260,10 +266,14 @@ static GPUShader *ensure_forward_composite_shaders(WORKBENCH_PrivateData *wpd)
void workbench_forward_choose_shaders(WORKBENCH_PrivateData *wpd, eGPUShaderConfig sh_cfg)
{
wpd->composite_sh = ensure_forward_composite_shaders(wpd);
- wpd->transparent_accum_sh = ensure_forward_accum_shaders(wpd, false, false, sh_cfg);
- wpd->transparent_accum_hair_sh = ensure_forward_accum_shaders(wpd, false, true, sh_cfg);
- wpd->transparent_accum_uniform_sh = ensure_forward_accum_shaders(wpd, true, false, sh_cfg);
- wpd->transparent_accum_uniform_hair_sh = ensure_forward_accum_shaders(wpd, true, true, sh_cfg);
+ wpd->transparent_accum_sh = ensure_forward_accum_shaders(wpd, false, false, false, sh_cfg);
+ wpd->transparent_accum_hair_sh = ensure_forward_accum_shaders(wpd, false, true, false, sh_cfg);
+ wpd->transparent_accum_uniform_sh = ensure_forward_accum_shaders(
+ wpd, true, false, false, sh_cfg);
+ wpd->transparent_accum_uniform_hair_sh = ensure_forward_accum_shaders(
+ wpd, true, true, false, sh_cfg);
+ wpd->transparent_accum_textured_sh = ensure_forward_accum_shaders(
+ wpd, false, false, true, sh_cfg);
}
void workbench_forward_outline_shaders_ensure(WORKBENCH_PrivateData *wpd, eGPUShaderConfig sh_cfg)
@@ -272,9 +282,9 @@ void workbench_forward_outline_shaders_ensure(WORKBENCH_PrivateData *wpd, eGPUSh
if (sh_data->object_outline_sh == NULL) {
const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[sh_cfg];
- char *defines = workbench_material_build_defines(wpd, false, false);
- char *defines_texture = workbench_material_build_defines(wpd, true, false);
- char *defines_hair = workbench_material_build_defines(wpd, false, true);
+ char *defines = workbench_material_build_defines(wpd, false, false, false);
+ char *defines_texture = workbench_material_build_defines(wpd, true, false, false);
+ char *defines_hair = workbench_material_build_defines(wpd, false, true, false);
char *forward_vert = workbench_build_forward_vert(false);
char *forward_hair_vert = workbench_build_forward_vert(true);
@@ -503,7 +513,7 @@ static void workbench_forward_cache_populate_particles(WORKBENCH_Data *vedata, O
workbench_material_get_image_and_mat(ob, part->omat, &image, &iuser, &interp, &mat);
int color_type = workbench_material_determine_color_type(wpd, image, ob, false);
WORKBENCH_MaterialData *material = workbench_forward_get_or_create_material_data(
- vedata, ob, mat, image, iuser, color_type, interp, false);
+ vedata, ob, mat, image, iuser, color_type, interp);
struct GPUShader *shader = (wpd->shading.color_type == color_type) ?
wpd->transparent_accum_hair_sh :
@@ -533,6 +543,53 @@ static void workbench_forward_cache_populate_particles(WORKBENCH_Data *vedata, O
}
}
}
+static void workbench_forward_cache_populate_texture_paint_mode(WORKBENCH_Data *vedata, Object *ob)
+{
+ WORKBENCH_StorageList *stl = vedata->stl;
+ WORKBENCH_PrivateData *wpd = stl->g_data;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+
+ Scene *scene = draw_ctx->scene;
+ const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d);
+ WORKBENCH_MaterialData *material;
+
+ /* Force workbench to render active object textured when in texture paint mode */
+ const ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
+
+ /* Single Image mode */
+ if (imapaint->mode == IMAGEPAINT_MODE_IMAGE) {
+ Image *image = imapaint->canvas;
+ int interp = (imapaint->interp == IMAGEPAINT_INTERP_LINEAR) ? SHD_INTERP_LINEAR :
+ SHD_INTERP_CLOSEST;
+ int color_type = workbench_material_determine_color_type(wpd, image, ob, use_sculpt_pbvh);
+ struct GPUBatch *geom = DRW_cache_mesh_surface_texpaint_single_get(ob);
+ material = workbench_forward_get_or_create_material_data(
+ vedata, ob, NULL, image, NULL, color_type, interp);
+
+ DRW_shgroup_call(material->shgrp, geom, ob);
+ DRW_shgroup_call(material->shgrp_object_outline, geom, ob);
+ }
+ else {
+ /* IMAGEPAINT_MODE_MATERIAL */
+ const int materials_len = MAX2(1, ob->totcol);
+ struct GPUBatch **geom_array = DRW_cache_mesh_surface_texpaint_get(ob);
+ for (int i = 0; i < materials_len; i++) {
+ if (geom_array != NULL && geom_array[i] != NULL) {
+ Material *mat;
+ Image *image;
+ ImageUser *iuser;
+ int interp;
+ workbench_material_get_image_and_mat(ob, i + 1, &image, &iuser, &interp, &mat);
+ int color_type = workbench_material_determine_color_type(wpd, image, ob, use_sculpt_pbvh);
+ material = workbench_forward_get_or_create_material_data(
+ vedata, ob, mat, image, iuser, color_type, interp);
+
+ DRW_shgroup_call(material->shgrp, geom_array[i], ob);
+ DRW_shgroup_call(material->shgrp_object_outline, geom_array[i], ob);
+ }
+ }
+ }
+}
void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob)
{
@@ -571,8 +628,13 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob)
const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d);
const int materials_len = MAX2(1, ob->totcol);
const Mesh *me = (ob->type == OB_MESH) ? ob->data : NULL;
+ const bool use_texture_paint_drawing = workbench_is_object_in_texture_paint_mode(ob) && me &&
+ me->mloopuv;
- if (!use_sculpt_pbvh && TEXTURE_DRAWING_ENABLED(wpd) && me && me->mloopuv) {
+ if (use_texture_paint_drawing) {
+ workbench_forward_cache_populate_texture_paint_mode(vedata, ob);
+ }
+ else if (!use_sculpt_pbvh && TEXTURE_DRAWING_ENABLED(wpd) && me && me->mloopuv) {
struct GPUBatch **geom_array = DRW_cache_mesh_surface_texpaint_get(ob);
for (int i = 0; i < materials_len; i++) {
Material *mat;
@@ -582,7 +644,7 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob)
workbench_material_get_image_and_mat(ob, i + 1, &image, &iuser, &interp, &mat);
int color_type = workbench_material_determine_color_type(wpd, image, ob, use_sculpt_pbvh);
material = workbench_forward_get_or_create_material_data(
- vedata, ob, mat, image, iuser, color_type, interp, use_sculpt_pbvh);
+ vedata, ob, mat, image, iuser, color_type, interp);
DRW_shgroup_call(material->shgrp_object_outline, geom_array[i], ob);
DRW_shgroup_call(material->shgrp, geom_array[i], ob);
}
@@ -597,7 +659,7 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob)
if (use_sculpt_pbvh) {
material = workbench_forward_get_or_create_material_data(
- vedata, ob, NULL, NULL, NULL, color_type, 0, use_sculpt_pbvh);
+ vedata, ob, NULL, NULL, NULL, color_type, 0);
bool use_vcol = (color_type == V3D_SHADING_VERTEX_COLOR);
/* TODO(fclem) make this call optional */
DRW_shgroup_call_sculpt(material->shgrp_object_outline, ob, false, false, false);
@@ -611,7 +673,7 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob)
DRW_cache_object_surface_get(ob);
if (geom) {
material = workbench_forward_get_or_create_material_data(
- vedata, ob, NULL, NULL, NULL, color_type, 0, use_sculpt_pbvh);
+ vedata, ob, NULL, NULL, NULL, color_type, 0);
/* TODO(fclem) make this call optional */
DRW_shgroup_call(material->shgrp_object_outline, geom, ob);
if (!is_wire) {
@@ -628,7 +690,7 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob)
for (int i = 0; i < materials_len; ++i) {
struct Material *mat = give_current_material(ob, i + 1);
material = workbench_forward_get_or_create_material_data(
- vedata, ob, mat, NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0, use_sculpt_pbvh);
+ vedata, ob, mat, NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0);
shgrps[i] = material->shgrp;
}
/* TODO(fclem) make this call optional */
@@ -651,7 +713,7 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob)
Material *mat = give_current_material(ob, i + 1);
material = workbench_forward_get_or_create_material_data(
- vedata, ob, mat, NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0, use_sculpt_pbvh);
+ vedata, ob, mat, NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0);
/* TODO(fclem) make this call optional */
DRW_shgroup_call(material->shgrp_object_outline, mat_geom[i], ob);
if (!is_wire) {
diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c
index 76f035562e5..1473b7df279 100644
--- a/source/blender/draw/engines/workbench/workbench_materials.c
+++ b/source/blender/draw/engines/workbench/workbench_materials.c
@@ -41,13 +41,9 @@
void workbench_material_update_data(WORKBENCH_PrivateData *wpd,
Object *ob,
Material *mat,
- WORKBENCH_MaterialData *data)
+ WORKBENCH_MaterialData *data,
+ int color_type)
{
- /* When V3D_SHADING_TEXTURE_COLOR is active, use V3D_SHADING_MATERIAL_COLOR as fallback when no
- * texture could be determined */
- int color_type = wpd->shading.color_type == V3D_SHADING_TEXTURE_COLOR ?
- V3D_SHADING_MATERIAL_COLOR :
- wpd->shading.color_type;
copy_v3_fl3(data->diffuse_color, 0.8f, 0.8f, 0.8f);
copy_v3_v3(data->base_color, data->diffuse_color);
copy_v3_fl3(data->specular_color, 0.05f, 0.05f, 0.05f); /* Dielectric: 5% reflective. */
@@ -59,6 +55,10 @@ void workbench_material_update_data(WORKBENCH_PrivateData *wpd,
copy_v3_v3(data->diffuse_color, wpd->shading.single_color);
copy_v3_v3(data->base_color, data->diffuse_color);
}
+ else if (color_type == V3D_SHADING_ERROR_COLOR) {
+ copy_v3_fl3(data->diffuse_color, 0.8, 0.0, 0.8);
+ copy_v3_v3(data->base_color, data->diffuse_color);
+ }
else if (color_type == V3D_SHADING_RANDOM_COLOR) {
uint hash = BLI_ghashutil_strhash_p_murmur(ob->id.name);
if (ob->id.lib) {
@@ -76,7 +76,7 @@ void workbench_material_update_data(WORKBENCH_PrivateData *wpd,
data->alpha *= ob->color[3];
}
else {
- /* V3D_SHADING_MATERIAL_COLOR */
+ /* V3D_SHADING_MATERIAL_COLOR or V3D_SHADING_TEXTURE_COLOR */
if (mat) {
data->alpha *= mat->a;
if (SPECULAR_HIGHLIGHT_ENABLED(wpd)) {
@@ -97,13 +97,19 @@ void workbench_material_update_data(WORKBENCH_PrivateData *wpd,
char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd,
bool is_uniform_color,
- bool is_hair)
+ bool is_hair,
+ bool is_texture_painting)
{
char *str = NULL;
bool use_textures = (wpd->shading.color_type == V3D_SHADING_TEXTURE_COLOR) && !is_uniform_color;
bool use_vertex_colors = (wpd->shading.color_type == V3D_SHADING_VERTEX_COLOR) &&
!is_uniform_color;
+ if (is_texture_painting) {
+ use_textures = true;
+ use_vertex_colors = false;
+ }
+
DynStr *ds = BLI_dynstr_new();
if (wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE) {
@@ -130,7 +136,7 @@ char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd,
if (OBJECT_ID_PASS_ENABLED(wpd)) {
BLI_dynstr_append(ds, "#define OBJECT_ID_PASS_ENABLED\n");
}
- if (MATDATA_PASS_ENABLED(wpd)) {
+ if (workbench_is_matdata_pass_enabled(wpd)) {
BLI_dynstr_append(ds, "#define MATDATA_PASS_ENABLED\n");
}
if (NORMAL_VIEWPORT_PASS_ENABLED(wpd)) {
@@ -193,22 +199,27 @@ int workbench_material_get_composite_shader_index(WORKBENCH_PrivateData *wpd)
SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_SHADOW, 1 << 2);
SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_CAVITY, 1 << 3);
SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE, 1 << 4);
- SET_FLAG_FROM_TEST(index, MATDATA_PASS_ENABLED(wpd), 1 << 5);
+ SET_FLAG_FROM_TEST(index, workbench_is_matdata_pass_enabled(wpd), 1 << 5);
BLI_assert(index < MAX_COMPOSITE_SHADERS);
return index;
}
int workbench_material_get_prepass_shader_index(WORKBENCH_PrivateData *wpd,
bool is_uniform_color,
- bool is_hair)
+ bool is_hair,
+ bool is_texture_painting)
{
bool use_textures = (wpd->shading.color_type == V3D_SHADING_TEXTURE_COLOR) && !is_uniform_color;
bool use_vertex_colors = (wpd->shading.color_type == V3D_SHADING_VERTEX_COLOR) &&
!is_uniform_color;
+ if (is_texture_painting) {
+ use_textures = true;
+ use_vertex_colors = false;
+ }
/* NOTE: change MAX_PREPASS_SHADERS accordingly when modifying this function. */
int index = 0;
SET_FLAG_FROM_TEST(index, is_hair, 1 << 0);
- SET_FLAG_FROM_TEST(index, MATDATA_PASS_ENABLED(wpd), 1 << 1);
+ SET_FLAG_FROM_TEST(index, workbench_is_matdata_pass_enabled(wpd), 1 << 1);
SET_FLAG_FROM_TEST(index, OBJECT_ID_PASS_ENABLED(wpd), 1 << 2);
SET_FLAG_FROM_TEST(index, NORMAL_VIEWPORT_PASS_ENABLED(wpd), 1 << 3);
SET_FLAG_FROM_TEST(index, MATCAP_ENABLED(wpd), 1 << 4);
@@ -220,11 +231,18 @@ int workbench_material_get_prepass_shader_index(WORKBENCH_PrivateData *wpd,
int workbench_material_get_accum_shader_index(WORKBENCH_PrivateData *wpd,
bool is_uniform_color,
- bool is_hair)
+ bool is_hair,
+ bool is_texture_painting)
{
bool use_textures = (wpd->shading.color_type == V3D_SHADING_TEXTURE_COLOR) && !is_uniform_color;
bool use_vertex_colors = (wpd->shading.color_type == V3D_SHADING_VERTEX_COLOR) &&
!is_uniform_color;
+ if (is_texture_painting) {
+ use_textures = true;
+ use_vertex_colors = false;
+ is_hair = false;
+ }
+
/* NOTE: change MAX_ACCUM_SHADERS accordingly when modifying this function. */
int index = 0;
/* 2 bits FLAT/STUDIO/MATCAP + Specular highlight */
@@ -253,6 +271,13 @@ int workbench_material_determine_color_type(WORKBENCH_PrivateData *wpd,
if (color_type == V3D_SHADING_VERTEX_COLOR && (me == NULL || me->mloopcol == NULL)) {
color_type = V3D_SHADING_OBJECT_COLOR;
}
+
+ /* Force V3D_SHADING_TEXTURE_COLOR for active object when in texture painting
+ * no matter the shading color that the user has chosen, when there is no
+ * texture we will render the object with the error color */
+ if (workbench_is_object_in_texture_paint_mode(ob)) {
+ color_type = ima ? V3D_SHADING_TEXTURE_COLOR : V3D_SHADING_ERROR_COLOR;
+ }
return color_type;
}
@@ -292,7 +317,7 @@ void workbench_material_shgroup_uniform(WORKBENCH_PrivateData *wpd,
const bool deferred,
const int interp)
{
- if (deferred && !MATDATA_PASS_ENABLED(wpd)) {
+ if (deferred && !workbench_is_matdata_pass_enabled(wpd)) {
return;
}
diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h
index 3b62ed33e96..17144c4dc10 100644
--- a/source/blender/draw/engines/workbench/workbench_private.h
+++ b/source/blender/draw/engines/workbench/workbench_private.h
@@ -43,6 +43,7 @@
#define TEXTURE_DRAWING_ENABLED(wpd) (wpd->shading.color_type == V3D_SHADING_TEXTURE_COLOR)
#define VERTEX_COLORS_ENABLED(wpd) (wpd->shading.color_type == V3D_SHADING_VERTEX_COLOR)
+#define MATERIAL_COLORS_ENABLED(wpd) (wpd->shading.color_type == V3D_SHADING_MATERIAL_COLOR)
#define FLAT_ENABLED(wpd) (wpd->shading.light == V3D_LIGHTING_FLAT)
#define STUDIOLIGHT_ENABLED(wpd) (wpd->shading.light == V3D_LIGHTING_STUDIO)
#define MATCAP_ENABLED(wpd) (wpd->shading.light == V3D_LIGHTING_MATCAP)
@@ -81,8 +82,6 @@
(!STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)))
#define OBJECT_OUTLINE_ENABLED(wpd) (wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE)
#define OBJECT_ID_PASS_ENABLED(wpd) (OBJECT_OUTLINE_ENABLED(wpd) || CURVATURE_ENABLED(wpd))
-#define MATDATA_PASS_ENABLED(wpd) \
- (wpd->shading.color_type != V3D_SHADING_SINGLE_COLOR || MATCAP_ENABLED(wpd))
#define NORMAL_VIEWPORT_COMP_PASS_ENABLED(wpd) \
(MATCAP_ENABLED(wpd) || STUDIOLIGHT_ENABLED(wpd) || SHADOW_ENABLED(wpd))
#define NORMAL_VIEWPORT_PASS_ENABLED(wpd) \
@@ -208,12 +207,14 @@ typedef struct WORKBENCH_PrivateData {
struct GPUShader *prepass_hair_sh;
struct GPUShader *prepass_uniform_sh;
struct GPUShader *prepass_uniform_hair_sh;
+ struct GPUShader *prepass_textured_sh;
struct GPUShader *composite_sh;
struct GPUShader *background_sh;
struct GPUShader *transparent_accum_sh;
struct GPUShader *transparent_accum_hair_sh;
struct GPUShader *transparent_accum_uniform_sh;
struct GPUShader *transparent_accum_uniform_hair_sh;
+ struct GPUShader *transparent_accum_textured_sh;
View3DShading shading;
StudioLight *studio_light;
const UserDef *preferences;
@@ -354,6 +355,32 @@ BLI_INLINE bool workbench_is_fxaa_enabled(WORKBENCH_PrivateData *wpd)
}
}
+/** Is texture paint mode enabled (globally) */
+BLI_INLINE bool workbench_is_in_texture_paint_mode(void)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ return draw_ctx->object_mode == OB_MODE_TEXTURE_PAINT;
+}
+
+/** Is texture paint mode active for the given object */
+BLI_INLINE bool workbench_is_object_in_texture_paint_mode(Object *ob)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ if (ob->type == OB_MESH && (draw_ctx->obact == ob)) {
+ const enum eContextObjectMode mode = CTX_data_mode_enum_ex(
+ draw_ctx->object_edit, draw_ctx->obact, draw_ctx->object_mode);
+ return (mode == CTX_MODE_PAINT_TEXTURE);
+ }
+
+ return false;
+}
+
+BLI_INLINE bool workbench_is_matdata_pass_enabled(WORKBENCH_PrivateData *wpd)
+{
+ return (wpd->shading.color_type != V3D_SHADING_SINGLE_COLOR || MATCAP_ENABLED(wpd)) ||
+ workbench_is_in_texture_paint_mode();
+}
+
/* workbench_deferred.c */
void workbench_deferred_engine_init(WORKBENCH_Data *vedata);
void workbench_deferred_engine_free(void);
@@ -383,8 +410,7 @@ WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_
Image *ima,
ImageUser *iuser,
int color_type,
- int interp,
- bool use_sculpt_pbvh);
+ int interp);
/* workbench_effect_aa.c */
void workbench_aa_create_pass(WORKBENCH_Data *vedata, GPUTexture **tx);
@@ -422,19 +448,23 @@ void workbench_material_get_image_and_mat(
Object *ob, int mat_nr, Image **r_image, ImageUser **r_iuser, int *r_interp, Material **r_mat);
char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd,
bool is_uniform_color,
- bool is_hair);
+ bool is_hair,
+ bool is_texture_painting);
void workbench_material_update_data(WORKBENCH_PrivateData *wpd,
Object *ob,
Material *mat,
- WORKBENCH_MaterialData *data);
+ WORKBENCH_MaterialData *data,
+ int color_type);
uint workbench_material_get_hash(WORKBENCH_MaterialData *material_template, bool is_ghost);
int workbench_material_get_composite_shader_index(WORKBENCH_PrivateData *wpd);
int workbench_material_get_prepass_shader_index(WORKBENCH_PrivateData *wpd,
bool is_uniform_color,
- bool is_hair);
+ bool is_hair,
+ bool is_texture_painting);
int workbench_material_get_accum_shader_index(WORKBENCH_PrivateData *wpd,
bool is_uniform_color,
- bool is_hair);
+ bool is_hair,
+ bool is_texture_painting);
void workbench_material_shgroup_uniform(WORKBENCH_PrivateData *wpd,
DRWShadingGroup *grp,
WORKBENCH_MaterialData *material,
diff --git a/source/blender/draw/modes/paint_texture_mode.c b/source/blender/draw/modes/paint_texture_mode.c
index 6c2f170a220..7c164a74f2f 100644
--- a/source/blender/draw/modes/paint_texture_mode.c
+++ b/source/blender/draw/modes/paint_texture_mode.c
@@ -63,7 +63,7 @@ typedef struct PAINT_TEXTURE_PassList {
/* Declare all passes here and init them in
* PAINT_TEXTURE_cache_init().
* Only contains (DRWPass *) */
- struct DRWPass *image_faces;
+ struct DRWPass *stencil_mask_overlay;
struct DRWPass *wire_select_overlay;
struct DRWPass *face_select_overlay;
@@ -107,9 +107,7 @@ typedef struct PAINT_TEXTURE_Shaders {
* Add sources to source/blender/draw/modes/shaders
* init in PAINT_TEXTURE_engine_init();
* free in PAINT_TEXTURE_engine_free(); */
- struct GPUShader *fallback;
- struct GPUShader *image;
- struct GPUShader *image_mask;
+ struct GPUShader *stencil_mask_overlay;
struct GPUShader *wire_select_overlay;
struct GPUShader *face_select_overlay;
@@ -124,8 +122,7 @@ static struct {
typedef struct PAINT_TEXTURE_PrivateData {
/* This keeps the references of the shading groups for
* easy access in PAINT_TEXTURE_cache_populate() */
- DRWShadingGroup *shgroup_fallback;
- DRWShadingGroup **shgroup_image_array;
+ DRWShadingGroup *shgroup_stencil_mask;
/* face-mask */
DRWShadingGroup *lwire_select_shgrp;
@@ -144,18 +141,9 @@ static void PAINT_TEXTURE_engine_init(void *vedata)
const DRWContextState *draw_ctx = DRW_context_state_get();
PAINT_TEXTURE_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
- if (!sh_data->fallback) {
+ if (!sh_data->stencil_mask_overlay) {
const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[draw_ctx->sh_cfg];
- sh_data->fallback = GPU_shader_create_from_arrays({
- .vert = (const char *[]){sh_cfg_data->lib,
- datatoc_common_view_lib_glsl,
- datatoc_paint_face_vert_glsl,
- NULL},
- .frag = (const char *[]){datatoc_gpu_shader_uniform_color_frag_glsl, NULL},
- .defs = (const char *[]){sh_cfg_data->def, NULL},
- });
-
- sh_data->image = GPU_shader_create_from_arrays({
+ sh_data->stencil_mask_overlay = GPU_shader_create_from_arrays({
.vert = (const char *[]){sh_cfg_data->lib,
datatoc_common_globals_lib_glsl,
datatoc_common_view_lib_glsl,
@@ -167,18 +155,6 @@ static void PAINT_TEXTURE_engine_init(void *vedata)
.defs = (const char *[]){sh_cfg_data->def, NULL},
});
- sh_data->image_mask = GPU_shader_create_from_arrays({
- .vert = (const char *[]){sh_cfg_data->lib,
- datatoc_common_globals_lib_glsl,
- datatoc_common_view_lib_glsl,
- datatoc_paint_texture_vert_glsl,
- NULL},
- .frag = (const char *[]){datatoc_common_colormanagement_lib_glsl,
- datatoc_paint_texture_frag_glsl,
- NULL},
- .defs = (const char *[]){sh_cfg_data->def, "#define TEXTURE_PAINT_MASK\n", NULL},
- });
-
sh_data->wire_select_overlay = GPU_shader_create_from_arrays({
.vert = (const char *[]){sh_cfg_data->lib,
datatoc_common_globals_lib_glsl,
@@ -204,45 +180,39 @@ static void PAINT_TEXTURE_engine_init(void *vedata)
if (!stl->g_data) {
/* Alloc transient pointers */
stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
- stl->g_data->shgroup_image_array = NULL;
+ stl->g_data->shgroup_stencil_mask = NULL;
}
stl->g_data->view_wires = DRW_view_create_with_zoffset(draw_ctx->rv3d, 1.0f);
}
-static DRWShadingGroup *create_texture_paint_shading_group(PAINT_TEXTURE_PassList *psl,
- const Image *image,
- const struct GPUTexture *texture,
- const DRWContextState *draw_ctx,
- const bool nearest_interp)
+static DRWShadingGroup *create_texture_paint_stencil_mask_shading_group(
+ PAINT_TEXTURE_PassList *psl, const DRWContextState *draw_ctx)
{
PAINT_TEXTURE_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
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 ? sh_data->image_mask : sh_data->image,
- psl->image_faces);
- DRW_shgroup_uniform_texture(grp, "image", texture);
- DRW_shgroup_uniform_bool_copy(
- grp, "imagePremultiplied", (image->alpha_mode == IMA_ALPHA_PREMUL));
+ DRWShadingGroup *grp = DRW_shgroup_create(sh_data->stencil_mask_overlay,
+ psl->stencil_mask_overlay);
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);
- DRW_shgroup_uniform_texture(grp, "maskingImage", stencil);
- DRW_shgroup_uniform_bool_copy(
- grp, "maskingImagePremultiplied", (imapaint->stencil->alpha_mode == IMA_ALPHA_PREMUL));
- DRW_shgroup_uniform_vec3(grp, "maskingColor", imapaint->stencil_col, 1);
- DRW_shgroup_uniform_bool_copy(grp, "maskingInvertStencil", masking_inverted);
- }
+
+ const bool masking_inverted = (imapaint->flag & IMAGEPAINT_PROJECT_LAYER_STENCIL_INV) > 0;
+ GPUTexture *stencil = GPU_texture_from_blender(imapaint->stencil, NULL, GL_TEXTURE_2D);
+ DRW_shgroup_uniform_texture(grp, "maskingImage", stencil);
+ DRW_shgroup_uniform_bool_copy(
+ grp, "maskingImagePremultiplied", (imapaint->stencil->alpha_mode == IMA_ALPHA_PREMUL));
+ DRW_shgroup_uniform_vec3(grp, "maskingColor", imapaint->stencil_col, 1);
+ DRW_shgroup_uniform_bool_copy(grp, "maskingInvertStencil", masking_inverted);
return grp;
}
+static bool PAINT_TEXTURE_stencil_mask_enabled(const ImagePaintSettings *imapaint)
+{
+ return imapaint->flag & IMAGEPAINT_PROJECT_LAYER_STENCIL && imapaint->stencil != NULL;
+}
+
/* Here init all passes and shading groups
* Assume that all Passes are NULL */
static void PAINT_TEXTURE_cache_init(void *vedata)
@@ -251,69 +221,17 @@ static void PAINT_TEXTURE_cache_init(void *vedata)
PAINT_TEXTURE_StorageList *stl = ((PAINT_TEXTURE_Data *)vedata)->stl;
const DRWContextState *draw_ctx = DRW_context_state_get();
- PAINT_TEXTURE_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
-
- /* Create a pass */
- {
- DRWPass *pass = DRW_pass_create(
- "Image Color Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND_ALPHA);
- DRWShadingGroup *shgrp = DRW_shgroup_create(sh_data->fallback, pass);
-
- /* Uniforms need a pointer to it's value so be sure it's accessible at
- * any given time (i.e. use static vars) */
- static const float color[4] = {1.0f, 0.0f, 1.0f, 1.0};
- DRW_shgroup_uniform_vec4(shgrp, "color", color, 1);
-
- if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_state_enable(shgrp, DRW_STATE_CLIP_PLANES);
- }
- psl->image_faces = pass;
- stl->g_data->shgroup_fallback = shgrp;
- }
+ Scene *scene = draw_ctx->scene;
+ const ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
- MEM_SAFE_FREE(stl->g_data->shgroup_image_array);
+ PAINT_TEXTURE_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
- Object *ob = draw_ctx->obact;
- if (ob && ob->type == OB_MESH) {
- Scene *scene = draw_ctx->scene;
- const ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
- const bool use_material_slots = (imapaint->mode == IMAGEPAINT_MODE_MATERIAL);
- const Mesh *me = ob->data;
- const int mat_nr = max_ii(1, me->totcol);
-
- stl->g_data->shgroup_image_array = MEM_mallocN(
- sizeof(*stl->g_data->shgroup_image_array) * (use_material_slots ? mat_nr : 1), __func__);
-
- if (use_material_slots) {
- for (int i = 0; i < mat_nr; i++) {
- 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 = GPU_texture_from_blender(ima, NULL, GL_TEXTURE_2D);
-
- if (tex) {
- DRWShadingGroup *grp = create_texture_paint_shading_group(
- psl, ima, tex, draw_ctx, interp == SHD_INTERP_CLOSEST);
- stl->g_data->shgroup_image_array[i] = grp;
- }
- else {
- stl->g_data->shgroup_image_array[i] = NULL;
- }
- }
- }
- else {
- Image *ima = imapaint->canvas;
- GPUTexture *tex = GPU_texture_from_blender(ima, NULL, GL_TEXTURE_2D);
-
- if (tex) {
- DRWShadingGroup *grp = create_texture_paint_shading_group(
- psl, ima, tex, draw_ctx, imapaint->interp == IMAGEPAINT_INTERP_CLOSEST);
- stl->g_data->shgroup_image_array[0] = grp;
- }
- else {
- stl->g_data->shgroup_image_array[0] = NULL;
- }
- }
+ /* Stencil Mask */
+ if (PAINT_TEXTURE_stencil_mask_enabled(imapaint)) {
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND_ALPHA;
+ psl->stencil_mask_overlay = DRW_pass_create("Stencil Mask Pass", state);
+ stl->g_data->shgroup_stencil_mask = create_texture_paint_stencil_mask_shading_group(psl,
+ draw_ctx);
}
/* Face Mask */
@@ -358,41 +276,18 @@ static void PAINT_TEXTURE_cache_populate(void *vedata, Object *ob)
if ((ob->type == OB_MESH) && (draw_ctx->obact == ob)) {
/* Get geometry cache */
- const Mesh *me = ob->data;
const Mesh *me_orig = DEG_get_original_object(ob)->data;
Scene *scene = draw_ctx->scene;
- const bool use_surface = draw_ctx->v3d->overlay.texture_paint_mode_opacity !=
- 0.0; // DRW_object_is_mode_shade(ob) == true;
- const bool use_material_slots = (scene->toolsettings->imapaint.mode ==
- IMAGEPAINT_MODE_MATERIAL);
+ const ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
+
const bool use_face_sel = (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
+ const bool masking_enabled = imapaint->flag & IMAGEPAINT_PROJECT_LAYER_STENCIL &&
+ imapaint->stencil != NULL;
- if (use_surface) {
- if (me->mloopuv != NULL) {
- if (use_material_slots) {
- int mat_nr = max_ii(1, me->totcol);
- struct GPUBatch **geom_array = DRW_cache_mesh_surface_texpaint_get(ob);
-
- for (int i = 0; i < mat_nr; i++) {
- const int index = use_material_slots ? i : 0;
- if ((i < me->totcol) && stl->g_data->shgroup_image_array[index]) {
- DRW_shgroup_call(stl->g_data->shgroup_image_array[index], geom_array[i], ob);
- }
- else {
- DRW_shgroup_call(stl->g_data->shgroup_fallback, geom_array[i], ob);
- }
- }
- }
- else {
- if (stl->g_data->shgroup_image_array[0]) {
- struct GPUBatch *geom = DRW_cache_mesh_surface_texpaint_single_get(ob);
- DRW_shgroup_call(stl->g_data->shgroup_image_array[0], geom, ob);
- }
- }
- }
- else {
- struct GPUBatch *geom = DRW_cache_mesh_surface_get(ob);
- DRW_shgroup_call(stl->g_data->shgroup_fallback, geom, ob);
+ if (masking_enabled) {
+ if (stl->g_data->shgroup_stencil_mask) {
+ struct GPUBatch *geom = DRW_cache_mesh_surface_texpaint_single_get(ob);
+ DRW_shgroup_call(stl->g_data->shgroup_stencil_mask, geom, ob);
}
}
@@ -408,32 +303,15 @@ static void PAINT_TEXTURE_cache_populate(void *vedata, Object *ob)
}
}
-/* Optional: Post-cache_populate callback */
-static void PAINT_TEXTURE_cache_finish(void *vedata)
-{
- PAINT_TEXTURE_PassList *psl = ((PAINT_TEXTURE_Data *)vedata)->psl;
- PAINT_TEXTURE_StorageList *stl = ((PAINT_TEXTURE_Data *)vedata)->stl;
-
- /* Do something here! dependent on the objects gathered */
- UNUSED_VARS(psl);
-
- MEM_SAFE_FREE(stl->g_data->shgroup_image_array);
-}
-
/* Draw time ! Control rendering pipeline from here */
static void PAINT_TEXTURE_draw_scene(void *vedata)
{
PAINT_TEXTURE_PassList *psl = ((PAINT_TEXTURE_Data *)vedata)->psl;
- PAINT_TEXTURE_FramebufferList *fbl = ((PAINT_TEXTURE_Data *)vedata)->fbl;
PAINT_TEXTURE_StorageList *stl = ((PAINT_TEXTURE_Data *)vedata)->stl;
- /* Default framebuffer and texture */
- DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
- DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
-
- UNUSED_VARS(fbl, dfbl, dtxl);
-
- DRW_draw_pass(psl->image_faces);
+ if (psl->stencil_mask_overlay) {
+ DRW_draw_pass(psl->stencil_mask_overlay);
+ }
DRW_draw_pass(psl->face_select_overlay);
@@ -469,7 +347,7 @@ DrawEngineType draw_engine_paint_texture_type = {
&PAINT_TEXTURE_engine_free,
&PAINT_TEXTURE_cache_init,
&PAINT_TEXTURE_cache_populate,
- &PAINT_TEXTURE_cache_finish,
+ NULL,
NULL, /* draw_background but not needed by mode engines */
&PAINT_TEXTURE_draw_scene,
NULL,
diff --git a/source/blender/draw/modes/shaders/paint_texture_frag.glsl b/source/blender/draw/modes/shaders/paint_texture_frag.glsl
index e8722590802..edd7c2af001 100644
--- a/source/blender/draw/modes/shaders/paint_texture_frag.glsl
+++ b/source/blender/draw/modes/shaders/paint_texture_frag.glsl
@@ -1,35 +1,17 @@
-
-in vec2 uv_interp;
-#ifdef TEXTURE_PAINT_MASK
in vec2 masking_uv_interp;
-#endif
out vec4 fragColor;
-uniform sampler2D image;
-uniform bool imagePremultiplied;
uniform float alpha = 1.0;
-uniform bool nearestInterp;
-#ifdef TEXTURE_PAINT_MASK
uniform sampler2D maskingImage;
uniform bool maskingImagePremultiplied;
uniform vec3 maskingColor;
uniform bool maskingInvertStencil;
-#endif
void main()
{
- vec2 uv = uv_interp;
- if (nearestInterp) {
- vec2 tex_size = vec2(textureSize(image, 0).xy);
- uv = (floor(uv_interp * tex_size) + 0.5) / tex_size;
- }
-
- vec4 color = texture_read_as_srgb(image, imagePremultiplied, uv);
- color.a *= alpha;
-#ifdef TEXTURE_PAINT_MASK
vec4 mask = vec4(
texture_read_as_srgb(maskingImage, maskingImagePremultiplied, masking_uv_interp).rgb, 1.0);
if (maskingInvertStencil) {
@@ -37,8 +19,7 @@ void main()
}
float mask_step = smoothstep(0, 3.0, mask.r + mask.g + mask.b);
mask.rgb *= maskingColor;
- color = mix(color, mask, mask_step);
-#endif
+ mask.a = mask_step * alpha;
- fragColor = color;
+ fragColor = mask;
}
diff --git a/source/blender/draw/modes/shaders/paint_texture_vert.glsl b/source/blender/draw/modes/shaders/paint_texture_vert.glsl
index 564f988348e..ddfc2b51437 100644
--- a/source/blender/draw/modes/shaders/paint_texture_vert.glsl
+++ b/source/blender/draw/modes/shaders/paint_texture_vert.glsl
@@ -1,27 +1,15 @@
-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()
{
vec3 world_pos = point_object_to_world(pos);
gl_Position = point_world_to_ndc(world_pos);
- uv_interp = u;
-
-#ifdef TEXTURE_PAINT_MASK
masking_uv_interp = mu;
-#endif
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance(world_pos);
diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h
index 31ffb3efebd..e7a4f9cbd4e 100644
--- a/source/blender/makesdna/DNA_view3d_types.h
+++ b/source/blender/makesdna/DNA_view3d_types.h
@@ -433,6 +433,10 @@ enum {
V3D_SHADING_TEXTURE_COLOR = 3,
V3D_SHADING_OBJECT_COLOR = 4,
V3D_SHADING_VERTEX_COLOR = 5,
+
+ /* Is used to display the object using the error color. For example when in
+ * solid texture paint mode without any textures configured */
+ V3D_SHADING_ERROR_COLOR = 999,
};
/** #View3DShading.background_type */
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index d3eb7a9258b..1c76753fb1b 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -3525,7 +3525,8 @@ static void rna_def_space_view3d_overlay(BlenderRNA *brna)
prop = RNA_def_property(srna, "texture_paint_mode_opacity", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "overlay.texture_paint_mode_opacity");
RNA_def_property_float_default(prop, 1.0f);
- RNA_def_property_ui_text(prop, "Texture Opacity", "Opacity of the texture paint mode overlay");
+ RNA_def_property_ui_text(
+ prop, "Stencil Opacity", "Opacity of the texture paint mode stencil mask overlay");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);