Titling Made Simple

Titling is an important part of any animation. Well-done titling adds a touch of professionalism to your work.
There are a lot of instances in which you will want to have some kind of titling in your POV-Ray scenes. There are two approaches you can employ to add titling: In-scene titling and post-processed titling.
In-scene Titling
The first approach has the advantage that it requires only one render. Its disadvantages are:
  • The artist has to make sure that the other scene elements do not obscure the titling;
  • If the titling is changed then the scene has to be entirely re-rendered;
  • The method does not work well (if at all) in scenes where there is a camera effect in place (such as focal blur).
In my earlier post about the main scene file, I invoke the scenery file and the titling file separately, so that the scenery file can specify the basic camera parameters, and the latter file can use these settings to place the titling exactly where it needs to be to appear in the render. You can put your titling into the titling file, and make use of values defined earlier in the scene parsing, and it will be positioned correctly, no matter how the camera happens to be positioned.
Post-processed Titling
With post-processed titling, you have to perform multiple renders. The first render generates the frames with the scenery, the second render creates the frames to be overlaid, and the third render composites the two sets of frames together. The advantages are the opposite of in-scene titling:
  • The titling will always appear in front of the scenery;
  • When there are changes in the titling, only the titling frames need to be re-rendered, which is very fast;
  • The titling will not be affected by any camera effects applied to the scenery (which are part of a separate render).
First, a helpful macro
The titling will be simple full-white lettering, and to ensure that it contrasts with the background we will put a semi-transparent black box immediately behind it. This macro will provide the black box for any object, with the following parameters:
  • oThing is the object to be given the box;
  • vView is the vector along which the object will be viewed.
  • vPad sets the padding along each of the coordinate axes.
  • #macro BackingBox(oThing, vView, vPad)
      #local vMin = min_extent(oThing) - vPad;
      #local vMax = max_extent(oThing) + vPad;
      #local fUnion = 0;
    
      #local fXN = vnormalize(vView).x < 0;
      #local fXP = vnormalize(vView).x > 0;
      #local fYN = vnormalize(vView).y < 0;
      #local fYP = vnormalize(vView).y > 0;
      #local fYN = vnormalize(vView).z < 0;
      #local fYP = vnormalize(vView).z > 0;
    
      #if ((fXN + fXP + fYN + fYP + fZN + fZP) > 1)
      union {
      #end
      
      #if (fXP)
        polygon { 5
          , <vMax.x, vMin.y, vMin.z>
          , <vMax.x, vMin.y, vMax.z>
          , <vMax.x, vMax.y, vMax.z>
          , <vMax.x, vMax.y, vMin.z>
          , <vMax.x, vMin.y, vMin.z>
        }
      #end
      #if (fXN)
        polygon { 5
          , <vMin.x, vMin.y, vMin.z>
          , <vMin.x, vMin.y, vMax.z>
          , <vMin.x, vMax.y, vMax.z>
          , <vMin.x, vMax.y, vMin.z>
          , <vMin.x, vMin.y, vMin.z>
        }
      #end
      #if (fYP)
        polygon { 5
          , <vMin.x, vMax.y, vMin.z>
          , <vMin.x, vMax.y, vMax.z>
          , <vMax.x, vMax.y, vMax.z>
          , <vMax.x, vMax.y, vMin.z>
          , <vMin.x, vMax.y, vMin.z>
        }
      #end
      #if (fYN)
        polygon { 5
          , <vMin.x, vMin.y, vMin.z>
          , <vMin.x, vMin.y, vMax.z>
          , <vMax.x, vMin.y, vMax.z>
          , <vMax.x, vMin.y, vMin.z>
          , <vMin.x, vMin.y, vMin.z>
        }
      #end
      #if (fZP)
        polygon { 5
          , <vMin.x, vMin.y, vMax.z>
          , <vMin.x, vMax.y, vMax.z>
          , <vMax.x, vMax.y, vMax.z>
          , <vMax.x, vMin.y, vMax.z>
          , <vMin.x, vMin.y, vMax.z>
        }
      #end
      #if (fZN)
        polygon { 5
          , <vMin.x, vMin.y, vMin.z>
          , <vMin.x, vMax.y, vMin.z>
          , <vMax.x, vMax.y, vMin.z>
          , <vMax.x, vMin.y, vMin.z>
          , <vMin.x, vMin.y, vMin.z>
        }
      #end
    
      #if ((fXN + fXP + fYN + fYP + fZN + fZP) > 1)
      }
      #end
    #end
    
    The following code also assumes that the following variables are defined as described:
  • vCamR is a normalized vector to the viewer's right;
  • vCamU is a normalized vector pointing up from the camera (tilted with the camera);
  • vCamD is a normalized vector pointing forward from the camera;
  • pCamL is the camera's location;
  • sCamZ the zoom of the camera.
  • Example: In-scene Titling
    The first thing you will want to do is to decide how the titling will actually look. For most titling you will use a text object:
    #local Text1 = text {
      ttf "cyrvetic.ttf" "Meanwhile..." .01, 0
    }
    
    I assign the titling to a #local object so that I can use the scene description language features to align and place the text and put a half-dark rectangle behind it to provide contrast. I put it into the scene using the following code:
    union {
      // Place the titling into the union
      object { Text1 pigment { rgb 1 } finish { ambient 1 diffuse 0 } }
      // Add the backing rectangle
      object { BackingBox(Text1, z, <.1, .1, 0>) pigment { rgbt <0, 0, 0, .5> } finish { ambient 1 diffuse 0 } }
      // Center the titling horizontally
      translate (min_extent(Text1) + max_extent(Text1)) * <-.5,0,0>
      // Scale the titling
      scale .1
      // Place the titling at the bottom of the screen
      translate -y * .45
    
      // Move the titling to the front of the viewing frustum
      translate z * sCamZ
      // Transform the titling to the camera space
      Matrix(vCamR, vCamU, vCamD, pCamL)
    }
    
    This last piece of code sets the background and the camera:
    sky_sphere { pigment { granite scale 2 } }
    
    camera {
      right vCamR * image_width
      up vCamU * image_height
      direction vCamD * sCamZ * min(image_width, image_height)
      location pCamL
    }
    
    When this is rendered, you will see something like dark clouds, with the titling just above the bottom edge of the screen, with a shadow box to ensure that it contrasts with the scenery.
    Example: Post-processed titling
    This will use the same local object as the text, and place it into the scene using code much like what you see above:
    union {
      // Place the titling into the union
      object { Text1 pigment { rgb 1 } finish { ambient 1 diffuse 0 } }
      // Add the backing rectangle
      object { BackingBox(Text1, z, <.1, .1, 0>) pigment { rgbt .5 } finish { ambient 1 diffuse 0 } }
      // Center the titling horizontally
      translate (min_extent(Text1) + max_extent(Text1)) * <-.5,0,0>
      // Scale the titling
      scale .1
      // Place the titling at the bottom of the screen
      translate -y * .45 + z * sCamZ
      // Scale to match the size of the image
      scale min(image_width, image_height)
      // Transform the titling to the camera space
      Matrix(vCamR, vCamU, vCamD, pCamL)
    }
    
    This last piece of code sets the background and the camera.
    background { rgb 0 }
    
    camera {
      orthographic
      right vCamR * image_width
      up vCamU * image_height
      direction vCamD
      location pCamL
    }
    
    You can render titling frames like these at the maximum anti-aliasing levels. There are so few objects that it will go very quickly. The scenery frames will be rendered normally. The compositing frames, which will produce the final results, are produced with the following code:
    plane { -z, 0
      pigment {
        pigment_pattern { TitlePigment }
        pigment_map {
          [0 SceneryPigment ]
          [.5 average pigment_map { [1 SceneryPigment] [1 rgb 0] } ]
          [ 1 rgb 1 ]
        }
        scale <image_width, image_height, 1>
      }
      finish { ambient 1 diffuse 0 } }
    }
    
    camera {
      orthographic
      right vCamR * image_width
      up vCamU * image_height
      direction vCamD
      location pCamL
    }
    
    The compositing step should be rendered with no anti-aliasing, and with the gamma settings set to one. For best results, render the titling frame, the scenery frame, and the compositing frame at the same resolution.

    Comments

    Popular posts from this blog

    Transition Macros

    Star Field Generator