//
// DepthBlurPlugin.cpp
//
// Depth Blur Plugin
//
// Copyright (c) 2000 memon/moppi productions
//

//#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <windows.h>
#include <gl\gl.h>
#include <gl\glu.h>
#include <stdio.h>
#include "glext.h"

#include "extgl.h"

// Demopaja headers
#include "DemopajaVersion.h"
#include "PajaTypes.h"
#include "ClassDescC.h"
#include "ImportableI.h"
#include "OpenGLDeviceC.h"
#include "OpenGLViewportC.h"
#include "GlarePlugin.h"
#include "FileIO.h"
#include "AutoGizmoC.h"
#include "ImportableImageI.h"
#include "PBufferC.h"
#include "EffectMaskI.h"

using namespace PajaTypes;
using namespace PluginClass;
using namespace PajaSystem;
using namespace Edit;
using namespace Composition;
using namespace Import;
using namespace FileIO;

using namespace DepthBlurPlugin;


// stuff from GlarePlugin.cpp

#define			CAPTURE_OFFSET	1


static
void
TRACE( const char* szFormat, ...  )
{
	char	szMsg[256];
	va_list	rList;
	va_start( rList, szFormat );
	_vsnprintf( szMsg, 255, szFormat, rList );
	va_end( rList );
	OutputDebugString( szMsg );
}

static
bool
CHECK_GL_ERROR( const char* szName )
{
	GLenum	eError = glGetError();
	if( eError ) {
		OutputDebugString( szName );
		OutputDebugString( " " );
		OutputDebugString( (const char*)gluErrorString( eError ) );
		OutputDebugString( "\n" );
		return true;
	}
	return false;
}


inline
uint32
lowest_bit_mask( uint32 v )
{
	return (v & -v);
}

static
uint32
ceil_power2( uint32 ui32Num )
{
	uint32	i = lowest_bit_mask( ui32Num );
	while( i < ui32Num )
		i <<= 1;
	return i;
}



//////////////////////////////////////////////////////////////////////////
//
//  depth blur effect class descriptor.
//

DepthBlurDescC::DepthBlurDescC()
{
	// empty
}

DepthBlurDescC::~DepthBlurDescC()
{
	// empty
}

void*
DepthBlurDescC::create()
{
	return (void*)DepthBlurEffectC::create_new();
}

int32
DepthBlurDescC::get_classtype() const
{
	return CLASS_TYPE_EFFECT;
}

SuperClassIdC
DepthBlurDescC::get_super_class_id() const
{
	return SUPERCLASS_EFFECT;
}

ClassIdC
DepthBlurDescC::get_class_id() const
{
	return CLASS_DEPTHBLUR_EFFECT;
}

const char*
DepthBlurDescC::get_name() const
{
	return "Depth Blur";
}

const char*
DepthBlurDescC::get_desc() const
{
	return "Depth Blur Effect";
}

const char*
DepthBlurDescC::get_author_name() const
{
	return "Mikko \"memon\" Mononen";
}

const char*
DepthBlurDescC::get_copyright_message() const
{
	return "Copyright (c) 2003 Moppi Productions";
}

const char*
DepthBlurDescC::get_url() const
{
	return "http://moppi.inside.org/demopaja/";
}

const char*
DepthBlurDescC::get_help_filename() const
{
	return "res://GlareHelp.html";
}

uint32
DepthBlurDescC::get_required_device_driver_count() const
{
	return 1;
}

const ClassIdC&
DepthBlurDescC::get_required_device_driver( uint32 ui32Idx )
{
	return PajaSystem::CLASS_OPENGL_DEVICEDRIVER;
}


uint32
DepthBlurDescC::get_ext_count() const
{
	return 0;
}

const char*
DepthBlurDescC::get_ext( uint32 ui32Index ) const
{
	return 0;
}


//////////////////////////////////////////////////////////////////////////
//
// Global descriptors, which will be returned to the Demopaja.
//

DepthBlurDescC	g_rDepthBlurDesc;

//////////////////////////////////////////////////////////////////////////
//
// The Depth Blur effect
//

DepthBlurEffectC::DepthBlurEffectC() :
	m_i32TexCapturedWidth( 0 ),
	m_i32TexCapturedHeight( 0 )
{
	//
	// Create Transform gizmo.
	//
	m_pTraGizmo = AutoGizmoC::create_new( this, "Transform", ID_GIZMO_TRANS );

	m_pTraGizmo->add_parameter(	ParamVector2C::create_new( m_pTraGizmo, "Position", Vector2C(), ID_TRANSFORM_POS,
						PARAM_STYLE_EDITBOX | PARAM_STYLE_ABS_POSITION, PARAM_ANIMATABLE ) );
	
	m_pTraGizmo->add_parameter(	ParamVector2C::create_new( m_pTraGizmo, "Pivot", Vector2C(), ID_TRANSFORM_PIVOT,
						PARAM_STYLE_EDITBOX | PARAM_STYLE_REL_POSITION | PARAM_STYLE_WORLD_SPACE, PARAM_ANIMATABLE ) );
	
	m_pTraGizmo->add_parameter(	ParamVector2C::create_new( m_pTraGizmo, "Scale", Vector2C( 1, 1 ), ID_TRANSFORM_SCALE,
						PARAM_STYLE_EDITBOX | PARAM_STYLE_PERCENT, PARAM_ANIMATABLE, Vector2C(), Vector2C(), 0.01f ) );


	//
	// Create Attributes gizmo.
	//
	m_pAttGizmo = AutoGizmoC::create_new( this, "Attributes", ID_GIZMO_ATTRIB );

	// Blur Near
	m_pAttGizmo->add_parameter(	ParamFloatC::create_new( m_pAttGizmo, "Near", 0.0f, ID_ATTRIBUTE_NEAR,
						PARAM_STYLE_EDITBOX | PARAM_STYLE_PERCENT, PARAM_ANIMATABLE, 0, 1.0f, 0.01f ) );

	// Blur Far
	m_pAttGizmo->add_parameter(	ParamFloatC::create_new( m_pAttGizmo, "Far", 1.0f, ID_ATTRIBUTE_FAR,
						PARAM_STYLE_EDITBOX | PARAM_STYLE_PERCENT, PARAM_ANIMATABLE, 0, 10.0f, 0.01f ) );

	// Blur Amount
	m_pAttGizmo->add_parameter(	ParamFloatC::create_new( m_pAttGizmo, "Opacity", 1.0f, ID_ATTRIBUTE_OPACITY,
						PARAM_STYLE_EDITBOX | PARAM_STYLE_PERCENT, PARAM_ANIMATABLE, 0, 1.0f, 0.01f ) );

	// Blend
	ParamIntC*	pBlendMode = ParamIntC::create_new( m_pAttGizmo, "Blend", 0, ID_ATTRIBUTE_BLEND, PARAM_STYLE_COMBOBOX, PARAM_ANIMATABLE, 0, 5 );
	pBlendMode->add_label( 0, "Normal" );
	pBlendMode->add_label( 1, "Add" );
	pBlendMode->add_label( 2, "Mult" );
	pBlendMode->add_label( 3, "Sub" );
	pBlendMode->add_label( 4, "Lighten" );
	pBlendMode->add_label( 5, "Darken" );
	m_pAttGizmo->add_parameter( pBlendMode );

	// Mask
	m_pAttGizmo->add_parameter(	ParamLinkC::create_new( m_pAttGizmo, "Mask", SUPERCLASS_EFFECT_MASK, NULL_CLASSID,
						ID_ATTRIBUTE_MASK, PARAM_STYLE_SINGLE_LINK ) );


	for( int32 i = 0; i < 5; i++ )
		m_ui32GradientTextures[i] = 0;
}

DepthBlurEffectC::DepthBlurEffectC( EditableI* pOriginal ) :
	EffectBlurI( pOriginal ),
	m_pTraGizmo( 0 ),
	m_pAttGizmo( 0 ),
	m_i32TexCapturedWidth( 0 ),
	m_i32TexCapturedHeight( 0 )
{
	for( int32 i = 0; i < 5; i++ )
		m_ui32GradientTextures[i] = 0;
}

DepthBlurEffectC::~DepthBlurEffectC()
{
	TRACE( "~DepthBlurEffectC()\n" );

	// Return if this is a clone.
	if( get_original() )
		return;

	for( int32 i = 0; i < 5; i++ )
	{
		if( m_ui32GradientTextures[i] )
			glDeleteTextures( 1, &m_ui32GradientTextures[i] );
	}

	// Release gizmos.
	m_pTraGizmo->release();
	m_pAttGizmo->release();
}

DepthBlurEffectC*
DepthBlurEffectC::create_new()
{
	return new DepthBlurEffectC;
}

DataBlockI*
DepthBlurEffectC::create()
{
	return new DepthBlurEffectC;
}

DataBlockI*
DepthBlurEffectC::create( EditableI* pOriginal )
{
	return new DepthBlurEffectC( pOriginal );
}

void
DepthBlurEffectC::copy( EditableI* pEditable )
{
	EffectI::copy( pEditable );

	// Make deep copy.
	DepthBlurEffectC*	pEffect = (DepthBlurEffectC*)pEditable;
	m_pTraGizmo->copy( pEffect->m_pTraGizmo );
	m_pAttGizmo->copy( pEffect->m_pAttGizmo );
}

void
DepthBlurEffectC::restore( EditableI* pEditable )
{
	EffectI::restore( pEditable );

	// Make shallow copy.
	DepthBlurEffectC*	pEffect = (DepthBlurEffectC*)pEditable;
	m_pTraGizmo = pEffect->m_pTraGizmo;
	m_pAttGizmo = pEffect->m_pAttGizmo;
}

int32
DepthBlurEffectC::get_gizmo_count()
{
	// Return number of gizmos inside this effect.
	return GIZMO_COUNT;
}

GizmoI*
DepthBlurEffectC::get_gizmo( PajaTypes::int32 i32Index )
{
	// Returns specified gizmo.
	// Since the ID's are zero based, we can use them as indices.
	switch( i32Index ) {
	case ID_GIZMO_TRANS:
		return m_pTraGizmo;
	case ID_GIZMO_ATTRIB:
		return m_pAttGizmo;
	}

	return 0;
}

ClassIdC
DepthBlurEffectC::get_class_id()
{
	// Return the class ID. Should be same as in the class descriptor.
	return CLASS_DEPTHBLUR_EFFECT;
}

const char*
DepthBlurEffectC::get_class_name()
{
	// Return the class name. Should be same as in the class descriptor.
	return "Depth Blur";
}

void
DepthBlurEffectC::set_default_file( int32 i32Time, FileHandleC* pHandle )
{
	// empty
}

ParamI*
DepthBlurEffectC::get_default_param( int32 i32Param )
{
	// Return specified default parameter.
	if( i32Param == DEFAULT_PARAM_POSITION )
		return m_pTraGizmo->get_parameter( ID_TRANSFORM_POS );
	else if( i32Param == DEFAULT_PARAM_SCALE )
		return m_pTraGizmo->get_parameter( ID_TRANSFORM_SCALE );
	else if( i32Param == DEFAULT_PARAM_PIVOT )
		return m_pTraGizmo->get_parameter( ID_TRANSFORM_PIVOT );
	return 0;
}

void
DepthBlurEffectC::initialize( uint32 ui32Reason, DemoInterfaceC* pInterface )
{
	EffectI::initialize( ui32Reason, pInterface );

	DeviceContextC* pContext = m_pDemoInterface->get_device_context();
	TimeContextC* pTimeContext = m_pDemoInterface->get_time_context();

	OpenGLDeviceC*	pDevice = (OpenGLDeviceC*)pContext->query_interface( CLASS_OPENGL_DEVICEDRIVER );
	if( !pDevice )
		return;

	if( ui32Reason == INIT_INITIAL_UPDATE ) {

		init_gl_extension();

		// Get the OpenGL viewport.
		OpenGLViewportC*	pViewport = (OpenGLViewportC*)pDevice->query_interface( GRAPHICSDEVICE_VIEWPORT_INTERFACE );
		if( !pViewport )
			return;

		init_resources( pViewport->get_width(), pViewport->get_height() );

		// Init range textures

		int32	i;

		for( i = 0; i < 5; i++ )
		{
			// Upload texture
			glGenTextures( 1, &m_ui32GradientTextures[i] );
			glBindTexture( GL_TEXTURE_2D, m_ui32GradientTextures[i] );
			glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
			glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
			glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
			glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
			glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
			glTexImage2D( GL_TEXTURE_2D, 0, GL_ALPHA8, 256, 4, 0, GL_ALPHA, GL_UNSIGNED_BYTE, NULL );
		}

	}
}


void
DepthBlurEffectC::update_range_textures( PajaTypes::float32 f32NearRange, PajaTypes::float32 f32FarRange )
{
		int32	i, j, k;
		uint8	ui8Texture[256 * 4];

		float32	f32BlurNear = f32NearRange * 255.0f;
		float32	f32BlurFar = f32FarRange * 255.0f;

//		TRACE( "near: %f  far: %f\n", f32BlurNear, f32BlurFar );

		for( i = 0; i < 5; i++ )
		{
			int32	i32Start, i32End;

			int32	i32X = 1 << i;

//			i32Start = (int32)((float32)(log( (float32)i32X ) / log( 2.0f )) / 5.0f * (f32BlurFar - f32BlurNear) + f32BlurNear);
//			i32End = (int32)((float32)(log( (float32)(i32X * 2) ) / log( 2.0f )) / 5.0f * (f32BlurFar - f32BlurNear) + f32BlurNear);

			float32	f32A = (float32)i / 5.0f;
			float32	f32B = (float32)(i + 1) / 5.0f;

//			f32A *= f32A;
//			f32B *= f32B;

			i32Start = (int32)(f32BlurNear + f32A * (f32BlurFar - f32BlurNear));
			i32End = (int32)(f32BlurNear + f32B * (f32BlurFar - f32BlurNear));

			if( i32Start < 0 ) i32Start = 0;
			if( i32Start > 255 ) i32Start = 255;

			if( i32End < 0 ) i32End = 0;
			if( i32End > 255 ) i32End = 255;

//			TRACE( "start: %d  end: %d\n", i32Start, i32End );

			for( j = 0; j < i32Start; j++ )
			{
				for( k = 0; k < 4; k++ )
				{
					ui8Texture[(255 - j) + (256 * k)] = 0;
				}
			}

//			if( i32Start < 255 )
			{
				for( j = i32Start; j < i32End; j++ )
				{
					float32	f32Val = (float32)(j - i32Start) / (float32)(i32End - i32Start);
					for( k = 0; k < 4; k++ )
					{
						ui8Texture[(255 - j) + (256 * k)] = (int32)(255.0f * f32Val);
					}
				}

				for( j = i32End; j < 256; j++ )
				{
					for( k = 0; k < 4; k++ )
					{
						ui8Texture[(255 - j) + (256 * k)] = 255;
					}
				}
			}


			// Upload texture
//			glGenTextures( 1, &m_ui32GradientTextures[i] );
			glBindTexture( GL_TEXTURE_2D, m_ui32GradientTextures[i] );
/*			glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
			glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
			glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
			glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
			glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );*/

			CHECK_GL_ERROR( "before\n" );

			glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 256, 4, GL_ALPHA, GL_UNSIGNED_BYTE, ui8Texture );

			CHECK_GL_ERROR( "after\n" );
		}
}


void
DepthBlurEffectC::make_blur_textures()
{
/*	int32	i;

	if( !m_pPBuffer || !m_pPBuffer->is_initialised() )
		return;

	// if multitexture is not supported, die out
	if( !g_bMultiTexture )
		return;

	if( !m_pPBuffer->begin_draw() )
	{
		TRACE( "begin_draw failed\n" );
		return;
	}

	//Setup ortho mode.
	glMatrixMode( GL_PROJECTION );
	glLoadIdentity();
	glOrtho( 0, m_pPBuffer->get_width(), 0, m_pPBuffer->get_height(), -100, 100 );
	glMatrixMode( GL_MODELVIEW );
	glLoadIdentity();

	glEnable( GL_BLEND );

//	glBlendFunc( GL_CONSTANT_ALPHA_EXT, GL_ONE_MINUS_CONSTANT_ALPHA_EXT );
	glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );

	glDisable( GL_DEPTH_TEST );
	glDepthMask( GL_FALSE );

	float32	f32A = 0.5f;

	// the texture mix alpha is in color, and the secand mix alpha is in the alpha
	glColor4f( 1, 1, 1, 0.5f );
	glBlendColor( 1, 1, 1, 0.5f );

	for( i = 0; i < BLUR_TEX_COUNT; i++ ) {		

		int32	i32W = (int32)m_ui32TexWidth >> (i + 1);
		int32	i32H = (int32)m_ui32TexHeight >> (i + 1);

//		TRACE( "w: %d  h: %d\n", i32W, i32H );

		float32	f32OX = 1.0f / (float32)i32W;
		float32	f32OY = 1.0f / (float32)i32H;

		uint32	ui32SrcTex;
		if( i > 0 )
			ui32SrcTex = m_ui32BlurTexId[i - 1];
		else
			ui32SrcTex = m_ui32TexId;

		glActiveTextureARB( GL_TEXTURE0_ARB );
		glEnable( GL_TEXTURE_2D );
		glBindTexture( GL_TEXTURE_2D, ui32SrcTex );
		CHECK_GL_ERROR( "make blur: tex0 color env (bind)\n" );

		glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );


		glActiveTextureARB( GL_TEXTURE1_ARB );
		glEnable( GL_TEXTURE_2D );
		glBindTexture( GL_TEXTURE_2D, ui32SrcTex );
		glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT );

		glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_INTERPOLATE_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_PRIMARY_COLOR_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA );

		glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_INTERPOLATE_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PREVIOUS_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_TEXTURE );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, GL_SRC_ALPHA );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, GL_PRIMARY_COLOR_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA );


		glBlendFunc( GL_ZERO, GL_ZERO );
		glBegin( GL_QUADS );
			glVertex2i( 0, 0 );
			glVertex2i( i32W, 0 );
			glVertex2i( i32W, (float32)i32H );
			glVertex2i( 0, i32H );
		glEnd();


		glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );


		if( i == 0 )
		{
			// Draw some padding to the outer edge

			float32	f32InvWidth = 1.0f / (float32)m_ui32TexWidth;
			float32	f32InvHeight = 1.0f / (float32)m_ui32TexHeight;
			float32	f32TexW = ((float32)m_i32TexCapturedWidth - 1) * f32InvWidth;
			float32	f32TexH = ((float32)m_i32TexCapturedHeight - 1) * f32InvHeight;

			int32	i32CapW = m_i32TexCapturedWidth >> 1;
			int32	i32CapH = m_i32TexCapturedHeight >> 1;

			const int32	i32Extend = 256;


//			glDisable( GL_BLEND );
	
			glBegin( GL_QUADS );
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 0 + f32OX, 0 );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 0 - f32OX, 0 );
				glVertex2i( 0, 0 );
				
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 1 + f32OX, 0 );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 1 - f32OX, 0 );
				glVertex2i( i32W, 0 );
				
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 1 + f32OX, 1 );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 1 - f32OX, 1 );
				glVertex2i( i32W, (float32)i32H );
				
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 0 + f32OX, 1 );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 0 - f32OX, 1 );
				glVertex2i( 0, i32H );
			glEnd();

//			glEnable( GL_BLEND );
			
			glBegin( GL_QUADS );
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 0, 0 + f32OY );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 0, 0 - f32OY );
				glVertex2i( 0, 0 );
				
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 1, 0 + f32OY );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 1, 0 - f32OY );
				glVertex2i( i32W, 0 );
				
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 1, 1 + f32OY );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 1, 1 - f32OY );
				glVertex2i( i32W, i32H );
				
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 0, 1 + f32OY );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 0, 1 - f32OY );
				glVertex2i( 0, i32H );
			glEnd();


			glDisable( GL_BLEND );

			glBegin( GL_QUADS );

				int32	i32PaddingOffset = -1;
				float32	f32RepW = f32TexW;
				float32	f32RepH = f32TexH;

				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, f32RepW, 0 );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32RepW, 0 );
				glVertex2i( i32CapW + i32PaddingOffset, 0 );
				
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, f32RepW, 0 );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32RepW, 0 );
				glVertex2i( i32CapW + i32Extend, 0 );
				
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, f32RepW, f32TexH + (float32)i32Extend * (2.0f * f32InvHeight) );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32RepW, f32TexH + (float32)i32Extend * (2.0f * f32InvHeight) );
				glVertex2i( i32CapW + i32Extend, i32CapH + i32Extend );
				
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, f32RepW, f32TexH + (float32)i32Extend * (2.0f * f32InvHeight) );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32RepW, f32TexH + (float32)i32Extend * (2.0f * f32InvHeight) );
				glVertex2i( i32CapW + i32PaddingOffset, i32CapH + i32Extend );

				// top padding
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 0, f32RepH );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 0, f32RepH );
				glVertex2i( 0, i32CapH + i32PaddingOffset );
				
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, f32TexW + (float32)i32Extend * (2.0f * f32InvWidth), f32RepH );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32TexW + (float32)i32Extend * (2.0f * f32InvWidth), f32RepH );
				glVertex2i( i32CapW + i32Extend, i32CapH + i32PaddingOffset );
				
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, f32TexW + (float32)i32Extend * (2.0f * f32InvWidth), f32RepH );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32TexW + (float32)i32Extend * (2.0f * f32InvWidth), f32RepH );
				glVertex2i( i32CapW + i32Extend, i32CapH + i32Extend );
				
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 0, f32RepH );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 0, f32RepH );
				glVertex2i( 0, i32CapH + i32Extend );


				// corner
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, f32RepW, f32RepH );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32RepW, f32RepH );
				glVertex2i( i32CapW + i32PaddingOffset, i32CapH + i32PaddingOffset );
				
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, f32RepW, f32RepH );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32RepW, f32RepH );
				glVertex2i( i32CapW + i32Extend, i32CapH + i32PaddingOffset );
				
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, f32RepW, f32RepH );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32RepW, f32RepH );
				glVertex2i( i32CapW + i32Extend, i32CapH + i32Extend );
				
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, f32RepW, f32RepH );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32RepW, f32RepH );
				glVertex2i( i32CapW + i32PaddingOffset, i32CapH + i32Extend );

			glEnd();

			glEnable( GL_BLEND );
		}
		else
		{
//			glDisable( GL_BLEND );
	
			glBegin( GL_QUADS );
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 0 + f32OX, 0 );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 0 - f32OX, 0 );
				glVertex2i( 0, 0 );
				
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 1 + f32OX, 0 );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 1 - f32OX, 0 );
				glVertex2i( i32W, 0 );
				
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 1 + f32OX, 1 );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 1 - f32OX, 1 );
				glVertex2i( i32W, (float32)i32H );
				
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 0 + f32OX, 1 );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 0 - f32OX, 1 );
				glVertex2i( 0, i32H );
			glEnd();

//			glEnable( GL_BLEND );
			
			glBegin( GL_QUADS );
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 0, 0 + f32OY );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 0, 0 - f32OY );
				glVertex2i( 0, 0 );
				
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 1, 0 + f32OY );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 1, 0 - f32OY );
				glVertex2i( i32W, 0 );
				
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 1, 1 + f32OY );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 1, 1 - f32OY );
				glVertex2i( i32W, i32H );
				
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 0, 1 + f32OY );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 0, 1 - f32OY );
				glVertex2i( 0, i32H );
			glEnd();
		}


		glBindTexture( GL_TEXTURE_2D, m_ui32BlurTexId[i] );

		glCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, i32W, i32H );
	}


	glActiveTextureARB( GL_TEXTURE1_ARB );
	glDisable( GL_TEXTURE_2D );
	glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );

	glActiveTextureARB( GL_TEXTURE0_ARB );
	glDisable( GL_TEXTURE_2D );
	glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );

	glDisable( GL_BLEND );
	glEnable( GL_DEPTH_TEST );
	glDepthMask( GL_TRUE );


	m_pPBuffer->end_draw();*/

	int32	i;

	if( !m_pPBuffer || !m_pPBuffer->is_initialised() )
		return;

	// if multitexture is not supported, die out
	if( !g_bMultiTexture )
		return;

	if( !m_pPBuffer->begin_draw() ) {
		TRACE( "begin_draw failed\n" );
		return;
	}

	//Setup ortho mode.
	glMatrixMode( GL_PROJECTION );
	glLoadIdentity();
	glOrtho( 0, m_pPBuffer->get_width(), 0, m_pPBuffer->get_height(), -100, 100 );
	glMatrixMode( GL_MODELVIEW );
	glLoadIdentity();

	glEnable( GL_BLEND );
	glBlendFunc( GL_CONSTANT_ALPHA_EXT, GL_ONE_MINUS_CONSTANT_ALPHA_EXT );
//	glBlendFunc( GL_ONE, GL_ONE );
	glDisable( GL_DEPTH_TEST );
	glDepthMask( GL_FALSE );
	glDisable( GL_ALPHA_TEST );

	float32	f32A = 0.5f;

	// the texture mix alpha is in color, and the secand mix alpha is in the alpha
	glColor4f( 1, 1, 1, 0.5f );
	glBlendColor( 1, 1, 1, 0.5f );




	for( i = 0; i < BLUR_TEX_COUNT; i++ )
	{

//		glClearColor( 0, 0, 0, 0 );
//		glClear( GL_COLOR_BUFFER_BIT );

		glEnable( GL_TEXTURE_SHADER_NV );

		int32	i32W = (int32)m_ui32TexWidth >> (i + 1);
		int32	i32H = (int32)m_ui32TexHeight >> (i + 1);

//		TRACE( "w: %d  h: %d\n", i32W, i32H );

		float32	f32OX = 1.0f / (float32)i32W;
		float32	f32OY = 1.0f / (float32)i32H;

		uint32	ui32SrcTex;
		if( i > 0 )
			ui32SrcTex = m_ui32BlurTexId[i - 1];
		else
			ui32SrcTex = m_ui32TexId;

		glActiveTextureARB( GL_TEXTURE0_ARB );

//		glEnable( GL_TEXTURE_2D );
		glTexEnvi( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D );

		glBindTexture( GL_TEXTURE_2D, ui32SrcTex );
		CHECK_GL_ERROR( "make blur: tex0 color env (bind)\n" );

		glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );


		glActiveTextureARB( GL_TEXTURE1_ARB );
//		glEnable( GL_TEXTURE_2D );

		glTexEnvi( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D );

		glBindTexture( GL_TEXTURE_2D, ui32SrcTex );
		glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT );

		glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_INTERPOLATE_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_PRIMARY_COLOR_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA );

		glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_INTERPOLATE_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PREVIOUS_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_TEXTURE );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, GL_SRC_ALPHA );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, GL_PRIMARY_COLOR_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA );


		// capture
		glActiveTextureARB( GL_TEXTURE2_ARB );
//		glTexEnvi( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_NONE );
//		glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_NONE );

		glTexEnvi( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D );
		glBindTexture( GL_TEXTURE_2D, m_ui32TexId );

		glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT );

		glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_REPLACE );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR );

		glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA );


		// Gradient
//		glActiveTextureARB( GL_TEXTURE3_ARB );
//		glTexEnvi( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_NONE );
//		glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_NONE );

		glActiveTextureARB( GL_TEXTURE3_ARB );
		glBindTexture( GL_TEXTURE_2D, m_ui32GradientTextures[i] );

		glTexEnvi( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_DEPENDENT_AR_TEXTURE_2D_NV );
		glTexEnvi( GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE2_ARB );


		glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT );

		glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_REPLACE );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR );

		glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA );


/*		glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA );*/

/*		if( i > 0 )
		{
			glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE );
			glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE );
			glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA );
			glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PREVIOUS_EXT );
			glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA );
		}
		else
		{
			glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE );
			glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE );
			glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA );
		}*/

/*			glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE );
			glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE );
			glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA );*/


		float32	f32MOX = 1.0f / (float32)m_ui32TexWidth;
		float32	f32MOY = 1.0f / (float32)m_ui32TexHeight;

		if( i == 0 )
		{
			glBlendColor( 1, 1, 1, 0.5f );

			// Draw some padding to the outer edge

			float32	f32InvWidth = 1.0f / (float32)m_ui32TexWidth;
			float32	f32InvHeight = 1.0f / (float32)m_ui32TexHeight;
			float32	f32TexW = ((float32)m_i32TexCapturedWidth - 1) * f32InvWidth;
			float32	f32TexH = ((float32)m_i32TexCapturedHeight - 1) * f32InvHeight;

			int32	i32CapW = m_i32TexCapturedWidth >> 1;
			int32	i32CapH = m_i32TexCapturedHeight >> 1;

			const int32	i32Extend = 256;


			glDisable( GL_BLEND );
	
			glBegin( GL_QUADS );
				glMultiTexCoord2fARB( GL_TEXTURE2_ARB, 0 + f32MOX, 0 );
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 0 + f32OX, 0 );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 0 - f32OX, 0 );
				glVertex2i( 0, 0 );
				
				glMultiTexCoord2fARB( GL_TEXTURE2_ARB, 1 + f32MOX, 0 );
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 1 + f32OX, 0 );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 1 - f32OX, 0 );
				glVertex2i( i32W, 0 );
				
				glMultiTexCoord2fARB( GL_TEXTURE2_ARB, 1 + f32MOX, 1 );
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 1 + f32OX, 1 );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 1 - f32OX, 1 );
				glVertex2i( i32W, (float32)i32H );
				
				glMultiTexCoord2fARB( GL_TEXTURE2_ARB, 0 + f32MOX, 1 );
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 0 + f32OX, 1 );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 0 - f32OX, 1 );
				glVertex2i( 0, i32H );
			glEnd();

			glEnable( GL_BLEND );
			
			glBegin( GL_QUADS );
				glMultiTexCoord2fARB( GL_TEXTURE2_ARB, 0, 0 + f32MOY );
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 0, 0 + f32OY );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 0, 0 - f32OY );
				glVertex2i( 0, 0 );
				
				glMultiTexCoord2fARB( GL_TEXTURE2_ARB, 1, 0 + f32MOY );
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 1, 0 + f32OY );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 1, 0 - f32OY );
				glVertex2i( i32W, 0 );
				
				glMultiTexCoord2fARB( GL_TEXTURE2_ARB, 1, 1 + f32MOY );
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 1, 1 + f32OY );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 1, 1 - f32OY );
				glVertex2i( i32W, i32H );
				
				glMultiTexCoord2fARB( GL_TEXTURE2_ARB, 0, 1 + f32MOY );
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 0, 1 + f32OY );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 0, 1 - f32OY );
				glVertex2i( 0, i32H );
			glEnd();


			glDisable( GL_BLEND );

			glBegin( GL_QUADS );

				int32	i32PaddingOffset = -1;
				float32	f32RepW = f32TexW;
				float32	f32RepH = f32TexH;

				glMultiTexCoord2fARB( GL_TEXTURE2_ARB, f32RepW, 0 );
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, f32RepW, 0 );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32RepW, 0 );
				glVertex2i( i32CapW + i32PaddingOffset, 0 );
				
				glMultiTexCoord2fARB( GL_TEXTURE2_ARB, f32RepW, 0 );
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, f32RepW, 0 );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32RepW, 0 );
				glVertex2i( i32CapW + i32Extend, 0 );
				
				glMultiTexCoord2fARB( GL_TEXTURE2_ARB, f32RepW, f32TexH + (float32)i32Extend * (2.0f * f32InvHeight) );
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, f32RepW, f32TexH + (float32)i32Extend * (2.0f * f32InvHeight) );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32RepW, f32TexH + (float32)i32Extend * (2.0f * f32InvHeight) );
				glVertex2i( i32CapW + i32Extend, i32CapH + i32Extend );
				
				glMultiTexCoord2fARB( GL_TEXTURE2_ARB, f32RepW, f32TexH + (float32)i32Extend * (2.0f * f32InvHeight) );
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, f32RepW, f32TexH + (float32)i32Extend * (2.0f * f32InvHeight) );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32RepW, f32TexH + (float32)i32Extend * (2.0f * f32InvHeight) );
				glVertex2i( i32CapW + i32PaddingOffset, i32CapH + i32Extend );

				// top padding
				glMultiTexCoord2fARB( GL_TEXTURE2_ARB, 0, f32RepH );
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 0, f32RepH );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 0, f32RepH );
				glVertex2i( 0, i32CapH + i32PaddingOffset );
				
				glMultiTexCoord2fARB( GL_TEXTURE2_ARB, f32TexW + (float32)i32Extend * (2.0f * f32InvWidth), f32RepH );
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, f32TexW + (float32)i32Extend * (2.0f * f32InvWidth), f32RepH );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32TexW + (float32)i32Extend * (2.0f * f32InvWidth), f32RepH );
				glVertex2i( i32CapW + i32Extend, i32CapH + i32PaddingOffset );
				
				glMultiTexCoord2fARB( GL_TEXTURE2_ARB, f32TexW + (float32)i32Extend * (2.0f * f32InvWidth), f32RepH );
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, f32TexW + (float32)i32Extend * (2.0f * f32InvWidth), f32RepH );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32TexW + (float32)i32Extend * (2.0f * f32InvWidth), f32RepH );
				glVertex2i( i32CapW + i32Extend, i32CapH + i32Extend );
				
				glMultiTexCoord2fARB( GL_TEXTURE2_ARB, 0, f32RepH );
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 0, f32RepH );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 0, f32RepH );
				glVertex2i( 0, i32CapH + i32Extend );


				// corner
				glMultiTexCoord2fARB( GL_TEXTURE2_ARB, f32RepW, f32RepH );
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, f32RepW, f32RepH );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32RepW, f32RepH );
				glVertex2i( i32CapW + i32PaddingOffset, i32CapH + i32PaddingOffset );
				
				glMultiTexCoord2fARB( GL_TEXTURE2_ARB, f32RepW, f32RepH );
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, f32RepW, f32RepH );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32RepW, f32RepH );
				glVertex2i( i32CapW + i32Extend, i32CapH + i32PaddingOffset );
				
				glMultiTexCoord2fARB( GL_TEXTURE2_ARB, f32RepW, f32RepH );
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, f32RepW, f32RepH );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32RepW, f32RepH );
				glVertex2i( i32CapW + i32Extend, i32CapH + i32Extend );
				
				glMultiTexCoord2fARB( GL_TEXTURE2_ARB, f32RepW, f32RepH );
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, f32RepW, f32RepH );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32RepW, f32RepH );
				glVertex2i( i32CapW + i32PaddingOffset, i32CapH + i32Extend );


			glEnd();
		}
		else
		{

			glDisable( GL_BLEND );
	
			glBegin( GL_QUADS );
				glMultiTexCoord2fARB( GL_TEXTURE2_ARB, 0 + f32MOX, 0 );
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 0 + f32OX, 0 );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 0 - f32OX, 0 );
				glVertex2i( 0, 0 );
				
				glMultiTexCoord2fARB( GL_TEXTURE2_ARB, 1 + f32MOX, 0 );
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 1 + f32OX, 0 );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 1 - f32OX, 0 );
				glVertex2i( i32W, 0 );
				
				glMultiTexCoord2fARB( GL_TEXTURE2_ARB, 1 + f32MOX, 1 );
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 1 + f32OX, 1 );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 1 - f32OX, 1 );
				glVertex2i( i32W, (float32)i32H );
				
				glMultiTexCoord2fARB( GL_TEXTURE2_ARB, 0 + f32MOX, 1 );
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 0 + f32OX, 1 );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 0 - f32OX, 1 );
				glVertex2i( 0, i32H );
			glEnd();

			glBlendColor( 1, 1, 1, 0.5f );

			glEnable( GL_BLEND );
			
			glBegin( GL_QUADS );
				glMultiTexCoord2fARB( GL_TEXTURE2_ARB, 0, 0 + f32MOY );
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 0, 0 + f32OY );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 0, 0 - f32OY );
				glVertex2i( 0, 0 );
				
				glMultiTexCoord2fARB( GL_TEXTURE2_ARB, 1, 0 + f32MOY );
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 1, 0 + f32OY );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 1, 0 - f32OY );
				glVertex2i( i32W, 0 );
				
				glMultiTexCoord2fARB( GL_TEXTURE2_ARB, 1, 1 + f32MOY );
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 1, 1 + f32OY );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 1, 1 - f32OY );
				glVertex2i( i32W, i32H );
				
				glMultiTexCoord2fARB( GL_TEXTURE2_ARB, 0, 1 + f32MOY );
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 0, 1 + f32OY );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 0, 1 - f32OY );
				glVertex2i( 0, i32H );
			glEnd();

			// Do again with blend to mix the mask better

			glBlendColor( 1, 1, 1, 0.25f );

			glBegin( GL_QUADS );
				glMultiTexCoord2fARB( GL_TEXTURE2_ARB, 0 - f32MOX, 0 );
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 0 + f32OX, 0 );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 0 - f32OX, 0 );
				glVertex2i( 0, 0 );
				
				glMultiTexCoord2fARB( GL_TEXTURE2_ARB, 1 - f32MOX, 0 );
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 1 + f32OX, 0 );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 1 - f32OX, 0 );
				glVertex2i( i32W, 0 );
				
				glMultiTexCoord2fARB( GL_TEXTURE2_ARB, 1 - f32MOX, 1 );
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 1 + f32OX, 1 );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 1 - f32OX, 1 );
				glVertex2i( i32W, (float32)i32H );
				
				glMultiTexCoord2fARB( GL_TEXTURE2_ARB, 0 - f32MOX, 1 );
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 0 + f32OX, 1 );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 0 - f32OX, 1 );
				glVertex2i( 0, i32H );
			glEnd();

			glBegin( GL_QUADS );
				glMultiTexCoord2fARB( GL_TEXTURE2_ARB, 0, 0 - f32MOY );
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 0, 0 + f32OY );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 0, 0 - f32OY );
				glVertex2i( 0, 0 );
				
				glMultiTexCoord2fARB( GL_TEXTURE2_ARB, 1, 0 - f32MOY );
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 1, 0 + f32OY );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 1, 0 - f32OY );
				glVertex2i( i32W, 0 );
				
				glMultiTexCoord2fARB( GL_TEXTURE2_ARB, 1, 1 - f32MOY );
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 1, 1 + f32OY );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 1, 1 - f32OY );
				glVertex2i( i32W, i32H );
				
				glMultiTexCoord2fARB( GL_TEXTURE2_ARB, 0, 1 - f32MOY );
				glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 0, 1 + f32OY );
				glMultiTexCoord2fARB( GL_TEXTURE0_ARB, 0, 1 - f32OY );
				glVertex2i( 0, i32H );
			glEnd();
		}

		glDisable( GL_TEXTURE_SHADER_NV );


		glActiveTextureARB( GL_TEXTURE0_ARB );
		glEnable( GL_TEXTURE_2D );
		glBindTexture( GL_TEXTURE_2D, m_ui32BlurTexId[i] );

		glCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, i32W, i32H );
	}




	glActiveTextureARB( GL_TEXTURE2_ARB );
	glDisable( GL_TEXTURE_2D );
	glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );

	glActiveTextureARB( GL_TEXTURE1_ARB );
	glDisable( GL_TEXTURE_2D );
	glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );

	glActiveTextureARB( GL_TEXTURE0_ARB );
	glDisable( GL_TEXTURE_2D );
	glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );

	glDisable( GL_BLEND );
	glEnable( GL_DEPTH_TEST );
	glDepthMask( GL_TRUE );


	m_pPBuffer->end_draw();
}

void
DepthBlurEffectC::eval_state( int32 i32Time )
{
	if( !m_pDemoInterface )
		return;

	// Requires some extensions.
	if( !g_bBlendEqu || !g_bMultiTexture )
		return;

	DeviceContextC* pContext = m_pDemoInterface->get_device_context();
	TimeContextC* pTimeContext = m_pDemoInterface->get_time_context();

	int32		i;
	Matrix2C	rPosMat, rRotMat, rScaleMat, rPivotMat;

	Vector2C	rScale;
	Vector2C	rPos;
	Vector2C	rPivot;

	// Get parameters which affect the transformation.
	((ParamVector2C*)m_pTraGizmo->get_parameter( ID_TRANSFORM_POS ))->get_val( i32Time, rPos );
	((ParamVector2C*)m_pTraGizmo->get_parameter( ID_TRANSFORM_PIVOT ))->get_val( i32Time, rPivot );
	((ParamVector2C*)m_pTraGizmo->get_parameter( ID_TRANSFORM_SCALE ))->get_val( i32Time, rScale );

	// Calculate transformation matrix.
	rPivotMat.set_trans( rPivot );
	rPosMat.set_trans( rPos );
	rScaleMat.set_scale( rScale ) ;
	m_rTM = rPivotMat * rScaleMat * rPosMat;

	float32		f32Width = 25;
	float32		f32Height = 25;
	Vector2C	rMin, rMax;
	Vector2C	rVec;

	// Calcualte vertices of the rectangle.
	m_rVertices[0][0] = -f32Width;		// top-left
	m_rVertices[0][1] = -f32Height;

	m_rVertices[1][0] =  f32Width;		// top-right
	m_rVertices[1][1] = -f32Height;

	m_rVertices[2][0] =  f32Width;		// bottom-right
	m_rVertices[2][1] =  f32Height;

	m_rVertices[3][0] = -f32Width;		// bottom-left
	m_rVertices[3][1] =  f32Height;

	// Calculate bounding box
	for( i = 0; i < 4; i++ ) {
		rVec = m_rTM * m_rVertices[i];
		m_rVertices[i] = rVec;

		if( !i )
			rMin = rMax = rVec;
		else {
			if( rVec[0] < rMin[0] ) rMin[0] = rVec[0];
			if( rVec[1] < rMin[1] ) rMin[1] = rVec[1];
			if( rVec[0] > rMax[0] ) rMax[0] = rVec[0];
			if( rVec[1] > rMax[1] ) rMax[1] = rVec[1];
		}
	}

	// Store bounding box.
	m_rBBox[0] = rMin;
	m_rBBox[1] = rMax;

	float32	f32NearRange = 0.0f;
	float32	f32FarRange = 1.0f;
	float32	f32Opacity = 1.0f;
	int32			i32Blend = BLENDMODE_NORMAL;

	// Get Size
	((ParamFloatC*)m_pAttGizmo->get_parameter_by_id( ID_ATTRIBUTE_NEAR ))->get_val( i32Time, f32NearRange );
	// Get Size
	((ParamFloatC*)m_pAttGizmo->get_parameter_by_id( ID_ATTRIBUTE_FAR ))->get_val( i32Time, f32FarRange );
	// Get Opacity.
	((ParamFloatC*)m_pAttGizmo->get_parameter_by_id( ID_ATTRIBUTE_OPACITY ))->get_val( i32Time, f32Opacity );
	// Get Blend mode.
	((ParamIntC*)m_pAttGizmo->get_parameter_by_id( ID_ATTRIBUTE_BLEND ))->get_val( i32Time, i32Blend );

	if( f32NearRange > f32FarRange )
		f32NearRange = f32FarRange;

	// Mask
	ParamLinkC*				pMaskParam = (ParamLinkC*)m_pAttGizmo->get_parameter_by_id( ID_ATTRIBUTE_MASK );
	EffectMaskI*			pMaskEffect = (EffectMaskI*)pMaskParam->get_link( 0 );
	ImportableImageI*	pMaskImp = 0;
	int32							i32MaskImageFlags = 0;
	Matrix2C					rMaskMat;
	if( pMaskEffect )
	{
		pMaskImp = pMaskEffect->get_mask_image();
		i32MaskImageFlags = pMaskEffect->get_mask_image_flags();
		rMaskMat = pMaskEffect->get_mask_matrix();
	}

	//
	// draw effect
	//

	// Get the OpenGL device.
	OpenGLDeviceC*	pDevice = (OpenGLDeviceC*)pContext->query_interface( CLASS_OPENGL_DEVICEDRIVER );
	if( !pDevice )
		return;

	// Get the OpenGL viewport.
	OpenGLViewportC*	pViewport = (OpenGLViewportC*)pDevice->query_interface( GRAPHICSDEVICE_VIEWPORT_INTERFACE );
	if( !pViewport )
		return;

	// Set orthographic projection.
	pViewport->set_ortho_pixel( m_rBBox );

	// get image from frame buffer
	int32	i32Width = pViewport->get_width();
	int32	i32Height = pViewport->get_height();

	check_blur_buffer_size( i32Width, i32Height );


	// the scale used with size parameter
	Vector2C	rOne( 1, 1 );
	rOne = pViewport->delta_layout_to_client( rOne );

	// calc where we get our image
	Vector2C	rOffset( 4, 4 );
	BBox2C	rCapture;
	rCapture[0] = pViewport->layout_to_client( m_rBBox[0] );
	rCapture[1] = pViewport->layout_to_client( m_rBBox[1] );

	int32	i32X, i32Y;

	i32X = (int32)floor( rCapture[0][0] ) - CAPTURE_OFFSET;
	i32Y = (int32)floor( rCapture[0][1] ) - CAPTURE_OFFSET;

	m_i32TexCapturedWidth = (int32)ceil( rCapture.width() ) + 2 * CAPTURE_OFFSET;
	m_i32TexCapturedHeight = (int32)ceil( rCapture.height() ) + 2 * CAPTURE_OFFSET;

	if( i32X >= i32Width )
		return;
	if( i32X < 0 ) {
		m_i32TexCapturedWidth += i32X;
		i32X = 0;
	}
	if( (i32X + m_i32TexCapturedWidth) >= i32Width )
		m_i32TexCapturedWidth -= (i32X + m_i32TexCapturedWidth) - i32Width;
	if( m_i32TexCapturedWidth <= 0 )
		return;

	if( i32Y >= i32Height )
		return;
	if( i32Y < 0 ) {
		m_i32TexCapturedHeight += i32Y;
		i32Y = 0;
	}
	if( (i32Y + m_i32TexCapturedHeight) >= i32Height )
		m_i32TexCapturedHeight -= (i32Y + m_i32TexCapturedHeight) - i32Height;
	if( m_i32TexCapturedHeight <= 0 )
		return;


	glActiveTextureARB( GL_TEXTURE0_ARB );

	glEnable( GL_TEXTURE_2D );
	glDisable( GL_DEPTH_TEST );
	glDepthMask( GL_FALSE );
	glEnable( GL_BLEND );


	glBindTexture( GL_TEXTURE_2D, m_ui32TexId );
	glCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, i32X, i32Y, m_i32TexCapturedWidth, m_i32TexCapturedHeight );

	update_range_textures( f32NearRange, f32FarRange );

	// make blur textures
	make_blur_textures();

	float32	f32TexX0 = 0;
	float32	f32TexY0 = 0;
	float32	f32TexX1 = m_i32TexCapturedWidth;
	float32	f32TexY1 = m_i32TexCapturedHeight;

	float32	f32InvTexWidth = 1.0f/ (float32)(m_ui32TexWidth);
	float32	f32InvTexHeight = 1.0f/ (float32)(m_ui32TexHeight);

	f32TexX0 *= f32InvTexWidth;
	f32TexY0 *= f32InvTexHeight;
	f32TexX1 *= f32InvTexWidth;
	f32TexY1 *= f32InvTexHeight;

	// draw depth blur

	glDisable( GL_DEPTH_TEST );
	glDepthMask( GL_FALSE );

	float32	f32A = 0.5f;

	// the texture mix alpha is in color, and the secand mix alpha is in the alpha
	glColor4f( 1, 1, 1, 1 );


/*
	// The most blurred version in the bottom

	glBlendFunc( GL_ONE, GL_ZERO );
	glColor3ub( 255, 255, 255 );


	glActiveTextureARB( GL_TEXTURE0_ARB );
	glEnable( GL_TEXTURE_2D );
	glBindTexture( GL_TEXTURE_2D, m_ui32BlurTexId[4] );
	glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );

	glActiveTextureARB( GL_TEXTURE1_ARB );
	glDisable( GL_TEXTURE_2D );
	glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );

	glBegin( GL_QUADS );

	glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32TexX0, f32TexY0 );
	glVertex2f( (float32)i32X, (float32)i32Y );

	glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32TexX1, f32TexY0 );
	glVertex2f( (float32)(i32X + m_i32TexCapturedWidth), (float32)i32Y );

	glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32TexX1, f32TexY1 );
	glVertex2f( (float32)(i32X + m_i32TexCapturedWidth), (float32)(i32Y + m_i32TexCapturedHeight) );

	glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32TexX0, f32TexY1 );
	glVertex2f( (float32)i32X, (float32)(i32Y + m_i32TexCapturedHeight) );

	glEnd();
*/

/*
	// Set shader
	glEnable( GL_TEXTURE_SHADER_NV );

	//
	// Stage 0, captured
	//
	glActiveTextureARB( GL_TEXTURE0_ARB );
	glEnable( GL_TEXTURE_2D );
	glDisable( GL_TEXTURE_2D );

	glBindTexture( GL_TEXTURE_2D, m_ui32TexId );

	glTexEnvi( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D );
	glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_NONE );

//	glDisable( GL_TEXTURE_2D );

	//
	// Stage 1, gradient lookup
	//
	glActiveTextureARB( GL_TEXTURE1_ARB );
	glEnable( GL_TEXTURE_2D );


	glTexEnvi( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_DEPENDENT_AR_TEXTURE_2D_NV );
	glTexEnvi( GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB );

	glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT );

	glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_REPLACE );
	glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PRIMARY_COLOR_EXT );
	glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR );

	glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE );
	glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE );
	glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA );


	//
	// Stage 2, the blurred texture.
	//
	glActiveTextureARB( GL_TEXTURE2_ARB );
	glEnable( GL_TEXTURE_2D );
	glTexEnvi( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D );

	glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT );

	glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_REPLACE );
	glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE );
	glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR );

	glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE );
	glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PREVIOUS_EXT );
	glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA );

	//
	// Stage 3, disabled.
	//
	glActiveTextureARB( GL_TEXTURE3_ARB );
	glTexEnvi( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_NONE );
	glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_NONE );


	glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );


	// @loop

	for( i = 0; i < 5; i++ )
//	for( i = 4; i >= 0; i-- )
	{

		glActiveTextureARB( GL_TEXTURE2_ARB );
		glEnable( GL_TEXTURE_2D );


		uint32	ui32SrcTex;
//		ui32SrcTex = m_ui32BlurTexId[i];
		if( i > 0 )
			ui32SrcTex = m_ui32BlurTexId[i - 1];
		else
			ui32SrcTex = m_ui32TexId;

		glBindTexture( GL_TEXTURE_2D, ui32SrcTex );

		glTexEnvi( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D );

		glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT );

		glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_REPLACE );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR );

		glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PREVIOUS_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA );



		glActiveTextureARB( GL_TEXTURE1_ARB );
//		glBindTexture( GL_TEXTURE_2D, m_ui32GradientTextures[i] );
		int32	i32RampId = i + 1;
		if( i32RampId < 0 )
			i32RampId = 0;
		if( i32RampId >= 4 )
			i32RampId = 4;
		glBindTexture( GL_TEXTURE_2D, m_ui32GradientTextures[i32RampId] );

		glTexEnvi( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_DEPENDENT_AR_TEXTURE_2D_NV );
		glTexEnvi( GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB );

		glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_REPLACE );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PRIMARY_COLOR_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR );

		glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA );



		glColor3ub( 255, 255, 255 );


		glBegin( GL_QUADS );

//		glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 0, 0 );
		glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32TexX0, f32TexY0 );
		glMultiTexCoord2fARB( GL_TEXTURE2_ARB, f32TexX0, f32TexY0 );
		glVertex2f( (float32)i32X, (float32)i32Y );

//		glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 1, 0 );
		glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32TexX1, f32TexY0 );
		glMultiTexCoord2fARB( GL_TEXTURE2_ARB, f32TexX1, f32TexY0 );
		glVertex2f( (float32)(i32X + m_i32TexCapturedWidth), (float32)i32Y );
	
//		glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 1, 1 );
		glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32TexX1, f32TexY1 );
		glMultiTexCoord2fARB( GL_TEXTURE2_ARB, f32TexX1, f32TexY1 );
		glVertex2f( (float32)(i32X + m_i32TexCapturedWidth), (float32)(i32Y + m_i32TexCapturedHeight) );
	
//		glMultiTexCoord2fARB( GL_TEXTURE1_ARB, 0, 1 );
		glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32TexX0, f32TexY1 );
		glMultiTexCoord2fARB( GL_TEXTURE2_ARB, f32TexX0, f32TexY1 );
		glVertex2f( (float32)i32X, (float32)(i32Y + m_i32TexCapturedHeight) );

		glEnd();
	}

	glDisable( GL_TEXTURE_SHADER_NV );
*/

	// @de

	CHECK_GL_ERROR( "@de\n" );

	glActiveTextureARB( GL_TEXTURE1_ARB );
	glDisable( GL_TEXTURE_2D );
	glActiveTextureARB( GL_TEXTURE2_ARB );
	glDisable( GL_TEXTURE_2D );
	glActiveTextureARB( GL_TEXTURE3_ARB );
	glDisable( GL_TEXTURE_2D );


//	glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
	glBlendFunc( GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA );

	glActiveTextureARB( GL_TEXTURE0_ARB );

	glEnable( GL_TEXTURE_2D );


//	glClearColor( 1, 0, 0, 0 );
//	glClear( GL_COLOR_BUFFER_BIT );

/*	i = (int32)(f32Opacity * 5.0f);
	if( i < 0 ) i = 0;
	if( i >= 4 ) i = 4;*/


	// the most blurred at BG
	glBlendFunc( GL_ONE, GL_ZERO );

	glBindTexture( GL_TEXTURE_2D, m_ui32BlurTexId[2] );
	glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );

	glColor3ub( 255, 255, 255 );

	glBegin( GL_QUADS );

	glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32TexX0, f32TexY0 );
	glVertex2f( (float32)i32X, (float32)i32Y );

	glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32TexX1, f32TexY0 );
	glVertex2f( (float32)(i32X + m_i32TexCapturedWidth), (float32)i32Y );

	glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32TexX1, f32TexY1 );
	glVertex2f( (float32)(i32X + m_i32TexCapturedWidth), (float32)(i32Y + m_i32TexCapturedHeight) );

	glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32TexX0, f32TexY1 );
	glVertex2f( (float32)i32X, (float32)(i32Y + m_i32TexCapturedHeight) );

	glEnd();


	CHECK_GL_ERROR( "back\n" );


//	for( i = 0; i < 5; i++ )
	for( i = 2; i >= 0; i-- )
	{

		uint32	ui32SrcTex;
//		ui32SrcTex = m_ui32BlurTexId[i];
		if( i > 0 )
		{
			ui32SrcTex = m_ui32BlurTexId[i - 1];
			glBlendFunc( GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA );

			glBindTexture( GL_TEXTURE_2D, ui32SrcTex );
			glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );

			glColor3ub( 255, 255, 255 );

			glBegin( GL_QUADS );

			glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32TexX0, f32TexY0 );
			glVertex2f( (float32)i32X, (float32)i32Y );

			glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32TexX1, f32TexY0 );
			glVertex2f( (float32)(i32X + m_i32TexCapturedWidth), (float32)i32Y );
		
			glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32TexX1, f32TexY1 );
			glVertex2f( (float32)(i32X + m_i32TexCapturedWidth), (float32)(i32Y + m_i32TexCapturedHeight) );
		
			glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32TexX0, f32TexY1 );
			glVertex2f( (float32)i32X, (float32)(i32Y + m_i32TexCapturedHeight) );

			glEnd();
		}
		else
		{

			// Set shader
			glEnable( GL_TEXTURE_SHADER_NV );

			//
			// Stage 0, captured
			//
			glActiveTextureARB( GL_TEXTURE0_ARB );
			glEnable( GL_TEXTURE_2D );
			glDisable( GL_TEXTURE_2D );

			glBindTexture( GL_TEXTURE_2D, m_ui32TexId );

			glTexEnvi( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D );
			glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );

		//	glDisable( GL_TEXTURE_2D );

			//
			// Stage 1, gradient lookup
			//
			glActiveTextureARB( GL_TEXTURE1_ARB );
			glEnable( GL_TEXTURE_2D );

			glBindTexture( GL_TEXTURE_2D, m_ui32GradientTextures[0] );

			glTexEnvi( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_DEPENDENT_AR_TEXTURE_2D_NV );
			glTexEnvi( GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB );

			glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT );

			glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_REPLACE );
			glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT );
			glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR );

			glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE );
			glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE );
			glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA );


			//
			// Stage 2, the blurred texture.
			//
			glActiveTextureARB( GL_TEXTURE2_ARB );
			glTexEnvi( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_NONE );
			glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_NONE );

			//
			// Stage 3, disabled.
			//
			glActiveTextureARB( GL_TEXTURE3_ARB );
			glTexEnvi( GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_NONE );
			glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_NONE );

			ui32SrcTex = m_ui32TexId;
			glBlendFunc( GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA );


			glColor3ub( 255, 255, 255 );

			glBegin( GL_QUADS );

			glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32TexX0, f32TexY0 );
			glVertex2f( (float32)i32X, (float32)i32Y );

			glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32TexX1, f32TexY0 );
			glVertex2f( (float32)(i32X + m_i32TexCapturedWidth), (float32)i32Y );
		
			glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32TexX1, f32TexY1 );
			glVertex2f( (float32)(i32X + m_i32TexCapturedWidth), (float32)(i32Y + m_i32TexCapturedHeight) );
		
			glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32TexX0, f32TexY1 );
			glVertex2f( (float32)i32X, (float32)(i32Y + m_i32TexCapturedHeight) );

			glEnd();

			glDisable( GL_TEXTURE_SHADER_NV );
		}

/*
		glBindTexture( GL_TEXTURE_2D, ui32SrcTex );
		glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );

		glColor3ub( 255, 255, 255 );

		glBegin( GL_QUADS );

		glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32TexX0, f32TexY0 );
		glVertex2f( (float32)i32X, (float32)i32Y );

		glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32TexX1, f32TexY0 );
		glVertex2f( (float32)(i32X + m_i32TexCapturedWidth), (float32)i32Y );
	
		glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32TexX1, f32TexY1 );
		glVertex2f( (float32)(i32X + m_i32TexCapturedWidth), (float32)(i32Y + m_i32TexCapturedHeight) );
	
		glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32TexX0, f32TexY1 );
		glVertex2f( (float32)i32X, (float32)(i32Y + m_i32TexCapturedHeight) );

		glEnd();*/
	}

//	glTexEnvf( GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1.0f );

	CHECK_GL_ERROR( "done\n" );


	glEnable( GL_DEPTH_TEST );
	glDisable( GL_BLEND );
	glDepthMask( GL_TRUE );


	// Reset blend equ
//	glBlendEquation( GL_FUNC_ADD );

	// Reset to default texture unit
	for( i = 0; i < 2; i++ )
	{
		glActiveTextureARB( GL_TEXTURE0_ARB + i );
		glDisable( GL_TEXTURE_2D );
		glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
	}


/*
	uint32	ui32TexId0 = 0;
	uint32	ui32TexId1 = 0;

	float32	f32LogSize = (float32)(log( f32Size * 20.0f * rOne[0] ) / log( 2.0f ));
	int32	i32Idx0 = (int32)floor( f32LogSize );
	float32	f32A = 1.0f - (f32LogSize - (float32)i32Idx0);
	int32	i32Idx1 = i32Idx0 + 1;

	i32Idx0 = __max( __min( i32Idx0, BLUR_TEX_COUNT ), 0 );
	i32Idx1 = __max( __min( i32Idx1, BLUR_TEX_COUNT ), 0 );

	if( i32Idx0 == 0 )
		ui32TexId0 = m_ui32TexId;
	else if( i32Idx0 <= BLUR_TEX_COUNT )
		ui32TexId0 = m_ui32BlurTexId[i32Idx0 - 1];

	if( i32Idx1 == 0 )
		ui32TexId1 = m_ui32TexId;
	else if( i32Idx1 <= BLUR_TEX_COUNT )
		ui32TexId1 = m_ui32BlurTexId[i32Idx1 - 1];


	int32	i32TextureUnit = 0;
	int32	i32MaskUnit = -1;
	int32	i32TempUnit = -1;


	if( i32Blend == BLENDMODE_NORMAL )
	{
		// Alpha is the destination blend
		glColor4f( 1, 1, 1, f32Opacity );

		// Put blend factor in texture env constant color.
		float32	f32EnvColor[4] = { 1, 1, 1, 1 };
		f32EnvColor[3] = f32A;

		// First blur texture
		glActiveTextureARB( GL_TEXTURE0_ARB + i32TextureUnit );
		glEnable( GL_TEXTURE_2D );
		glBindTexture( GL_TEXTURE_2D, ui32TexId0 );
		glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
		i32TextureUnit++;

		glActiveTextureARB( GL_TEXTURE0_ARB + i32TextureUnit );
		glEnable( GL_TEXTURE_2D );
		glBindTexture( GL_TEXTURE_2D, ui32TexId1 );

		glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT );
		glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, f32EnvColor );
		glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_INTERPOLATE_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_CONSTANT_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA );

		glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA );

		i32TextureUnit++;


		// Mask
		if( pMaskImp ) {
			glActiveTextureARB( GL_TEXTURE0_ARB + i32TextureUnit );
			pMaskImp->bind_texture( pDevice, i32MaskImageFlags );
			glEnable( GL_TEXTURE_2D );

			// Pass color from previous texture stage
			glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT );

			glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_REPLACE );
			glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT );
			glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR );

			// Modulate alpha
			glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE );
			glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE );
			glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA );
			glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_PREVIOUS_EXT );
			glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, GL_SRC_ALPHA );

			i32MaskUnit = i32TextureUnit;
			i32TextureUnit++;
		}

		glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
	}
	else if( i32Blend == BLENDMODE_ADD )
	{
		// Alpha is the destination blend
		glColor4f( 1, 1, 1, f32Opacity );

		// Put blend factor in texture env constant color.
		float32	f32EnvColor[4] = { 1, 1, 1, 1 };
		f32EnvColor[3] = f32A;

		// First blur texture
		glActiveTextureARB( GL_TEXTURE0_ARB + i32TextureUnit );
		glEnable( GL_TEXTURE_2D );
		glBindTexture( GL_TEXTURE_2D, ui32TexId0 );
		glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
		i32TextureUnit++;

		glActiveTextureARB( GL_TEXTURE0_ARB + i32TextureUnit );
		glEnable( GL_TEXTURE_2D );
		glBindTexture( GL_TEXTURE_2D, ui32TexId1 );

		glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT );
		glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, f32EnvColor );
		glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_INTERPOLATE_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_CONSTANT_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA );

		glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA );

		i32TextureUnit++;


		// Mask
		if( pMaskImp ) {
			glActiveTextureARB( GL_TEXTURE0_ARB + i32TextureUnit );
			pMaskImp->bind_texture( pDevice, i32MaskImageFlags );
			glEnable( GL_TEXTURE_2D );

			// Pass color from previous texture stage
			glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT );

			glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_REPLACE );
			glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT );
			glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR );

			// Modulate alpha
			glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE );
			glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE );
			glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA );
			glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_PREVIOUS_EXT );
			glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, GL_SRC_ALPHA );

			i32MaskUnit = i32TextureUnit;
			i32TextureUnit++;
		}

		glBlendFunc( GL_SRC_ALPHA, GL_ONE );
	}
	else if( i32Blend == BLENDMODE_MULT )
	{
		// Alpha is the destination blend
		glColor4f( 1, 1, 1, f32Opacity );

		// Put blend factor in texture env constant color.
		float32	f32EnvColor[4] = { 1, 1, 1, 1 };
		f32EnvColor[3] = f32A;

		// First blur texture
		glActiveTextureARB( GL_TEXTURE0_ARB + i32TextureUnit );
		glEnable( GL_TEXTURE_2D );
		glBindTexture( GL_TEXTURE_2D, ui32TexId0 );
		glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
		i32TextureUnit++;

		glActiveTextureARB( GL_TEXTURE0_ARB + i32TextureUnit );
		glEnable( GL_TEXTURE_2D );
		glBindTexture( GL_TEXTURE_2D, ui32TexId1 );

		glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT );
		glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, f32EnvColor );
		glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_INTERPOLATE_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_CONSTANT_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA );

		glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA );

		i32TextureUnit++;


		// Mask
		if( pMaskImp ) {
			glActiveTextureARB( GL_TEXTURE0_ARB + i32TextureUnit );
			pMaskImp->bind_texture( pDevice, i32MaskImageFlags );
			glEnable( GL_TEXTURE_2D );

			// Pass color from previous texture stage
			glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT );

			glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_REPLACE );
			glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT );
			glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR );

			// Modulate alpha
			glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE );
			glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE );
			glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA );
			glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_PREVIOUS_EXT );
			glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, GL_SRC_ALPHA );

			i32MaskUnit = i32TextureUnit;
			i32TextureUnit++;
		}

		// Transparency unit
		glActiveTextureARB( GL_TEXTURE0_ARB + i32TextureUnit );
		glBindTexture( GL_TEXTURE_2D, m_ui32WhiteTextureID );
		glEnable( GL_TEXTURE_2D );

		// Pass color from previous texture stage
		glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT );

		glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_INTERPOLATE_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_PREVIOUS_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA );

		// Modulate alpha
		glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PREVIOUS_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA );

		i32TextureUnit++;

		glBlendFunc( GL_DST_COLOR, GL_ZERO );
	}
	else if( i32Blend == BLENDMODE_SUB )
	{
		// Alpha is the destination blend
		glColor4f( 1, 1, 1, f32Opacity );

		// Put blend factor in texture env constant color.
		float32	f32EnvColor[4] = { 1, 1, 1, 1 };
		f32EnvColor[3] = f32A;

		// First blur texture
		glActiveTextureARB( GL_TEXTURE0_ARB + i32TextureUnit );
		glEnable( GL_TEXTURE_2D );
		glBindTexture( GL_TEXTURE_2D, ui32TexId0 );
		glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
		i32TextureUnit++;

		glActiveTextureARB( GL_TEXTURE0_ARB + i32TextureUnit );
		glEnable( GL_TEXTURE_2D );
		glBindTexture( GL_TEXTURE_2D, ui32TexId1 );

		glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT );
		glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, f32EnvColor );
		glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_INTERPOLATE_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_CONSTANT_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA );

		glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA );

		i32TextureUnit++;


		// Mask
		if( pMaskImp ) {
			glActiveTextureARB( GL_TEXTURE0_ARB + i32TextureUnit );
			pMaskImp->bind_texture( pDevice, i32MaskImageFlags );
			glEnable( GL_TEXTURE_2D );

			// Pass color from previous texture stage
			glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT );

			glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_REPLACE );
			glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT );
			glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR );

			// Modulate alpha
			glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE );
			glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE );
			glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA );
			glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_PREVIOUS_EXT );
			glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, GL_SRC_ALPHA );

			i32MaskUnit = i32TextureUnit;
			i32TextureUnit++;
		}

		i32TextureUnit++;

		glBlendEquation( GL_FUNC_REVERSE_SUBTRACT_EXT );
		glBlendFunc( GL_SRC_ALPHA, GL_ONE );
	}
	else if( i32Blend == BLENDMODE_LIGHTEN )
	{
		// Alpha is the destination blend
		glColor4f( 1, 1, 1, f32Opacity );

		// Put blend factor in texture env constant color.
		float32	f32EnvColor[4] = { 1, 1, 1, 1 };
		f32EnvColor[3] = f32A;

		// First blur texture
		glActiveTextureARB( GL_TEXTURE0_ARB + i32TextureUnit );
		glEnable( GL_TEXTURE_2D );
		glBindTexture( GL_TEXTURE_2D, ui32TexId0 );
		glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
		i32TextureUnit++;

		glActiveTextureARB( GL_TEXTURE0_ARB + i32TextureUnit );
		glEnable( GL_TEXTURE_2D );
		glBindTexture( GL_TEXTURE_2D, ui32TexId1 );

		glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT );
		glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, f32EnvColor );
		glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_INTERPOLATE_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_CONSTANT_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA );

		glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA );

		i32TextureUnit++;


		// Mask
		if( pMaskImp ) {
			glActiveTextureARB( GL_TEXTURE0_ARB + i32TextureUnit );
			pMaskImp->bind_texture( pDevice, i32MaskImageFlags );
			glEnable( GL_TEXTURE_2D );

			// Pass color from previous texture stage
			glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT );

			glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_REPLACE );
			glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT );
			glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR );

			// Modulate alpha
			glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE );
			glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE );
			glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA );
			glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_PREVIOUS_EXT );
			glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, GL_SRC_ALPHA );

			i32MaskUnit = i32TextureUnit;
			i32TextureUnit++;
		}

		// Transparency unit
		glActiveTextureARB( GL_TEXTURE0_ARB + i32TextureUnit );
		glBindTexture( GL_TEXTURE_2D, m_ui32BlackTextureID );
		glEnable( GL_TEXTURE_2D );

		// Pass color from previous texture stage
		glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT );

		glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_INTERPOLATE_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_PREVIOUS_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA );

		// Modulate alpha
		glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PREVIOUS_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA );

		i32TextureUnit++;

		glBlendEquation( GL_MAX );
		glBlendFunc( GL_ONE, GL_ONE );
	}
	else if( i32Blend == BLENDMODE_DARKEN )
	{
		// Alpha is the destination blend
		glColor4f( 1, 1, 1, f32Opacity );

		// Put blend factor in texture env constant color.
		float32	f32EnvColor[4] = { 1, 1, 1, 1 };
		f32EnvColor[3] = f32A;

		// First blur texture
		glActiveTextureARB( GL_TEXTURE0_ARB + i32TextureUnit );
		glEnable( GL_TEXTURE_2D );
		glBindTexture( GL_TEXTURE_2D, ui32TexId0 );
		glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
		i32TextureUnit++;

		glActiveTextureARB( GL_TEXTURE0_ARB + i32TextureUnit );
		glEnable( GL_TEXTURE_2D );
		glBindTexture( GL_TEXTURE_2D, ui32TexId1 );

		glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT );
		glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, f32EnvColor );
		glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_INTERPOLATE_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_CONSTANT_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA );

		glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA );

		i32TextureUnit++;


		// Mask
		if( pMaskImp ) {
			glActiveTextureARB( GL_TEXTURE0_ARB + i32TextureUnit );
			pMaskImp->bind_texture( pDevice, i32MaskImageFlags );
			glEnable( GL_TEXTURE_2D );

			// Pass color from previous texture stage
			glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT );

			glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_REPLACE );
			glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT );
			glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR );

			// Modulate alpha
			glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE );
			glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE );
			glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA );
			glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_PREVIOUS_EXT );
			glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, GL_SRC_ALPHA );

			i32MaskUnit = i32TextureUnit;
			i32TextureUnit++;
		}

		// Transparency unit
		glActiveTextureARB( GL_TEXTURE0_ARB + i32TextureUnit );
		glBindTexture( GL_TEXTURE_2D, m_ui32WhiteTextureID );
		glEnable( GL_TEXTURE_2D );

		// Pass color from previous texture stage
		glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT );

		glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_INTERPOLATE_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_PREVIOUS_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA );

		// Modulate alpha
		glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE );
		glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PREVIOUS_EXT );
		glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA );

		i32TextureUnit++;

		glBlendEquation( GL_MIN );
		glBlendFunc( GL_ONE, GL_ONE );
	}



	// Calc mask coordinates
	Vector2C	rMaskTexCoords[4];

	// Mask Texcoords
	rMaskTexCoords[0] = pViewport->client_to_layout( Vector2C( (float32)i32X, (float32)i32Y ) ) * rMaskMat;
	rMaskTexCoords[1] = pViewport->client_to_layout( Vector2C( (float32)(i32X + m_i32TexCapturedWidth), (float32)i32Y ) ) * rMaskMat;
	rMaskTexCoords[2] = pViewport->client_to_layout( Vector2C( (float32)(i32X + m_i32TexCapturedWidth), (float32)(i32Y + m_i32TexCapturedHeight) ) ) * rMaskMat;
	rMaskTexCoords[3] = pViewport->client_to_layout( Vector2C( (float32)i32X, (float32)(i32Y + m_i32TexCapturedHeight) ) ) * rMaskMat;

	glBegin( GL_QUADS );

	if( i32MaskUnit != -1 )
		glMultiTexCoord2fARB( i32MaskUnit, rMaskTexCoords[0][0], rMaskTexCoords[0][1] );
	glMultiTexCoord2fARB( GL_TEXTURE1_ARB, f32TexX0, f32TexY0 );
	glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32TexX0, f32TexY0 );
	glVertex2f( (float32)i32X, (float32)i32Y );

	if( i32MaskUnit != -1 )
		glMultiTexCoord2fARB( i32MaskUnit, rMaskTexCoords[1][0], rMaskTexCoords[1][1] );
	glMultiTexCoord2fARB( GL_TEXTURE1_ARB, f32TexX1, f32TexY0 );
	glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32TexX1, f32TexY0 );
	glVertex2f( (float32)(i32X + m_i32TexCapturedWidth), (float32)i32Y );
	
	if( i32MaskUnit != -1 )
		glMultiTexCoord2fARB( i32MaskUnit, rMaskTexCoords[2][0], rMaskTexCoords[2][1] );
	glMultiTexCoord2fARB( GL_TEXTURE1_ARB, f32TexX1, f32TexY1 );
	glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32TexX1, f32TexY1 );
	glVertex2f( (float32)(i32X + m_i32TexCapturedWidth), (float32)(i32Y + m_i32TexCapturedHeight) );
	
	if( i32MaskUnit != -1 )
		glMultiTexCoord2fARB( i32MaskUnit, rMaskTexCoords[3][0], rMaskTexCoords[3][1] );
	glMultiTexCoord2fARB( GL_TEXTURE1_ARB, f32TexX0, f32TexY1 );
	glMultiTexCoord2fARB( GL_TEXTURE0_ARB, f32TexX0, f32TexY1 );
	glVertex2f( (float32)i32X, (float32)(i32Y + m_i32TexCapturedHeight) );

	glEnd();


	glEnable( GL_DEPTH_TEST );
	glDisable( GL_BLEND );
	glDepthMask( GL_TRUE );

	// Reset blend equ
	glBlendEquation( GL_FUNC_ADD );

	// Reset to default texture unit
	for( i = 0; i < i32TextureUnit; i++ )
	{
		glActiveTextureARB( GL_TEXTURE0_ARB + i );
		glDisable( GL_TEXTURE_2D );
		glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
	}
*/
}


BBox2C
DepthBlurEffectC::get_bbox()
{
	// Return the bounding box.
	return m_rBBox;
}

const Matrix2C&
DepthBlurEffectC::get_transform_matrix() const
{
	// Return the trnasformation matrix.
	return m_rTM;
}

bool
DepthBlurEffectC::hit_test( const Vector2C& rPoint )
{
	// Point in polygon test.
	// from c.g.a FAQ
	int		i, j;
	bool	bInside = false;

	for( i = 0, j = 4 - 1; i < 4; j = i++ ) {
		if( ( ((m_rVertices[i][1] <= rPoint[1]) && (rPoint[1] < m_rVertices[j][1])) ||
			((m_rVertices[j][1] <= rPoint[1]) && (rPoint[1] < m_rVertices[i][1])) ) &&
			(rPoint[0] < (m_rVertices[j][0] - m_rVertices[i][0]) * (rPoint[1] - m_rVertices[i][1]) / (m_rVertices[j][1] - m_rVertices[i][1]) + m_rVertices[i][0]) )

			bInside = !bInside;
	}

	return bInside;
}


enum DepthBlurEffectChunksE {
	CHUNK_DEPTHBLUR_BASE =			0x1000,
	CHUNK_DEPTHBLUR_TRANSGIZMO =		0x2000,
	CHUNK_DEPTHBLUR_ATTRIBGIZMO =	0x3000,
};

const uint32	DEPTHBLUR_VERSION = 1;

uint32
DepthBlurEffectC::save( SaveC* pSave )
{
	uint32	ui32Error = IO_OK;

	// EffectI base class
	pSave->begin_chunk( CHUNK_DEPTHBLUR_BASE, DEPTHBLUR_VERSION );
		ui32Error = EffectI::save( pSave );
	pSave->end_chunk();

	// Transform
	pSave->begin_chunk( CHUNK_DEPTHBLUR_TRANSGIZMO, DEPTHBLUR_VERSION );
		ui32Error = m_pTraGizmo->save( pSave );
	pSave->end_chunk();

	// Attribute
	pSave->begin_chunk( CHUNK_DEPTHBLUR_ATTRIBGIZMO, DEPTHBLUR_VERSION );
		ui32Error = m_pAttGizmo->save( pSave );
	pSave->end_chunk();

	return ui32Error;
}

uint32
DepthBlurEffectC::load( LoadC* pLoad )
{
	uint32	ui32Error = IO_OK;

	while( (ui32Error = pLoad->open_chunk()) == IO_OK ) {

		switch( pLoad->get_chunk_id() ) {
		case CHUNK_DEPTHBLUR_BASE:
			// EffectI base class
			if( pLoad->get_chunk_version() == DEPTHBLUR_VERSION )
				ui32Error = EffectI::load( pLoad );
			break;

		case CHUNK_DEPTHBLUR_TRANSGIZMO:
			// Transform
			if( pLoad->get_chunk_version() == DEPTHBLUR_VERSION )
				ui32Error = m_pTraGizmo->load( pLoad );
			break;

		case CHUNK_DEPTHBLUR_ATTRIBGIZMO:
			// Attribute
			if( pLoad->get_chunk_version() == DEPTHBLUR_VERSION )
				ui32Error = m_pAttGizmo->load( pLoad );
			break;

		default:
			assert( 0 );
		}

		pLoad->close_chunk();

		if( ui32Error != IO_OK && ui32Error != IO_END )
			return ui32Error;
	}

	return ui32Error;
}
