Creating Images
Images operations generally occur from the application’s rendering thread, because most image operations are synchronous, and are not allowed while a rendering is being processed. This behavior can be bypassed, but in the case of GPU application, it requires a fine management of OpenGL contexts on the various threads involved in image operations. So as a general guideline, all image operations should occur from the rendering thread.
Let’s start by creating (or destroying) images. As other resources managed by the RED::IResourceManager
class, images are shared resources. An image is used by shaders, themselves used inside materials to define how a shape is going to be rendered.
Creating and Destroying Images
// First, get our resource manager and access its interface.
RED::Object* resmgr = RED::Factory::CreateInstance( CID_REDResourceManager );
RED::IResourceManager* iresmgr = resmgr->As< RED::IResourceManager >();
// Then, create an image from it (here a 2D image in this example):
RED::Object* image2D;
RC_TEST( iresmgr->CreateImage2D( image2D, iresmgr->GetState() ) );
// Release the image after use:
RC_TEST( iresmgr->DeleteImage( image2D, iresmgr->GetState() ) );
Images are shared resources. Most of the time, they get used by shader parameters (see the RED::RenderShaderParameter class
). It’s the responsibility of the application to ensure that an image is no longer used anymore when a draw occurs after the destruction of the image. HOOPS Luminate may detect invalid images addresses still used in a scene graph and will return a RED_SCG_INVALID_IMAGE_ADDRESS
during the draw of that scene graph.
Then, images may be duplicated whenever needed (keeping in mind that an image may take a lot of space in memory!) using the following code:
Duplicating an Image
// First, get our resource manager and access its interface.
RED::Object* resmgr = RED::Factory::CreateInstance( CID_REDResourceManager );
RED::IResourceManager* iresmgr = resmgr->As< RED::IResourceManager >();
// Let's create a sample 2D image:
RED::Object* image2D;
RC_TEST( iresmgr->CreateImage2D( image2D, iresmgr->GetState() ) );
// And add some contents to it for the purpose of this example:
RED::IImage2D* iimage2D = image2D->As< RED::IImage2D >();
float pixel[4] = { 2.0f, 1.0f, 0.5f, 1.0f };
RC_TEST( iimage2D->SetPixels( (unsigned char*)pixel, RED::FMT_FLOAT_RGBA, RED::TGT_TEX_RECT, 1, 1, iresmgr->GetState() ) );
// And duplicate that image:
RED::Object* image2D_copy;
RC_TEST( iresmgr->CloneImage( image2D_copy, image2D, iresmgr->GetState() ) );
Please note that, as detailed by the RED::IResourceManager::CloneImage
method, the local storage of the source image is overridden and lost during the operation due to the fact that the engine reads back the source image contents to its local storage before re-assigning it to the copy.
An image can be sourced by the application from a local pixel array, from the disk through commonly supported image formats (JPEG, PNG, HDR) or from .red files. See the details here on Loading and Saving Images.