Creating Textures

Textures are 2D images that can be applied to the materials that make up a mesh or a mesh instance. For example, the mesh for a door might use a texture image to make it look like wood grain, or the mesh for a wall might use a stone texture.

Setting up a texture

You can create a texture from the contents of an image file on disk, or programmatically by providing the Beast API with the RGBA values for each pixel in the texture.

In order to apply a texture that you create to a mesh instance in a scene, you need to link the texture to a specific input parameter of the shader set up for the material used by that mesh instance. See Creating Physical Materials.

Creating a texture from a file

Beast can read RGB(A) texture data from any of the following file types:

  • BMP
  • DDS (either RGB or RGBA, compressed or uncompressed)
  • EXR
  • HDR
  • JPG
  • PNG
  • TGA
  • TIFF
  • TX
    NOTE:You may be able to significantly increase shading performance by using tiled .tx files created by the maketx utility, which is included in the OpenImageIO toolkit. For more information, see https://sites.google.com/site/openimageio/.

To create a texture from a file:

  1. Create a new ILBTextureHandle.
  2. Call ILBReferenceTexture(). In this function, you provide the path and filename of the source file, and a unique name that should be used to identify the texture in the Beast cache. This unique name may be related to the file name or not.

The source file is copied to the Beast cache and used from there. Once the source is copied to the cache, it is no longer used.

Note that you do not call ILBBeginTexture() or ILBEndTexture() when you create the texture from a file on disk.

For example:

ILBTextureHandle tex;
ILBReferenceTexture(beastManager, _T("MyTextureName"), _T("C:\textures\floor.png"), &tex);

Creating a texture programmatically

When you create a texture programmatically, you provide the color data for each pixel in the texture one-by-one. You start with the pixel at the bottom left corner, and progress upward line by line. In other words, you first provide the bottom horizontal line in the image from left to right; then the next line up starting from the left again; etc.

For each pixel, you can provide a monochrome value, a three-channel RGB color, or a four-channel RGBA color.

You can provide the color of each pixel in either HDR or LDR format.

  • If you use HDR, you must provide each pixel color value as a floating-point number expressed in linear color space.
  • If you use LDR, you must provide each pixel color value as an unsigned char that contains the value expressed in a gamma space. Beast converts your color values to linear color space using an input gamma that you provide (typically the default value of 2.2).

To create a texture programmatically:

  1. Create a new ILBTextureHandle.
  2. Initialize the texture handle and open it for modification by calling ILBBeginTexture(). In your call, you must specify the dimensions of the texture, and an element from the ILBPixelFormat enumeration that determines the type of data that you will be able to record for each pixel.
  3. Call either ILBAddPixelDataHDR() or ILBAddPixelDataLDR() to add the data for the pixels in the image. You can call these functions multiple times to add pixel data in batches; this can be useful if you are working from a source data structure that expresses pixel data in a different order from the order expected by Beast.

    For each pixel, you must add a number of data elements of a type that corresponds to the pixel format you set in your call to ILBBeginTexture(). For example, if you want to set an RGBA colors for each pixel in HDR format (ILB_PF_RGBA_FLOAT), you need to provide four floating-point numbers for each pixel.

  4. When you have added color data for each pixel in the texture, finalize the texture by calling ILBEndTexture(). Once you have finalized the texture, you can no longer modify it, but it will be ready for use in your scenes.

For example:

ILBTextureHandle tex;
ILBBeginTexture(beastManager, "texture1", width, height, ILB_PF_RGBA_BYTE, &tex)
ILBAddPixelDataLDR(tex, pixelDataArray, arrayLength);
ILBEndTexture(tex)

If you need to re-interpret the line order or color values from a source data structure, you can avoid creating a full temporary copy of the texture by adding pixel data in batches using an approach such as this:

ILBTextureHandle tex;
ILBBeginTexture(bm, "texture2", width, height, ILB_PF_RGBA_BYTE, &tex)
// Add data line by line
for(int y = 0; y < height; ++y) {
    // Prepare a scanline of data by looking it up in source data structure
    char* lineData = prepareLine(y);
    // Add a scanline of data
    ILBAddPixelDataLDR(tex, lineData, width);
}
ILBEndTexture(tex)

Thread safety

You can create multiple different textures simultaneously in multiple threads. In addition, multiple threads can find textures in the cache and use them simultaneously. However, only one thread should add pixel data to any given texture at any time; therefore, each texture should be created entirely within a single thread and not split across multiple threads.

Related API functions

API functions related to the creation and setup of textures are declared in the beasttexture.h file.