Material properties configuration

1. Usage

You can configure material properties using an XML file. This is useful to configure behavior that is naturally dependent on a given material or texture. Right now this allows to define things like:

  • footsteps,
  • toxic ground (hurts player),
  • bump mapping,
  • texture GPU-compressed alternatives, and downscaled alternatives.

See TMaterialProperties docs.

In code, you have to load this file like this:

uses ..., CastleMaterialProperties;
 
...
MaterialProperties.URL := ApplicationData('material_properties.xml');

It's usually best to do it as early as possible, for example at the beginning on Application.OnInitialize (if you use CastleWindow) or TForm.OnCreate (if you use CastleControl in Lazarus).

2. Example material_properties.xml file

This is a sample material_properties.xml file with links to documentation for every attribute.

<?xml version="1.0"?>

<properties>
  <!--
    Contains a list of <property> elements.
    Only the "texture_base_name" attribute is required, and it must be unique.
  -->

  <property
    texture_base_name="test_texture"
    footsteps_sound="">
    <toxic>
      <damage
        const="0.0"
        random="0.0"
        time="0.0" />
    </toxic>
  </property>

  <property
    texture_base_name="test_texture_2"
    normal_map="test_normal_map.png"
    alpha_channel="TEST" />

  <!-- You can use as many <property> elements as you like... -->

  <!-- Automatically compressed and downscaled texture rules are defined below.
       See the description below. -->
  <auto_generated_textures>
    <compress>
      <!-- Automatically compressed texture formats.
        Format names are the same as TTextureCompression enum names
        (without leading "tc").
        Two most common RGBA compressions for mobiles are listed below. -->
      <format name="Pvrtc1_4bpp_RGBA"/>
      <format name="ATITC_RGBA_InterpolatedAlpha"/>
    </compress>

    <!-- Automatically downscaled texture versions.
        Value smallest="1" is the default, it means that no downscaling is done.
        Value smallest="2" says to generate downscaled
        versions (of uncompressed, and all compressed formats)
        of size 1/2. -->
    <scale smallest="1" />

    <!-- Rules that determine which textures are automatically
         compressed and downscaled, by including / excluding appropriate paths. -->

    <include path="spells/*" recursive="True" />
    <include path="castles/*" recursive="True" />
    <include path="player.png" />

    <exclude path="*.jpg" />
    <exclude path="spells/gui/*" />
    <exclude path="*/gui_hud.png" />
  </auto_generated_textures>

  <!-- You can use as many <auto_generated_textures> elements as you like,
       to specify different properties (compression, downscaling) for different
       texture groups.

       Just make sure that no image falls into more than one <auto_generated_textures>
       group (use include/exclude to make the groups disjoint).
       You will get a clean warning in case it happens, so don't worry:) -->
</properties>

3. How does the automatic texture compression work

Textures inside folders mentioned in <auto_generated_textures> will have GPU-compressed alternative versions automatically generated. This allows to easily reduce the GPU texture memory usage, which is especially crucial on mobile devices. The compressed textures should be distributed as part of your application, and at runtime we will automatically load a suitable GPU-compressed alternative version (that can be used on the current device).

  1. Running castle-engine auto-generate-textures will generate the GPU-compressed (and optionally scaled down) counterparts. See the castle-engine build tool documentation. They will be generated inside the auto_generated subdirectories of your data files.

    This process underneath may call various external tools:

    • nvcompress from NVidia Texture Tools. Cross-platform (Windows, Linux...), free and open source. On Debian and derivatives (like Ubuntu) install them simply by sudo apt-get install libnvtt-bin.

    • PVRTexToolCLI from PowerVR Texture Tools. Cross-platform (Windows, Linux...), free to download. Include both command-line and GUI tools to convert and view image files.

    • ATI Compressonator

      On non-Windows, it can be run under Wine You will need to do "winetricks vcrun2005" first. Installing it is troublesome under Wine, but a working installed dir can be copied from your Windows installation.

    • Not used for now: AMDCompressCLI from AMD Compress

      We have it implemented, but it's broken unfortunately, so it's disabled by default. Messes up colors in ATITC* texture compression modes. Also, on non-Windows, running in under wine is even more troublesome than running ATI Compressonator... Please send complaints to AMD, maybe one day they'll release a tool that can correctly compress to ATITC*, from command-line, and is cross-platform.

      Update on 2017-08: Possibly things are better now: AMD Compress is now open-source. It is available on GitHub. See new AMD Compress page.

      It is still Windows-only, but possibly it's working better now. TODO: someone needs to check the latest version of AMD Compress.

  2. In game, trying to load an uncompressed texture URL will automatically load the GPU-compressed version instead, if the GPU compression is supported. Just load the material_properties.xml (setting MaterialProperties.URL) early in your code.

This workflow allows to easily enable GPU texture compression in your games, and work even when the GPU texture compression algorithm is not supported by the given device. Very useful on Android, with the price: you should distribute all compression variants.

Note that some GPU compression algorithms have particular limitations. They often require your texture to have a "power of two" size, some even require it to be square (PVRTC1 on Apple devices — blame Apple here). We do not forcefully resize your texture, as it could break your texture coordinates. Instead, we require your textures to already have the necessary size. Usually, the compression is OK for 3D textures and texture atlases (as they are usually created already with power-of-2 sizes), but not OK for GUI images. Use the <include> / <exclude> elements to select only the sensible subset of your data textures. Include / exclude work just like including / excluding data to package inside the CastleEngineManifest.xml. We first include matching files, then exclude matching.

4. How does the automatic downscaling work

If you use the <scale> element in the <auto_generated_textures> group, we will generate alternative downscaled versions of the textures. The castle-engine auto-generate-textures call with generate them, using a high-quality scaling algorithm.

These textures will be automatically used if you set the global TextureLoadingScale variable in your code.

The attribute smallest of the <scale> element is interpreted analogous to TextureLoadingScale variable, so

  • <scale smallest="1" /> (default) means that no downscaling actually occurs,
  • <scale smallest="2" /> means that textures are scaled to 1/2 of their size,
  • <scale smallest="3" /> means that each size is scaled to 1/4 and so on.

The advantages of downscaling this way:

  • For uncompressed textures, this downscaling is high-quality.

    Unlike the fast scaling at run-time which is done by GLTextureScale. Note that the runtime scaling can still be performed by GLTextureScale, if you set it. The effects of TextureLoadingScale and GLTextureScale cummulate.

  • For compressed textures, this is the only way to get downscaled texture versions that can be chosen at runtime. We cannot downscale compressed textures at runtime, so GLTextureScale has no effect on compressed textures.