12
$\begingroup$

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

$\endgroup$
  • 2
    $\begingroup$ @Dontwalk 54 if you include the jokers. $\endgroup$ – cegaton Mar 19 '18 at 4:38
  • 4
    $\begingroup$ Oh come on guys, that's not the point, right? lol $\endgroup$ – Leon Cheung Mar 19 '18 at 4:41
  • 1
    $\begingroup$ Can that be a single image instead of a sequence? $\endgroup$ – lemon Mar 19 '18 at 7:38
  • 1
    $\begingroup$ 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. $\endgroup$ – Leon Cheung Mar 19 '18 at 8:22
  • 1
    $\begingroup$ @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. $\endgroup$ – lemon Mar 21 '18 at 7:06
14
$\begingroup$

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.

$\endgroup$
  • $\begingroup$ 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? $\endgroup$ – Leon Cheung Mar 20 '18 at 12:16
  • $\begingroup$ @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. $\endgroup$ – Rich Sedman Mar 20 '18 at 14:41
  • $\begingroup$ 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. $\endgroup$ – Leon Cheung Mar 20 '18 at 14:52
  • $\begingroup$ Currently I'm inspired by things like this, but supposing you got better idea on animating it. :) $\endgroup$ – Leon Cheung Mar 20 '18 at 15:24
  • $\begingroup$ 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.). $\endgroup$ – Rich Sedman Mar 21 '18 at 0:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.