Specifically, is there any way to change the color of the instanced cubes based on their scale attribute?
2 Answers
No. You can't.
You can, however, use common input for your shading nodes and geometry nodes: the empty's position:
Of course as you can see it creates gradients:
So you want to change each coordinate of an inner cube to one single coordinate of that cube - most logically to the center (which is also the vertex that spawned the inner cube).
First an approach that didn't work, to perhaps save someone some time investigating the same thing...
I found that Texture Coordinate > Object for unspecified (default) Object target will give the coordinate in the spawned cube's coordinate system - so you get the information on how far you're from the center of the inner cube:
But the above is a dead end, because you want to know how far you're from the center in the BIG coordinate space, so you end up where you started - you need the inner cube's dimensions relatively to the big cube's dimensions, to know how to scale their coordinate systems so they're compatible with each-other.
--
Now for a solution, that actually works in your case: you can (easily) mathematically describe the geometry, so you can figure out for each pixel's coordinate where's the center of the inner cube this pixel is on. Start by using Object coordinate of the Instancer:
X, Y, Z components are in range of -1.11444..1.11444
instead of usual -1..1
- that's because the coordinate system is defined by the vertices of the object before its geometry is changed - so -1
is the leftmost/lowest/furthest center of an inner cube, and not the boundary of resulting shape:
If there's no empty space between inner cubes, a line between 1st and 9th centers is equal to the length of 7 and 2 halves on either side = 8 inner cubes in middle:
1 / 8 * 9 = 1.125
. That would be the number instead of 1.11444
if inner cubes would be as big as possible without overlapping. Armed in this information, let's snap the values to 2/8
as our current range is 2 integers (-1..1
), and 8 inner cubes fit into it:
There's an obvious offset in colors, because the snapping starts at half of a cube, so let's translate by half of a cube: 1/8/2*2
(1 of 8 cubes, divided by 2 for a half, multiplied by the range which is two from -1 to +1) = 0.125
of the entire range:
Now subtracting pixel's position in the empty's coordinate system from its position in the instancer's coordinate system should give the position of the empty in the instancer's coordinate system; then displaying a color based on the distance from it should yield the desired result:
But the gradient returned, something is wrong. Viewing the result of subtraction mentioned in the last paragraph, we can see the problem:
There should be just one color, because regardless of the pixel position, the calculated empty position should be the same (we calculate position relative to the coordinate system, not relative to the pixel). The problem comes from two places:
- the instancer is rotating - counter the rotation using drivers pointing to the instancer's rotation (you can right click, Copy as New Driver, then in node right click, and Paste Driver)
- the empty is scaled - multiply the vector by the empty's scale, you can use drivers here too.
All that's left is to duplicate the nodes (3 first and 2 last can be common) for the other empty and combine the distances somehow (average, sum etc.).
-
1$\begingroup$ You are a wizard...I can't wait to play around with this. Thanks for answering and teaching me! $\endgroup$ Commented Mar 30, 2021 at 3:24
If you use Cycles, you can add Verts as children of your Empties, and use the "Attribute Proximity" node to calculate the distance from that vertex (doesn't work with pure empties from what I can tell). These nodes need to be placed after the "Point Instance" node in order to be able to access the new attribute (dist1
and dist2
in this case). Unfortunately it's per point in the final mesh, not per cube (not exactly sure what you need/want), but there might be some rounding tricks you could pipe in to get that effect - it'd be based on the number of cubes (width/height) you have in your object, I believe.
You can then use those attributes to influence the color ramp you had setup in your material - this material needs to be assign to your Instancer
object. You may want to play with the Math node to get a nice gradient. I'm not sure the setup I have here is ideal, and looks be causing some artifacts.
Here's what I got after playing with the values a little - .blend file is also attached: