Axiom To Ogre v1.0 - Axiom : A 3D Rendering Engine in C#

Axiom To Ogre v1.0

From Axiom

Jump to: navigation, search
 Legend 
 Not Started or Tested
 In Progress or Partially Implemented
 Implemented and Compatible ( See notes )
 Can't or Won't Implement

Contents

OGRE v1.0 aka Azathoth

ChangeLog

Resource system revisited more
Image class interface changed more
Material changes more
Particle system changes more
Generic external access to lock and read & write texture data, including sub-surfaces such as mipmap levels and cubemap faces more
Added primitives to work with a volume or image of pixels in memory, scale 1D, 2D, and 3D images with nearest and bilinear filtering, and convert between pixel formats
New demos: DynTex, that demonstrates dynamically changing textures in real time, and VolTex that demonstrates volume rendering and procedurally generated meshes and 3D textures.
HDR rendering more
Allow material colours to track the vertex colours defined in a mesh (diffuse vertexcolours instead of diffuse <r> <g> <b> <a>)
Support MinGW/Cygwin compilation using the autoconf/automake system
GL: allow rendertextures larger than frame buffer dimensions, and in other pixel formats as RenderTextures now use PBuffers
Method renaming: MipMaps is Mipmaps everywhere to be consistent about naming. For example, TextureManager::getDefaultNumMipMaps is now called TextureManager::getDefaultNumMipmaps)
Better support for 3D and compressed textures
Interactive GUI elements removed in favour of CEGui more
D3D9: use best possible filter method supported by hardware for generating Mipmaps, this can improve display quality especially when using trilinear filtering
Texture::blitToTexture and Texture::blitImage removed; Texture::blitToTexture had already been @deprecated for a while and both have been forsaken in favor of the hardware pixel buffer API.more
Support all image types that DevIL can load: bmp, gif, hdr, ico, jpeg, pnm, mng and many more...
Nature plugin and demo have been removed from the OGRE core. All the features of Nature are implemented better in Terrain, so use that or one of the Paged Terrains in ogreaddons. If you want to continue using Nature, pull it from ogreaddons.
Interface to RenderSystem::createWindow and RenderSystem::createRenderTexture cleaned up and made more flexible. See more. Be sure to read this if you are using SetExternalWindowHandle.
GLX, SDL, D3D9: FSAA(Full Scene AntiAliasing) support improved
Pixel formats have been unambigiously defined more
Ogre does not depend on DevIL anymore internally, if you provide your own image loading codecs. In case of windows, just define OGRE_NO_DEVIL and remove OgreIL* from your build system. In case of Linux, use ./configure --disable-devil .
Important: All OGRE C++ macros have been prefixed with OGRE_ . This means that LITTLE_ENDIAN is now OGRE_LITTLE_ENDIAN and Except is now OGRE_EXCEPT. If you use LITTLE_ENDIAN or BIG_ENDIAN anywhere in your program you have to be very careful, as using the old macro name does compile but always evaluates to false.

Porting notes

Resource system revisited

ResourcePtr et al - Resource subclasses should no longer be addressed using raw pointers - use their specialised shared pointers e.g. MaterialPtr, TexturePtr, MeshPtr. You can assign directly to these classes from the more general form ResourcePtr. Remember that ResourcePtr and the specialised versions are reference counted, if you need to pass around temporary copies (e.g. as parameters to methods), use const <whatever>Ptr& to avoid the reference count overhead
Resource deletion - When all user references to a Resource are gone, the resource is still not deleted since the ResourceManager subclass still holds a reference. The Resource will only be deleted once you call one of the ResourceManager::remove methods (e.g. TextureManager::getSingleton().remove(resourceptr)) and all other references to it are gone. ResourceManager holds 'strong' references deliberately to avoid excessive unload/reload behaviour when resources are temporarily unused.
Shutdown - The exception to the reference counting rule is that Ogre forcibly deletes resources at shutdown (this is to avoid shutdown ordering issues with plugin resources). Thus you must destroy your ResourcePtr instances before shutting down Ogre. Failure to do so will result in a crash at shutdown (the location of which in debug mode will make it clear that you made this mistake!) since the shared pointer will try to delete the resource, which will have already been cleaned up at shutdown. This is easy to do if you organise your variable scopes correctly.
Resource Groups - All resources must belong to a resource group. A resource group can be used to load / unload / remove resources in bulk, and resource locations are defined in relation to resource groups, so the group a resource is a member of determines where it looks for files to load itself from. All the load and create methods now take a resource group - you can just use ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME if you don't want to partition your resources into separate groups.
resources.cfg has changed and now uses section headers to identify the association between resource groups and resource locations, e.g. [General].
Resource locations - These are now registered through ResourceGroupManager::addResourceLocation (although the Root passthrough still exists). They can now be added recursively or non-recursively - recursive only affects how searching and indexing is done (ie scripts will be found in subdirectories), resource names must still be fully qualified for uniqueness. Resource locations are associated with resource groups, and no one location should be added to more than one group (since this will cause scripts to be parsed twice)
Manual resources - If you manually create resources, ie by setting up the contents in code rather than loading from a file, you will need to adjust your code structure a little:
You should avoid using 'new' and create resources using the 'create' method of the ResourceManager subclass in question, e.g. TextureManager::getSingleton().create(....).
The code which populates the resource should now be implemented in a subclass of ManualResourceLoader, which is a callback interface used when the resource wishes to (re)load. You pass a pointer to the ManualResourceLoader implementation to the 'create' method noted above. The ManualResourceLoader::loadResource method will be called when the manual resource needs to load; this more formal interface means that unloading / reloading can be done even for manually defined resources.
Script parsing - Script parsing is now more formalised, with a ScriptLoader base class which anyone can override. ScriptLoaders must register themselves with ResourceGroupManager, and must expose the script patterns they are interested in reading. They then get automatically called whenever a resource group is initialised with a list of streams containing files which match their requested patterns.
DataChunk removed, replaced with DataStream - DataChunk used to be used to carry data around regardless of it's source. However, this meant that resources were always fully loaded into memory, which is undesirable if the resource is large and only small parts are needed at once (like a video or audio stream). Now, the resource system returns DataStream objects, or rather DataStreamPtr (reference-counted pointers to DataStream). DataStream only opens a stream on the resource and so is much more lightweight than DataChunk. There are specialised versions of it for reading from different archive sources (including files, zip archives, and memory chunks) but the top-level interface is always the same. If at any point you need to pre-cache a stream, or you wish to wrap a memory area as a stream, you can wrap any existing DataStream or memory buffer in a MemoryDataStream.
Thread safety - by changing OGRE_THREAD_SUPPORT to 1 in OgreConfig.h you can now make the resource system thread safe, and thus load resources in the background. Boost::threads is used to enable this (you'll need it on your path). This feature is still highly experimental.
ResourceGroupListener - you can now register a ResourceGroupListener class which will get called back to announce various resource events, including parsing of scripts, loading of resources, and loading of world geometry. You can use this to write loading screens.
Pre-declaring resources - you can now pre-declare resources through ResourceGroupManager even if the resource manager isn't created yet. This allows you to enumerate all the resources you'll be using and pre-assign them to groups before they are used. This allows you to then load the resources as a group and also to get progress callbacks through the ResourceGroupListener. Pre-declared resources take parameters in a very generalised NameValuePairList and are identified by String resource types (e.g. "Mesh"). When you initialise the resource group, declared resources get instantiated as real (unloaded) resources using the real ResourceManager (which by then must be set up)
ResourceGroupManager::initialiseAllResourceGroups - this method kicks off parsing of scripts for a given resource group, and creates (but doesn't load) any resources that you have pre-declared. You can also initialise individual groups if you want. It's important you do this before you're expecting any scripts to have been parsed. Previously OGRE parsed all scripts on Root::initialise, but it no longer does this to give you more control over the timing, and especially so you can set up loading screens which report the progress of the script loading, even when you choose to have a window automatically created. ExampleApplication has some new hooks to make sure this happens for you, but if you don't use ExampleApplication you'll have to remember to do it.

Image changes

Removed the pixel format information functions on Image (including PF2PS which had been deprecated for a long time). They moved to PixelUtil. Below is a list of pixelformat info calls and their new syntax.

Image::PF2PS -> PixelUtil::getNumElemBytes
Image::getNumElemBytes -> PixelUtil::getNumElemBytes
Image::hasAlpha -> PixelUtil::hasAlpha(m_eFormat)
Image::formatHasFloat -> PixelUtil::isFloat(m_eFormat)
Image::getNumElemBits -> PixelUtil::getNumElemBits

Images now have mipmaps and faces. A cubemap image, for example, has 6 faces, the top, bottom, left, right, front and back face. A normal image only has one. Faces are currently only used to represent cubemap faces, but in the future they could be used for other purposes like animated images (MNG, GIF).

Mipmaps represent subdivisions of the image dimensions into 2, each mipmap is (width/2)x(height/2)x(depth/2) compared to the previous one. A mipmap is used instead of the base image when the object it textures is further away.

Image::getNumFaces() - get the number of faces in this image, usually 1 for a normal image/volume and 6 for a cubemap
Image::getNumMipmaps() - get the number of levels in this image. Most image format don't support custom mipmaps, so this is usually 1 (only the main mip level)
Image::getPixelBox(face,level) - gets the content of a certain mipmap of a certain face as a PixelBox. This can be conviently used to copy the contents to a texture

Material changes

alpha_rejection attribute has moved from texture_unit to pass; this reflects the true location where alpha rejection is done.
Material attributes can now track vertex colours by speficying a combination of 'diffuse vertexcolour', 'specular vertexcolour', 'emissive vertexcolour' and 'ambient vertexcolour'
It is possible to manually define the number of mipmaps generated for a texture inside a material script by spefifying a number or unlimited as last argument for a texture definition. If none is specified, the default is TextureManager::getDefaultNumMipmaps() which defaults to unlimited.

Examples: Define 0 mipmaps (just the base texture)

texture heavyvolume.dds 3d 0

Define unlimited mipmaps for a texture (up to 1x1)

texture crazyfish.jpg 2d unlimited
scene_blend modulate was previously incorrectly translated into 'scene_blend src_colour one_minus_src_colour', when it should have been 'scene_blend dest_colour zero'. This has been corrected, but if you were previously relying on this incorrect behaviour, change your scripts to use 'scene_blend colour_blend' instead, which does what the previous behaviour did.

Particle System changes

ParticleSystem no longer subclasses from BillboardSet. Instead, every ParticleSystem has a linked ParticleSystemRenderer which performs the rendering of the generic particles. By default this is set to an instance of BillboardParticleRenderer for backwards compatibility, but this can be replaced with other renderers to perform alternative particle effects.
All the same parameters apply in particle scripts, except some are now attributes of the renderer instead of attributes of the particle system (e.g. billboard_type). The scripts still work because if an attribute is not matched on the particle system, the renderer is tried instead. The only change to the particle system scripts is that you can now include a 'renderer' attribute, which takes the name of the renderer to use. Renderers (or rather ParticleSystemRendererFactory implementations) are registered by name with ParticleSystemManager, and so plugins can register new particle renderers which can be used with a simple script change.

Custom SceneManager changes

Respect the value of SceneManager::mWorldGeometryRenderQueue Custom SceneManagers which provide world geometry should take note of the new mWorldGeometryRenderQueue member variable. If they are actually adding geometry to the queue they should add it with that render queue ID. If rendering the geometry manually, they should check manually using isRenderQueueToBeProcessed(mWorldGeometryRenderQueue) before rendering their world geometry. This is because users now have the ability to turn render queues off.

Gui / Overlay Changes

GuiElement renamed OverlayElement, GuiContainer renamed OverlayContainer
GuiManager removed and all methods moved to OverlayManager
All 'interactive' GUI features removed - cursors, buttons, scroll bars, editable text widgets etc are all gone. People needing interactive GUIs should use Crazy Eddie's GUI (aka CEGui)
Overlay, OverlayContainer and OverlayElement and their panels, text areas etc continue to work as before for non-interactive overlays

RenderSystem Changes

createWindow has a new syntax. In 0.15.x and before it had a long list of arguments, trying to including everything but the kitchen sink and leaving no place for extensions or platform specific handles. (which had to be passed through hacky inflexible interfaces)

This enourmous function signature has been changed to

virtual RenderWindow:<font color="red" size="4" >◙</font> createRenderWindow(const String &name, unsigned int width, unsigned int height, 
			bool fullScreen, const NameValuePairList :<font color="red" size="4" >◙</font>miscParams = 0) = 0;

miscParams is the new parameter; it is an optional list of name-value pairs describing the desired properties of the new RenderWindow. The possible properties are:

Key Values Default Description
title Any string RenderTarget name The title of the window that will appear in the title bar
colourDepth 16 or 32 desktop depth Colour depth of the resulting rendering window; only applies if fullScreen is set.
left positive integers center on screen Screen x coordinate from left; only applies if fullScreen is not set.
top positive integers center on screen Screen y coordinate from top; only applies if fullScreen is not set.
depthBuffer true, false true Use depth buffer
externalWindowHandle API specific None External window handle, for embedding the OGRE context. For Windows, this is the HWND handle converted to an unsigned integer.
FSAA 0,2,4,6,... 0 Full screen antialiasing factor
displayFrequency 60..200 Desktop frequency Display frequency rate; only applies if fullScreen is set.
vsync true, false false Synchronize buffer swaps to vsync

Parameters that are not recognized by a certain render system or platform are silently ignored, unless stated otherwise.

For example, the code to create a full screen (800x600) render window with vertical synchronisation and 4x FSAA is now:

NameValuePairList misc;
misc["vsync"] = "1";
misc["FSAA"] = "4";
createRenderWindow("My render window", 800, 600, true, &misc);

This makes it easy to provide new features without breaking the API, and is much more readable than that crazy long parameter list.

SetExternalWindowHandle and friends have been removed. The way to do this is now
NameValuePairList misc;
misc["externalWindowHandle"] = StringConverter::toString((size_t)hWnd);
createRenderWindow("My sub render window", width, height, false, &misc);

Passing the externalWindowHandle as string makes it possible to use the same API for all platform window handles, so that embedding GLX ogre can become possible too.

createRenderTexture now has parameters for internal pixel format and texture type. This means that it is possible to create rendertextures in different pixel formats (with and without alpha). Depth-buffer formats and rendering to cubemap faces are still on the todo list.

createRenderTexture also got added a miscParams parameter to be similar in interface to createWindow. No important miscellenous parameters have been defined yet.

PixelFormat changes

The meaning of individual pixel formats (PF_*) inside Ogre was shady to say at least in the past. With this new version, the formats and their memory layout have been nonambigiously defined.

PF_A8R8G8B8 and other formats with bit counts -- These are native endian (16, 24 and 32 bit) integers in memory. This means that an image with format PF_A8R8G8B8 can be seen as an array of 32 bit integers, defined as 0xAARRGGBB in hexadecimal.
PF_BYTE_* -- These formats have one byte per channel, and their channels in memory are organized in the order they are specified in the format name. For example, PF_BYTE_RGBA consists of blocks of four bytes, one for red, one for green, one for blue, one for alpha.
PF_SHORT_* -- These formats have one unsigned short (16 bit integer) per channel, and their channels in memory are organized in the order they are specified in the format name. For example, PF_SHORT_RGBA consists of blocks of four 16 bit integers, one for red, one for green, one for blue, one for alpha.
PF_FLOAT16_* -- These formats have one 16 bit floating point number per channel, and their channels in memory are organized in the order they are specified in the format name. For example, PF_FLOAT16_RGBA consists of blocks of four 16 bit floats, one for red, one for green, one for blue, one for alpha. The 16 bit floats, also called half float) are very similar to the IEEE single-precision floating-point standard of the 32 bits floats, except that they have only 5 exponent bits and 10 mantissa. Note that there is no standard C++ data type or CPU support to work with these efficiently.
PF_FLOAT32_* -- These formats have one 32 bit floating point number per channel, and their channels in memory are organized in the order they are specified in the format name. For example, PF_FLOAT32_RGBA consists of blocks of four 32 bit floats, one for red, one for green, one for blue, one for alpha. The C++ data type for these 32 bits floats is just "float".
PF_DEPTH -- This is a special format defining depth textures. The internal data is not accesible by the CPU, thus unknown and card dependent. This can never be used for images.
PF_DXT[1-5] -- S3TC compressed texture formats, a good description can be found at | Wikipedia

The meaning of the channels R,G,B,A,L and X is defined as

R -- Red colour component, usually ranging from 0.0 (no red) to 1.0 (full red)
G -- Green colour component, usually ranging from 0.0 (no green) to 1.0 (full green)
B -- Blue colour component, usually ranging from 0.0 (no blue) to 1.0 (full blue)
A -- Alpha component, usually ranging from 0.0 (entire transparent) to 1.0 (opaque)
L -- Luminance component, usually ranging from 0.0 (black) to 1.0 (white). The luminance component is duplicated in the R, G, and B channels to achieve a greyscale image
X -- This component is completely ignored

If none of red, green and blue components, or luminance is defined in a format, these default to 0. For the alpha channel this is different; if no alpha is defined, it defaults to 1.

Complete list of pixel formats

This are all of the pixel formats supported by version 1.0.0 of Ogre

Byte formats: PF_BYTE_RGB, PF_BYTE_BGR, PF_BYTE_BGRA, PF_BYTE_RGBA, PF_BYTE_L, PF_BYTE_LA, PF_BYTE_A
Short formats: PF_SHORT_RGBA
Float16 formats: PF_FLOAT16_RGB, PF_FLOAT16_RGBA
Float32 formats: PF_FLOAT32_RGB, PF_FLOAT32_RGBA
8 bit native endian formats: PF_L8, PF_A8, PF_A4L4, PF_R3G3B2
16 bit native endian formats: PF_L16, PF_R5G6B5, PF_B5G6R5, PF_A4R4G4B4, PF_A1R5G5B5
24 bit native endian formats: PF_R8G8B8, PF_B8G8R8
32 bit native endian formats: PF_A8R8G8B8, PF_A8B8G8R8, PF_B8G8R8A8, PF_R8G8B8A8, PF_X8R8G8B8, PF_X8B8G8R8, PF_A2R10G10B10 PF_A2B10G10R10
Compressed formats: PF_DXT1, PF_DXT2, PF_DXT3, PF_DXT4, PF_DXT5

New features

HDR rendering

Create a renderTexture with floating point pixelformat (see below) to do rendering to a floating point texture, or use .hdr/.exr textures to load them from disk. It is possible to load textures in hdr format (if your devil version supports it) or exr (if you build the exr codec).

The new floating point pixel formats are:

'PF_FLOAT16_RGB' -- 16 bit floats, red green and blue elements
'PF_FLOAT16_RGBA' -- 16 bit floats, red green, blue and alpha elements
'PF_FLOAT32_RGB' -- 32 bit floats, red green and blue elements
'PF_FLOAT32_RGBA' -- 32 bit floats, red green, blue and alpha elements

Also, a new fixed point pixel format was added:

'PF_SHORT_RGBA' -- 16 bit ints, red green, blue and alpha elements

The 16 bit floats, also called half float) are very similar to the IEEE single-precision floating-point standard of the 32 bits floats, except that they have only 5 exponent bits and 10 mantissa.

Hardware Pixel Buffers

Hardware pixel buffers are a new addition that, like vertex buffers and index buffers, represents a resource that is stored by the rendering API, most probably on the graphics card. Like vertex buffers represent a list of rendering primitives, a pixel buffer represents a 1D, 2D or 3D block of pixels in "foreign" memory. This is very useful because the task of a graphics card is doing interesting things with blocks of pixels. Now these that primitives are abstracted it is possible to read and write their contents in an efficient, straightforward way. Such a method is mandatory for dynamic texturing, for example playback of movies on a texture. Like the other types of HardwareBuffers, HardwarePixelBuffer implements lock and unlock methods. These can be used to gain temporary direct access to them from a program. The entire buffer can be locked or only a subset of it, in case only part of it is updated.

The following methods are defined on the HardwarePixelBuffer interface

lock(lockBox, options) - Lock a subregion of this buffer or the entire buffer. A PixelBox is returned that contains the data pointer and information about the locked region like the extents and pixel format.
lock(lockBox) - Lock the entire buffer. To remain compatible with the parent class HardwareBuffer, it only returns a pointer. To get the information about the locked region use getCurrentLock
getCurrentLock() - Get information about the locked region like the extents and pixel format. This is the same information as returned by the first lock method.
unlock() - Unlock the buffer again, so that it can be returned to the card
blit(srcBox, dst, dstBox) - Copies a box from this PixelBuffer to a region of the destination PixelBuffer. Only call this function when both buffers are unlocked.
blitFromMemory(src, dstBox) - Copies a region from normal memory to a region of this pixelbuffer. The source image can be in any pixel format supported by OGRE, and in any size. Automatic scaling is done if needed. The dstBox parameter is optional, if it is not provided the source image will span the entire buffer.
blitToMemory(srcBox, dst) - Copies a region of this pixelbuffer to normal memory. Like blitFromMemory, automatic scaling and pixel format conversion is done if the destination PixelBox has a different type or dimensions from the hardware surface.

A demo DynTex has been added to show a subset of these features.

Deprecation of Texture::blitToTexture and Texture::blitImage

NOTE: make sure you create dynamic textures with the TU_DYNAMIC_WRITE_ONLY usage ( TextureManager::getSingleton().createManual("DynaTex",..., TU_DYNAMIC_WRITE_ONLY) ), otherwise severe performance issues might occur.

Texture::blitToTexture should be replaced in the following way

Old:

tex->blitToTexture( const Image &src, unsigned uStartX, unsigned uStartY );

New:

// Copy the first mipmap of the first cubemap face from the image to the texture
// By default, TU_AUTOMIPMAP is enabled on textures so this is enough to generate sub mip levels
// as well.
tex->getBuffer()->blitFromMemory(src.getPixelBox());

Texture::blitImage should be replaced in the following way

Old:

tex->blitImage( const Image& src, 
            const Image::Rect imgRect, const Image::Rect texRect );

New:

// Copy the first mipmap of the first cubemap face from the image to the texture
// By default, TU_AUTOMIPMAP is enabled on textures so this is enough to generate sub mip levels
// as well.
// Copy the area bounded by imgBox in the image to the area bounded by texBox in the 
// texture surface.
PixelBox region = src.getPixelBox();

tex->getBuffer()->blitFromMemory(region.getSubVolume(imgBox), texBox);

Note that you should use a Box structure to supply the region now, instead of an Image::Rect. A Box is constructed just like a Image::Rect, with optional front and back parameters for volume textures.

Views
Powered by MediaWiki GNU Free Documentation License 1.2