Function Node: Hash Value #110769
No reviewers
Labels
No Label
Interest
Alembic
Interest
Animation & Rigging
Interest
Asset System
Interest
Audio
Interest
Automated Testing
Interest
Blender Asset Bundle
Interest
BlendFile
Interest
Code Documentation
Interest
Collada
Interest
Compatibility
Interest
Compositing
Interest
Core
Interest
Cycles
Interest
Dependency Graph
Interest
Development Management
Interest
EEVEE
Interest
Freestyle
Interest
Geometry Nodes
Interest
Grease Pencil
Interest
ID Management
Interest
Images & Movies
Interest
Import Export
Interest
Line Art
Interest
Masking
Interest
Metal
Interest
Modeling
Interest
Modifiers
Interest
Motion Tracking
Interest
Nodes & Physics
Interest
OpenGL
Interest
Overlay
Interest
Overrides
Interest
Performance
Interest
Physics
Interest
Pipeline, Assets & IO
Interest
Platforms, Builds & Tests
Interest
Python API
Interest
Render & Cycles
Interest
Render Pipeline
Interest
Sculpt, Paint & Texture
Interest
Text Editor
Interest
Translations
Interest
Triaging
Interest
Undo
Interest
USD
Interest
User Interface
Interest
UV Editing
Interest
VFX & Video
Interest
Video Sequencer
Interest
Viewport & EEVEE
Interest
Virtual Reality
Interest
Vulkan
Interest
Wayland
Interest
Workbench
Interest: X11
Legacy
Asset Browser Project
Legacy
Blender 2.8 Project
Legacy
Milestone 1: Basic, Local Asset Browser
Legacy
OpenGL Error
Meta
Good First Issue
Meta
Papercut
Meta
Retrospective
Meta
Security
Module
Animation & Rigging
Module
Core
Module
Development Management
Module
Grease Pencil
Module
Modeling
Module
Nodes & Physics
Module
Pipeline, Assets & IO
Module
Platforms, Builds & Tests
Module
Python API
Module
Render & Cycles
Module
Sculpt, Paint & Texture
Module
Triaging
Module
User Interface
Module
VFX & Video
Module
Viewport & EEVEE
Platform
FreeBSD
Platform
Linux
Platform
macOS
Platform
Windows
Severity
High
Severity
Low
Severity
Normal
Severity
Unbreak Now!
Status
Archived
Status
Confirmed
Status
Duplicate
Status
Needs Info from Developers
Status
Needs Information from User
Status
Needs Triage
Status
Resolved
Type
Bug
Type
Design
Type
Known Issue
Type
Patch
Type
Report
Type
To Do
No Milestone
No project
No Assignees
8 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: blender/blender#110769
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "CharlieJolly/blender:gn-hash-node"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
This node hashes float, vector, color, string and integers to a hash.
Uses hash functions from BLI_noise.hh.
These are also used in White Noise node.
I'm not experienced enough with the hash functions to know if
the int/uint conversion is a real issue or not.
Originally suggested in comments for D15375
Based on archived patch: https://archive.blender.org/developer/D15835
Mentioned here: #103457
We haven't discussed that in a meeting yet, but currently I think this is a useful low level building block.
@ -0,0 +88,4 @@
static auto exec_preset = mf::build::exec_presets::AllSpanOrSingle();
static auto fn_hash_float = mf::build::SI1_SO<float, int>(
"Hash Float", [](float a) { return get_default_hash(a); }, exec_preset);
This hash is not designed to generated very random results in these cases, it shouldn't be exposed in the node.
Just expose the
noise::hash
functions like you did below. Those are used indirectly by noise code already anyway.I'll wait for meeting discussion but I guess the suggestion is to remove all the
get_default_hash
methods and just use the BLI_noise functions? This also simplifies node without the need for users to choose the method. This was originally added to explore what was useful or not.Yeah, that's what I meant.
I agree with Jacques, the node seems very useful, I often think about it when I work with groups.
NodeHashMode
by simply socket types.node_update
and compare types.static auto fn_hash_vector
inbke::attribute_math::convert_to_static_type
(usesocket_type_to_custom_data_type
) (wrap in constexpr if statement to not generate code for unsupported types (See accumulate or blur attribute nodes as example)).node_gather_link_searches
(nodeStaticSocketLabel
,std::string = "HashFor" + nodes::...(type)
can be captured by lambda[name = std::move(name)]
). And make sure, if connected sockets types is converteble (bke function).custom1
.This node seems generic enough to be found in utilities like Random Value node.
btw how does this work? what does a string turn into? and can you convert a hash into a string? that would be pretty cool.
and what would a float look like after it's converted back and forth?
Hash, this is the thing that may not be stabile very much from many things. You don't even have to think about converting data to and from hash.
@mod_moder you are saying it isn't stable and you can't convert things back and forth. in that case, why and how to you have these conversion to a hash and from a hash. I'm unsure on the behavior.
@shmuel You can get a random number for any data. It must be identical for the same data. But even just
x = 10 * 4
/x = 10 + 10 + 10 + 10
for float will actually give us different real numbers and its hashs.@ -0,0 +128,4 @@
}
if (params.in_out() == SOCK_IN) {
if (type == CD_PROP_FLOAT) {
params.add_item(IFACE_("Value"), SocketSearchOp{"Value", type});
To clarify a little: we must add all options if their type can be converted to
type
. So, for string is {sring}, for color, is {all, except of string and rotation}, ... . That's the point of the loop and the function to check if the socket types are convertible.For inputs I'm not sure this is needed. I'd expect to hash by type so only having the one option reduces clutter. So plugging in a Float will use the Float To Hash function etc.
I have added Boolean socket and mapped that to Int.
Node to convert Float to Int doesn't make sense if you create this via drag-and-drop from int output socket of other one node so it is connected to float input, but this still exist in the list to search/
Maybe you can add a screen shot because I'm not sure I understand.
This search result makes no sense. But it still exists:
Your node should also show all options, and not just those that are equal to current socket type.
Sorry, I still don't understand. Drag link only limits by type not node. Hash output is Integer. User might want to plug that into a math node.
I mean,
node_gather_link_searches
have to create search items all input socket for all the types supported by the node, and the output one kind at the single call (noy only one input and one output for supported type). Only one limitation of what socket can not be converted to other type by implicit value conversion.It might be easier for you to provide code if you need me to change something here.
Or are you talking about weight as is done for math node?
I'm still not understanding what this is doing different other than using an array and excluding Rotation socks.
Ok, I get what you are saying but we're not consistent here. E.g. Map Range doesn't list all available sockets. Listing all sockets also adds noise that the user needs to go through. In most cases, users will be hashing the data type associated with the socket so current behaviour seems favourable to me.
That was my mistake.
The code generally looks good. I think the main thing that's missing in the description is the motivation and examples for how someone should use this. Like, why should this be used instead of White Noise for example?
This was originally motivated as a response to the comments in D15375. 😝
https://archive.blender.org/developer/D15375
White Noise only handles float data so this compliments that to allow users to hash data for indexes etc
@mod_moder Has also mentioned it here Attribute Map node #103457
Hash is a good thing to have during groups building from non-integer noises.
Multidimensional hash can be used in recreating all noise textures as node groups (as the base noise node).
To me it's not immediately obvious, why there are 3 inputs for the Integer type. I can see needing 2, but that should be enough to hash any amount of integers together by folding.
Also this seems a bit strange in comparison with the other types. I'd propose the following:
Add a
Seed
integer field input, same as the random value node has, for all types. That way it makes the inputs and behavior between types more consistent and intuitive imo. Any type will have one input for the value of that type and a second input for the seed. That happens to be 2 integers for the integer type.The main input to be hashed should be called
Value
regardless of the type for consistency with other nodes, e.g. store named attribute.I'm not sure about the name of the node and the output. I think it's fine to introduce the term hash, as it's descriptive, but we don't have that anywhere in the UI yet afaik. It might be worth considering the term
ID
instead in something likeID from Value
,Random ID
, ... to avoid introducing new terms.@dfelinto , what do you think?
Design-wise, combining hash-to-float in a node that otherwise just creates integers is a bit confusing. Maybe that should be a separate node? It also seems a bit arbitrary for the integer mode to have three inputs where the float mode only has one. I guess in an ideal world the number of inputs would be dynamic. Other than that, I do think this node makes sense!
Where is that happening? Did I miss something? Afaict the node is always just creating integer hashes.
I just saw it in the screenshot in the description.
hash-to-float
was removed, some changes were discussed in Blender chat a while ago but the node didn't have any tlc for a bit!The hash functions take 1, 2, 3 or 4 inputs. Exposing 3 seemed a good compromise here for hashing integer based positions.
This complicates the code somewhat, I'm not clear why you would need a seed here? This could also be achieved by adding an offset to the input value.
We're not consistent here, see Map Range which has
Value
andVector
inputs depending on type.I'm not opinionated on this.
Let's just use the word "Value," it's simpler and using other words is redundant with the socket type itself.
Since there's a performance cost for hashing more values, I'd probably go with 2 for now until the amount of inputs could be dynamic. But it's not a big deal either way.
To me it's a matter of the consistency of the design and usability. You could argue for the integer input type just as well, that you could just have a single input and offset it, if you need a different hash. I think it's reasonable to avoid such workarounds to allow multiple inputs hashed together. And rather than having those different for every type I think it's more intuitive, more consistent with other existing nodes and nicer design to introduce that second input as a seed integer value. how much does it complicate the code? To me it is still worth it, if it's not by that much. I'm quite confident that this is a nice solution on the user level.
Maybe someone more technical can evaluate this better on the code level @HooglyBoogly ?
Concentrating the comments, the node declaration should be?:
@HooglyBoogly @JacquesLucke how do you want me to implement the seed here? The current node is simply wrapping the
noise::hash
functions at present.E.g.
For Float3, I can call
hash_float(float4(a.x, a.y, a.z, float(seed)))
orhash_float(float3(a.x, a.y, a.z) + float(seed))
For Rotation, I could call
hash_float(float4(a.x, a.y, a.z, a.w) + float(seed))
For String, do we introduce a new function?
@CharlieJolly
blender::get_default_hash_2<T, int>
(frombli
)From previous review from Jacques it was decided to expose
noise::hash
functions and notdefault_hash
.With Seed socket and one input for each hashable type
That looks great to me now, thank you!
I still haven't actually tested functionality but as that is pretty straightforward, I'll trust the code review on that.
I'm still not 100% sure about exposing the 'new' term
Hash
in the UI, as we don't use that anywhere else. I just briefly talked to Andy as well and now I do think that since.The term hash can totally be in the docs and output socket description imo. But since no other socket has that name, it seems like we're introducing a new concept, that doesn't really add that much being called its own term. So I would propose reusing the
ID
term here.The only issue is that while hash works nicely as a Verb, ID does not. Personally I'd lean most towards
ID from Value
, but maybe there's a better name.Since I might also be misinterpreting the similarity of the terms I'd still like this to be signed off by the dev team.
I'll put it on the agenda of the next meeting.
@SimonThommes I'm not opinionated on the Hash name so I'll leave this for the meeting. One thing to consider is if we add a
Hash to Float
node at some point that the naming fits in with this.We generally use
X to Y
instead ofY from X
when naming nodes.While I generally like "ID" here, it has one major problem for me. "ID" indicates uniqueness which a hashing function can't guarantee and there will inevitably be collisions where different input values map to the same output. A "hash" is less expected to be unique.
I don't have a strong opinion on the name. I guess we should talk about it at a module meeting to make a final decision. Either way merge conflicts would need to be resolved before this is merged though.
Happy to confirm that this PR doesn't have the same floating point precision issue as the random value node (#118207) 👍
Sorry, I've not been active on Blender for a while. Thanks for picking this up.
Hello ! Just wanted to say that these set of nodes could be useful indeed. I had a situation where I had to generate some indices for some elements (curves, points) and for now the only way was to use a random value node, which is fine but the hash function seems more straightforward to use and maybe will avoid some repetitions that I might ran into with the random node...
About the name, I found that Hash is better as it's basically what it is. If that was called ID I probably wouldn't have figured out what it is unless I looked into the manual.
@blender-bot build
@blender-bot build
@blender-bot build
To me this is good to go tbh 👍
Still wait for another checkmark by either Jacques or Hans for merging.
The only thing that could still be done imo is update supporting the matrix socket, but since it can also be separated into components and hashed that way this is not really a dealbreaker imo.
There isn't currently a matrix hash function but could implement this as follows.
@ -1838,6 +1838,17 @@ static const EnumPropertyItem *rna_FunctionNodeRandomValue_type_itemf(bContext *
return itemf_function_check(rna_enum_attribute_type_items, random_value_type_supported);
}
static bool hash_value_type_supported(const EnumPropertyItem *item)
Unused.
@ -0,0 +1,186 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
Outdate license (
23
->24
).@ -0,0 +2,4 @@
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include <cmath>
Unused include.
@ -0,0 +44,4 @@
node->custom1 = SOCK_INT;
}
static const mf::MultiFunction *get_multi_function(const bNode &bnode)
Swap
get_multi_function
andnode_gather_link_searches
things, just to less mix them/@ -0,0 +107,4 @@
};
static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms)
{
To handle
Seed
input andHash
output automatically:Left this for the moment as it did not work as expected with Boolean and String.
@ -0,0 +146,4 @@
{
RNA_def_node_enum(
srna,
"input_type",
Coud be
data_type
as in all other nodes?@blender-bot build
@blender-bot package
Package build started. Download here when ready.
In convention with random value node, do we really need quaternion and matrix built-in support?\
@mod_moder
I don't think this comparison holds up here. The main issue imo with the random value node is that uniform distribution of these types is ill-defined and we'd need a more specialized node-group for that. I don't see that same issue with hashing
@ -28,6 +29,7 @@ uint32_t hash_float(float kx);
uint32_t hash_float(float2 k);
uint32_t hash_float(float3 k);
uint32_t hash_float(float4 k);
uint32_t hash_float(float4x4 k);
float4x4
is quite large and should be passed by const reference rather than by value. It has made a performance difference to do that in the past.@blender-bot build