Re: distributed rendering

Christoph Fabianek <[email protected]> Sun, 21 Sep 2003 02:46:45 +0200
Newsgroups gmane.comp.kde.devel.kpovmodeler
Message-ID <[email protected]>
Hi,

ok - I have now an implementation of the distributed rendering interface that 
works fine for me and includes user feedback and correct orientation.

The user feedback works as described in a previous mail, i.e., whenever a row 
of tiles is finished it is displayed which leads to a somewhat snatchy 
feedback but I think for remote rendering you can't get anything better. And 
there is always the option to look into the output window to see which 
machines are currently working.

As for the orientation of the images: it turns out that there are various TGA 
formats with different orientations - this is also fixed now.

I will also write some documentation today - could someone please send me the 
sources of the kpovmodeler docs or point me to the location where to download 
- I will update the section "POV-Ray Interaction".

Attached is the patch - I would be glad if someone would test it and give me 
feedback. Beside the patch you will need nspovray and optionally NetSolve 
(you may use SSH or NetSolve as transport for accessing other machines). 
Unfortunately, building nspovray from sources is currently a bit difficult 
since it requires NetSolve. So you have two choices:

- Download the binaries from
  http://fsmat.at/~cfabiane/software/nspovray_i686-pc-linux-gnu_0.4pre.tar.gz
  and unpack it into an empty directory. Afterwards use this directory as
  "nspovray Path" in the "Distributed Rendering" tab (Render Modes dialog) and
  specify the following agent: "netsolve.cs.utk.edu"
  see the screenshot for an example configuration:
  http://fsmat.at/~cfabiane/tmp/render_modes.png

- or you may download the sources and compile at first NetSolve
  http://icl.cs.utk.edu/netsolve/downloads/
  and then nspovray
  http://fsmat.at/~cfabiane/software/nspovray_src_0.4pre.tar.gz
  follow the instructions on 
  http://fsmat.at/~cfabiane/nspovray.html
  (this will take a few hours so I highly recommend using the binaries!)

Greetings,
   Christoph


PS: I just did a final test and I know - the machines currently in the 
NetSolve grid are really slow and the scheduler still doesn't distribute the 
load optimally... Hopefully, I can add some faster machines in the next days 
and the scheduler gets better before the release of NetSolve 2.0 scheduled 
within the next weeks.


On Friday 19 September 2003 11:48, [email protected] wrote:
> Hi Christoph!
>
> > I agree that with a render plugin framework and perhaps some other
> > architectural changes a cleaner support would be possible. But just
>
> trashing
>
> > my work and wait at least another year (in Nove Hrady it was looking
>
> like
>
> > that the next KDE version will be based on Qt 4) would be quite
> > unsatisfactory.
>
> That has nothing to do with trashing your work.
> KPovModeler was always released with stable, complete and well tested
> features. Your distributed rendering tool is not finished yet, as it
> doesn't give any direct feedback to the user.
> You have to understand me: We have one(!) week left for feature commits
> and string changes. If you realize in two weeks that the current POV-Ray
> rendering implementation is not suitable for your tool, we have no chance
> to change it any more.
>
> If you can finish a version until monday, 22 september, that has a user
> feedback and shows the image in correct orientation, then I will add it in
> this version.
>
> Greetings, Andreas
>
>
>
> List archive and information:
> http://mail.kde.org/mailman/listinfo/kpovmodeler-devel


List archive and information: http://mail.kde.org/mailman/listinfo/kpovmodeler-devel
dist_render.patch (text/x-diff, 17.4 KB)
Index: pmpovrayrenderwidget.cpp
===================================================================
RCS file: /home/kde/kdegraphics/kpovmodeler/pmpovrayrenderwidget.cpp,v
retrieving revision 1.21
diff -u -r1.21 pmpovrayrenderwidget.cpp
--- pmpovrayrenderwidget.cpp	4 Jul 2003 21:23:34 -0000	1.21
+++ pmpovrayrenderwidget.cpp	21 Sep 2003 00:36:15 -0000
@@ -92,7 +92,16 @@
    connect( m_pProcess, SIGNAL( processExited( KProcess* ) ),
             SLOT( slotRenderingFinished( KProcess* ) ) );
 
-   *m_pProcess << s_povrayCommand;
+   if ( m_renderMode.distributed( ) )
+   {
+      if( m_renderMode.NetSolve( ) ) {
+         m_pProcess->setEnvironment( QString( "NETSOLVE_AGENT" ), m_renderMode.transportConfig( ) );
+         m_pProcess->setEnvironment( QString( "PROXY_DIR" ), m_renderMode.nspovrayPath( ) );
+      }
+      *m_pProcess << QString( "%1/nspovray" ).arg( m_renderMode.nspovrayPath( ) );
+   } else {
+      *m_pProcess << s_povrayCommand;
+   }
 
    QStringList::ConstIterator it;
    QStringList args = m_renderMode.commandLineSwitches( );
@@ -107,10 +116,19 @@
             path.truncate( path.length( ) - 1 );
       *m_pProcess << ( QString( "+L" ) + path );
    }
-   *m_pProcess << QString( "+I" ) + m_pTempFile->name( ) << "+O-" << "+FT"
+   *m_pProcess << QString( "+I" ) + m_pTempFile->name( ) << "+FT"
                << "+K0.0" << "+KFI1" << "+KFF1" << "+KI0.0" << "+KF0.0"
                << "+SF1" << "+EF1" << "-KC" << "-D";
 
+   if ( m_renderMode.distributed() )
+   {
+      QStringList args = m_renderMode.commandLineDistributedSwitches( );
+      for( it = args.begin( ); it != args.end( ); ++it )
+          *m_pProcess << *it;
+   } else {
+      *m_pProcess << "+O-";
+   }
+
 #if ( ( KDE_VERSION_MAJOR == 2 ) && ( KDE_VERSION_MINOR >= 9 ) ) || ( KDE_VERSION_MAJOR == 3 )
    if( !documentURL.isEmpty( ) && documentURL.isLocalFile( ) )
       m_pProcess->setWorkingDirectory( documentURL.directory( ) );
@@ -136,9 +154,13 @@
 
    if( !m_pProcess->start( KProcess::NotifyOnExit, KProcess::AllOutput ) )
    {
-      KMessageBox::error( this, i18n( "Couldn't call povray.\n"
-                                      "Please check your installation "
-                                      "or set another povray command." ) );
+      if ( m_renderMode.distributed() )
+         KMessageBox::error( this, i18n( "Couldn't call nspovray.\n"
+                                         "Please check your installation." ) );
+      else
+         KMessageBox::error( this, i18n( "Couldn't call povray.\n"
+                                         "Please check your installation "
+                                         "or set another povray command." ) );
       delete m_pProcess;
       m_pProcess = 0;
       return false;
Index: pmrendermode.cpp
===================================================================
RCS file: /home/kde/kdegraphics/kpovmodeler/pmrendermode.cpp,v
retrieving revision 1.6
diff -u -r1.6 pmrendermode.cpp
--- pmrendermode.cpp	6 Sep 2003 04:20:38 -0000	1.6
+++ pmrendermode.cpp	21 Sep 2003 00:36:19 -0000
@@ -51,6 +51,15 @@
    m_description = i18n( "New mode" );
 
    m_alpha = false;
+
+   m_distributed = false;
+   m_nspovrayPath = QString( "" );
+   m_transport = 1;
+   m_transportConfig = QString( "" );
+   m_instances = 2;
+   m_timeout = 120;
+   m_tilewidth = 100;
+   m_tileheight = 100;
 }
 
 PMRenderMode::PMRenderMode( const QDomElement& e )
@@ -75,6 +84,14 @@
    m_antialiasJitterAmount = hlp.doubleAttribute( "aa_jitter_amount", m_antialiasJitterAmount );
    m_antialiasDepth = hlp.intAttribute( "aa_depth", m_antialiasDepth );
    m_alpha = hlp.boolAttribute( "alpha", m_alpha );
+   m_distributed = hlp.boolAttribute ("distributed", m_distributed );
+   m_nspovrayPath = hlp.stringAttribute( "nspovrayPath", m_nspovrayPath );
+   m_transport = hlp.intAttribute( "transport", m_transport );
+   m_transportConfig = hlp.stringAttribute( "transportConfig", m_transportConfig );
+   m_instances = hlp.intAttribute( "instances", m_instances );
+   m_timeout = hlp.intAttribute( "timeout", m_timeout );
+   m_tilewidth = hlp.intAttribute( "tilewidth", m_tilewidth );
+   m_tileheight = hlp.intAttribute( "tileheight", m_tileheight );
 }
 
 void PMRenderMode::serialize( QDomElement& e ) const
@@ -96,6 +113,14 @@
    e.setAttribute( "aa_jitter_amount", m_antialiasJitterAmount );
    e.setAttribute( "aa_depth", m_antialiasDepth );
    e.setAttribute( "alpha", m_alpha );
+   e.setAttribute( "distributed", m_distributed );
+   e.setAttribute( "nspovrayPath", m_nspovrayPath );
+   e.setAttribute( "transport", m_transport );
+   e.setAttribute( "transportConfig", m_transportConfig );
+   e.setAttribute( "instances", m_instances );
+   e.setAttribute( "timeout", m_timeout );
+   e.setAttribute( "tilewidth", m_tilewidth );
+   e.setAttribute( "tileheight", m_tileheight );
 }
 
 void PMRenderMode::setHeight( int height )
@@ -155,6 +180,36 @@
       m_samplingMethod = AntialiasingNonRecursive;
 }
 
+void PMRenderMode::setTransport( int transport )
+{
+   if( ( transport >= 0 ) && ( transport <= 1 ) )
+      m_transport = transport;
+}
+
+void PMRenderMode::setInstances( int instances )
+{
+   if( instances >= 0 )
+      m_instances = instances;
+}
+
+void PMRenderMode::setTimeout( int timeout )
+{
+   if( timeout >= 0 )
+      m_timeout = timeout;
+}
+
+void PMRenderMode::setTilewidth( int tilewidth )
+{
+   if( tilewidth >= 0 )
+      m_tilewidth = tilewidth;
+}
+
+void PMRenderMode::setTileheight( int tileheight )
+{
+   if( tileheight >= 0 )
+      m_tileheight = tileheight;
+}
+
 QStringList PMRenderMode::commandLineSwitches( ) const
 {
    QStringList cl;
@@ -215,6 +270,22 @@
    else
       cl.append( QString( "-UA" ) );
 
+   return cl;
+}
+
+QStringList PMRenderMode::commandLineDistributedSwitches( ) const
+{
+   QStringList cl;
+   cl.append( QString( "--kpm" ) );
+
+   cl.append( QString( "--dist" ) );
+   cl.append( QString( "%1" ).arg( m_instances ) );
+
+   cl.append( QString( "--timeout" ) );
+   cl.append( QString( "%1" ).arg( m_timeout ) );
+
+   cl.append( QString( "--tile" ) );
+   cl.append( QString( "%1x" ).arg( m_tilewidth ) + QString( "%1" ).arg( m_tileheight ) );
    return cl;
 }
 
Index: pmrendermode.h
===================================================================
RCS file: /home/kde/kdegraphics/kpovmodeler/pmrendermode.h,v
retrieving revision 1.6
diff -u -r1.6 pmrendermode.h
--- pmrendermode.h	30 Dec 2002 19:55:16 -0000	1.6
+++ pmrendermode.h	21 Sep 2003 00:36:20 -0000
@@ -92,11 +92,31 @@
    void setAlpha( bool on ) { m_alpha = on; }
    bool alpha( ) const { return m_alpha; }
    
-   
+   void setDistributed( bool on ) { m_distributed = on; }
+   bool distributed( ) const { return m_distributed; }
+   void setNspovrayPath( const QString& nspovrayPath ) { m_nspovrayPath = nspovrayPath; }
+   QString nspovrayPath( ) const { return m_nspovrayPath; }
+   void setTransport( int m_transport );
+   int transport( ) const { return m_transport; }
+   bool NetSolve( ) const { return (m_transport == 0); }
+   void setTransportConfig( const QString& tpconf ) { m_transportConfig = tpconf; }
+   QString transportConfig( ) const { return m_transportConfig; }
+   void setInstances( int instances );
+   int instances( ) const { return m_instances; }
+   void setTimeout( int timeout );
+   int timeout( ) const { return m_timeout; }
+   void setTilewidth( int tilewidth );
+   int tilewidth( ) const { return m_tilewidth; }
+   void setTileheight( int tileheight );
+   int tileheight( ) const { return m_tileheight; }
+
+
    /**
     * Returns the settings as povray command line switches
     */
    QStringList commandLineSwitches( ) const;
+   /* command line switches for nspovray */
+   QStringList commandLineDistributedSwitches( ) const;
    /**
     * Saves the data
     */
@@ -120,6 +140,15 @@
    int m_antialiasDepth;
 
    bool m_alpha;
+   bool m_distributed;
+   QString m_nspovrayPath;
+   int m_transport;
+   QString m_transportConfig;
+   int m_instances;
+   int m_timeout;
+   int m_tilewidth;
+   int m_tileheight;
+
 };
 
 typedef QPtrList<PMRenderMode> PMRenderModeList;
Index: pmrendermodesdialog.cpp
===================================================================
RCS file: /home/kde/kdegraphics/kpovmodeler/pmrendermodesdialog.cpp,v
retrieving revision 1.6
diff -u -r1.6 pmrendermodesdialog.cpp
--- pmrendermodesdialog.cpp	18 May 2003 19:57:25 -0000	1.6
+++ pmrendermodesdialog.cpp	21 Sep 2003 00:36:27 -0000
@@ -30,6 +30,7 @@
 
 #include <klocale.h>
 #include <kconfig.h>
+#include <kiconloader.h>
 #include <kmessagebox.h>
 #include <kfiledialog.h>
 
@@ -358,14 +359,68 @@
 
    tabLayout->addStretch( 1 );
 
-   
+   // distribued rendering options tab
+   tab = new QWidget( );
+   m_pTabWidget->addTab( tab, i18n( "Distributed rendering" ) );
+   tabLayout = new QVBoxLayout( tab, marginHint( ), spacingHint( ) );
+
+   m_pDistributedBox = new QCheckBox( i18n( "Use distributed rendering" ), tab );
+   tabLayout->addWidget( m_pDistributedBox );
+
+   QHBoxLayout* nspovrayPathLayout = new QHBoxLayout( tabLayout );
+   QLabel* nspovrayPathLabel = new QLabel( i18n( "nspovray Path:" ), tab );
+   nspovrayPathLayout->addWidget( nspovrayPathLabel );
+   m_pNspovrayPathEdit = new QLineEdit( tab );
+   nspovrayPathLayout->addWidget( m_pNspovrayPathEdit );
+   m_pBrowseNspovrayPath = new QPushButton( tab );
+   m_pBrowseNspovrayPath->setPixmap( SmallIcon( "fileopen" ) );
+   nspovrayPathLayout->addWidget( m_pBrowseNspovrayPath );
+
+   QHBoxLayout* distHelpLayout = new QHBoxLayout( tabLayout );
+   QGridLayout* distLayout = new QGridLayout( distHelpLayout, 6, 2 );
+   distLayout->addWidget( new QLabel( i18n( "Transport:" ), tab ), 0, 0 );
+   m_pTransportCombo = new QComboBox( tab );
+   distLayout->addWidget( m_pTransportCombo, 0, 1 );
+   m_pTransportCombo->insertItem( i18n( "NetSolve" ) );
+   m_pTransportCombo->insertItem( i18n( "SSH" ) );
+
+   m_pTransportConfigLabel = new QLabel( i18n( "Hostfile:" ), tab );
+   distLayout->addWidget( m_pTransportConfigLabel, 1, 0 );
+   m_pTransportConfigLineEdit = new QLineEdit( tab );
+   distLayout->addWidget( m_pTransportConfigLineEdit, 1, 1 );
+
+   distLayout->addWidget( new QLabel( i18n( "Instances:" ), tab ), 2, 0 );
+   m_pInstancesEdit = new PMIntEdit( tab );
+   m_pInstancesEdit->setValidation( true, 1, false, 0 );
+   distLayout->addWidget( m_pInstancesEdit, 2, 1 );
+
+   distLayout->addWidget( new QLabel( i18n( "Timeout (sec):" ), tab ), 3, 0 );
+   m_pTimeoutEdit = new PMIntEdit( tab );
+   m_pTimeoutEdit->setValidation( true, 1, false, 0 );
+   distLayout->addWidget( m_pTimeoutEdit, 3, 1 );
+
+   distLayout->addWidget( new QLabel( i18n( "Tile width:" ), tab ), 4, 0 );
+   m_pTileWidthEdit = new PMIntEdit( tab );
+   m_pTileWidthEdit->setValidation( true, 1, false, 0 );
+   distLayout->addWidget( m_pTileWidthEdit, 4, 1 );
+
+   distLayout->addWidget( new QLabel( i18n( "Tile height:" ), tab ), 5, 0 );
+   m_pTileHeightEdit = new PMIntEdit( tab );
+   m_pTileHeightEdit->setValidation( true, 1, false, 0 );
+   distLayout->addWidget( m_pTileHeightEdit, 5, 1 );
+
+   distHelpLayout->addStretch( 1 );
+
+   tabLayout->addStretch( 1 );
+
+
    resize( s_size );
-   
+
    // display the mode BEFORE the signals are connected!!!
    displayMode( );
 
    enableButtonOK( false );
-   
+
    // connect signals
    connect( m_pDescriptionEdit, SIGNAL( textChanged( const QString& ) ), SLOT( slotTextChanged( const QString& ) ) );
    connect( m_pHeightEdit, SIGNAL( dataChanged( ) ), SLOT( slotChanged( ) ) );
@@ -384,6 +439,15 @@
    connect( m_pJitterAmountEdit, SIGNAL( dataChanged( ) ), SLOT( slotChanged( ) ) );
    connect( m_pAntialiasDepthEdit, SIGNAL( dataChanged( ) ), SLOT( slotChanged( ) ) );
    connect( m_pAlphaBox, SIGNAL( toggled( bool ) ), SLOT( slotToggled( bool ) ) );
+   connect( m_pDistributedBox, SIGNAL( toggled( bool ) ), SLOT( slotDistributedToggled( bool ) ) );
+   connect( m_pNspovrayPathEdit, SIGNAL( textChanged( const QString& ) ), SLOT( slotTextChanged( const QString& ) ) );
+   connect( m_pBrowseNspovrayPath, SIGNAL( clicked( ) ), SLOT( slotBrowseNspovrayPath( ) ) );
+   connect( m_pTransportCombo, SIGNAL( activated( int ) ), SLOT( slotTransportChanged( int ) ) );
+   connect( m_pTransportConfigLineEdit, SIGNAL( textChanged( const QString& ) ), SLOT( slotTextChanged( const QString& ) ) );
+   connect( m_pInstancesEdit, SIGNAL( dataChanged( ) ), SLOT( slotChanged( ) ) );
+   connect( m_pTimeoutEdit, SIGNAL( dataChanged( ) ), SLOT( slotChanged( ) ) );
+   connect( m_pTileWidthEdit, SIGNAL( dataChanged( ) ), SLOT( slotChanged( ) ) );
+   connect( m_pTileHeightEdit, SIGNAL( dataChanged( ) ), SLOT( slotChanged( ) ) );
 }
 
 void PMRenderModeDialog::saveConfig( KConfig* cfg )
@@ -433,6 +497,14 @@
          m_pMode->setAntialiasingDepth( m_pAntialiasDepthEdit->value( ) );
       }
       m_pMode->setAlpha( m_pAlphaBox->isChecked( ) );
+      m_pMode->setDistributed( m_pDistributedBox->isChecked( ) );
+      m_pMode->setNspovrayPath( m_pNspovrayPathEdit->text( ) );
+      m_pMode->setTransport( m_pTransportCombo->currentItem( ) );
+      m_pMode->setTransportConfig( m_pTransportConfigLineEdit->text( ) );
+      m_pMode->setInstances( m_pInstancesEdit->value( ) );
+      m_pMode->setTimeout( m_pTimeoutEdit->value( ) );
+      m_pMode->setTilewidth( m_pTileWidthEdit->value( ) );
+      m_pMode->setTileheight( m_pTileHeightEdit->value( ) );
       return true;
    }
    return false;
@@ -515,6 +587,16 @@
    m_pJitterAmountEdit->setValue( m_pMode->antialiasingJitterAmount( ) );
    m_pAntialiasDepthEdit->setValue( m_pMode->antialiasingDepth( ) );
    m_pAlphaBox->setChecked( m_pMode->alpha( ) );
+   m_pDistributedBox->setChecked( m_pMode->distributed( ) );
+   m_pNspovrayPathEdit->setText( m_pMode->nspovrayPath( ) );
+   enableDistributed( m_pMode->distributed( ) );
+   m_pTransportCombo->setCurrentItem( m_pMode->transport( ) );
+   setTransportConfigLabel( m_pMode->transport( ) );
+   m_pTransportConfigLineEdit->setText( m_pMode->transportConfig( ) );
+   m_pInstancesEdit->setValue( m_pMode->instances( ) );
+   m_pTimeoutEdit->setValue( m_pMode->timeout( ) );
+   m_pTileWidthEdit->setValue( m_pMode->tilewidth( ) );
+   m_pTileHeightEdit->setValue( m_pMode->tileheight( ) );
 }
 
 void PMRenderModeDialog::enableSubsection( bool yes )
@@ -539,13 +621,41 @@
    m_pJitterAmountEdit->setEnabled( yes );
 }
 
+void PMRenderModeDialog::enableDistributed( bool yes )
+{
+   m_pNspovrayPathEdit->setEnabled( yes );
+   m_pBrowseNspovrayPath->setEnabled( yes );
+   m_pTransportCombo->setEnabled( yes );
+   m_pTransportConfigLineEdit->setEnabled( yes );
+   m_pInstancesEdit->setEnabled( yes );
+   m_pTimeoutEdit->setEnabled( yes );
+   m_pTileWidthEdit->setEnabled( yes );
+   m_pTileHeightEdit->setEnabled( yes );
+}
+
+void PMRenderModeDialog::setTransportConfigLabel( int transport )
+{
+   switch( transport )
+   {
+      case 0:
+         m_pTransportConfigLabel->setText( i18n( "Agent:" ) );
+         break;
+      case 1:
+         m_pTransportConfigLabel->setText( i18n( "Hostfile:" ) );
+         break;
+      default:
+         m_pTransportConfigLabel->setText( QString( "" ) );
+         break;
+   }
+}
+
 int PMRenderModeDialog::qualityToIndex( int quality )
 {
    if( quality < 0 )
       quality = 0;
    if( quality > 11 )
       quality = 11;
-   
+
    return c_qualityToIndex[quality];
 }
 
@@ -584,6 +694,10 @@
 {
    slotChanged( );
    enableSubsection( on );
+   if ( on == true ) {
+      m_pDistributedBox->setChecked( false );
+      enableDistributed( false );
+   }
 }
 
 void PMRenderModeDialog::slotAntialiasingToggled( bool on )
@@ -596,6 +710,31 @@
 {
    slotChanged( );
    enableJitter( on );
+}
+
+void PMRenderModeDialog::slotDistributedToggled( bool on )
+{
+   slotChanged( );
+   enableDistributed( on );
+   if ( on == true ) {
+      m_pSubsectionBox->setChecked( false );
+      enableSubsection( false );
+   }
+}
+
+void PMRenderModeDialog::slotBrowseNspovrayPath( )
+{
+   QString str = KFileDialog::getExistingDirectory( );
+
+   if( !str.isEmpty( ) )
+      m_pNspovrayPathEdit->setText( str );
+}
+
+void PMRenderModeDialog::slotTransportChanged( int item )
+{
+   setTransportConfigLabel( item );
+   m_pTransportConfigLineEdit->setText( QString( "" ) );
+   slotActivated( item );
 }
 
 void PMRenderModeDialog::slotToggled( bool )
Index: pmrendermodesdialog.h
===================================================================
RCS file: /home/kde/kdegraphics/kpovmodeler/pmrendermodesdialog.h,v
retrieving revision 1.4
diff -u -r1.4 pmrendermodesdialog.h
--- pmrendermodesdialog.h	30 Dec 2002 19:55:16 -0000	1.4
+++ pmrendermodesdialog.h	21 Sep 2003 00:36:28 -0000
@@ -128,7 +128,10 @@
    void slotAntialiasingToggled( bool );
    void slotJitterToggled( bool );
    void slotToggled( bool );
-   
+   void slotDistributedToggled( bool );
+   void slotBrowseNspovrayPath( );
+   void slotTransportChanged( int );
+
 private:
    /**
     * Saves the current changes. Returns true if successful.
@@ -148,7 +151,9 @@
    void enableJitter( bool yes );
    int qualityToIndex( int quality );
    int indexToQuality( int index );
-   
+   void enableDistributed( bool yes );
+   void setTransportConfigLabel( int transport );
+
    PMRenderMode* m_pMode;
    
    QTabWidget* m_pTabWidget;
@@ -172,6 +177,18 @@
    // output
    QCheckBox* m_pAlphaBox;
    
+   // distributed rendering
+   QCheckBox* m_pDistributedBox;
+   QLineEdit* m_pNspovrayPathEdit;
+   QPushButton* m_pBrowseNspovrayPath;
+   QComboBox* m_pTransportCombo;
+   QLabel* m_pTransportConfigLabel;
+   QLineEdit* m_pTransportConfigLineEdit;
+   PMIntEdit* m_pInstancesEdit;
+   PMIntEdit* m_pTimeoutEdit;
+   PMIntEdit* m_pTileWidthEdit;
+   PMIntEdit* m_pTileHeightEdit;
+
    static QSize s_size;
 };