diff options
-rw-r--r-- | source/blender/draw/engines/eevee/eevee_data.c | 15 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/eevee_engine.c | 2 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/eevee_materials.c | 78 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/eevee_motion_blur.c | 51 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/eevee_private.h | 13 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/eevee_render.c | 2 | ||||
-rw-r--r-- | source/blender/draw/engines/workbench/workbench_engine.c | 3 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_common.h | 5 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_hair.c | 137 |
9 files changed, 237 insertions, 69 deletions
diff --git a/source/blender/draw/engines/eevee/eevee_data.c b/source/blender/draw/engines/eevee/eevee_data.c index ee70cebcfd2..b846480182b 100644 --- a/source/blender/draw/engines/eevee/eevee_data.c +++ b/source/blender/draw/engines/eevee/eevee_data.c @@ -160,7 +160,7 @@ EEVEE_HairMotionData *EEVEE_motion_blur_hair_data_get(EEVEE_ObjectMotionData *mb { if (mb_data->hair_data == NULL) { /* Ugly, we allocate for each modifiers and just fill based on modifier index in the list. */ - int psys_len = (ob->type != OB_CURVES) ? BLI_listbase_count(&ob->modifiers) : 1; + int psys_len = BLI_listbase_count(&ob->modifiers); EEVEE_HairMotionData *hair_step = MEM_callocN( sizeof(EEVEE_HairMotionData) + sizeof(hair_step->psys[0]) * psys_len, __func__); hair_step->psys_len = psys_len; @@ -170,6 +170,19 @@ EEVEE_HairMotionData *EEVEE_motion_blur_hair_data_get(EEVEE_ObjectMotionData *mb return mb_data->hair_data; } +EEVEE_HairMotionData *EEVEE_motion_blur_curves_data_get(EEVEE_ObjectMotionData *mb_data, + Object *ob) +{ + if (mb_data->hair_data == NULL) { + EEVEE_HairMotionData *hair_step = MEM_callocN( + sizeof(EEVEE_HairMotionData) + sizeof(hair_step->psys[0]), __func__); + hair_step->psys_len = 1; + hair_step->type = EEVEE_MOTION_DATA_HAIR; + mb_data->hair_data = hair_step; + } + return mb_data->hair_data; +} + /* View Layer data. */ void EEVEE_view_layer_data_free(void *storage) diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index 6cd1a31085f..0729b2078a8 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -111,7 +111,7 @@ void EEVEE_cache_populate(void *vedata, Object *ob) EEVEE_materials_cache_populate(vedata, sldata, ob, &cast_shadow); } else if (ob->type == OB_CURVES) { - EEVEE_object_hair_cache_populate(vedata, sldata, ob, &cast_shadow); + EEVEE_object_curves_cache_populate(vedata, sldata, ob, &cast_shadow); } else if (ob->type == OB_VOLUME) { EEVEE_volumes_cache_object_add(sldata, vedata, draw_ctx->scene, ob); diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index 4b9ad693971..c3f9a606dd0 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -740,34 +740,6 @@ BLI_INLINE EeveeMaterialCache eevee_material_cache_get( return matcache; } -static void eevee_hair_cache_populate(EEVEE_Data *vedata, - EEVEE_ViewLayerData *sldata, - Object *ob, - ParticleSystem *psys, - ModifierData *md, - int matnr, - bool *cast_shadow) -{ - EeveeMaterialCache matcache = eevee_material_cache_get(vedata, sldata, ob, matnr - 1, true); - - if (matcache.depth_grp) { - *matcache.depth_grp_p = DRW_shgroup_hair_create_sub(ob, psys, md, matcache.depth_grp, NULL); - DRW_shgroup_add_material_resources(*matcache.depth_grp_p, matcache.shading_gpumat); - } - if (matcache.shading_grp) { - *matcache.shading_grp_p = DRW_shgroup_hair_create_sub( - ob, psys, md, matcache.shading_grp, matcache.shading_gpumat); - DRW_shgroup_add_material_resources(*matcache.shading_grp_p, matcache.shading_gpumat); - } - if (matcache.shadow_grp) { - *matcache.shadow_grp_p = DRW_shgroup_hair_create_sub(ob, psys, md, matcache.shadow_grp, NULL); - DRW_shgroup_add_material_resources(*matcache.shadow_grp_p, matcache.shading_gpumat); - *cast_shadow = true; - } - - EEVEE_motion_blur_hair_cache_populate(sldata, vedata, ob, psys, md); -} - #define ADD_SHGROUP_CALL(shgrp, ob, geom, oedata) \ do { \ if (oedata) { \ @@ -899,18 +871,56 @@ void EEVEE_particle_hair_cache_populate(EEVEE_Data *vedata, if (draw_as != PART_DRAW_PATH) { continue; } - eevee_hair_cache_populate(vedata, sldata, ob, psys, md, part->omat, cast_shadow); + EeveeMaterialCache matcache = eevee_material_cache_get( + vedata, sldata, ob, part->omat - 1, true); + + if (matcache.depth_grp) { + *matcache.depth_grp_p = DRW_shgroup_hair_create_sub( + ob, psys, md, matcache.depth_grp, NULL); + DRW_shgroup_add_material_resources(*matcache.depth_grp_p, matcache.shading_gpumat); + } + if (matcache.shading_grp) { + *matcache.shading_grp_p = DRW_shgroup_hair_create_sub( + ob, psys, md, matcache.shading_grp, matcache.shading_gpumat); + DRW_shgroup_add_material_resources(*matcache.shading_grp_p, matcache.shading_gpumat); + } + if (matcache.shadow_grp) { + *matcache.shadow_grp_p = DRW_shgroup_hair_create_sub( + ob, psys, md, matcache.shadow_grp, NULL); + DRW_shgroup_add_material_resources(*matcache.shadow_grp_p, matcache.shading_gpumat); + *cast_shadow = true; + } + + EEVEE_motion_blur_hair_cache_populate(sldata, vedata, ob, psys, md); } } } } -void EEVEE_object_hair_cache_populate(EEVEE_Data *vedata, - EEVEE_ViewLayerData *sldata, - Object *ob, - bool *cast_shadow) +void EEVEE_object_curves_cache_populate(EEVEE_Data *vedata, + EEVEE_ViewLayerData *sldata, + Object *ob, + bool *cast_shadow) { - eevee_hair_cache_populate(vedata, sldata, ob, NULL, NULL, CURVES_MATERIAL_NR, cast_shadow); + EeveeMaterialCache matcache = eevee_material_cache_get( + vedata, sldata, ob, CURVES_MATERIAL_NR - 1, true); + + if (matcache.depth_grp) { + *matcache.depth_grp_p = DRW_shgroup_curves_create_sub(ob, matcache.depth_grp, NULL); + DRW_shgroup_add_material_resources(*matcache.depth_grp_p, matcache.shading_gpumat); + } + if (matcache.shading_grp) { + *matcache.shading_grp_p = DRW_shgroup_curves_create_sub( + ob, matcache.shading_grp, matcache.shading_gpumat); + DRW_shgroup_add_material_resources(*matcache.shading_grp_p, matcache.shading_gpumat); + } + if (matcache.shadow_grp) { + *matcache.shadow_grp_p = DRW_shgroup_curves_create_sub(ob, matcache.shadow_grp, NULL); + DRW_shgroup_add_material_resources(*matcache.shadow_grp_p, matcache.shading_gpumat); + *cast_shadow = true; + } + + EEVEE_motion_blur_curves_cache_populate(sldata, vedata, ob); } void EEVEE_materials_cache_finish(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) diff --git a/source/blender/draw/engines/eevee/eevee_motion_blur.c b/source/blender/draw/engines/eevee/eevee_motion_blur.c index fbc19a01a8b..0ef2e11131e 100644 --- a/source/blender/draw/engines/eevee/eevee_motion_blur.c +++ b/source/blender/draw/engines/eevee/eevee_motion_blur.c @@ -270,6 +270,57 @@ void EEVEE_motion_blur_hair_cache_populate(EEVEE_ViewLayerData *UNUSED(sldata), } } +void EEVEE_motion_blur_curves_cache_populate(EEVEE_ViewLayerData *UNUSED(sldata), + EEVEE_Data *vedata, + Object *ob) +{ + EEVEE_PassList *psl = vedata->psl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; + + if (!DRW_state_is_scene_render() || psl->velocity_hair == NULL) { + return; + } + + /* For now we assume curves objects are always moving. */ + EEVEE_ObjectMotionData *mb_data = EEVEE_motion_blur_object_data_get(&effects->motion_blur, ob); + if (mb_data == NULL) { + return; + } + + int mb_step = effects->motion_blur_step; + /* Store transform. */ + copy_m4_m4(mb_data->obmat[mb_step], ob->obmat); + + EEVEE_HairMotionData *mb_curves = EEVEE_motion_blur_curves_data_get(mb_data, ob); + + if (mb_step == MB_CURR) { + /* Fill missing matrices if the object was hidden in previous or next frame. */ + if (is_zero_m4(mb_data->obmat[MB_PREV])) { + copy_m4_m4(mb_data->obmat[MB_PREV], mb_data->obmat[MB_CURR]); + } + if (is_zero_m4(mb_data->obmat[MB_NEXT])) { + copy_m4_m4(mb_data->obmat[MB_NEXT], mb_data->obmat[MB_CURR]); + } + + GPUTexture *tex_prev = mb_curves->psys[0].step_data[MB_PREV].hair_pos_tx; + GPUTexture *tex_next = mb_curves->psys[0].step_data[MB_NEXT].hair_pos_tx; + + DRWShadingGroup *grp = DRW_shgroup_curves_create_sub(ob, effects->motion_blur.hair_grp, NULL); + DRW_shgroup_uniform_mat4(grp, "prevModelMatrix", mb_data->obmat[MB_PREV]); + DRW_shgroup_uniform_mat4(grp, "currModelMatrix", mb_data->obmat[MB_CURR]); + DRW_shgroup_uniform_mat4(grp, "nextModelMatrix", mb_data->obmat[MB_NEXT]); + DRW_shgroup_uniform_texture(grp, "prvBuffer", tex_prev); + DRW_shgroup_uniform_texture(grp, "nxtBuffer", tex_next); + DRW_shgroup_uniform_bool(grp, "useDeform", &mb_curves->use_deform, 1); + } + else { + /* Store vertex position buffer. */ + mb_curves->psys[0].step_data[mb_step].hair_pos = DRW_curves_pos_buffer_get(ob); + mb_curves->use_deform = true; + } +} + void EEVEE_motion_blur_cache_populate(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata, Object *ob) diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index 5220bac4e3f..f58c2339c82 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -1095,6 +1095,8 @@ EEVEE_ObjectEngineData *EEVEE_object_data_ensure(Object *ob); EEVEE_ObjectMotionData *EEVEE_motion_blur_object_data_get(EEVEE_MotionBlurData *mb, Object *ob); EEVEE_GeometryMotionData *EEVEE_motion_blur_geometry_data_get(EEVEE_ObjectMotionData *mb_data); EEVEE_HairMotionData *EEVEE_motion_blur_hair_data_get(EEVEE_ObjectMotionData *mb_data, Object *ob); +EEVEE_HairMotionData *EEVEE_motion_blur_curves_data_get(EEVEE_ObjectMotionData *mb_data, + Object *ob); EEVEE_LightProbeEngineData *EEVEE_lightprobe_data_get(Object *ob); EEVEE_LightProbeEngineData *EEVEE_lightprobe_data_ensure(Object *ob); EEVEE_LightEngineData *EEVEE_light_data_get(Object *ob); @@ -1120,10 +1122,10 @@ void EEVEE_particle_hair_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata, Object *ob, bool *cast_shadow); -void EEVEE_object_hair_cache_populate(EEVEE_Data *vedata, - EEVEE_ViewLayerData *sldata, - Object *ob, - bool *cast_shadow); +void EEVEE_object_curves_cache_populate(EEVEE_Data *vedata, + EEVEE_ViewLayerData *sldata, + Object *ob, + bool *cast_shadow); void EEVEE_materials_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_materials_free(void); void EEVEE_update_noise(EEVEE_PassList *psl, EEVEE_FramebufferList *fbl, const double offsets[3]); @@ -1463,6 +1465,9 @@ void EEVEE_motion_blur_hair_cache_populate(EEVEE_ViewLayerData *sldata, Object *ob, struct ParticleSystem *psys, struct ModifierData *md); +void EEVEE_motion_blur_curves_cache_populate(EEVEE_ViewLayerData *sldata, + EEVEE_Data *vedata, + Object *ob); void EEVEE_motion_blur_swap_data(EEVEE_Data *vedata); void EEVEE_motion_blur_cache_finish(EEVEE_Data *vedata); void EEVEE_motion_blur_draw(EEVEE_Data *vedata); diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c index e971edbaa44..47e2b95f367 100644 --- a/source/blender/draw/engines/eevee/eevee_render.c +++ b/source/blender/draw/engines/eevee/eevee_render.c @@ -230,7 +230,7 @@ void EEVEE_render_cache(void *vedata, } } else if (ob->type == OB_CURVES) { - EEVEE_object_hair_cache_populate(vedata, sldata, ob, &cast_shadow); + EEVEE_object_curves_cache_populate(vedata, sldata, ob, &cast_shadow); if (do_cryptomatte) { EEVEE_cryptomatte_object_curves_cache_populate(data, sldata, ob); } diff --git a/source/blender/draw/engines/workbench/workbench_engine.c b/source/blender/draw/engines/workbench/workbench_engine.c index 85c8f9c420a..566fd30096d 100644 --- a/source/blender/draw/engines/workbench/workbench_engine.c +++ b/source/blender/draw/engines/workbench/workbench_engine.c @@ -425,7 +425,8 @@ void workbench_cache_populate(void *ved, Object *ob) } else if (ob->type == OB_CURVES) { int color_type = workbench_color_type_get(wpd, ob, NULL, NULL, NULL); - workbench_cache_hair_populate(wpd, ob, NULL, NULL, color_type, false, CURVES_MATERIAL_NR); + DRWShadingGroup *grp = workbench_material_hair_setup(wpd, ob, CURVES_MATERIAL_NR, color_type); + DRW_shgroup_curves_create_sub(ob, grp, NULL); } else if (ob->type == OB_VOLUME) { if (wpd->shading.type != OB_WIRE) { diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h index 34b930ae9c8..d302140d9ac 100644 --- a/source/blender/draw/intern/draw_common.h +++ b/source/blender/draw/intern/draw_common.h @@ -53,12 +53,17 @@ struct DRWShadingGroup *DRW_shgroup_hair_create_sub(struct Object *object, struct ModifierData *md, struct DRWShadingGroup *shgrp, struct GPUMaterial *gpu_material); + +struct DRWShadingGroup *DRW_shgroup_curves_create_sub(struct Object *object, + struct DRWShadingGroup *shgrp, + struct GPUMaterial *gpu_material); /** * \note Only valid after #DRW_hair_update(). */ struct GPUVertBuf *DRW_hair_pos_buffer_get(struct Object *object, struct ParticleSystem *psys, struct ModifierData *md); +struct GPUVertBuf *DRW_curves_pos_buffer_get(struct Object *object); void DRW_hair_duplimat_get(struct Object *object, struct ParticleSystem *psys, struct ModifierData *md, diff --git a/source/blender/draw/intern/draw_hair.c b/source/blender/draw/intern/draw_hair.c index e06df334d23..0a447bf7041 100644 --- a/source/blender/draw/intern/draw_hair.c +++ b/source/blender/draw/intern/draw_hair.c @@ -164,17 +164,28 @@ static ParticleHairCache *drw_hair_particle_cache_get(Object *object, int subdiv, int thickness_res) { - bool update; ParticleHairCache *cache; - if (psys) { - /* Old particle hair. */ - update = particles_ensure_procedural_data( - object, psys, md, &cache, gpu_material, subdiv, thickness_res); - } - else { - /* New curves object. */ - update = curves_ensure_procedural_data(object, &cache, gpu_material, subdiv, thickness_res); + bool update = particles_ensure_procedural_data( + object, psys, md, &cache, gpu_material, subdiv, thickness_res); + + if (update) { + if (drw_hair_shader_type_get() == PART_REFINE_SHADER_COMPUTE) { + drw_hair_particle_cache_update_compute(cache, subdiv); + } + else { + drw_hair_particle_cache_update_transform_feedback(cache, subdiv); + } } + return cache; +} + +static ParticleHairCache *drw_curves_cache_get(Object *object, + GPUMaterial *gpu_material, + int subdiv, + int thickness_res) +{ + ParticleHairCache *cache; + bool update = curves_ensure_procedural_data(object, &cache, gpu_material, subdiv, thickness_res); if (update) { if (drw_hair_shader_type_get() == PART_REFINE_SHADER_COMPUTE) { @@ -201,37 +212,44 @@ GPUVertBuf *DRW_hair_pos_buffer_get(Object *object, ParticleSystem *psys, Modifi return cache->final[subdiv].proc_buf; } +GPUVertBuf *DRW_curves_pos_buffer_get(Object *object) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene = draw_ctx->scene; + + int subdiv = scene->r.hair_subdiv; + int thickness_res = (scene->r.hair_type == SCE_HAIR_SHAPE_STRAND) ? 1 : 2; + + ParticleHairCache *cache = drw_curves_cache_get(object, NULL, subdiv, thickness_res); + + return cache->final[subdiv].proc_buf; +} + void DRW_hair_duplimat_get(Object *object, - ParticleSystem *psys, + ParticleSystem *UNUSED(psys), ModifierData *UNUSED(md), float (*dupli_mat)[4]) { Object *dupli_parent = DRW_object_get_dupli_parent(object); DupliObject *dupli_object = DRW_object_get_dupli(object); - if (psys) { - if ((dupli_parent != NULL) && (dupli_object != NULL)) { - if (dupli_object->type & OB_DUPLICOLLECTION) { - unit_m4(dupli_mat); - Collection *collection = dupli_parent->instance_collection; - if (collection != NULL) { - sub_v3_v3(dupli_mat[3], collection->instance_offset); - } - mul_m4_m4m4(dupli_mat, dupli_parent->obmat, dupli_mat); - } - else { - copy_m4_m4(dupli_mat, dupli_object->ob->obmat); - invert_m4(dupli_mat); - mul_m4_m4m4(dupli_mat, object->obmat, dupli_mat); + if ((dupli_parent != NULL) && (dupli_object != NULL)) { + if (dupli_object->type & OB_DUPLICOLLECTION) { + unit_m4(dupli_mat); + Collection *collection = dupli_parent->instance_collection; + if (collection != NULL) { + sub_v3_v3(dupli_mat[3], collection->instance_offset); } + mul_m4_m4m4(dupli_mat, dupli_parent->obmat, dupli_mat); } else { - unit_m4(dupli_mat); + copy_m4_m4(dupli_mat, dupli_object->ob->obmat); + invert_m4(dupli_mat); + mul_m4_m4m4(dupli_mat, object->obmat, dupli_mat); } } else { - /* New curves object. */ - copy_m4_m4(dupli_mat, object->obmat); + unit_m4(dupli_mat); } } @@ -317,6 +335,71 @@ DRWShadingGroup *DRW_shgroup_hair_create_sub(Object *object, return shgrp; } +DRWShadingGroup *DRW_shgroup_curves_create_sub(Object *object, + DRWShadingGroup *shgrp_parent, + GPUMaterial *gpu_material) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene = draw_ctx->scene; + + int subdiv = scene->r.hair_subdiv; + int thickness_res = (scene->r.hair_type == SCE_HAIR_SHAPE_STRAND) ? 1 : 2; + + ParticleHairCache *curves_cache = drw_curves_cache_get( + object, gpu_material, subdiv, thickness_res); + + DRWShadingGroup *shgrp = DRW_shgroup_create_sub(shgrp_parent); + + /* TODO: optimize this. Only bind the ones GPUMaterial needs. */ + for (int i = 0; i < curves_cache->num_uv_layers; i++) { + for (int n = 0; n < MAX_LAYER_NAME_CT && curves_cache->uv_layer_names[i][n][0] != '\0'; n++) { + DRW_shgroup_uniform_texture( + shgrp, curves_cache->uv_layer_names[i][n], curves_cache->uv_tex[i]); + } + } + for (int i = 0; i < curves_cache->num_col_layers; i++) { + for (int n = 0; n < MAX_LAYER_NAME_CT && curves_cache->col_layer_names[i][n][0] != '\0'; n++) { + DRW_shgroup_uniform_texture( + shgrp, curves_cache->col_layer_names[i][n], curves_cache->col_tex[i]); + } + } + + /* Fix issue with certain driver not drawing anything if there is no texture bound to + * "ac", "au", "u" or "c". */ + if (curves_cache->num_uv_layers == 0) { + DRW_shgroup_uniform_texture(shgrp, "u", g_dummy_texture); + DRW_shgroup_uniform_texture(shgrp, "au", g_dummy_texture); + } + if (curves_cache->num_col_layers == 0) { + DRW_shgroup_uniform_texture(shgrp, "c", g_dummy_texture); + DRW_shgroup_uniform_texture(shgrp, "ac", g_dummy_texture); + } + + /* TODO: Generalize radius implementation for curves data type. */ + float hair_rad_shape = 1.0f; + float hair_rad_root = 0.005f; + float hair_rad_tip = 0.0f; + bool hair_close_tip = true; + + DRW_shgroup_uniform_texture(shgrp, "hairPointBuffer", curves_cache->final[subdiv].proc_tex); + if (curves_cache->length_tex) { + DRW_shgroup_uniform_texture(shgrp, "hairLen", curves_cache->length_tex); + } + DRW_shgroup_uniform_int(shgrp, "hairStrandsRes", &curves_cache->final[subdiv].strands_res, 1); + DRW_shgroup_uniform_int_copy(shgrp, "hairThicknessRes", thickness_res); + DRW_shgroup_uniform_float_copy(shgrp, "hairRadShape", hair_rad_shape); + DRW_shgroup_uniform_mat4_copy(shgrp, "hairDupliMatrix", object->obmat); + DRW_shgroup_uniform_float_copy(shgrp, "hairRadRoot", hair_rad_root); + DRW_shgroup_uniform_float_copy(shgrp, "hairRadTip", hair_rad_tip); + DRW_shgroup_uniform_bool_copy(shgrp, "hairCloseTip", hair_close_tip); + /* TODO(fclem): Until we have a better way to cull the curves and render with orco, bypass + * culling test. */ + GPUBatch *geom = curves_cache->final[subdiv].proc_hairs[thickness_res - 1]; + DRW_shgroup_call_no_cull(shgrp, geom, object); + + return shgrp; +} + void DRW_hair_update(void) { #ifndef USE_TRANSFORM_FEEDBACK |