Geometry nodes one frame of animation per grid instance?

Hi there,

I have a curve, taken into GeoNodes, resampled, and then a grid instanced on each point. I want to be able to specify which frame of an animation sequence goes on which instance & cannot work out how to do it.

This image is a simplified version of what I’m after (done manually, but I need it for hundreds of frames)

I have managed to export the point index of the curve as a group output and bring that over into the shader node tree. And I can control which image of the frames appears on all of the grids via a driver, but this affects all of the grids.

What I can’t work out is how to get the index attribute into the driver. It doesn’t work if you copy the data path of the attribute into the driver, unless I’m doing something wrong.

This is the data path for the attribute: node_tree.nodes[“Attribute.001”].attribute_name

and I’ve tried things like:

node_tree.nodes[“Attribute.001”].outputs[2].default_value

but no joy

I’d like to be able to animate this property eg change which frame appears by, say, adding the index to a frame number.

Or is there a completely different & better way of doing this?

Thanks for your help!

This is an offer and it would be better for him to write to right click selection
But I’ll answer here: no.
To do this: when rendering, it is necessary that all the frames be in video memory at the same time
For geometry nodes: what would someone implement in the form of a node. So far this is not
Suggestion: turn your video into an image atlas and uv address them

You could write a script that would do this, if you have an array of images and an array of planes, you can just loop through and assign the image to the material :slight_smile:

Yes I was thinking an atlas too. The image texture node doesn’t have inputs for the frame number so I think that’s OP’s best bet.

1 Like

Would this still work with creating the planes through Geo Nodes? I need the flexibility of being able to place the planes along a path, and then manipulate the path. Thanks.

I need hundreds of images so an atlas might get a bit unwieldy?

It’s something that feels like it should be so simple!

I honestly have no idea, but you don’t have to use Geometry Nodes to place the planes along a path and manipulate it… you could use a script :wink:

At some point, in some way, you’re going to have to store all of those images in a way that assigns each one an individual index. That could range from a simple array, to a dictionary, to a more complicated 2D texture atlas, or a 2d nested array, or even a n-degree nested array (if you have a thousand images, you could use a 3D array, 10 X, 10 Y, and 10 Z… your coordinates would be a bit complicated, though). At the end of the day, your easiest option would be a 1D array, but you’re going to have to script to use that… if you don’t want to script, a 2D image atlas will be the simplest option

Looks like I’m going to have to improve my scripting!!

I managed to work out what the correct python expression is to get the correct index of the plane in the shader:

bpy.context.object.evaluated_get(bpy.context.evaluated_depsgraph_get()).data.attributes[‘Idx’].data[0].value

and was hoping I could just feed that into the driver I already have attached to the ‘offset’ field of the image texture node. Oh well.

With your script idea, do I have to set up hundreds of different shaders, or can the image be controlled directly in the script?

thanks for your help.

You should be able to control the image pretty easily from the script without having to worry too much about shader nodes. Something like this should work:

import bpy
from bpy import context, data, ops


mat = bpy.data.materials.new(name="New_Mat")
mat.use_nodes = True
bsdf = mat.node_tree.nodes["Principled BSDF"]
texImage = mat.node_tree.nodes.new('ShaderNodeTexImage')
texImage.image = bpy.data.images.load("C:\\Users\\myName\\Downloads\\Textures\\Downloaded\\flooring5.jpg")
mat.node_tree.links.new(bsdf.inputs['Base Color'], texImage.outputs['Color'])

ob = context.view_layer.objects.active

# Assign it to object
if ob.data.materials:
    ob.data.materials[0] = mat
else:
    ob.data.materials.append(mat)

Not my code, it’s from https://blender.stackexchange.com/questions/157531/blender-2-8-python-add-texture-image

You’d just want to loop through objects and change the “texImage.image” for each

1 Like

amazing, thanks! I’ll get stuck in and give it a go and let you know how I get on.