diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2022-01-27 00:06:17 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2022-01-27 14:34:42 +0300 |
commit | 032baf06f31063c956ab818a927200241529fa99 (patch) | |
tree | 6df0d1b8b12683cf2b6c1bdcb54387f8100df88e | |
parent | 4226c484bdbe7336f1221094916fcdfb12850034 (diff) | |
parent | 0bdf574ea20e6b138e243f2bf08e93b2e1ee5771 (diff) |
Merge branch 'draw-viewport-data' into eevee-rewrite
55 files changed, 689 insertions, 461 deletions
diff --git a/source/blender/draw/engines/eevee/eevee_film.cc b/source/blender/draw/engines/eevee/eevee_film.cc index a45d503a25c..2542e39aed0 100644 --- a/source/blender/draw/engines/eevee/eevee_film.cc +++ b/source/blender/draw/engines/eevee/eevee_film.cc @@ -92,9 +92,9 @@ void Film::init(const ivec2 &full_extent, const rcti *output_rect) } data_.opacity = 1.0f; - data_.uv_scale = 1.0f / vec2(full_extent); - data_.uv_scale_inv = full_extent; - data_.uv_bias = data_.offset / vec2(full_extent); + data_.uv_scale_inv = vec2(full_extent); + data_.uv_scale = 1.0f / data_.uv_scale_inv; + data_.uv_bias = vec2(data_.offset) * data_.uv_scale; } void Film::sync(void) diff --git a/source/blender/draw/engines/eevee/eevee_light.cc b/source/blender/draw/engines/eevee/eevee_light.cc index ab09ff4b0e5..bcc68d773f5 100644 --- a/source/blender/draw/engines/eevee/eevee_light.cc +++ b/source/blender/draw/engines/eevee/eevee_light.cc @@ -76,8 +76,8 @@ void Light::sync(ShadowModule &shadows, const Object *ob, float threshold) this->color = vec3(&la->r) * la->energy; normalize_m4_m4_ex(this->object_mat, ob->obmat, scale); /* Make sure we have consistent handedness (in case of negatively scaled Z axis). */ - vec3 cross = vec3::cross(this->_right, this->_up); - if (vec3::dot(cross, this->_back) < 0.0f) { + vec3 cross = math::cross(float3(this->_right), float3(this->_up)); + if (math::dot(cross, float3(this->_back)) < 0.0f) { negate_v3(this->_up); } diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.cc b/source/blender/draw/engines/eevee/eevee_lightcache.cc index c778c07f098..8c6625e4515 100644 --- a/source/blender/draw/engines/eevee/eevee_lightcache.cc +++ b/source/blender/draw/engines/eevee/eevee_lightcache.cc @@ -1104,7 +1104,7 @@ void EEVEE_lightbake_job(void *custom_data, short *stop, short *do_update, float void EEVEE_lightcache_free(struct LightCache *lcache_) { eevee::LightCache *lcache = reinterpret_cast<eevee::LightCache *>(lcache_); - OBJECT_GUARDED_SAFE_DELETE(lcache, eevee::LightCache); + MEM_delete(lcache); } void EEVEE_lightcache_info_update(struct SceneEEVEE *eevee) diff --git a/source/blender/draw/engines/eevee/eevee_lightprobe.cc b/source/blender/draw/engines/eevee/eevee_lightprobe.cc index 2acce4ee203..c8eadea5f9e 100644 --- a/source/blender/draw/engines/eevee/eevee_lightprobe.cc +++ b/source/blender/draw/engines/eevee/eevee_lightprobe.cc @@ -38,7 +38,7 @@ void LightProbeModule::init() bool use_lookdev = inst_.use_studio_light(); if (!use_lookdev && lightcache_ && lightcache_->load()) { - OBJECT_GUARDED_SAFE_DELETE(lightcache_lookdev_, LightCache); + MEM_delete(lightcache_lookdev_); } else { if (lightcache_ && (lightcache_->flag & LIGHTCACHE_NOT_USABLE)) { diff --git a/source/blender/draw/engines/eevee/eevee_lightprobe.hh b/source/blender/draw/engines/eevee/eevee_lightprobe.hh index 1a58f73409b..c13f7a75ca4 100644 --- a/source/blender/draw/engines/eevee/eevee_lightprobe.hh +++ b/source/blender/draw/engines/eevee/eevee_lightprobe.hh @@ -89,8 +89,8 @@ class LightProbeModule { ~LightProbeModule() { - OBJECT_GUARDED_SAFE_DELETE(lightcache_lookdev_, LightCache); - OBJECT_GUARDED_SAFE_DELETE(lightcache_baking_, LightCache); + MEM_delete(lightcache_lookdev_); + MEM_delete(lightcache_baking_); } void init(); diff --git a/source/blender/draw/engines/eevee/eevee_lookdev.cc b/source/blender/draw/engines/eevee/eevee_lookdev.cc index e5633ac47ee..881ab90343f 100644 --- a/source/blender/draw/engines/eevee/eevee_lookdev.cc +++ b/source/blender/draw/engines/eevee/eevee_lookdev.cc @@ -314,7 +314,7 @@ void LookDev::sync_overlay(void) /* Pass 2D scale and bias factor in the last column. */ vec2 scale = sphere_size_ / vec2(viewport_size); - vec2 bias = -1.0f + scale + 2.0f * (anchor_ + offset + jitter) / vec2(viewport_size); + vec2 bias = -1.0f + scale + 2.0f * (vec2(anchor_) + offset + jitter) / vec2(viewport_size); copy_v4_fl4(sphere_mat[3], UNPACK2(scale), UNPACK2(bias)); DRW_shgroup_call_obmat(grp, sphere, sphere_mat); diff --git a/source/blender/draw/engines/eevee/eevee_shader_shared.hh b/source/blender/draw/engines/eevee/eevee_shader_shared.hh index 746087ad232..07690744367 100644 --- a/source/blender/draw/engines/eevee/eevee_shader_shared.hh +++ b/source/blender/draw/engines/eevee/eevee_shader_shared.hh @@ -43,12 +43,7 @@ #else /* C++ */ # pragma once -# include "BLI_float2.hh" -# include "BLI_float3.hh" -# include "BLI_float4.hh" # include "BLI_float4x4.hh" -# include "BLI_int2.hh" -# include "BLI_int3.hh" typedef float mat4[4][4]; using vec4 = blender::float4; diff --git a/source/blender/draw/engines/eevee/eevee_shadow.cc b/source/blender/draw/engines/eevee/eevee_shadow.cc index 70eb49ec487..06306ff770a 100644 --- a/source/blender/draw/engines/eevee/eevee_shadow.cc +++ b/source/blender/draw/engines/eevee/eevee_shadow.cc @@ -77,7 +77,7 @@ void ShadowTileMap::sync_clipmap(const float3 &camera_position, float4x4 viewinv = object_mat; copy_v3_v3(viewinv.values[3], tilemap_center); - float camera_distance_to_plane = float3::dot(float3(object_mat.values[2]), camera_position); + float camera_distance_to_plane = math::dot(float3(object_mat.values[2]), camera_position); float visible_near = camera_distance_to_plane - half_size; float visible_far = camera_distance_to_plane + half_size; @@ -444,7 +444,7 @@ void ShadowDirectional::end_sync(int min_level, far_ = -1.0e30f; BoundBox bbox = casters_bounds; for (auto i : IndexRange(8)) { - float dist = -float3::dot(z_axis, float3(bbox.vec[i])); + float dist = -math::dot(z_axis, float3(bbox.vec[i])); near_ = min_ff(near_, dist); far_ = max_ff(far_, dist); } @@ -471,8 +471,8 @@ void ShadowDirectional::end_sync(int min_level, /* Compute full offset from origin to the smallest clipmap tile size. */ float tile_size = first_clipmap.tile_size_get(); base_offset_ = int2( - roundf(float3::dot(float3(object_mat_.values[0]), camera_position) / tile_size), - roundf(float3::dot(float3(object_mat_.values[1]), camera_position) / tile_size)); + roundf(math::dot(float3(object_mat_.values[0]), camera_position) / tile_size), + roundf(math::dot(float3(object_mat_.values[1]), camera_position) / tile_size)); int level = min_level; int divisor = 1; @@ -653,7 +653,7 @@ void ShadowModule::end_sync(void) /* Get the farthest point from camera to know what distance to cover. */ float3 farthest_point = float3(1.0f, 1.0f, 1.0f); mul_project_m4_v3(inst_.camera.data_get().wininv, farthest_point); - float far_dist = farthest_point.length(); + float far_dist = math::length(farthest_point); float near_dist = fabsf(inst_.camera.data_get().clip_near); float3 cam_position = inst_.camera.position(); @@ -1041,7 +1041,7 @@ void ShadowModule::set_view(const DRWView *view, GPUTexture *depth_tx) p0 = p0 / p0.z; p1 = p1 / p1.z; } - screen_pixel_radius_inv_ = min_dim / float3::distance(p0, p1); + screen_pixel_radius_inv_ = min_dim / math::distance(p0, p1); } #ifdef SHADOW_DEBUG_FREEZE_CAMERA diff --git a/source/blender/draw/engines/eevee/eevee_shadow.hh b/source/blender/draw/engines/eevee/eevee_shadow.hh index 65456f11326..a7db2f6dc0e 100644 --- a/source/blender/draw/engines/eevee/eevee_shadow.hh +++ b/source/blender/draw/engines/eevee/eevee_shadow.hh @@ -107,7 +107,7 @@ struct AABB { float radius(void) const { - return (max - min).length() / 2.0f; + return math::length(max - min) / 2.0f; } operator BoundBox() const diff --git a/source/blender/draw/engines/workbench/workbench_shader.cc b/source/blender/draw/engines/workbench/workbench_shader.cc index b38286303f1..011a3fd3b13 100644 --- a/source/blender/draw/engines/workbench/workbench_shader.cc +++ b/source/blender/draw/engines/workbench/workbench_shader.cc @@ -27,52 +27,6 @@ #include "workbench_engine.h" #include "workbench_private.h" -extern char datatoc_common_math_lib_glsl[]; -extern char datatoc_common_math_geom_lib_glsl[]; -extern char datatoc_common_hair_lib_glsl[]; -extern char datatoc_common_pointcloud_lib_glsl[]; -extern char datatoc_common_view_lib_glsl[]; -extern char datatoc_common_smaa_lib_glsl[]; - -extern char datatoc_workbench_prepass_vert_glsl[]; -extern char datatoc_workbench_prepass_hair_vert_glsl[]; -extern char datatoc_workbench_prepass_pointcloud_vert_glsl[]; -extern char datatoc_workbench_prepass_frag_glsl[]; - -extern char datatoc_workbench_effect_cavity_frag_glsl[]; -extern char datatoc_workbench_effect_outline_frag_glsl[]; -extern char datatoc_workbench_effect_dof_frag_glsl[]; -extern char datatoc_workbench_effect_taa_frag_glsl[]; -extern char datatoc_workbench_effect_smaa_frag_glsl[]; -extern char datatoc_workbench_effect_smaa_vert_glsl[]; - -extern char datatoc_workbench_composite_frag_glsl[]; - -extern char datatoc_workbench_transparent_accum_frag_glsl[]; -extern char datatoc_workbench_transparent_resolve_frag_glsl[]; - -extern char datatoc_workbench_merge_infront_frag_glsl[]; - -extern char datatoc_workbench_shadow_vert_glsl[]; -extern char datatoc_workbench_shadow_geom_glsl[]; -extern char datatoc_workbench_shadow_caps_geom_glsl[]; -extern char datatoc_workbench_shadow_debug_frag_glsl[]; - -extern char datatoc_workbench_volume_vert_glsl[]; -extern char datatoc_workbench_volume_frag_glsl[]; - -extern char datatoc_workbench_cavity_lib_glsl[]; -extern char datatoc_workbench_common_lib_glsl[]; -extern char datatoc_workbench_curvature_lib_glsl[]; -extern char datatoc_workbench_data_lib_glsl[]; -extern char datatoc_workbench_image_lib_glsl[]; -extern char datatoc_workbench_matcap_lib_glsl[]; -extern char datatoc_workbench_material_lib_glsl[]; -extern char datatoc_workbench_world_light_lib_glsl[]; - -extern char datatoc_gpu_shader_depth_only_frag_glsl[]; -extern char datatoc_gpu_shader_common_obinfos_lib_glsl[]; - /* Maximum number of variations. */ #define MAX_LIGHTING 3 diff --git a/source/blender/editors/space_outliner/CMakeLists.txt b/source/blender/editors/space_outliner/CMakeLists.txt index 60b881fb32b..bc6db978a4f 100644 --- a/source/blender/editors/space_outliner/CMakeLists.txt +++ b/source/blender/editors/space_outliner/CMakeLists.txt @@ -67,6 +67,7 @@ set(SRC tree/tree_element_overrides.cc tree/tree_element_rna.cc tree/tree_element_scene_objects.cc + tree/tree_element_seq.cc tree/tree_element_view_layer.cc outliner_intern.hh @@ -84,6 +85,7 @@ set(SRC tree/tree_element_overrides.hh tree/tree_element_rna.hh tree/tree_element_scene_objects.hh + tree/tree_element_seq.hh tree/tree_element_view_layer.hh ) diff --git a/source/blender/editors/space_outliner/outliner_draw.cc b/source/blender/editors/space_outliner/outliner_draw.cc index 6de8d9539a9..5fd7559370f 100644 --- a/source/blender/editors/space_outliner/outliner_draw.cc +++ b/source/blender/editors/space_outliner/outliner_draw.cc @@ -81,6 +81,7 @@ #include "outliner_intern.hh" #include "tree/tree_display.hh" #include "tree/tree_element.hh" +#include "tree/tree_element_rna.hh" using namespace blender::ed::outliner; @@ -1909,20 +1910,20 @@ static void outliner_draw_rnacols(ARegion *region, int sizex) static void outliner_draw_rnabuts( uiBlock *block, ARegion *region, SpaceOutliner *space_outliner, int sizex, ListBase *lb) { - PointerRNA *ptr; + PointerRNA ptr; PropertyRNA *prop; LISTBASE_FOREACH (TreeElement *, te, lb) { TreeStoreElem *tselem = TREESTORE(te); if (te->ys + 2 * UI_UNIT_Y >= region->v2d.cur.ymin && te->ys <= region->v2d.cur.ymax) { - if (tselem->type == TSE_RNA_PROPERTY) { - ptr = &te->rnaptr; - prop = reinterpret_cast<PropertyRNA *>(te->directdata); + if (TreeElementRNAProperty *te_rna_prop = tree_element_cast<TreeElementRNAProperty>(te)) { + ptr = te_rna_prop->getPointerRNA(); + prop = te_rna_prop->getPropertyRNA(); if (!TSELEM_OPEN(tselem, space_outliner)) { if (RNA_property_type(prop) == PROP_POINTER) { uiBut *but = uiDefAutoButR(block, - ptr, + &ptr, prop, -1, "", @@ -1935,7 +1936,7 @@ static void outliner_draw_rnabuts( } else if (RNA_property_type(prop) == PROP_ENUM) { uiDefAutoButR(block, - ptr, + &ptr, prop, -1, nullptr, @@ -1947,7 +1948,7 @@ static void outliner_draw_rnabuts( } else { uiDefAutoButR(block, - ptr, + &ptr, prop, -1, "", @@ -1959,12 +1960,13 @@ static void outliner_draw_rnabuts( } } } - else if (tselem->type == TSE_RNA_ARRAY_ELEM) { - ptr = &te->rnaptr; - prop = reinterpret_cast<PropertyRNA *>(te->directdata); + else if (TreeElementRNAArrayElement *te_rna_array_elem = + tree_element_cast<TreeElementRNAArrayElement>(te)) { + ptr = te_rna_array_elem->getPointerRNA(); + prop = te_rna_array_elem->getPropertyRNA(); uiDefAutoButR(block, - ptr, + &ptr, prop, te->index, "", @@ -2554,15 +2556,19 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te) case TSE_SEQUENCE_DUP: data.icon = ICON_SEQ_STRIP_DUPLICATE; break; - case TSE_RNA_STRUCT: - if (RNA_struct_is_ID(te->rnaptr.type)) { - data.drag_id = (ID *)te->rnaptr.data; - data.icon = RNA_struct_ui_icon(te->rnaptr.type); + case TSE_RNA_STRUCT: { + const TreeElementRNAStruct *te_rna_struct = tree_element_cast<TreeElementRNAStruct>(te); + const PointerRNA &ptr = te_rna_struct->getPointerRNA(); + + if (RNA_struct_is_ID(ptr.type)) { + data.drag_id = reinterpret_cast<ID *>(ptr.data); + data.icon = RNA_struct_ui_icon(ptr.type); } else { - data.icon = RNA_struct_ui_icon(te->rnaptr.type); + data.icon = RNA_struct_ui_icon(ptr.type); } break; + } case TSE_LAYER_COLLECTION: case TSE_SCENE_COLLECTION_BASE: case TSE_VIEW_COLLECTION_BASE: { @@ -3319,8 +3325,9 @@ static void outliner_draw_tree_element(bContext *C, offsx += 2 * ufac; } + const TreeElementRNAStruct *te_rna_struct = tree_element_cast<TreeElementRNAStruct>(te); if (ELEM(tselem->type, TSE_SOME_ID, TSE_LAYER_COLLECTION) || - ((tselem->type == TSE_RNA_STRUCT) && RNA_struct_is_ID(te->rnaptr.type))) { + (te_rna_struct && RNA_struct_is_ID(te_rna_struct->getPointerRNA().type))) { const BIFIconID lib_icon = (BIFIconID)UI_icon_from_library(tselem->id); if (lib_icon != ICON_NONE) { UI_icon_draw_alpha( diff --git a/source/blender/editors/space_outliner/outliner_edit.cc b/source/blender/editors/space_outliner/outliner_edit.cc index a10dbc94b34..b41b260b14a 100644 --- a/source/blender/editors/space_outliner/outliner_edit.cc +++ b/source/blender/editors/space_outliner/outliner_edit.cc @@ -74,6 +74,9 @@ #include "GPU_material.h" #include "outliner_intern.hh" +#include "tree/tree_element_rna.hh" + +using namespace blender::ed::outliner; static void outliner_show_active(SpaceOutliner *space_outliner, ARegion *region, @@ -1714,11 +1717,6 @@ static void tree_element_to_path(TreeElement *te, short *UNUSED(groupmode)) { ListBase hierarchy = {nullptr, nullptr}; - LinkData *ld; - TreeElement *tem, *temnext; - TreeStoreElem *tse /* , *tsenext */ /* UNUSED */; - PointerRNA *ptr, *nextptr; - PropertyRNA *prop; char *newpath = nullptr; /* optimize tricks: @@ -1738,20 +1736,19 @@ static void tree_element_to_path(TreeElement *te, */ /* step 1: flatten out hierarchy of parents into a flat chain */ - for (tem = te->parent; tem; tem = tem->parent) { - ld = MEM_cnew<LinkData>("LinkData for tree_element_to_path()"); + for (TreeElement *tem = te->parent; tem; tem = tem->parent) { + LinkData *ld = MEM_cnew<LinkData>("LinkData for tree_element_to_path()"); ld->data = tem; BLI_addhead(&hierarchy, ld); } /* step 2: step down hierarchy building the path * (NOTE: addhead in previous loop was needed so that we can loop like this) */ - for (ld = reinterpret_cast<LinkData *>(hierarchy.first); ld; ld = ld->next) { + LISTBASE_FOREACH (LinkData *, ld, &hierarchy) { /* get data */ - tem = (TreeElement *)ld->data; - tse = TREESTORE(tem); - ptr = &tem->rnaptr; - prop = reinterpret_cast<PropertyRNA *>(tem->directdata); + TreeElement *tem = (TreeElement *)ld->data; + TreeElementRNACommon *tem_rna = tree_element_cast<TreeElementRNACommon>(tem); + PointerRNA ptr = tem_rna->getPointerRNA(); /* check if we're looking for first ID, or appending to path */ if (*id) { @@ -1759,19 +1756,19 @@ static void tree_element_to_path(TreeElement *te, * - to prevent memory leaks, we must write to newpath not path, * then free old path + swap them. */ - if (tse->type == TSE_RNA_PROPERTY) { + if (TreeElementRNAProperty *tem_rna_prop = tree_element_cast<TreeElementRNAProperty>(tem)) { + PropertyRNA *prop = tem_rna_prop->getPropertyRNA(); + if (RNA_property_type(prop) == PROP_POINTER) { /* for pointer we just append property name */ - newpath = RNA_path_append(*path, ptr, prop, 0, nullptr); + newpath = RNA_path_append(*path, &ptr, prop, 0, nullptr); } else if (RNA_property_type(prop) == PROP_COLLECTION) { char buf[128], *name; - temnext = (TreeElement *)(ld->next->data); - // tsenext = TREESTORE(temnext); /* UNUSED */ - - nextptr = &temnext->rnaptr; - name = RNA_struct_name_get_alloc(nextptr, buf, sizeof(buf), nullptr); + TreeElement *temnext = (TreeElement *)(ld->next->data); + PointerRNA nextptr = tree_element_cast<TreeElementRNACommon>(temnext)->getPointerRNA(); + name = RNA_struct_name_get_alloc(&nextptr, buf, sizeof(buf), nullptr); if (name) { /* if possible, use name as a key in the path */ @@ -1789,6 +1786,7 @@ static void tree_element_to_path(TreeElement *te, if (temsub == temnext) { break; } + index++; } newpath = RNA_path_append(*path, nullptr, prop, index, nullptr); } @@ -1808,11 +1806,11 @@ static void tree_element_to_path(TreeElement *te, else { /* no ID, so check if entry is RNA-struct, * and if that RNA-struct is an ID datablock to extract info from. */ - if (tse->type == TSE_RNA_STRUCT) { + if (tree_element_cast<TreeElementRNAStruct>(tem)) { /* ptr->data not ptr->owner_id seems to be the one we want, * since ptr->data is sometimes the owner of this ID? */ - if (RNA_struct_is_ID(ptr->type)) { - *id = reinterpret_cast<ID *>(ptr->data); + if (RNA_struct_is_ID(ptr.type)) { + *id = reinterpret_cast<ID *>(ptr.data); /* clear path */ if (*path) { @@ -1827,8 +1825,7 @@ static void tree_element_to_path(TreeElement *te, /* step 3: if we've got an ID, add the current item to the path */ if (*id) { /* add the active property to the path */ - ptr = &te->rnaptr; - prop = reinterpret_cast<PropertyRNA *>(te->directdata); + PropertyRNA *prop = tree_element_cast<TreeElementRNACommon>(te)->getPropertyRNA(); /* array checks */ if (tselem->type == TSE_RNA_ARRAY_ELEM) { @@ -1886,9 +1883,12 @@ static void do_outliner_drivers_editop(SpaceOutliner *space_outliner, short flag = 0; short groupmode = KSP_GROUP_KSNAME; + TreeElementRNACommon *te_rna = tree_element_cast<TreeElementRNACommon>(te); + PointerRNA ptr = te_rna ? te_rna->getPointerRNA() : PointerRNA_NULL; + PropertyRNA *prop = te_rna ? te_rna->getPropertyRNA() : nullptr; + /* check if RNA-property described by this selected element is an animatable prop */ - if (ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM) && - RNA_property_animateable(&te->rnaptr, reinterpret_cast<PropertyRNA *>(te->directdata))) { + if (prop && RNA_property_animateable(&ptr, prop)) { /* get id + path + index info from the selected element */ tree_element_to_path(te, tselem, &id, &path, &array_index, &flag, &groupmode); } @@ -1901,8 +1901,7 @@ static void do_outliner_drivers_editop(SpaceOutliner *space_outliner, /* array checks */ if (flag & KSP_FLAG_WHOLE_ARRAY) { /* entire array was selected, so add drivers for all */ - arraylen = RNA_property_array_length(&te->rnaptr, - reinterpret_cast<PropertyRNA *>(te->directdata)); + arraylen = RNA_property_array_length(&ptr, prop); } else { arraylen = array_index; @@ -2084,8 +2083,10 @@ static void do_outliner_keyingset_editop(SpaceOutliner *space_outliner, short groupmode = KSP_GROUP_KSNAME; /* check if RNA-property described by this selected element is an animatable prop */ - if (ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM) && - RNA_property_animateable(&te->rnaptr, reinterpret_cast<PropertyRNA *>(te->directdata))) { + const TreeElementRNACommon *te_rna = tree_element_cast<TreeElementRNACommon>(te); + PointerRNA ptr = te_rna->getPointerRNA(); + if (te_rna && te_rna->getPropertyRNA() && + RNA_property_animateable(&ptr, te_rna->getPropertyRNA())) { /* get id + path + index info from the selected element */ tree_element_to_path(te, tselem, &id, &path, &array_index, &flag, &groupmode); } diff --git a/source/blender/editors/space_outliner/outliner_intern.hh b/source/blender/editors/space_outliner/outliner_intern.hh index a62d35131ca..9db1d73dc76 100644 --- a/source/blender/editors/space_outliner/outliner_intern.hh +++ b/source/blender/editors/space_outliner/outliner_intern.hh @@ -27,6 +27,9 @@ #include "RNA_types.h" +/* Needed for `tree_element_cast()`. */ +#include "tree/tree_element.hh" + #ifdef __cplusplus extern "C" { #endif @@ -104,8 +107,7 @@ typedef struct TreeElement { short idcode; /* From TreeStore id. */ short xend; /* Width of item display, for select. */ const char *name; - void *directdata; /* Armature Bones, Base, Sequence, Strip... */ - PointerRNA rnaptr; /* RNA Pointer. */ + void *directdata; /* Armature Bones, Base, ... */ } TreeElement; typedef struct TreeElementIcon { @@ -686,3 +688,19 @@ int outliner_context(const struct bContext *C, #ifdef __cplusplus } #endif + +namespace blender::ed::outliner { + +/** + * Helper to safely "cast" a #TreeElement to its new C++ #AbstractTreeElement, if possible. + * \return nullptr if the tree-element doesn't match the requested type \a TreeElementT or the + * element doesn't hold a C++ #AbstractTreeElement pendant yet. + */ +template<typename TreeElementT> TreeElementT *tree_element_cast(const TreeElement *te) +{ + static_assert(std::is_base_of_v<AbstractTreeElement, TreeElementT>, + "Requested tree-element type must be an AbstractTreeElement"); + return dynamic_cast<TreeElementT *>(te->type.get()); +} + +} // namespace blender::ed::outliner diff --git a/source/blender/editors/space_outliner/outliner_select.cc b/source/blender/editors/space_outliner/outliner_select.cc index c2a7bfb9b37..3ff8b9e973f 100644 --- a/source/blender/editors/space_outliner/outliner_select.cc +++ b/source/blender/editors/space_outliner/outliner_select.cc @@ -80,6 +80,9 @@ #include "RNA_define.h" #include "outliner_intern.hh" +#include "tree/tree_element_seq.hh" + +using namespace blender::ed::outliner; /** * \note changes to selection are by convention and not essential. @@ -676,7 +679,8 @@ static void tree_element_sequence_activate(bContext *C, TreeElement *te, const eOLSetState set) { - Sequence *seq = (Sequence *)te->directdata; + const TreeElementSequence *te_seq = tree_element_cast<TreeElementSequence>(te); + Sequence *seq = &te_seq->getSequence(); Editing *ed = SEQ_editing_get(scene); if (BLI_findindex(ed->seqbasep, seq) != -1) { @@ -954,7 +958,8 @@ static eOLDrawState tree_element_posegroup_state_get(const ViewLayer *view_layer static eOLDrawState tree_element_sequence_state_get(const Scene *scene, const TreeElement *te) { - const Sequence *seq = (const Sequence *)te->directdata; + const TreeElementSequence *te_seq = tree_element_cast<TreeElementSequence>(te); + const Sequence *seq = &te_seq->getSequence(); const Editing *ed = scene->ed; if (ed && ed->act_seq == seq && seq->flag & SELECT) { @@ -965,7 +970,9 @@ static eOLDrawState tree_element_sequence_state_get(const Scene *scene, const Tr static eOLDrawState tree_element_sequence_dup_state_get(const TreeElement *te) { - const Sequence *seq = (const Sequence *)te->directdata; + const TreeElementSequenceStripDuplicate *te_dup = + tree_element_cast<TreeElementSequenceStripDuplicate>(te); + const Sequence *seq = &te_dup->getSequence(); if (seq->flag & SELECT) { return OL_DRAWSEL_NORMAL; } diff --git a/source/blender/editors/space_outliner/outliner_tools.cc b/source/blender/editors/space_outliner/outliner_tools.cc index 1c1a4f6f4c2..fa31025b550 100644 --- a/source/blender/editors/space_outliner/outliner_tools.cc +++ b/source/blender/editors/space_outliner/outliner_tools.cc @@ -96,9 +96,13 @@ #include "SEQ_sequencer.h" #include "outliner_intern.hh" +#include "tree/tree_element_rna.hh" +#include "tree/tree_element_seq.hh" static CLG_LogRef LOG = {"ed.outliner.tools"}; +using namespace blender::ed::outliner; + /* -------------------------------------------------------------------- */ /** \name ID/Library/Data Set/Un-link Utilities * \{ */ @@ -1285,7 +1289,8 @@ static void ebone_fn(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem), static void sequence_fn(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem), void *scene_ptr) { - Sequence *seq = (Sequence *)te->directdata; + TreeElementSequence *te_seq = tree_element_cast<TreeElementSequence>(te); + Sequence *seq = &te_seq->getSequence(); Scene *scene = (Scene *)scene_ptr; Editing *ed = SEQ_editing_get(scene); if (BLI_findindex(ed->seqbasep, seq) != -1) { @@ -1336,10 +1341,16 @@ static void data_select_linked_fn(int event, TreeStoreElem *UNUSED(tselem), void *C_v) { + const TreeElementRNAStruct *te_rna_struct = tree_element_cast<TreeElementRNAStruct>(te); + if (!te_rna_struct) { + return; + } + if (event == OL_DOP_SELECT_LINKED) { - if (RNA_struct_is_ID(te->rnaptr.type)) { + const PointerRNA &ptr = te_rna_struct->getPointerRNA(); + if (RNA_struct_is_ID(ptr.type)) { bContext *C = (bContext *)C_v; - ID *id = reinterpret_cast<ID *>(te->rnaptr.data); + ID *id = reinterpret_cast<ID *>(ptr.data); ED_object_select_linked_by_id(C, id); } diff --git a/source/blender/editors/space_outliner/outliner_tree.cc b/source/blender/editors/space_outliner/outliner_tree.cc index be792be95a9..eb885eba20d 100644 --- a/source/blender/editors/space_outliner/outliner_tree.cc +++ b/source/blender/editors/space_outliner/outliner_tree.cc @@ -925,57 +925,14 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, TSE_NLA, TSE_NLA_ACTION, TSE_NLA_TRACK, - TSE_GP_LAYER)) { - /* Should already use new AbstractTreeElement design. */ - BLI_assert(0); - } - else if (type == TSE_SEQUENCE) { - Sequence *seq = (Sequence *)idv; - - /* - * The idcode is a little hack, but the outliner - * only check te->idcode if te->type is equal to zero, - * so this is "safe". - */ - te->idcode = seq->type; - te->directdata = seq; - te->name = seq->name + 2; - - if (!(seq->type & SEQ_TYPE_EFFECT)) { - /* - * This work like the sequence. - * If the sequence have a name (not default name) - * show it, in other case put the filename. - */ - - if (seq->type == SEQ_TYPE_META) { - LISTBASE_FOREACH (Sequence *, p, &seq->seqbase) { - outliner_add_element(space_outliner, &te->subtree, (void *)p, te, TSE_SEQUENCE, index); - } - } - else { - outliner_add_element( - space_outliner, &te->subtree, (void *)seq->strip, te, TSE_SEQ_STRIP, index); - } - } - } - else if (type == TSE_SEQ_STRIP) { - Strip *strip = (Strip *)idv; - - if (strip->dir[0] != '\0') { - te->name = strip->dir; - } - else { - te->name = IFACE_("Strip None"); - } - te->directdata = strip; - } - else if (type == TSE_SEQUENCE_DUP) { - Sequence *seq = (Sequence *)idv; - - te->idcode = seq->type; - te->directdata = seq; - te->name = seq->strip->stripdata->name; + TSE_GP_LAYER, + TSE_RNA_STRUCT, + TSE_RNA_PROPERTY, + TSE_RNA_ARRAY_ELEM, + TSE_SEQUENCE, + TSE_SEQ_STRIP, + TSE_SEQUENCE_DUP)) { + BLI_assert_msg(false, "Element type should already use new AbstractTreeElement design"); } if (tree_element_warnings_get(te, nullptr, nullptr)) { diff --git a/source/blender/editors/space_outliner/tree/tree_element.cc b/source/blender/editors/space_outliner/tree/tree_element.cc index bed28e59f0b..5685d8964f5 100644 --- a/source/blender/editors/space_outliner/tree/tree_element.cc +++ b/source/blender/editors/space_outliner/tree/tree_element.cc @@ -35,6 +35,7 @@ #include "tree_element_overrides.hh" #include "tree_element_rna.hh" #include "tree_element_scene_objects.hh" +#include "tree_element_seq.hh" #include "tree_element_view_layer.hh" #include "../outliner_intern.hh" @@ -96,6 +97,14 @@ std::unique_ptr<AbstractTreeElement> AbstractTreeElement::createFromType(const i case TSE_RNA_ARRAY_ELEM: return std::make_unique<TreeElementRNAArrayElement>( legacy_te, *reinterpret_cast<PointerRNA *>(idv), legacy_te.index); + case TSE_SEQUENCE: + return std::make_unique<TreeElementSequence>(legacy_te, *reinterpret_cast<Sequence *>(idv)); + case TSE_SEQ_STRIP: + return std::make_unique<TreeElementSequenceStrip>(legacy_te, + *reinterpret_cast<Strip *>(idv)); + case TSE_SEQUENCE_DUP: + return std::make_unique<TreeElementSequenceStripDuplicate>( + legacy_te, *reinterpret_cast<Sequence *>(idv)); default: break; } diff --git a/source/blender/editors/space_outliner/tree/tree_element_rna.cc b/source/blender/editors/space_outliner/tree/tree_element_rna.cc index 0152f59268d..7a9f1b6f0fa 100644 --- a/source/blender/editors/space_outliner/tree/tree_element_rna.cc +++ b/source/blender/editors/space_outliner/tree/tree_element_rna.cc @@ -54,8 +54,6 @@ TreeElementRNACommon::TreeElementRNACommon(TreeElement &legacy_te, PointerRNA &r legacy_te_.name = IFACE_("(empty)"); return; } - - legacy_te_.rnaptr = rna_ptr; } bool TreeElementRNACommon::isExpandValid() const @@ -73,12 +71,24 @@ bool TreeElementRNACommon::expandPoll(const SpaceOutliner &) const return isRNAValid(); } +const PointerRNA &TreeElementRNACommon::getPointerRNA() const +{ + return rna_ptr_; +} + +PropertyRNA *TreeElementRNACommon::getPropertyRNA() const +{ + return nullptr; +} + /* -------------------------------------------------------------------- */ /* RNA Struct */ TreeElementRNAStruct::TreeElementRNAStruct(TreeElement &legacy_te, PointerRNA &rna_ptr) : TreeElementRNACommon(legacy_te, rna_ptr) { + BLI_assert(legacy_te.store_elem->type == TSE_RNA_STRUCT); + if (!isRNAValid()) { return; } @@ -95,21 +105,23 @@ TreeElementRNAStruct::TreeElementRNAStruct(TreeElement &legacy_te, PointerRNA &r void TreeElementRNAStruct::expand(SpaceOutliner &space_outliner) const { TreeStoreElem &tselem = *TREESTORE(&legacy_te_); - PointerRNA *ptr = &legacy_te_.rnaptr; + PointerRNA ptr = rna_ptr_; /* If searching don't expand RNA entries */ if (SEARCHING_OUTLINER(&space_outliner) && BLI_strcasecmp("RNA", legacy_te_.name) == 0) { tselem.flag &= ~TSE_CHILDSEARCH; } - PropertyRNA *iterprop = RNA_struct_iterator_property(ptr->type); - int tot = RNA_property_collection_length(ptr, iterprop); + PropertyRNA *iterprop = RNA_struct_iterator_property(ptr.type); + int tot = RNA_property_collection_length(&ptr, iterprop); CLAMP_MAX(tot, max_index); + TreeElementRNAProperty *parent_prop_te = legacy_te_.parent ? + tree_element_cast<TreeElementRNAProperty>( + legacy_te_.parent) : + nullptr; /* auto open these cases */ - if (!legacy_te_.parent || - (RNA_property_type(reinterpret_cast<PropertyRNA *>(legacy_te_.parent->directdata))) == - PROP_POINTER) { + if (!parent_prop_te || (RNA_property_type(parent_prop_te->getPropertyRNA()) == PROP_POINTER)) { if (!tselem.used) { tselem.flag &= ~TSE_CLOSED; } @@ -118,14 +130,10 @@ void TreeElementRNAStruct::expand(SpaceOutliner &space_outliner) const if (TSELEM_OPEN(&tselem, &space_outliner)) { for (int index = 0; index < tot; index++) { PointerRNA propptr; - RNA_property_collection_lookup_int(ptr, iterprop, index, &propptr); + RNA_property_collection_lookup_int(&ptr, iterprop, index, &propptr); if (!(RNA_property_flag(reinterpret_cast<PropertyRNA *>(propptr.data)) & PROP_HIDDEN)) { - outliner_add_element(&space_outliner, - &legacy_te_.subtree, - (void *)ptr, - &legacy_te_, - TSE_RNA_PROPERTY, - index); + outliner_add_element( + &space_outliner, &legacy_te_.subtree, &ptr, &legacy_te_, TSE_RNA_PROPERTY, index); } } } @@ -142,6 +150,8 @@ TreeElementRNAProperty::TreeElementRNAProperty(TreeElement &legacy_te, const int index) : TreeElementRNACommon(legacy_te, rna_ptr) { + BLI_assert(legacy_te.store_elem->type == TSE_RNA_PROPERTY); + if (!isRNAValid()) { return; } @@ -153,7 +163,6 @@ TreeElementRNAProperty::TreeElementRNAProperty(TreeElement &legacy_te, PropertyRNA *prop = reinterpret_cast<PropertyRNA *>(propptr.data); legacy_te_.name = RNA_property_ui_name(prop); - legacy_te_.directdata = prop; rna_prop_ = prop; } @@ -174,7 +183,7 @@ void TreeElementRNAProperty::expand(SpaceOutliner &space_outliner) const if (pptr.data) { if (TSELEM_OPEN(&tselem, &space_outliner)) { outliner_add_element( - &space_outliner, &legacy_te_.subtree, (void *)&pptr, &legacy_te_, TSE_RNA_STRUCT, -1); + &space_outliner, &legacy_te_.subtree, &pptr, &legacy_te_, TSE_RNA_STRUCT, -1); } else { legacy_te_.flag |= TE_LAZY_CLOSED; @@ -189,12 +198,8 @@ void TreeElementRNAProperty::expand(SpaceOutliner &space_outliner) const for (int index = 0; index < tot; index++) { PointerRNA pptr; RNA_property_collection_lookup_int(&rna_ptr, rna_prop_, index, &pptr); - outliner_add_element(&space_outliner, - &legacy_te_.subtree, - (void *)&pptr, - &legacy_te_, - TSE_RNA_STRUCT, - index); + outliner_add_element( + &space_outliner, &legacy_te_.subtree, &pptr, &legacy_te_, TSE_RNA_STRUCT, index); } } else if (tot) { @@ -221,6 +226,11 @@ void TreeElementRNAProperty::expand(SpaceOutliner &space_outliner) const } } +PropertyRNA *TreeElementRNAProperty::getPropertyRNA() const +{ + return rna_prop_; +} + /* -------------------------------------------------------------------- */ /* RNA Array Element */ @@ -229,11 +239,12 @@ TreeElementRNAArrayElement::TreeElementRNAArrayElement(TreeElement &legacy_te, const int index) : TreeElementRNACommon(legacy_te, rna_ptr) { - PropertyRNA *prop = reinterpret_cast<PropertyRNA *>(legacy_te_.parent->directdata); - legacy_te_.directdata = prop; + BLI_assert(legacy_te.store_elem->type == TSE_RNA_ARRAY_ELEM); + + BLI_assert(legacy_te.parent && (legacy_te.parent->store_elem->type == TSE_RNA_PROPERTY)); legacy_te_.index = index; - char c = RNA_property_array_item_char(prop, index); + char c = RNA_property_array_item_char(TreeElementRNAArrayElement::getPropertyRNA(), index); legacy_te_.name = reinterpret_cast<char *>( MEM_callocN(sizeof(char[20]), "OutlinerRNAArrayName")); @@ -246,4 +257,12 @@ TreeElementRNAArrayElement::TreeElementRNAArrayElement(TreeElement &legacy_te, legacy_te_.flag |= TE_FREE_NAME; } +PropertyRNA *TreeElementRNAArrayElement::getPropertyRNA() const +{ + /* Forward query to the parent (which is expected to be a #TreeElementRNAProperty). */ + const TreeElementRNAProperty *parent_prop_te = tree_element_cast<TreeElementRNAProperty>( + legacy_te_.parent); + return parent_prop_te ? parent_prop_te->getPropertyRNA() : nullptr; +} + } // namespace blender::ed::outliner diff --git a/source/blender/editors/space_outliner/tree/tree_element_rna.hh b/source/blender/editors/space_outliner/tree/tree_element_rna.hh index 352b8763acb..1f107ddbf88 100644 --- a/source/blender/editors/space_outliner/tree/tree_element_rna.hh +++ b/source/blender/editors/space_outliner/tree/tree_element_rna.hh @@ -43,6 +43,13 @@ class TreeElementRNACommon : public AbstractTreeElement { bool isExpandValid() const override; bool expandPoll(const SpaceOutliner &) const override; + const PointerRNA &getPointerRNA() const; + /** + * If this element represents a property or is part of a property (array element), this returns + * the property. Otherwise nullptr. + */ + virtual PropertyRNA *getPropertyRNA() const; + bool isRNAValid() const; }; @@ -63,6 +70,8 @@ class TreeElementRNAProperty : public TreeElementRNACommon { public: TreeElementRNAProperty(TreeElement &legacy_te, PointerRNA &rna_ptr, int index); void expand(SpaceOutliner &space_outliner) const override; + + PropertyRNA *getPropertyRNA() const override; }; /* -------------------------------------------------------------------- */ @@ -70,6 +79,8 @@ class TreeElementRNAProperty : public TreeElementRNACommon { class TreeElementRNAArrayElement : public TreeElementRNACommon { public: TreeElementRNAArrayElement(TreeElement &legacy_te, PointerRNA &rna_ptr, int index); + + PropertyRNA *getPropertyRNA() const override; }; } // namespace blender::ed::outliner diff --git a/source/blender/editors/space_outliner/tree/tree_element_seq.cc b/source/blender/editors/space_outliner/tree/tree_element_seq.cc new file mode 100644 index 00000000000..8d0b4c140c7 --- /dev/null +++ b/source/blender/editors/space_outliner/tree/tree_element_seq.cc @@ -0,0 +1,111 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup spoutliner + */ + +#include "DNA_outliner_types.h" +#include "DNA_sequence_types.h" + +#include "BLI_listbase.h" + +#include "BLT_translation.h" + +#include "../outliner_intern.hh" +#include "tree_element_seq.hh" + +namespace blender::ed::outliner { + +TreeElementSequence::TreeElementSequence(TreeElement &legacy_te, Sequence &sequence) + : AbstractTreeElement(legacy_te), sequence_(sequence) +{ + BLI_assert(legacy_te.store_elem->type == TSE_SEQUENCE); + + /* + * The idcode is a little hack, but the outliner + * only check te->idcode if te->type is equal to zero, + * so this is "safe". + */ + legacy_te.idcode = sequence_.type; + legacy_te.name = sequence_.name + 2; +} + +bool TreeElementSequence::expandPoll(const SpaceOutliner & /*space_outliner*/) const +{ + return !(sequence_.type & SEQ_TYPE_EFFECT); +} + +void TreeElementSequence::expand(SpaceOutliner &space_outliner) const +{ + /* + * This work like the sequence. + * If the sequence have a name (not default name) + * show it, in other case put the filename. + */ + + if (sequence_.type == SEQ_TYPE_META) { + LISTBASE_FOREACH (Sequence *, child, &sequence_.seqbase) { + outliner_add_element( + &space_outliner, &legacy_te_.subtree, child, &legacy_te_, TSE_SEQUENCE, 0); + } + } + else { + outliner_add_element( + &space_outliner, &legacy_te_.subtree, sequence_.strip, &legacy_te_, TSE_SEQ_STRIP, 0); + } +} + +Sequence &TreeElementSequence::getSequence() const +{ + return sequence_; +} + +/* -------------------------------------------------------------------- */ +/* Strip */ + +TreeElementSequenceStrip::TreeElementSequenceStrip(TreeElement &legacy_te, Strip &strip) + : AbstractTreeElement(legacy_te) +{ + BLI_assert(legacy_te.store_elem->type == TSE_SEQ_STRIP); + + if (strip.dir[0] != '\0') { + legacy_te_.name = strip.dir; + } + else { + legacy_te_.name = IFACE_("Strip None"); + } +} + +/* -------------------------------------------------------------------- */ +/* Strip Duplicate */ + +TreeElementSequenceStripDuplicate::TreeElementSequenceStripDuplicate(TreeElement &legacy_te, + Sequence &sequence) + : AbstractTreeElement(legacy_te), sequence_(sequence) +{ + BLI_assert(legacy_te.store_elem->type == TSE_SEQUENCE_DUP); + + legacy_te_.idcode = sequence.type; + legacy_te_.name = sequence.strip->stripdata->name; +} + +Sequence &TreeElementSequenceStripDuplicate::getSequence() const +{ + return sequence_; +} + +} // namespace blender::ed::outliner diff --git a/source/blender/editors/space_outliner/tree/tree_element_seq.hh b/source/blender/editors/space_outliner/tree/tree_element_seq.hh new file mode 100644 index 00000000000..2b334b5b7fa --- /dev/null +++ b/source/blender/editors/space_outliner/tree/tree_element_seq.hh @@ -0,0 +1,60 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup spoutliner + */ + +#pragma once + +#include "tree_element.hh" + +struct Sequence; +struct Strip; + +namespace blender::ed::outliner { + +class TreeElementSequence : public AbstractTreeElement { + Sequence &sequence_; + + public: + TreeElementSequence(TreeElement &legacy_te, Sequence &sequence); + + bool expandPoll(const SpaceOutliner &) const override; + void expand(SpaceOutliner &) const override; + + Sequence &getSequence() const; +}; + +/* -------------------------------------------------------------------- */ + +class TreeElementSequenceStrip : public AbstractTreeElement { + public: + TreeElementSequenceStrip(TreeElement &legacy_te, Strip &strip); +}; + +/* -------------------------------------------------------------------- */ + +class TreeElementSequenceStripDuplicate : public AbstractTreeElement { + Sequence &sequence_; + + public: + TreeElementSequenceStripDuplicate(TreeElement &legacy_te, Sequence &sequence); + + Sequence &getSequence() const; +}; + +} // namespace blender::ed::outliner diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index 6e3598703a2..f143730c5cb 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -107,6 +107,8 @@ typedef enum eGPUMaterialFlag { GPU_MATFLAG_LOOKDEV_HACK = (1 << 30), } eGPUMaterialFlag; +ENUM_OPERATORS(eGPUMaterialFlag, GPU_MATFLAG_LOOKDEV_HACK); + typedef struct GPUNodeStack { eGPUType type; float vec[4]; @@ -173,6 +175,10 @@ bool GPU_stack_link(GPUMaterial *mat, GPUNodeStack *in, GPUNodeStack *out, ...); +/** + * This is a special function to call the "*_eval" function of a BSDF node. + * \note This must be call right after GPU_stack_link() so that out[0] contains a valid link. + */ bool GPU_stack_eval_link(GPUMaterial *material, struct bNode *bnode, const char *name, diff --git a/source/blender/gpu/intern/gpu_node_graph.c b/source/blender/gpu/intern/gpu_node_graph.c index 593a89bbf21..65848620339 100644 --- a/source/blender/gpu/intern/gpu_node_graph.c +++ b/source/blender/gpu/intern/gpu_node_graph.c @@ -647,27 +647,25 @@ bool GPU_link(GPUMaterial *mat, const char *name, ...) } va_end(params); - GPUNodeGraph *graph = gpu_material_node_graph(mat); BLI_addtail(&graph->nodes, node); return true; } -bool GPU_stack_link(GPUMaterial *material, - bNode *bnode, - const char *name, - GPUNodeStack *in, - GPUNodeStack *out, - ...) +static bool gpu_stack_link_v(GPUMaterial *material, + bNode *bnode, + const char *name, + GPUNodeStack *in, + GPUNodeStack *out, + va_list params) { - GSet *used_libraries = gpu_material_used_libraries(material); + GPUNodeGraph *graph = gpu_material_node_graph(material); GPUNode *node; GPUFunction *function; GPUNodeLink *link, **linkptr; - va_list params; int i, totin, totout; - function = gpu_material_library_use_function(used_libraries, name); + function = gpu_material_library_use_function(graph->used_libraries, name); if (!function) { fprintf(stderr, "GPU failed to find function %s\n", name); return false; @@ -695,7 +693,6 @@ bool GPU_stack_link(GPUMaterial *material, } } - va_start(params, out); for (i = 0; i < function->totparam; i++) { if (function->paramqual[i] != FUNCTION_QUAL_IN) { if (totout == 0) { @@ -721,14 +718,51 @@ bool GPU_stack_link(GPUMaterial *material, } } } - va_end(params); - GPUNodeGraph *graph = gpu_material_node_graph(material); BLI_addtail(&graph->nodes, node); return true; } +bool GPU_stack_link(GPUMaterial *material, + bNode *bnode, + const char *name, + GPUNodeStack *in, + GPUNodeStack *out, + ...) +{ + va_list params; + va_start(params, out); + bool valid = gpu_stack_link_v(material, bnode, name, in, out, params); + va_end(params); + + return valid; +} + +bool GPU_stack_eval_link(GPUMaterial *material, + bNode *bnode, + const char *name, + GPUNodeStack *in, + GPUNodeStack *out, + ...) +{ + /* Save the closure link to replace the one created by the eval function call. Avoiding + * dependency to the eval call before the end of the graph. */ + GPUNodeLink *closure_out = out[0].link; + + va_list params; + va_start(params, out); + bool valid = gpu_stack_link_v(material, bnode, name, in, out, params); + va_end(params); + + /* Save both nodes for graph amendment. */ + GPU_material_add_closure_eval(material, closure_out, out[0].link); + /* Restore original link. */ + out[0].link = closure_out; + + return valid; +} + GPUNodeLink *GPU_uniformbuf_link_out(GPUMaterial *mat, bNode *node, GPUNodeStack *stack, @@ -790,7 +824,11 @@ void gpu_node_graph_free_nodes(GPUNodeGraph *graph) gpu_node_free(node); } - graph->outlink = NULL; + BLI_freelistN(&graph->eval_nodes); + graph->outlink_surface = NULL; + graph->outlink_volume = NULL; + graph->outlink_displacement = NULL; + graph->outlink_thickness = NULL; } void gpu_node_graph_free(GPUNodeGraph *graph) @@ -805,28 +843,32 @@ void gpu_node_graph_free(GPUNodeGraph *graph) BLI_freelistN(&graph->textures); BLI_freelistN(&graph->attributes); GPU_uniform_attr_list_free(&graph->uniform_attrs); + + if (graph->used_libraries) { + BLI_gset_free(graph->used_libraries, NULL); + graph->used_libraries = NULL; + } } /* Prune Unused Nodes */ -static void gpu_nodes_tag(GPUNodeLink *link) +static void gpu_nodes_tag(GPUNodeLink *link, eGPUNodeTag tag) { GPUNode *node; - GPUInput *input; - if (!link->output) { + if (!link || !link->output) { return; } node = link->output->node; - if (node->tag) { + if (node->tag & tag) { return; } - node->tag = true; - for (input = node->inputs.first; input; input = input->next) { + node->tag |= tag; + LISTBASE_FOREACH (GPUInput *, input, &node->inputs) { if (input->link) { - gpu_nodes_tag(input->link); + gpu_nodes_tag(input->link, tag); } } } @@ -834,18 +876,30 @@ static void gpu_nodes_tag(GPUNodeLink *link) void gpu_node_graph_prune_unused(GPUNodeGraph *graph) { LISTBASE_FOREACH (GPUNode *, node, &graph->nodes) { - node->tag = false; + node->tag = GPU_NODE_TAG_NONE; } - gpu_nodes_tag(graph->outlink); + gpu_nodes_tag(graph->outlink_surface, GPU_NODE_TAG_SURFACE); + gpu_nodes_tag(graph->outlink_volume, GPU_NODE_TAG_VOLUME); + gpu_nodes_tag(graph->outlink_displacement, GPU_NODE_TAG_DISPLACEMENT); + gpu_nodes_tag(graph->outlink_thickness, GPU_NODE_TAG_THICKNESS); + LISTBASE_FOREACH (GPUNodeGraphOutputLink *, aovlink, &graph->outlink_aovs) { - gpu_nodes_tag(aovlink->outlink); + gpu_nodes_tag(aovlink->outlink, GPU_NODE_TAG_AOV); + } + + LISTBASE_FOREACH (GPUNodeGraphEvalNode *, node, &graph->eval_nodes) { + /* Copy weight node tag to avoid pruning of eval node since they are node connected to + * output. */ + if (node->weight_node->tag != GPU_NODE_TAG_NONE) { + node->eval_node->tag = GPU_NODE_TAG_EVAL | node->weight_node->tag; + } } for (GPUNode *node = graph->nodes.first, *next = NULL; node; node = next) { next = node->next; - if (!node->tag) { + if (node->tag == GPU_NODE_TAG_NONE) { BLI_remlink(&graph->nodes, node); gpu_node_free(node); } diff --git a/source/blender/gpu/intern/gpu_shader_builder_stubs.cc b/source/blender/gpu/intern/gpu_shader_builder_stubs.cc index 40e54ab4394..469085026b3 100644 --- a/source/blender/gpu/intern/gpu_shader_builder_stubs.cc +++ b/source/blender/gpu/intern/gpu_shader_builder_stubs.cc @@ -216,10 +216,7 @@ int BKE_subdiv_ccg_grid_to_face_index(const SubdivCCG *UNUSED(subdiv_ccg), /* -------------------------------------------------------------------- */ /** \name Stubs of BKE_node.h * \{ */ -void ntreeGPUMaterialNodes(struct bNodeTree *UNUSED(localtree), - struct GPUMaterial *UNUSED(mat), - bool *UNUSED(has_surface_output), - bool *UNUSED(has_volume_output)) +void ntreeGPUMaterialNodes(struct bNodeTree *UNUSED(localtree), struct GPUMaterial *UNUSED(mat)) { BLI_assert_unreachable(); } diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h index 57740ce3ad9..3ebd3ef8a2a 100644 --- a/source/blender/nodes/NOD_shader.h +++ b/source/blender/nodes/NOD_shader.h @@ -160,10 +160,7 @@ struct bNode *ntreeShaderOutputNode(struct bNodeTree *ntree, int target); /** * This one needs to work on a local tree. */ -void ntreeGPUMaterialNodes(struct bNodeTree *localtree, - struct GPUMaterial *mat, - bool *has_surface_output, - bool *has_volume_output); +void ntreeGPUMaterialNodes(struct bNodeTree *localtree, struct GPUMaterial *mat); #ifdef __cplusplus } diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc index 68b609f8045..81421609dfd 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc @@ -44,7 +44,9 @@ static void node_declare(NodeDeclarationBuilder &b) .subtype(PropertySubType::PROP_DISTANCE) .default_value(0.25f) .supports_field(); - b.add_input<decl::Bool>(N_("Limit Radius")); + b.add_input<decl::Bool>(N_("Limit Radius")) + .description( + N_("Limit the maximum value of the radius in order to avoid overlapping fillets")); b.add_output<decl::Geometry>(N_("Curve")); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc index ae282017e0c..c2b9ddfb114 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc @@ -30,7 +30,12 @@ namespace blender::nodes::node_geo_curve_subdivide_cc { static void node_declare(NodeDeclarationBuilder &b) { b.add_input<decl::Geometry>(N_("Curve")).supported_type(GEO_COMPONENT_TYPE_CURVE); - b.add_input<decl::Int>(N_("Cuts")).default_value(1).min(0).max(1000).supports_field(); + b.add_input<decl::Int>(N_("Cuts")) + .default_value(1) + .min(0) + .max(1000) + .supports_field() + .description(N_("The number of control points to create on the segment following each point")); b.add_output<decl::Geometry>(N_("Curve")); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_id.cc b/source/blender/nodes/geometry/nodes/node_geo_input_id.cc index 3fe0588a46d..afe7546f7e5 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_id.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_id.cc @@ -20,7 +20,9 @@ namespace blender::nodes::node_geo_input_id_cc { static void node_declare(NodeDeclarationBuilder &b) { - b.add_output<decl::Int>(N_("ID")).field_source(); + b.add_output<decl::Int>(N_("ID")).field_source().description( + N_("The values from the \"id\" attribute on points, or the index if that attribute does not " + "exist")); } static void node_geo_exec(GeoNodeExecParams params) diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_edge_neighbors.cc b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_edge_neighbors.cc index ddeb3ded511..43c867e0977 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_edge_neighbors.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_edge_neighbors.cc @@ -27,7 +27,7 @@ static void node_declare(NodeDeclarationBuilder &b) { b.add_output<decl::Int>(N_("Face Count")) .field_source() - .description(N_("Number of faces that contain the edge")); + .description(N_("The number of faces that use each edge as one of their sides")); } class EdgeNeighborCountFieldInput final : public GeometryFieldInput { diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_island.cc b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_island.cc index 68bb93bbb64..f1777c9ebf5 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_island.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_island.cc @@ -29,8 +29,8 @@ static void node_declare(NodeDeclarationBuilder &b) { b.add_output<decl::Int>(N_("Island Index")) .field_source() - .description(N_("Island indices are based on the order of the lowest-numbered vertex " - "contained in each island")); + .description(N_("The index of the each vertex's island. Indices are based on the " + "lowest vertex index contained in each island")); b.add_output<decl::Int>(N_("Island Count")) .field_source() .description(N_("The total number of mesh islands")); diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_vertex_neighbors.cc b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_vertex_neighbors.cc index 7d79164634d..c2da065cbfc 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_vertex_neighbors.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_vertex_neighbors.cc @@ -27,7 +27,8 @@ static void node_declare(NodeDeclarationBuilder &b) { b.add_output<decl::Int>(N_("Vertex Count")) .field_source() - .description(N_("Vertex count and edge count are equal")); + .description(N_("The number of vertices connected to this vertex with an edge, " + "equal to the number of connected edges")); b.add_output<decl::Int>(N_("Face Count")) .field_source() .description(N_("Number of faces that contain the vertex")); diff --git a/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc b/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc index 71256a7f781..06f24113308 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc @@ -36,7 +36,8 @@ static void node_declare(NodeDeclarationBuilder &b) .description(N_("Geometry that is instanced on the points")); b.add_input<decl::Bool>(N_("Pick Instance")) .supports_field() - .description(N_("Place different instances on different points")); + .description(N_("Choose instances from the \"Instance\" input at each point instead of " + "instancing the entire geometry")); b.add_input<decl::Int>(N_("Instance Index")) .implicit_field() .description(N_( diff --git a/source/blender/nodes/intern/node_exec.cc b/source/blender/nodes/intern/node_exec.cc index 4ff662036c3..788d938ca6f 100644 --- a/source/blender/nodes/intern/node_exec.cc +++ b/source/blender/nodes/intern/node_exec.cc @@ -35,7 +35,7 @@ #include "node_exec.h" #include "node_util.h" -int node_exec_socket_use_stack(bNodeSocket *sock) +static int node_exec_socket_use_stack(bNodeSocket *sock) { /* NOTE: INT supported as FLOAT. Only for EEVEE. */ return ELEM(sock->type, SOCK_INT, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA, SOCK_SHADER); @@ -276,60 +276,3 @@ void ntree_exec_end(bNodeTreeExec *exec) MEM_freeN(exec); } - -/**** Material/Texture trees ****/ - -bNodeThreadStack *ntreeGetThreadStack(bNodeTreeExec *exec, int thread) -{ - ListBase *lb = &exec->threadstack[thread]; - bNodeThreadStack *nts; - - for (nts = (bNodeThreadStack *)lb->first; nts; nts = nts->next) { - if (!nts->used) { - nts->used = true; - break; - } - } - - if (!nts) { - nts = MEM_cnew<bNodeThreadStack>("bNodeThreadStack"); - nts->stack = (bNodeStack *)MEM_dupallocN(exec->stack); - nts->used = true; - BLI_addtail(lb, nts); - } - - return nts; -} - -void ntreeReleaseThreadStack(bNodeThreadStack *nts) -{ - nts->used = false; -} - -bool ntreeExecThreadNodes(bNodeTreeExec *exec, bNodeThreadStack *nts, void *callerdata, int thread) -{ - bNodeStack *nsin[MAX_SOCKET] = {nullptr}; /* arbitrary... watch this */ - bNodeStack *nsout[MAX_SOCKET] = {nullptr}; /* arbitrary... watch this */ - bNodeExec *nodeexec; - bNode *node; - int n; - - /* nodes are presorted, so exec is in order of list */ - - for (n = 0, nodeexec = exec->nodeexec; n < exec->totnodes; n++, nodeexec++) { - node = nodeexec->node; - if (node->need_exec) { - node_get_stack(node, nts->stack, nsin, nsout); - /* Handle muted nodes... - * If the mute func is not set, assume the node should never be muted, - * and hence execute it! - */ - if (node->typeinfo->exec_fn && !(node->flag & NODE_MUTED)) { - node->typeinfo->exec_fn(callerdata, thread, node, &nodeexec->data, nsin, nsout); - } - } - } - - /* signal to that all went OK, for render */ - return true; -} diff --git a/source/blender/nodes/intern/node_exec.h b/source/blender/nodes/intern/node_exec.h index b2e1c6564b6..115389afd67 100644 --- a/source/blender/nodes/intern/node_exec.h +++ b/source/blender/nodes/intern/node_exec.h @@ -71,9 +71,6 @@ typedef struct bNodeThreadStack { bool used; } bNodeThreadStack; -/** Supported socket types in old nodes. */ -int node_exec_socket_use_stack(struct bNodeSocket *sock); - /** For a given socket, find the actual stack entry. */ struct bNodeStack *node_get_socket_stack(struct bNodeStack *stack, struct bNodeSocket *sock); void node_get_stack(struct bNode *node, @@ -86,23 +83,6 @@ struct bNodeTreeExec *ntree_exec_begin(struct bNodeExecContext *context, bNodeInstanceKey parent_key); void ntree_exec_end(struct bNodeTreeExec *exec); -struct bNodeThreadStack *ntreeGetThreadStack(struct bNodeTreeExec *exec, int thread); -void ntreeReleaseThreadStack(struct bNodeThreadStack *nts); -bool ntreeExecThreadNodes(struct bNodeTreeExec *exec, - struct bNodeThreadStack *nts, - void *callerdata, - int thread); - -struct bNodeTreeExec *ntreeShaderBeginExecTree_internal(struct bNodeExecContext *context, - struct bNodeTree *ntree, - bNodeInstanceKey parent_key); -void ntreeShaderEndExecTree_internal(struct bNodeTreeExec *exec); - -struct bNodeTreeExec *ntreeTexBeginExecTree_internal(struct bNodeExecContext *context, - struct bNodeTree *ntree, - bNodeInstanceKey parent_key); -void ntreeTexEndExecTree_internal(struct bNodeTreeExec *exec); - #ifdef __cplusplus } #endif diff --git a/source/blender/nodes/shader/node_shader_tree.cc b/source/blender/nodes/shader/node_shader_tree.cc index 1cb1ee3163d..8bf4f37a70b 100644 --- a/source/blender/nodes/shader/node_shader_tree.cc +++ b/source/blender/nodes/shader/node_shader_tree.cc @@ -262,13 +262,13 @@ static bNodeSocket *ntree_shader_node_find_output(bNode *node, const char *ident /* Find input socket at a specific position. */ static bNodeSocket *ntree_shader_node_input_get(bNode *node, int n) { - return BLI_findlink(&node->inputs, n); + return reinterpret_cast<bNodeSocket *>(BLI_findlink(&node->inputs, n)); } /* Find output socket at a specific position. */ static bNodeSocket *ntree_shader_node_output_get(bNode *node, int n) { - return BLI_findlink(&node->outputs, n); + return reinterpret_cast<bNodeSocket *>(BLI_findlink(&node->outputs, n)); } /* Return true on success. */ @@ -940,7 +940,7 @@ static void ntree_shader_weight_tree_invert(bNodeTree *ntree, bNode *output_node int node_count = 1; nodeChainIterBackwards(ntree, output_node, ntree_weight_tree_tag_nodes, &node_count, 0); /* Make a mirror copy of the weight tree. */ - bNode **nodes_copy = MEM_mallocN(sizeof(bNode *) * node_count, __func__); + bNode **nodes_copy = static_cast<bNode **>(MEM_mallocN(sizeof(bNode *) * node_count, __func__)); LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { if (node->tmp_flag >= 0) { int id = node->tmp_flag; diff --git a/source/blender/nodes/shader/node_shader_util.hh b/source/blender/nodes/shader/node_shader_util.hh index 5a5b4f613f3..31229c8693b 100644 --- a/source/blender/nodes/shader/node_shader_util.hh +++ b/source/blender/nodes/shader/node_shader_util.hh @@ -101,6 +101,11 @@ void node_shader_gpu_tex_mapping(struct GPUMaterial *mat, struct GPUNodeStack *in, struct GPUNodeStack *out); +struct bNodeTreeExec *ntreeShaderBeginExecTree_internal(struct bNodeExecContext *context, + struct bNodeTree *ntree, + bNodeInstanceKey parent_key); +void ntreeShaderEndExecTree_internal(struct bNodeTreeExec *exec); + void ntreeExecGPUNodes(struct bNodeTreeExec *exec, struct GPUMaterial *mat, struct bNode *output_node); diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.cc index 3f0749ab2af..42f56a0b576 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.cc +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.cc @@ -40,6 +40,7 @@ static void node_declare(NodeDeclarationBuilder &b) .subtype(PROP_FACTOR); b.add_input<decl::Vector>(N_("Normal")).hide_value(); b.add_input<decl::Vector>(N_("Tangent")).hide_value(); + b.add_input<decl::Float>(N_("Weight")).unavailable(); b.add_output<decl::Shader>(N_("BSDF")); } @@ -67,13 +68,12 @@ static int node_shader_gpu_bsdf_anisotropic(GPUMaterial *mat, float use_multi_scatter = (node->custom1 == SHD_GLOSSY_MULTI_GGX) ? 1.0f : 0.0f; - return GPU_stack_link(mat, - node, - "node_bsdf_anisotropic", - in, - out, - GPU_constant(&use_multi_scatter), - GPU_constant(&node->ssr_id)); + GPU_stack_link(mat, node, "node_bsdf_anisotropic", in, out); + + GPU_stack_eval_link( + mat, node, "node_bsdf_anisotropic_eval", in, out, GPU_constant(&use_multi_scatter)); + + return true; } } // namespace blender::nodes::node_shader_bsdf_anisotropic_cc diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.cc index 5848ca76cdd..9767da497ed 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.cc +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.cc @@ -30,6 +30,7 @@ static void node_declare(NodeDeclarationBuilder &b) .max(1.0f) .subtype(PROP_FACTOR); b.add_input<decl::Vector>(N_("Normal")).hide_value(); + b.add_input<decl::Float>(N_("Weight")).unavailable(); b.add_output<decl::Shader>(N_("BSDF")); } @@ -45,7 +46,8 @@ static int node_shader_gpu_bsdf_diffuse(GPUMaterial *mat, GPU_material_flag_set(mat, GPU_MATFLAG_DIFFUSE); - return GPU_stack_link(mat, node, "node_bsdf_diffuse", in, out); + GPU_stack_link(mat, node, "node_bsdf_diffuse", in, out); + return GPU_stack_eval_link(mat, node, "node_bsdf_diffuse_eval", in, out); } } // namespace blender::nodes::node_shader_bsdf_diffuse_cc diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.cc index 47d4b87198b..fbc35c23734 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.cc +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.cc @@ -31,6 +31,7 @@ static void node_declare(NodeDeclarationBuilder &b) .subtype(PROP_FACTOR); b.add_input<decl::Float>(N_("IOR")).default_value(1.45f).min(0.0f).max(1000.0f); b.add_input<decl::Vector>(N_("Normal")).hide_value(); + b.add_input<decl::Float>(N_("Weight")).unavailable(); b.add_output<decl::Shader>(N_("BSDF")); } @@ -53,17 +54,30 @@ static int node_shader_gpu_bsdf_glass(GPUMaterial *mat, GPU_link(mat, "set_value_zero", &in[1].link); } - GPU_material_flag_set(mat, (eGPUMatFlag)(GPU_MATFLAG_GLOSSY | GPU_MATFLAG_REFRACT)); + GPU_material_flag_set(mat, GPU_MATFLAG_GLOSSY | GPU_MATFLAG_REFRACT); float use_multi_scatter = (node->custom1 == SHD_GLOSSY_MULTI_GGX) ? 1.0f : 0.0f; - return GPU_stack_link(mat, - node, - "node_bsdf_glass", - in, - out, - GPU_constant(&use_multi_scatter), - GPU_constant(&node->ssr_id)); + GPUNodeLink *reflection_weight; + GPUNodeLink *refraction_weight; + + GPU_stack_link(mat, + node, + "node_bsdf_glass", + in, + out, + GPU_constant(&use_multi_scatter), + &reflection_weight, + &refraction_weight); + + return GPU_stack_eval_link(mat, + node, + "node_bsdf_glass_eval", + in, + out, + GPU_constant(&use_multi_scatter), + reflection_weight, + refraction_weight); } } // namespace blender::nodes::node_shader_bsdf_glass_cc diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.cc index 03a3e634f56..879e00a6995 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.cc +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.cc @@ -30,6 +30,7 @@ static void node_declare(NodeDeclarationBuilder &b) .max(1.0f) .subtype(PROP_FACTOR); b.add_input<decl::Vector>(N_("Normal")).hide_value(); + b.add_input<decl::Float>(N_("Weight")).unavailable(); b.add_output<decl::Shader>(N_("BSDF")); } @@ -56,13 +57,9 @@ static int node_shader_gpu_bsdf_glossy(GPUMaterial *mat, float use_multi_scatter = (node->custom1 == SHD_GLOSSY_MULTI_GGX) ? 1.0f : 0.0f; - return GPU_stack_link(mat, - node, - "node_bsdf_glossy", - in, - out, - GPU_constant(&use_multi_scatter), - GPU_constant(&node->ssr_id)); + GPU_stack_link(mat, node, "node_bsdf_glossy", in, out); + return GPU_stack_eval_link( + mat, node, "node_bsdf_glossy_eval", in, out, GPU_constant(&use_multi_scatter)); } } // namespace blender::nodes::node_shader_bsdf_glossy_cc diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc index 4c378d9bc09..e49a39b5a4a 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc @@ -144,8 +144,6 @@ static int node_shader_gpu_bsdf_principled(GPUMaterial *mat, GPUNodeStack *in, GPUNodeStack *out) { - GPUNodeLink *sss_scale; - /* Normals */ if (!in[22].link) { GPU_link(mat, "world_normals_get", &in[22].link); @@ -161,36 +159,17 @@ static int node_shader_gpu_bsdf_principled(GPUMaterial *mat, if (!in[24].link) { GPUNodeLink *orco = GPU_attribute(CD_ORCO, ""); GPU_link(mat, "tangent_orco_z", orco, &in[24].link); - GPU_link(mat, - "node_tangent", - GPU_builtin(GPU_WORLD_NORMAL), - in[24].link, - GPU_builtin(GPU_OBJECT_MATRIX), - &in[24].link); + GPU_link(mat, "node_tangent", in[24].link, &in[24].link); } #endif bool use_diffuse = socket_not_one(6) && socket_not_one(17); - bool use_subsurf = socket_not_zero(1) && use_diffuse && node->sss_id > 0; + bool use_subsurf = socket_not_zero(1) && use_diffuse; bool use_refract = socket_not_one(6) && socket_not_zero(17); - bool use_clear = socket_not_zero(14); + bool use_transparency = socket_not_one(21); + // bool use_clear = socket_not_zero(14); - /* SSS Profile */ - if (use_subsurf) { - bNodeSocket *socket = (bNodeSocket *)BLI_findlink(&node->original->inputs, 2); - bNodeSocketValueRGBA *socket_data = (bNodeSocketValueRGBA *)socket->default_value; - /* For some reason it seems that the socket value is in ARGB format. */ - GPU_material_sss_profile_create(mat, &socket_data->value[1]); - } - - if (in[2].link) { - sss_scale = in[2].link; - } - else { - GPU_link(mat, "set_rgb_one", &sss_scale); - } - - uint flag = GPU_MATFLAG_GLOSSY; + eGPUMaterialFlag flag = GPU_MATFLAG_GLOSSY; if (use_diffuse) { flag |= GPU_MATFLAG_DIFFUSE; } @@ -198,28 +177,42 @@ static int node_shader_gpu_bsdf_principled(GPUMaterial *mat, flag |= GPU_MATFLAG_REFRACT; } if (use_subsurf) { - flag |= GPU_MATFLAG_SSS; + flag |= GPU_MATFLAG_SUBSURFACE; + } + if (use_transparency) { + flag |= GPU_MATFLAG_TRANSPARENT; } - float f_use_diffuse = use_diffuse ? 1.0f : 0.0f; - float f_use_clearcoat = use_clear ? 1.0f : 0.0f; - float f_use_refraction = use_refract ? 1.0f : 0.0f; float use_multi_scatter = (node->custom1 == SHD_GLOSSY_MULTI_GGX) ? 1.0f : 0.0f; - GPU_material_flag_set(mat, (eGPUMatFlag)flag); - - return GPU_stack_link(mat, - node, - "node_bsdf_principled", - in, - out, - GPU_constant(&f_use_diffuse), - GPU_constant(&f_use_clearcoat), - GPU_constant(&f_use_refraction), - GPU_constant(&use_multi_scatter), - GPU_constant(&node->ssr_id), - GPU_constant(&node->sss_id), - sss_scale); + GPU_material_flag_set(mat, flag); + + GPUNodeLink *diffuse_weight, *specular_weight, *glass_reflection_weight, + *glass_transmission_weight, *clearcoat_weight; + + GPU_stack_link(mat, + node, + "node_bsdf_principled", + in, + out, + GPU_constant(&use_multi_scatter), + &diffuse_weight, + &specular_weight, + &glass_reflection_weight, + &glass_transmission_weight, + &clearcoat_weight); + + return GPU_stack_eval_link(mat, + node, + "node_bsdf_principled_eval", + in, + out, + GPU_constant(&use_multi_scatter), + diffuse_weight, + specular_weight, + glass_reflection_weight, + glass_transmission_weight, + clearcoat_weight); } static void node_shader_update_principled(bNodeTree *ntree, bNode *node) diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.cc index 0d588c82869..b1320714c70 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.cc +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.cc @@ -31,6 +31,7 @@ static void node_declare(NodeDeclarationBuilder &b) .subtype(PROP_FACTOR); b.add_input<decl::Float>(N_("IOR")).default_value(1.45f).min(0.0f).max(1000.0f); b.add_input<decl::Vector>(N_("Normal")).hide_value(); + b.add_input<decl::Float>(N_("Weight")).unavailable(); b.add_output<decl::Shader>(N_("BSDF")); } @@ -55,7 +56,8 @@ static int node_shader_gpu_bsdf_refraction(GPUMaterial *mat, GPU_material_flag_set(mat, GPU_MATFLAG_REFRACT); - return GPU_stack_link(mat, node, "node_bsdf_refraction", in, out); + GPU_stack_link(mat, node, "node_bsdf_refraction", in, out); + return GPU_stack_eval_link(mat, node, "node_bsdf_refraction_eval", in, out); } } // namespace blender::nodes::node_shader_bsdf_refraction_cc diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_toon.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_toon.cc index 5093b896764..4c9ca56eab2 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_toon.cc +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_toon.cc @@ -38,6 +38,7 @@ static void node_declare(NodeDeclarationBuilder &b) .max(1.0f) .subtype(PROP_FACTOR); b.add_input<decl::Vector>(N_("Normal")).hide_value(); + b.add_input<decl::Float>(N_("Weight")).unavailable(); b.add_output<decl::Shader>(N_("BSDF")); } @@ -58,7 +59,8 @@ static int node_shader_gpu_bsdf_toon(GPUMaterial *mat, GPU_material_flag_set(mat, GPU_MATFLAG_DIFFUSE); - return GPU_stack_link(mat, node, "node_bsdf_toon", in, out); + GPU_stack_link(mat, node, "node_bsdf_toon", in, out); + return GPU_stack_eval_link(mat, node, "node_bsdf_toon_eval", in, out); } } // namespace blender::nodes::node_shader_bsdf_toon_cc diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.cc index 22891738299..ec85b5357fa 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.cc +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.cc @@ -25,6 +25,7 @@ static void node_declare(NodeDeclarationBuilder &b) { b.add_input<decl::Color>(N_("Color")).default_value({0.8f, 0.8f, 0.8f, 1.0f}); b.add_input<decl::Vector>(N_("Normal")).hide_value(); + b.add_input<decl::Float>(N_("Weight")).unavailable(); b.add_output<decl::Shader>(N_("BSDF")); } @@ -40,7 +41,8 @@ static int node_shader_gpu_bsdf_translucent(GPUMaterial *mat, GPU_material_flag_set(mat, GPU_MATFLAG_DIFFUSE); - return GPU_stack_link(mat, node, "node_bsdf_translucent", in, out); + GPU_stack_link(mat, node, "node_bsdf_translucent", in, out); + return GPU_stack_eval_link(mat, node, "node_bsdf_translucent_eval", in, out); } } // namespace blender::nodes::node_shader_bsdf_translucent_cc diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.cc index d764f4dd76b..d79f3884a4b 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.cc +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.cc @@ -33,6 +33,9 @@ static int node_shader_gpu_bsdf_transparent(GPUMaterial *mat, GPUNodeStack *in, GPUNodeStack *out) { + if (in[0].link || !is_zero_v3(in[0].vec)) { + GPU_material_flag_set(mat, GPU_MATFLAG_TRANSPARENT); + } return GPU_stack_link(mat, node, "node_bsdf_transparent", in, out); } diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.cc index dd090236c08..7822c2f5961 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.cc +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.cc @@ -30,6 +30,7 @@ static void node_declare(NodeDeclarationBuilder &b) .max(1.0f) .subtype(PROP_FACTOR); b.add_input<decl::Vector>(N_("Normal")).hide_value(); + b.add_input<decl::Float>(N_("Weight")).unavailable(); b.add_output<decl::Shader>(N_("BSDF")); } @@ -45,7 +46,8 @@ static int node_shader_gpu_bsdf_velvet(GPUMaterial *mat, GPU_material_flag_set(mat, GPU_MATFLAG_DIFFUSE); - return GPU_stack_link(mat, node, "node_bsdf_velvet", in, out); + GPU_stack_link(mat, node, "node_bsdf_velvet", in, out); + return GPU_stack_link(mat, node, "node_bsdf_velvet_eval", in, out); } } // namespace blender::nodes::node_shader_bsdf_velvet_cc diff --git a/source/blender/nodes/shader/nodes/node_shader_eevee_specular.cc b/source/blender/nodes/shader/nodes/node_shader_eevee_specular.cc index e4c80725c8e..8db56551236 100644 --- a/source/blender/nodes/shader/nodes/node_shader_eevee_specular.cc +++ b/source/blender/nodes/shader/nodes/node_shader_eevee_specular.cc @@ -49,6 +49,7 @@ static void node_declare(NodeDeclarationBuilder &b) .subtype(PROP_FACTOR); b.add_input<decl::Vector>(N_("Clear Coat Normal")).hide_value(); b.add_input<decl::Float>(N_("Ambient Occlusion")).hide_value(); + b.add_input<decl::Float>(N_("Weight")).unavailable(); b.add_output<decl::Shader>(N_("BSDF")); } @@ -75,9 +76,10 @@ static int node_shader_gpu_eevee_specular(GPUMaterial *mat, GPU_link(mat, "set_value", GPU_constant(&one), &in[9].link); } - GPU_material_flag_set(mat, static_cast<eGPUMatFlag>(GPU_MATFLAG_DIFFUSE | GPU_MATFLAG_GLOSSY)); + GPU_material_flag_set(mat, GPU_MATFLAG_DIFFUSE | GPU_MATFLAG_GLOSSY); - return GPU_stack_link(mat, node, "node_eevee_specular", in, out, GPU_constant(&node->ssr_id)); + GPU_stack_link(mat, node, "node_eevee_specular", in, out); + return GPU_stack_eval_link(mat, node, "node_eevee_specular_eval", in, out); } } // namespace blender::nodes::node_shader_eevee_specular_cc diff --git a/source/blender/nodes/shader/nodes/node_shader_emission.cc b/source/blender/nodes/shader/nodes/node_shader_emission.cc index ea36763578f..93dadf8e898 100644 --- a/source/blender/nodes/shader/nodes/node_shader_emission.cc +++ b/source/blender/nodes/shader/nodes/node_shader_emission.cc @@ -25,6 +25,7 @@ static void node_declare(NodeDeclarationBuilder &b) { b.add_input<decl::Color>(N_("Color")).default_value({1.0f, 1.0f, 1.0f, 1.0f}); b.add_input<decl::Float>(N_("Strength")).default_value(1.0f).min(0.0f).max(1000000.0f); + b.add_input<decl::Float>(N_("Weight")).unavailable(); b.add_output<decl::Shader>(N_("Emission")); } @@ -34,7 +35,8 @@ static int node_shader_gpu_emission(GPUMaterial *mat, GPUNodeStack *in, GPUNodeStack *out) { - return GPU_stack_link(mat, node, "node_emission", in, out, GPU_builtin(GPU_VIEW_NORMAL)); + GPU_material_flag_set(mat, GPU_MATFLAG_EMISSION); + return GPU_stack_link(mat, node, "node_emission", in, out); } } // namespace blender::nodes::node_shader_emission_cc diff --git a/source/blender/nodes/shader/nodes/node_shader_output_material.cc b/source/blender/nodes/shader/nodes/node_shader_output_material.cc index 5fc95b92e3f..e96f55cf3cf 100644 --- a/source/blender/nodes/shader/nodes/node_shader_output_material.cc +++ b/source/blender/nodes/shader/nodes/node_shader_output_material.cc @@ -36,31 +36,24 @@ static int node_shader_gpu_output_material(GPUMaterial *mat, GPUNodeStack *in, GPUNodeStack *out) { - GPUNodeLink *outlink, *alpha_threshold_link, *shadow_threshold_link; - Material *ma = GPU_material_get_material(mat); - - static float no_alpha_threshold = -1.0f; - if (ma) { - alpha_threshold_link = GPU_uniform((ma->blend_method == MA_BM_CLIP) ? &ma->alpha_threshold : - &no_alpha_threshold); - shadow_threshold_link = GPU_uniform((ma->blend_shadow == MA_BS_CLIP) ? &ma->alpha_threshold : - &no_alpha_threshold); + GPUNodeLink *outlink_surface, *outlink_volume, *outlink_displacement, *outlink_thickness; + /* Passthrough node in order to do the right socket conversions (important for displacement). */ + if (in[0].link) { + GPU_link(mat, "node_output_material_surface", in[0].link, &outlink_surface); + GPU_material_output_surface(mat, outlink_surface); } - else { - alpha_threshold_link = GPU_uniform(&no_alpha_threshold); - shadow_threshold_link = GPU_uniform(&no_alpha_threshold); + if (in[1].link) { + GPU_link(mat, "node_output_material_volume", in[1].link, &outlink_volume); + GPU_material_output_volume(mat, outlink_volume); + } + if (in[2].link) { + GPU_link(mat, "node_output_material_displacement", in[2].link, &outlink_displacement); + GPU_material_output_displacement(mat, outlink_displacement); + } + if (in[3].link) { + GPU_link(mat, "node_output_material_thickness", in[3].link, &outlink_thickness); + GPU_material_output_thickness(mat, outlink_thickness); } - - GPU_stack_link(mat, - node, - "node_output_material", - in, - out, - alpha_threshold_link, - shadow_threshold_link, - &outlink); - GPU_material_output_link(mat, outlink); - return true; } diff --git a/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.cc b/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.cc index f60db81b4a9..a3e03d00a1f 100644 --- a/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.cc +++ b/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.cc @@ -41,6 +41,7 @@ static void node_declare(NodeDeclarationBuilder &b) .max(1.0f) .subtype(PROP_FACTOR); b.add_input<decl::Vector>(N_("Normal")).hide_value(); + b.add_input<decl::Float>(N_("Weight")).unavailable(); b.add_output<decl::Shader>(N_("BSSRDF")); } @@ -65,19 +66,9 @@ static int node_shader_gpu_subsurface_scattering(GPUMaterial *mat, GPU_link(mat, "world_normals_get", &in[5].link); } - if (node->sss_id > 0) { - bNodeSocket *socket = (bNodeSocket *)BLI_findlink(&node->original->inputs, 2); - bNodeSocketValueRGBA *socket_data = (bNodeSocketValueRGBA *)socket->default_value; - /* For some reason it seems that the socket value is in ARGB format. */ - GPU_material_sss_profile_create(mat, &socket_data->value[1]); - - /* sss_id is 0 only the node is not connected to any output. - * In this case flagging the material would trigger a bug (see T68736). */ - GPU_material_flag_set(mat, (eGPUMatFlag)(GPU_MATFLAG_DIFFUSE | GPU_MATFLAG_SSS)); - } - - return GPU_stack_link( - mat, node, "node_subsurface_scattering", in, out, GPU_constant(&node->sss_id)); + GPU_material_flag_set(mat, GPU_MATFLAG_DIFFUSE | GPU_MATFLAG_SUBSURFACE); + GPU_stack_link(mat, node, "node_subsurface_scattering", in, out); + return GPU_stack_eval_link(mat, node, "node_subsurface_scattering_eval", in, out); } static void node_shader_update_subsurface_scattering(bNodeTree *ntree, bNode *node) diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_coord.cc b/source/blender/nodes/shader/nodes/node_shader_tex_coord.cc index 1bbaed88ea5..d81316b0f8b 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_coord.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_coord.cc @@ -51,24 +51,22 @@ static int node_shader_gpu_tex_coord(GPUMaterial *mat, { Object *ob = (Object *)node->id; - GPUNodeLink *inv_obmat = (ob != nullptr) ? GPU_uniform(&ob->imat[0][0]) : - GPU_builtin(GPU_INVERSE_OBJECT_MATRIX); + /* Use special matrix to let the shader branch to using the render object's matrix. */ + float dummy_matrix[4][4]; + dummy_matrix[3][3] = 0.0f; + GPUNodeLink *inv_obmat = (ob != NULL) ? GPU_uniform(&ob->imat[0][0]) : + GPU_uniform(&dummy_matrix[0][0]); /* Opti: don't request orco if not needed. */ - const float default_coords[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - GPUNodeLink *orco = (!out[0].hasoutput) ? GPU_constant(default_coords) : - GPU_attribute(mat, CD_ORCO, ""); + float4 zero(0.0f); + GPUNodeLink *orco = (!out[0].hasoutput) ? GPU_constant(zero) : GPU_attribute(mat, CD_ORCO, ""); GPUNodeLink *mtface = GPU_attribute(mat, CD_MTFACE, ""); - GPUNodeLink *viewpos = GPU_builtin(GPU_VIEW_POSITION); - GPUNodeLink *worldnor = GPU_builtin(GPU_WORLD_NORMAL); - GPUNodeLink *texcofacs = GPU_builtin(GPU_CAMERA_TEXCO_FACTORS); if (out[0].hasoutput) { GPU_link(mat, "generated_from_orco", orco, &orco); } - GPU_stack_link( - mat, node, "node_tex_coord", in, out, viewpos, worldnor, inv_obmat, texcofacs, orco, mtface); + GPU_stack_link(mat, node, "node_tex_coord", in, out, inv_obmat, orco, mtface); int i; LISTBASE_FOREACH_INDEX (bNodeSocket *, sock, &node->outputs, i) { diff --git a/source/blender/nodes/shader/nodes/node_shader_vector_transform.cc b/source/blender/nodes/shader/nodes/node_shader_vector_transform.cc index a8a6902e30c..e38f67fb751 100644 --- a/source/blender/nodes/shader/nodes/node_shader_vector_transform.cc +++ b/source/blender/nodes/shader/nodes/node_shader_vector_transform.cc @@ -59,42 +59,43 @@ static void node_shader_init_vect_transform(bNodeTree *UNUSED(ntree), bNode *nod node->storage = vect; } -static GPUNodeLink *get_gpulink_matrix_from_to(short from, short to) +static const char *get_gpufn_name_from_to(short from, short to) { switch (from) { case SHD_VECT_TRANSFORM_SPACE_OBJECT: switch (to) { case SHD_VECT_TRANSFORM_SPACE_OBJECT: - return nullptr; + return NULL; case SHD_VECT_TRANSFORM_SPACE_WORLD: - return GPU_builtin(GPU_OBJECT_MATRIX); + return "object_to_world"; case SHD_VECT_TRANSFORM_SPACE_CAMERA: - return GPU_builtin(GPU_LOC_TO_VIEW_MATRIX); + return "object_to_view"; } break; case SHD_VECT_TRANSFORM_SPACE_WORLD: switch (to) { case SHD_VECT_TRANSFORM_SPACE_WORLD: - return nullptr; + return NULL; case SHD_VECT_TRANSFORM_SPACE_CAMERA: - return GPU_builtin(GPU_VIEW_MATRIX); + return "world_to_view"; case SHD_VECT_TRANSFORM_SPACE_OBJECT: - return GPU_builtin(GPU_INVERSE_OBJECT_MATRIX); + return "world_to_object"; } break; case SHD_VECT_TRANSFORM_SPACE_CAMERA: switch (to) { case SHD_VECT_TRANSFORM_SPACE_CAMERA: - return nullptr; + return NULL; case SHD_VECT_TRANSFORM_SPACE_WORLD: - return GPU_builtin(GPU_INVERSE_VIEW_MATRIX); + return "view_to_world"; case SHD_VECT_TRANSFORM_SPACE_OBJECT: - return GPU_builtin(GPU_INVERSE_LOC_TO_VIEW_MATRIX); + return "view_to_object"; } break; } - return nullptr; + return NULL; } + static int gpu_shader_vect_transform(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), @@ -102,11 +103,6 @@ static int gpu_shader_vect_transform(GPUMaterial *mat, GPUNodeStack *out) { struct GPUNodeLink *inputlink; - struct GPUNodeLink *fromto; - - const char *vtransform = "direction_transform_m4v3"; - const char *ptransform = "point_transform_m4v3"; - const char *func_name = nullptr; NodeShaderVectTransform *nodeprop = (NodeShaderVectTransform *)node->storage; @@ -117,9 +113,10 @@ static int gpu_shader_vect_transform(GPUMaterial *mat, inputlink = GPU_constant(in[0].vec); } - fromto = get_gpulink_matrix_from_to(nodeprop->convert_from, nodeprop->convert_to); + const char *xform = (nodeprop->type == SHD_VECT_TRANSFORM_TYPE_POINT) ? "point_transform_" : + "direction_transform_"; + const char *fromto = get_gpufn_name_from_to(nodeprop->convert_from, nodeprop->convert_to); - func_name = (nodeprop->type == SHD_VECT_TRANSFORM_TYPE_POINT) ? ptransform : vtransform; if (fromto) { /* For cycles we have inverted Z */ /* TODO: pass here the correct matrices */ @@ -127,7 +124,11 @@ static int gpu_shader_vect_transform(GPUMaterial *mat, nodeprop->convert_to != SHD_VECT_TRANSFORM_SPACE_CAMERA) { GPU_link(mat, "invert_z", inputlink, &inputlink); } - GPU_link(mat, func_name, inputlink, fromto, &out[0].link); + + char func_name[48]; + SNPRINTF(func_name, "%s%s", xform, fromto); + GPU_link(mat, func_name, inputlink, &out[0].link); + if (nodeprop->convert_to == SHD_VECT_TRANSFORM_SPACE_CAMERA && nodeprop->convert_from != SHD_VECT_TRANSFORM_SPACE_CAMERA) { GPU_link(mat, "invert_z", out[0].link, &out[0].link); diff --git a/source/blender/nodes/texture/node_texture_tree.c b/source/blender/nodes/texture/node_texture_tree.c index 3d914d486c3..82ed43be779 100644 --- a/source/blender/nodes/texture/node_texture_tree.c +++ b/source/blender/nodes/texture/node_texture_tree.c @@ -170,6 +170,63 @@ void register_node_tree_type_tex(void) ntreeTypeAdd(tt); } +/**** Material/Texture trees ****/ + +bNodeThreadStack *ntreeGetThreadStack(bNodeTreeExec *exec, int thread) +{ + ListBase *lb = &exec->threadstack[thread]; + bNodeThreadStack *nts; + + for (nts = (bNodeThreadStack *)lb->first; nts; nts = nts->next) { + if (!nts->used) { + nts->used = true; + break; + } + } + + if (!nts) { + nts = MEM_callocN(sizeof(bNodeThreadStack), "bNodeThreadStack"); + nts->stack = (bNodeStack *)MEM_dupallocN(exec->stack); + nts->used = true; + BLI_addtail(lb, nts); + } + + return nts; +} + +void ntreeReleaseThreadStack(bNodeThreadStack *nts) +{ + nts->used = false; +} + +bool ntreeExecThreadNodes(bNodeTreeExec *exec, bNodeThreadStack *nts, void *callerdata, int thread) +{ + bNodeStack *nsin[MAX_SOCKET] = {NULL}; /* arbitrary... watch this */ + bNodeStack *nsout[MAX_SOCKET] = {NULL}; /* arbitrary... watch this */ + bNodeExec *nodeexec; + bNode *node; + int n; + + /* nodes are presorted, so exec is in order of list */ + + for (n = 0, nodeexec = exec->nodeexec; n < exec->totnodes; n++, nodeexec++) { + node = nodeexec->node; + if (node->need_exec) { + node_get_stack(node, nts->stack, nsin, nsout); + /* Handle muted nodes... + * If the mute func is not set, assume the node should never be muted, + * and hence execute it! + */ + if (node->typeinfo->exec_fn && !(node->flag & NODE_MUTED)) { + node->typeinfo->exec_fn(callerdata, thread, node, &nodeexec->data, nsin, nsout); + } + } + } + + /* signal to that all went OK, for render */ + return true; +} + bNodeTreeExec *ntreeTexBeginExecTree_internal(bNodeExecContext *context, bNodeTree *ntree, bNodeInstanceKey parent_key) diff --git a/source/blender/nodes/texture/node_texture_util.h b/source/blender/nodes/texture/node_texture_util.h index d53000058a3..7c8e39925bc 100644 --- a/source/blender/nodes/texture/node_texture_util.h +++ b/source/blender/nodes/texture/node_texture_util.h @@ -123,6 +123,18 @@ void tex_output(bNode *node, void params_from_cdata(TexParams *out, TexCallData *in); +struct bNodeThreadStack *ntreeGetThreadStack(struct bNodeTreeExec *exec, int thread); +void ntreeReleaseThreadStack(struct bNodeThreadStack *nts); +bool ntreeExecThreadNodes(struct bNodeTreeExec *exec, + struct bNodeThreadStack *nts, + void *callerdata, + int thread); + +struct bNodeTreeExec *ntreeTexBeginExecTree_internal(struct bNodeExecContext *context, + struct bNodeTree *ntree, + bNodeInstanceKey parent_key); +void ntreeTexEndExecTree_internal(struct bNodeTreeExec *exec); + #ifdef __cplusplus } #endif |