Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/bin/sh
- # Parallelized POV-Ray script
- # Usage: ./script FILE.POV [+FLAGS...]
- #-------------------------------------------------------------------------------
- # PARAMS
- #-------------------------------------------------------------------------------
- # povray exe path, space separated include directories (simple paths ONLY)
- # the directory of the input file is included automatically
- HERE="$(dirname "$(readlink -f "${0}")")"
- POVEXE="$HERE/povray"
- POVINC="$HERE/include $HERE/demo"
- # ImageMagick or GraphicsMagick command (typically `magick` or `gm`)
- MAGICK="magick"
- # default render options
- W=640 # output image width
- H=480 # output image height
- CHUNK=240 # chunk width & height (240)
- MAXPROCS=16 # maximum number of parallel processes
- MARGIN=4 # safety margin around each chunk (4)
- Q=9 # quality (9)
- R=3 # number of rays (3)
- A=0.1 # anti-alias threshold
- V=2 # major POV-Ray version (1 or 2)
- #-------------------------------------------------------------------------------
- # INPUT
- #-------------------------------------------------------------------------------
- # check for ImageMagick
- if ! which $MAGICK >/dev/null 2>&1; then
- echo "Error: \`$MAGICK\` not found, please install ImageMagick."
- exit 1
- fi
- # parse command line args
- for arg in "$@"; do
- case "$arg" in
- +W*) W="${arg#+W}" ;;
- +H*) H="${arg#+H}" ;;
- +A*) A="${arg#+A}" ;;
- +R*) R="${arg#+R}" ;;
- +*) echo "??? $arg" ;;
- *) f="`realpath "$1"`" ;;
- esac
- done
- # get input file name if not provided already
- if [ -z "$f" ]; then
- printf "Input POV file (%d x %d, Q=%d, R=%d): " $W $H $Q $R
- read f
- f="${f#"'"}" && f="${f%"'"}"
- fi
- # symlink directory of input file to temp directory without spaces
- fdir_o="`dirname "$f"`"
- fdir="`mktemp -tu povincXXXXXX`"
- ln -s "$fdir_o" "$fdir"
- # generate include flags
- INCDIR="+L$fdir"
- for i in $POVINC; do INCDIR="$INCDIR +L$i"; done
- # generate input and output file names
- INFILE="$fdir/`basename "$f"`"
- OUTFILE="${INFILE%.pov}" && OUTFILE="${OUTFILE%.POV}.png"
- # generate chunk information
- step=$(( CHUNK - 1 )) # 1 -> 119+1
- COLS=$(( (W + CHUNK - 1) / CHUNK )) # total columns rounded up
- ROWS=$(( (H + CHUNK - 1) / CHUNK )) # total rows rounded up
- TOTAL=$(( COLS * ROWS )) # total number of chunks
- # create temporary working directory
- POVTMP=`mktemp -td povtmpXXXXXX`
- # create empty scene for padding chunks
- BLKPOV="$POVTMP/black.pov"
- echo 'light_source {<0,0,0> color red 0}' > "$BLKPOV"
- # create lists for started and finished render jobs
- J0="$POVTMP/j0"
- J1="$POVTMP/j1"
- true > $J0 && true > $J1
- # start timer
- start_time=`date +%s`
- #-------------------------------------------------------------------------------
- # RENDER
- #-------------------------------------------------------------------------------
- # iterate over rows from top to bottom
- i=0 && ER=0
- while [ $i -lt $ROWS ]; do
- # start at last iteration's end + 1, stop if start row is out of bounds
- SR=$(( ER + 1 ))
- if [ $SR -gt $H ]; then break; fi
- # end at <step> rows after start, keep end row within image bounds
- ER=$(( SR + step ))
- if [ $ER -gt $H ]; then ER=$H; fi
- # iterate over columns from left to right
- j=0 && EC=0
- while [ $j -lt $COLS ]; do
- # same thing we did for rows
- SC=$(( EC + 1 ))
- if [ $SC -gt $W ]; then break; fi
- EC=$(( SC + step ))
- if [ $EC -gt $W ]; then EC=$W; fi
- # add safety margin around each chunk...
- SR1=$(( SR - MARGIN ))
- SC1=$(( SC - MARGIN ))
- ER1=$(( ER + MARGIN ))
- EC1=$(( EC + MARGIN ))
- # ...but stay within bounds
- if [ $SR1 -lt 1 ]; then SR1=1; fi
- if [ $SC1 -lt 1 ]; then SC1=1; fi
- if [ $EC1 -gt $W ]; then EC1=$W; fi
- if [ $ER1 -gt $H ]; then ER1=$H; fi
- # wait until background job count is under maximum allowed
- while true; do
- started=`cat $J0 | wc -c`
- ended=`cat $J1 | wc -c`
- procs=$(( started - ended ))
- echo "$procs render jobs running (maximum $MAXPROCS)"
- if [ $procs -lt $MAXPROCS ]
- then break # under capacity, proceed
- else sleep 1s # over capacity, wait
- fi
- done
- # use numbered file names for the chunks
- TMPTGA="$POVTMP/`printf "%04d" $i``printf "%04d" $j`.tga"
- # render chunk, pad it with black, crop it, delete uncropped
- # all in background { ... } &
- printf "0" >> $J0
- {
- $POVEXE +I$INFILE +O$TMPTGA $INCDIR \
- +FT -P -V +A$A +W$W +H$H +Q$Q +R$R +MV$V.0 \
- +SC$SC1 +EC$EC1 +SR$SR1 +ER$ER1 ;
- $POVEXE +I$BLKPOV +O$TMPTGA \
- +FT -P -V -A +C +W$W +H$H +Q0 ;
- x=$(( SC - 1 )) ;
- if [ $SR -eq 1 ]; then y=0; else y=$MARGIN; fi ;
- w=$(( EC - SC + 1 )) ;
- h=$(( ER - SR + 1 )) ;
- $MAGICK convert $TMPTGA -crop ${w}x${h}+${x}+${y} ${TMPTGA%tga}png ;
- rm $TMPTGA ;
- printf "1" >> $J1 ;
- } &
- j=$(( j + 1 ))
- done
- i=$(( i + 1 ))
- done
- #-------------------------------------------------------------------------------
- # FINALIZE
- #-------------------------------------------------------------------------------
- # wait for all render jobs to finish
- while [ `cat $J1 | wc -c` -lt $TOTAL ]; do
- started=`cat $J0 | wc -c`
- ended=`cat $J1 | wc -c`
- procs=$(( started - ended ))
- echo "Waiting for $procs render jobs to finish..."
- sleep 1s
- done
- # concatenate chunks into final image
- $MAGICK montage -mode concatenate -tile ${COLS}x${ROWS} $POVTMP/*.png $OUTFILE
- # clean up temporary files
- rm -r $POVTMP
- rm $fdir
- echo "Finished"
- # calculate time elapsed
- end_time="`date +%s`"
- seconds=$(( end_time - start_time ))
- hours=$(( seconds / 3600 ))
- seconds=$(( seconds - hours * 3600 ))
- minutes=$(( seconds / 60 ))
- seconds=$(( seconds - minutes * 60 ))
- echo "Time elapsed: $hours hours, $minutes minutes, $seconds seconds"
Advertisement
Add Comment
Please, Sign In to add comment