# How to Programatically Render Multiple Times with Different Materials each

I have an animation about 170 frames long (not important). In the animation I have Balls with a certain Material on them (UV map).

I'd like to have this Animation rendered 100 different times - each time with a different UV Map on the Balls.

Additionally, I'd like each of the 170 set of PNGs to have a different name, corresponding to the UV Map being rendered.

Like: Ball01_001.png ... Ball01_170.png Ball27_001.png ... Ball27_170.png . . . Ball99_001.png ... Ball99_170.png

Is this possible with some code?

• If the UVmap is the same, but the image must change each time, you don't even need code in Blender: you just need to a) render from command line with textureX to image1, b) change what textureX is (renaming/copying texture1 to textureX, then texture2 to textureX and so on), and then render to image2, etc... you could do this with any scripting language, imho... Feb 2 '17 at 8:41
• That sounds about right. Looking into it here: blenderist.com/b/?p=131 Feb 8 '17 at 17:05
• Basically, what I'm thinking of doing is writing a python script that gets all the Texture files, enumerates them, then for each, runs the render - first replacing the texture of the balls, of course. Just need to find what property changes the outputed names. Feb 8 '17 at 17:06
• looking at the command log into "info" window, when saving a rendered image it logs something like: bpy.ops.image.save_as(save_as_render=True, copy=True, filepath="/home/marco/Desktop/untitled.png", relative_path=True, show_multiview=False, use_multiview=False) so I guess you could use this same command to edit your save path/filename Feb 8 '17 at 19:15

Okay, so with m.ardito's help in the above comments, this post on Blenderist and some related questions on Stack, I came up with the following Python script, running it with

blender -b filename.blend -P setting.py


Here's the script:

import os
import shutil
import bpy

uvMaps = os.listdir('C:\\GameDev\\UVs')

for i in range(len(uvMaps)):
if uvMaps[i].endswith('.png'):
shutil.copy('C:\\GameDev\\UVs\\' + uvMaps[i], 'C:\\GameDev\\UVs\\Actual\\BallActual.png')

Scenename = 'Scene'

#quality
bpy.data.scenes[Scenename].render.resolution_x = 900
bpy.data.scenes[Scenename].render.resolution_y = 900
bpy.data.scenes[Scenename].render.resolution_percentage = 100
bpy.data.scenes[Scenename].cycles.samples = 200

bpy.data.scenes[Scenename].frame_start = 0
bpy.data.scenes[Scenename].frame_end = 44
bpy.data.scenes[Scenename].render.filepath = 'C:\\GameDev\\Balls Sprites\\Ball_' + uvMaps[i][:-4] + '_Pos1_###.png'
bpy.data.scenes[Scenename].render.use_placeholder = True
bpy.ops.render.render(animation=True,scene=Scenename)
bpy.data.objects["Ball1"].hide_render = True

bpy.data.scenes[Scenename].frame_start = 45
bpy.data.scenes[Scenename].frame_end = 77
bpy.data.scenes[Scenename].render.filepath = 'C:\\GameDev\\Balls Sprites\\Ball_' + uvMaps[i][:-4] + '_Pos2_###.png'
bpy.data.scenes[Scenename].render.use_placeholder = True
bpy.ops.render.render(animation=True,scene=Scenename)
bpy.data.objects["Ball2"].hide_render = True

bpy.data.scenes[Scenename].frame_start = 78
bpy.data.scenes[Scenename].frame_end = 108
bpy.data.scenes[Scenename].render.filepath = 'C:\\GameDev\\Balls Sprites\\Ball_' + uvMaps[i][:-4] + '_Pos3_###.png'
bpy.data.scenes[Scenename].render.use_placeholder = True
bpy.ops.render.render(animation=True,scene=Scenename)
bpy.data.objects["Ball3"].hide_render = True

bpy.data.scenes[Scenename].frame_start = 109
bpy.data.scenes[Scenename].frame_end = 135
bpy.data.scenes[Scenename].render.filepath = 'C:\\GameDev\\Balls Sprites\\Ball_' + uvMaps[i][:-4] + '_Pos4_###.png'
bpy.data.scenes[Scenename].render.use_placeholder = True
bpy.ops.render.render(animation=True,scene=Scenename)
bpy.data.objects["Ball4"].hide_render = True

bpy.data.scenes[Scenename].frame_start = 136
bpy.data.scenes[Scenename].frame_end = 160
bpy.data.scenes[Scenename].render.filepath = 'C:\\GameDev\\Balls Sprites\\Ball_' + uvMaps[i][:-4] + '_Pos5_###.png'
bpy.data.scenes[Scenename].render.use_placeholder = True
bpy.ops.render.render(animation=True,scene=Scenename)
bpy.data.objects["Ball5"].hide_render = True

bpy.data.scenes[Scenename].frame_start = 161
bpy.data.scenes[Scenename].frame_end = 181
bpy.data.scenes[Scenename].render.filepath = 'C:\\GameDev\\Balls Sprites\\Ball_' + uvMaps[i][:-4] + '_Pos6_###.png'
bpy.data.scenes[Scenename].render.use_placeholder = True
bpy.ops.render.render(animation=True,scene=Scenename)

bpy.data.objects["Ball1"].hide_render = False
bpy.data.objects["Ball2"].hide_render = False
bpy.data.objects["Ball3"].hide_render = False
bpy.data.objects["Ball4"].hide_render = False
bpy.data.objects["Ball5"].hide_render = False


The idea here is that each Ball is coming out from behind a Masked object and travels a number of Frames until it reaches an end, spins down and stops (end_frame). The animation is one long animation from 0 to 183. Each ball begins the travel after the previous one has completely stopped.

By hiding the previous Ball each time, I'm allowing to completely disregard the previous animation - using each Pos (in the file name - from 1 to 6) to be used as a different layer in the Spritehseet I'm creating from these animations.

Since all 99 animation sets are the same, I've created 594 different animation combinations. To be used as sprite animations in a 2D game.

Update:

After running this for three whole days, and barely passing half of the 99 ball renderings, I've added this:

bpy.data.scenes[Scenename].cycles.device = 'GPU'


See a tripling of speed, on average.

• After running this for three whole days, and barely passing half of the 99 ball renderings, I've added this: bpy.data.scenes[Scenename].cycles.device = 'GPU' Feb 13 '17 at 6:46