Suggestions for rendering hundreds of cubes more efficiently

Discuss about anything related to the Irrlicht Engine, or read announcements about any significant features or usage changes.
Post Reply
Fred

Suggestions for rendering hundreds of cubes more efficiently

Post by Fred »

Any suggestions for speeding up the rendering of hundreds of test cubes (added using smgr->addTestSceneNode)?

I made a test program that adds 300 cubes and renders them on the terrain - my FPS value dropped by 100fps on my AMD64 + GeForce 2 GTS.

Is there anything I need to do to make this render more efficiently?

Thanks
Guest

Post by Guest »

using opengl or directx ? i experienced more heavy fps dropdowns with opengl because i think in irrlicht it does not use vertex buffers / display lists? direct x does
eXodus
Posts: 320
Joined: Tue Jan 04, 2005 10:07 am
Location: Canada
Contact:

Post by eXodus »

I don't know how much helpful this could be, but you might give a look at Instancing. It is part of DirectX SDK.

Here's the FX file :

Code: Select all

//--------------------------------------------------------------------------------------
// File: Instancing.fx
//
// The effect file for the Instancing sample.  
// 
// Copyright (c) Microsoft Corporation. All rights reserved.
//--------------------------------------------------------------------------------------


//--------------------------------------------------------------------------------------
// Global variables
//--------------------------------------------------------------------------------------
texture g_txScene : TEXTURE;		// texture for scene rendering
float4x4 g_mWorld : WORLD : register(c0); // World matrix for object
float4x4 g_mView : VIEW : register(c4);			// World matrix for object
float4x4 g_mProj : PROJECTION : register(c8);		// World matrix for object

// only used for Constants instancing
float4 g_BoxInstance_Position : BOXINSTANCE_POSITION : register(c13);
float4 g_BoxInstance_Color : BOXINSTANCE_COLOR : register(c14);

// only used for vs_2_0 Shader instancing
#define g_nNumBatchInstance 120
float4 g_vBoxInstance_Position[g_nNumBatchInstance] : BOXINSTANCEARRAY_POSITION : register(c16);
float4 g_vBoxInstance_Color[g_nNumBatchInstance] : BOXINSTANCEARRAY_COLOR : register(c136);

//-----------------------------------------------------------------------------
// Texture samplers
//-----------------------------------------------------------------------------
sampler g_samScene =
sampler_state
{
    Texture = <g_txScene>;
    MinFilter = Linear;
    MagFilter = Linear;
    MipFilter = Linear;
};

//-----------------------------------------------------------------------------
// Name: VS_HWInstancing
// Type: Vertex shader (HW Instancing)
// Desc: This shader computes standard transform and lighting for unlit, texture-mapped triangles.
//-----------------------------------------------------------------------------
void VS_HWInstancing( float4 vPos : POSITION,
					float3 vNormal : NORMAL,
					float2 vTex0 : TEXCOORD0,
					float4 vColor : COLOR0,
					float4 vBoxInstance : COLOR1,
					out float4 oPos : POSITION,
					out float4 oColor : COLOR0,
					out float2 oTex0 : TEXCOORD0 )
{
	//Use the fourth component of the vBoxInstance to rotate the box:
	vBoxInstance.w *= 2 * 3.1415;
	float4 vRotatedPos = vPos;
	vRotatedPos.x = vPos.x * cos(vBoxInstance.w) + vPos.z * sin(vBoxInstance.w);
	vRotatedPos.z = vPos.z * cos(vBoxInstance.w) - vPos.x * sin(vBoxInstance.w);
	
	//Use the instance position to offset the incoming box corner position:
	//  The "* 32 - 16" is to scale the incoming 0-1 intrapos range so that it maps to 8 box widths, covering
	//  the signed range -8 to 8. Boxes are 2 word units wide.
	vRotatedPos += float4( vBoxInstance.xyz * 32 - 16, 0 );
	
	// Transform the position from object space to homogeneous projection space
	oPos = mul( vRotatedPos, g_mWorld );
	oPos = mul( oPos, g_mView );
	oPos = mul( oPos, g_mProj );
	
	// Just copy the texture coordinate & color through
	oTex0 = vTex0;
	oColor = vColor;
}


//-----------------------------------------------------------------------------
// Name: VS_ShaderInstancing
// Type: Vertex shader (Shader Instancing)
// Desc: This shader computes standard transform and lighting for unlit, texture-mapped triangles.
//-----------------------------------------------------------------------------
void VS_ShaderInstancing( float4 vPos : POSITION,
						float3 vNormal : NORMAL,
						float2 vTex0 : TEXCOORD0,
						float vBoxInstanceIndex : TEXCOORD1,
						out float4 oPos : POSITION,
						out float4 oColor : COLOR0,
						out float2 oTex0 : TEXCOORD0 )
{
	// Use the fourth component of the vBoxInstance to rotate the box:
	float4 vBoxInstance = g_vBoxInstance_Position[vBoxInstanceIndex];
	vBoxInstance.w *= 2 * 3.1415;
	float4 vRotatedPos = vPos;
	vRotatedPos.x = vPos.x * cos(vBoxInstance.w) + vPos.z * sin(vBoxInstance.w);
	vRotatedPos.z = vPos.z * cos(vBoxInstance.w) - vPos.x * sin(vBoxInstance.w);
	
	//Use the instance position to offset the incoming box corner position
	//  The "* 32 - 16" is to scale the incoming 0-1 intrapos range so that it maps to 8 box widths, covering
	//  the signed range -8 to 8. Boxes are 2 word units wide.
	vRotatedPos += float4( vBoxInstance.xyz * 32 - 16, 0 );
	
	// Transform the position from object space to homogeneous projection space
	oPos = mul( vRotatedPos, g_mWorld );
	oPos = mul( oPos, g_mView );
	oPos = mul( oPos, g_mProj );
	
	// Just copy the texture coordinate & color through
	oTex0 = vTex0;
	oColor = g_vBoxInstance_Color[vBoxInstanceIndex];
}


//-----------------------------------------------------------------------------
// Name: VS_ConstantsInstancing
// Type: Vertex shader (Constants Instancing)
// Desc: This shader computes standard transform and lighting for unlit, texture-mapped triangles.
//-----------------------------------------------------------------------------
void VS_ConstantsInstancing( float4 vPos : POSITION,
							float3 vNormal : NORMAL,
							float2 vTex0 : TEXCOORD0,
							out float4 oPos : POSITION,
							out float4 oColor : COLOR0,
							out float2 oTex0 : TEXCOORD0 )
{
	// Use the fourth component of the vBoxInstance to rotate the box:
	float4 vBoxInstance = g_BoxInstance_Position;
	vBoxInstance.w *= 2 * 3.1415;
	float4 vRotatedPos = vPos;
	vRotatedPos.x = vPos.x * cos(vBoxInstance.w) + vPos.z * sin(vBoxInstance.w);
	vRotatedPos.z = vPos.z * cos(vBoxInstance.w) - vPos.x * sin(vBoxInstance.w);
	
	// Use the instance position to offset the incoming box corner position
	//  The "* 32 - 16" is to scale the incoming 0-1 intrapos range so that it maps to 8 box widths, covering
	//  the signed range -8 to 8. Boxes are 2 word units wide.
	vRotatedPos += float4( vBoxInstance.xyz * 32 - 16, 0 );
	
	// Transform the position from object space to homogeneous projection space
	oPos = mul( vRotatedPos, g_mWorld );
	oPos = mul( oPos, g_mView );
	oPos = mul( oPos, g_mProj );
	
	// Just copy the texture coordinate & color through
    oTex0 = vTex0;
    oColor = g_BoxInstance_Color;
}


//-----------------------------------------------------------------------------
// Name: PS
// Type: Pixel shader
// Desc: This shader outputs the pixel's color by modulating the texture's
//		 color with diffuse material color
//-----------------------------------------------------------------------------
float4 PS(	float2 vTex0 : TEXCOORD0,
			float4 vColor : COLOR0 ) : COLOR0
{
    // Lookup texture and modulate it with diffuse
    return tex2D( g_samScene, vTex0 ) * vColor;
}


//-----------------------------------------------------------------------------
// Name: THW_Instancing
// Type: Technique
// Desc: Renders scene through Hardware instancing
//-----------------------------------------------------------------------------
technique THW_Instancing
{
    pass P0
    {
        VertexShader = compile vs_2_0 VS_HWInstancing();
        PixelShader  = compile ps_1_1 PS();
        ZEnable = true;
        AlphaBlendEnable = false;
    }
}


//-----------------------------------------------------------------------------
// Name: TShader_Instancing
// Type: Technique
// Desc: Renders scene through Shader instancing (batching)
//-----------------------------------------------------------------------------
technique TShader_Instancing
{
    pass P0
    {
        VertexShader = compile vs_2_0 VS_ShaderInstancing();
        PixelShader  = compile ps_1_1 PS();
        ZEnable = true;
        AlphaBlendEnable = false;
    }
}


//-----------------------------------------------------------------------------
// Name: TConstants_Instancing
// Type: Technique
// Desc: Renders scene through Constants instancing (no batching)
//-----------------------------------------------------------------------------
technique TConstants_Instancing
{
    pass P0
    {
        VertexShader = compile vs_2_0 VS_ConstantsInstancing();
        PixelShader  = compile ps_1_1 PS();
        ZEnable = true;
        AlphaBlendEnable = false;
    }
}
You'll have to fetch the source code by yourself, its 58kb and won't fit here :P
Electron
Posts: 874
Joined: Sun Mar 14, 2004 12:05 am
Location: Massachusetts USA

Post by Electron »

The problem is with the OnPostRender call and the fact that, unless its been changed in a recent version, the world transform is recomputed for every node every frame regardless of whether it has actually moved
You do a lot of programming? Really? I try to get some in, but the debugging keeps me pretty busy.

Crucible of Stars
Fred

Post by Fred »

Sorry, this is for OpenGL only as it's cross platform for Linux and Windows.

Is the OpenGL driver not as uptodate as the DX9 one?

Thanks
William Finlayson
Posts: 61
Joined: Mon Oct 25, 2004 12:11 am

Post by William Finlayson »

It's not really no, but it is improving all the time as Niko seems pretty receptive to contributions to the OpenGL device. If you have any ideas of how to improve the speed then grab the source and start playing :D Render-to-texture and GLSL should hopefully already be in the next release, but if you have any fixes to improve the general speed then post em or send Niko a mail about it. It's a big engine for one guy, and I guess he will be concentrating on bug-fixes and getting all features working rather than making optimisations until 1.0 is out the door.
Midnight
Posts: 1772
Joined: Fri Jul 02, 2004 2:37 pm
Location: Wonderland

Post by Midnight »

just a question why the hell would you want to render hundreds of cubes?
Guest

Post by Guest »

just a question why dont you go the hell away?
Midnight
Posts: 1772
Joined: Fri Jul 02, 2004 2:37 pm
Location: Wonderland

Post by Midnight »

GFXstyLER wrote:just a question why dont you go the hell away?
Because I love you 8)
Fred

Post by Fred »

Why the hell do you have to be such an arrogant jerk all of the time?

It's a prototype for a turn based strategy game. THat's all you need to know.
JonChaos
Posts: 15
Joined: Thu Aug 24, 2006 2:03 pm
Location: Saarland , Germany

Post by JonChaos »

Fred wrote: It's a prototype for a turn based strategy game. THat's all you need to know.
Sadly with this little information its doubtfull that you can get help.

We dont know what you do to the cubes.
We dont know for what they are in your game.
We dont know what kind of textures you use.

So finding out where your problem comes from is nearly impossible.


If you use the cubes for the tilemap my advice would be dont use cubes.

A cube has 6 sides.
In a tilemap you usually see only the one facing up.

That would be 5/6 of the triangles used for 0 effect other than slowing things down.
finger007

Post by finger007 »

lol, JonChaos :)
you revived a thread that is over a year old.
chances are good that Fred sorted it out in the meantime ;)

cheers
Post Reply