12

I got an image sequence for the poker faces (totally 54 images). And I want to find an effective way to place them on 54 objects. According to my knowledge, I just tried to use tricks like the Oject Info node, with concept like this:

enter image description here

It would also be great to be able to animate multiple frames per object - for example, something similar to this, with each cube showingn a short video clip :

video wall

Rich Sedman
  • 44,721
  • 2
  • 105
  • 222
Leon Cheung
  • 27,718
  • 11
  • 89
  • 161
  • Theres 52 cards in a deck – Dontwalk Mar 19 '18 at 04:10
  • 2
    @Dontwalk 54 if you include the jokers. –  Mar 19 '18 at 04:38
  • 4
    Oh come on guys, that's not the point, right? lol – Leon Cheung Mar 19 '18 at 04:41
  • Does using an object info/random into color ramp with constant interpolation as mix factor between two or more of these sequences do the trick by chance? I do something similar for random materials, not at my computer to show an example at the moment however. – Timaroberts Mar 19 '18 at 06:19
  • @Timaroberts thanks but the problem is that it's not a "two or more" thing, it's a sequence of the whiole poker cards.... Yeah I'm sure I can put 54 Image Texture nodes there for mixing, but... you know. – Leon Cheung Mar 19 '18 at 06:35
  • I thin I do not get the questin. It sounds like the usual: have one big picutre for UV mapping. Map each object with suitable coordinates to only a part of the picture. What keeps you from doing it like that? – Yunnosch Mar 19 '18 at 06:40
  • 1
    Can that be a single image instead of a sequence? – lemon Mar 19 '18 at 07:38
  • 1
    Actually what I'm trying to learn here can have other usages, like this, or this, which can be simply textured by using a single clip with random offsets. And obviously, a giant UV texture won't work easily. – Leon Cheung Mar 19 '18 at 08:22
  • An idea could be to use a driver. But as it is to be set in the image_user/offset (in the outliner), for now I don't know how to bind a card object property to the driven value... but if the idea can help you... – lemon Mar 19 '18 at 10:10
  • It is possible with tile mapping. It is similar to what i did here: https://curiousblends.blogspot.bg/2018/02/all-in-one-blender-matcaps-material.html But too long to explain here. – Rumen Belev Mar 19 '18 at 10:44
  • @lemon you can add a driver to the frame offset value of an image/movie node. Then set duration to 1. Assuming you have individual card images as a sequence then the Object Index node should be enough – 3pointedit Mar 20 '18 at 21:50
  • @RumenBelev Interesting, that should be a good way when I have to use a huge altas texture for them. Will learn from it, thx. – Leon Cheung Mar 21 '18 at 01:10
  • 1
    @3pointedit, it seems it does not work when the driver is directly added to the node in the node editor (no update occurs), but it works adding the driver from the outliner. But from that, I was no able to get the corresponding pass index because I don't know how to reach an "upper element" through the data from the "offset" field put in the driver. – lemon Mar 21 '18 at 07:06
  • @lemon Yeah I only have success driving from the 3D scene, e.g. from object locations etc. – 3pointedit Mar 21 '18 at 13:03
  • Solution 1. I think it is a good idea for UDIM tiles map. https://blender.stackexchange.com/questions/264619/one-frame-of-image-sequence-per-geo-node-instance Solution 2. You can tile the video clips into one video clip firstly, and then use uv-offset to select different part. – jane Lia Feb 23 '23 at 06:54

1 Answers1

16

Here's a solution using OSL to read from multiple images based on the Object Index.

Enable OSL and paste the following into a new Text Editor datablock named something like dynamic_texture.osl :

shader dynamic_texture(
    vector Vector = P,
    string FileName = "",
    float Index = 0,
    string Suffix = ".png",
    output color Color = color(1,1,0)
    ) {
    int _index = (int)Index;

    Color = texture(format("%s%i%s",FileName,_index,Suffix), Vector[0], Vector[1]);

}

In the Node Editor you can now add a Script node and point it at the new Text block. This should create you a new node with inputs for Filename, Suffix, and Index. This can be used to feed the Object Info Object Index to dynamically select the required texture from a set of images :

dynamic texture

Note that the filename is absolute in your filesystem - so you need to specify the full path - or prefix with //to specify a relative path in relation to your saved .blend file (eg, //rendered/ for a local subdirectory named ‘rendered’). In my example I placed the files in c:\users\rsedman\Pictures and named them 1.png, 2.png, 3.png, etc. The Suffix indicates the filename suffix - in this case .png.


EDIT : In order to allow for multiple 'frames' per image set you could amend the OSL shader code to the following :

shader dynamic_texture(
    vector Vector = P,
    string FileName = "",
    float Index = 0,
    float Subframe = 0,
    string Suffix = ".png",
    output color Color = color(1,1,0)
    ) {
    int _index = (int)Index;
    int _subframe = (int)Subframe;

    Color = texture(format("%s%i_%04i%s",FileName,_index,_subframe,Suffix), Vector[0], Vector[1]);
}

This will add an additional 'Subframe' input to the socket and the filename will now be built using the subframe as an additional suffix (with up to 4 leading zeros).

with subframe

For example, setting the Filename parameter to '/tmp/images/', the Index to 3, the Subframe to 26, and the Suffix to '.png' will pick up the image from /tmp/images/3_0026.png. In this way you can use the node to pick out a particular frame of your particular set of images. To drive this from an MP4 video you would need to split out the individual frames and name each file appropriately.

This can produce the following result :

animated

NOTE : I don't know exactly how OSL manages memory and file access when accessing multiple images in this way - there may be a noticeable practical limit of how many images can be accessed by an OSL shader. If nothing more, it will certainly require a significant amount of additional memory to cache a large number of images.

Rich Sedman
  • 44,721
  • 2
  • 105
  • 222
  • Brilliant idea, Rich! It works like magic. Just... As I commented above, I really wonder how could I use the sequence as "video clip" texture for things like a wall with tens of TVs? You know, it needs to be animated. Besides, can I use something llike a mp4 file directly as sequence in this way? – Leon Cheung Mar 20 '18 at 12:16
  • @LeonCheung The OSL ‘texture’ function does accept an optional subimage argument - that may be able to select the sub-frame of an mp4 but would presumably work with other formats if not - so if you could convert your videos into a suitable format you could tailor this to pick a specific image based on an additional input to the OSL shader node. The alternative might be to split your videos into individual frames, each stored in a uniquely named file, and pick them out based on, say objID *1000+subframe or suchlike. – Rich Sedman Mar 20 '18 at 14:41
  • I see. And one last question, how can I add frame as var to index, so that I can animate the texture? Should it be like int _index = (int)Index + frame_current? I don't know if osl support it. – Leon Cheung Mar 20 '18 at 14:52
  • Currently I'm inspired by things like this, but supposing you got better idea on animating it. :) – Leon Cheung Mar 20 '18 at 15:24
  • I've updated my answer with a change that should allow you to access multiple frames per ID - these must be split into actual separate files and given appropriate names (eg, 1_0001.png, 1_0002.png, 1_0003.png, etc., 2_0001.png, 2_0002.png, 2_0003.png, etc.). – Rich Sedman Mar 21 '18 at 00:09