I have a feeling Nathan is right that this is irrelevant to the performance, however it could very much be the opposite: I remember when I had a project with a UV sphere displaying a different video on each face. When rendering a test animation, most of the time of the renders was taken by loading the video files on each frame. However, would a single higher resolution movie work better in this case, probably not... However, there might be various optimizations in Blender that make one work better than the other, so...
Let's test it
I created a plane, and added a texture node, with color grid texture in 16K resolution. Subdivided the plane with 7 cuts, twice, so that each face is associated with 4 titled squares. Separated all those faces as individual objects, made some random transformations and a 60 frame animation:
Using Eevee, samples: 1, 500x500 resolution, Image Texture directly connected to shader output, to make it as light as possible to only measure the actual performance of loading the big image or small images.
After making first test with this setup, I reset all UVs, added mapping to the material:
Then I used a script to separate the materials and use the mapping to position each plane on a different coordinate without using UV:
import bpy
coords = ((x/64, y/64) for x in range(64) for y in range(64))
for o, co in zip(bpy.data.objects, coords):
if not o.name.startswith("Plane"):
continue
mat = o.material_slots[0].material.copy()
loc = mat.node_tree.nodes['Mapping'].inputs['Location'].default_value
loc.xy = co
o.material_slots[0].material = mat
Rendered the animation again and it took twice as long now, evidently the 8 seconds needed at first, now was needed just to prepare for the first frame - but once that rendered, the rest went smoothly, because apparently Blender cached that data.
Now in order to divide the image to many images, I used this node setup:
Rendered 64*64=4096 frames from 0 to 4095. The folder with those images weighs 341 MiB while the single file weighs only 41.8 MiB. This alone might be significant.
Reverting the test file back to the situation with a single material, removing the Mapping node, and applying this script:
import bpy
for o, i in zip(bpy.data.objects, range(64*64)):
if not o.name.startswith("Plane"):
continue
mat = o.material_slots[0].material.copy()
image_node = mat.node_tree.nodes['Image Texture']
image_node.image = bpy.data.images.load(f"C:/imgs/{i:04d}.png")
o.material_slots[0].material = mat
I experienced more UI lags then on previous test. But rendering took a second or two less, but I used a faster SSD, so with all this slopiness, I decided to be a little more rigorous and repeated those tests 3 times per each technique, each on the faster SSD with a measurement error of +/- 0.5 s, starting a stopwatch at the same time as pressing CtrlF12 and stopping it as soon as I see Frame: 60 in the render window:
try # |
1 material 1 image |
4096 materials 1 image |
4096 materials 4096 images |
1 |
8.19s |
13.91s |
15.29s |
2 |
8.15s |
13.98s |
16.75s |
3 |
8.15s |
14.56s |
15.50s |
So out of the 2 last options the OP considers, the 2nd option (single image file) seems better. UI is more responsive in my experience, it renders faster, it's easier to work with. However, what comes to mind is that perhaps if some of your scenes don't use entire texture, dividing the texture may make it easier to render or to work with your file because thanks to that Blender will load only those parts that are needed.
It's very important though that you consider what Jachym Michal said: not only using a single material was much faster than using many materials, it also allows you to put some kind of offsets (e.g. random offsets), and then, since your texture is not a tiled grid like the testing texture here, this could allow you for more variance, by having overlapping mappings but still different enough to not be perceived as the same rock.