diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2020-02-19 03:44:52 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2020-02-19 03:57:06 +0300 |
commit | e82827bf6ed54a1d1552ac9176df9e309b4d29e2 (patch) | |
tree | 10b10084cc42f21d77ed7aca8cf0f424bc37c58f /source | |
parent | 77619f527403608a349b3037d18f71893d4484d1 (diff) |
DRW: New High Quality Normal & Tangent extract
This patch adds a dedicated path to extract 16bit normals instead of packing them into 10bits/comp.
The tangents are also packed to 10bits/comp if not using the new High Quality Normal option.
Fix T61024 Degraded texture shading on dense meshes
Reviewed By: brecht
Differential Revision: https://developer.blender.org/D6614
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/draw/intern/draw_cache_extract.h | 1 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache_extract_mesh.c | 174 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache_impl_mesh.c | 3 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_scene_types.h | 10 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_scene.c | 22 |
5 files changed, 196 insertions, 14 deletions
diff --git a/source/blender/draw/intern/draw_cache_extract.h b/source/blender/draw/intern/draw_cache_extract.h index 9228147af44..6226b5dcf7f 100644 --- a/source/blender/draw/intern/draw_cache_extract.h +++ b/source/blender/draw/intern/draw_cache_extract.h @@ -253,6 +253,7 @@ void mesh_buffer_cache_create_requested(MeshBatchCache *cache, const bool do_uvedit, const bool use_subsurf_fdots, const DRW_MeshCDMask *cd_layer_used, + const Scene *scene, const ToolSettings *ts, const bool use_hide); diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.c b/source/blender/draw/intern/draw_cache_extract_mesh.c index 61a4a963cf9..edd7dee004c 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh.c +++ b/source/blender/draw/intern/draw_cache_extract_mesh.c @@ -1580,6 +1580,81 @@ static const MeshExtract extract_pos_nor = { /** \} */ /* ---------------------------------------------------------------------- */ +/** \name Extract HQ Loop Normal + * \{ */ + +typedef struct gpuHQNor { + short x, y, z, w; +} gpuHQNor; + +static void *extract_lnor_hq_init(const MeshRenderData *mr, void *buf) +{ + static GPUVertFormat format = {0}; + if (format.attr_len == 0) { + GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); + GPU_vertformat_alias_add(&format, "lnor"); + } + GPUVertBuf *vbo = buf; + GPU_vertbuf_init_with_format(vbo, &format); + GPU_vertbuf_data_alloc(vbo, mr->loop_len); + + return vbo->data; +} + +static void extract_lnor_hq_loop_bmesh(const MeshRenderData *mr, int l, BMLoop *loop, void *data) +{ + if (mr->loop_normals) { + normal_float_to_short_v3(&((gpuHQNor *)data)[l].x, mr->loop_normals[l]); + } + else if (BM_elem_flag_test(loop->f, BM_ELEM_SMOOTH)) { + normal_float_to_short_v3(&((gpuHQNor *)data)[l].x, loop->v->no); + } + else { + normal_float_to_short_v3(&((gpuHQNor *)data)[l].x, loop->f->no); + } +} + +static void extract_lnor_hq_loop_mesh( + const MeshRenderData *mr, int l, const MLoop *mloop, int p, const MPoly *mpoly, void *data) +{ + if (mr->loop_normals) { + normal_float_to_short_v3(&((gpuHQNor *)data)[l].x, mr->loop_normals[l]); + } + else if (mpoly->flag & ME_SMOOTH) { + copy_v3_v3_short(&((gpuHQNor *)data)[l].x, mr->mvert[mloop->v].no); + } + else { + normal_float_to_short_v3(&((gpuHQNor *)data)[l].x, mr->poly_normals[p]); + } + /* Flag for paint mode overlay. */ + if (mpoly->flag & ME_HIDE) { + ((gpuHQNor *)data)[l].w = -1; + } + else if (mpoly->flag & ME_FACE_SEL) { + ((gpuHQNor *)data)[l].w = 1; + } + else { + ((gpuHQNor *)data)[l].w = 0; + } +} + +static const MeshExtract extract_lnor_hq = { + extract_lnor_hq_init, + NULL, + NULL, + extract_lnor_hq_loop_bmesh, + extract_lnor_hq_loop_mesh, + NULL, + NULL, + NULL, + NULL, + NULL, + MR_DATA_LOOP_NOR, + true, +}; + +/** \} */ +/* ---------------------------------------------------------------------- */ /** \name Extract Loop Normal * \{ */ @@ -1762,8 +1837,11 @@ static const MeshExtract extract_uv = { /** \name Extract Tangent layers * \{ */ -static void *extract_tan_init(const MeshRenderData *mr, void *buf) +static void extract_tan_ex(const MeshRenderData *mr, GPUVertBuf *vbo, const bool do_hq) { + GPUVertCompType comp_type = do_hq ? GPU_COMP_F32 : GPU_COMP_I10; + GPUVertFetchMode fetch_mode = do_hq ? GPU_FETCH_FLOAT : GPU_FETCH_INT_TO_FLOAT_UNIT; + GPUVertFormat format = {0}; GPU_vertformat_deinterleave(&format); @@ -1784,7 +1862,7 @@ static void *extract_tan_init(const MeshRenderData *mr, void *buf) GPU_vertformat_safe_attrib_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTRIB_NAME); /* Tangent layer name. */ BLI_snprintf(attr_name, sizeof(attr_name), "t%s", attr_safe_name); - GPU_vertformat_attr_add(&format, attr_name, GPU_COMP_F32, 4, GPU_FETCH_FLOAT); + GPU_vertformat_attr_add(&format, attr_name, comp_type, 4, fetch_mode); /* Active render layer name. */ if (i == CustomData_get_render_layer(cd_ldata, CD_MLOOPUV)) { GPU_vertformat_alias_add(&format, "t"); @@ -1860,7 +1938,7 @@ static void *extract_tan_init(const MeshRenderData *mr, void *buf) const char *layer_name = CustomData_get_layer_name(cd_ldata, CD_TANGENT, 0); GPU_vertformat_safe_attrib_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTRIB_NAME); BLI_snprintf(attr_name, sizeof(*attr_name), "t%s", attr_safe_name); - GPU_vertformat_attr_add(&format, attr_name, GPU_COMP_F32, 4, GPU_FETCH_FLOAT); + GPU_vertformat_attr_add(&format, attr_name, comp_type, 4, fetch_mode); GPU_vertformat_alias_add(&format, "t"); GPU_vertformat_alias_add(&format, "at"); } @@ -1876,23 +1954,56 @@ static void *extract_tan_init(const MeshRenderData *mr, void *buf) v_len = 1; } - GPUVertBuf *vbo = buf; GPU_vertbuf_init_with_format(vbo, &format); GPU_vertbuf_data_alloc(vbo, v_len); - float(*tan_data)[4] = (float(*)[4])vbo->data; - for (int i = 0; i < tan_len; i++) { - void *layer_data = CustomData_get_layer_named(cd_ldata, CD_TANGENT, tangent_names[i]); - memcpy(tan_data, layer_data, sizeof(*tan_data) * mr->loop_len); - tan_data += mr->loop_len; + if (do_hq) { + short(*tan_data)[4] = (short(*)[4])vbo->data; + for (int i = 0; i < tan_len; i++) { + const char *name = tangent_names[i]; + float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_named(cd_ldata, CD_TANGENT, name); + for (int l = 0; l < mr->loop_len; l++) { + normal_float_to_short_v3(*tan_data, layer_data[l]); + (*tan_data)[3] = (layer_data[l][3] > 0.0f) ? SHRT_MAX : SHRT_MIN; + tan_data++; + } + } + if (use_orco_tan) { + float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_n(cd_ldata, CD_TANGENT, 0); + for (int l = 0; l < mr->loop_len; l++) { + normal_float_to_short_v3(*tan_data, layer_data[l]); + (*tan_data)[3] = (layer_data[l][3] > 0.0f) ? SHRT_MAX : SHRT_MIN; + tan_data++; + } + } } - if (use_orco_tan) { - void *layer_data = CustomData_get_layer_n(cd_ldata, CD_TANGENT, 0); - memcpy(tan_data, layer_data, sizeof(*tan_data) * mr->loop_len); + else { + GPUPackedNormal *tan_data = (GPUPackedNormal *)vbo->data; + for (int i = 0; i < tan_len; i++) { + const char *name = tangent_names[i]; + float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_named(cd_ldata, CD_TANGENT, name); + for (int l = 0; l < mr->loop_len; l++) { + *tan_data = GPU_normal_convert_i10_v3(layer_data[l]); + tan_data->w = (layer_data[l][3] > 0.0f) ? 1 : -2; + tan_data++; + } + } + if (use_orco_tan) { + float(*layer_data)[4] = (float(*)[4])CustomData_get_layer_n(cd_ldata, CD_TANGENT, 0); + for (int l = 0; l < mr->loop_len; l++) { + *tan_data = GPU_normal_convert_i10_v3(layer_data[l]); + tan_data->w = (layer_data[l][3] > 0.0f) ? 1 : -2; + tan_data++; + } + } } CustomData_free_layers(cd_ldata, CD_TANGENT, mr->loop_len); +} +static void *extract_tan_init(const MeshRenderData *mr, void *buf) +{ + extract_tan_ex(mr, buf, false); return NULL; } @@ -1914,6 +2025,33 @@ static const MeshExtract extract_tan = { /** \} */ /* ---------------------------------------------------------------------- */ +/** \name Extract HQ Tangent layers + * \{ */ + +static void *extract_tan_hq_init(const MeshRenderData *mr, void *buf) +{ + extract_tan_ex(mr, buf, true); + return NULL; +} + +static const MeshExtract extract_tan_hq = { + extract_tan_hq_init, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + MR_DATA_POLY_NOR | MR_DATA_TAN_LOOP_NOR | MR_DATA_LOOPTRI, + false, +}; + +/** \} */ + +/* ---------------------------------------------------------------------- */ /** \name Extract VCol * \{ */ @@ -4354,11 +4492,20 @@ static void extract_range_task_create( } static void extract_task_create(TaskPool *task_pool, + const Scene *scene, const MeshRenderData *mr, const MeshExtract *extract, void *buf, int32_t *task_counter) { + const bool do_hq_normals = (scene->r.perf_flag & SCE_PERF_HQ_NORMALS) != 0; + if (do_hq_normals && (extract == &extract_lnor)) { + extract = &extract_lnor_hq; + } + if (do_hq_normals && (extract == &extract_tan)) { + extract = &extract_tan_hq; + } + /* Divide extraction of the VBO/IBO into sensible chunks of works. */ ExtractTaskData *taskdata = MEM_mallocN(sizeof(*taskdata), "ExtractTaskData"); taskdata->mr = mr; @@ -4419,6 +4566,7 @@ void mesh_buffer_cache_create_requested(MeshBatchCache *cache, const bool do_uvedit, const bool use_subsurf_fdots, const DRW_MeshCDMask *cd_layer_used, + const Scene *scene, const ToolSettings *ts, const bool use_hide) { @@ -4498,7 +4646,7 @@ void mesh_buffer_cache_create_requested(MeshBatchCache *cache, #define EXTRACT(buf, name) \ if (mbc.buf.name) { \ extract_task_create( \ - task_pool, mr, &extract_##name, mbc.buf.name, &task_counters[counter_used++]); \ + task_pool, scene, mr, &extract_##name, mbc.buf.name, &task_counters[counter_used++]); \ } \ ((void)0) diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c index 5b273159cdf..2e423c4dfe2 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.c +++ b/source/blender/draw/intern/draw_cache_impl_mesh.c @@ -1341,6 +1341,7 @@ void DRW_mesh_batch_cache_create_requested( true, false, &cache->cd_used, + scene, ts, true); } @@ -1355,6 +1356,7 @@ void DRW_mesh_batch_cache_create_requested( false, use_subsurf_fdots, &cache->cd_used, + scene, ts, true); } @@ -1368,6 +1370,7 @@ void DRW_mesh_batch_cache_create_requested( false, use_subsurf_fdots, &cache->cd_used, + scene, ts, use_hide); diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 13bbd9319a0..f66ce132edb 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -750,7 +750,10 @@ typedef struct RenderData { /* render engine */ char engine[32]; - char _pad2[4]; + char _pad2[2]; + + /* Performance Options */ + short perf_flag; /* Cycles baking */ struct BakeData bake; @@ -776,6 +779,11 @@ typedef struct RenderData { struct CurveMapping mblur_shutter_curve; } RenderData; +/* RenderData.quality_flag */ +typedef enum eQualityOption { + SCE_PERF_HQ_NORMALS = (1 << 0), +} eQualityOption; + /* RenderData.hair_type */ typedef enum eHairType { SCE_HAIR_SHAPE_STRAND = 0, diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 5e5bafdc178..d2a17967de9 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -1654,6 +1654,20 @@ static void rna_Scene_world_update(Main *bmain, Scene *scene, PointerRNA *ptr) DEG_relations_tag_update(bmain); } +static void rna_Scene_mesh_quality_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) +{ + Scene *scene = (Scene *)ptr->owner_id; + + FOREACH_SCENE_OBJECT_BEGIN (scene, ob) { + if (ob->type == OB_MESH) { + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + } + } + FOREACH_SCENE_OBJECT_END; + + rna_Scene_glsl_update(bmain, scene, ptr); +} + void rna_Scene_freestyle_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { Scene *scene = (Scene *)ptr->owner_id; @@ -5762,6 +5776,14 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Additional Subdiv", "Additional subdivision along the hair"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_glsl_update"); + /* Performance */ + prop = RNA_def_property(srna, "use_high_quality_normals", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "perf_flag", SCE_PERF_HQ_NORMALS); + RNA_def_property_ui_text(prop, + "High Quality Normals", + "Use high quality tangent space at the cost of lower performance"); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_mesh_quality_update"); + /* border */ prop = RNA_def_property(srna, "use_border", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mode", R_BORDER); |