2009-05-08 13:28:41 +00:00
/*
* OpenClonk , http : //www.openclonk.org
*
2010-12-23 00:01:24 +00:00
* Copyright ( c ) 2002 , 2005 - 2006 , 2010 Sven Eberhardt
* Copyright ( c ) 2005 - 2010 G ü nther Brammer
2009-06-05 13:41:20 +00:00
* Copyright ( c ) 2007 Julian Raschke
* Copyright ( c ) 2008 Matthes Bender
2011-09-01 18:22:35 +00:00
* Copyright ( c ) 2009 Carl - Philip H ä nsch
2011-09-01 14:58:52 +00:00
* Copyright ( c ) 2009 - 2011 Armin Burgmeier
2010-12-23 00:01:24 +00:00
* Copyright ( c ) 2009 - 2010 Nicolas Hake
* Copyright ( c ) 2010 Benjamin Herr
2009-05-08 13:28:41 +00:00
* Copyright ( c ) 2001 - 2009 , RedWolf Design GmbH , http : //www.clonk.de
*
* Portions might be copyrighted by other authors who have contributed
* to OpenClonk .
*
* Permission to use , copy , modify , and / or distribute this software for any
* purpose with or without fee is hereby granted , provided that the above
* copyright notice and this permission notice appear in all copies .
* See isc_license . txt for full license and disclaimer .
*
* " Clonk " is a registered trademark of Matthes Bender .
* See clonk_trademark_license . txt for full license .
*/
/* OpenGL implementation of NewGfx */
2009-10-20 03:39:24 +00:00
# include "C4Include.h"
2012-04-27 17:04:43 +00:00
# include <C4DrawGL.h>
2011-11-01 22:17:41 +00:00
2011-10-03 14:06:41 +00:00
# include <C4Surface.h>
2011-10-03 15:19:24 +00:00
# include <C4Window.h>
2009-08-12 20:03:50 +00:00
# include "C4Rect.h"
2010-01-27 15:50:07 +00:00
# include "StdMesh.h"
2010-09-05 13:07:45 +00:00
# include "C4Config.h"
# include "C4Application.h"
2009-05-08 13:28:41 +00:00
# ifdef USE_GL
2010-01-26 18:35:15 +00:00
// MSVC doesn't define M_PI in math.h unless requested
# ifdef _MSC_VER
# define _USE_MATH_DEFINES
# endif /* _MSC_VER */
2009-05-08 13:28:41 +00:00
# include <stdio.h>
# include <math.h>
# include <limits.h>
static void glColorDw ( DWORD dwClr )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
glColor4ub ( GLubyte ( dwClr > > 16 ) , GLubyte ( dwClr > > 8 ) , GLubyte ( dwClr ) , GLubyte ( dwClr > > 24 ) ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// GLubyte (&r)[4] is a reference to an array of four bytes named r.
static void DwTo4UB ( DWORD dwClr , GLubyte ( & r ) [ 4 ] )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
//unsigned char r[4];
r [ 0 ] = GLubyte ( dwClr > > 16 ) ;
r [ 1 ] = GLubyte ( dwClr > > 8 ) ;
r [ 2 ] = GLubyte ( dwClr ) ;
r [ 3 ] = GLubyte ( dwClr > > 24 ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2010-03-06 14:07:30 +00:00
CStdGL : : CStdGL ( ) :
2010-03-28 18:58:01 +00:00
pMainCtx ( 0 )
{
2009-05-08 13:28:41 +00:00
Default ( ) ;
2010-03-06 14:07:30 +00:00
byByteCnt = 4 ;
2009-05-08 13:28:41 +00:00
// global ptr
pGL = this ;
shaders [ 0 ] = 0 ;
vbo = 0 ;
2010-03-18 12:52:09 +00:00
lines_tex = 0 ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
CStdGL : : ~ CStdGL ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
Clear ( ) ;
pGL = NULL ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void CStdGL : : Clear ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
NoPrimaryClipper ( ) ;
2010-12-29 14:19:46 +00:00
//if (pTexMgr) pTexMgr->IntUnlock(); // cannot do this here or we can't preserve textures across GL reinitialization as required when changing multisampling
2009-05-31 00:09:15 +00:00
InvalidateDeviceObjects ( ) ;
NoPrimaryClipper ( ) ;
RenderTarget = NULL ;
// clear context
if ( pCurrCtx ) pCurrCtx - > Deselect ( ) ;
2010-03-06 14:07:30 +00:00
pMainCtx = 0 ;
2011-10-03 14:34:08 +00:00
C4Draw : : Clear ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void CStdGL : : FillBG ( DWORD dwClr )
2010-03-28 18:58:01 +00:00
{
2010-03-06 14:07:30 +00:00
if ( ! pCurrCtx ) return ;
2011-03-11 02:37:27 +00:00
glClearColor ( ( float ) GetRedValue ( dwClr ) / 255.0f , ( float ) GetGreenValue ( dwClr ) / 255.0f , ( float ) GetBlueValue ( dwClr ) / 255.0f , 0.0f ) ;
2009-05-08 13:28:41 +00:00
glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool CStdGL : : UpdateClipper ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// no render target? do nothing
if ( ! RenderTarget | | ! Active ) return true ;
// negative/zero?
int iWdt = Min ( iClipX2 , RenderTarget - > Wdt - 1 ) - iClipX1 + 1 ;
int iHgt = Min ( iClipY2 , RenderTarget - > Hgt - 1 ) - iClipY1 + 1 ;
int iX = iClipX1 ; if ( iX < 0 ) { iWdt + = iX ; iX = 0 ; }
int iY = iClipY1 ; if ( iY < 0 ) { iHgt + = iY ; iY = 0 ; }
2010-12-29 14:19:46 +00:00
2009-05-08 13:28:41 +00:00
if ( iWdt < = 0 | | iHgt < = 0 )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
ClipAll = true ;
return true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
ClipAll = false ;
// set it
glViewport ( iX , RenderTarget - > Hgt - iY - iHgt , iWdt , iHgt ) ;
glMatrixMode ( GL_PROJECTION ) ;
glLoadIdentity ( ) ;
2009-09-10 02:54:12 +00:00
// Set clipping plane to -1000 and 1000 so that large meshes are not
// clipped away.
2010-02-06 17:33:30 +00:00
//glOrtho((GLdouble) iX, (GLdouble) (iX+iWdt), (GLdouble) (iY+iHgt), (GLdouble) iY, -1000.0f, 1000.0f);
gluOrtho2D ( ( GLdouble ) iX , ( GLdouble ) ( iX + iWdt ) , ( GLdouble ) ( iY + iHgt ) , ( GLdouble ) iY ) ;
2009-05-08 13:28:41 +00:00
//gluOrtho2D((GLdouble) 0, (GLdouble) xRes, (GLdouble) yRes, (GLdouble) yRes-iHgt);
return true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2010-01-02 02:26:47 +00:00
bool CStdGL : : PrepareMaterial ( StdMeshMaterial & mat )
{
// select context, if not already done
2010-03-06 14:07:30 +00:00
if ( ! pCurrCtx ) return false ;
2010-01-02 02:26:47 +00:00
2010-03-28 18:58:01 +00:00
for ( unsigned int i = 0 ; i < mat . Techniques . size ( ) ; + + i )
2010-01-02 02:26:47 +00:00
{
StdMeshMaterialTechnique & technique = mat . Techniques [ i ] ;
technique . Available = true ;
2010-03-28 18:58:01 +00:00
for ( unsigned int j = 0 ; j < technique . Passes . size ( ) ; + + j )
2010-01-02 02:26:47 +00:00
{
StdMeshMaterialPass & pass = technique . Passes [ j ] ;
2010-03-28 18:58:01 +00:00
2010-01-03 22:58:26 +00:00
GLint max_texture_units ;
glGetIntegerv ( GL_MAX_TEXTURE_UNITS , & max_texture_units ) ;
assert ( max_texture_units > = 1 ) ;
2010-04-05 15:02:41 +00:00
if ( pass . TextureUnits . size ( ) > static_cast < unsigned int > ( max_texture_units - 1 ) ) // One texture is reserved for clrmodmap as soon as we apply clrmodmap with a shader for meshes
2010-01-03 22:58:26 +00:00
technique . Available = false ;
2010-03-28 18:58:01 +00:00
for ( unsigned int k = 0 ; k < pass . TextureUnits . size ( ) ; + + k )
2010-01-02 02:26:47 +00:00
{
StdMeshMaterialTextureUnit & texunit = pass . TextureUnits [ k ] ;
2010-03-28 18:58:01 +00:00
for ( unsigned int l = 0 ; l < texunit . GetNumTextures ( ) ; + + l )
2010-01-02 02:26:47 +00:00
{
2011-10-03 14:16:38 +00:00
const C4TexRef & texture = texunit . GetTexture ( l ) ;
2010-03-16 22:31:53 +00:00
glBindTexture ( GL_TEXTURE_2D , texture . texName ) ;
2010-03-28 18:58:01 +00:00
switch ( texunit . TexAddressMode )
2010-01-03 22:58:26 +00:00
{
case StdMeshMaterialTextureUnit : : AM_Wrap :
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , GL_REPEAT ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T , GL_REPEAT ) ;
break ;
case StdMeshMaterialTextureUnit : : AM_Border :
glTexParameterfv ( GL_TEXTURE_2D , GL_TEXTURE_BORDER_COLOR , texunit . TexBorderColor ) ;
// fallthrough
case StdMeshMaterialTextureUnit : : AM_Clamp :
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , GL_CLAMP ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T , GL_CLAMP ) ;
break ;
case StdMeshMaterialTextureUnit : : AM_Mirror :
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , GL_MIRRORED_REPEAT ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T , GL_MIRRORED_REPEAT ) ;
break ;
}
2010-01-02 02:26:47 +00:00
2010-03-28 18:58:01 +00:00
if ( texunit . Filtering [ 2 ] = = StdMeshMaterialTextureUnit : : F_Point | |
texunit . Filtering [ 2 ] = = StdMeshMaterialTextureUnit : : F_Linear )
2010-01-03 22:58:26 +00:00
{
// If mipmapping is enabled, then autogenerate mipmap data.
// In OGRE this is deactivated for several OS/graphics card
// combinations because of known bugs...
// This does work for me, but requires re-upload of texture data...
// so the proper way would be to set this prior to the initial
// upload, which would be the same place where we could also use
// gluBuild2DMipmaps. GL_GENERATE_MIPMAP is probably still more
// efficient though.
2010-03-28 18:58:01 +00:00
2011-10-03 14:16:38 +00:00
// Disabled for now, until we find a better place for this (C4TexRef?)
2010-03-16 22:31:53 +00:00
#if 0
2010-03-28 18:58:01 +00:00
if ( GLEW_VERSION_1_4 )
2011-10-03 14:16:38 +00:00
{ glTexParameteri ( GL_TEXTURE_2D , GL_GENERATE_MIPMAP , GL_TRUE ) ; const_cast < C4TexRef * > ( & texunit . GetTexture ( ) ) - > Lock ( ) ; const_cast < C4TexRef * > ( & texunit . GetTexture ( ) ) - > Unlock ( ) ; }
2010-01-03 22:58:26 +00:00
else
technique . Available = false ;
2010-03-16 22:31:53 +00:00
# else
2010-01-03 22:58:26 +00:00
// Disable mipmap for now as a workaround.
texunit . Filtering [ 2 ] = StdMeshMaterialTextureUnit : : F_None ;
2010-03-16 22:31:53 +00:00
# endif
2010-01-03 22:58:26 +00:00
}
2010-01-02 02:26:47 +00:00
2010-03-28 18:58:01 +00:00
switch ( texunit . Filtering [ 0 ] ) // min
2010-01-02 02:26:47 +00:00
{
case StdMeshMaterialTextureUnit : : F_None :
2010-01-03 22:58:26 +00:00
technique . Available = false ;
2010-01-02 02:26:47 +00:00
break ;
case StdMeshMaterialTextureUnit : : F_Point :
2010-03-28 18:58:01 +00:00
switch ( texunit . Filtering [ 2 ] ) // mip
2010-01-03 22:58:26 +00:00
{
case StdMeshMaterialTextureUnit : : F_None :
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_NEAREST ) ;
break ;
case StdMeshMaterialTextureUnit : : F_Point :
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_NEAREST_MIPMAP_NEAREST ) ;
break ;
case StdMeshMaterialTextureUnit : : F_Linear :
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_NEAREST_MIPMAP_LINEAR ) ;
break ;
case StdMeshMaterialTextureUnit : : F_Anisotropic :
technique . Available = false ; // invalid
break ;
}
2010-01-02 02:26:47 +00:00
break ;
case StdMeshMaterialTextureUnit : : F_Linear :
2010-03-28 18:58:01 +00:00
switch ( texunit . Filtering [ 2 ] ) // mip
2010-01-03 22:58:26 +00:00
{
case StdMeshMaterialTextureUnit : : F_None :
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ;
break ;
case StdMeshMaterialTextureUnit : : F_Point :
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR_MIPMAP_NEAREST ) ;
break ;
case StdMeshMaterialTextureUnit : : F_Linear :
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR_MIPMAP_LINEAR ) ;
break ;
case StdMeshMaterialTextureUnit : : F_Anisotropic :
technique . Available = false ; // invalid
break ;
}
2010-01-02 02:26:47 +00:00
break ;
case StdMeshMaterialTextureUnit : : F_Anisotropic :
2010-01-03 22:58:26 +00:00
// unsupported
technique . Available = false ;
2010-01-02 02:26:47 +00:00
break ;
}
2010-01-03 22:58:26 +00:00
2010-03-28 18:58:01 +00:00
switch ( texunit . Filtering [ 1 ] ) // max
2010-01-02 02:26:47 +00:00
{
case StdMeshMaterialTextureUnit : : F_None :
2010-01-03 22:58:26 +00:00
technique . Available = false ; // invalid
2010-01-02 02:26:47 +00:00
break ;
case StdMeshMaterialTextureUnit : : F_Point :
2010-01-03 22:58:26 +00:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_NEAREST ) ;
2010-01-02 02:26:47 +00:00
break ;
case StdMeshMaterialTextureUnit : : F_Linear :
2010-01-03 22:58:26 +00:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
2010-01-02 02:26:47 +00:00
break ;
case StdMeshMaterialTextureUnit : : F_Anisotropic :
2010-01-03 22:58:26 +00:00
// unsupported
technique . Available = false ;
2010-01-02 02:26:47 +00:00
break ;
}
2010-03-17 19:19:14 +00:00
2010-03-28 18:58:01 +00:00
for ( unsigned int m = 0 ; m < texunit . Transformations . size ( ) ; + + m )
2010-03-17 19:19:14 +00:00
{
StdMeshMaterialTextureUnit : : Transformation & trans = texunit . Transformations [ m ] ;
2010-03-28 18:58:01 +00:00
if ( trans . TransformType = = StdMeshMaterialTextureUnit : : Transformation : : T_TRANSFORM )
2010-03-17 19:19:14 +00:00
{
// transpose so we can directly pass it to glMultMatrixf
std : : swap ( trans . Transform . M [ 1 ] , trans . Transform . M [ 4 ] ) ;
std : : swap ( trans . Transform . M [ 2 ] , trans . Transform . M [ 8 ] ) ;
std : : swap ( trans . Transform . M [ 3 ] , trans . Transform . M [ 12 ] ) ;
std : : swap ( trans . Transform . M [ 6 ] , trans . Transform . M [ 9 ] ) ;
std : : swap ( trans . Transform . M [ 7 ] , trans . Transform . M [ 13 ] ) ;
std : : swap ( trans . Transform . M [ 11 ] , trans . Transform . M [ 14 ] ) ;
}
}
2010-03-16 22:31:53 +00:00
} // loop over textures
2010-01-02 02:26:47 +00:00
2010-01-03 22:58:26 +00:00
// Check blending: Can only have one manual source color
2010-01-04 01:33:45 +00:00
unsigned int manu_count = 0 ;
2010-03-28 18:58:01 +00:00
if ( texunit . ColorOpEx = = StdMeshMaterialTextureUnit : : BOX_AddSmooth | | texunit . ColorOpEx = = StdMeshMaterialTextureUnit : : BOX_BlendManual )
2010-01-04 01:33:45 +00:00
+ + manu_count ;
2010-03-28 18:58:01 +00:00
if ( texunit . ColorOpSources [ 0 ] = = StdMeshMaterialTextureUnit : : BOS_PlayerColor | | texunit . ColorOpSources [ 0 ] = = StdMeshMaterialTextureUnit : : BOS_Manual )
2010-01-04 01:33:45 +00:00
+ + manu_count ;
2010-03-28 18:58:01 +00:00
if ( texunit . ColorOpSources [ 1 ] = = StdMeshMaterialTextureUnit : : BOS_PlayerColor | | texunit . ColorOpSources [ 1 ] = = StdMeshMaterialTextureUnit : : BOS_Manual )
2010-01-04 01:33:45 +00:00
+ + manu_count ;
2010-03-28 18:58:01 +00:00
if ( manu_count > 1 )
2010-01-04 01:33:45 +00:00
technique . Available = false ;
2010-03-28 18:58:01 +00:00
manu_count = 0 ;
if ( texunit . ColorOpEx = = StdMeshMaterialTextureUnit : : BOX_AddSmooth | | texunit . AlphaOpEx = = StdMeshMaterialTextureUnit : : BOX_BlendManual )
2010-01-04 01:33:45 +00:00
+ + manu_count ;
2010-03-28 18:58:01 +00:00
if ( texunit . AlphaOpSources [ 0 ] = = StdMeshMaterialTextureUnit : : BOS_PlayerColor | | texunit . AlphaOpSources [ 0 ] = = StdMeshMaterialTextureUnit : : BOS_Manual )
2010-01-04 01:33:45 +00:00
+ + manu_count ;
2010-03-28 18:58:01 +00:00
if ( texunit . AlphaOpSources [ 1 ] = = StdMeshMaterialTextureUnit : : BOS_PlayerColor | | texunit . AlphaOpSources [ 1 ] = = StdMeshMaterialTextureUnit : : BOS_Manual )
2010-01-04 01:33:45 +00:00
+ + manu_count ;
2010-03-28 18:58:01 +00:00
if ( manu_count > 1 )
2010-01-04 01:33:45 +00:00
technique . Available = false ;
2010-01-02 02:26:47 +00:00
}
}
2010-03-28 18:58:01 +00:00
if ( technique . Available & & mat . BestTechniqueIndex = = - 1 )
2010-01-02 02:26:47 +00:00
mat . BestTechniqueIndex = i ;
}
return mat . BestTechniqueIndex ! = - 1 ;
}
2011-10-03 14:07:07 +00:00
bool CStdGL : : PrepareRendering ( C4Surface * sfcToSurface )
2009-05-08 13:28:41 +00:00
{
// call from gfx thread only!
if ( ! pApp | | ! pApp - > AssertMainThread ( ) ) return false ;
// not ready?
if ( ! Active )
//if (!RestoreDeviceObjects())
2010-03-28 18:58:01 +00:00
return false ;
2009-05-08 13:28:41 +00:00
// target?
if ( ! sfcToSurface ) return false ;
// target locked?
if ( sfcToSurface - > Locked ) return false ;
// target is already set as render target?
if ( sfcToSurface ! = RenderTarget )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// target is a render-target?
if ( ! sfcToSurface - > IsRenderTarget ( ) ) return false ;
2010-03-06 14:07:30 +00:00
// context
if ( sfcToSurface - > pCtx & & sfcToSurface - > pCtx ! = pCurrCtx )
if ( ! sfcToSurface - > pCtx - > Select ( ) ) return false ;
2009-05-08 13:28:41 +00:00
// set target
RenderTarget = sfcToSurface ;
// new target has different size; needs other clipping rect
UpdateClipper ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// done
return true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2009-05-31 00:10:57 +00:00
void CStdGL : : SetupTextureEnv ( bool fMod2 , bool landscape )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( shaders [ 0 ] )
2010-03-28 18:58:01 +00:00
{
2009-05-31 00:10:57 +00:00
GLuint s = landscape ? 2 : ( fMod2 ? 1 : 0 ) ;
2009-05-08 13:28:41 +00:00
if ( Saturation < 255 )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
s + = 3 ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
if ( fUseClrModMap )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
s + = 6 ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
glBindProgramARB ( GL_FRAGMENT_PROGRAM_ARB , shaders [ s ] ) ;
if ( Saturation < 255 )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
GLfloat bla [ 4 ] = { Saturation / 255.0f , Saturation / 255.0f , Saturation / 255.0f , 1.0f } ;
glProgramLocalParameter4fvARB ( GL_FRAGMENT_PROGRAM_ARB , 0 , bla ) ;
}
2010-03-28 18:58:01 +00:00
}
2009-05-31 00:10:57 +00:00
// texture environment
2009-05-08 13:28:41 +00:00
else
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
glTexEnvi ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_COMBINE ) ;
glTexEnvi ( GL_TEXTURE_ENV , GL_COMBINE_RGB , fMod2 ? GL_ADD_SIGNED : GL_MODULATE ) ;
glTexEnvf ( GL_TEXTURE_ENV , GL_RGB_SCALE , fMod2 ? 2.0f : 1.0f ) ;
2010-01-02 02:26:47 +00:00
glTexEnvi ( GL_TEXTURE_ENV , GL_COMBINE_ALPHA , GL_MODULATE ) ;
2009-05-08 13:28:41 +00:00
glTexEnvi ( GL_TEXTURE_ENV , GL_SOURCE0_RGB , GL_TEXTURE ) ;
glTexEnvi ( GL_TEXTURE_ENV , GL_SOURCE1_RGB , GL_PRIMARY_COLOR ) ;
glTexEnvi ( GL_TEXTURE_ENV , GL_SOURCE0_ALPHA , GL_TEXTURE ) ;
glTexEnvi ( GL_TEXTURE_ENV , GL_SOURCE1_ALPHA , GL_PRIMARY_COLOR ) ;
glTexEnvi ( GL_TEXTURE_ENV , GL_OPERAND0_RGB , GL_SRC_COLOR ) ;
glTexEnvi ( GL_TEXTURE_ENV , GL_OPERAND1_RGB , GL_SRC_COLOR ) ;
glTexEnvi ( GL_TEXTURE_ENV , GL_OPERAND0_ALPHA , GL_SRC_ALPHA ) ;
glTexEnvi ( GL_TEXTURE_ENV , GL_OPERAND1_ALPHA , GL_SRC_ALPHA ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-31 00:10:57 +00:00
// set modes
2010-02-18 16:24:43 +00:00
glShadeModel ( ( fUseClrModMap & & ! shaders [ 0 ] ) ? GL_SMOOTH : GL_FLAT ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-31 00:10:57 +00:00
2011-10-03 14:16:38 +00:00
void CStdGL : : PerformBlt ( C4BltData & rBltData , C4TexRef * pTex , DWORD dwModClr , bool fMod2 , bool fExact )
2010-03-28 18:58:01 +00:00
{
2009-05-31 00:10:57 +00:00
// global modulation map
int i ;
2009-08-23 21:46:56 +00:00
bool fAnyModNotBlack = ( dwModClr ! = 0xff000000 ) ;
if ( ! shaders [ 0 ] & & fUseClrModMap & & dwModClr ! = 0xff000000 )
2010-03-28 18:58:01 +00:00
{
2009-05-31 00:10:57 +00:00
fAnyModNotBlack = false ;
for ( i = 0 ; i < rBltData . byNumVertices ; + + i )
2010-03-28 18:58:01 +00:00
{
2009-05-31 00:10:57 +00:00
float x = rBltData . vtVtx [ i ] . ftx ;
float y = rBltData . vtVtx [ i ] . fty ;
if ( rBltData . pTransform )
2010-03-28 18:58:01 +00:00
{
2009-05-31 00:10:57 +00:00
rBltData . pTransform - > TransformPoint ( x , y ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-31 00:10:57 +00:00
DWORD c = pClrModMap - > GetModAt ( int ( x ) , int ( y ) ) ;
ModulateClr ( c , dwModClr ) ;
2009-08-23 21:46:56 +00:00
if ( c ! = 0xff000000 ) fAnyModNotBlack = true ;
2009-05-31 00:10:57 +00:00
DwTo4UB ( c , rBltData . vtVtx [ i ] . color ) ;
}
2010-03-28 18:58:01 +00:00
}
2009-05-31 00:10:57 +00:00
else
2010-03-28 18:58:01 +00:00
{
2009-05-31 00:10:57 +00:00
for ( i = 0 ; i < rBltData . byNumVertices ; + + i )
DwTo4UB ( dwModClr , rBltData . vtVtx [ i ] . color ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-31 00:10:57 +00:00
// reset MOD2 for completely black modulations
fMod2 = fMod2 & & fAnyModNotBlack ;
SetupTextureEnv ( fMod2 , false ) ;
2009-05-08 13:28:41 +00:00
glBindTexture ( GL_TEXTURE_2D , pTex - > texName ) ;
2010-02-18 16:24:43 +00:00
if ( ! fExact )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
glMatrixMode ( GL_TEXTURE ) ;
2010-09-04 16:17:59 +00:00
/*float matrix[16];
2009-05-08 13:28:41 +00:00
matrix [ 0 ] = rBltData . TexPos . mat [ 0 ] ; matrix [ 1 ] = rBltData . TexPos . mat [ 3 ] ; matrix [ 2 ] = 0 ; matrix [ 3 ] = rBltData . TexPos . mat [ 6 ] ;
matrix [ 4 ] = rBltData . TexPos . mat [ 1 ] ; matrix [ 5 ] = rBltData . TexPos . mat [ 4 ] ; matrix [ 6 ] = 0 ; matrix [ 7 ] = rBltData . TexPos . mat [ 7 ] ;
matrix [ 8 ] = 0 ; matrix [ 9 ] = 0 ; matrix [ 10 ] = 1 ; matrix [ 11 ] = 0 ;
2009-05-31 00:10:57 +00:00
matrix [ 12 ] = rBltData . TexPos . mat [ 2 ] ; matrix [ 13 ] = rBltData . TexPos . mat [ 5 ] ; matrix [ 14 ] = 0 ; matrix [ 15 ] = rBltData . TexPos . mat [ 8 ] ;
2010-09-04 16:17:59 +00:00
glLoadMatrixf ( matrix ) ; */
glLoadIdentity ( ) ;
2009-05-08 13:28:41 +00:00
if ( shaders [ 0 ] & & fUseClrModMap )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
glActiveTexture ( GL_TEXTURE3 ) ;
glLoadIdentity ( ) ;
2011-10-03 14:06:41 +00:00
C4Surface * pSurface = pClrModMap - > GetSurface ( ) ;
2010-09-04 17:30:45 +00:00
glScalef ( 1.0f / ( pClrModMap - > GetResolutionX ( ) * ( * pSurface - > ppTex ) - > iSizeX ) , 1.0f / ( pClrModMap - > GetResolutionY ( ) * ( * pSurface - > ppTex ) - > iSizeY ) , 1.0f ) ;
2009-05-08 13:28:41 +00:00
glTranslatef ( float ( - pClrModMap - > OffX ) , float ( - pClrModMap - > OffY ) , 0.0f ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
if ( rBltData . pTransform )
2010-03-28 18:58:01 +00:00
{
2011-09-18 13:54:22 +00:00
const float * mat = rBltData . pTransform - > mat ;
2010-09-04 16:17:59 +00:00
float matrix [ 16 ] ;
2009-05-08 13:28:41 +00:00
matrix [ 0 ] = mat [ 0 ] ; matrix [ 1 ] = mat [ 3 ] ; matrix [ 2 ] = 0 ; matrix [ 3 ] = mat [ 6 ] ;
matrix [ 4 ] = mat [ 1 ] ; matrix [ 5 ] = mat [ 4 ] ; matrix [ 6 ] = 0 ; matrix [ 7 ] = mat [ 7 ] ;
matrix [ 8 ] = 0 ; matrix [ 9 ] = 0 ; matrix [ 10 ] = 1 ; matrix [ 11 ] = 0 ;
2010-03-28 18:58:01 +00:00
matrix [ 12 ] = mat [ 2 ] ; matrix [ 13 ] = mat [ 5 ] ; matrix [ 14 ] = 0 ; matrix [ 15 ] = mat [ 8 ] ;
2009-05-08 13:28:41 +00:00
if ( shaders [ 0 ] & & fUseClrModMap )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
glMultMatrixf ( matrix ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
glActiveTexture ( GL_TEXTURE0 ) ;
glMatrixMode ( GL_MODELVIEW ) ;
glLoadMatrixf ( matrix ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
glActiveTexture ( GL_TEXTURE0 ) ;
glMatrixMode ( GL_MODELVIEW ) ;
glLoadIdentity ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// draw polygon
for ( i = 0 ; i < rBltData . byNumVertices ; + + i )
2010-03-28 18:58:01 +00:00
{
2010-09-04 16:17:59 +00:00
//rBltData.vtVtx[i].tx = rBltData.vtVtx[i].ftx;
//rBltData.vtVtx[i].ty = rBltData.vtVtx[i].fty;
2009-05-08 13:28:41 +00:00
//if (rBltData.pTransform) rBltData.pTransform->TransformPoint(rBltData.vtVtx[i].ftx, rBltData.vtVtx[i].fty);
rBltData . vtVtx [ i ] . ftz = 0 ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
if ( vbo )
2010-03-28 18:58:01 +00:00
{
2011-09-30 20:15:51 +00:00
glBufferDataARB ( GL_ARRAY_BUFFER_ARB , rBltData . byNumVertices * sizeof ( C4BltVertex ) , rBltData . vtVtx , GL_STREAM_DRAW_ARB ) ;
glInterleavedArrays ( GL_T2F_C4UB_V3F , sizeof ( C4BltVertex ) , 0 ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else
2010-03-28 18:58:01 +00:00
{
2011-09-30 20:15:51 +00:00
glInterleavedArrays ( GL_T2F_C4UB_V3F , sizeof ( C4BltVertex ) , rBltData . vtVtx ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
if ( shaders [ 0 ] & & fUseClrModMap )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
glClientActiveTexture ( GL_TEXTURE3 ) ;
glEnableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
2011-09-30 20:15:51 +00:00
glTexCoordPointer ( 2 , GL_FLOAT , sizeof ( C4BltVertex ) , & rBltData . vtVtx [ 0 ] . ftx ) ;
2009-05-08 13:28:41 +00:00
glClientActiveTexture ( GL_TEXTURE0 ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
glDrawArrays ( GL_POLYGON , 0 , rBltData . byNumVertices ) ;
2011-01-02 19:33:45 +00:00
if ( shaders [ 0 ] & & fUseClrModMap )
{
glClientActiveTexture ( GL_TEXTURE3 ) ;
glDisableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
glClientActiveTexture ( GL_TEXTURE0 ) ;
}
2009-05-08 13:28:41 +00:00
glLoadIdentity ( ) ;
2010-02-18 16:24:43 +00:00
if ( ! fExact )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_NEAREST ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_NEAREST ) ;
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2010-01-03 22:58:26 +00:00
namespace
{
inline void SetTexCombine ( GLenum combine , StdMeshMaterialTextureUnit : : BlendOpExType blendop )
{
2010-03-28 18:58:01 +00:00
switch ( blendop )
2010-01-03 22:58:26 +00:00
{
case StdMeshMaterialTextureUnit : : BOX_Source1 :
case StdMeshMaterialTextureUnit : : BOX_Source2 :
glTexEnvi ( GL_TEXTURE_ENV , combine , GL_REPLACE ) ;
break ;
case StdMeshMaterialTextureUnit : : BOX_Modulate :
case StdMeshMaterialTextureUnit : : BOX_ModulateX2 :
case StdMeshMaterialTextureUnit : : BOX_ModulateX4 :
glTexEnvi ( GL_TEXTURE_ENV , combine , GL_MODULATE ) ;
break ;
case StdMeshMaterialTextureUnit : : BOX_Add :
glTexEnvi ( GL_TEXTURE_ENV , combine , GL_ADD ) ;
break ;
case StdMeshMaterialTextureUnit : : BOX_AddSigned :
glTexEnvi ( GL_TEXTURE_ENV , combine , GL_ADD_SIGNED ) ;
break ;
case StdMeshMaterialTextureUnit : : BOX_AddSmooth :
// b+c-b*c == a*c + b*(1-c) for a==1.
glTexEnvi ( GL_TEXTURE_ENV , combine , GL_INTERPOLATE ) ;
break ;
case StdMeshMaterialTextureUnit : : BOX_Subtract :
glTexEnvi ( GL_TEXTURE_ENV , combine , GL_SUBTRACT ) ;
break ;
case StdMeshMaterialTextureUnit : : BOX_BlendDiffuseAlpha :
case StdMeshMaterialTextureUnit : : BOX_BlendTextureAlpha :
case StdMeshMaterialTextureUnit : : BOX_BlendCurrentAlpha :
case StdMeshMaterialTextureUnit : : BOX_BlendManual :
glTexEnvi ( GL_TEXTURE_ENV , combine , GL_INTERPOLATE ) ;
break ;
case StdMeshMaterialTextureUnit : : BOX_Dotproduct :
glTexEnvi ( GL_TEXTURE_ENV , combine , GL_DOT3_RGB ) ;
break ;
case StdMeshMaterialTextureUnit : : BOX_BlendDiffuseColor :
glTexEnvi ( GL_TEXTURE_ENV , combine , GL_INTERPOLATE ) ;
break ;
}
}
inline void SetTexScale ( GLenum scale , StdMeshMaterialTextureUnit : : BlendOpExType blendop )
{
2010-03-28 18:58:01 +00:00
switch ( blendop )
2010-01-03 22:58:26 +00:00
{
case StdMeshMaterialTextureUnit : : BOX_Source1 :
case StdMeshMaterialTextureUnit : : BOX_Source2 :
case StdMeshMaterialTextureUnit : : BOX_Modulate :
glTexEnvf ( GL_TEXTURE_ENV , scale , 1.0f ) ;
break ;
case StdMeshMaterialTextureUnit : : BOX_ModulateX2 :
glTexEnvf ( GL_TEXTURE_ENV , scale , 2.0f ) ;
break ;
case StdMeshMaterialTextureUnit : : BOX_ModulateX4 :
glTexEnvf ( GL_TEXTURE_ENV , scale , 4.0f ) ;
break ;
case StdMeshMaterialTextureUnit : : BOX_Add :
case StdMeshMaterialTextureUnit : : BOX_AddSigned :
case StdMeshMaterialTextureUnit : : BOX_AddSmooth :
case StdMeshMaterialTextureUnit : : BOX_Subtract :
case StdMeshMaterialTextureUnit : : BOX_BlendDiffuseAlpha :
case StdMeshMaterialTextureUnit : : BOX_BlendTextureAlpha :
case StdMeshMaterialTextureUnit : : BOX_BlendCurrentAlpha :
case StdMeshMaterialTextureUnit : : BOX_BlendManual :
case StdMeshMaterialTextureUnit : : BOX_Dotproduct :
case StdMeshMaterialTextureUnit : : BOX_BlendDiffuseColor :
glTexEnvf ( GL_TEXTURE_ENV , scale , 1.0f ) ;
break ;
}
}
2010-03-28 18:58:01 +00:00
2010-01-03 22:58:26 +00:00
inline void SetTexSource ( GLenum source , StdMeshMaterialTextureUnit : : BlendOpSourceType blendsource )
{
2010-03-28 18:58:01 +00:00
switch ( blendsource )
2010-01-03 22:58:26 +00:00
{
case StdMeshMaterialTextureUnit : : BOS_Current :
glTexEnvi ( GL_TEXTURE_ENV , source , GL_PREVIOUS ) ;
break ;
case StdMeshMaterialTextureUnit : : BOS_Texture :
glTexEnvi ( GL_TEXTURE_ENV , source , GL_TEXTURE ) ;
break ;
case StdMeshMaterialTextureUnit : : BOS_Diffuse :
case StdMeshMaterialTextureUnit : : BOS_Specular :
glTexEnvi ( GL_TEXTURE_ENV , source , GL_PRIMARY_COLOR ) ;
break ;
case StdMeshMaterialTextureUnit : : BOS_PlayerColor :
glTexEnvi ( GL_TEXTURE_ENV , source , GL_CONSTANT ) ;
break ;
case StdMeshMaterialTextureUnit : : BOS_Manual :
glTexEnvi ( GL_TEXTURE_ENV , source , GL_CONSTANT ) ;
break ;
}
}
2010-03-28 18:58:01 +00:00
2010-01-03 22:58:26 +00:00
inline void SetTexSource2 ( GLenum source , StdMeshMaterialTextureUnit : : BlendOpExType blendop )
{
// Set Arg2 for interpolate (Arg0 for BOX_Add_Smooth)
2010-03-28 18:58:01 +00:00
switch ( blendop )
2010-01-03 22:58:26 +00:00
{
case StdMeshMaterialTextureUnit : : BOX_AddSmooth :
glTexEnvi ( GL_TEXTURE_ENV , source , GL_CONSTANT ) ; // 1.0, Set in SetTexColor
break ;
case StdMeshMaterialTextureUnit : : BOX_BlendDiffuseAlpha :
glTexEnvi ( GL_TEXTURE_ENV , source , GL_PRIMARY_COLOR ) ;
break ;
case StdMeshMaterialTextureUnit : : BOX_BlendTextureAlpha :
glTexEnvi ( GL_TEXTURE_ENV , source , GL_TEXTURE ) ;
break ;
case StdMeshMaterialTextureUnit : : BOX_BlendCurrentAlpha :
glTexEnvi ( GL_TEXTURE_ENV , source , GL_PREVIOUS ) ;
break ;
case StdMeshMaterialTextureUnit : : BOX_BlendManual :
glTexEnvi ( GL_TEXTURE_ENV , source , GL_CONSTANT ) ; // Set in SetTexColor
break ;
case StdMeshMaterialTextureUnit : : BOX_BlendDiffuseColor :
// difference to BOX_Blend_Diffuse_Alpha is operand, see SetTexOperand2
glTexEnvi ( GL_TEXTURE_ENV , source , GL_PRIMARY_COLOR ) ;
break ;
2010-01-25 04:00:59 +00:00
default :
// TODO
break ;
2010-01-03 22:58:26 +00:00
}
}
inline void SetTexOperand2 ( GLenum operand , StdMeshMaterialTextureUnit : : BlendOpExType blendop )
{
2010-03-28 18:58:01 +00:00
switch ( blendop )
2010-01-03 22:58:26 +00:00
{
case StdMeshMaterialTextureUnit : : BOX_Add :
case StdMeshMaterialTextureUnit : : BOX_AddSigned :
case StdMeshMaterialTextureUnit : : BOX_AddSmooth :
case StdMeshMaterialTextureUnit : : BOX_Subtract :
glTexEnvi ( GL_TEXTURE_ENV , operand , GL_SRC_COLOR ) ;
break ;
case StdMeshMaterialTextureUnit : : BOX_BlendDiffuseAlpha :
case StdMeshMaterialTextureUnit : : BOX_BlendTextureAlpha :
case StdMeshMaterialTextureUnit : : BOX_BlendCurrentAlpha :
case StdMeshMaterialTextureUnit : : BOX_BlendManual :
glTexEnvi ( GL_TEXTURE_ENV , operand , GL_SRC_ALPHA ) ;
break ;
case StdMeshMaterialTextureUnit : : BOX_Dotproduct :
case StdMeshMaterialTextureUnit : : BOX_BlendDiffuseColor :
glTexEnvi ( GL_TEXTURE_ENV , operand , GL_SRC_COLOR ) ;
break ;
2010-01-25 04:00:59 +00:00
default :
// TODO
break ;
2010-01-03 22:58:26 +00:00
}
}
inline void SetTexColor ( const StdMeshMaterialTextureUnit & texunit , DWORD PlayerColor )
{
float Color [ 4 ] = { 0.0f , 0.0f , 0.0f , 0.0f } ;
2010-03-28 18:58:01 +00:00
if ( texunit . ColorOpEx = = StdMeshMaterialTextureUnit : : BOX_AddSmooth )
2010-01-03 22:58:26 +00:00
{
Color [ 0 ] = Color [ 1 ] = Color [ 2 ] = 1.0f ;
}
2010-03-28 18:58:01 +00:00
else if ( texunit . ColorOpEx = = StdMeshMaterialTextureUnit : : BOX_BlendManual )
2010-01-03 22:58:26 +00:00
{
// operand of GL_CONSTANT is set to alpha for this blend mode
// see SetTexOperand2
Color [ 3 ] = texunit . ColorOpManualFactor ;
}
2010-03-28 18:58:01 +00:00
else if ( texunit . ColorOpSources [ 0 ] = = StdMeshMaterialTextureUnit : : BOS_PlayerColor | | texunit . ColorOpSources [ 1 ] = = StdMeshMaterialTextureUnit : : BOS_PlayerColor )
2010-01-03 22:58:26 +00:00
{
Color [ 0 ] = ( ( PlayerColor > > 16 ) & 0xff ) / 255.0f ;
Color [ 1 ] = ( ( PlayerColor > > 8 ) & 0xff ) / 255.0f ;
Color [ 2 ] = ( ( PlayerColor ) & 0xff ) / 255.0f ;
}
2010-03-28 18:58:01 +00:00
else if ( texunit . ColorOpSources [ 0 ] = = StdMeshMaterialTextureUnit : : BOS_Manual )
2010-01-03 22:58:26 +00:00
{
Color [ 0 ] = texunit . ColorOpManualColor1 [ 0 ] ;
Color [ 1 ] = texunit . ColorOpManualColor1 [ 1 ] ;
Color [ 2 ] = texunit . ColorOpManualColor1 [ 2 ] ;
}
2010-03-28 18:58:01 +00:00
else if ( texunit . ColorOpSources [ 1 ] = = StdMeshMaterialTextureUnit : : BOS_Manual )
2010-01-03 22:58:26 +00:00
{
Color [ 0 ] = texunit . ColorOpManualColor2 [ 0 ] ;
Color [ 1 ] = texunit . ColorOpManualColor2 [ 1 ] ;
Color [ 2 ] = texunit . ColorOpManualColor2 [ 2 ] ;
}
2010-03-28 18:58:01 +00:00
if ( texunit . AlphaOpEx = = StdMeshMaterialTextureUnit : : BOX_AddSmooth )
2010-01-03 22:58:26 +00:00
Color [ 3 ] = 1.0f ;
2010-03-28 18:58:01 +00:00
else if ( texunit . AlphaOpEx = = StdMeshMaterialTextureUnit : : BOX_BlendManual )
2010-01-03 22:58:26 +00:00
Color [ 3 ] = texunit . AlphaOpManualFactor ;
2010-03-28 18:58:01 +00:00
else if ( texunit . AlphaOpSources [ 0 ] = = StdMeshMaterialTextureUnit : : BOS_PlayerColor | | texunit . AlphaOpSources [ 1 ] = = StdMeshMaterialTextureUnit : : BOS_PlayerColor )
2010-01-03 22:58:26 +00:00
Color [ 3 ] = ( ( PlayerColor > > 24 ) & 0xff ) / 255.0f ;
2010-03-28 18:58:01 +00:00
else if ( texunit . AlphaOpSources [ 0 ] = = StdMeshMaterialTextureUnit : : BOS_Manual )
2010-01-03 22:58:26 +00:00
Color [ 3 ] = texunit . AlphaOpManualAlpha1 ;
2010-03-28 18:58:01 +00:00
else if ( texunit . AlphaOpSources [ 1 ] = = StdMeshMaterialTextureUnit : : BOS_Manual )
2010-01-03 22:58:26 +00:00
Color [ 3 ] = texunit . AlphaOpManualAlpha2 ;
glTexEnvfv ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_COLOR , Color ) ;
}
2010-01-11 23:54:36 +00:00
2010-06-08 22:55:34 +00:00
inline GLenum OgreBlendTypeToGL ( StdMeshMaterialPass : : SceneBlendType blend )
{
switch ( blend )
{
case StdMeshMaterialPass : : SB_One : return GL_ONE ;
case StdMeshMaterialPass : : SB_Zero : return GL_ZERO ;
case StdMeshMaterialPass : : SB_DestColor : return GL_DST_COLOR ;
case StdMeshMaterialPass : : SB_SrcColor : return GL_SRC_COLOR ;
case StdMeshMaterialPass : : SB_OneMinusDestColor : return GL_ONE_MINUS_DST_COLOR ;
case StdMeshMaterialPass : : SB_OneMinusSrcColor : return GL_ONE_MINUS_SRC_COLOR ;
case StdMeshMaterialPass : : SB_DestAlpha : return GL_DST_ALPHA ;
case StdMeshMaterialPass : : SB_SrcAlpha : return GL_SRC_ALPHA ;
case StdMeshMaterialPass : : SB_OneMinusDestAlpha : return GL_ONE_MINUS_DST_ALPHA ;
case StdMeshMaterialPass : : SB_OneMinusSrcAlpha : return GL_ONE_MINUS_SRC_ALPHA ;
default : assert ( false ) ; return GL_ZERO ;
}
}
2012-02-15 22:04:19 +00:00
void RenderSubMeshImpl ( const StdMeshInstance & mesh_instance , const StdSubMeshInstance & instance , DWORD dwModClr , DWORD dwBlitMode , DWORD dwPlayerColor , bool parity )
2010-01-10 21:02:40 +00:00
{
2010-03-16 22:31:53 +00:00
const StdMeshMaterial & material = instance . GetMaterial ( ) ;
2010-01-10 21:02:40 +00:00
assert ( material . BestTechniqueIndex ! = - 1 ) ;
const StdMeshMaterialTechnique & technique = material . Techniques [ material . BestTechniqueIndex ] ;
2012-02-15 22:04:19 +00:00
const StdMeshVertex * vertices = instance . GetVertices ( ) . empty ( ) ? & mesh_instance . GetSharedVertices ( ) [ 0 ] : & instance . GetVertices ( ) [ 0 ] ;
2010-01-10 21:02:40 +00:00
// Render each pass
2010-03-28 18:58:01 +00:00
for ( unsigned int i = 0 ; i < technique . Passes . size ( ) ; + + i )
2010-01-10 21:02:40 +00:00
{
const StdMeshMaterialPass & pass = technique . Passes [ i ] ;
2010-01-12 20:30:36 +00:00
glDepthMask ( pass . DepthWrite ? GL_TRUE : GL_FALSE ) ;
2012-02-13 22:40:47 +00:00
if ( pass . AlphaToCoverage )
glEnable ( GL_SAMPLE_ALPHA_TO_COVERAGE ) ;
else
glDisable ( GL_SAMPLE_ALPHA_TO_COVERAGE ) ;
2010-01-10 21:02:40 +00:00
// Apply ClrMod to material
2010-04-05 15:02:41 +00:00
// TODO: ClrModMap is not taken into account by this; we should just check
// mesh center.
// TODO: Or in case we have shaders enabled use the shader... note the
// clrmodmap texture needs to be the last texture in that case... we should
// change the index to maxtextures-1 instead of 3.
2011-12-25 17:55:45 +00:00
const float dwMod [ 4 ] = {
( ( dwModClr > > 16 ) & 0xff ) / 255.0f ,
( ( dwModClr > > 8 ) & 0xff ) / 255.0f ,
( ( dwModClr ) & 0xff ) / 255.0f ,
( ( dwModClr > > 24 ) & 0xff ) / 255.0f
} ;
2010-06-08 22:55:34 +00:00
if ( ! ( dwBlitMode & C4GFXBLIT_MOD2 ) & & dwModClr = = 0xffffffff )
2010-04-05 15:02:41 +00:00
{
// Fastpath for the easy case
2010-07-19 23:33:49 +00:00
glMaterialfv ( GL_FRONT_AND_BACK , GL_AMBIENT , pass . Ambient ) ;
glMaterialfv ( GL_FRONT_AND_BACK , GL_DIFFUSE , pass . Diffuse ) ;
glMaterialfv ( GL_FRONT_AND_BACK , GL_SPECULAR , pass . Specular ) ;
glMaterialfv ( GL_FRONT_AND_BACK , GL_EMISSION , pass . Emissive ) ;
glMaterialf ( GL_FRONT_AND_BACK , GL_SHININESS , pass . Shininess ) ;
2010-04-05 15:02:41 +00:00
}
else
{
float Ambient [ 4 ] , Diffuse [ 4 ] , Specular [ 4 ] , Emissive [ 4 ] ;
// TODO: We could also consider applying dwmod using an additional
// texture unit, maybe we can even re-use the one which is reserved for
// the clrmodmap texture anyway (+adapt the shader).
2010-06-08 22:55:34 +00:00
if ( ! ( dwBlitMode & C4GFXBLIT_MOD2 ) )
2010-04-05 15:02:41 +00:00
{
Ambient [ 0 ] = pass . Ambient [ 0 ] * dwMod [ 0 ] ;
Ambient [ 1 ] = pass . Ambient [ 1 ] * dwMod [ 1 ] ;
Ambient [ 2 ] = pass . Ambient [ 2 ] * dwMod [ 2 ] ;
Ambient [ 3 ] = pass . Ambient [ 3 ] * dwMod [ 3 ] ;
Diffuse [ 0 ] = pass . Diffuse [ 0 ] * dwMod [ 0 ] ;
Diffuse [ 1 ] = pass . Diffuse [ 1 ] * dwMod [ 1 ] ;
Diffuse [ 2 ] = pass . Diffuse [ 2 ] * dwMod [ 2 ] ;
Diffuse [ 3 ] = pass . Diffuse [ 3 ] * dwMod [ 3 ] ;
Specular [ 0 ] = pass . Specular [ 0 ] * dwMod [ 0 ] ;
Specular [ 1 ] = pass . Specular [ 1 ] * dwMod [ 1 ] ;
Specular [ 2 ] = pass . Specular [ 2 ] * dwMod [ 2 ] ;
Specular [ 3 ] = pass . Specular [ 3 ] * dwMod [ 3 ] ;
Emissive [ 0 ] = pass . Emissive [ 0 ] * dwMod [ 0 ] ;
Emissive [ 1 ] = pass . Emissive [ 1 ] * dwMod [ 1 ] ;
Emissive [ 2 ] = pass . Emissive [ 2 ] * dwMod [ 2 ] ;
Emissive [ 3 ] = pass . Emissive [ 3 ] * dwMod [ 3 ] ;
}
else
{
2011-12-25 17:55:45 +00:00
// The RGB part for fMod2 drawing is set in the texture unit,
// since its effect cannot be achieved properly by playing with
// the material color.
// TODO: This should go into an additional texture unit.
Ambient [ 0 ] = pass . Ambient [ 0 ] ;
Ambient [ 1 ] = pass . Ambient [ 1 ] ;
Ambient [ 2 ] = pass . Ambient [ 2 ] ;
Ambient [ 3 ] = pass . Ambient [ 3 ] ;
Diffuse [ 0 ] = pass . Diffuse [ 0 ] ;
Diffuse [ 1 ] = pass . Diffuse [ 1 ] ;
Diffuse [ 2 ] = pass . Diffuse [ 2 ] ;
Diffuse [ 3 ] = pass . Diffuse [ 3 ] ;
Specular [ 0 ] = pass . Specular [ 0 ] ;
Specular [ 1 ] = pass . Specular [ 1 ] ;
Specular [ 2 ] = pass . Specular [ 2 ] ;
Specular [ 3 ] = pass . Specular [ 3 ] ;
Emissive [ 0 ] = pass . Emissive [ 0 ] ;
Emissive [ 1 ] = pass . Emissive [ 1 ] ;
Emissive [ 2 ] = pass . Emissive [ 2 ] ;
Emissive [ 3 ] = pass . Emissive [ 3 ] ;
2010-04-05 15:02:41 +00:00
}
2010-07-19 23:33:49 +00:00
glMaterialfv ( GL_FRONT_AND_BACK , GL_AMBIENT , Ambient ) ;
glMaterialfv ( GL_FRONT_AND_BACK , GL_DIFFUSE , Diffuse ) ;
glMaterialfv ( GL_FRONT_AND_BACK , GL_SPECULAR , Specular ) ;
glMaterialfv ( GL_FRONT_AND_BACK , GL_EMISSION , Emissive ) ;
glMaterialf ( GL_FRONT_AND_BACK , GL_SHININESS , pass . Shininess ) ;
2010-04-05 15:02:41 +00:00
}
2010-01-10 21:02:40 +00:00
2010-07-19 23:33:49 +00:00
// Use two-sided light model so that vertex normals are inverted for lighting calculation on back-facing polygons
glLightModeli ( GL_LIGHT_MODEL_TWO_SIDE , 1 ) ;
glFrontFace ( parity ? GL_CW : GL_CCW ) ;
2012-02-26 00:09:42 +00:00
if ( mesh_instance . GetCompletion ( ) < 1.0f )
2010-01-29 14:58:33 +00:00
{
2012-02-26 00:09:42 +00:00
// Backfaces might be visible when completion is < 1.0f since front
// faces might be omitted.
2010-01-29 14:58:33 +00:00
glDisable ( GL_CULL_FACE ) ;
2012-02-26 00:09:42 +00:00
}
else
{
switch ( pass . CullHardware )
{
case StdMeshMaterialPass : : CH_Clockwise :
glEnable ( GL_CULL_FACE ) ;
glCullFace ( GL_BACK ) ;
break ;
case StdMeshMaterialPass : : CH_CounterClockwise :
glEnable ( GL_CULL_FACE ) ;
glCullFace ( GL_FRONT ) ;
break ;
case StdMeshMaterialPass : : CH_None :
glDisable ( GL_CULL_FACE ) ;
break ;
}
2010-01-29 14:58:33 +00:00
}
2010-08-14 10:23:45 +00:00
// Overwrite blend mode with default alpha blending when alpha in clrmod
// is <255. This makes sure that normal non-blended meshes can have
// blending disabled in their material script (which disables expensive
// face ordering) but when they are made translucent via clrmod
2010-06-08 22:55:34 +00:00
if ( ! ( dwBlitMode & C4GFXBLIT_ADDITIVE ) )
{
2011-12-25 17:55:45 +00:00
if ( ( ( dwModClr > > 24 ) & 0xff ) < 0xff ) // && (!(dwBlitMode & C4GFXBLIT_MOD2)) )
2010-08-14 10:23:45 +00:00
glBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ;
else
glBlendFunc ( OgreBlendTypeToGL ( pass . SceneBlendFactors [ 0 ] ) ,
OgreBlendTypeToGL ( pass . SceneBlendFactors [ 1 ] ) ) ;
2010-06-08 22:55:34 +00:00
}
else
{
2011-12-25 17:55:45 +00:00
if ( ( ( dwModClr > > 24 ) & 0xff ) < 0xff ) // && (!(dwBlitMode & C4GFXBLIT_MOD2)) )
2010-08-14 10:23:45 +00:00
glBlendFunc ( GL_SRC_ALPHA , GL_ONE ) ;
else
glBlendFunc ( OgreBlendTypeToGL ( pass . SceneBlendFactors [ 0 ] ) , GL_ONE ) ;
2010-06-08 22:55:34 +00:00
}
2010-01-10 21:02:40 +00:00
// TODO: Use vbo if available.
2010-08-14 10:23:45 +00:00
2012-04-07 14:47:23 +00:00
glVertexPointer ( 3 , GL_FLOAT , sizeof ( StdMeshVertex ) , & vertices - > x ) ;
glNormalPointer ( GL_FLOAT , sizeof ( StdMeshVertex ) , & vertices - > nx ) ;
2010-01-10 21:02:40 +00:00
glMatrixMode ( GL_TEXTURE ) ;
GLuint have_texture = 0 ;
2010-03-28 18:58:01 +00:00
for ( unsigned int j = 0 ; j < pass . TextureUnits . size ( ) ; + + j )
2010-01-10 21:02:40 +00:00
{
// Note that it is guaranteed that the GL_TEXTUREn
// constants are contiguous.
2010-04-05 15:02:41 +00:00
glActiveTexture ( GL_TEXTURE0 + j ) ;
glClientActiveTexture ( GL_TEXTURE0 + j ) ;
2010-03-28 18:58:01 +00:00
2010-01-10 21:02:40 +00:00
const StdMeshMaterialTextureUnit & texunit = pass . TextureUnits [ j ] ;
2010-07-19 23:33:49 +00:00
glEnable ( GL_TEXTURE_2D ) ;
2010-03-28 18:58:01 +00:00
if ( texunit . HasTexture ( ) )
2010-01-10 21:02:40 +00:00
{
2010-03-16 22:31:53 +00:00
const unsigned int Phase = instance . GetTexturePhase ( i , j ) ;
have_texture = texunit . GetTexture ( Phase ) . texName ;
2010-03-17 12:43:17 +00:00
glBindTexture ( GL_TEXTURE_2D , texunit . GetTexture ( Phase ) . texName ) ;
2010-01-10 21:02:40 +00:00
}
else
{
// We need to bind a valid texture here, even if the texture unit
2010-04-05 15:02:41 +00:00
// does not access the texture.
// TODO: Could use StdGL::lines_tex... this function should be a
// member of StdGL anyway.
2010-01-10 21:02:40 +00:00
glBindTexture ( GL_TEXTURE_2D , have_texture ) ;
}
glEnableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
2012-02-15 22:04:19 +00:00
glTexCoordPointer ( 2 , GL_FLOAT , sizeof ( StdMeshVertex ) , & vertices - > u ) ;
2010-03-17 19:19:14 +00:00
// Setup texture coordinate transform
2010-01-10 21:02:40 +00:00
glLoadIdentity ( ) ;
2010-03-17 19:19:14 +00:00
const double Position = instance . GetTexturePosition ( i , j ) ;
2010-03-28 18:58:01 +00:00
for ( unsigned int k = 0 ; k < texunit . Transformations . size ( ) ; + + k )
2010-03-17 19:19:14 +00:00
{
const StdMeshMaterialTextureUnit : : Transformation & trans = texunit . Transformations [ k ] ;
2010-03-28 18:58:01 +00:00
switch ( trans . TransformType )
2010-03-17 19:19:14 +00:00
{
case StdMeshMaterialTextureUnit : : Transformation : : T_SCROLL :
glTranslatef ( trans . Scroll . X , trans . Scroll . Y , 0.0f ) ;
break ;
case StdMeshMaterialTextureUnit : : Transformation : : T_SCROLL_ANIM :
glTranslatef ( trans . GetScrollX ( Position ) , trans . GetScrollY ( Position ) , 0.0f ) ;
break ;
case StdMeshMaterialTextureUnit : : Transformation : : T_ROTATE :
glRotatef ( trans . Rotate . Angle , 0.0f , 0.0f , 1.0f ) ;
break ;
case StdMeshMaterialTextureUnit : : Transformation : : T_ROTATE_ANIM :
glRotatef ( trans . GetRotate ( Position ) , 0.0f , 0.0f , 1.0f ) ;
break ;
case StdMeshMaterialTextureUnit : : Transformation : : T_SCALE :
glScalef ( trans . Scale . X , trans . Scale . Y , 1.0f ) ;
break ;
case StdMeshMaterialTextureUnit : : Transformation : : T_TRANSFORM :
glMultMatrixf ( trans . Transform . M ) ;
break ;
case StdMeshMaterialTextureUnit : : Transformation : : T_WAVE_XFORM :
2010-03-28 18:58:01 +00:00
switch ( trans . WaveXForm . XForm )
2010-03-17 19:19:14 +00:00
{
case StdMeshMaterialTextureUnit : : Transformation : : XF_SCROLL_X :
glTranslatef ( trans . GetWaveXForm ( Position ) , 0.0f , 0.0f ) ;
break ;
case StdMeshMaterialTextureUnit : : Transformation : : XF_SCROLL_Y :
glTranslatef ( 0.0f , trans . GetWaveXForm ( Position ) , 0.0f ) ;
break ;
case StdMeshMaterialTextureUnit : : Transformation : : XF_ROTATE :
glRotatef ( trans . GetWaveXForm ( Position ) , 0.0f , 0.0f , 1.0f ) ;
break ;
case StdMeshMaterialTextureUnit : : Transformation : : XF_SCALE_X :
glScalef ( trans . GetWaveXForm ( Position ) , 1.0f , 1.0f ) ;
break ;
case StdMeshMaterialTextureUnit : : Transformation : : XF_SCALE_Y :
glScalef ( 1.0f , trans . GetWaveXForm ( Position ) , 1.0f ) ;
break ;
}
break ;
}
}
2010-01-10 21:02:40 +00:00
glTexEnvi ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_COMBINE ) ;
2011-12-25 17:55:45 +00:00
bool fMod2 = ( dwBlitMode & C4GFXBLIT_MOD2 ) ! = 0 ;
2010-01-10 21:02:40 +00:00
2011-12-25 17:55:45 +00:00
// Overwrite texcombine and texscale for fMod2 drawing.
// TODO: Use an additional texture unit or a shader to do this,
// so that the settings of this texture unit are not lost.
2010-01-10 21:02:40 +00:00
2011-12-25 17:55:45 +00:00
if ( fMod2 )
2010-01-10 21:02:40 +00:00
{
2011-12-25 17:55:45 +00:00
// Special case RGBA setup for fMod2
glTexEnvi ( GL_TEXTURE_ENV , GL_COMBINE_ALPHA , GL_MODULATE ) ;
glTexEnvi ( GL_TEXTURE_ENV , GL_COMBINE_RGB , GL_ADD_SIGNED ) ;
glTexEnvf ( GL_TEXTURE_ENV , GL_ALPHA_SCALE , 1.0f ) ;
glTexEnvf ( GL_TEXTURE_ENV , GL_RGB_SCALE , 2.0f ) ;
SetTexSource ( GL_SOURCE0_RGB , texunit . ColorOpSources [ 0 ] ) ; // TODO: Fails for StdMeshMaterialTextureUnit::BOX_Source2
glTexEnvi ( GL_TEXTURE_ENV , GL_SOURCE1_RGB , GL_CONSTANT ) ;
2010-01-10 21:02:40 +00:00
glTexEnvi ( GL_TEXTURE_ENV , GL_OPERAND0_RGB , GL_SRC_COLOR ) ;
2011-12-25 17:55:45 +00:00
glTexEnvi ( GL_TEXTURE_ENV , GL_OPERAND1_RGB , GL_SRC_COLOR ) ;
SetTexSource ( GL_SOURCE0_ALPHA , texunit . AlphaOpSources [ 0 ] ) ;
glTexEnvi ( GL_TEXTURE_ENV , GL_SOURCE1_ALPHA , GL_CONSTANT ) ;
glTexEnvi ( GL_TEXTURE_ENV , GL_OPERAND0_ALPHA , GL_SRC_ALPHA ) ;
glTexEnvi ( GL_TEXTURE_ENV , GL_OPERAND1_ALPHA , GL_SRC_ALPHA ) ;
glTexEnvfv ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_COLOR , dwMod ) ;
2010-01-10 21:02:40 +00:00
}
else
{
2011-12-25 17:55:45 +00:00
// Combine
SetTexCombine ( GL_COMBINE_RGB , texunit . ColorOpEx ) ;
SetTexCombine ( GL_COMBINE_ALPHA , texunit . AlphaOpEx ) ;
// Scale
SetTexScale ( GL_RGB_SCALE , texunit . ColorOpEx ) ;
SetTexScale ( GL_ALPHA_SCALE , texunit . AlphaOpEx ) ;
if ( texunit . ColorOpEx = = StdMeshMaterialTextureUnit : : BOX_Source2 )
2010-01-10 21:02:40 +00:00
{
2011-12-25 17:55:45 +00:00
SetTexSource ( GL_SOURCE0_RGB , texunit . ColorOpSources [ 1 ] ) ;
glTexEnvi ( GL_TEXTURE_ENV , GL_OPERAND0_RGB , GL_SRC_COLOR ) ;
2010-01-10 21:02:40 +00:00
}
else
{
2011-12-25 17:55:45 +00:00
if ( texunit . ColorOpEx = = StdMeshMaterialTextureUnit : : BOX_AddSmooth )
2010-01-10 21:02:40 +00:00
{
2011-12-25 17:55:45 +00:00
// GL_SOURCE0 is GL_CONSTANT to achieve the desired effect with GL_INTERPOLATE
SetTexSource2 ( GL_SOURCE0_RGB , texunit . ColorOpEx ) ;
SetTexSource ( GL_SOURCE1_RGB , texunit . ColorOpSources [ 0 ] ) ;
SetTexSource ( GL_SOURCE2_RGB , texunit . ColorOpSources [ 1 ] ) ;
SetTexOperand2 ( GL_OPERAND0_RGB , texunit . ColorOpEx ) ;
2010-01-10 21:02:40 +00:00
glTexEnvi ( GL_TEXTURE_ENV , GL_OPERAND1_RGB , GL_SRC_COLOR ) ;
2011-12-25 17:55:45 +00:00
glTexEnvi ( GL_TEXTURE_ENV , GL_OPERAND2_RGB , GL_SRC_COLOR ) ;
2010-01-10 21:02:40 +00:00
}
2011-12-25 17:55:45 +00:00
else
{
SetTexSource ( GL_SOURCE0_RGB , texunit . ColorOpSources [ 0 ] ) ;
glTexEnvi ( GL_TEXTURE_ENV , GL_OPERAND0_RGB , GL_SRC_COLOR ) ;
if ( texunit . ColorOpEx ! = StdMeshMaterialTextureUnit : : BOX_Source1 )
{
SetTexSource ( GL_SOURCE1_RGB , texunit . ColorOpSources [ 1 ] ) ;
glTexEnvi ( GL_TEXTURE_ENV , GL_OPERAND1_RGB , GL_SRC_COLOR ) ;
}
2010-01-10 21:02:40 +00:00
2011-12-25 17:55:45 +00:00
SetTexSource2 ( GL_SOURCE2_RGB , texunit . ColorOpEx ) ;
SetTexOperand2 ( GL_OPERAND2_RGB , texunit . ColorOpEx ) ;
}
2010-01-10 21:02:40 +00:00
}
2011-12-25 17:55:45 +00:00
if ( texunit . AlphaOpEx = = StdMeshMaterialTextureUnit : : BOX_Source2 )
2010-01-10 21:02:40 +00:00
{
2011-12-25 17:55:45 +00:00
SetTexSource ( GL_SOURCE0_ALPHA , texunit . AlphaOpSources [ 1 ] ) ;
2010-01-10 21:02:40 +00:00
glTexEnvi ( GL_TEXTURE_ENV , GL_OPERAND0_ALPHA , GL_SRC_ALPHA ) ;
}
else
{
2011-12-25 17:55:45 +00:00
if ( texunit . AlphaOpEx = = StdMeshMaterialTextureUnit : : BOX_AddSmooth )
2010-01-10 21:02:40 +00:00
{
2011-12-25 17:55:45 +00:00
// GL_SOURCE0 is GL_CONSTANT to achieve the desired effect with GL_INTERPOLATE
SetTexSource2 ( GL_SOURCE0_ALPHA , texunit . AlphaOpEx ) ;
SetTexSource ( GL_SOURCE1_ALPHA , texunit . AlphaOpSources [ 0 ] ) ;
SetTexSource ( GL_SOURCE2_ALPHA , texunit . AlphaOpSources [ 1 ] ) ;
glTexEnvi ( GL_TEXTURE_ENV , GL_OPERAND0_ALPHA , GL_SRC_ALPHA ) ;
2010-01-10 21:02:40 +00:00
glTexEnvi ( GL_TEXTURE_ENV , GL_OPERAND1_ALPHA , GL_SRC_ALPHA ) ;
2011-12-25 17:55:45 +00:00
glTexEnvi ( GL_TEXTURE_ENV , GL_OPERAND2_ALPHA , GL_SRC_ALPHA ) ;
2010-01-10 21:02:40 +00:00
}
2011-12-25 17:55:45 +00:00
else
{
SetTexSource ( GL_SOURCE0_ALPHA , texunit . AlphaOpSources [ 0 ] ) ;
glTexEnvi ( GL_TEXTURE_ENV , GL_OPERAND0_ALPHA , GL_SRC_ALPHA ) ;
if ( texunit . AlphaOpEx ! = StdMeshMaterialTextureUnit : : BOX_Source1 )
{
SetTexSource ( GL_SOURCE1_ALPHA , texunit . AlphaOpSources [ 1 ] ) ;
glTexEnvi ( GL_TEXTURE_ENV , GL_OPERAND1_ALPHA , GL_SRC_ALPHA ) ;
}
2010-01-10 21:02:40 +00:00
2011-12-25 17:55:45 +00:00
SetTexSource2 ( GL_SOURCE2_ALPHA , texunit . AlphaOpEx ) ;
glTexEnvi ( GL_TEXTURE_ENV , GL_OPERAND2_ALPHA , GL_SRC_ALPHA ) ;
}
2010-01-10 21:02:40 +00:00
}
2011-12-25 17:55:45 +00:00
SetTexColor ( texunit , dwPlayerColor ) ;
}
2010-01-10 21:02:40 +00:00
}
2010-04-05 15:02:41 +00:00
2010-01-10 21:02:40 +00:00
glMatrixMode ( GL_MODELVIEW ) ;
2010-03-16 22:31:53 +00:00
glDrawElements ( GL_TRIANGLES , instance . GetNumFaces ( ) * 3 , GL_UNSIGNED_INT , instance . GetFaces ( ) ) ;
2010-01-10 21:02:40 +00:00
2010-03-28 18:58:01 +00:00
for ( unsigned int j = 0 ; j < pass . TextureUnits . size ( ) ; + + j )
2010-01-10 21:02:40 +00:00
{
2010-04-05 15:02:41 +00:00
glActiveTexture ( GL_TEXTURE0 + j ) ;
glClientActiveTexture ( GL_TEXTURE0 + j ) ;
2010-01-30 17:56:11 +00:00
glDisableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
2010-01-10 21:02:40 +00:00
glDisable ( GL_TEXTURE_2D ) ;
}
}
2010-01-11 23:54:36 +00:00
}
2010-08-31 21:44:56 +00:00
void RenderMeshImpl ( StdMeshInstance & instance , DWORD dwModClr , DWORD dwBlitMode , DWORD dwPlayerColor , bool parity ) ; // Needed by RenderAttachedMesh
void RenderAttachedMesh ( StdMeshInstance : : AttachedMesh * attach , DWORD dwModClr , DWORD dwBlitMode , DWORD dwPlayerColor , bool parity )
2010-01-11 23:54:36 +00:00
{
2010-08-31 21:44:56 +00:00
const StdMeshMatrix & FinalTrans = attach - > GetFinalTransformation ( ) ;
2010-01-11 23:54:36 +00:00
2010-08-31 21:44:56 +00:00
// Convert matrix to column-major order, add fourth row
const float attach_trans_gl [ 16 ] =
{
FinalTrans ( 0 , 0 ) , FinalTrans ( 1 , 0 ) , FinalTrans ( 2 , 0 ) , 0 ,
FinalTrans ( 0 , 1 ) , FinalTrans ( 1 , 1 ) , FinalTrans ( 2 , 1 ) , 0 ,
FinalTrans ( 0 , 2 ) , FinalTrans ( 1 , 2 ) , FinalTrans ( 2 , 2 ) , 0 ,
FinalTrans ( 0 , 3 ) , FinalTrans ( 1 , 3 ) , FinalTrans ( 2 , 3 ) , 1
} ;
// TODO: Take attach transform's parity into account
glPushMatrix ( ) ;
glMultMatrixf ( attach_trans_gl ) ;
RenderMeshImpl ( * attach - > Child , dwModClr , dwBlitMode , dwPlayerColor , parity ) ;
glPopMatrix ( ) ;
2010-01-10 21:02:40 +00:00
#if 0
2010-08-31 21:44:56 +00:00
const StdMeshMatrix & own_trans = instance . GetBoneTransform ( attach - > ParentBone )
* StdMeshMatrix : : Transform ( instance . Mesh . GetBone ( attach - > ParentBone ) . Transformation ) ;
2010-01-10 21:02:40 +00:00
2010-08-31 21:44:56 +00:00
// Draw attached bone
2010-01-10 21:02:40 +00:00
glDisable ( GL_DEPTH_TEST ) ;
glDisable ( GL_LIGHTING ) ;
2010-08-31 21:44:56 +00:00
glColor4f ( 1.0f , 0.0f , 0.0f , 1.0f ) ;
2010-01-10 21:02:40 +00:00
GLUquadric * quad = gluNewQuadric ( ) ;
glPushMatrix ( ) ;
glTranslatef ( own_trans ( 0 , 3 ) , own_trans ( 1 , 3 ) , own_trans ( 2 , 3 ) ) ;
gluSphere ( quad , 1.0f , 4 , 4 ) ;
glPopMatrix ( ) ;
gluDeleteQuadric ( quad ) ;
glEnable ( GL_DEPTH_TEST ) ;
glEnable ( GL_LIGHTING ) ;
# endif
2010-08-31 21:44:56 +00:00
}
2010-01-10 21:02:40 +00:00
2010-08-31 21:44:56 +00:00
void RenderMeshImpl ( StdMeshInstance & instance , DWORD dwModClr , DWORD dwBlitMode , DWORD dwPlayerColor , bool parity )
{
2011-08-19 22:01:08 +00:00
const StdMesh & mesh = instance . GetMesh ( ) ;
2010-01-29 21:18:18 +00:00
2010-08-31 21:44:56 +00:00
// Render AM_DrawBefore attached meshes
StdMeshInstance : : AttachedMeshIter attach_iter = instance . AttachedMeshesBegin ( ) ;
2010-01-10 21:02:40 +00:00
2010-08-31 21:44:56 +00:00
for ( ; attach_iter ! = instance . AttachedMeshesEnd ( ) & & ( ( * attach_iter ) - > GetFlags ( ) & StdMeshInstance : : AM_DrawBefore ) ; + + attach_iter )
RenderAttachedMesh ( * attach_iter , dwModClr , dwBlitMode , dwPlayerColor , parity ) ;
2012-04-17 15:29:29 +00:00
GLint modes [ 2 ] ;
// Check if we should draw in wireframe or normal mode
if ( dwBlitMode & C4GFXBLIT_WIREFRAME )
{
// save old mode
glGetIntegerv ( GL_POLYGON_MODE , modes ) ;
glPolygonMode ( GL_FRONT_AND_BACK , GL_LINE ) ;
}
2010-08-31 21:44:56 +00:00
// Render each submesh
for ( unsigned int i = 0 ; i < mesh . GetNumSubMeshes ( ) ; + + i )
2012-02-15 22:04:19 +00:00
RenderSubMeshImpl ( instance , instance . GetSubMesh ( i ) , dwModClr , dwBlitMode , dwPlayerColor , parity ) ;
2010-01-10 21:02:40 +00:00
2012-04-17 15:29:29 +00:00
// reset old mode to prevent rendering errors
if ( dwBlitMode & C4GFXBLIT_WIREFRAME )
{
glPolygonMode ( GL_FRONT , modes [ 0 ] ) ;
glPolygonMode ( GL_BACK , modes [ 1 ] ) ;
}
2010-01-10 21:02:40 +00:00
#if 0
2010-08-31 21:44:56 +00:00
// Draw attached bone
if ( instance . GetAttachParent ( ) )
{
const StdMeshInstance : : AttachedMesh * attached = instance . GetAttachParent ( ) ;
const StdMeshMatrix & own_trans = instance . GetBoneTransform ( attached - > ChildBone ) * StdMeshMatrix : : Transform ( instance . Mesh . GetBone ( attached - > ChildBone ) . Transformation ) ;
2010-01-10 21:02:40 +00:00
glDisable ( GL_DEPTH_TEST ) ;
glDisable ( GL_LIGHTING ) ;
2010-08-31 21:44:56 +00:00
glColor4f ( 1.0f , 1.0f , 0.0f , 1.0f ) ;
2010-01-10 21:02:40 +00:00
GLUquadric * quad = gluNewQuadric ( ) ;
glPushMatrix ( ) ;
glTranslatef ( own_trans ( 0 , 3 ) , own_trans ( 1 , 3 ) , own_trans ( 2 , 3 ) ) ;
gluSphere ( quad , 1.0f , 4 , 4 ) ;
glPopMatrix ( ) ;
gluDeleteQuadric ( quad ) ;
glEnable ( GL_DEPTH_TEST ) ;
glEnable ( GL_LIGHTING ) ;
}
2010-08-31 21:44:56 +00:00
# endif
// Render non-AM_DrawBefore attached meshes
for ( ; attach_iter ! = instance . AttachedMeshesEnd ( ) ; + + attach_iter )
RenderAttachedMesh ( * attach_iter , dwModClr , dwBlitMode , dwPlayerColor , parity ) ;
2010-01-10 21:02:40 +00:00
}
2010-02-06 17:33:30 +00:00
// Apply Zoom and Transformation to the current matrix stack. Return
// parity of the transformation.
2011-09-30 20:15:51 +00:00
bool ApplyZoomAndTransform ( float ZoomX , float ZoomY , float Zoom , C4BltTransform * pTransform )
2010-02-06 17:33:30 +00:00
{
// Apply zoom
glTranslatef ( ZoomX , ZoomY , 0.0f ) ;
glScalef ( Zoom , Zoom , 1.0f ) ;
glTranslatef ( - ZoomX , - ZoomY , 0.0f ) ;
// Apply transformation
2010-03-28 18:58:01 +00:00
if ( pTransform )
2010-02-06 17:33:30 +00:00
{
const GLfloat transform [ 16 ] = { pTransform - > mat [ 0 ] , pTransform - > mat [ 3 ] , 0 , pTransform - > mat [ 6 ] , pTransform - > mat [ 1 ] , pTransform - > mat [ 4 ] , 0 , pTransform - > mat [ 7 ] , 0 , 0 , 1 , 0 , pTransform - > mat [ 2 ] , pTransform - > mat [ 5 ] , 0 , pTransform - > mat [ 8 ] } ;
glMultMatrixf ( transform ) ;
2010-03-28 18:58:01 +00:00
2010-02-06 17:33:30 +00:00
// Compute parity of the transformation matrix - if parity is swapped then
// we need to cull front faces instead of back faces.
const float det = transform [ 0 ] * transform [ 5 ] * transform [ 15 ]
2010-03-28 18:58:01 +00:00
+ transform [ 4 ] * transform [ 13 ] * transform [ 3 ]
+ transform [ 12 ] * transform [ 1 ] * transform [ 7 ]
- transform [ 0 ] * transform [ 13 ] * transform [ 7 ]
- transform [ 4 ] * transform [ 1 ] * transform [ 15 ]
- transform [ 12 ] * transform [ 5 ] * transform [ 3 ] ;
2010-02-06 17:33:30 +00:00
return det > 0 ;
}
return true ;
}
2010-01-03 22:58:26 +00:00
}
2011-09-30 20:15:51 +00:00
void CStdGL : : PerformMesh ( StdMeshInstance & instance , float tx , float ty , float twdt , float thgt , DWORD dwPlayerColor , C4BltTransform * pTransform )
2009-07-10 23:10:18 +00:00
{
2010-03-15 21:50:11 +00:00
// Field of View for perspective projection, in degrees
static const float FOV = 60.0f ;
static const float TAN_FOV = tan ( FOV / 2.0f / 180.0f * M_PI ) ;
2010-06-08 22:55:34 +00:00
// Convert OgreToClonk matrix to column-major order
2011-10-03 14:34:08 +00:00
// TODO: This must be executed after C4Draw::OgreToClonk was
2010-06-08 22:55:34 +00:00
// initialized - is this guaranteed at this position?
static const float OgreToClonkGL [ 16 ] =
{
2011-10-03 14:34:08 +00:00
C4Draw : : OgreToClonk ( 0 , 0 ) , C4Draw : : OgreToClonk ( 1 , 0 ) , C4Draw : : OgreToClonk ( 2 , 0 ) , 0 ,
C4Draw : : OgreToClonk ( 0 , 1 ) , C4Draw : : OgreToClonk ( 1 , 1 ) , C4Draw : : OgreToClonk ( 2 , 1 ) , 0 ,
C4Draw : : OgreToClonk ( 0 , 2 ) , C4Draw : : OgreToClonk ( 1 , 2 ) , C4Draw : : OgreToClonk ( 2 , 2 ) , 0 ,
C4Draw : : OgreToClonk ( 0 , 3 ) , C4Draw : : OgreToClonk ( 1 , 3 ) , C4Draw : : OgreToClonk ( 2 , 3 ) , 1
2010-06-08 22:55:34 +00:00
} ;
2011-10-03 14:34:08 +00:00
static const bool OgreToClonkParity = C4Draw : : OgreToClonk . Determinant ( ) > 0.0f ;
2010-06-08 22:55:34 +00:00
2011-08-19 22:01:08 +00:00
const StdMesh & mesh = instance . GetMesh ( ) ;
2009-07-10 23:10:18 +00:00
2010-02-06 17:33:30 +00:00
bool parity = OgreToClonkParity ;
// Convert bounding box to clonk coordinate system
// (TODO: We should cache this, not sure where though)
// TODO: Note that this does not generally work with an arbitrary transformation this way
const StdMeshBox & box = mesh . GetBoundingBox ( ) ;
StdMeshVector v1 , v2 ;
v1 . x = box . x1 ; v1 . y = box . y1 ; v1 . z = box . z1 ;
v2 . x = box . x2 ; v2 . y = box . y2 ; v2 . z = box . z2 ;
v1 = OgreToClonk * v1 ; // TODO: Include translation
v2 = OgreToClonk * v2 ; // TODO: Include translation
2010-03-17 12:43:17 +00:00
// Vector from origin of mesh to center of mesh
const StdMeshVector MeshCenter = ( v1 + v2 ) / 2.0f ;
2009-07-12 14:27:04 +00:00
glShadeModel ( GL_SMOOTH ) ;
2009-07-10 23:10:18 +00:00
glEnable ( GL_DEPTH_TEST ) ;
glEnable ( GL_LIGHTING ) ;
2010-01-01 14:26:54 +00:00
glEnable ( GL_BLEND ) ; // TODO: Shouldn't this always be enabled? - blending does not work for meshes without this though.
2010-06-08 22:55:34 +00:00
2012-04-07 14:47:23 +00:00
glEnableClientState ( GL_VERTEX_ARRAY ) ;
glEnableClientState ( GL_NORMAL_ARRAY ) ;
2012-04-09 20:03:55 +00:00
glDisableClientState ( GL_COLOR_ARRAY ) ; // might still be active from a previous (non-mesh-rendering) GL operation
2012-05-05 21:04:35 +00:00
glClientActiveTexture ( GL_TEXTURE0 ) ;
glDisableClientState ( GL_TEXTURE_COORD_ARRAY ) ; // same -- we enable this individually for every texture unit in RenderSubMeshImpl
2012-04-07 14:47:23 +00:00
2010-06-08 22:55:34 +00:00
// TODO: We ignore the additive drawing flag for meshes but instead
// set the blending mode of the corresponding material. I'm not sure
// how the two could be combined.
2010-09-01 18:53:32 +00:00
// TODO: Maybe they can be combined using a pixel shader which does
// ftransform() and then applies colormod, additive and mod2
// on the result (with alpha blending).
2010-06-08 22:55:34 +00:00
//int iAdditive = dwBlitMode & C4GFXBLIT_ADDITIVE;
//glBlendFunc(GL_SRC_ALPHA, iAdditive ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA);
2009-07-10 23:10:18 +00:00
2010-02-06 17:33:30 +00:00
// Set up projection matrix first. We do transform and Zoom with the
// projection matrix, so that lighting is applied to the untransformed/unzoomed
// mesh.
glMatrixMode ( GL_PROJECTION ) ;
2009-07-28 02:29:09 +00:00
glPushMatrix ( ) ;
2009-07-19 01:36:08 +00:00
2012-03-03 00:45:46 +00:00
// Mesh extents
const float b = fabs ( v2 . x - v1 . x ) / 2.0f ;
const float h = fabs ( v2 . y - v1 . y ) / 2.0f ;
const float l = fabs ( v2 . z - v1 . z ) / 2.0f ;
2010-03-28 18:58:01 +00:00
if ( ! fUsePerspective )
2009-07-19 01:36:08 +00:00
{
2010-02-06 17:33:30 +00:00
// Orthographic projection. The orthographic projection matrix
// is already loaded in the GL matrix stack.
2010-03-28 18:58:01 +00:00
if ( ! ApplyZoomAndTransform ( ZoomX , ZoomY , Zoom , pTransform ) )
2010-02-06 17:33:30 +00:00
parity = ! parity ;
// Scale so that the mesh fits in (tx,ty,twdt,thgt)
const float rx = - std : : min ( v1 . x , v1 . y ) / fabs ( v2 . x - v1 . x ) ;
const float ry = - std : : min ( v1 . y , v2 . y ) / fabs ( v2 . y - v1 . y ) ;
const float dx = tx + rx * twdt ;
const float dy = ty + ry * thgt ;
// Scale so that Z coordinate is between -1 and 1, otherwise parts of
// the mesh could be clipped away by the near or far clipping plane.
2010-03-17 20:15:00 +00:00
// Note that this only works for the projection matrix, otherwise
2010-02-06 17:33:30 +00:00
// lighting is screwed up.
// This technique might also enable us not to clear the depth buffer
// after every mesh rendering - we could simply scale the first mesh
// of the scene so that it's Z coordinate is between 0 and 1, scale
// the second mesh that it is between 1 and 2, and so on.
// This of course requires an orthogonal projection so that the
// meshes don't look distorted - if we should ever decide to use
// a perspective projection we need to think of something different.
// Take also into account that the depth is not linear but linear
2010-03-17 20:15:00 +00:00
// in the logarithm (if I am not mistaken), so goes as 1/z
// Don't scale by Z extents since mesh might be transformed
// by MeshTransformation, so use GetBoundingRadius to be safe.
2010-04-10 11:46:51 +00:00
// Note this still fails if mesh is scaled in Z direction or
// there are attached meshes.
2010-07-21 20:23:34 +00:00
const float scz = 1.0 / ( mesh . GetBoundingRadius ( ) ) ;
2010-02-06 17:33:30 +00:00
glTranslatef ( dx , dy , 0.0f ) ;
2010-07-21 19:57:08 +00:00
glScalef ( 1.0f , 1.0f , scz ) ;
2009-07-19 01:36:08 +00:00
}
2010-02-06 17:33:30 +00:00
else
{
// Perspective projection. We need current viewport size.
const int iWdt = Min ( iClipX2 , RenderTarget - > Wdt - 1 ) - iClipX1 + 1 ;
const int iHgt = Min ( iClipY2 , RenderTarget - > Hgt - 1 ) - iClipY1 + 1 ;
2009-07-12 17:06:31 +00:00
2010-02-06 17:33:30 +00:00
// Get away with orthographic projection matrix currently loaded
glLoadIdentity ( ) ;
2010-01-26 14:28:32 +00:00
2010-02-06 17:33:30 +00:00
// Back to GL device coordinates
glTranslatef ( - 1.0f , 1.0f , 0.0f ) ;
glScalef ( 2.0f / iWdt , - 2.0f / iHgt , 1.0f ) ;
2009-09-10 02:54:12 +00:00
2010-03-25 11:27:35 +00:00
glTranslatef ( - iClipX1 , - iClipY1 , 0.0f ) ;
2010-03-28 18:58:01 +00:00
if ( ! ApplyZoomAndTransform ( ZoomX , ZoomY , Zoom , pTransform ) )
2010-02-06 17:33:30 +00:00
parity = ! parity ;
2009-07-19 01:36:08 +00:00
2010-04-28 19:30:15 +00:00
// Move to target location and compensate for 1.0f aspect
float ttx = tx , tty = ty , ttwdt = twdt , tthgt = thgt ;
if ( twdt > thgt )
{
tty + = ( thgt - twdt ) / 2.0 ;
tthgt = twdt ;
}
else
{
ttx + = ( twdt - thgt ) / 2.0 ;
ttwdt = thgt ;
}
2010-03-25 11:27:35 +00:00
2010-04-28 19:30:15 +00:00
glTranslatef ( ttx , tty , 0.0f ) ;
glScalef ( ( ( float ) ttwdt ) / iWdt , ( ( float ) tthgt ) / iHgt , 1.0f ) ;
2010-02-06 17:33:30 +00:00
// Return to Clonk coordinate frame
glScalef ( iWdt / 2.0 , - iHgt / 2.0 , 1.0f ) ;
glTranslatef ( 1.0f , - 1.0f , 0.0f ) ;
2012-03-03 00:45:46 +00:00
// Fix for the case when we have a non-square target
const float ta = twdt / thgt ;
const float ma = b / h ;
if ( ta < = 1 & & ta / ma < = 1 )
glScalef ( std : : max ( ta , ta / ma ) , std : : max ( ta , ta / ma ) , 1.0f ) ;
else if ( ta > = 1 & & ta / ma > = 1 )
glScalef ( std : : max ( 1.0f / ta , ma / ta ) , std : : max ( 1.0f / ta , ma / ta ) , 1.0f ) ;
2010-02-06 17:33:30 +00:00
// Apply perspective projection. After this, x and y range from
// -1 to 1, and this is mapped into tx/ty/twdt/thgt by the above code.
2010-04-28 19:30:15 +00:00
// Aspect is 1.0f which is accounted for above.
2010-03-15 21:50:11 +00:00
gluPerspective ( FOV , 1.0f , 0.1f , 100.0f ) ;
2010-02-06 17:33:30 +00:00
}
// Now set up modelview matrix
glMatrixMode ( GL_MODELVIEW ) ;
glPushMatrix ( ) ;
glLoadIdentity ( ) ;
2010-03-28 18:58:01 +00:00
if ( ! fUsePerspective )
2010-02-06 17:33:30 +00:00
{
// Put a light source in front of the object
2010-03-17 12:54:38 +00:00
const GLfloat light_position [ ] = { 0.0f , 0.0f , 1.0f , 0.0f } ;
2010-02-06 17:33:30 +00:00
glLightfv ( GL_LIGHT0 , GL_POSITION , light_position ) ;
glEnable ( GL_LIGHT0 ) ;
}
else
{
2010-03-15 21:50:11 +00:00
// Setup camera position so that the mesh with uniform transformation
2012-03-03 00:45:46 +00:00
// fits well into a square target (without distortion).
const float EyeR = l + std : : max ( b / TAN_FOV , h / TAN_FOV ) ;
2010-03-17 12:43:17 +00:00
const float EyeX = MeshCenter . x ;
const float EyeY = MeshCenter . y ;
const float EyeZ = MeshCenter . z + EyeR ;
2010-02-06 17:33:30 +00:00
// Up vector is unit vector in theta direction
2010-03-15 21:50:11 +00:00
const float UpX = 0 ; //-sinEyePhi * sinEyeTheta;
const float UpY = - 1 ; //-cosEyeTheta;
const float UpZ = 0 ; //-cosEyePhi * sinEyeTheta;
2010-02-06 17:33:30 +00:00
// Apply lighting (light source at camera position)
const GLfloat light_position [ ] = { EyeX , EyeY , EyeZ , 1.0f } ;
glLightfv ( GL_LIGHT0 , GL_POSITION , light_position ) ;
glEnable ( GL_LIGHT0 ) ;
2010-03-15 21:50:11 +00:00
// Fix X axis (???)
glScalef ( - 1.0f , 1.0f , 1.0f ) ;
2010-02-06 17:33:30 +00:00
// center on mesh's bounding box, so that the mesh is really in the center of the viewport
2010-03-17 12:43:17 +00:00
gluLookAt ( EyeX , EyeY , EyeZ , MeshCenter . x , MeshCenter . y , MeshCenter . z , UpX , UpY , UpZ ) ;
}
2010-02-06 17:33:30 +00:00
2010-03-17 12:43:17 +00:00
// Apply mesh transformation matrix
2010-03-28 18:58:01 +00:00
if ( MeshTransform )
2010-03-17 12:43:17 +00:00
{
// Convert to column-major order
const float Matrix [ 16 ] =
{
( * MeshTransform ) ( 0 , 0 ) , ( * MeshTransform ) ( 1 , 0 ) , ( * MeshTransform ) ( 2 , 0 ) , 0 ,
( * MeshTransform ) ( 0 , 1 ) , ( * MeshTransform ) ( 1 , 1 ) , ( * MeshTransform ) ( 2 , 1 ) , 0 ,
( * MeshTransform ) ( 0 , 2 ) , ( * MeshTransform ) ( 1 , 2 ) , ( * MeshTransform ) ( 2 , 2 ) , 0 ,
( * MeshTransform ) ( 0 , 3 ) , ( * MeshTransform ) ( 1 , 3 ) , ( * MeshTransform ) ( 2 , 3 ) , 1
} ;
2010-03-28 18:58:01 +00:00
2010-03-17 12:43:17 +00:00
const float det = MeshTransform - > Determinant ( ) ;
2010-03-28 18:58:01 +00:00
if ( det < 0 ) parity = ! parity ;
2010-03-17 12:43:17 +00:00
// Renormalize if transformation resizes the mesh
2010-07-21 20:23:34 +00:00
// for lighting to be correct.
// TODO: Also needs to check for orthonormality to be correct
2010-03-28 18:58:01 +00:00
if ( det ! = 1 & & det ! = - 1 )
2010-03-17 12:43:17 +00:00
glEnable ( GL_NORMALIZE ) ;
2010-07-21 20:23:34 +00:00
// Apply MeshTransformation (in the Mesh's coordinate system)
2010-03-17 12:43:17 +00:00
glMultMatrixf ( Matrix ) ;
2010-02-06 17:33:30 +00:00
}
2010-01-26 14:28:32 +00:00
2010-03-17 12:43:17 +00:00
// Convert from Ogre to Clonk coordinate system
glMultMatrixf ( OgreToClonkGL ) ;
2010-01-10 21:02:40 +00:00
DWORD dwModClr = BlitModulated ? BlitModulateClr : 0xffffffff ;
2009-07-10 23:10:18 +00:00
2010-04-10 11:46:51 +00:00
if ( fUseClrModMap )
{
float x = tx + twdt / 2.0f ;
float y = ty + thgt / 2.0f ;
if ( pTransform )
pTransform - > TransformPoint ( x , y ) ;
ApplyZoom ( x , y ) ;
DWORD c = pClrModMap - > GetModAt ( int ( x ) , int ( y ) ) ;
ModulateClr ( dwModClr , c ) ;
}
2009-09-10 02:54:12 +00:00
2010-06-08 22:55:34 +00:00
RenderMeshImpl ( instance , dwModClr , dwBlitMode , dwPlayerColor , parity ) ;
2009-07-10 23:10:18 +00:00
2010-02-06 17:33:30 +00:00
glMatrixMode ( GL_PROJECTION ) ;
glPopMatrix ( ) ;
glMatrixMode ( GL_MODELVIEW ) ;
glPopMatrix ( ) ;
2010-01-03 22:58:26 +00:00
glActiveTexture ( GL_TEXTURE0 ) ; // switch back to default
glClientActiveTexture ( GL_TEXTURE0 ) ; // switch back to default
2010-01-12 20:30:36 +00:00
glDepthMask ( GL_TRUE ) ;
2010-01-04 01:33:45 +00:00
2012-04-07 14:47:23 +00:00
glDisableClientState ( GL_NORMAL_ARRAY ) ;
glDisableClientState ( GL_VERTEX_ARRAY ) ;
2010-03-15 21:50:11 +00:00
glDisable ( GL_NORMALIZE ) ;
2009-07-10 23:10:18 +00:00
glDisable ( GL_LIGHT0 ) ;
glDisable ( GL_LIGHTING ) ;
glDisable ( GL_DEPTH_TEST ) ;
2010-01-01 15:03:56 +00:00
glDisable ( GL_CULL_FACE ) ;
2012-02-19 16:49:02 +00:00
glDisable ( GL_SAMPLE_ALPHA_TO_COVERAGE ) ;
2010-01-01 14:26:54 +00:00
//glDisable(GL_BLEND);
2009-07-12 14:27:04 +00:00
glShadeModel ( GL_FLAT ) ;
2010-03-28 18:58:01 +00:00
2009-07-10 23:10:18 +00:00
// TODO: glScissor, so that we only clear the area the mesh covered.
glClear ( GL_DEPTH_BUFFER_BIT ) ;
}
2011-10-03 14:07:07 +00:00
void CStdGL : : BlitLandscape ( C4Surface * sfcSource , float fx , float fy ,
C4Surface * sfcTarget , float tx , float ty , float wdt , float hgt , const C4Surface * mattextures [ ] )
2010-03-28 18:58:01 +00:00
{
2009-05-27 23:38:14 +00:00
//Blit(sfcSource, fx, fy, wdt, hgt, sfcTarget, tx, ty, wdt, hgt);return;
2009-05-08 13:28:41 +00:00
// safety
if ( ! sfcSource | | ! sfcTarget | | ! wdt | | ! hgt ) return ;
assert ( sfcTarget - > IsRenderTarget ( ) ) ;
assert ( ! ( dwBlitMode & C4GFXBLIT_MOD2 ) ) ;
// Apply Zoom
float twdt = wdt ;
float thgt = hgt ;
tx = ( tx - ZoomX ) * Zoom + ZoomX ;
ty = ( ty - ZoomY ) * Zoom + ZoomY ;
twdt * = Zoom ;
thgt * = Zoom ;
// bound
if ( ClipAll ) return ;
// manual clipping? (primary surface only)
2010-09-28 17:07:47 +00:00
if ( Config . Graphics . ClipManuallyE )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
int iOver ;
// Left
iOver = int ( tx ) - iClipX1 ;
if ( iOver < 0 )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
wdt + = iOver ;
twdt + = iOver * Zoom ;
fx - = iOver ;
tx = float ( iClipX1 ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// Top
iOver = int ( ty ) - iClipY1 ;
if ( iOver < 0 )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
hgt + = iOver ;
thgt + = iOver * Zoom ;
fy - = iOver ;
ty = float ( iClipY1 ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// Right
iOver = iClipX2 + 1 - int ( tx + twdt ) ;
if ( iOver < 0 )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
wdt + = iOver / Zoom ;
twdt + = iOver ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// Bottom
iOver = iClipY2 + 1 - int ( ty + thgt ) ;
if ( iOver < 0 )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
hgt + = iOver / Zoom ;
thgt + = iOver ;
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// inside screen?
if ( wdt < = 0 | | hgt < = 0 ) return ;
// prepare rendering to surface
if ( ! PrepareRendering ( sfcTarget ) ) return ;
// texture present?
if ( ! sfcSource - > ppTex )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
return ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// get involved texture offsets
2010-09-04 17:30:45 +00:00
int iTexSizeX = sfcSource - > iTexSize ;
int iTexSizeY = sfcSource - > iTexSize ;
int iTexX = Max ( int ( fx / iTexSizeX ) , 0 ) ;
int iTexY = Max ( int ( fy / iTexSizeY ) , 0 ) ;
int iTexX2 = Min ( ( int ) ( fx + wdt - 1 ) / iTexSizeX + 1 , sfcSource - > iTexX ) ;
int iTexY2 = Min ( ( int ) ( fy + hgt - 1 ) / iTexSizeY + 1 , sfcSource - > iTexY ) ;
2009-05-08 13:28:41 +00:00
// blit from all these textures
SetTexture ( ) ;
2009-05-27 23:31:31 +00:00
if ( mattextures )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
glActiveTexture ( GL_TEXTURE1 ) ;
glEnable ( GL_TEXTURE_2D ) ;
glActiveTexture ( GL_TEXTURE0 ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
DWORD dwModMask = 0 ;
2009-08-10 14:48:25 +00:00
SetupTextureEnv ( false , ! ! mattextures ) ;
2009-05-08 13:28:41 +00:00
glMatrixMode ( GL_MODELVIEW ) ;
glLoadIdentity ( ) ;
glMatrixMode ( GL_TEXTURE ) ;
glLoadIdentity ( ) ;
for ( int iY = iTexY ; iY < iTexY2 ; + + iY )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
for ( int iX = iTexX ; iX < iTexX2 ; + + iX )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// blit
2009-08-23 21:46:56 +00:00
DWORD dwModClr = BlitModulated ? BlitModulateClr : 0xffffffff ;
2009-05-08 13:28:41 +00:00
2009-05-30 19:26:55 +00:00
glActiveTexture ( GL_TEXTURE0 ) ;
2011-10-03 14:16:38 +00:00
C4TexRef * pTex = * ( sfcSource - > ppTex + iY * sfcSource - > iTexX + iX ) ;
2009-05-08 13:28:41 +00:00
glBindTexture ( GL_TEXTURE_2D , pTex - > texName ) ;
2009-05-30 19:26:55 +00:00
if ( ! mattextures & & Zoom ! = 1.0 )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-30 19:26:55 +00:00
else
2010-03-28 18:58:01 +00:00
{
2009-05-30 19:26:55 +00:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_NEAREST ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_NEAREST ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2010-09-04 17:30:45 +00:00
// get current blitting offset in texture
int iBlitX = sfcSource - > iTexSize * iX ;
int iBlitY = sfcSource - > iTexSize * iY ;
2009-05-08 13:28:41 +00:00
// size changed? recalc dependant, relevant (!) values
2010-09-04 17:30:45 +00:00
if ( iTexSizeX ! = pTex - > iSizeX )
iTexSizeX = pTex - > iSizeX ;
if ( iTexSizeY ! = pTex - > iSizeY )
iTexSizeY = pTex - > iSizeY ;
2009-05-08 13:28:41 +00:00
// get new texture source bounds
FLOAT_RECT fTexBlt ;
// get new dest bounds
FLOAT_RECT tTexBlt ;
// set up blit data as rect
fTexBlt . left = Max < float > ( ( float ) ( fx - iBlitX ) , 0.0f ) ;
tTexBlt . left = ( fTexBlt . left + iBlitX - fx ) * Zoom + tx ;
fTexBlt . top = Max < float > ( ( float ) ( fy - iBlitY ) , 0.0f ) ;
tTexBlt . top = ( fTexBlt . top + iBlitY - fy ) * Zoom + ty ;
2010-09-04 17:30:45 +00:00
fTexBlt . right = Min < float > ( ( float ) ( fx + wdt - iBlitX ) , ( float ) iTexSizeX ) ;
2009-05-08 13:28:41 +00:00
tTexBlt . right = ( fTexBlt . right + iBlitX - fx ) * Zoom + tx ;
2010-09-04 17:30:45 +00:00
fTexBlt . bottom = Min < float > ( ( float ) ( fy + hgt - iBlitY ) , ( float ) iTexSizeY ) ;
2009-05-08 13:28:41 +00:00
tTexBlt . bottom = ( fTexBlt . bottom + iBlitY - fy ) * Zoom + ty ;
2011-09-30 20:15:51 +00:00
C4BltVertex Vtx [ 4 ] ;
2009-05-08 13:28:41 +00:00
// blit positions
Vtx [ 0 ] . ftx = tTexBlt . left ; Vtx [ 0 ] . fty = tTexBlt . top ;
Vtx [ 1 ] . ftx = tTexBlt . right ; Vtx [ 1 ] . fty = tTexBlt . top ;
Vtx [ 2 ] . ftx = tTexBlt . right ; Vtx [ 2 ] . fty = tTexBlt . bottom ;
Vtx [ 3 ] . ftx = tTexBlt . left ; Vtx [ 3 ] . fty = tTexBlt . bottom ;
// blit positions
Vtx [ 0 ] . tx = fTexBlt . left ; Vtx [ 0 ] . ty = fTexBlt . top ;
Vtx [ 1 ] . tx = fTexBlt . right ; Vtx [ 1 ] . ty = fTexBlt . top ;
Vtx [ 2 ] . tx = fTexBlt . right ; Vtx [ 2 ] . ty = fTexBlt . bottom ;
Vtx [ 3 ] . tx = fTexBlt . left ; Vtx [ 3 ] . ty = fTexBlt . bottom ;
// color modulation
// global modulation map
2009-05-27 23:36:03 +00:00
if ( shaders [ 0 ] & & fUseClrModMap )
2010-03-28 18:58:01 +00:00
{
2009-05-27 23:36:03 +00:00
glActiveTexture ( GL_TEXTURE3 ) ;
glLoadIdentity ( ) ;
2011-10-03 14:06:41 +00:00
C4Surface * pSurface = pClrModMap - > GetSurface ( ) ;
2010-09-04 17:30:45 +00:00
glScalef ( 1.0f / ( pClrModMap - > GetResolutionX ( ) * ( * pSurface - > ppTex ) - > iSizeX ) , 1.0f / ( pClrModMap - > GetResolutionY ( ) * ( * pSurface - > ppTex ) - > iSizeY ) , 1.0f ) ;
2009-05-27 23:36:03 +00:00
glTranslatef ( float ( - pClrModMap - > OffX ) , float ( - pClrModMap - > OffY ) , 0.0f ) ;
glClientActiveTexture ( GL_TEXTURE3 ) ;
glEnableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
2011-09-30 20:15:51 +00:00
glTexCoordPointer ( 2 , GL_FLOAT , sizeof ( C4BltVertex ) , & Vtx [ 0 ] . ftx ) ;
2009-05-27 23:36:03 +00:00
glClientActiveTexture ( GL_TEXTURE0 ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-27 23:36:03 +00:00
if ( ! shaders [ 0 ] & & fUseClrModMap & & dwModClr )
2010-03-28 18:58:01 +00:00
{
2009-05-27 23:36:03 +00:00
for ( int i = 0 ; i < 4 ; + + i )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
DWORD c = pClrModMap - > GetModAt ( int ( Vtx [ i ] . ftx ) , int ( Vtx [ i ] . fty ) ) ;
ModulateClr ( c , dwModClr ) ;
DwTo4UB ( c | dwModMask , Vtx [ i ] . color ) ;
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else
2010-03-28 18:58:01 +00:00
{
2009-05-27 23:36:03 +00:00
for ( int i = 0 ; i < 4 ; + + i )
2009-05-08 13:28:41 +00:00
DwTo4UB ( dwModClr | dwModMask , Vtx [ i ] . color ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-27 23:36:03 +00:00
for ( int i = 0 ; i < 4 ; + + i )
2010-03-28 18:58:01 +00:00
{
2010-09-04 17:30:45 +00:00
Vtx [ i ] . tx / = iTexSizeX ;
Vtx [ i ] . ty / = iTexSizeY ;
2009-05-08 13:28:41 +00:00
Vtx [ i ] . ftz = 0 ;
2010-03-28 18:58:01 +00:00
}
if ( mattextures )
{
2009-05-27 23:38:14 +00:00
GLfloat shaderparam [ 4 ] ;
2010-03-28 18:58:01 +00:00
for ( int cnt = 1 ; cnt < 127 ; cnt + + )
{
if ( mattextures [ cnt ] )
2009-05-27 23:38:14 +00:00
{
shaderparam [ 0 ] = static_cast < GLfloat > ( cnt ) / 255.0f ;
2009-05-27 23:36:03 +00:00
glProgramLocalParameter4fvARB ( GL_FRAGMENT_PROGRAM_ARB , 1 , shaderparam ) ;
//Bind Mat Texture
glActiveTexture ( GL_TEXTURE1 ) ;
2009-05-27 23:38:14 +00:00
glBindTexture ( GL_TEXTURE_2D , ( * ( mattextures [ cnt ] - > ppTex ) ) - > texName ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , GL_REPEAT ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T , GL_REPEAT ) ;
glActiveTexture ( GL_TEXTURE0 ) ;
2011-09-30 20:15:51 +00:00
glInterleavedArrays ( GL_T2F_C4UB_V3F , sizeof ( C4BltVertex ) , Vtx ) ;
2009-05-27 23:38:14 +00:00
glDrawArrays ( GL_QUADS , 0 , 4 ) ;
}
}
2010-03-28 18:58:01 +00:00
}
2009-05-27 23:38:14 +00:00
else
2010-03-28 18:58:01 +00:00
{
2011-09-30 20:15:51 +00:00
glInterleavedArrays ( GL_T2F_C4UB_V3F , sizeof ( C4BltVertex ) , Vtx ) ;
2009-05-27 23:38:14 +00:00
glDrawArrays ( GL_QUADS , 0 , 4 ) ;
2009-05-08 13:28:41 +00:00
}
2010-03-28 18:58:01 +00:00
2011-01-02 19:33:45 +00:00
if ( shaders [ 0 ] & & fUseClrModMap )
{
glClientActiveTexture ( GL_TEXTURE3 ) ;
glDisableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
glClientActiveTexture ( GL_TEXTURE0 ) ;
}
2009-05-08 13:28:41 +00:00
}
2010-03-28 18:58:01 +00:00
}
2009-05-27 23:31:31 +00:00
if ( mattextures )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
glActiveTexture ( GL_TEXTURE1 ) ;
glDisable ( GL_TEXTURE_2D ) ;
glActiveTexture ( GL_TEXTURE0 ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// reset texture
ResetTexture ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-08-27 21:12:01 +00:00
CStdGLCtx * CStdGL : : CreateContext ( C4Window * pWindow , C4AbstractApp * pApp )
2010-03-28 18:58:01 +00:00
{
2009-06-02 23:59:04 +00:00
DebugLog ( " gl: Create Context... " ) ;
2009-05-08 13:28:41 +00:00
// safety
if ( ! pWindow ) return NULL ;
// create it
CStdGLCtx * pCtx = new CStdGLCtx ( ) ;
2010-03-06 14:07:30 +00:00
if ( ! pMainCtx ) pMainCtx = pCtx ;
2009-05-08 13:28:41 +00:00
if ( ! pCtx - > Init ( pWindow , pApp ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
delete pCtx ; Error ( " gl: Error creating secondary context! " ) ; return NULL ;
2010-03-28 18:58:01 +00:00
}
2010-12-03 19:18:36 +00:00
// creation selected the new context - switch back to previous context
RenderTarget = NULL ;
pCurrCtx = NULL ;
2009-05-08 13:28:41 +00:00
// done
return pCtx ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2012-03-23 21:53:56 +00:00
# ifdef USE_WIN32_WINDOWS
2011-08-27 14:20:39 +00:00
CStdGLCtx * CStdGL : : CreateContext ( HWND hWindow , C4AbstractApp * pApp )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// safety
if ( ! hWindow ) return NULL ;
// create it
CStdGLCtx * pCtx = new CStdGLCtx ( ) ;
if ( ! pCtx - > Init ( NULL , pApp , hWindow ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
delete pCtx ; Error ( " gl: Error creating secondary context! " ) ; return NULL ;
2010-03-28 18:58:01 +00:00
}
2010-12-03 19:18:36 +00:00
if ( ! pMainCtx )
{
pMainCtx = pCtx ;
}
else
{
// creation selected the new context - switch back to previous context
RenderTarget = NULL ;
pCurrCtx = NULL ;
}
2009-05-08 13:28:41 +00:00
// done
return pCtx ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
# endif
2010-02-18 20:19:04 +00:00
bool CStdGL : : CreatePrimarySurfaces ( bool , unsigned int , unsigned int , int iColorDepth , unsigned int )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// store options
2009-05-31 00:09:15 +00:00
return RestoreDeviceObjects ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:07:07 +00:00
void CStdGL : : DrawQuadDw ( C4Surface * sfcTarget , float * ipVtx , DWORD dwClr1 , DWORD dwClr2 , DWORD dwClr3 , DWORD dwClr4 )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// prepare rendering to target
if ( ! PrepareRendering ( sfcTarget ) ) return ;
// apply global modulation
ClrByCurrentBlitMod ( dwClr1 ) ;
ClrByCurrentBlitMod ( dwClr2 ) ;
ClrByCurrentBlitMod ( dwClr3 ) ;
ClrByCurrentBlitMod ( dwClr4 ) ;
// apply modulation map
if ( fUseClrModMap )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
ModulateClr ( dwClr1 , pClrModMap - > GetModAt ( int ( ipVtx [ 0 ] ) , int ( ipVtx [ 1 ] ) ) ) ;
ModulateClr ( dwClr2 , pClrModMap - > GetModAt ( int ( ipVtx [ 2 ] ) , int ( ipVtx [ 3 ] ) ) ) ;
ModulateClr ( dwClr3 , pClrModMap - > GetModAt ( int ( ipVtx [ 4 ] ) , int ( ipVtx [ 5 ] ) ) ) ;
ModulateClr ( dwClr4 , pClrModMap - > GetModAt ( int ( ipVtx [ 6 ] ) , int ( ipVtx [ 7 ] ) ) ) ;
2010-03-28 18:58:01 +00:00
}
2010-02-18 16:24:43 +00:00
glShadeModel ( ( dwClr1 = = dwClr2 & & dwClr1 = = dwClr3 & & dwClr1 = = dwClr4 ) ? GL_FLAT : GL_SMOOTH ) ;
2009-05-08 13:28:41 +00:00
// set blitting state
int iAdditive = dwBlitMode & C4GFXBLIT_ADDITIVE ;
2009-08-23 21:46:56 +00:00
glBlendFunc ( GL_SRC_ALPHA , iAdditive ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA ) ;
2009-05-08 13:28:41 +00:00
// draw two triangles
glInterleavedArrays ( GL_V2F , sizeof ( float ) * 2 , ipVtx ) ;
GLubyte colors [ 4 ] [ 4 ] ;
DwTo4UB ( dwClr1 , colors [ 0 ] ) ;
DwTo4UB ( dwClr2 , colors [ 1 ] ) ;
DwTo4UB ( dwClr3 , colors [ 2 ] ) ;
DwTo4UB ( dwClr4 , colors [ 3 ] ) ;
glColorPointer ( 4 , GL_UNSIGNED_BYTE , 0 , colors ) ;
glEnableClientState ( GL_COLOR_ARRAY ) ;
glDrawArrays ( GL_POLYGON , 0 , 4 ) ;
2009-05-31 00:10:57 +00:00
glDisableClientState ( GL_COLOR_ARRAY ) ;
2009-05-08 13:28:41 +00:00
glShadeModel ( GL_FLAT ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2009-07-22 00:49:45 +00:00
# ifdef _MSC_VER
2010-02-27 13:48:01 +00:00
# ifdef _M_X64
2010-03-28 18:58:01 +00:00
# include <emmintrin.h>
2010-02-27 13:48:01 +00:00
# endif
2009-07-22 00:49:45 +00:00
static inline long int lrintf ( float f )
{
2010-02-27 13:48:01 +00:00
# ifdef _M_X64
return _mm_cvtt_ss2si ( _mm_load_ps1 ( & f ) ) ;
# else
2009-07-22 00:49:45 +00:00
long int i ;
2010-03-28 18:58:01 +00:00
__asm
{
2009-07-22 00:49:45 +00:00
fld f
fistp i
} ;
return i ;
2010-02-27 13:48:01 +00:00
# endif
2009-07-22 00:49:45 +00:00
}
# endif
2011-10-03 14:07:07 +00:00
void CStdGL : : PerformLine ( C4Surface * sfcTarget , float x1 , float y1 , float x2 , float y2 , DWORD dwClr )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// render target?
if ( sfcTarget - > IsRenderTarget ( ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// prepare rendering to target
if ( ! PrepareRendering ( sfcTarget ) ) return ;
2009-05-31 00:20:36 +00:00
SetTexture ( ) ;
SetupTextureEnv ( false , false ) ;
float offx = y1 - y2 ;
float offy = x2 - x1 ;
float l = sqrtf ( offx * offx + offy * offy ) ;
// avoid division by zero
l + = 0.000000005f ;
offx / = l ; offx * = Zoom ;
offy / = l ; offy * = Zoom ;
2011-09-30 20:15:51 +00:00
C4BltVertex vtx [ 4 ] ;
2009-05-31 00:20:36 +00:00
vtx [ 0 ] . ftx = x1 + offx ; vtx [ 0 ] . fty = y1 + offy ; vtx [ 0 ] . ftz = 0 ;
vtx [ 1 ] . ftx = x1 - offx ; vtx [ 1 ] . fty = y1 - offy ; vtx [ 1 ] . ftz = 0 ;
vtx [ 2 ] . ftx = x2 - offx ; vtx [ 2 ] . fty = y2 - offy ; vtx [ 2 ] . ftz = 0 ;
vtx [ 3 ] . ftx = x2 + offx ; vtx [ 3 ] . fty = y2 + offy ; vtx [ 3 ] . ftz = 0 ;
2009-05-08 13:28:41 +00:00
// global clr modulation map
DWORD dwClr1 = dwClr ;
2009-05-31 00:20:36 +00:00
glMatrixMode ( GL_TEXTURE ) ;
glLoadIdentity ( ) ;
2009-05-08 13:28:41 +00:00
if ( fUseClrModMap )
2010-03-28 18:58:01 +00:00
{
2009-05-31 00:20:36 +00:00
if ( shaders [ 0 ] )
2010-03-28 18:58:01 +00:00
{
2009-05-31 00:20:36 +00:00
glActiveTexture ( GL_TEXTURE3 ) ;
glLoadIdentity ( ) ;
2011-10-03 14:06:41 +00:00
C4Surface * pSurface = pClrModMap - > GetSurface ( ) ;
2010-09-04 17:30:45 +00:00
glScalef ( 1.0f / ( pClrModMap - > GetResolutionX ( ) * ( * pSurface - > ppTex ) - > iSizeX ) , 1.0f / ( pClrModMap - > GetResolutionY ( ) * ( * pSurface - > ppTex ) - > iSizeY ) , 1.0f ) ;
2009-05-31 00:20:36 +00:00
glTranslatef ( float ( - pClrModMap - > OffX ) , float ( - pClrModMap - > OffY ) , 0.0f ) ;
glClientActiveTexture ( GL_TEXTURE3 ) ;
glEnableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
2011-09-30 20:15:51 +00:00
glTexCoordPointer ( 2 , GL_FLOAT , sizeof ( C4BltVertex ) , & vtx [ 0 ] . ftx ) ;
2009-05-31 00:20:36 +00:00
glClientActiveTexture ( GL_TEXTURE0 ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-31 00:20:36 +00:00
else
2010-03-28 18:58:01 +00:00
{
2009-05-31 00:20:36 +00:00
ModulateClr ( dwClr1 , pClrModMap - > GetModAt ( lrintf ( x1 ) , lrintf ( y1 ) ) ) ;
ModulateClr ( dwClr , pClrModMap - > GetModAt ( lrintf ( x2 ) , lrintf ( y2 ) ) ) ;
2009-05-08 13:28:41 +00:00
}
2010-03-28 18:58:01 +00:00
}
2009-05-31 00:20:36 +00:00
glMatrixMode ( GL_MODELVIEW ) ;
glLoadIdentity ( ) ;
DwTo4UB ( dwClr1 , vtx [ 0 ] . color ) ;
DwTo4UB ( dwClr1 , vtx [ 1 ] . color ) ;
DwTo4UB ( dwClr , vtx [ 2 ] . color ) ;
DwTo4UB ( dwClr , vtx [ 3 ] . color ) ;
vtx [ 0 ] . tx = 0 ; vtx [ 0 ] . ty = 0 ;
vtx [ 1 ] . tx = 0 ; vtx [ 1 ] . ty = 2 ;
vtx [ 2 ] . tx = 1 ; vtx [ 2 ] . ty = 2 ;
vtx [ 3 ] . tx = 1 ; vtx [ 3 ] . ty = 0 ;
// draw two triangles
glActiveTexture ( GL_TEXTURE0 ) ;
glBindTexture ( GL_TEXTURE_2D , lines_tex ) ;
2011-09-30 20:15:51 +00:00
glInterleavedArrays ( GL_T2F_C4UB_V3F , sizeof ( C4BltVertex ) , vtx ) ;
2009-05-31 00:20:36 +00:00
glDrawArrays ( GL_POLYGON , 0 , 4 ) ;
glClientActiveTexture ( GL_TEXTURE3 ) ;
glDisableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
glClientActiveTexture ( GL_TEXTURE0 ) ;
ResetTexture ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// emulate
if ( ! LockSurfaceGlobal ( sfcTarget ) ) return ;
2010-06-28 23:02:16 +00:00
ForLine ( ( int32_t ) x1 , ( int32_t ) y1 , ( int32_t ) x2 , ( int32_t ) y2 , & DLineSPixDw , ( int ) dwClr ) ;
2009-05-08 13:28:41 +00:00
UnLockSurfaceGlobal ( sfcTarget ) ;
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2011-10-03 14:07:07 +00:00
void CStdGL : : PerformPix ( C4Surface * sfcTarget , float tx , float ty , DWORD dwClr )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// render target?
if ( sfcTarget - > IsRenderTarget ( ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( ! PrepareRendering ( sfcTarget ) ) return ;
int iAdditive = dwBlitMode & C4GFXBLIT_ADDITIVE ;
// use a different blendfunc here because of GL_POINT_SMOOTH
glBlendFunc ( GL_SRC_ALPHA , iAdditive ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA ) ;
// convert the alpha value for that blendfunc
glBegin ( GL_POINTS ) ;
2009-08-23 21:46:56 +00:00
glColorDw ( dwClr ) ;
2009-05-08 13:28:41 +00:00
glVertex2f ( tx + 0.5f , ty + 0.5f ) ;
glEnd ( ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// emulate
sfcTarget - > SetPixDw ( ( int ) tx , ( int ) ty , dwClr ) ;
2010-03-27 16:05:02 +00:00
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
static void DefineShaderARB ( const char * p , GLuint & s )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
glBindProgramARB ( GL_FRAGMENT_PROGRAM_ARB , s ) ;
glProgramStringARB ( GL_FRAGMENT_PROGRAM_ARB , GL_PROGRAM_FORMAT_ASCII_ARB , strlen ( p ) , p ) ;
if ( GL_INVALID_OPERATION = = glGetError ( ) )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
GLint errPos ; glGetIntegerv ( GL_PROGRAM_ERROR_POSITION_ARB , & errPos ) ;
fprintf ( stderr , " ARB program%d:%d: Error: %s \n " , s , errPos , glGetString ( GL_PROGRAM_ERROR_STRING_ARB ) ) ;
s = 0 ;
}
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool CStdGL : : RestoreDeviceObjects ( )
2010-03-28 18:58:01 +00:00
{
2010-03-06 14:07:30 +00:00
assert ( pMainCtx ) ;
2009-05-08 13:28:41 +00:00
// delete any previous objects
InvalidateDeviceObjects ( ) ;
2010-02-18 20:19:04 +00:00
2010-03-06 14:07:30 +00:00
// set states
Active = pMainCtx - > Select ( ) ;
RenderTarget = pApp - > pWindow - > pSurface ;
// BGRA Pixel Formats, Multitexturing, Texture Combine Environment Modes
2012-03-03 22:25:50 +00:00
// Check for GL 1.2 and two functions from 1.3 we need.
if ( ! GLEW_VERSION_1_2 | |
glActiveTexture = = NULL | |
glClientActiveTexture = = NULL
) {
2010-08-03 17:02:00 +00:00
return Error ( " gl: OpenGL Version 1.3 or higher required. A better graphics driver will probably help. " ) ;
2010-03-28 18:58:01 +00:00
}
2010-03-06 14:07:30 +00:00
2010-02-18 20:19:04 +00:00
// lines texture
glPixelStorei ( GL_UNPACK_ALIGNMENT , 1 ) ;
glGenTextures ( 1 , & lines_tex ) ;
glBindTexture ( GL_TEXTURE_2D , lines_tex ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , GL_MIRRORED_REPEAT ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T , GL_MIRRORED_REPEAT ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ;
const char * linedata = byByteCnt = = 2 ? " \xff \xf0 \xff \xff " : " \xff \xff \xff \x00 \xff \xff \xff \xff " ;
glTexImage2D ( GL_TEXTURE_2D , 0 , 4 , 1 , 2 , 0 , GL_BGRA , byByteCnt = = 2 ? GL_UNSIGNED_SHORT_4_4_4_4_REV : GL_UNSIGNED_INT_8_8_8_8_REV , linedata ) ;
2009-05-08 13:28:41 +00:00
2010-02-18 20:19:04 +00:00
MaxTexSize = 64 ;
GLint s = 0 ;
glGetIntegerv ( GL_MAX_TEXTURE_SIZE , & s ) ;
if ( s > 0 ) MaxTexSize = s ;
2009-05-08 13:28:41 +00:00
// restore gamma if active
if ( Active )
EnableGamma ( ) ;
// reset blit states
dwBlitMode = 0 ;
2009-05-27 23:36:03 +00:00
// Vertex Buffer Objects crash some versions of the free radeon driver. TODO: provide an option for them
2009-05-08 13:28:41 +00:00
if ( 0 & & GLEW_ARB_vertex_buffer_object )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
glGenBuffersARB ( 1 , & vbo ) ;
glBindBufferARB ( GL_ARRAY_BUFFER_ARB , vbo ) ;
2011-09-30 20:15:51 +00:00
glBufferDataARB ( GL_ARRAY_BUFFER_ARB , 8 * sizeof ( C4BltVertex ) , 0 , GL_STREAM_DRAW_ARB ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
2010-09-28 17:07:47 +00:00
if ( ! Config . Graphics . EnableShaders )
2010-03-28 18:58:01 +00:00
{
}
2009-05-08 13:28:41 +00:00
else if ( ! shaders [ 0 ] & & GLEW_ARB_fragment_program )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
glGenProgramsARB ( sizeof ( shaders ) / sizeof ( * shaders ) , shaders ) ;
const char * preface =
2010-03-28 18:58:01 +00:00
" !!ARBfp1.0 \n "
" TEMP tmp; \n "
// sample the texture
" TXP tmp, fragment.texcoord[0], texture, 2D; \n " ;
2009-09-19 17:36:31 +00:00
const char * alpha_mod =
2010-03-28 18:58:01 +00:00
// perform the modulation
" MUL tmp.rgba, tmp, fragment.color.primary; \n " ;
2009-05-08 13:28:41 +00:00
const char * funny_add =
2010-03-28 18:58:01 +00:00
// perform the modulation
" ADD tmp.rgb, tmp, fragment.color.primary; \n "
" MUL tmp.a, tmp, fragment.color.primary; \n "
" MAD_SAT tmp, tmp, { 2.0, 2.0, 2.0, 1.0 }, { -1.0, -1.0, -1.0, 0.0 }; \n " ;
2009-05-08 13:28:41 +00:00
const char * grey =
2010-03-28 18:58:01 +00:00
" TEMP grey; \n "
" DP3 grey, tmp, { 0.299, 0.587, 0.114, 1.0 }; \n "
" LRP tmp.rgb, program.local[0], tmp, grey; \n " ;
2009-05-27 23:38:14 +00:00
const char * landscape =
2010-03-28 18:58:01 +00:00
" TEMP col; \n "
" MOV col.x, program.local[1].x; \n " //Load color to indentify
" ADD col.y, col.x, 0.001; \n "
" SUB col.z, col.x, 0.001; \n " //epsilon-range
" SGE tmp.r, tmp.b, 0.5015; \n " //Tunnel?
" MAD tmp.r, tmp.r, -0.5019, tmp.b; \n "
" SGE col.z, tmp.r, col.z; \n " //mat identified?
" SLT col.y, tmp.r, col.y; \n "
" TEMP coo; \n "
" MOV coo, fragment.texcoord; \n "
" MUL coo.xy, coo, 3.0; \n "
" TXP tmp, coo, texture[1], 2D; \n "
" MUL tmp.a, col.y, col.z; \n " ;
2009-05-08 13:28:41 +00:00
const char * fow =
2010-03-28 18:58:01 +00:00
" TEMP fow; \n "
// sample the texture
" TXP fow, fragment.texcoord[3], texture[3], 2D; \n "
" LRP tmp.rgb, fow.aaaa, tmp, fow; \n " ;
2009-05-08 13:28:41 +00:00
const char * end =
2010-03-28 18:58:01 +00:00
" MOV result.color, tmp; \n "
" END \n " ;
2009-09-19 17:36:31 +00:00
DefineShaderARB ( FormatString ( " %s%s%s " , preface , alpha_mod , end ) . getData ( ) , shaders [ 0 ] ) ;
2009-05-27 23:36:03 +00:00
DefineShaderARB ( FormatString ( " %s%s%s " , preface , funny_add , end ) . getData ( ) , shaders [ 1 ] ) ;
2009-09-19 17:36:31 +00:00
DefineShaderARB ( FormatString ( " %s%s%s%s " , preface , landscape , alpha_mod , end ) . getData ( ) , shaders [ 2 ] ) ;
DefineShaderARB ( FormatString ( " %s%s%s%s " , preface , alpha_mod , grey , end ) . getData ( ) , shaders [ 3 ] ) ;
2009-05-27 23:36:03 +00:00
DefineShaderARB ( FormatString ( " %s%s%s%s " , preface , funny_add , grey , end ) . getData ( ) , shaders [ 4 ] ) ;
2009-09-19 17:36:31 +00:00
DefineShaderARB ( FormatString ( " %s%s%s%s%s " , preface , landscape , alpha_mod , grey , end ) . getData ( ) , shaders [ 5 ] ) ;
DefineShaderARB ( FormatString ( " %s%s%s%s " , preface , alpha_mod , fow , end ) . getData ( ) , shaders [ 6 ] ) ;
2009-05-27 23:36:03 +00:00
DefineShaderARB ( FormatString ( " %s%s%s%s " , preface , funny_add , fow , end ) . getData ( ) , shaders [ 7 ] ) ;
2009-09-19 17:36:31 +00:00
DefineShaderARB ( FormatString ( " %s%s%s%s%s " , preface , landscape , alpha_mod , fow , end ) . getData ( ) , shaders [ 8 ] ) ;
DefineShaderARB ( FormatString ( " %s%s%s%s%s " , preface , alpha_mod , grey , fow , end ) . getData ( ) , shaders [ 9 ] ) ;
2009-05-27 23:36:03 +00:00
DefineShaderARB ( FormatString ( " %s%s%s%s%s " , preface , funny_add , grey , fow , end ) . getData ( ) , shaders [ 10 ] ) ;
2009-09-19 17:36:31 +00:00
DefineShaderARB ( FormatString ( " %s%s%s%s%s%s " , preface , landscape , alpha_mod , grey , fow , end ) . getData ( ) , shaders [ 11 ] ) ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
// done
return Active ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool CStdGL : : InvalidateDeviceObjects ( )
{
bool fSuccess = true ;
// clear gamma
2010-03-28 18:58:01 +00:00
# ifndef USE_SDL_MAINLOOP
2009-05-08 13:28:41 +00:00
DisableGamma ( ) ;
2010-03-28 18:58:01 +00:00
# endif
2009-05-08 13:28:41 +00:00
// deactivate
Active = false ;
// invalidate font objects
// invalidate primary surfaces
2010-02-18 20:19:04 +00:00
if ( lines_tex )
2010-03-28 18:58:01 +00:00
{
2010-02-18 20:19:04 +00:00
glDeleteTextures ( 1 , & lines_tex ) ;
lines_tex = 0 ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
if ( shaders [ 0 ] )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
glDeleteProgramsARB ( sizeof ( shaders ) / sizeof ( * shaders ) , shaders ) ;
shaders [ 0 ] = 0 ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
if ( vbo )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
glDeleteBuffersARB ( 1 , & vbo ) ;
vbo = 0 ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
return fSuccess ;
}
void CStdGL : : SetTexture ( )
2010-03-28 18:58:01 +00:00
{
2009-08-23 21:46:56 +00:00
glBlendFunc ( GL_SRC_ALPHA , ( dwBlitMode & C4GFXBLIT_ADDITIVE ) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA ) ;
2009-08-28 13:52:22 +00:00
if ( shaders [ 0 ] )
2010-03-28 18:58:01 +00:00
{
2009-05-31 00:10:57 +00:00
glEnable ( GL_FRAGMENT_PROGRAM_ARB ) ;
2009-08-28 13:52:22 +00:00
if ( fUseClrModMap )
2010-03-28 18:58:01 +00:00
{
2009-08-28 13:52:22 +00:00
glActiveTexture ( GL_TEXTURE3 ) ;
glEnable ( GL_TEXTURE_2D ) ;
glBindTexture ( GL_TEXTURE_2D , ( * pClrModMap - > GetSurface ( ) - > ppTex ) - > texName ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ;
glActiveTexture ( GL_TEXTURE0 ) ;
2009-05-31 00:10:57 +00:00
}
2009-05-08 13:28:41 +00:00
}
2010-03-28 18:58:01 +00:00
glEnable ( GL_TEXTURE_2D ) ;
}
2009-05-08 13:28:41 +00:00
void CStdGL : : ResetTexture ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// disable texturing
2009-05-31 00:10:57 +00:00
if ( shaders [ 0 ] )
2010-03-28 18:58:01 +00:00
{
2009-05-31 00:10:57 +00:00
glDisable ( GL_FRAGMENT_PROGRAM_ARB ) ;
glActiveTexture ( GL_TEXTURE3 ) ;
glDisable ( GL_TEXTURE_2D ) ;
glActiveTexture ( GL_TEXTURE0 ) ;
2009-05-08 13:28:41 +00:00
}
2010-03-28 18:58:01 +00:00
glDisable ( GL_TEXTURE_2D ) ;
}
2009-05-08 13:28:41 +00:00
2010-08-03 17:02:00 +00:00
bool CStdGL : : Error ( const char * szMsg )
{
LogF ( " gl: %s " , glGetString ( GL_VENDOR ) ) ;
LogF ( " gl: %s " , glGetString ( GL_RENDERER ) ) ;
LogF ( " gl: %s " , glGetString ( GL_VERSION ) ) ;
LogF ( " gl: %s " , glGetString ( GL_EXTENSIONS ) ) ;
2011-10-03 14:34:08 +00:00
return C4Draw : : Error ( szMsg ) ;
2010-08-03 17:02:00 +00:00
}
2009-05-08 13:28:41 +00:00
bool CStdGL : : CheckGLError ( const char * szAtOp )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
GLenum err = glGetError ( ) ;
if ( ! err ) return true ;
Log ( szAtOp ) ;
switch ( err )
2010-03-28 18:58:01 +00:00
{
case GL_INVALID_ENUM : Log ( " GL_INVALID_ENUM " ) ; break ;
case GL_INVALID_VALUE : Log ( " GL_INVALID_VALUE " ) ; break ;
case GL_INVALID_OPERATION : Log ( " GL_INVALID_OPERATION " ) ; break ;
case GL_STACK_OVERFLOW : Log ( " GL_STACK_OVERFLOW " ) ; break ;
case GL_STACK_UNDERFLOW : Log ( " GL_STACK_UNDERFLOW " ) ; break ;
case GL_OUT_OF_MEMORY : Log ( " GL_OUT_OF_MEMORY " ) ; break ;
default : Log ( " unknown error " ) ; break ;
2009-05-08 13:28:41 +00:00
}
2010-03-28 18:58:01 +00:00
return false ;
}
2009-05-08 13:28:41 +00:00
CStdGL * pGL = NULL ;
2012-04-07 19:33:39 +00:00
# ifdef USE_WIN32_WINDOWS
2009-05-08 13:28:41 +00:00
void CStdGL : : TaskOut ( )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if ( pCurrCtx ) pCurrCtx - > Deselect ( ) ;
2010-03-28 18:58:01 +00:00
}
2010-09-05 13:07:45 +00:00
# endif
2009-05-08 13:28:41 +00:00
bool CStdGL : : OnResolutionChanged ( unsigned int iXRes , unsigned int iYRes )
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Re-create primary clipper to adapt to new size.
CreatePrimaryClipper ( iXRes , iYRes ) ;
2010-02-18 20:19:04 +00:00
RestoreDeviceObjects ( ) ;
2009-05-08 13:28:41 +00:00
return true ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void CStdGL : : Default ( )
2010-03-28 18:58:01 +00:00
{
2011-10-03 14:34:08 +00:00
C4Draw : : Default ( ) ;
2010-03-06 14:07:30 +00:00
pCurrCtx = NULL ;
2009-05-08 13:28:41 +00:00
iPixelFormat = 0 ;
sfcFmt = 0 ;
iClrDpt = 0 ;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
# endif // USE_GL