Rendering large images

Introduction

In today graphics, a lot of images need big resolutions. In fact, resolutions can be so high that you can't even think about rendering them in a single video buffer. You may also need to render parts of a same image onto different displays. REDsdk provides an easy way to split an image calculation in buckets of pixels that can be later reassembled into the whole image: the asymmetric camera (see Viewpoints).

Description

In this tutorial, we'll render a large images made of 16 buckets of pixels using REDsdk asymmetric cameras. As usual, we start by setuping a simple scene: a collection of coloured boxes lit by a single spotlight.

Then, the rendering is split into 16 passes. Each pass renders 1/16th of the whole image using an asymmetric camera.

The subdivision in buckets used to render the whole image.

The rendering then consists of a 4x4 loop:

// Computes the 16 image chunks.
for( int y = 0; y < 4; ++y )
{
  for( int x = 0; x < 4; ++x )
  {
    while( ( RFK::TutorialApplication::GetTime() - last_time ) < 1000.0f ) {}
    last_time = RFK::TutorialApplication::GetTime();

    float tfov = tanf( fov );
    float tfovleft = tfov - x * 2.f * tfov / 4.f;
    float tfovright = -tfov + ( x + 1 ) * 2.f * tfov / 4.f;

    float tfovbottom = ratio * ( tfov - ( 3 - y ) * 2.f * tfov / 4.f );
    float tfovtop = ratio * ( -tfov + ( 4 - y ) * 2.f * tfov / 4.f );

    RC_TEST( iviewpoint->SetAsymmetricFrustumPerspective( atanf( tfovleft ), atanf( tfovright ), 
                                                          atanf( tfovbottom ), atanf( tfovtop ), 
                                                          iresmgr->GetState() ) );

    RFK::TutorialApplication::UpdateProgressBar( ( x + y * 4 + 1 ) / 16.f );
    RC_TEST( RFK::TutorialApplication::Invalidate() );

    // Blits the chunk pixels into the output image.
    RC_TEST( iimg2d->GetPixels() );
    unsigned char* pixels = iimg2d->GetLocalPixels();

    unsigned char* dst = output + 4 * ( ( 3 - y ) * h * ww + x * w );
    unsigned char* src = pixels;
    for( int line = 0; line < h; ++line )
    {
      memcpy( dst, src, 4 * w );
      dst += 4 * ww;
      src += 4 * w;
    }
  }
}

For each new bucket to render, the corresponding asymmetric camera is setup. After the bucket rendering, the rendered pixels are get back using a RED render image (see RED::IImage2D::SetRenderImage) and immediately blit into the final hi-res image.

Finally, the hi-res image is saved to the disk using the RED::ImageTools API.