Applying a Logo Over a Material’s Geometry

This tutorial illustrates how the material applied on a geometry can be modified to show extra decals or logos over it. The logos applied on the material can use a custom proprietary shading independent on the base material shading. The tutorial produces the image below:

../../../_images/wf_LogoMapping04.jpg

The cube material with an opaque logo applied onto it

Scene Setup

As usual, the scene used in this tutorial is not really complex. It is composed of a cube primitive on which a generic transparent material is applied. The important functions here are RED::IMeshShape::Box and RED::IMaterial::SetupGenericMaterial.

// Creating a cube:
RED::Object* cube = RED::Factory::CreateInstance( CID_REDMeshShape );
cube->SetID( "Cube" );

RED::IMeshShape* icube = cube->As< RED::IMeshShape >();
RC_TEST( icube->Box( RED::Vector3( 0.0, 0.0, 10.01 ), RED::Vector3( 10.0 ), state ) );

// Adding the cube to the scene:
RC_TEST( icamera->AddShape( cube, state ) );

// Creating a generic material:
RED::LayerSet photo = RED::LayerSet::ALL_LAYERS;
RED::LayerSet rt = RED::LayerSet::ALL_LAYERS;

RED::Object* material;
RC_TEST( iresmgr->CreateMaterial( material, state ) );
RED::IMaterial* imaterial = material->As< RED::IMaterial >();
RC_TEST( imaterial->SetupGenericMaterial( true, false,
                                        RED::Color::BLACK, NULL, RED::Matrix::IDENTITY, RED::MCL_TEX0,
                                        RED::Color::WHITE, NULL, RED::Matrix::IDENTITY, RED::MCL_TEX0,
                                        RED::Color::WHITE, NULL, RED::Matrix::IDENTITY, RED::MCL_TEX0,
                                        RED::Color::BLACK, NULL, RED::Matrix::IDENTITY, RED::MCL_TEX0, 0.0f,
                                        RED::Color::BLACK, NULL, RED::Matrix::IDENTITY, RED::MCL_TEX0, 0.0f,
                                        true, false,       NULL, RED::Matrix::IDENTITY, 1.0f, true,
                                        RED::Color::GREY,  NULL, RED::Matrix::IDENTITY, RED::MCL_TEX0, 0.0f,
                                                            NULL, RED::Matrix::IDENTITY, RED::MCL_TEX0, RED::MCL_USER0,
                                        &rt, &photo, resmgr, state ) );

// Assigning the material to the cube:
RED::IShape* ishape = cube->As< RED::IShape >();
RC_TEST( ishape->SetMaterial( material, state ) );

Controlling the Logo Opacity

If we take a look at the alpha channel set by RED::IMaterial::SetLogoMask, we get the following image:

../../../_images/wf_LogoMapping02.jpg

View of the alpha channel in the frame buffer

From this, we can apply any custom material setup to repaint our shading over the source material that has been modified by the application of the logos.

First, during the shading, we must preserve the existing alpha mask. This is where we have to draw. Thanks to RED::StateShader::SetColorMask, we can decide to preserve the alpha masking at each rendering pass.

RC_TEST( logostate.SetColorMask( true, true, true, false ) );

Then, the blending formula we’ll use to accumulate each shader is important. using RED::StateShader::DST_ALPHA will preserve the color on the logo and discard it outside of the logo (the alpha is black out of the logo): RED::StateShader::ONE_MINUS_DST_ALPHA will preserve the color outside of the logo and discard all information in the logo area.

RC_TEST( logostate.SetBlendingMode( RED::StateShader::CUSTOM,
                                RED::StateShader::DST_ALPHA,
                                RED::StateShader::ADD,
                                RED::StateShader::ONE_MINUS_DST_ALPHA ) );

So, if we add a RED::RenderShaderAmbient after the ‘logostate’ shader, we’ll see the ambient contribution on the logo and nothing outside of it. As we have no ambient contribution here, the result if black over the logo. Outside of the logo, the RED::StateShader::ONE_MINUS_DST_ALPHA preserves the destination color, so we continue to see through the material, while the color is set to black in the logo area.

Then, we have to accumulate lighting passes. This is done using the following blending formula:

RC_TEST( logostate_lit.SetBlendingMode( RED::StateShader::CUSTOM,
                                    RED::StateShader::DST_ALPHA,
                                    RED::StateShader::ADD,
                                    RED::StateShader::ONE ) );

We want to preserve the existing shading outside of the logo and inside the logo, and only accumulate lighting contribution inside the logo. Therefore, the RED::StateShader::DST_ALPHA term applied to the source color does the job: the accumulated Lambertian shader is discarded outside of the logo, while we keep all existing contribution, thanks to the RED::StateShader::ONE term applied to the framebuffer color. These two steps are illustrated below:

../../../_images/wf_LogoMapping03.jpg

Ambient contribution over the logo on the left, Ambient + Lambertian lighting on the right

Logo Visualization on the GPU

So far, the tutorial was rendered on the CPU, but the application of logos can be used on the CPU and on the GPU. For identical settings, both results will look the same. The last tutorial step illustrates a simple real-time GPU setup with the logo. No GPU ray-tracing options besides the transparencies are set to preserve real-time performances on all types of hardware.

Visualizing Multiple Logos

The logo visualization code we have programmed above uses an ambient shader (RED::RenderShaderAmbient) plus a Lambertian shader for the lighting passes (RED::RenderShaderLambert):

RED::RenderShaderAmbient ambient( RED::MTL_PRELIT,
                              RED::Color::WHITE, g_logo, RED::Matrix::IDENTITY, RED::MCL_TEX0,
                              RED::Color::BLACK, NULL,   RED::Matrix::IDENTITY, RED::MCL_TEX0,
                              RED::Color::BLACK, NULL,   RED::Matrix::IDENTITY, RED::MCL_TEX0,
                              RED::Color::WHITE, NULL,   RED::Matrix::IDENTITY, RED::MCL_TEX0,
                              true, resmgr, rc );
RED::RenderShaderLambert lambert( RED::MTL_LIT,
                                RED::Color::WHITE, g_logo, RED::Matrix::IDENTITY, RED::MCL_TEX0,
                                RED::Color::WHITE, NULL,   RED::Matrix::IDENTITY, RED::MCL_TEX0,
                                NULL, RED::Matrix::IDENTITY, RED::MCL_TEX0, RED::MCL_USER0,
                                resmgr, rc );

The logo image ‘g_logo’ is used as a diffuse texture for the display of the logos. If we want to visualize multiple logos, we have to replace this texture by a composite image (RED::IImageComposite) to generate the appropriate diffusion image. The composite can be created with the RED::IResourceManager::CreateImageComposite method and setup using the function RED::IImageComposite::SetRenderShader with our RED::RenderShaderLogo parameter.

The RED::RenderShaderLogo takes as parameter the list of textures, matrices and uvs corresponding to the multiple logos.