// .----------------------------------------------------------------------. // | Jaap's distributed render system for povray animations v 0.01 | // | | // | (for a Windows network) | // | | // | 2006 J.W. Stolk http://www.jwstolk.xs4all.nl | // '----------------------------------------------------------------------' // .----------------------------------------------------------------------. // | Why? | // '----------------------------------------------------------------------' // // It's very easy to speed up rendering of animation by using more computers, // simply render a subset of frames on each computer. it can be done by // choosing apropreate start_frame and end_frame settings for each computer. // The biggest disadvantage of this methode is that the render time per frame // (as wel as the processing power of the used computers) can vary a lot. // This results is that some comuters have finished ther part (and do nothing) // while other computers still have a few days to go... // // This render system contains a "master" (this file) that distributes the // to-be-rendered frames to the "clients" one by one, untill all frmes are // rendered. this way all computers will be used untill the whole animation // is compleated. // // appart from a small dos batch file that repeatetly runs povray, its all SDL, // so you should be able to change it to your needs. :-) // .----------------------------------------------------------------------. // | How it works: | // '----------------------------------------------------------------------' // // Please note: I'm have just thrown this together and I don't have the time // to clean things up right now. a lot of directories and file // names are hard-coded, so you will have to change them if needed. // // mater <-> client communication: // very simple: it is done with files in a shared folder on a windows network. // all clients need to have read and write permission in this folder. // // // It all starts with the master_loop.bat batch file. This batch file // contains a simple loop that repeatedly "renders" the master.pov file. // you should run this _ONLY_ on the master computer. // // master.pov keeps track of the render farm status using a simple textfile. // the textfile mainly indicates which frame each client is rendering. // master.pov assigns frames to the clients by generating a batch file with // the name of the client, containing a render command for that frame. // // Each client runs its own copy of the client_loop.bat batch file. This // batch file moves the render command to the client, runs it and copies the // rendered image back to the shared folder. // // master.pov detects that a client is ready by testing for the returned image // file. if the image is returned, it assigns a new frame to that client. // // .----------------------------------------------------------------------. // | usage: | // '----------------------------------------------------------------------' // Make up a name for each computer and put it in this list: #declare clients = 3; #declare client_name = array[clients] { "pc_red", "pc_green", "pc_blue" // (note the missing comma after the last entry) } // put the following batch file on each client. (call it client_loop.bat) /* --- client_loop.bat --- (cut here) ---- @echo off :loop REM -- move the render command to this client: copy "z:\render_farm\run_pov_pc_red.bat" "c:\render_farm\" /y del "z:\render_farm\run_pov_pc_red.bat" REM -- run the render command: call run_pov_pc_red.bat REM -- 1 sec delay: (needs the sleep.exe program!) sleep 1 REM -- delete the finished render command: REM (prevents running it again) del "c:\render_farm\run_pov_pc_red.bat" REM -- move the resulting image to the shared directory: REM (this indicates that the client is ready) copy "c:\render_farm\*.png" "z:\render_farm\" del "c:\render_farm\*.png" goto loop */ //--- (upto here) ---- // change "pc_red" to the name of that client. // change "z:\render_farm\" to the name of the folder shared by all clients. // change "c:\render_farm\" to the name of the local folder on the client. // you will also need the sleep.exe DOS utility !! // set the render settings for the animation: // "test.pov" -> test001.png .. test199.png #declare animation_name = "test"; // the pov-file you want to render, without ".pov" !! #declare animation_first_frame = 1; #declare animation_last_frame = 199; // options without "+SF" or "+EF" !!!!!: //(i don't know why I needed the "+L". it's already in the povray.ini file) #declare animation_render_options= "+w720 +h400 +a0.3 -j +KF8.0 +KFF199 +FN +L\"C:\\render_farm\\POV-Ray for Windows v3.6\\INCLUDE\""; #declare client_povray_location = "C:\\render_farm\\POV-Ray for Windows v3.6\\bin\\megapov.exe"; #declare status_file_name = "render_farm_status.txt"; #debug " -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=-\n" // the master computer runs (renders) master.pov repeatedly using // the following batch file on each computer. (call it master_loop.bat) /* --- master_loop.bat --- (cut here) ---- @echo off :loop REM -- try to assign frames to clients: C:\render_farm\POV-Ray for Windows v3.6\bin\megapov.exe master.pov +w10 +h10 -a -j -D -F REM -- rename new assignments from .tmp to .bat: REM (to prevent race conditions) call rename_list.bat REM -- 1 sec delay: (needs the sleep.exe program!) sleep 1 goto loop */ //--- (upto here) ---- // That's it !! you are now ready to start your render farm :-) // // start the client_loop.bat on each client first. // finally start the master_loop.bat on the master computer. // .----------------------------------------------------------------------. // | notes: (PLEASE READ): | // '----------------------------------------------------------------------' // // -you can open the render_farm_status.txt at any time using notepad // (notepad will open the file as read-only). so you can see what the next // (non-rendered) frame is and which frame each client is rendering. // -the only limmitation is the number of computers that you can give read/write // acces to a shared folder. (limmited to 10 in XP ??? (to sell more windows server?)) // -it's setup for PNG output images. // -it's setup for megapov, you only need to change the client_povray_location // to make it work with the official pov-ray // -you probably need to disable I/O restrictions (only for the shared folder?) // -each client has it's own copy of the povray code that you want to render. // (local copy is faster anyway) // -before starting: // -old render_farm_status.txt file should be deleted !!! // -the output directories in the clients should not contain _any_ PNG's // -the clients should not contain old render commands // -the shared directory should not contain PNG's with the same filename. // -the shared directory should not contain old render commands // -you should probably not run the client on the master computers. it would // result in two instances of povray running on the same computer. // -you can use a slow computer as master, since it doesn't do any rendering. // -it's best to start the loop.bat files from a dos-box. that way the dos-box // is not closed if there is an error, so you can read the error :-) // -the loops can only be stoped manually ( +c ) or close the dos-box. // they don't stop automatically if the animation is rendered. // -povray must be installed in the same path on each client // -I installed povray+megapov in c:\render_farm\ (can be anywhere) // -I needed to use a very short pov-ray name to keep the name of the rendered // images (including the frame number!) within 8 chracters. it's probably a // windows megapov limmitation, I haven't noticed it in the Linux version. // -possible (big?) rewrite: don't define a table with clients names here, // let each client indicate it's own name in some way. That would make it // possible to add and remove clients while rendering. // .----------------------------------------------------------------------. // |----------------------------------------------------------------------| // '----------------------------------------------------------------------' // .----------------------------------------------------------------------. // | read the status file: | // '----------------------------------------------------------------------' #declare status_first_frame = 0; #declare client_working = array[clients]; #declare client_frame = array[clients]; #declare not_used = "not_used"; #if(file_exists(status_file_name)=1) // file exists: read it: #fopen status_file status_file_name read #read (status_file, not_used, status_first_frame) #declare client=0; #while (client < clients) #read (status_file, not_used, val1, val2) #declare client_working[client] = val1; #declare client_frame[client] = val2; #declare client=client+1; #end #fclose status_file #else // file does not exist: start with clear status: #declare status_first_frame = animation_first_frame; #declare client=0; #while (client < clients) #declare client_working[client] = 0; #declare client_frame[client] = 0; #declare client=client+1; #end #end // .----------------------------------------------------------------------. // | check if any of the clients are ready: | // '----------------------------------------------------------------------' // if a client has returned its output image, it's ready :-) // calculate number of digits in output images: #declare animation_output_digits = 1; #declare animation_output_max = 9; #while(animation_last_frame > animation_output_max) #declare animation_output_digits = animation_output_digits + 1; #declare animation_output_max = animation_output_max*10 + 9; #end #declare client=0; #while (client < clients) #if(client_working[client] = 1) #declare PNG_file_name = concat("z:\\render_farm\\",animation_name, str(client_frame[client],-animation_output_digits,0),".png"); #if(file_exists(PNG_file_name)=1) #debug concat("client ",client_name[client]," has compleated frame ",str(client_frame[client],0,0),".\n") #declare client_working[client] = 0; #declare client_frame[client] = 0; #else #debug concat(PNG_file_name," not ready\n") #end #end #declare client=client+1; #end // .----------------------------------------------------------------------. // | generate new command batch files for clients that are ready: | // '----------------------------------------------------------------------' // The file is generated with a .tmp extension, and later renamed, // to prevent that a client reads an incompleat command. #fopen bat_rename "rename_list.bat" write #declare client=0; #while (client < clients) #if(status_first_frame > animation_last_frame) #debug "all frames are done !! (currently rendering the last frame(s) )\n" #declare client=9999; // (break out of loop) #else #if(client_working[client] = 0) #debug concat("assigned frame ",str(status_first_frame,0,0)," to client ",client_name[client],"\n") // generate new command batch file: // #declare tmp_file_name = concat("z:\\render_farm\\run_pov_",client_name[client],".tmp"); // #declare bat_file_name = concat("z:\\render_farm\\run_pov_",client_name[client],".bat"); #declare tmp_file_name = concat("run_pov_",client_name[client],".tmp"); #declare bat_file_name = concat("run_pov_",client_name[client],".bat"); #fopen bat_file tmp_file_name write #write(bat_file, "\"",client_povray_location,"\" ",animation_name,".pov ",animation_render_options) #write(bat_file, " +SF",str(status_first_frame,0,0)," +EF",str(status_first_frame,0,0),"\n") #fclose bat_file // add it to the rename_list batch file: #write(bat_rename, "rename \"",tmp_file_name,"\" \"",bat_file_name,"\"\n") // update the client status: #declare client_working[client] = 1; #declare client_frame[client] = status_first_frame; #declare status_first_frame = status_first_frame + 1; #end #end #declare client=client+1; #end #fclose bat_rename #debug " -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=-\n" // .----------------------------------------------------------------------. // | write the status file: | // '----------------------------------------------------------------------' #fopen status_file status_file_name write #write(status_file, "\"next_frame:\",",status_first_frame,",\n") #declare client=0; #while (client < clients) #write(status_file,"\"",client_name[client],"\",",client_working[client],",",client_frame[client]",\n") #declare client=client+1; #end #fclose status_file //end