|
1 # vim: set nosta noet ts=4 sw=4: |
|
2 # |
|
3 # Split a single frame into 100 separate pieces, for blender network |
|
4 # rendering. |
|
5 # |
|
6 # Assumptions: |
|
7 # - Shared storage between all render nodes. |
|
8 # - A method for simultaneous blender execution on all nodes (even |
|
9 # just ssh) |
|
10 # - Re-constituting the image performed out of band (most easily with |
|
11 # ImageMagick toolset) |
|
12 # |
|
13 # Copy this script into the same directory as your blend file, then run |
|
14 # like so across your render farm: |
|
15 # |
|
16 # blender file.blend -b -P chunked_render.py |
|
17 # |
|
18 # When all nodes are finished rendering their chunks, you'll have 100 |
|
19 # separate images. Combine them back into a single image like so, if |
|
20 # you have ImageMagick installed: |
|
21 # |
|
22 # montage -background none -mode concatenate -tile 10x10 chunk_* rendered.jpg |
|
23 # |
|
24 # Authors: |
|
25 # |
|
26 # Mahlon E. Smith <mahlon@martini.nu> and |
|
27 # Justin Smith <justin@statisticool.com> |
|
28 # |
|
29 # License: |
|
30 # |
|
31 # Copyright (c) 2016, Mahlon E. Smith <mahlon@martini.nu> |
|
32 # All rights reserved. |
|
33 # Redistribution and use in source and binary forms, with or without |
|
34 # modification, are permitted provided that the following conditions are met: |
|
35 # |
|
36 # * Redistributions of source code must retain the above copyright |
|
37 # notice, this list of conditions and the following disclaimer. |
|
38 # |
|
39 # * Redistributions in binary form must reproduce the above copyright |
|
40 # notice, this list of conditions and the following disclaimer in the |
|
41 # documentation and/or other materials provided with the distribution. |
|
42 # |
|
43 # * Neither the name of Mahlon E. Smith nor the names of his |
|
44 # contributors may be used to endorse or promote products derived |
|
45 # from this software without specific prior written permission. |
|
46 # |
|
47 # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY |
|
48 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
49 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
|
50 # DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY |
|
51 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
|
52 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
|
53 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
|
54 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
55 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
|
56 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
57 |
|
58 |
|
59 import bpy |
|
60 import os |
|
61 import math |
|
62 |
|
63 tiles = 100 |
|
64 t_sqr = math.sqrt( tiles ) |
|
65 |
|
66 bpy.ops.wm.addon_enable( module='render_auto_tile_size' ) |
|
67 |
|
68 s = bpy.context.scene |
|
69 r = s.render |
|
70 |
|
71 s.ats_settings.is_enabled = True |
|
72 s.ats_settings.use_optimal = True |
|
73 |
|
74 r.use_border = True |
|
75 r.use_crop_to_border = True |
|
76 r.threads_mode = 'AUTO' |
|
77 |
|
78 count = 0 |
|
79 for row in range( 1, 11 ): |
|
80 for column in range( 1, 11 ): |
|
81 count = count + 1 |
|
82 filepath = "chunk_%04d" % count |
|
83 placeholder = "." + filepath |
|
84 r.filepath = "//%s" % filepath |
|
85 |
|
86 if not os.path.isfile( placeholder ): |
|
87 print( "Working on chunk %d (row %d, column %d)" % (count, row, column) ) |
|
88 placeholder = open( placeholder, 'w') |
|
89 placeholder.close |
|
90 |
|
91 r.border_min_x = ( column - 1 ) / t_sqr |
|
92 r.border_max_x = column / t_sqr |
|
93 r.border_min_y = ( t_sqr - row ) / t_sqr |
|
94 r.border_max_y = ( t_sqr - row + 1 ) / t_sqr |
|
95 |
|
96 bpy.ops.render.render( write_still=True ) |
|
97 |
|
98 else: |
|
99 print( "Another worker already on %s, skipping." % filepath ) |
|
100 |
|
101 |