[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ] [ Search: ]

4.15.7 Procedural Texture System

Crystal Space supports procedural textures. These are textures that you can change dynamically (at runtime) so that you get the appearance of an animated texture.

The current implementation of procedural textures works by rendering the contents of the texture on screen and then doing a copy to the texture memory. This means that procedural textures must be updated before the 3D view starts rendering and it also means that the 3D view must make sure that that part of the screen is changed (i.e. either put geometry there or manually clear screen every frame). Note that all textures can be updated with this technique. i.e. you don't need to mark a texture as being procedural.

Updating a Texture Image with 2D and 3D graphics

The following code demonstrates how you can update a texture image:

 
  bool UpdateTexture (iTextureWrapper* tex)
  {
    g3d->SetRenderTarget (tex->GetTextureHandle ());
    if (!g3d->BeginDraw (CSDRAW_2DGRAPHICS)) return false;
    ...
    // Do various operations on g2d.
    ...
    g3d->FinishDraw ();
    return true;
  }

Similarly, it is also possible to do 3D graphics on a procedural texture.

Note that the code above may overwrite what is currently displayed on screen! So make sure to do it before anything you need is rendered.

SetRenderTarget also has a second parameter which is called ‘persistant’ and which is set to false by default. If you set this to true then the previous contents of the texture is copied on screen first. That means you can make modifications to an existing texture. With this parameter set to false (default) you have to create the entire texture again. Note that setting ‘persistant’ to true is slower if you intend to update the entire texture area anyway.

Updating a Texture Image with RGBA Pixel Data

Another way to realize procedural textures is to use the function iTextureHandle->Blit() which can copy a RGBA or BGRA buffer from memory directly to a texture. This is useful for procedural textures where you compute the pixel data directly or obtain it from some external source and hence don't need the 2D or 3D graphics functions.

Using csProcTexture

In the ‘cstool’ module there is a convenience class you can use to make updating of procedural textures easier. This class is called csProcTexture. Basically you make a subclass of this class like this:

 
#include "cstool/proctex.h"
class MyProcTexture : public csProcTexture
{
public:
  MyProcTexture () { }
  virtual ~MyProcTexture () { }
  virtual bool PrepareAnim ();
  virtual void Animate (csTicks current_time);
};

bool MyProcTexture::PrepareAnim ()
{
  if (anim_prepared) return true;
  if (!csProcTexture::PrepareAnim ()) return false;
  ...
  // Do your stuff.
  return true;
}

void MyProcTexture::Animate (csTicks current_time)
{
  g3d->SetRenderTarget (...);
  ...
  g3d->FinishDraw ();
}

To use this procedural texture you must do the following:

 
  MyProcTexture* proctex = new MyProcTexture ();
  if (proctex->Initialize (object_reg))
  {
    iTextureWrapper* txt = proctex->GetTextureWrapper ();
    iMaterialWrapper* mat = engine->CreateMaterial ("mymaterial", txt);
    ...
  }

csProcTexture will make sure that your Animate routine is called when needed. In practice this means that your animate routine will be called AFTER the first time the texture was needed. This is because Animate will change the display (because procedural textures render on screen) so it can't be done while rendering other objects. In general this is not really a problem since typically the material will be needed as soon as only a tiny part of the object is visible and this will only be visible for one frame.

To minimize the impact of this effect you can make sure that the initial contents of the procedural texture is reasonable. You can do that by manually calling Animate for example.

Another way to fix this is by letting your procedural texture subclass set the ‘always_animate’ flag to true. Of course this will make things slower.

Performance Hints

When supported by the hardware, mipmaps are generated for procedural textures. While this improves the display quality it may have a noticeable impact on performance. You can use the CS_TEXTURE_NOMIPMAPS texture flag to disable this behaviour.

iTextureHandle->Blit() performance might differ depending on hardware and data format. For example, NVIDIA hardware is fastest with BGRA data but may suffer greatly when using RGBA data. On the other hand, documentation from ATI's Software Development Kit suggests that modern ATI hardware supports RGBA and BGRA equally well. This means there is no “universal fastest format” for using iTextureHandle->Blit(), albeit for the most widespread graphics chips BGRA seems to be the most practical choice.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

This document was generated using texi2html 1.76.