@c -*-texinfo-*-
@node ProcTextures, , Sequence Manager, Animation
@subsection Procedural Texture System
@cindex Procedural Texture System
@cindex @code{SetRenderTarget}
@cindex @code{csProcTexture}

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.

@subsubheading Updating a Texture Image with 2D and 3D graphics
@cindex @code{SetRenderTarget()}

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

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

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.

@code{SetRenderTarget} also has a second parameter which is called
@samp{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 @samp{persistant} to true is slower if you intend
to update the entire texture area anyway.

@subsubheading Updating a Texture Image with @sc{rgba} Pixel Data
@cindex @code{Blit()}

Another way to realize procedural textures is to use the function 
@code{iTextureHandle->Blit()} which can copy a @sc{rgba} or @sc{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.

@subsubheading Using csProcTexture
@cindex @code{csProcTexture}

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

@example
#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;
  @dots{}
  // Do your stuff.
  return true;
@}

void MyProcTexture::Animate (csTicks current_time)
@{
  g3d->SetRenderTarget (@dots{});
  @dots{}
  g3d->FinishDraw ();
@}
@end example

To use this procedural texture you must do the following:

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

@code{csProcTexture} will make sure that your @code{Animate} routine
is called when needed.  In practice this means that your animate routine
will be called @sc{after} the first time the texture was needed.  This is
because @code{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 @code{Animate} for example.

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

@subsubheading 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 @code{CS_TEXTURE_NOMIPMAPS} texture flag to 
disable this behaviour.

@code{iTextureHandle->Blit()} performance might differ depending on hardware
and data format.  For example, @sc{nvidia} hardware is fastest with @sc{bgra}
data but may suffer greatly when using @sc{rgba} data.  On the other hand,
documentation from @sc{ati}'s Software Development Kit suggests that modern
@sc{ati} hardware supports @sc{rgba} and @sc{bgra} equally well.  This means
there is no ``universal fastest format'' for using 
@code{iTextureHandle->Blit()}, albeit for the most widespread graphics chips
@sc{bgra} seems to be the most practical choice.
