bw logo

Chapter 22. 3D Engine (Moo)

Moo is a 3D engine using DirectX 9 that provides resource-, object- and device- based services up to, but not including the scene database.

Resource-based services include the generation and management of vertex buffers, index buffers, vertex shaders, pixel shaders, and effects. Textures are compressed and stored automatically. All resources that are not managed by Direct3D are managed by Moo, allowing for large amounts of data moving in and out of use.

Object-based services include a full animation system, skinned bipeds, compound skeletal geometrics, and specialised terrain rendering. Moo exposes the concept of a visual, an important mid-level geometric construct that sits beneath the scene database and greatly simplifies the scene database code.

Device-based services include level-of-detail control over rendering states, encapsulated in materials and shaders. The 3D window is encapsulated as a RenderContext, and provides frames-of-reference in which to render geometrics and store lighting states.

Finally, Moo provides the essential alpha-blended sorted triangle pipeline, a service that unfortunately is still not provided by Direct3D or directly in (most) hardware.

It is important to note that where possible, Moo uses underlying Direct3DX structures such as D3DXMatrix, D3DXVector, and D3DXQuaternion. The DirectX team continually improves the implementation of these mathematical classes, and their functionality often takes advantage of processor specific instructions, such as MMX, SIMD and 3DNow!. It is prudent to leverage the efforts of these engineers.

22.1. Features

Some of the advanced features of Moo are listed below:

  • D3DXEffects vertex and pixel shader support

  • Cubic environment maps

  • Render targets

  • Lighting

  • Normal mapping/bump mapping

  • Terrain

  • Animation

  • Vertex morphing

The following sections describe these features.

22.1.1. D3DXEffects vertex and pixel shader support

Effect files are used extensively in Moo. Most of the rendering pipeline is based around the class EffectMaterial, which implements a way of managing the global values used by the effects, and also the per-instance data for the effects, such as textures, self-illumination values, and specular reflection constants.

The effect files also make it easier to manage pixel and vertex shaders, as they are created together in one file. Using the D3DXEffect format removes much of the complexities of adding new shader effects to the engine and allows rapid prototyping of new visual effects.

22.1.2. Cubic environment maps

Cubic environment maps can be used for some reflections and for normalisation cube maps (used for normal mapping).

22.1.3. Render targets

Render targets are used to create billboard textures. They can also be used in conjunction with the GUI components to display 3D objects in the 2D GUI (for example, for item selection previews).

22.1.4. Lighting

The lighting component of Moo supports three different kinds of lights:

  • Directional lights.

  • Point lights.

  • Spot lights.

Any object can be lit by two directional lights, four point lights and two spot lights. These lights are picked according to an attenuation metric, so that generally the closest lights will be chosen. It is also important to note that the fewer lights used, the faster the execution of the lighting vertex shader will be.

22.1.4.1. Light maps

The class bigworld/src/lib/romp/light_map.cpp is generalised to support both the flora and sky light maps. Light maps are configurable in XML files.

22.1.4.1.1. Flora light map

The flora light map details are specified in flora.xml (for details on this file's grammar, see the document File Grammar Guide's section <flora>.xml) and its location is specified in the file resources.xml (for details on this file, see File resources.xml).

The material tag for flora light map should be system/materials/light_map.mfm (for details on this file's grammar, see the document File Grammar Guide's section .mfm).

The default width/height for the flora light map is 64x64. This is small, but still enough resolution for the projection onto the flora, because its visible area is 100x100 metres.

Definition of flora light map

22.1.4.1.2. Sky light map

The sky light map details are specified in the space's sky.xml file, and its location is specified in the space's space.settings file (for details on this file's grammar, see the document File Grammar Guide's section space.settings.).

The material tag for sky light map should be system/materials/sky_light_map.mfm (for details on this file's grammar, see the document File Grammar Guide's section .mfm).

The default width/height for the sky light map is 512x512. This is quite large because the light map is projected across the whole visible world (usually around 1x1 km).

Definition of sky light map

Note

The sky light map can be disabled via the SKY_LIGHT_MAP graphic setting (for details, see Customising options).

22.1.5. Normal mapping/bump mapping

Normal mapping is used to add surface detail to objects by using per-texel normals baked into a texture. Moo currently supports normal maps for specular and diffuse lighting on dynamically lit objects, and specular lighting on statically lit objects. The current version of the Exporter supports tangent space normal mapping only.

22.1.6. Terrain

Moo takes advantage of the multi-texture, vertex, and pixel shading capabilities of the supported graphics cards. Since it uses a blended 4-layered texturing system for the terrain, Moo utilises the hardware's four texture stages optimally so that most of the terrain can be rendered in just one pass. The terrain also supports self-shadowing from a directional light source.

22.1.7. Animation

Moo supports node-based and vertex-based (morph) animation. Moo can also blend animations together to provide smooth transitions between them.

22.1.8. Vertex morphing

Moo's vertex morphing is suitable for small changes in surfaces, such as facial animation. Morph targets are exported from the content creation package, and controlled through the normal animation system.

Please note that as morph targets are applied in software, extensive use will affect rendering performance.

22.2. Supported video cards

The currently supported graphics cards are as follows:

  • NVIDIA

    GeForce4 series, GeForce FX series, GeForce 6x00 series, GeForce 7x00 series cards and above.

  • ATI

    Radeon 9000 series, and Radeon x000 series of cards.

Any graphics chip that supports at least Hardware Transform and Lighting and two texture stages should work, some with a limited subset of features enabled. These include (but are not limited to):

  • NVIDIA

    GeForce3 series and GeForce GO 4 series cards.

  • ATI

    Radeon 7000 series, Radeon 8000 series, Mobility 8000 and Mobility 9000 series.

22.3. Hardware requirements for special effects

The table below lists the special effects available in Moo, and their hardware requirements:

Special effect Vertex shader version Pixel shader version Texture stages required
Bloom 1.1 1.1 4
Cloud shadows 1.1 - 3
Flora 1.1 - 1
Heat Shimmer 1.1 - 1
Normal mapping 1.1 1.1 4
PyModel Shimmer 1.1 - 1
PyModel stipple 1.1 1.1 4
Entity shadows 2.0 2.0 1
Simulated sub-surface scattering 3.0 3.0 4
Sky Gradient dome 1.1 - 3
Terrain shadows 1.1 1.1 4
Terrain Specular 1.1 1.1 4

Hardware requirements for special effects

22.4. Visual

The Visual class implements the basic renderable objects drawn by the 3D engine. A visual contains a node hierarchy, vertices, indices, and materials used for rendering objects, and it also contains a BSP tree used for collision detection.

The node hierarchy gives the renderable object a frame of reference when rendering objects. Visual uses the EffectMaterial, Primitives, and Vertices classes to render its geometry.

22.5. EffectMaterial

The material system in the BigWorld 3D engine uses D3DXEffects files extensively.

The material system is implemented through the class EffectMaterial, which contains one or more D3DX effects, their overridden values, and information about the collision properties and surface type of the material.

The idea behind the material system is to give as much control as possible to the artists, to allow them to experiment with new rendering techniques without involving programmers.

22.5.1. Format

The format of the EffectMaterial on disk is very simple, having only a handful of sections, and with most of the work done through the .fx file.

22.5.2. Automatic variables/Globals

Automatic variables are used for any variable that is controlled by the engine, such as transforms, lights, camera positions, etc... Automatic variables are exposed to Effect files using variable semantics.

In an Effect file, the automatic variables are defined like below:

<type> <variableName> : <semantic>;

where:

  • <type>

    The variable type (float, bool, texture, etc.).

  • <variableName>

    Name used for the variable in the effect file.

  • <semantic>

    Name exposed to the engine.

The automatic variables are connected to the effect through the class EffectConstantValue. New automatic variables can be added by overriding the EffectConstantValue interface, implementing the operation (), and adding an instance of the new class using EffectConstantValue::set or using a handle returned from EffectConstantValue::get.

The automatic variables set up by Moo::EffectVisualContext are listed below:

  • Ambient (float4)

    Current ambient colour.

  • CameraPos (float3)

    Current camera position in world space.

  • CameraPosObjectSpace (float3)

    Current camera position in object space.

  • DepthTex (texture)

    The depth of the scene, stored encoded in a 32-bit RGBA texture. This is only available when the Advanced Post Processing graphics setting is switched on.

  • DirectionalLightCount (int)

    Number of directional lights.

  • DirectionalLights (DirectionalLights[2])

    Current diffuse directional lights in world space.

  • DirectionalLightsObjectSpace (DirectionalLights[2])

    Current diffuse directional lights in object space.

  • EnvironmentCubeMap (texture)

    Cube map containing a low-resolution dynamic cube map of the environment (sun, moon, sky gradient dome, sky boxes ).

  • EnvironmentTransform(float4x4)

    Matrix used to transform environmental and skybox objects to the screen. Comes pre-multiplied with the projection matrix.

  • EnvironmentShadowTransform(float4x4)

    Matrix used to transform environmental and skybox objects to the sky light map.

  • FarPlane (float)

    Current far plane in metres.

  • FloraAnimationGrid (float4[64])

    8x8 array of Perlin noise values used to animate the flora vertex buffer.

  • FloraTexture (texture)

    The composite Flora texture map used by the FloraRenderer.

  • FogColour (float4)

    Fog colour.

  • FogEnd (float)

    End of linear fog.

  • FogGradientTexture (texture)

    The fog texture used by the terrain renderer.

  • FogStart (float)

    Start of linear fog.

  • FogTextureTransform (matrix)

    Projects the fog texture onto the terrain.

  • GUIColour (float4)

    Colour for use by the GUI.

  • LastViewProjection (float4x4)

    The last frame's view*projection matrix.

  • InvView (float4x4)

    Current inverse view matrix.

  • InvViewProjection (float4x4)

    Current inverse view*projection matrix.

  • MipFilter (int)

    Configurable MIPFILTER.

  • MinMagFilter (int)

    Configurable MIN/ MAGFILTER.

  • MaxAnisotropy (int)

    Configurable MAXANISOTROPY.

  • NearPlane (float)

    Current near plane in metres.

  • NormalisationMap (texture)

    Normalisation cubemap.

  • ObjectID (float)

    Set to 1 when rendering a PyModel, aka a dynamic/entity model. Set to 0 for all other models. In future, this may expand to designate further groups of objects.

  • PenumbraSize (float)

    Used by the terrain renderer for self-shadowing.

  • PointLightCount (int)

    Number of point lights.

  • PointLights (PointLights[4])

    Current diffuse point lights in world space.

  • PointLightsObjectSpace (PointLights[4])

    Current diffuse point lights in object space.

  • Screen (float4)

    Holds the screen dimension thus : ( width, height, half width, half height )

  • SkyBoxController (float4)

    Holds the current value of the Vector4 that was registered with the sky box currently being rendered. How this variable is interpreted is up to the individual sky box, although the fourth component is generally treated as an alpha value.

  • SpecularDirectionalLightCount (int)

    Number of specular directional lights.

  • SpecularDirectionalLights (DirectionalLights[2])

    Current specular directional lights in world space.

  • SpecularDirectionalLightsObjectSpace (DirectionalLights[2])

    Current specular directional lights in object space.

  • SpecularPointLightCount (int)

    Number of specular point lights.

  • SpecularPointLights (PointLights[2])

    Current specular point lights in world space.

  • SpecularPointLightsObjectSpace (PointLights[2])

    Current specular point lights in object space.

  • SpotLightCount (int)

    Number of spot lights.

  • SpotLights (SpotLights[2])

    Current diffuse spot lights in world space.

  • SpotLightsObjectSpace (SpotLights[2])

    Current diffuse spot lights in object space.

  • StaticLighting (bool)

    Whether static lighting is applied or not.

  • StippleMap (texture)

    Map to be used for the stipple effect.

  • SunAngle (float)

    Used by the terrain renderer for self-shadowing.

  • TerrainTextureTransform (float4[2])

    Projects textures onto the terrain.

  • Time (float)

    Time in seconds since the game started.

  • View (float4x4)

    Current view matrix.

  • ViewProjection (float4x4)

    Current view*projection matrix.

  • WindAnimation (float4)

    Two Vector2's. in (x,y) is a value that can be used for wind-affected texture scrolling. It keeps the incremental value of a single uv coordinate blown around by the wind. in (x,z) is the current wind average speed.

  • World (float4x4)

    Current world matrix.

  • WorldPalette (float4[17*3])

    Matrix palette, made up of the current renderset matrices stored as transposed 4x3 matrices.

  • WorldView (float4x4)

    Current world*view matrix.

  • WorldViewProjection (float4x4)

    Current world*view*projection matrix.

22.5.3. Artist-editable/tweakable variables

Artist-editable variables are variables that are designed to be overridden on a per-material basis. These variables can be edited in World Editor and Model Editor, allowing you to change the look of a model in real time, while visualising it.

The artist-editable variables can be exposed to the engine by setting the attribute artistEditable or worldBuilderEditable to true.

Setting artistEditable to true exposes the variable to Model Editor's Materials Settings panel (for details, see the document Content Tools Reference Guide's section Model Editor Panel summary Materials Settings panel), while setting worldBuilderEditable to true exposes it to both Model Editor and, if the objects/materialOverrideMode tag is set to 1 in bigworld/tools/worldeditor/options.xml (for details on this file's grammar, see the document File Grammar Guide's section options.xml World Editor) file, to World Editor's Properties panel (for details, see the document Content Tools Reference Guide's section World Editor Panel summary Properties panel).

The notation for these variables in a FX file is described below:

<type> <variableName>
<
  bool [artistEditable|worldBuilderEditable] = true;
  ... 1
> = <defaultValue>;

1

Other attribute definitions.

where:

  • <type> — Type of the object.

  • <variableName> — Variable name in the effect file.

  • <defaultValue> — Default value of the variable.

Currently, the supported types of artist-editable variables are:

  • bool

  • float

  • float4

  • float4x4

  • int

  • texture

The conditions to have the variable exposed in either tool are described below:

  • If artistEditable is set to true in the FX file

    Exposed in Model Editor?: Yes

    Exposed in World Editor?: No

  • If worldBuilderEditable is set to true in the FX file

    • If materialOverrideMode is set to 1 in bigworld/tools/ worldeditor/options.xml

      Exposed in Model Editor?: No

      Exposed in World Editor?: No

    • If materialOverrideMode is set to 0 in bigworld/tools/ worldeditor/options.xml

      Exposed in Model Editor?: No

      Exposed in World Editor?: Yes

22.5.4. Multiple-layered effects per material

The Moo::EffectMaterial class supports having multiple-layered D3DXEffects per material.

This is useful for materials that need to use a standard set of vertex shaders, but only have slight changes to the pixel shader component of the effect. These materials would generally only be created by the asset converter, as Model Editor does not support adding more than one effect per material.

22.5.5. Recording material states

Material states can be recorded by class Moo::EffectMaterial by calling the method recordPass() between a begin() and end() pair on the material.

This method returns a Moo::StateRecorder that is used to store the current render states for delayed rendering.

This object only stays valid until the end of the current render loop, and will not be usable after this point.

22.5.6. Using BigWorld .fx files with 3ds Max

BigWorld .fx files and 3ds Max .fx files unfortunately are not 100% compatible. It is however possible to create a .fx file that can be used in both applications.

To expose editable parameters, BigWorld shaders use the annotation below:

bool artistEditable = true;

whereas 3ds Max requires the annotation string below:

UIName="name"

The sample effect file bigworld/res/shaders/std_effects/normalmap.fx exposes its parameters properly to BigWorld and 3ds Max. The exporter also exports the values entered in the 3ds Max shader material panel.

The file normalmap.fx also uses a separate technique, called max_preview, plus additional vertex and pixel shaders.

This is due to two reasons:

  • There is no uniform way to apply the lighting in both the BigWorld engine and 3ds Max.

  • 3ds Max uses a right-handed coordinate system, while BigWorld uses a left-handed one.

In itself this is not a big problem, but it means that additional shader work is required if you want to preview your shaders in 3ds Max.

If you have not applied Service Pack 1for 3ds Max 7, an issue exists in that its Material Panel is very poor at dealing with #include directives in the effect files. What happens is that if you save a material with the effect normalmap applied, then not always it will be properly loaded up again in 3ds Max, which can cause additional confusion for the artists. This problem has been fixed in Service Pack 1, so it is important to apply it if you want to use .fx files in 3ds Max.

It is important to be mindful of these issues before you decide to make your .fx files compatible with 3ds Max.

22.6. Visual channels

The visual channels implement the delayed rendering pipeline in Moo.

There are presently five standard channels implemented:

  • Sorted channel

  • Internal sorted channel

  • Shimmer channel

  • Sorted shimmer channel

  • Distortion channel

An application can create as many channels as it wants by overriding the Moo::VisualChannel interface and implementing VisualChannel::addItem.

The following sub-sections describe these channels.

22.6.1. Sorted channel

The sorted channel is used for objects that need to be rendered in a back-to-front order.

When a primitive group from a visual is added to this channel, its triangles are not sorted internally.

This channel is mostly useful for additive objects, i.e., objects with a destination blend of one.

22.6.2. Internal sorted channel

The internal sorted channel is used for objects that need to be rendered in a back-to-front order, and also have its triangles rendered in a back-to-front order.

Objects that are added to this channel will also be sorted against objects in the sorted channel.

This channel is useful for alpha-blended objects, and any transparent object that does not have a destination blend of one.

22.6.3. Shimmer channel

The shimmer channel is used for objects that need a heat shimmer.

Any object that is added to this channel should only write to the alpha channel of the frame buffer.

22.6.4. Sorted shimmer channel

The sorted shimmer channel is used for objects that need a heat shimmer, and also need to draw colour information.

Any object added to this channel should write to both the alpha channel (for shimmer amount) and colour channel of the frame buffer.

22.6.5. Distortion channel

The distortion channel is used for objects that want direct access to the final scene as a texture. This can be used to achieve effects like refraction (for example, the water).

22.7. Textures

22.7.1. Texture detail levels/compression

Textures are loaded and compressed automatically based on their filenames, which control the size, format conversions, and compression levels.

For details on this file's grammar, see the document File Grammar Guide's section .texformat.

The system is implemented through the class Moo::TextureDetailLevel. The Texture Manager stores a list of texture detail levels and uses them to resize and compress textures based on their filenames. The legacy .texformat system is still supported.

The properties for the TextureDetailLevel are divided into two sets:

  • Filename matching criterion.

  • Conversion rule.

The filename matching criterion set of properties defines the criteria used to check if the current TextureDetailLevel applies to the texture being checked. They are described below:

  • contains_

    Matched strings for a string contained in the texture filename.

  • postFixes_

    Matched strings for the postfixes of the texture filename.

  • preFixes_

    Matched strings for the prefixes of the texture filename.

Only one string from each list of strings has to match the texture name for the TextureDetailLevel to consider it a match. If there are no strings in one of the lists, that will be considered a match as well.

The conversion rule set of properties defines how matching textures will be converted. They are described below:

  • compressedFormat_

    Format to which convert the texture (when texture compression is enabled).AB

  • format_

    The format to convert the texture to.

  • lodMode_

    Defines how texture responds to the texture quality settings.

    Texture quality is set via TEXTURE_QUALITY graphics setting.AB

  • maxDim_

    The maximum width/height dimension of the texture.

  • minDim_

    The minimum width/height dimension of the texture.

  • noResize_

    Determines that the texture will not be scaled to be a power of two, and will not have mipmapping, compression or a .dds version.

  • reduceDim_

    The number of times to halve the dimensions of the texture when compression is disabled.A

A — Texture compression can be toggled via TEXTURE_COMPRESSION graphics setting.B

B — For details, see Graphics settings.

The texture detail level can be read from a datasection, as displayed in the example below:

<prefix>     objects/ </prefix>
<postfix>    tga      </postfix>
<postfix>    bmp      </postfix>
<contains>   norms    </contains>
<contains>   normals  </contains>
<maxDim>     512      </maxDim>
<minDim>     128      </minDim>
<reduceDim>  1        </reduceDim>
<format>     A8R8G8B8 </format>

Example texture detail level format

The example above results in any texture loaded from a sub-tree of folder objects/ with the extension .tga or .bmp and that contains the string norms or normals to have its dimensions reduced by half once, as long as the smallest dimension does not fall below 128. If the format is different, it will be changed to a 32-bit colour with alpha.

The default detail levels are:

  • Any file with a filename ending in norms.tga or norms.bmp will be converted to an A8R8G8B8 texture (so as to not compress BigWorld's normal maps).

  • Any other .tga file is converted to the DXT3 format.

  • Any other .bmp file is converted to the DXT1 format.

By default textures are only scaled down if their dimensions are bigger than 2048.

22.7.2. Animated textures

Moo supports simple animated textures by texture swapping.

When Texture Manager loads a texture, it will look for a file with the same name as the one being loaded, but with a .texanim extension. If such file is found, then it will be loaded as an animated texture.

The .texanim file is a simple XML file that references a number of textures, contains an animation string and a frames-per-second value.

The format of a .texanim file is described below:

 <frames>  string           </frames>
 <fps>     .f               </fps>
+<texture> TEXTURE_RESOURCE </texture>

File .texanim format

An example of a .texanim file is displayed below:

<frames>  abcdefgh              </frames>
<fps>     10.0                  </fps>
<texture> maps/fx/fx_dirt01.tga </texture>
<texture> maps/fx/fx_dirt02.tga </texture>
<texture> maps/fx/fx_dirt03.tga </texture>
<texture> maps/fx/fx_dirt04.tga </texture>
<texture> maps/fx/fx_dirt05.tga </texture>
<texture> maps/fx/fx_dirt06.tga </texture>
<texture> maps/fx/fx_dirt07.tga </texture>
<texture> maps/fx/fx_dirt08.tga </texture>

Example file .texanim format

In this case, the animating texture will play the fx_dirt textures back in order at a rate of ten frames per second.

You can change the order in which the frames are played back by changing the frames tag . The a in the tag's value refers to the first texture stored in the XML file, b refers to the second texture stored, and so on.

22.7.3. Applying a code-generated texture to a character

To apply a code-generated texture to a model, follow the steps below:

  1. Create an automatic .fx variable (e.g., customTexture).

  2. Update the character's shaders so that they render using the new .fx variable, instead of the diffuseMap property.

  3. You will need a single TextureSetter, which is a Moo::EffectConstantValue. This provides the "current custom texture" to .fx files.

  4. Write a PyFashion that sets up the "current custom texture" when drawing an instance of a PyModel.

  5. Create a Moo::BaseTexture that wraps the custom texture creation process.

22.7.3.1. Loading textures from disk

When loading texture from disk, it is recommended to have the loading thread running in the background, so that it does not interrupt the rendering thread.

The example below illustrates a texture loader using the BackgroundTask and BGTaskManager classes. Note that the code provides two features — threaded texture loading, and providing the texture to the .fx file system.

#include "pch.hpp"
#include "cstdmf/bgtask_manager.hpp"
#include "cstdmf/concurrency.hpp"

DECLARE_DEBUG_COMPONENT2( "romp", 0 );

// -------------------------------------------------------------------------
// Section: Texture Setter
// -----------------------------------------------------------------------
/**
 *  This class sets textures on the device.  It is also multi-threaded.
 *  When it is told to use a new texture, it uses the background loading thread
 *  to do so.  While it is doing this, the textureName refers to the new
 *  texture, but isLoading() will return true.  And in this state, it will be
 *  sneakily using the pre-existing texture until the new one is ready.
 */
class ThreadedTextureSetter : public Moo::EffectConstantValue
{
public:
  ThreadedTextureSetter():
    pTexture_( NULL ),
    bgLoader_( NULL ),
    textureName_( "" )
  {    
  }
  /**
   *  This method is called by the effect system when a material needs
   *  to draw using a texture with the given automatic semantic.
   */
  bool operator()(ID3DXEffect* pEffect, D3DXHANDLE constantHandle)
  {
    SimpleMutexHolder holder( mutex_ );

    if (pTexture_ && pTexture_->pTexture())
      pEffect->SetTexture(constantHandle, pTexture_->pTexture());
    else
      pEffect->SetTexture(constantHandle, NULL);

    return true;
  }

  /**
   *  This method sets our texture.  If the texture is different then
   *  the existing one, we schedule the new one for loading, and set
   *  the textureName and the isLoading() flag.  In an unspecified amount
   *  of time, the new texture will be loaded and used.
   */
  void texture( const std::string& texName )
  {
    if (textureName_ == texName)
      return;
    
    if (this->isLoading())
      return;
    
    textureName_ = texName;    
    
    bgLoader_ = new BackgroundTask(
            &ThreadedTextureSetter::loadTexture, this,
            &ThreadedTextureSetter::onLoadComplete, this );

#ifndef EDITOR_ENABLED
    BgTaskManager::instance()->addTask( *bgLoader_ );
#else
    ThreadedTextureSetter::loadTexture( this );
    ThreadedTextureSetter::onLoadComplete( this );
#endif
  }

  /**
   *  This class-static method is called by the background loading thread
   *  and allows us to load the texture resource in a blocking manner.
   */
  static void loadTexture( void* s )
  {
    ThreadedTextureSetter* setter = static_cast<ThreadedTextureSetter*>(s);
    Moo::BaseTexturePtr pTex = 
      Moo::TextureManager::instance()->get( setter->textureName() );
    setter->pTexture(pTex);
  }

  /**
   *  This class-static method is called when the background loading thread
   *  has finished.
   */
  static void onLoadComplete( void* s )
  {
    ThreadedTextureSetter* setter = static_cast<ThreadedTextureSetter*>(s);
    setter->onBgLoadComplete();
  }

  /**
   *  This method returns the name of the texture we are currently
   *  drawing with.  If isLoading() is true, then the textureName
   *  refers to the texture we would like to draw with (however we
   *  will be actually drawing with the previous texture ptr).
   */
  const std::string& textureName() const
  {
    return textureName_;
  }

  /**
   *  This method returns true if we are currently waiting for the
   *  background loading thread to load our texture.
   */
  bool isLoading()
  {
    SimpleMutexHolder holder( mutex_ );
    return (bgLoader_ != NULL);
  }

private:
  //only called by the background loading thread
  void pTexture( Moo::BaseTexturePtr pTex )
  {    
    SimpleMutexHolder holder( mutex_ );
    pTexture_ = pTex;    
  }

  //only called by the background loading thread
  void onBgLoadComplete()
  {
    SimpleMutexHolder holder( mutex_ );
    delete bgLoader_;
    bgLoader_ = NULL;
  }

  Moo::BaseTexturePtr pTexture_;
  std::string textureName_;  //store a copy for use while loading.
  BackgroundTask* bgLoader_;  
  SimpleMutex    mutex_;
};

Example of texture loader

22.7.3.2. Manipulate individual pixels within a texture

To manipulate pixel within a code-generated texture, there are at least two available options:

  1. Create the texture in the managed pool

    This way there will be a system memory copy and a video memory copy. You can then lock the texture and manipulate it as needed — DirectX will update the changes to video memory.

    The only drawback to this option is that on some hardware configurations, the system memory texture may be stored swizzled, meaning that the lock operation would have to unswizzle it before you can make changes — a potentially costly lock operation.

    Note that to use the texture, you will need to have mipmaps available, so when performing the lock you will have to either:

    • Update each surface of the texture individually.

      — or —

    • Use stretch rect to supply the mipmap chain from the top surface.

  2. Create the texture in video memory as a render target

    You will have to use shaders to write your changes to the texture.

    The drawback to this method is that if the device is reset, then your changes will be lost. If that happens, you will have to handle the CreateUnmanagedObjects callback (from the DeviceCallback interface) and recreate the custom texture.

    Unfortunately, you cannot just copy the data to system memory, because a CTRL+ALT+DEL will lose the device without giving you a chance to save the video memory data first.

    Note again that to use the texture, you will need to have mipmaps available. So perhaps in this instance you can create a separate mipmap texture in video memory, and use stretch rect to supply the mipmap chain from the source render target. The source render target might be a 'scratch pad' used in building all the custom character textures.

22.7.3.3. Using a shader to build a custom texture

The closest example on how to achieve this is provided by the flora light map, which uses a variation of the terrain shaders to render the lighting information to a render target. For details, see bigworld/src/lib/romp/flora_light_map.cpp.

Note that to use shaders you will need a video memory/render target surface as described in the section above.

22.7.3.4. Dealing with the texture cache

The custom texture is needed to implement the Moo::BaseTexture interface, so that it can add itself to the Texture Manager. However, depending on the following step (applying custom textures to models), you may not even need to use the TextureManager, as it simply provides a 'retrieve texture by name' access to textures.

If you are creating several custom textures for characters, then you may have an internal (hidden) naming scheme, which would result in a minimal benefit for using the texture cache. It may be good enough simply to use smart pointers to handle caching.

22.7.3.5. Assigning custom textures to a model

Assuming that you have one model that you want display many times, each with a unique custom texture, then you will have to implement a class deriving from the PyFashion class.

Such classes are created from Python, assigned to a PyModel instance, and given an opportunity to alter how a shared model renders (i.e., to set the custom texture on the model). The PyFashion class will become the main interface to your scripts, so in Python you can construct the PyFashion instance with the names of the texture you want to combine, and then assign it to a player's model by simply setting the fashion as any named attribute on its PyModel (PyModel::pySetAttribute automatically detects when a fashion is set on itself, and incorporates it into its rendering chain).

To actually set the custom texture on the model, we recommend creating a class deriving from Moo::EffectConstantValue, and that provides the custom texture to .fx files by name. In the .fx files, use the automatic variable semantic (e.g., Texture diffuseMap :customCharacterTexture), instead of the existing artistEditable property.

For an example code on creating a texture setter, see Loading textures from disk.

22.8. Vertex declaration

Vertex declarations are used by Direct3D to map vertex stream data to vertex shaders.

Moo uses the VertexDeclaration class to ease the handling of vertex declarations used by Direct3D. Vertex declarations are stored on disk in XML format and loaded as needed. The vertex declarations stored on disk can be retrieved by calling method VertexDeclaration::get().

By default, the vertex declarations are stored under folder bigworld/res/shaders/ formats.

Two declarations can be combined with VertexDeclaration::combine() as long as the elements of both declarations are mutually exclusive.

22.8.1. File format

The format of the vertex declaration file is described below:

<root>

  +<USAGE> (usage index, optional defaults to 0)

    ?<stream> (strm #, opt, dflt is strm used by the prev elmnt)     </stream>
    ?<offset> (ofst into strm, opt, dflt is nxt ofst aft prev elmnt) </offset>
    ?<type>    (data type, opt, defaults to FLOAT3)                   </type>

   </USAGE>

</root>

Vertex declaration file format

The USAGE tag maps to the enumerated type D3DDECLUSAGE, and its possible values are listed below:

  • POSITION

  • BLENDWEIGHT

  • BLENDINDICES

  • NORMAL

  • PSIZE

  • TEXCOORD

  • TANGENT

  • BINORMAL

  • TESSFACTOR

  • POSITIONT

  • COLOR

  • FOG

  • DEPTH

  • SAMPLE

The data types entered in the type tag map to enumerated type D3DDECLTYPE, and its possible values are listed below:

  • D3DCOLOR

  • DEC3N

  • FLOAT1

  • FLOAT16_2

  • FLOAT16_4

  • FLOAT2

  • FLOAT3

  • FLOAT4

  • SHORT2

  • SHORT2N

  • SHORT4

  • SHORT4N

  • UBYTE4

  • UBYTE4N

  • UDEC3

  • USHORT2N

  • USHORT4N

As an example, the xyznuv_d vertex format is defined like this:

<xyznuv_d.xml>

  <POSITION/> 
  <NORMAL/>
  <TEXCOORD>
    <type>  FLOAT2  </type>
  </TEXCOORD>
  <COLOR>
    <stream> 1         </stream>
    <offset> 0         </offset>
    <type>   D3DCOLOR  </type>
  </COLOR>

</xyznuv_d.xml>

Vertex declaration file xyznuv_d.xml

22.9. Graphics settings

To allow the game client to run as smoothly as possible in the widest range of systems, BigWorld's 3D engine exposes several parameters. These can be tweaked by the player to achieve the optimal balance between visual quality and game responsiveness for his particular hardware configuration.

These parameters are known as graphics settings, and are listed below:

  • FAR_PLANEA

    Available options: FAR, MEDIUM, NEAR Customising options

    Modifies the viewing distance. The viewing distance is defined per space and this graphics option modifies the viewing distance by a factor. The factors and options are configurable in the file bigworld/res/system/data/graphics_settings.xml

  • FLORA_DENSITYA

    Available options: HIGH, MEDIUM, LOW, OFF Customising options

    Sets the density of the flora detail objects by a factor. The factors and options are configurable in the file bigworld/res/system/data/graphics_settings.xml.

  • FOOT_PRINTS

    Available options: ON, OFF

    Toggles footprints on and off.

  • OBJECT_LODA

    Available options: HIGH, MEDIUM, LOW Customising options

    Modifies the relative distance from the camera for LOD transitions by a factor.

  • SHADER_VERSION_CAP

    Available options: SHADER_MODEL_3, SHADER_MODEL_2, SHADER_MODEL_1, SHADER_MODEL_0

    Sets the maximum shader model version available to the engine.

    SHADER_MODEL_0 is disabled if client is running with a graphics card supports Shader Model 1 only. SHADER_MODEL_0 need vertex shader 2.0 capability, no matter it is software or hardware vertex processing. SM1 graphics card such as nVidia TI4400 enables hardware vertex processing but only support vertex shader 1.1, so SHADER_MODEL_0 option can’t be applied.

  • SHADOWS_COUNTA

    Available options: From 1 to maxCount (defined in shadows.xml — for details on this file's grammar, see the document File Grammar Guide's section shadows.xml)

    Sets the number of simultaneously visible dynamic entity shadows.

  • SHADOWS_QUALITY

    Available options: HIGH, MEDIUM,LOW, OFF

    Sets entity shadow quality. HIGH uses a 12-tap filter for shadows, MEDIUM uses a 4-tap filter for shadows, LOW uses a 1-tap filter for shadows and OFF turns shadows off

  • SKY_LIGHT_MAPB

    Available options: ON, OFF

    Toggles the cloud shadows on and off.

  • TERRAIN_SPECULARB

    Available options: ON, OFF

    Toggles terrain specular lighting on and off.

  • TERRAIN_LOD

    Available options: FAR, MEDIUM,NEAR

    Modifies the terrain geo-morphing distances by a factor. The factors and options are configurable in the file bigworld/res/system/data/terrain2.xml

  • TERRAIN_MESH_RESOLUTION

    Available options: HIGH, MEDIUM,LOW

    Selects the terrain resolution to use. HIGH uses the highest available resolution, MEDIUM uses half the available resolution, LOW uses a quarter of the available resolution

  • TEXTURE_COMPRESSIONAC

    Available options: ON, OFF Customising options

    Toggles texture compression on and off

  • TEXTURE_FILTERING

    Available options: ANISOTROPIC_16X, ANISOTROPIC_8X, ANISOTROPIC_4X, ANISOTROPIC_2X, TRILINEAR, BILINEAR, LINEAR, POINT

    Selects texture filtering. Shaders can be modified to take advantage of this setting by using the automatic variables MinMagFilter, MipFilter, and MaxAnisotropy to set the MINFILTER , MAGFILTER, MIPFILTER and MAXANISOTROPY sampler states. For details, see bigworld/res/shaders/speedtree/speedtree.fx.

  • TEXTURE_QUALITYAC Customising options

    Available options: HIGH, MEDIUM, LOW

    Sets texture quality level.

  • SPEEDTREE_QUALITY

    Available options: VERYHIGH, HIGH, MEDIUM, LOW, LOWEST

    Sets the quality of the speedtree rendering. VERYHIGH Enables per-pixel lighting (normal mapped) on all tree parts, HIGH Enables per-pixel lighting (normal mapped) on only the tree branches, MEDIUM Trees use simple lighting, LOW Trees use simple animation and lighting, using the fixed function pipeline.

  • WATER_QUALITY

    Available options: HIGH, MEDIUM, LOW, LOWEST

    Sets the quality of water reflection rendering. HIGH Enables drawing of all object types, MEDIUM Disables drawing of dynamic objects, LOW Disables drawing of dynamic objects and halves the resolution of the render target. LOWEST only renders specular reflections.

  • WATER_SIMULATION

    Available options: HIGH, LOW, OFF

    Sets the quality of the water simulation. HIGH Enables inter-cell water simulation, MEDIUM enables water simulation on a cell by cell basis, OFF turns water simulation off.

  • POST_PROCESSING

    Available options: HIGH, MEDIUM, LOW, OFF

    Sets the default post-processing chain. These are selected from the chains folder, for example : bigworld/res/system/post_processing/chains/high_graphics_setting.xml. If you want to edit the default post-processing then edit the three chain files there. There are two versions of each chain, one version with FXAA and one without, see FXAA_PROCESSING below.

  • FXAA_PROCESSING

    Available options: ON, OFF

    Sets if FXAA (Fast approXimate Anti-Aliasing) is in the post-processing chain.

  • MRT_DEPTH

    Available options: ON, OFF

    Enables creation of the depth texture (exposed to .fx files via the DepthTex semantic.) This enables a variety of advanced post-processing effects such as depth-of-field and depth-fades, as well as the depth-based colouring of the water.

A — Adjustable via configuration files. For details, see Customising options.

B — Requires restart of the client. For details, see Settings that require restarting the client.

C — Delayed setting. For details, see Delayed settings.

22.9.1. Customising options

Although most of these settings have their options determined in the engine, some settings can have their options customised via configuration files.

These settings and their customisation are discussed in the following topics.

22.9.1.1. TEXTURE_QUALITY and TEXTURE_COMPRESSION

Both TEXTURE_QUALITY and TEXURE_COMPRESSION settings are customised by the way of the texture format (.texformat) and detail levels (texture_detail_level.xml) files (for details on this file's grammar, see the document File Grammar Guide's section .texformat).

Lowering the texture quality and using compressed formats helps improving engine performance, by reducing the amount of texture memory required to store them. This means that less data needs to be sent to the graphics card at each frame, ultimately improving frame rate.

TEXURE_QUALITY adjusts the resolution of a texture by preventing its topmost mipmap levels from being loaded. This means that, at the highest level of quality, the texture will be at the same resolution as the original texture map. At medium level, it will be at half its original size, and at a quarter of it at the lowest level of quality.

How many mipmap levels are skipped in each quality level for each texture can be controlled by the lodMode tag in the texture's detailLevel section.

The table below lists the values lodMode can assume, next to the number of mipmaps skipped for each of the texture quality setting levels:

lodMode # of skipped mipmaps
Value Description High quality Medium quality Low quality
1 Normal 0 1 2
2 Low bias 0 1 1
3 High bias 0 0 1

Number of skipped mipmaps per quality setting level/ LOD level

TEXURE_COMPRESSION affects the format in which texture maps are stored in memory. When texture compression is disabled, all textures are stored using the format defined by the format tag in the texture's detailLevel section. When texture compression is enabled, the format defined by the formatCompressed is used. If formatCompressed is not defined for a texture, then format is used, whatever the compression setting is.

Note that there is no restriction to what texture format is used for format or formatCompressed, but for the texture compression setting to yield any significant performance results, formatCompressed should define a texture format that uses less texture memory than its non-compressed format counterpart.

For details on how to setup a texture's level of detail, see Texture detail levels/compression. For details on the configuration file's grammar, see the document File Grammar Guide's section .texformat.

22.9.1.2. SHADOWS_COUNT

SHADOWS_COUNT defines the maximum number of simultaneous dynamic entity shadow casters in a scene.

Shadows are rendered using shadow buffers, thus consuming texture memory. Filling the buffers up at every frame requires rendering the scene again for each shadow caster. Reducing the number of simultaneous dynamic shadow casters reduces the memory requirements and the amount of processing used to update the buffers at every frame.

Value ranges from 1 to value specified in maxCount shadows.xml file, in power of two steps (defined in shadows.xml — for details on this file's grammar, see the document File Grammar Guide's section shadows.xml).

22.9.1.3. FLORA_DENSITY

FLORA_DENSITY defines the size of the vertex buffer used to render the flora detail objects.

Since the flora drawing distance to the camera is fixed, defining the size of the vertex buffer also determines the flora density. Because it uses alpha blending, drawing the flora can negatively influence the frame rendering time, especially on hardware with limited fill rate performance. Reducing the amount of flora rendered at any one time may help improving the frame rate.

Flora density options are defined in <graphics_settings>.xml (for details on this file's grammar, see the document File Grammar Guide's section <graphics_settings>.xml) as a multiplier of the vertex buffer, which actual size is defined per space in <flora>.xml (for details on this file's grammar, see the document File Grammar Guide's section <flora>.xml).

<graphics_settings.xml>

  <flora>
    <option>
      <label>  HIGH </label>
      <value>  1.0  </value>
    </option>

    <option>
      <label>  LOW  </label>
      <value>  0.5  </value>
    </option>

    <option>
      <label>  OFF  </label>
      <value>  0    </value>
    </option>
  </flora>

</graphics_settings.xml>

Example <graphics_settings>.xml — Configuring flora density

22.9.1.4. FAR_PLANE

FAR_PLANE defines the maximum viewing distance when rendering the 3D world.

Decreasing the viewing distance reduces the amount of geometry sent to the rendering pipeline, resulting in higher frame rates.

Because the far plane distance can be defined on a per-space basis (in space.settings file — for details on this file's grammar, see the document File Grammar Guide's section space.settings), FAR_PLANE is actually multiplied by the space's specific far plane value before it is applied to the camera.

Specified in <graphics_settings>.xml (for details on this file's grammar, see the document File Grammar Guide's section <graphics_settings>.xml), the far plane can be configured as in the example below:

<graphics_settings.xml>

  <farPlane>

    <option>
      <value>  1.0     </value>
      <label>  FAR     </label>
    </option>

    <option>
      <value>  0.75    </value>
      <label>  MEDIUM  </label>
    </option>

    <option>
      <value>  0.5     </value>
      <label>  NEAR    </label>
    </option>

  </farPlane>

</graphics_settings.xml>

Example <graphics_settings>.xml — Configuring far plane

22.9.1.5. OBJECT_LOD

OBJECT_LOD defines the relative distance to the camera before LOD transitions occur.

For standard BigWorld models, LOD distances are defined using the Model Editor. Particle Editor is used to set the LOD distance for particle systems (the maximum distance to which the system is still visible). LOD levels and transition distances for SpeedTrees are defined inside SpeedTreeCAD (although they can be overridden by the SpeedTree's XML configuration file, which is specified in resources.xml file's speedTreeXML tag. For details on this file, see File resources.xml).

The OBJECT_LOD setting specify multipliers that will modify those distances during runtime, allowing the user to trade some visual quality for better performance.

The LOD multipliers are defined in <graphics_settings>.xml (for details on this file's grammar, see the document File Grammar Guide's section <graphics_settings>.xml):

<graphics_settings.xml>

  <objectLOD>

    <option>
      <value>  1.0     </value>
      <label>  HIGH   </label>
    </option>

    <option>
      <value>  0.66    </value>
      <label>  MEDIUM  </label>
    </option>

    <option>
      <value>  0.33    </value>
      <label>  LOW     </label>
    </option>

  </objectLOD>

</graphics_settings.xml>

Example <graphics_settings>.xml — Configuring object LOD

22.9.2. Using settings

Upon startup, the client automatically tries to load the graphics settings from disk. All graphics settings are stored in the graphicsPreferences section of the file specified in preferences tag of the file specified in resources.xml's engineConfigXML tag (for details, see File <preferences>.xml). The first time the application is run, and when the graphics card or its driver has changed, the graphics settings will try to auto-detect the most appropriate settings for the device.

Saving, on the other hand, is not performed automatically; it must be controlled from the scripts, using the BigWorld.savePreferences method — it will save both the graphics settings and the video and script preferences.

The game scripts can use the functions BigWorld.graphicsSettings and BigWorld.setGraphicsSettings to query and change the current state of the settings (usually trough a graphical user interface).

22.9.2.1. Auto-detecting settings

Auto-detecting of settings is supported through an xml configuration file specified by the tag graphicsSettingsPresets in resources.xml. This file defines matching criteria to attempt to match a group of settings to a specific device (graphics card). There are three different ways of matching a group of settings to a device. All matching is done against the D3DADAPTER_IDENTIFIER9 structure. The auto-detection itself is performed in the method Moo::GraphicsSetting::init

  • GUID

    Matches a specific device type and driver version to a settings group, this is useful when there are known issues with a certain driver/device pair and you can adjust your graphics settings accordingly

  • VendorID/DeviceID pair

    Matches a specific device type to the settings this is useful when you know the vendor and device id's for a specific device

  • Device description string

    Matches the strings to the device description, all the strings need to match for the setting to be selected

<graphicsPreferences> HIGH <=== Name of the preset, if no name is present, the preset will not appear in the list of settings, 
                                but it will still be used when auto-detecting settings for the graphics card

  <entry> <=== a graphics setting to change 
    <label> CLASSIC_TERRAIN_QUALITY </label> <=== the name of the graphics setting
    <activeOption> 0 </activeOption> <===the selected option
  </entry>

  <GUIDMatch>  01234567.89abcdef.01234567.89abcdef </GUIDMatch>  
    <===  Combined GUID of device and driver version, this is the value from DeviceIdentifier in the 
          D3DADAPTER_IDENTIFIER9 structure saved out using the BigWorld UniqueID class.
          If this value matches, the setting will be used.

  <VendorDeviceIDMatch>
    <VendorID> 4318 </VendorID> <=== the VendorId from D3DADAPTER_IDENTIFIER9
    <DeviceID> 1554 </DeviceID> <=== the DeviceId from D3DADAPTER_IDENTIFIER9
  </VendorDeviceIDMatch> <=== If these two values match the current device, the setting will be selected
                              unless there is a GUIDMatch with the current device

  <DeviceDescriptionMatch> 
    <string> nvidia </string> <=== Any number of strings that will be matched against the 
    <string> 6800 </string> <=== Description property from D3DADAPTER_IDENTIFIER9
  </DeviceDescriptionMatch>  <=== If these values match the current device, the setting will be selected
                                  unless there is a GUIDMatch or VendorDeviceIDMatch with the 
                                  current device

  <defaultSetting> true </defaultSetting> <=== this value is true for the value to be used as the default setting,
                                               the default setting is used when no other settings match.
</graphicsPreferences>

Example <graphics_settings_presets>.xml — Setting up device matches

22.9.2.2. GraphicsPresets class

A simple python graphics presets class is also supplied. This class helps with grouping several graphics settings together so that you can have pre-defined settings for multiple graphics options for a specific level of hardware or performance. The GraphicsPresets class can be found in the folder bigworld/res/scripts/GraphicsPresets.py.

22.9.2.3. Delayed settings

Most settings take effect immediately after calling BigWorld.setGraphicsSettings, but some are just flagged as delayed. That means that after being set they are added to a list of pending settings, and that they will only come into effect when that list gets committed.

This was designed to give the interface programmer a chance to warn the user that processing the new settings may take a while to complete before the client application blocks for a few seconds (currently, there is no support for displaying a progress bar while the settings are being processed).

The following functions allow the scripts to manage the pending settings list:

  • BigWorld.hasPendingGraphicsSettings

  • BigWorld.commitPendingGraphicsSettings

  • BigWorld.rollBackPendingGraphicsSettings

22.9.2.4. Settings that require restarting the client

Some settings are not applied until the client application is restarted. The function BigWorld.graphicsSettingsNeedRestart returns true whenever the client requires a restart for a recently changed setting to take effect.

22.10. Taking Screenshots

The BigWorld client is able to take screenshots and save them to a number of different formats. It does this by retrieving the current content of the back buffer at the time the screenshot operation is called. To take an in-game screenshot, press the PrtScn button, or use the BigWorld.screenShot(extension, name) Python API function.

The default image type, filename prefix, and output location are all configured within the engine_config.xml (see File <engine_config>.xml). The schema for the <screenShot> tag is:

<engine_config.xml>
  ...
    <screenShot>
        <path> relativePath
            <pathBase>  basePathName </pathBase>
        </path>        
        <name> prefixName </name>
        <extension> extension </extension>                
    </screenShot>
  ...
</engine_config.xml>
  • relativePath — This is the output path relative to basePath (outlined below). For example, if relativePath is MY_DOCS, you may want to set this to something like "My Company/Game Name/Screenshots". Leave blank or specify "./" to place directly in basePathName (which is the default behaviour).

  • basePathName — This configures the base output location for the screenshots. This can be one of the following values:

    • EXE_PATH — Screenshots relative to the location of the client executable. This is the default location if none is supplied.

    • CWD — Screenshots will be stored relative to the current working directory. Note that if the working directory changes during runtime, it will save in the new working directory.

    • ROAMING_APP_DATA — Screenshots will be stored relative to the current user's roaming AppData directory. In other words, if the user is on a domain the data will be syncronised with the domain controller when the user logs in and out of Windows.

    • LOCAL_APP_DATA — Screenshots will be stored relative to the current user's local AppData directory.

    • APP_DATA — This is the same as ROAMING_APP_DATA.

    • MY_DOCS — Screenshots will be stored relative to the current user's My Documents directory.

    • MY_PICTURES — Screenshots will be stored relative to the current user's My Pictures directory.

    • RES_TREE — Screenshots will be stored relative to the first resource path found in paths.xml.

    The default value is EXE_PATH.

  • prefixName — Specifies the prefix to use when generating a numbered screenshot. The default value is "shot".

  • extension — Specifies the file format to use when saving the screenshot. This can be one of "bmp", "jpg", "tga", "png" or "dds". The default value is "bmp".

The full path of the generated screenshot will therefore be basePathName/relativePath/prefixName_<sequence>.extension, where <sequence> is a four-digit non-negative integer, padded with leading zeros (e.g., shot_0012.bmp). The screen capture mechanism will not overwrite pre-existing files.

22.10.1. High Resolution Screenshots

Normally the back buffer is the same size as the window or the screen resolution when in full-screen mode. However, when running in windowed mode it is possible to have a back buffer that is larger than the window itself, thus increasing the size of the screenshot.

22.10.1.1. The backBufferWidthOverride watcher

The size of the back buffer can be changed (via Debug (Watchers) Console) by the backBufferWidthOverride watcher.

The values specified to the watcher, and their effect on the back buffer are described below:

  • Watcher's value: 0 (default)

    Resulting dimensions of the back buffer: Same as those of the window (when in windowed mode) or screen (when in full-screen mode).

  • Watcher's value: Between 1 and the maximum surface width (4096 high-end cards)

    Resulting dimensions of the back buffer: Width of the back buffer will be as specified. Height of the back buffer will be the specified width divided by the aspect ratio of the window.

  • Watcher's value: Greater than supported by hardware

    Resulting dimensions of the back buffer: Maximum value supported by the hardware (typically 2048 or 4096). Specified value will be ignored.

22.10.1.2. How to take a high resolution screenshot

To take a high-resolution screenshot

  1. Open engine_config.xml (for details on this file, see File <engine_config>.xml) and check the settings in <supershot> tag. If you have a video card with a large amount of memory you may be able to change hRes to 4096.

  2. Load the space/level and navigate to the place of which you want the screenshot.

  3. Press ctrl+PrtScn to enable high resolution screenshot settings.

  4. Press PrtScn to take a screenshot.

  5. Press ctrl+PrtScn to restore regular render settings.

22.10.1.3. Troubleshooting

The list below describes some errors that you might come across when taking high-resolution screenshots and how to solve them:

  • Back buffer's size did not change to the value that I specified.

    When setting backBufferWidthOverride, client checks if specified size is larger than the hardware can support. If that is the case, then hardware will ignore the specified size and use its maximum (typically 2048 or 4096).

    — or —

    When very large numbers are specified in the Debug (Watchers) Console, parsing may wrap the value. If this is the case of the value specified for backBufferWidthOverride, then it will be set to 0.

  • There is a glow covering the screen.

    Sometimes, limited video memory resources will stop the renderer from allocating some of the buffers that it uses, or from drawing full-screen post-processing.

    This is particularly common when changing to a lower resolution after using a very large one.

    To solve this, you can either:

    • Set buffer to a smaller width (an application restart may also be necessary).

    • Turn off post-processing through the graphics settings

      • Press DEBUG+P to open the Python Console.

      • Type BigWorld.setGraphicsSetting( "POST_PROCESSING", 3 )

  • Changing back buffer's size had no effect when working in full-screen mode.

    When in full-screen mode, the back buffer must always have the same dimensions as the screen resolution — this is a hardware/API limitation.

    Hence, backBufferWidthOverride will always be disabled (value equals 0) when running in full-screen mode.

22.10.1.4. Hardware recommendations

To produce high-resolution screenshots, a very capable video card is necessary — the two key requirements are:

  • Maximum texture resolution

  • Available video memory

DirectX 9 requires 2048 resolution as a minimum, but 4096 is available on nVidia GeForce3+ (7800+ recommended) and ATI 1X800+ series cards. It is recommended that you have a minimum of 256MB video memory when taking screenshots at resolutions in the order of 4096x3072.

22.11. Dynamic Entity Shadows

The client supports two different ways to allow entity models to cast shadows into the scene. The method you choose to use will depend on the target hardware as they differ greatly in cost.

22.11.1. Splodges

This system works by drawing a special "splodge" texture onto the geometry below the feet of the entity model, projected in the direction of the sun (they are only visible while in outside chunks). This is a good low-end solution as they are inexpensive to draw, however they will only provide a crude approximation of a shadow.

Splodges can be added to an entity model by using the PySplodge API. The PySplodge class is a type of attachment, and are attached to the feet of the entity model (one per foot). For example:

>>> lsplodge = BigWorld.Splodge()
>>> rsplodge = BigWorld.Splodge()
>>> model.node( "biped L Toe0" ).attach( lsplodge )
>>> model.node( "biped R Toe0" ).attach( rsplodge )

While all splodges use the same material to draw (this can be configured by modifying the environment/splodgeMaterial section in resources.xml), each PySplodge instance can modify the following parameters:

  • The maximum LOD distance from the camera, after which they are culled. Defaults to 50 metres.

  • The size of the individual splodge.

Note

Since the collision scene is used to determine where to draw a splodge, only solid objects will receive splodge shadows.

An example of splodge shadows

22.11.2. Shadow maps

Entity models can be configured so that they cast a shadow into the scene based on the direction of the sun light, utilising a dynamic shadow map. Each frame the engine will select a set of shadow casting entities closest to the camera, the number of which is configured via the SHADOWS_COUNT graphics setting. For each shadow caster it will render the caster into a texture from the direction of the light and then project this texture into the scene by re-rendering each object that intersects the shadow (using the shadow map as input).

In order to cast shadows, an entity must be explicitly added to the entity shadow manager. Two Python API's are provided:

  • BigWorld.addShadowEntity - this is usually called from the onEnterWorld entity callback.

  • BigWorld.delShadowEntity - this is usually called from the onLeaveWorld entity callback.

Global shadow settings (e.g. shadow map resolution, intensity, and shaders) are configured in the shadows XML file (defined in shadows.xml — for details on this file's grammar, see the document File Grammar Guide's section shadows.xml).

User controllable graphics settings are SHADOWS_COUNT and SHADOWS_QUALITY. See Graphics settings for details.

Note

Shadows will be cast onto terrain, solid models, and flora. Sorted triangles (i.e. translucent objects) will not cast or receive shadows.

Note

Keep in mind that the expense of using entity shadows will increase as the number of rendered shadowed entities increases, so it is recommended to keep the SHADOWS_COUNT setting as low as possible to maintain performance. As such this is not designed to be a general purpose full-scene shadowing system.

An example of dynamic entity shadows