TexturePaint: Force Workbench Texture Color Mode
When in texture paint mode and in solid mode the object that is being texture painted will be rendered by the workbench engine with textures. All other objects would render the same. For other cases the texture paint draw engine will still draw the texture. The texture mode draw engine now only drawn the masks. The opacity sliders influences the texture mask. This change has been implemented conserably. In the future we need to look into making this better, like adding support that every object can be colored differently. Currently when rendering in the workbench we can have up to 3 different color types active (what the user selected, the fallback in case no materials have been configured and this one, forcing textures) Reviewed By: fclem, brecht Differential Revision: https://developer.blender.org/D5190
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
Scene *scene = draw_ctx->scene;
|
||||
const ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
MEM_SAFE_FREE(stl->g_data->shgroup_image_array);
|
||||
|
||||
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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user