diff options
author | Jeroen Bakker <j.bakker@atmind.nl> | 2018-05-07 15:59:27 +0300 |
---|---|---|
committer | Jeroen Bakker <j.bakker@atmind.nl> | 2018-05-07 15:59:27 +0300 |
commit | f09d3a7a4027229df88a0b0c0d42a2b75efcc953 (patch) | |
tree | 87b24ad41431f707aff2b949a8a6ea3f2ba3b137 /source | |
parent | e3d30ffb9205a4974ecc551a1a2af842622855b6 (diff) |
Workbench: Texture Shading mode
Diffstat (limited to 'source')
6 files changed, 160 insertions, 46 deletions
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl index 7ed5ecca45f..7853e361172 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl @@ -1,9 +1,15 @@ uniform int object_id = 0; uniform vec3 object_color = vec3(1.0, 0.0, 1.0); +#ifdef OB_TEXTURE +uniform sampler2D image; +#endif #ifdef V3D_LIGHTING_STUDIO in vec3 normal_viewport; #endif /* V3D_LIGHTING_STUDIO */ +#ifdef OB_TEXTURE +in vec2 uv_interp; +#endif /* OB_TEXTURE */ layout(location=0) out uint objectId; layout(location=1) out vec4 diffuseColor; @@ -18,7 +24,13 @@ layout(location=2) out vec3 normalViewport; void main() { objectId = uint(object_id); +#ifdef OB_SOLID diffuseColor = vec4(object_color, 0.0); +#endif /* OB_SOLID */ +#ifdef OB_TEXTURE + diffuseColor = texture(image, uv_interp); +#endif /* OB_TEXTURE */ + #ifdef V3D_LIGHTING_STUDIO #ifdef WORKBENCH_ENCODE_NORMALS if (!gl_FrontFacing) { @@ -26,6 +38,7 @@ void main() diffuseColor.a = 1.0; } else { normalViewport = normal_encode(normal_viewport); + diffuseColor.a = 0.0; } #else /* WORKBENCH_ENCODE_NORMALS */ normalViewport = normal_viewport; diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl index 8f62ddb161d..22b16bf1d6a 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl @@ -7,13 +7,22 @@ in vec3 pos; #ifdef V3D_LIGHTING_STUDIO in vec3 nor; #endif /* V3D_LIGHTING_STUDIO */ +#ifdef OB_TEXTURE +in vec2 uv; +#endif #ifdef V3D_LIGHTING_STUDIO out vec3 normal_viewport; #endif /* V3D_LIGHTING_STUDIO */ +#ifdef OB_TEXTURE +out vec2 uv_interp; +#endif void main() { +#ifdef OB_TEXTURE + uv_interp = uv; +#endif #ifdef V3D_LIGHTING_STUDIO normal_viewport = normalize(NormalMatrix * nor); #endif /* V3D_LIGHTING_STUDIO */ diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c index 258ce500191..b9c51552b50 100644 --- a/source/blender/draw/engines/workbench/workbench_materials.c +++ b/source/blender/draw/engines/workbench/workbench_materials.c @@ -25,15 +25,24 @@ #include "workbench_private.h" +#include "BIF_gl.h" + #include "BLI_alloca.h" #include "BLI_dynstr.h" #include "BLI_utildefines.h" +#include "BKE_node.h" #include "BKE_particle.h" +#include "DNA_image_types.h" +#include "DNA_mesh_types.h" #include "DNA_modifier_types.h" +#include "DNA_node_types.h" + +#include "ED_uvedit.h" #include "GPU_shader.h" +#include "GPU_texture.h" #include "UI_resources.h" @@ -75,7 +84,7 @@ extern DrawEngineType draw_engine_workbench_solid; #define OBJECT_ID_PASS_ENABLED(wpd) (wpd->shading.flag & V3D_SHADING_OBJECT_OVERLAP) #define NORMAL_VIEWPORT_PASS_ENABLED(wpd) (wpd->shading.light & V3D_LIGHTING_STUDIO) #define SHADOW_ENABLED(wpd) (wpd->shading.flag & V3D_SHADING_SHADOW) -static char *workbench_build_defines(WORKBENCH_PrivateData *wpd) +static char *workbench_build_defines(WORKBENCH_PrivateData *wpd, int drawtype) { char *str = NULL; @@ -87,6 +96,14 @@ static char *workbench_build_defines(WORKBENCH_PrivateData *wpd) if (wpd->shading.light & V3D_LIGHTING_STUDIO) { BLI_dynstr_appendf(ds, "#define V3D_LIGHTING_STUDIO\n"); } + switch(drawtype) { + case OB_SOLID: + BLI_dynstr_appendf(ds, "#define OB_SOLID\n"); + break; + case OB_TEXTURE: + BLI_dynstr_appendf(ds, "#define OB_TEXTURE\n"); + break; + } #ifdef WORKBENCH_ENCODE_NORMALS BLI_dynstr_appendf(ds, "#define WORKBENCH_ENCODE_NORMALS\n"); @@ -135,44 +152,65 @@ static char *workbench_build_prepass_frag(void) return str; } -static int get_shader_index(WORKBENCH_PrivateData *wpd) +static int get_shader_index(WORKBENCH_PrivateData *wpd, int drawtype) { const int DRAWOPTIONS_MASK = V3D_SHADING_OBJECT_OVERLAP; int index = (wpd->shading.flag & DRAWOPTIONS_MASK); index = (index << 2) + wpd->shading.light; + /* set the drawtype flag + 0 = OB_SOLID, + 1 = OB_TEXTURE */ + index = index << 1; + SET_FLAG_FROM_TEST(index, drawtype == OB_TEXTURE, 1); return index; } -static void select_deferred_shaders(WORKBENCH_PrivateData *wpd) -{ - int index = get_shader_index(wpd); - +static void ensure_deferred_shaders(WORKBENCH_PrivateData *wpd, int index, int drawtype) { if (e_data.prepass_sh_cache[index] == NULL) { - char *defines = workbench_build_defines(wpd); + char *defines = workbench_build_defines(wpd, drawtype); char *composite_frag = workbench_build_composite_frag(wpd); char *prepass_frag = workbench_build_prepass_frag(); e_data.prepass_sh_cache[index] = DRW_shader_create(datatoc_workbench_prepass_vert_glsl, NULL, prepass_frag, defines); - e_data.composite_sh_cache[index] = DRW_shader_create_fullscreen(composite_frag, defines); + if (drawtype == OB_SOLID) { + e_data.composite_sh_cache[index] = DRW_shader_create_fullscreen(composite_frag, defines); + } MEM_freeN(prepass_frag); MEM_freeN(composite_frag); MEM_freeN(defines); } +} + +static void select_deferred_shaders(WORKBENCH_PrivateData *wpd) +{ + int index_solid = get_shader_index(wpd, OB_SOLID); + int index_texture = get_shader_index(wpd, OB_TEXTURE); + + ensure_deferred_shaders(wpd, index_solid, OB_SOLID); + ensure_deferred_shaders(wpd, index_texture, OB_TEXTURE); - wpd->prepass_sh = e_data.prepass_sh_cache[index]; - wpd->composite_sh = e_data.composite_sh_cache[index]; + wpd->prepass_solid_sh = e_data.prepass_sh_cache[index_solid]; + wpd->prepass_texture_sh = e_data.prepass_sh_cache[index_texture]; + wpd->composite_sh = e_data.composite_sh_cache[index_solid]; } /* Functions */ static uint get_material_hash(WORKBENCH_MaterialData *material_template) { + /* TODO: make a C-string with settings and hash the string */ uint input[4]; + uint result; float *color = material_template->color; input[0] = (uint)(color[0] * 512); input[1] = (uint)(color[1] * 512); input[2] = (uint)(color[2] * 512); input[3] = material_template->object_id; + result = BLI_ghashutil_uinthash_v4_murmur(input); - return BLI_ghashutil_uinthash_v4_murmur(input); + if (material_template->drawtype == OB_TEXTURE) { + /* add texture reference */ + result += BLI_ghashutil_inthash_p_murmur(material_template->ima); + } + return result; } static void workbench_init_object_data(ObjectEngineData *engine_data) @@ -183,11 +221,13 @@ static void workbench_init_object_data(ObjectEngineData *engine_data) static void get_material_solid_color(WORKBENCH_PrivateData *wpd, Object *ob, Material *mat, float *color, float hsv_saturation, float hsv_value) { + /* When in OB_TEXTURE always uyse V3D_SHADING_MATERIAL_COLOR as fallback when no texture could be determined */ + int color_type = wpd->drawtype == OB_SOLID? wpd->shading.color_type:V3D_SHADING_MATERIAL_COLOR; static float default_color[] = {0.8f, 0.8f, 0.8f}; - if (DRW_object_is_paint_mode(ob) || wpd->shading.color_type == V3D_SHADING_SINGLE_COLOR) { + if (DRW_object_is_paint_mode(ob) || color_type == V3D_SHADING_SINGLE_COLOR) { copy_v3_v3(color, wpd->shading.single_color); } - else if (wpd->shading.color_type == V3D_SHADING_RANDOM_COLOR) { + else if (color_type == V3D_SHADING_RANDOM_COLOR) { uint hash = BLI_ghashutil_strhash_p_murmur(ob->id.name); if (ob->id.lib) { hash = (hash * 13) ^ BLI_ghashutil_strhash_p_murmur(ob->id.lib->name); @@ -197,7 +237,7 @@ static void get_material_solid_color(WORKBENCH_PrivateData *wpd, Object *ob, Mat float hsv[3] = {offset, hsv_saturation, hsv_value}; hsv_to_rgb_v(hsv, color); } - else if (wpd->shading.color_type == V3D_SHADING_OBJECT_COLOR) { + else if (color_type == V3D_SHADING_OBJECT_COLOR) { copy_v3_v3(color, ob->col); } else { @@ -299,12 +339,15 @@ void workbench_materials_cache_init(WORKBENCH_Data *vedata) View3D *v3d = DCS->v3d; if (v3d) { wpd->shading = v3d->shading; + wpd->drawtype = v3d->drawtype; } else { + /* XXX: We should get the default shading from the view layer, after we implemented the render callback */ memset(&wpd->shading, 0, sizeof(wpd->shading)); wpd->shading.light = V3D_LIGHTING_STUDIO; wpd->shading.shadow_intensity = 0.5; copy_v3_fl(wpd->shading.single_color, 0.8f); + wpd->drawtype = OB_SOLID; } select_deferred_shaders(wpd); @@ -365,7 +408,7 @@ void workbench_materials_cache_init(WORKBENCH_Data *vedata) } } } -static WORKBENCH_MaterialData *get_or_create_material_data(WORKBENCH_Data *vedata, IDProperty *props, Object *ob, Material *mat) +static WORKBENCH_MaterialData *get_or_create_material_data(WORKBENCH_Data *vedata, IDProperty *props, Object *ob, Material *mat, Image *ima, int drawtype) { WORKBENCH_StorageList *stl = vedata->stl; WORKBENCH_PassList *psl = vedata->psl; @@ -374,24 +417,35 @@ static WORKBENCH_MaterialData *get_or_create_material_data(WORKBENCH_Data *vedat WORKBENCH_ObjectData *engine_object_data = (WORKBENCH_ObjectData *)DRW_object_engine_data_ensure( ob, &draw_engine_workbench_solid, sizeof(WORKBENCH_ObjectData), &workbench_init_object_data, NULL); WORKBENCH_MaterialData material_template; - float color[3]; const float hsv_saturation = BKE_collection_engine_property_value_get_float(props, "random_object_color_saturation"); const float hsv_value = BKE_collection_engine_property_value_get_float(props, "random_object_color_value"); /* Solid */ - get_material_solid_color(wpd, ob, mat, color, hsv_saturation, hsv_value); - copy_v3_v3(material_template.color, color); + get_material_solid_color(wpd, ob, mat, material_template.color, hsv_saturation, hsv_value); material_template.object_id = engine_object_data->object_id; + material_template.drawtype = drawtype; + material_template.ima = ima; unsigned int hash = get_material_hash(&material_template); material = BLI_ghash_lookup(wpd->material_hash, SET_UINT_IN_POINTER(hash)); if (material == NULL) { material = MEM_mallocN(sizeof(WORKBENCH_MaterialData), __func__); - material->shgrp = DRW_shgroup_create(wpd->prepass_sh, psl->prepass_pass); + material->shgrp = DRW_shgroup_create(drawtype == OB_SOLID?wpd->prepass_solid_sh:wpd->prepass_texture_sh, psl->prepass_pass); DRW_shgroup_stencil_mask(material->shgrp, 0xFF); material->object_id = engine_object_data->object_id; copy_v3_v3(material->color, material_template.color); - DRW_shgroup_uniform_vec3(material->shgrp, "object_color", material->color, 1); + switch(drawtype) { + case OB_SOLID: + DRW_shgroup_uniform_vec3(material->shgrp, "object_color", material->color, 1); + break; + + case OB_TEXTURE: + { + GPUTexture *tex = GPU_texture_from_blender(ima, NULL, GL_TEXTURE_2D, false, false, false); + DRW_shgroup_uniform_texture(material->shgrp, "image", tex); + break; + } + } DRW_shgroup_uniform_int(material->shgrp, "object_id", &material->object_id, 1); BLI_ghash_insert(wpd->material_hash, SET_UINT_IN_POINTER(hash), material); } @@ -420,7 +474,7 @@ static void workbench_cache_populate_particles(WORKBENCH_Data *vedata, IDPropert if (draw_as == PART_DRAW_PATH) { struct Gwn_Batch *geom = DRW_cache_particles_get_hair(psys, NULL); - WORKBENCH_MaterialData *material = get_or_create_material_data(vedata, props, ob, NULL); + WORKBENCH_MaterialData *material = get_or_create_material_data(vedata, props, ob, NULL, NULL, OB_SOLID); DRW_shgroup_call_add(material->shgrp, geom, mat); } } @@ -447,33 +501,62 @@ void workbench_materials_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob const DRWContextState *draw_ctx = DRW_context_state_get(); const bool is_active = (ob == draw_ctx->obact); const bool is_sculpt_mode = is_active && (draw_ctx->object_mode & OB_MODE_SCULPT) != 0; - - if (vedata->stl->g_data->shading.color_type != V3D_SHADING_MATERIAL_COLOR || is_sculpt_mode) { - /* No material split needed */ - struct Gwn_Batch *geom = DRW_cache_object_surface_get(ob); - if (geom) { - material = get_or_create_material_data(vedata, props, ob, NULL); - if (is_sculpt_mode) { - DRW_shgroup_call_sculpt_add(material->shgrp, ob, ob->obmat); - } - else { - DRW_shgroup_call_object_add(material->shgrp, geom, ob); + bool is_drawn = false; + + if (!is_sculpt_mode && wpd->drawtype == OB_TEXTURE && ob->type == OB_MESH) + { + const Mesh *me = ob->data; + if (me->mloopuv) { + struct Gwn_Batch **geom_array = me->totcol ? DRW_cache_mesh_surface_texpaint_get(ob) : NULL; + const int materials_len = MAX2(1, (is_sculpt_mode ? 1 : ob->totcol)); + struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len); + if (materials_len > 0 && geom_array) { + for (int i = 0; i < materials_len; i++) { + Material *mat = give_current_material(ob, i + 1); + Image *image; + ED_object_get_active_image(ob, i + 1, &image, NULL, NULL, NULL); + /* use OB_SOLID when no texture could be determined */ + int mat_drawtype = OB_SOLID; + if (image) { + mat_drawtype = OB_TEXTURE; + } + material = get_or_create_material_data(vedata, props, ob, mat, image, mat_drawtype); + DRW_shgroup_call_add(material->shgrp, geom_array[i], ob->obmat); + } + is_drawn = true; } } } - else { /* MATERIAL colors */ - const int materials_len = MAX2(1, (is_sculpt_mode ? 1 : ob->totcol)); - struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len); - for (int i = 0; i < materials_len; i ++) { - gpumat_array[i] = NULL; + + /* Fallback from not drawn OB_TEXTURE mode or just OB_SOLID mode */ + if (!is_drawn) { + if ((wpd->shading.color_type != V3D_SHADING_MATERIAL_COLOR) || is_sculpt_mode) { + /* No material split needed */ + struct Gwn_Batch *geom = DRW_cache_object_surface_get(ob); + if (geom) { + material = get_or_create_material_data(vedata, props, ob, NULL, NULL, OB_SOLID); + if (is_sculpt_mode) { + DRW_shgroup_call_sculpt_add(material->shgrp, ob, ob->obmat); + } + else { + DRW_shgroup_call_object_add(material->shgrp, geom, ob); + } + } } + else { /* MATERIAL colors */ + const int materials_len = MAX2(1, (is_sculpt_mode ? 1 : ob->totcol)); + struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len); + for (int i = 0; i < materials_len; i ++) { + gpumat_array[i] = NULL; + } - struct Gwn_Batch **mat_geom = DRW_cache_object_surface_material_get(ob, gpumat_array, materials_len, NULL, NULL, NULL); - if (mat_geom) { - for (int i = 0; i < materials_len; ++i) { - Material *mat = give_current_material(ob, i + 1); - material = get_or_create_material_data(vedata, props, ob, mat); - DRW_shgroup_call_object_add(material->shgrp, mat_geom[i], ob); + struct Gwn_Batch **mat_geom = DRW_cache_object_surface_material_get(ob, gpumat_array, materials_len, NULL, NULL, NULL); + if (mat_geom) { + for (int i = 0; i < materials_len; ++i) { + Material *mat = give_current_material(ob, i + 1); + material = get_or_create_material_data(vedata, props, ob, mat, NULL, OB_SOLID); + DRW_shgroup_call_object_add(material->shgrp, mat_geom[i], ob); + } } } } diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h index 3c2e6d43ab1..76f8f7bfd05 100644 --- a/source/blender/draw/engines/workbench/workbench_private.h +++ b/source/blender/draw/engines/workbench/workbench_private.h @@ -27,13 +27,17 @@ #define __WORKBENCH_PRIVATE_H__ -#include "DRW_render.h" +#include "DNA_image_types.h" #include "DNA_view3d_types.h" +#include "DRW_render.h" + + #define WORKBENCH_ENGINE "BLENDER_WORKBENCH" #define M_GOLDEN_RATION_CONJUGATE 0.618033988749895 #define WORKBENCH_ENCODE_NORMALS + typedef struct WORKBENCH_FramebufferList { struct GPUFrameBuffer *prepass_fb; struct GPUFrameBuffer *composite_fb; @@ -73,9 +77,11 @@ BLI_STATIC_ASSERT_ALIGN(WORKBENCH_UBO_World, 16) typedef struct WORKBENCH_PrivateData { struct GHash *material_hash; - struct GPUShader *prepass_sh; + struct GPUShader *prepass_solid_sh; + struct GPUShader *prepass_texture_sh; struct GPUShader *composite_sh; View3DShading shading; + int drawtype; struct GPUUniformBuffer *world_ubo; struct DRWShadingGroup *shadow_shgrp; WORKBENCH_UBO_World world_data; @@ -85,6 +91,8 @@ typedef struct WORKBENCH_MaterialData { /* Solid color */ float color[3]; int object_id; + int drawtype; + Image* ima; /* Linked shgroup for drawing */ DRWShadingGroup *shgrp; diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 907c62d091e..fcc8e73b626 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -987,10 +987,10 @@ static void drw_engines_enable_from_engine(RenderEngineType *engine_type, int dr break; case OB_SOLID: + case OB_TEXTURE: use_drw_engine(&draw_engine_workbench_solid); break; - case OB_TEXTURE: case OB_MATERIAL: case OB_RENDER: default: diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 7c5e798651b..d209e0f08da 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -674,6 +674,7 @@ static const EnumPropertyItem *rna_3DViewShading_type_itemf( int totitem = 0; RNA_enum_items_add_value(&item, &totitem, rna_enum_shading_type_items, OB_SOLID); + RNA_enum_items_add_value(&item, &totitem, rna_enum_shading_type_items, OB_TEXTURE); if (BKE_scene_uses_blender_eevee(scene)) { RNA_enum_items_add_value(&item, &totitem, rna_enum_shading_type_items, OB_RENDER); |