2008-10-28 09:46:13 -07:00
// Copyright (C) 2002-2008 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
# include "COGLESDriver.h"
2013-10-25 09:08:45 -07:00
# include "SIrrCreationParameters.h" // for createDriver function
# include "SExposedVideoData.h" // also
# include "IFileSystem.h" // and here as well
2008-10-28 09:46:13 -07:00
# ifdef _IRR_COMPILE_WITH_OGLES1_
2008-11-12 15:04:00 -08:00
# include "COGLESTexture.h"
# include "COGLESMaterialRenderer.h"
2008-10-28 09:46:13 -07:00
# include "CImage.h"
# include "os.h"
2009-10-01 10:00:20 -07:00
# ifdef _IRR_COMPILE_WITH_SDL_DEVICE_
2008-10-28 09:46:13 -07:00
# include <SDL/SDL.h>
# endif
namespace irr
{
namespace video
{
2009-01-02 17:02:59 -08:00
COGLES1Driver : : COGLES1Driver ( const SIrrlichtCreationParameters & params ,
2013-11-13 15:20:30 -08:00
io : : IFileSystem * io
2014-09-12 11:38:11 -07:00
# if defined(_IRR_COMPILE_WITH_X11_DEVICE_) || defined(_IRR_WINDOWS_API_) || defined(_IRR_COMPILE_WITH_ANDROID_DEVICE_) || defined(_IRR_COMPILE_WITH_FB_DEVICE_)
2013-10-25 17:02:19 -07:00
, IContextManager * contextManager
2013-10-16 23:50:30 -07:00
# elif defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_)
, CIrrDeviceIPhone * device
2009-01-02 17:02:59 -08:00
# endif
2013-10-16 23:50:30 -07:00
) : CNullDriver ( io , params . WindowSize ) , COGLES1ExtensionHandler ( ) ,
2008-10-28 09:46:13 -07:00
CurrentRenderMode ( ERM_NONE ) , ResetRenderStates ( true ) ,
Transformation3DChanged ( true ) , AntiAlias ( params . AntiAlias ) ,
2014-05-10 14:47:14 -07:00
RenderTargetTexture ( 0 ) , CurrentRendertargetSize ( 0 , 0 ) , ColorFormat ( ECF_R8G8B8 ) , BridgeCalls ( 0 )
2014-09-12 11:38:11 -07:00
# if defined(_IRR_COMPILE_WITH_X11_DEVICE_) || defined(_IRR_WINDOWS_API_) || defined(_IRR_COMPILE_WITH_ANDROID_DEVICE_) || defined(_IRR_COMPILE_WITH_FB_DEVICE_)
2013-10-25 17:02:19 -07:00
, ContextManager ( contextManager )
2009-10-01 10:00:20 -07:00
# elif defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_)
2013-10-16 23:50:30 -07:00
, Device ( device ) , ViewFramebuffer ( 0 ) ,
ViewRenderbuffer ( 0 ) , ViewDepthRenderbuffer ( 0 )
2008-11-12 15:04:00 -08:00
# endif
2008-10-28 09:46:13 -07:00
{
2013-10-16 23:50:30 -07:00
# ifdef _DEBUG
2008-10-28 09:46:13 -07:00
setDebugName ( " COGLESDriver " ) ;
2008-11-12 15:04:00 -08:00
# endif
2013-10-16 23:50:30 -07:00
core : : dimension2d < u32 > WindowSize ( 0 , 0 ) ;
2012-09-06 16:14:12 -07:00
2014-09-12 11:38:11 -07:00
# if defined(_IRR_COMPILE_WITH_X11_DEVICE_) || defined(_IRR_WINDOWS_API_) || defined(_IRR_COMPILE_WITH_ANDROID_DEVICE_) || defined(_IRR_COMPILE_WITH_FB_DEVICE_)
2013-10-25 17:02:19 -07:00
if ( ! ContextManager )
return ;
ContextManager - > grab ( ) ;
2013-11-13 15:20:30 -08:00
ContextManager - > generateSurface ( ) ;
ContextManager - > generateContext ( ) ;
ExposedData = ContextManager - > getContext ( ) ;
ContextManager - > activateContext ( ExposedData ) ;
2008-11-12 15:04:00 -08:00
2013-11-19 15:09:06 -08:00
WindowSize = params . WindowSize ;
2013-10-16 23:50:30 -07:00
# elif defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_)
2009-01-02 17:02:59 -08:00
glGenFramebuffersOES ( 1 , & ViewFramebuffer ) ;
glGenRenderbuffersOES ( 1 , & ViewRenderbuffer ) ;
glBindRenderbufferOES ( GL_RENDERBUFFER_OES , ViewRenderbuffer ) ;
2009-05-07 02:34:53 -07:00
2012-10-24 19:25:31 -07:00
ExposedData . OGLESIPhone . AppDelegate = Device ;
2013-11-19 15:09:06 -08:00
Device - > displayInitialize ( & ExposedData . OGLESIPhone . Context , & ExposedData . OGLESIPhone . View ) ;
2009-05-07 02:34:53 -07:00
2009-01-02 17:02:59 -08:00
GLint backingWidth ;
GLint backingHeight ;
2012-10-22 18:03:27 -07:00
glGetRenderbufferParameterivOES ( GL_RENDERBUFFER_OES , GL_RENDERBUFFER_WIDTH_OES , & backingWidth ) ;
glGetRenderbufferParameterivOES ( GL_RENDERBUFFER_OES , GL_RENDERBUFFER_HEIGHT_OES , & backingHeight ) ;
2014-05-08 09:23:12 -07:00
2009-01-02 17:02:59 -08:00
glGenRenderbuffersOES ( 1 , & ViewDepthRenderbuffer ) ;
glBindRenderbufferOES ( GL_RENDERBUFFER_OES , ViewDepthRenderbuffer ) ;
2014-05-08 09:23:12 -07:00
2012-10-22 18:03:27 -07:00
GLenum depthComponent = GL_DEPTH_COMPONENT16_OES ;
2014-05-08 09:23:12 -07:00
2012-10-22 18:03:27 -07:00
if ( params . ZBufferBits > = 24 )
depthComponent = GL_DEPTH_COMPONENT24_OES ;
2014-05-08 09:23:12 -07:00
2012-10-22 18:03:27 -07:00
glRenderbufferStorageOES ( GL_RENDERBUFFER_OES , depthComponent , backingWidth , backingHeight ) ;
2014-05-08 09:23:12 -07:00
2009-05-07 02:34:53 -07:00
glBindFramebufferOES ( GL_FRAMEBUFFER_OES , ViewFramebuffer ) ;
2012-10-22 18:03:27 -07:00
glFramebufferRenderbufferOES ( GL_FRAMEBUFFER_OES , GL_COLOR_ATTACHMENT0_OES , GL_RENDERBUFFER_OES , ViewRenderbuffer ) ;
glFramebufferRenderbufferOES ( GL_FRAMEBUFFER_OES , GL_DEPTH_ATTACHMENT_OES , GL_RENDERBUFFER_OES , ViewDepthRenderbuffer ) ;
2014-05-08 09:23:12 -07:00
2013-10-16 23:50:30 -07:00
WindowSize = core : : dimension2d < u32 > ( backingWidth , backingHeight ) ;
2012-10-22 18:03:27 -07:00
CNullDriver : : ScreenSize = WindowSize ;
CNullDriver : : ViewPort = core : : rect < s32 > ( core : : position2d < s32 > ( 0 , 0 ) , core : : dimension2di ( WindowSize ) ) ;
2009-01-02 16:49:20 -08:00
# endif
2013-10-16 23:50:30 -07:00
genericDriverInit ( WindowSize , params . Stencilbuffer ) ;
2008-10-28 09:46:13 -07:00
}
2008-11-12 15:04:00 -08:00
COGLES1Driver : : ~ COGLES1Driver ( )
2008-10-28 09:46:13 -07:00
{
2010-01-24 12:26:32 -08:00
RequestedLights . clear ( ) ;
2014-05-22 10:07:49 -07:00
CurrentTexture . clear ( ) ;
2008-10-28 09:46:13 -07:00
deleteMaterialRenders ( ) ;
deleteAllTextures ( ) ;
2014-05-10 14:47:14 -07:00
delete BridgeCalls ;
2014-09-12 11:38:11 -07:00
# if defined(_IRR_COMPILE_WITH_X11_DEVICE_) || defined(_IRR_WINDOWS_API_) || defined(_IRR_COMPILE_WITH_ANDROID_DEVICE_) || defined(_IRR_COMPILE_WITH_FB_DEVICE_)
2013-10-25 17:02:19 -07:00
if ( ContextManager )
{
ContextManager - > destroyContext ( ) ;
2013-11-13 15:20:30 -08:00
ContextManager - > destroySurface ( ) ;
2013-10-25 17:02:19 -07:00
ContextManager - > drop ( ) ;
}
2013-10-16 23:50:30 -07:00
# elif defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_)
2009-01-02 17:02:59 -08:00
if ( 0 ! = ViewFramebuffer )
{
extGlDeleteFramebuffers ( 1 , & ViewFramebuffer ) ;
ViewFramebuffer = 0 ;
}
if ( 0 ! = ViewRenderbuffer )
{
extGlDeleteRenderbuffers ( 1 , & ViewRenderbuffer ) ;
ViewRenderbuffer = 0 ;
}
if ( 0 ! = ViewDepthRenderbuffer )
{
extGlDeleteRenderbuffers ( 1 , & ViewDepthRenderbuffer ) ;
ViewDepthRenderbuffer = 0 ;
}
2009-01-02 16:49:20 -08:00
# endif
2008-10-28 09:46:13 -07:00
}
// -----------------------------------------------------------------------
// METHODS
// -----------------------------------------------------------------------
2009-01-27 05:45:17 -08:00
bool COGLES1Driver : : genericDriverInit ( const core : : dimension2d < u32 > & screenSize , bool stencilBuffer )
2008-10-28 09:46:13 -07:00
{
2009-01-02 16:49:20 -08:00
Name = glGetString ( GL_VERSION ) ;
2008-10-28 09:46:13 -07:00
printVersion ( ) ;
// print renderer information
2009-01-02 16:49:20 -08:00
vendorName = glGetString ( GL_VENDOR ) ;
2008-11-12 15:04:00 -08:00
os : : Printer : : log ( vendorName . c_str ( ) , ELL_INFORMATION ) ;
2008-10-28 09:46:13 -07:00
2014-05-22 10:07:49 -07:00
CurrentTexture . clear ( ) ;
2008-10-28 09:46:13 -07:00
// load extensions
2013-10-16 23:50:30 -07:00
initExtensions ( this , stencilBuffer ) ;
2014-05-10 14:47:14 -07:00
if ( ! BridgeCalls )
BridgeCalls = new COGLES1CallBridge ( this ) ;
2009-05-05 14:14:21 -07:00
StencilBuffer = stencilBuffer ;
2008-10-28 09:46:13 -07:00
2011-06-09 07:53:26 -07:00
DriverAttributes - > setAttribute ( " MaxTextures " , MaxTextureUnits ) ;
DriverAttributes - > setAttribute ( " MaxSupportedTextures " , MaxSupportedTextures ) ;
DriverAttributes - > setAttribute ( " MaxLights " , MaxLights ) ;
DriverAttributes - > setAttribute ( " MaxAnisotropy " , MaxAnisotropy ) ;
DriverAttributes - > setAttribute ( " MaxUserClipPlanes " , MaxUserClipPlanes ) ;
DriverAttributes - > setAttribute ( " MaxAuxBuffers " , MaxAuxBuffers ) ;
DriverAttributes - > setAttribute ( " MaxMultipleRenderTargets " , MaxMultipleRenderTargets ) ;
DriverAttributes - > setAttribute ( " MaxIndices " , ( s32 ) MaxIndices ) ;
DriverAttributes - > setAttribute ( " MaxTextureSize " , ( s32 ) MaxTextureSize ) ;
DriverAttributes - > setAttribute ( " MaxTextureLODBias " , MaxTextureLODBias ) ;
DriverAttributes - > setAttribute ( " Version " , Version ) ;
DriverAttributes - > setAttribute ( " AntiAlias " , AntiAlias ) ;
2008-10-28 09:46:13 -07:00
glPixelStorei ( GL_PACK_ALIGNMENT , 1 ) ;
// Reset The Current Viewport
glViewport ( 0 , 0 , screenSize . Width , screenSize . Height ) ;
2010-01-24 12:26:32 -08:00
UserClipPlane . reallocate ( MaxUserClipPlanes ) ;
UserClipPlaneEnabled . reallocate ( MaxUserClipPlanes ) ;
2014-05-22 10:07:49 -07:00
u32 i = 0 ;
2010-01-24 12:26:32 -08:00
for ( i = 0 ; i < MaxUserClipPlanes ; + + i )
{
UserClipPlane . push_back ( core : : plane3df ( ) ) ;
UserClipPlaneEnabled . push_back ( false ) ;
}
for ( i = 0 ; i < ETS_COUNT ; + + i )
setTransform ( static_cast < E_TRANSFORMATION_STATE > ( i ) , core : : IdentityMatrix ) ;
2008-10-28 09:46:13 -07:00
setAmbientLight ( SColorf ( 0.0f , 0.0f , 0.0f , 0.0f ) ) ;
// TODO ogl-es
// glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
2010-01-24 12:26:32 -08:00
glClearDepthf ( 1.0f ) ;
2009-01-02 03:11:50 -08:00
glHint ( GL_PERSPECTIVE_CORRECTION_HINT , GL_FASTEST ) ;
glHint ( GL_GENERATE_MIPMAP_HINT , GL_FASTEST ) ;
2010-01-24 12:26:32 -08:00
glHint ( GL_LINE_SMOOTH_HINT , GL_FASTEST ) ;
glHint ( GL_POINT_SMOOTH_HINT , GL_FASTEST ) ;
2008-10-28 09:46:13 -07:00
glDepthFunc ( GL_LEQUAL ) ;
glFrontFace ( GL_CW ) ;
// create material renderers
createMaterialRenderers ( ) ;
// set the renderstates
setRenderStates3DMode ( ) ;
glAlphaFunc ( GL_GREATER , 0.f ) ;
// set fog mode
2009-10-01 10:00:20 -07:00
setFog ( FogColor , FogType , FogStart , FogEnd , FogDensity , PixelFog , RangeFog ) ;
2008-10-28 09:46:13 -07:00
// create matrix for flipping textures
TextureFlipMatrix . buildTextureTransform ( 0.0f , core : : vector2df ( 0 , 0 ) , core : : vector2df ( 0 , 1.0f ) , core : : vector2df ( 1.0f , - 1.0f ) ) ;
2009-05-05 15:27:24 -07:00
// We need to reset once more at the beginning of the first rendering.
// This fixes problems with intermediate changes to the material during texture load.
ResetRenderStates = true ;
2008-10-28 09:46:13 -07:00
return true ;
}
2008-11-12 15:04:00 -08:00
void COGLES1Driver : : createMaterialRenderers ( )
2008-10-28 09:46:13 -07:00
{
2008-11-12 15:04:00 -08:00
// create OGLES1 material renderers
2008-10-28 09:46:13 -07:00
2008-11-12 15:04:00 -08:00
addAndDropMaterialRenderer ( new COGLES1MaterialRenderer_SOLID ( this ) ) ;
addAndDropMaterialRenderer ( new COGLES1MaterialRenderer_SOLID_2_LAYER ( this ) ) ;
2008-10-28 09:46:13 -07:00
// add the same renderer for all lightmap types
2008-11-12 15:04:00 -08:00
COGLES1MaterialRenderer_LIGHTMAP * lmr = new COGLES1MaterialRenderer_LIGHTMAP ( this ) ;
2008-10-28 09:46:13 -07:00
addMaterialRenderer ( lmr ) ; // for EMT_LIGHTMAP:
addMaterialRenderer ( lmr ) ; // for EMT_LIGHTMAP_ADD:
addMaterialRenderer ( lmr ) ; // for EMT_LIGHTMAP_M2:
addMaterialRenderer ( lmr ) ; // for EMT_LIGHTMAP_M4:
addMaterialRenderer ( lmr ) ; // for EMT_LIGHTMAP_LIGHTING:
addMaterialRenderer ( lmr ) ; // for EMT_LIGHTMAP_LIGHTING_M2:
addMaterialRenderer ( lmr ) ; // for EMT_LIGHTMAP_LIGHTING_M4:
lmr - > drop ( ) ;
// add remaining material renderer
2008-11-12 15:04:00 -08:00
addAndDropMaterialRenderer ( new COGLES1MaterialRenderer_DETAIL_MAP ( this ) ) ;
addAndDropMaterialRenderer ( new COGLES1MaterialRenderer_SPHERE_MAP ( this ) ) ;
addAndDropMaterialRenderer ( new COGLES1MaterialRenderer_REFLECTION_2_LAYER ( this ) ) ;
addAndDropMaterialRenderer ( new COGLES1MaterialRenderer_TRANSPARENT_ADD_COLOR ( this ) ) ;
addAndDropMaterialRenderer ( new COGLES1MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL ( this ) ) ;
addAndDropMaterialRenderer ( new COGLES1MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF ( this ) ) ;
addAndDropMaterialRenderer ( new COGLES1MaterialRenderer_TRANSPARENT_VERTEX_ALPHA ( this ) ) ;
addAndDropMaterialRenderer ( new COGLES1MaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER ( this ) ) ;
2008-10-28 09:46:13 -07:00
// add normal map renderers
2008-11-12 15:04:00 -08:00
// TODO ogl-es
2009-05-05 15:35:59 -07:00
addAndDropMaterialRenderer ( new COGLES1MaterialRenderer_SOLID ( this ) ) ;
addAndDropMaterialRenderer ( new COGLES1MaterialRenderer_SOLID ( this ) ) ;
addAndDropMaterialRenderer ( new COGLES1MaterialRenderer_SOLID ( this ) ) ;
2008-10-28 09:46:13 -07:00
// add parallax map renderers
2009-05-05 15:35:59 -07:00
addAndDropMaterialRenderer ( new COGLES1MaterialRenderer_SOLID ( this ) ) ;
addAndDropMaterialRenderer ( new COGLES1MaterialRenderer_SOLID ( this ) ) ;
addAndDropMaterialRenderer ( new COGLES1MaterialRenderer_SOLID ( this ) ) ;
2008-10-28 09:46:13 -07:00
// add basic 1 texture blending
2008-11-12 15:04:00 -08:00
addAndDropMaterialRenderer ( new COGLES1MaterialRenderer_ONETEXTURE_BLEND ( this ) ) ;
2008-10-28 09:46:13 -07:00
}
//! presents the rendered scene on the screen, returns false if failed
2008-11-12 15:04:00 -08:00
bool COGLES1Driver : : endScene ( )
2008-10-28 09:46:13 -07:00
{
CNullDriver : : endScene ( ) ;
2014-09-12 11:38:11 -07:00
# if defined(_IRR_COMPILE_WITH_X11_DEVICE_) || defined(_IRR_WINDOWS_API_) || defined(_IRR_COMPILE_WITH_ANDROID_DEVICE_) || defined(_IRR_COMPILE_WITH_FB_DEVICE_)
2013-10-25 17:02:19 -07:00
ContextManager - > swapBuffers ( ) ;
2013-10-16 23:50:30 -07:00
# elif defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_)
glFlush ( ) ;
2009-01-02 17:02:59 -08:00
glBindRenderbufferOES ( GL_RENDERBUFFER_OES , ViewRenderbuffer ) ;
2012-10-24 19:25:31 -07:00
Device - > displayEnd ( ) ;
2009-01-02 16:49:20 -08:00
# endif
2008-11-12 15:04:00 -08:00
2008-10-28 09:46:13 -07:00
return true ;
}
//! clears the zbuffer
2008-11-12 15:04:00 -08:00
bool COGLES1Driver : : beginScene ( bool backBuffer , bool zBuffer , SColor color ,
2010-01-23 17:44:36 -08:00
const SExposedVideoData & videoData ,
core : : rect < s32 > * sourceRect )
2008-10-28 09:46:13 -07:00
{
2008-11-12 15:04:00 -08:00
CNullDriver : : beginScene ( backBuffer , zBuffer , color ) ;
2008-10-28 09:46:13 -07:00
2012-10-24 19:25:31 -07:00
# if defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_)
Device - > displayBegin ( ) ;
2009-01-02 17:02:59 -08:00
glBindFramebufferOES ( GL_FRAMEBUFFER_OES , ViewFramebuffer ) ;
# endif
2008-10-28 09:46:13 -07:00
GLbitfield mask = 0 ;
if ( backBuffer )
{
2014-05-25 08:34:18 -07:00
glColorMask ( GL_TRUE , GL_TRUE , GL_TRUE , GL_TRUE ) ;
Material . ColorMask = ECP_ALL ;
2008-10-28 09:46:13 -07:00
const f32 inv = 1.0f / 255.0f ;
glClearColor ( color . getRed ( ) * inv , color . getGreen ( ) * inv ,
color . getBlue ( ) * inv , color . getAlpha ( ) * inv ) ;
mask | = GL_COLOR_BUFFER_BIT ;
}
if ( zBuffer )
{
glDepthMask ( GL_TRUE ) ;
2014-05-25 08:34:18 -07:00
Material . ZWriteEnable = true ;
2008-10-28 09:46:13 -07:00
mask | = GL_DEPTH_BUFFER_BIT ;
}
glClear ( mask ) ;
return true ;
}
//! Returns the transformation set by setTransform
2008-11-12 15:04:00 -08:00
const core : : matrix4 & COGLES1Driver : : getTransform ( E_TRANSFORMATION_STATE state ) const
2008-10-28 09:46:13 -07:00
{
return Matrices [ state ] ;
}
//! sets transformation
2008-11-12 15:04:00 -08:00
void COGLES1Driver : : setTransform ( E_TRANSFORMATION_STATE state , const core : : matrix4 & mat )
2008-10-28 09:46:13 -07:00
{
Matrices [ state ] = mat ;
Transformation3DChanged = true ;
switch ( state )
{
case ETS_VIEW :
case ETS_WORLD :
{
2008-11-12 15:04:00 -08:00
// OGLES1 only has a model matrix, view and world is not existent. so lets fake these two.
2008-10-28 09:46:13 -07:00
glMatrixMode ( GL_MODELVIEW ) ;
glLoadMatrixf ( ( Matrices [ ETS_VIEW ] * Matrices [ ETS_WORLD ] ) . pointer ( ) ) ;
// we have to update the clip planes to the latest view matrix
for ( u32 i = 0 ; i < MaxUserClipPlanes ; + + i )
if ( UserClipPlaneEnabled [ i ] )
uploadClipPlane ( i ) ;
}
break ;
case ETS_PROJECTION :
{
GLfloat glmat [ 16 ] ;
createGLMatrix ( glmat , mat ) ;
2008-11-12 15:04:00 -08:00
// flip z to compensate OGLES1s right-hand coordinate system
2008-10-28 09:46:13 -07:00
glmat [ 12 ] * = - 1.0f ;
glMatrixMode ( GL_PROJECTION ) ;
glLoadMatrixf ( glmat ) ;
}
break ;
case ETS_TEXTURE_0 :
case ETS_TEXTURE_1 :
case ETS_TEXTURE_2 :
case ETS_TEXTURE_3 :
{
const u32 i = state - ETS_TEXTURE_0 ;
2008-12-16 09:09:01 -08:00
if ( i > = MaxTextureUnits )
break ;
2008-10-28 09:46:13 -07:00
const bool isRTT = Material . getTexture ( i ) & & Material . getTexture ( i ) - > isRenderTarget ( ) ;
if ( MultiTextureExtension )
extGlActiveTexture ( GL_TEXTURE0 + i ) ;
glMatrixMode ( GL_TEXTURE ) ;
2009-05-05 15:27:24 -07:00
if ( ! isRTT & & mat . isIdentity ( ) )
2008-10-28 09:46:13 -07:00
glLoadIdentity ( ) ;
else
{
GLfloat glmat [ 16 ] ;
if ( isRTT )
createGLTextureMatrix ( glmat , mat * TextureFlipMatrix ) ;
else
createGLTextureMatrix ( glmat , mat ) ;
glLoadMatrixf ( glmat ) ;
}
break ;
}
default :
break ;
}
}
2008-11-12 15:04:00 -08:00
bool COGLES1Driver : : updateVertexHardwareBuffer ( SHWBufferLink_opengl * HWBuffer )
2008-10-28 09:46:13 -07:00
{
if ( ! HWBuffer )
return false ;
const scene : : IMeshBuffer * mb = HWBuffer - > MeshBuffer ;
const void * vertices = mb - > getVertices ( ) ;
const u32 vertexCount = mb - > getVertexCount ( ) ;
const E_VERTEX_TYPE vType = mb - > getVertexType ( ) ;
const u32 vertexSize = getVertexPitchFromType ( vType ) ;
//buffer vertex data, and convert colours...
core : : array < c8 > buffer ( vertexSize * vertexCount ) ;
memcpy ( buffer . pointer ( ) , vertices , vertexSize * vertexCount ) ;
// in order to convert the colors into opengl format (RGBA)
switch ( vType )
{
case EVT_STANDARD :
{
S3DVertex * pb = reinterpret_cast < S3DVertex * > ( buffer . pointer ( ) ) ;
const S3DVertex * po = static_cast < const S3DVertex * > ( vertices ) ;
for ( u32 i = 0 ; i < vertexCount ; i + + )
{
po [ i ] . Color . toOpenGLColor ( ( u8 * ) & ( pb [ i ] . Color . color ) ) ;
}
}
break ;
case EVT_2TCOORDS :
{
S3DVertex2TCoords * pb = reinterpret_cast < S3DVertex2TCoords * > ( buffer . pointer ( ) ) ;
const S3DVertex2TCoords * po = static_cast < const S3DVertex2TCoords * > ( vertices ) ;
for ( u32 i = 0 ; i < vertexCount ; i + + )
{
po [ i ] . Color . toOpenGLColor ( ( u8 * ) & ( pb [ i ] . Color . color ) ) ;
}
}
break ;
case EVT_TANGENTS :
{
S3DVertexTangents * pb = reinterpret_cast < S3DVertexTangents * > ( buffer . pointer ( ) ) ;
const S3DVertexTangents * po = static_cast < const S3DVertexTangents * > ( vertices ) ;
for ( u32 i = 0 ; i < vertexCount ; i + + )
{
po [ i ] . Color . toOpenGLColor ( ( u8 * ) & ( pb [ i ] . Color . color ) ) ;
}
}
break ;
default :
{
return false ;
}
}
//get or create buffer
bool newBuffer = false ;
if ( ! HWBuffer - > vbo_verticesID )
{
extGlGenBuffers ( 1 , & HWBuffer - > vbo_verticesID ) ;
if ( ! HWBuffer - > vbo_verticesID ) return false ;
newBuffer = true ;
}
else if ( HWBuffer - > vbo_verticesSize < vertexCount * vertexSize )
{
newBuffer = true ;
}
extGlBindBuffer ( GL_ARRAY_BUFFER , HWBuffer - > vbo_verticesID ) ;
2014-05-25 08:43:33 -07:00
// copy data to graphics card
2008-10-28 09:46:13 -07:00
if ( ! newBuffer )
extGlBufferSubData ( GL_ARRAY_BUFFER , 0 , vertexCount * vertexSize , buffer . const_pointer ( ) ) ;
else
{
HWBuffer - > vbo_verticesSize = vertexCount * vertexSize ;
if ( HWBuffer - > Mapped_Vertex = = scene : : EHM_STATIC )
extGlBufferData ( GL_ARRAY_BUFFER , vertexCount * vertexSize , buffer . const_pointer ( ) , GL_STATIC_DRAW ) ;
2008-11-12 15:04:00 -08:00
else
2008-10-28 09:46:13 -07:00
extGlBufferData ( GL_ARRAY_BUFFER , vertexCount * vertexSize , buffer . const_pointer ( ) , GL_DYNAMIC_DRAW ) ;
}
extGlBindBuffer ( GL_ARRAY_BUFFER , 0 ) ;
2014-05-25 08:43:33 -07:00
return ( ! testGLError ( ) ) ;
2008-10-28 09:46:13 -07:00
}
2008-11-12 15:04:00 -08:00
bool COGLES1Driver : : updateIndexHardwareBuffer ( SHWBufferLink_opengl * HWBuffer )
2008-10-28 09:46:13 -07:00
{
if ( ! HWBuffer )
return false ;
const scene : : IMeshBuffer * mb = HWBuffer - > MeshBuffer ;
const void * indices = mb - > getIndices ( ) ;
u32 indexCount = mb - > getIndexCount ( ) ;
GLenum indexSize ;
switch ( mb - > getIndexType ( ) )
{
case ( EIT_16BIT ) :
{
indexSize = sizeof ( u16 ) ;
break ;
}
case ( EIT_32BIT ) :
{
indexSize = sizeof ( u32 ) ;
break ;
}
default :
{
return false ;
}
}
//get or create buffer
bool newBuffer = false ;
if ( ! HWBuffer - > vbo_indicesID )
{
extGlGenBuffers ( 1 , & HWBuffer - > vbo_indicesID ) ;
if ( ! HWBuffer - > vbo_indicesID ) return false ;
newBuffer = true ;
}
else if ( HWBuffer - > vbo_indicesSize < indexCount * indexSize )
{
newBuffer = true ;
}
extGlBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , HWBuffer - > vbo_indicesID ) ;
2014-05-25 08:43:33 -07:00
// copy data to graphics card
2008-10-28 09:46:13 -07:00
if ( ! newBuffer )
extGlBufferSubData ( GL_ELEMENT_ARRAY_BUFFER , 0 , indexCount * indexSize , indices ) ;
else
{
HWBuffer - > vbo_indicesSize = indexCount * indexSize ;
if ( HWBuffer - > Mapped_Index = = scene : : EHM_STATIC )
extGlBufferData ( GL_ELEMENT_ARRAY_BUFFER , indexCount * indexSize , indices , GL_STATIC_DRAW ) ;
2008-11-12 15:04:00 -08:00
else
2008-10-28 09:46:13 -07:00
extGlBufferData ( GL_ELEMENT_ARRAY_BUFFER , indexCount * indexSize , indices , GL_DYNAMIC_DRAW ) ;
}
extGlBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , 0 ) ;
2014-05-25 08:43:33 -07:00
return ( ! testGLError ( ) ) ;
2008-10-28 09:46:13 -07:00
}
//! updates hardware buffer if needed
2008-11-12 15:04:00 -08:00
bool COGLES1Driver : : updateHardwareBuffer ( SHWBufferLink * HWBuffer )
2008-10-28 09:46:13 -07:00
{
if ( ! HWBuffer )
return false ;
if ( HWBuffer - > Mapped_Vertex ! = scene : : EHM_NEVER )
{
if ( HWBuffer - > ChangedID_Vertex ! = HWBuffer - > MeshBuffer - > getChangedID_Vertex ( )
| | ! ( ( SHWBufferLink_opengl * ) HWBuffer ) - > vbo_verticesID )
{
HWBuffer - > ChangedID_Vertex = HWBuffer - > MeshBuffer - > getChangedID_Vertex ( ) ;
if ( ! updateVertexHardwareBuffer ( ( SHWBufferLink_opengl * ) HWBuffer ) )
return false ;
}
}
if ( HWBuffer - > Mapped_Index ! = scene : : EHM_NEVER )
{
if ( HWBuffer - > ChangedID_Index ! = HWBuffer - > MeshBuffer - > getChangedID_Index ( )
| | ! ( ( SHWBufferLink_opengl * ) HWBuffer ) - > vbo_indicesID )
{
HWBuffer - > ChangedID_Index = HWBuffer - > MeshBuffer - > getChangedID_Index ( ) ;
if ( ! updateIndexHardwareBuffer ( ( SHWBufferLink_opengl * ) HWBuffer ) )
return false ;
}
}
return true ;
}
//! Create hardware buffer from meshbuffer
2008-11-12 15:04:00 -08:00
COGLES1Driver : : SHWBufferLink * COGLES1Driver : : createHardwareBuffer ( const scene : : IMeshBuffer * mb )
2008-10-28 09:46:13 -07:00
{
if ( ! mb | | ( mb - > getHardwareMappingHint_Index ( ) = = scene : : EHM_NEVER & & mb - > getHardwareMappingHint_Vertex ( ) = = scene : : EHM_NEVER ) )
return 0 ;
SHWBufferLink_opengl * HWBuffer = new SHWBufferLink_opengl ( mb ) ;
//add to map
HWBufferMap . insert ( HWBuffer - > MeshBuffer , HWBuffer ) ;
HWBuffer - > ChangedID_Vertex = HWBuffer - > MeshBuffer - > getChangedID_Vertex ( ) ;
HWBuffer - > ChangedID_Index = HWBuffer - > MeshBuffer - > getChangedID_Index ( ) ;
HWBuffer - > Mapped_Vertex = mb - > getHardwareMappingHint_Vertex ( ) ;
HWBuffer - > Mapped_Index = mb - > getHardwareMappingHint_Index ( ) ;
HWBuffer - > LastUsed = 0 ;
HWBuffer - > vbo_verticesID = 0 ;
HWBuffer - > vbo_indicesID = 0 ;
HWBuffer - > vbo_verticesSize = 0 ;
HWBuffer - > vbo_indicesSize = 0 ;
if ( ! updateHardwareBuffer ( HWBuffer ) )
{
deleteHardwareBuffer ( HWBuffer ) ;
return 0 ;
}
return HWBuffer ;
}
2008-11-12 15:04:00 -08:00
void COGLES1Driver : : deleteHardwareBuffer ( SHWBufferLink * _HWBuffer )
2008-10-28 09:46:13 -07:00
{
2014-05-08 09:23:12 -07:00
if ( ! _HWBuffer )
2008-11-12 15:04:00 -08:00
return ;
2008-10-28 09:46:13 -07:00
SHWBufferLink_opengl * HWBuffer = ( SHWBufferLink_opengl * ) _HWBuffer ;
if ( HWBuffer - > vbo_verticesID )
{
extGlDeleteBuffers ( 1 , & HWBuffer - > vbo_verticesID ) ;
HWBuffer - > vbo_verticesID = 0 ;
}
if ( HWBuffer - > vbo_indicesID )
{
extGlDeleteBuffers ( 1 , & HWBuffer - > vbo_indicesID ) ;
HWBuffer - > vbo_indicesID = 0 ;
}
CNullDriver : : deleteHardwareBuffer ( _HWBuffer ) ;
}
//! Draw hardware buffer
2008-11-12 15:04:00 -08:00
void COGLES1Driver : : drawHardwareBuffer ( SHWBufferLink * _HWBuffer )
2008-10-28 09:46:13 -07:00
{
if ( ! _HWBuffer )
return ;
SHWBufferLink_opengl * HWBuffer = ( SHWBufferLink_opengl * ) _HWBuffer ;
updateHardwareBuffer ( HWBuffer ) ; //check if update is needed
HWBuffer - > LastUsed = 0 ; //reset count
const scene : : IMeshBuffer * mb = HWBuffer - > MeshBuffer ;
const void * vertices = mb - > getVertices ( ) ;
const void * indexList = mb - > getIndices ( ) ;
if ( HWBuffer - > Mapped_Vertex ! = scene : : EHM_NEVER )
{
extGlBindBuffer ( GL_ARRAY_BUFFER , HWBuffer - > vbo_verticesID ) ;
vertices = 0 ;
}
if ( HWBuffer - > Mapped_Index ! = scene : : EHM_NEVER )
{
extGlBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , HWBuffer - > vbo_indicesID ) ;
indexList = 0 ;
}
2008-11-12 15:04:00 -08:00
drawVertexPrimitiveList ( vertices , mb - > getVertexCount ( ) , indexList ,
mb - > getIndexCount ( ) / 3 , mb - > getVertexType ( ) ,
scene : : EPT_TRIANGLES , mb - > getIndexType ( ) ) ;
2008-10-28 09:46:13 -07:00
if ( HWBuffer - > Mapped_Vertex ! = scene : : EHM_NEVER )
extGlBindBuffer ( GL_ARRAY_BUFFER , 0 ) ;
if ( HWBuffer - > Mapped_Index ! = scene : : EHM_NEVER )
extGlBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , 0 ) ;
}
// small helper function to create vertex buffer object adress offsets
static inline u8 * buffer_offset ( const long offset )
{
return ( ( u8 * ) 0 + offset ) ;
}
//! draws a vertex primitive list
2008-11-12 15:04:00 -08:00
void COGLES1Driver : : drawVertexPrimitiveList ( const void * vertices , u32 vertexCount ,
2008-10-28 09:46:13 -07:00
const void * indexList , u32 primitiveCount ,
E_VERTEX_TYPE vType , scene : : E_PRIMITIVE_TYPE pType , E_INDEX_TYPE iType )
{
if ( ! checkPrimitiveCount ( primitiveCount ) )
return ;
setRenderStates3DMode ( ) ;
2009-05-07 10:05:05 -07:00
drawVertexPrimitiveList2d3d ( vertices , vertexCount , ( const u16 * ) indexList , primitiveCount , vType , pType , iType ) ;
2008-10-28 09:46:13 -07:00
}
2008-11-12 15:04:00 -08:00
void COGLES1Driver : : drawVertexPrimitiveList2d3d ( const void * vertices , u32 vertexCount ,
2008-10-28 09:46:13 -07:00
const void * indexList , u32 primitiveCount ,
E_VERTEX_TYPE vType , scene : : E_PRIMITIVE_TYPE pType , E_INDEX_TYPE iType , bool threed )
{
if ( ! primitiveCount | | ! vertexCount )
return ;
if ( ! threed & & ! checkPrimitiveCount ( primitiveCount ) )
return ;
CNullDriver : : drawVertexPrimitiveList ( vertices , vertexCount , indexList , primitiveCount , vType , pType , iType ) ;
if ( vertices )
{
// convert colors to gl color format.
vertexCount * = 4 ; //reused as color component count
ColorBuffer . set_used ( vertexCount ) ;
u32 i ;
switch ( vType )
{
case EVT_STANDARD :
{
const S3DVertex * p = static_cast < const S3DVertex * > ( vertices ) ;
for ( i = 0 ; i < vertexCount ; i + = 4 )
{
p - > Color . toOpenGLColor ( & ColorBuffer [ i ] ) ;
+ + p ;
}
}
break ;
case EVT_2TCOORDS :
{
const S3DVertex2TCoords * p = static_cast < const S3DVertex2TCoords * > ( vertices ) ;
for ( i = 0 ; i < vertexCount ; i + = 4 )
{
p - > Color . toOpenGLColor ( & ColorBuffer [ i ] ) ;
+ + p ;
}
}
break ;
case EVT_TANGENTS :
{
const S3DVertexTangents * p = static_cast < const S3DVertexTangents * > ( vertices ) ;
for ( i = 0 ; i < vertexCount ; i + = 4 )
{
p - > Color . toOpenGLColor ( & ColorBuffer [ i ] ) ;
+ + p ;
}
}
break ;
}
}
// draw everything
if ( MultiTextureExtension )
extGlClientActiveTexture ( GL_TEXTURE0 ) ;
glEnableClientState ( GL_COLOR_ARRAY ) ;
glEnableClientState ( GL_VERTEX_ARRAY ) ;
if ( ( pType ! = scene : : EPT_POINTS ) & & ( pType ! = scene : : EPT_POINT_SPRITES ) )
glEnableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
2009-05-11 02:28:22 -07:00
# ifdef GL_OES_point_size_array
else if ( FeatureAvailable [ IRR_OES_point_size_array ] & & ( Material . Thickness = = 0.0f ) )
glEnableClientState ( GL_POINT_SIZE_ARRAY_OES ) ;
# endif
2008-10-28 09:46:13 -07:00
if ( threed & & ( pType ! = scene : : EPT_POINTS ) & & ( pType ! = scene : : EPT_POINT_SPRITES ) )
glEnableClientState ( GL_NORMAL_ARRAY ) ;
if ( vertices )
glColorPointer ( 4 , GL_UNSIGNED_BYTE , 0 , & ColorBuffer [ 0 ] ) ;
switch ( vType )
{
case EVT_STANDARD :
if ( vertices )
{
2009-05-11 02:28:22 -07:00
# ifdef GL_OES_point_size_array
if ( ( pType = = scene : : EPT_POINTS ) | | ( pType = = scene : : EPT_POINT_SPRITES ) )
{
if ( FeatureAvailable [ IRR_OES_point_size_array ] & & ( Material . Thickness = = 0.0f ) )
glPointSizePointerOES ( GL_FLOAT , sizeof ( S3DVertex ) , & ( static_cast < const S3DVertex * > ( vertices ) ) [ 0 ] . Normal . X ) ;
}
else
# endif
2008-10-28 09:46:13 -07:00
if ( threed )
glNormalPointer ( GL_FLOAT , sizeof ( S3DVertex ) , & ( static_cast < const S3DVertex * > ( vertices ) ) [ 0 ] . Normal ) ;
glTexCoordPointer ( 2 , GL_FLOAT , sizeof ( S3DVertex ) , & ( static_cast < const S3DVertex * > ( vertices ) ) [ 0 ] . TCoords ) ;
glVertexPointer ( ( threed ? 3 : 2 ) , GL_FLOAT , sizeof ( S3DVertex ) , & ( static_cast < const S3DVertex * > ( vertices ) ) [ 0 ] . Pos ) ;
}
else
{
glNormalPointer ( GL_FLOAT , sizeof ( S3DVertex ) , buffer_offset ( 12 ) ) ;
glColorPointer ( 4 , GL_UNSIGNED_BYTE , sizeof ( S3DVertex ) , buffer_offset ( 24 ) ) ;
glTexCoordPointer ( 2 , GL_FLOAT , sizeof ( S3DVertex ) , buffer_offset ( 28 ) ) ;
glVertexPointer ( 3 , GL_FLOAT , sizeof ( S3DVertex ) , 0 ) ;
}
if ( MultiTextureExtension & & CurrentTexture [ 1 ] )
{
extGlClientActiveTexture ( GL_TEXTURE1 ) ;
glEnableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
if ( vertices )
glTexCoordPointer ( 2 , GL_FLOAT , sizeof ( S3DVertex ) , & ( static_cast < const S3DVertex * > ( vertices ) ) [ 0 ] . TCoords ) ;
else
glTexCoordPointer ( 2 , GL_FLOAT , sizeof ( S3DVertex ) , buffer_offset ( 28 ) ) ;
}
break ;
case EVT_2TCOORDS :
if ( vertices )
{
if ( threed )
glNormalPointer ( GL_FLOAT , sizeof ( S3DVertex2TCoords ) , & ( static_cast < const S3DVertex2TCoords * > ( vertices ) ) [ 0 ] . Normal ) ;
glTexCoordPointer ( 2 , GL_FLOAT , sizeof ( S3DVertex2TCoords ) , & ( static_cast < const S3DVertex2TCoords * > ( vertices ) ) [ 0 ] . TCoords ) ;
glVertexPointer ( ( threed ? 3 : 2 ) , GL_FLOAT , sizeof ( S3DVertex2TCoords ) , & ( static_cast < const S3DVertex2TCoords * > ( vertices ) ) [ 0 ] . Pos ) ;
}
else
{
glNormalPointer ( GL_FLOAT , sizeof ( S3DVertex2TCoords ) , buffer_offset ( 12 ) ) ;
glColorPointer ( 4 , GL_UNSIGNED_BYTE , sizeof ( S3DVertex2TCoords ) , buffer_offset ( 24 ) ) ;
glTexCoordPointer ( 2 , GL_FLOAT , sizeof ( S3DVertex2TCoords ) , buffer_offset ( 28 ) ) ;
glVertexPointer ( 3 , GL_FLOAT , sizeof ( S3DVertex2TCoords ) , buffer_offset ( 0 ) ) ;
}
if ( MultiTextureExtension )
{
extGlClientActiveTexture ( GL_TEXTURE1 ) ;
glEnableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
if ( vertices )
glTexCoordPointer ( 2 , GL_FLOAT , sizeof ( S3DVertex2TCoords ) , & ( static_cast < const S3DVertex2TCoords * > ( vertices ) ) [ 0 ] . TCoords2 ) ;
else
glTexCoordPointer ( 2 , GL_FLOAT , sizeof ( S3DVertex2TCoords ) , buffer_offset ( 36 ) ) ;
}
break ;
case EVT_TANGENTS :
if ( vertices )
{
if ( threed )
glNormalPointer ( GL_FLOAT , sizeof ( S3DVertexTangents ) , & ( static_cast < const S3DVertexTangents * > ( vertices ) ) [ 0 ] . Normal ) ;
glTexCoordPointer ( 2 , GL_FLOAT , sizeof ( S3DVertexTangents ) , & ( static_cast < const S3DVertexTangents * > ( vertices ) ) [ 0 ] . TCoords ) ;
glVertexPointer ( ( threed ? 3 : 2 ) , GL_FLOAT , sizeof ( S3DVertexTangents ) , & ( static_cast < const S3DVertexTangents * > ( vertices ) ) [ 0 ] . Pos ) ;
}
else
{
glNormalPointer ( GL_FLOAT , sizeof ( S3DVertexTangents ) , buffer_offset ( 12 ) ) ;
glColorPointer ( 4 , GL_UNSIGNED_BYTE , sizeof ( S3DVertexTangents ) , buffer_offset ( 24 ) ) ;
glTexCoordPointer ( 2 , GL_FLOAT , sizeof ( S3DVertexTangents ) , buffer_offset ( 28 ) ) ;
glVertexPointer ( 3 , GL_FLOAT , sizeof ( S3DVertexTangents ) , buffer_offset ( 0 ) ) ;
}
if ( MultiTextureExtension )
{
extGlClientActiveTexture ( GL_TEXTURE1 ) ;
glEnableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
if ( vertices )
glTexCoordPointer ( 3 , GL_FLOAT , sizeof ( S3DVertexTangents ) , & ( static_cast < const S3DVertexTangents * > ( vertices ) ) [ 0 ] . Tangent ) ;
else
glTexCoordPointer ( 3 , GL_FLOAT , sizeof ( S3DVertexTangents ) , buffer_offset ( 36 ) ) ;
extGlClientActiveTexture ( GL_TEXTURE2 ) ;
glEnableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
if ( vertices )
glTexCoordPointer ( 3 , GL_FLOAT , sizeof ( S3DVertexTangents ) , & ( static_cast < const S3DVertexTangents * > ( vertices ) ) [ 0 ] . Binormal ) ;
else
glTexCoordPointer ( 3 , GL_FLOAT , sizeof ( S3DVertexTangents ) , buffer_offset ( 48 ) ) ;
}
break ;
}
GLenum indexSize = 0 ;
switch ( iType )
{
case ( EIT_16BIT ) :
{
indexSize = GL_UNSIGNED_SHORT ;
break ;
}
case ( EIT_32BIT ) :
{
2009-05-10 16:25:22 -07:00
# ifdef GL_OES_element_index_uint
2009-05-10 16:27:42 -07:00
# ifndef GL_UNSIGNED_INT
# define GL_UNSIGNED_INT 0x1405
# endif
2009-05-10 16:25:22 -07:00
if ( FeatureAvailable [ IRR_OES_element_index_uint ] )
indexSize = GL_UNSIGNED_INT ;
else
# endif
2008-11-12 15:04:00 -08:00
indexSize = GL_UNSIGNED_SHORT ;
2008-10-28 09:46:13 -07:00
break ;
}
}
switch ( pType )
{
case scene : : EPT_POINTS :
case scene : : EPT_POINT_SPRITES :
{
2008-11-27 08:02:09 -08:00
# ifdef GL_OES_point_sprite
if ( pType = = scene : : EPT_POINT_SPRITES & & FeatureAvailable [ IRR_OES_point_sprite ] )
glEnable ( GL_POINT_SPRITE_OES ) ;
2008-10-28 09:46:13 -07:00
# endif
2009-05-11 05:16:18 -07:00
// if ==0 we use the point size array
if ( Material . Thickness ! = 0.f )
{
float quadratic [ ] = { 0.0f , 0.0f , 10.01f } ;
extGlPointParameterfv ( GL_POINT_DISTANCE_ATTENUATION , quadratic ) ;
float maxParticleSize = 1.0f ;
glGetFloatv ( GL_POINT_SIZE_MAX , & maxParticleSize ) ;
// maxParticleSize=maxParticleSize<Material.Thickness?maxParticleSize:Material.Thickness;
// extGlPointParameterf(GL_POINT_SIZE_MAX,maxParticleSize);
// extGlPointParameterf(GL_POINT_SIZE_MIN,Material.Thickness);
extGlPointParameterf ( GL_POINT_FADE_THRESHOLD_SIZE , 60.0f ) ;
glPointSize ( Material . Thickness ) ;
}
2008-11-27 08:02:09 -08:00
# ifdef GL_OES_point_sprite
if ( pType = = scene : : EPT_POINT_SPRITES & & FeatureAvailable [ IRR_OES_point_sprite ] )
glTexEnvf ( GL_POINT_SPRITE_OES , GL_COORD_REPLACE_OES , GL_TRUE ) ;
2008-10-28 09:46:13 -07:00
# endif
glDrawArrays ( GL_POINTS , 0 , primitiveCount ) ;
2008-11-28 00:57:59 -08:00
# ifdef GL_OES_point_sprite
2008-11-27 08:02:09 -08:00
if ( pType = = scene : : EPT_POINT_SPRITES & & FeatureAvailable [ IRR_OES_point_sprite ] )
2008-10-28 09:46:13 -07:00
{
2008-11-27 08:02:09 -08:00
glDisable ( GL_POINT_SPRITE_OES ) ;
glTexEnvf ( GL_POINT_SPRITE_OES , GL_COORD_REPLACE_OES , GL_FALSE ) ;
2008-10-28 09:46:13 -07:00
}
# endif
}
break ;
case scene : : EPT_LINE_STRIP :
glDrawElements ( GL_LINE_STRIP , primitiveCount + 1 , indexSize , indexList ) ;
break ;
case scene : : EPT_LINE_LOOP :
glDrawElements ( GL_LINE_LOOP , primitiveCount , indexSize , indexList ) ;
break ;
case scene : : EPT_LINES :
glDrawElements ( GL_LINES , primitiveCount * 2 , indexSize , indexList ) ;
break ;
case scene : : EPT_TRIANGLE_STRIP :
glDrawElements ( GL_TRIANGLE_STRIP , primitiveCount + 2 , indexSize , indexList ) ;
break ;
case scene : : EPT_TRIANGLE_FAN :
glDrawElements ( GL_TRIANGLE_FAN , primitiveCount + 2 , indexSize , indexList ) ;
break ;
case scene : : EPT_TRIANGLES :
2009-05-08 14:47:06 -07:00
glDrawElements ( ( LastMaterial . Wireframe ) ? GL_LINES : ( LastMaterial . PointCloud ) ? GL_POINTS : GL_TRIANGLES , primitiveCount * 3 , indexSize , indexList ) ;
2008-10-28 09:46:13 -07:00
break ;
case scene : : EPT_QUAD_STRIP :
2008-11-12 15:04:00 -08:00
// TODO ogl-es
2008-10-28 09:46:13 -07:00
// glDrawElements(GL_QUAD_STRIP, primitiveCount*2+2, indexSize, indexList);
break ;
case scene : : EPT_QUADS :
2008-11-12 15:04:00 -08:00
// TODO ogl-es
2008-10-28 09:46:13 -07:00
// glDrawElements(GL_QUADS, primitiveCount*4, indexSize, indexList);
break ;
case scene : : EPT_POLYGON :
2008-11-12 15:04:00 -08:00
// TODO ogl-es
2008-10-28 09:46:13 -07:00
// glDrawElements(GL_POLYGON, primitiveCount, indexSize, indexList);
break ;
}
if ( MultiTextureExtension )
{
if ( vType = = EVT_TANGENTS )
{
extGlClientActiveTexture ( GL_TEXTURE2 ) ;
glDisableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
}
if ( ( vType ! = EVT_STANDARD ) | | CurrentTexture [ 1 ] )
{
extGlClientActiveTexture ( GL_TEXTURE1 ) ;
glDisableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
}
extGlClientActiveTexture ( GL_TEXTURE0 ) ;
}
2009-05-11 02:28:22 -07:00
# ifdef GL_OES_point_size_array
if ( FeatureAvailable [ IRR_OES_point_size_array ] & & ( Material . Thickness = = 0.0f ) )
glDisableClientState ( GL_POINT_SIZE_ARRAY_OES ) ;
# endif
2008-10-28 09:46:13 -07:00
glDisableClientState ( GL_COLOR_ARRAY ) ;
glDisableClientState ( GL_VERTEX_ARRAY ) ;
glDisableClientState ( GL_NORMAL_ARRAY ) ;
glDisableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
}
2008-11-12 15:04:00 -08:00
//! draws a 2d image, using a color and the alpha channel of the texture
void COGLES1Driver : : draw2DImage ( const video : : ITexture * texture ,
2008-10-28 09:46:13 -07:00
const core : : position2d < s32 > & pos ,
const core : : rect < s32 > & sourceRect ,
const core : : rect < s32 > * clipRect , SColor color ,
bool useAlphaChannelOfTexture )
{
if ( ! texture )
return ;
if ( ! sourceRect . isValid ( ) )
return ;
2008-12-28 06:35:16 -08:00
# if defined(GL_OES_draw_texture)
// currently disabled due to problems with the emulator.
if ( false & & FeatureAvailable [ IRR_OES_draw_texture ] )
{
disableTextures ( 1 ) ;
2011-06-03 04:32:53 -07:00
if ( ! setActiveTexture ( 0 , texture ) )
2008-12-28 06:35:16 -08:00
return ;
setRenderStates2DMode ( color . getAlpha ( ) < 255 , true , useAlphaChannelOfTexture ) ;
2014-02-13 13:09:38 -08:00
const GLint crop [ ] = { sourceRect . UpperLeftCorner . X , static_cast < GLint > ( getCurrentRenderTargetSize ( ) . Height - sourceRect . LowerRightCorner . Y ) , sourceRect . getWidth ( ) , sourceRect . getHeight ( ) } ;
2009-01-02 03:11:50 -08:00
glTexParameteriv ( GL_TEXTURE_2D , GL_TEXTURE_CROP_RECT_OES , crop ) ;
2012-07-19 04:31:32 -07:00
const bool isRTT = true ; //texture->isRenderTarget();
if ( ! isRTT )
{
glMatrixMode ( GL_TEXTURE ) ;
GLfloat glmat [ 16 ] ;
createGLTextureMatrix ( glmat , TextureFlipMatrix ) ;
glLoadMatrixf ( glmat ) ;
}
core : : rect < s32 > destRect ( pos , sourceRect . getSize ( ) ) ;
2008-12-28 06:35:16 -08:00
if ( clipRect )
destRect . clipAgainst ( * clipRect ) ;
2012-07-19 04:31:32 -07:00
extGlDrawTex ( destRect . UpperLeftCorner . X , getCurrentRenderTargetSize ( ) . Height - destRect . UpperLeftCorner . Y , 0 , destRect . getWidth ( ) , destRect . getHeight ( ) ) ;
2008-12-28 06:35:16 -08:00
return ;
}
# endif
2008-10-28 09:46:13 -07:00
core : : position2d < s32 > targetPos ( pos ) ;
core : : position2d < s32 > sourcePos ( sourceRect . UpperLeftCorner ) ;
core : : dimension2d < s32 > sourceSize ( sourceRect . getSize ( ) ) ;
if ( clipRect )
{
if ( targetPos . X < clipRect - > UpperLeftCorner . X )
{
sourceSize . Width + = targetPos . X - clipRect - > UpperLeftCorner . X ;
if ( sourceSize . Width < = 0 )
return ;
sourcePos . X - = targetPos . X - clipRect - > UpperLeftCorner . X ;
targetPos . X = clipRect - > UpperLeftCorner . X ;
}
if ( targetPos . X + sourceSize . Width > clipRect - > LowerRightCorner . X )
{
sourceSize . Width - = ( targetPos . X + sourceSize . Width ) - clipRect - > LowerRightCorner . X ;
if ( sourceSize . Width < = 0 )
return ;
}
if ( targetPos . Y < clipRect - > UpperLeftCorner . Y )
{
sourceSize . Height + = targetPos . Y - clipRect - > UpperLeftCorner . Y ;
if ( sourceSize . Height < = 0 )
return ;
sourcePos . Y - = targetPos . Y - clipRect - > UpperLeftCorner . Y ;
targetPos . Y = clipRect - > UpperLeftCorner . Y ;
}
if ( targetPos . Y + sourceSize . Height > clipRect - > LowerRightCorner . Y )
{
sourceSize . Height - = ( targetPos . Y + sourceSize . Height ) - clipRect - > LowerRightCorner . Y ;
if ( sourceSize . Height < = 0 )
return ;
}
}
// clip these coordinates
if ( targetPos . X < 0 )
{
sourceSize . Width + = targetPos . X ;
if ( sourceSize . Width < = 0 )
return ;
sourcePos . X - = targetPos . X ;
targetPos . X = 0 ;
}
2009-01-27 05:45:17 -08:00
const core : : dimension2d < u32 > & renderTargetSize = getCurrentRenderTargetSize ( ) ;
2008-10-28 09:46:13 -07:00
2009-01-27 05:45:17 -08:00
if ( targetPos . X + sourceSize . Width > ( s32 ) renderTargetSize . Width )
2008-10-28 09:46:13 -07:00
{
sourceSize . Width - = ( targetPos . X + sourceSize . Width ) - renderTargetSize . Width ;
if ( sourceSize . Width < = 0 )
return ;
}
if ( targetPos . Y < 0 )
{
sourceSize . Height + = targetPos . Y ;
if ( sourceSize . Height < = 0 )
return ;
sourcePos . Y - = targetPos . Y ;
targetPos . Y = 0 ;
}
2009-01-27 05:45:17 -08:00
if ( targetPos . Y + sourceSize . Height > ( s32 ) renderTargetSize . Height )
2008-10-28 09:46:13 -07:00
{
sourceSize . Height - = ( targetPos . Y + sourceSize . Height ) - renderTargetSize . Height ;
if ( sourceSize . Height < = 0 )
return ;
}
// ok, we've clipped everything.
// now draw it.
// texcoords need to be flipped horizontally for RTTs
const bool isRTT = texture - > isRenderTarget ( ) ;
2009-01-27 05:45:17 -08:00
const core : : dimension2d < u32 > & ss = texture - > getOriginalSize ( ) ;
2008-10-28 09:46:13 -07:00
const f32 invW = 1.f / static_cast < f32 > ( ss . Width ) ;
const f32 invH = 1.f / static_cast < f32 > ( ss . Height ) ;
const core : : rect < f32 > tcoords (
sourcePos . X * invW ,
( isRTT ? ( sourcePos . Y + sourceSize . Height ) : sourcePos . Y ) * invH ,
( sourcePos . X + sourceSize . Width ) * invW ,
( isRTT ? sourcePos . Y : ( sourcePos . Y + sourceSize . Height ) ) * invH ) ;
const core : : rect < s32 > poss ( targetPos , sourceSize ) ;
disableTextures ( 1 ) ;
2011-06-03 04:32:53 -07:00
if ( ! setActiveTexture ( 0 , texture ) )
2008-10-28 09:46:13 -07:00
return ;
setRenderStates2DMode ( color . getAlpha ( ) < 255 , true , useAlphaChannelOfTexture ) ;
u16 indices [ ] = { 0 , 1 , 2 , 3 } ;
S3DVertex vertices [ 4 ] ;
2008-11-12 15:04:00 -08:00
vertices [ 0 ] = S3DVertex ( ( f32 ) poss . UpperLeftCorner . X , ( f32 ) poss . UpperLeftCorner . Y , 0 , 0 , 0 , 1 , color , tcoords . UpperLeftCorner . X , tcoords . UpperLeftCorner . Y ) ;
vertices [ 1 ] = S3DVertex ( ( f32 ) poss . LowerRightCorner . X , ( f32 ) poss . UpperLeftCorner . Y , 0 , 0 , 0 , 1 , color , tcoords . LowerRightCorner . X , tcoords . UpperLeftCorner . Y ) ;
vertices [ 2 ] = S3DVertex ( ( f32 ) poss . LowerRightCorner . X , ( f32 ) poss . LowerRightCorner . Y , 0 , 0 , 0 , 1 , color , tcoords . LowerRightCorner . X , tcoords . LowerRightCorner . Y ) ;
vertices [ 3 ] = S3DVertex ( ( f32 ) poss . UpperLeftCorner . X , ( f32 ) poss . LowerRightCorner . Y , 0 , 0 , 0 , 1 , color , tcoords . UpperLeftCorner . X , tcoords . LowerRightCorner . Y ) ;
drawVertexPrimitiveList2d3d ( vertices , 4 , indices , 2 , video : : EVT_STANDARD , scene : : EPT_TRIANGLE_FAN , EIT_16BIT , false ) ;
2008-10-28 09:46:13 -07:00
}
//! The same, but with a four element array of colors, one for each vertex
2008-11-12 15:04:00 -08:00
void COGLES1Driver : : draw2DImage ( const video : : ITexture * texture , const core : : rect < s32 > & destRect ,
2008-10-28 09:46:13 -07:00
const core : : rect < s32 > & sourceRect , const core : : rect < s32 > * clipRect ,
const video : : SColor * const colors , bool useAlphaChannelOfTexture )
{
if ( ! texture )
return ;
// texcoords need to be flipped horizontally for RTTs
const bool isRTT = texture - > isRenderTarget ( ) ;
2009-01-27 05:45:17 -08:00
const core : : dimension2du & ss = texture - > getOriginalSize ( ) ;
2008-10-28 09:46:13 -07:00
const f32 invW = 1.f / static_cast < f32 > ( ss . Width ) ;
const f32 invH = 1.f / static_cast < f32 > ( ss . Height ) ;
const core : : rect < f32 > tcoords (
sourceRect . UpperLeftCorner . X * invW ,
( isRTT ? sourceRect . LowerRightCorner . Y : sourceRect . UpperLeftCorner . Y ) * invH ,
sourceRect . LowerRightCorner . X * invW ,
( isRTT ? sourceRect . UpperLeftCorner . Y : sourceRect . LowerRightCorner . Y ) * invH ) ;
const video : : SColor temp [ 4 ] =
{
0xFFFFFFFF ,
0xFFFFFFFF ,
0xFFFFFFFF ,
0xFFFFFFFF
} ;
const video : : SColor * const useColor = colors ? colors : temp ;
disableTextures ( 1 ) ;
2011-06-03 04:32:53 -07:00
setActiveTexture ( 0 , texture ) ;
2008-10-28 09:46:13 -07:00
setRenderStates2DMode ( useColor [ 0 ] . getAlpha ( ) < 255 | | useColor [ 1 ] . getAlpha ( ) < 255 | |
useColor [ 2 ] . getAlpha ( ) < 255 | | useColor [ 3 ] . getAlpha ( ) < 255 ,
true , useAlphaChannelOfTexture ) ;
if ( clipRect )
{
if ( ! clipRect - > isValid ( ) )
return ;
glEnable ( GL_SCISSOR_TEST ) ;
2009-01-27 05:45:17 -08:00
const core : : dimension2d < u32 > & renderTargetSize = getCurrentRenderTargetSize ( ) ;
2008-10-28 09:46:13 -07:00
glScissor ( clipRect - > UpperLeftCorner . X , renderTargetSize . Height - clipRect - > LowerRightCorner . Y ,
clipRect - > getWidth ( ) , clipRect - > getHeight ( ) ) ;
}
u16 indices [ ] = { 0 , 1 , 2 , 3 } ;
S3DVertex vertices [ 4 ] ;
2008-11-12 15:04:00 -08:00
vertices [ 0 ] = S3DVertex ( ( f32 ) destRect . UpperLeftCorner . X , ( f32 ) destRect . UpperLeftCorner . Y , 0 , 0 , 0 , 1 , useColor [ 0 ] , tcoords . UpperLeftCorner . X , tcoords . UpperLeftCorner . Y ) ;
vertices [ 1 ] = S3DVertex ( ( f32 ) destRect . LowerRightCorner . X , ( f32 ) destRect . UpperLeftCorner . Y , 0 , 0 , 0 , 1 , useColor [ 3 ] , tcoords . LowerRightCorner . X , tcoords . UpperLeftCorner . Y ) ;
vertices [ 2 ] = S3DVertex ( ( f32 ) destRect . LowerRightCorner . X , ( f32 ) destRect . LowerRightCorner . Y , 0 , 0 , 0 , 1 , useColor [ 2 ] , tcoords . LowerRightCorner . X , tcoords . LowerRightCorner . Y ) ;
vertices [ 3 ] = S3DVertex ( ( f32 ) destRect . UpperLeftCorner . X , ( f32 ) destRect . LowerRightCorner . Y , 0 , 0 , 0 , 1 , useColor [ 1 ] , tcoords . UpperLeftCorner . X , tcoords . LowerRightCorner . Y ) ;
drawVertexPrimitiveList2d3d ( vertices , 4 , indices , 2 , video : : EVT_STANDARD , scene : : EPT_TRIANGLE_FAN , EIT_16BIT , false ) ;
2008-10-28 09:46:13 -07:00
if ( clipRect )
glDisable ( GL_SCISSOR_TEST ) ;
}
2008-11-12 15:04:00 -08:00
//! draws a set of 2d images, using a color and the alpha channel
void COGLES1Driver : : draw2DImage ( const video : : ITexture * texture ,
2008-10-28 09:46:13 -07:00
const core : : position2d < s32 > & pos ,
const core : : array < core : : rect < s32 > > & sourceRects ,
const core : : array < s32 > & indices ,
const core : : rect < s32 > * clipRect , SColor color ,
bool useAlphaChannelOfTexture )
{
if ( ! texture )
return ;
disableTextures ( 1 ) ;
2011-06-03 04:32:53 -07:00
if ( ! setActiveTexture ( 0 , texture ) )
2008-10-28 09:46:13 -07:00
return ;
setRenderStates2DMode ( color . getAlpha ( ) < 255 , true , useAlphaChannelOfTexture ) ;
if ( clipRect )
{
if ( ! clipRect - > isValid ( ) )
return ;
glEnable ( GL_SCISSOR_TEST ) ;
2009-01-27 05:45:17 -08:00
const core : : dimension2d < u32 > & renderTargetSize = getCurrentRenderTargetSize ( ) ;
2008-10-28 09:46:13 -07:00
glScissor ( clipRect - > UpperLeftCorner . X , renderTargetSize . Height - clipRect - > LowerRightCorner . Y ,
clipRect - > getWidth ( ) , clipRect - > getHeight ( ) ) ;
}
2009-01-27 05:45:17 -08:00
const core : : dimension2du & ss = texture - > getOriginalSize ( ) ;
2008-10-28 09:46:13 -07:00
core : : position2d < s32 > targetPos ( pos ) ;
// texcoords need to be flipped horizontally for RTTs
const bool isRTT = texture - > isRenderTarget ( ) ;
const f32 invW = 1.f / static_cast < f32 > ( ss . Width ) ;
const f32 invH = 1.f / static_cast < f32 > ( ss . Height ) ;
core : : array < S3DVertex > vertices ;
core : : array < u16 > quadIndices ;
vertices . reallocate ( indices . size ( ) * 4 ) ;
2011-05-22 13:25:05 -07:00
quadIndices . reallocate ( indices . size ( ) * 6 ) ;
2008-10-28 09:46:13 -07:00
for ( u32 i = 0 ; i < indices . size ( ) ; + + i )
{
const s32 currentIndex = indices [ i ] ;
if ( ! sourceRects [ currentIndex ] . isValid ( ) )
break ;
const core : : rect < f32 > tcoords (
sourceRects [ currentIndex ] . UpperLeftCorner . X * invW ,
( isRTT ? sourceRects [ currentIndex ] . LowerRightCorner . Y : sourceRects [ currentIndex ] . UpperLeftCorner . Y ) * invH ,
sourceRects [ currentIndex ] . LowerRightCorner . X * invW ,
( isRTT ? sourceRects [ currentIndex ] . UpperLeftCorner . Y : sourceRects [ currentIndex ] . LowerRightCorner . Y ) * invH ) ;
const core : : rect < s32 > poss ( targetPos , sourceRects [ currentIndex ] . getSize ( ) ) ;
2011-05-22 13:25:05 -07:00
const u32 vstart = vertices . size ( ) ;
2008-11-12 15:04:00 -08:00
vertices . push_back ( S3DVertex ( ( f32 ) poss . UpperLeftCorner . X , ( f32 ) poss . UpperLeftCorner . Y , 0 , 0 , 0 , 1 , color , tcoords . UpperLeftCorner . X , tcoords . UpperLeftCorner . Y ) ) ;
vertices . push_back ( S3DVertex ( ( f32 ) poss . LowerRightCorner . X , ( f32 ) poss . UpperLeftCorner . Y , 0 , 0 , 0 , 1 , color , tcoords . LowerRightCorner . X , tcoords . UpperLeftCorner . Y ) ) ;
vertices . push_back ( S3DVertex ( ( f32 ) poss . LowerRightCorner . X , ( f32 ) poss . LowerRightCorner . Y , 0 , 0 , 0 , 1 , color , tcoords . LowerRightCorner . X , tcoords . LowerRightCorner . Y ) ) ;
vertices . push_back ( S3DVertex ( ( f32 ) poss . UpperLeftCorner . X , ( f32 ) poss . LowerRightCorner . Y , 0 , 0 , 0 , 1 , color , tcoords . UpperLeftCorner . X , tcoords . LowerRightCorner . Y ) ) ;
2008-10-28 09:46:13 -07:00
2011-06-02 15:34:34 -07:00
quadIndices . push_back ( vstart ) ;
quadIndices . push_back ( vstart + 1 ) ;
quadIndices . push_back ( vstart + 2 ) ;
quadIndices . push_back ( vstart ) ;
quadIndices . push_back ( vstart + 2 ) ;
quadIndices . push_back ( vstart + 3 ) ;
2011-05-22 13:25:05 -07:00
2008-10-28 09:46:13 -07:00
targetPos . X + = sourceRects [ currentIndex ] . getWidth ( ) ;
}
2012-07-19 04:31:32 -07:00
if ( vertices . size ( ) )
drawVertexPrimitiveList2d3d ( vertices . pointer ( ) , vertices . size ( ) ,
quadIndices . pointer ( ) , vertices . size ( ) / 2 ,
video : : EVT_STANDARD , scene : : EPT_TRIANGLES ,
EIT_16BIT , false ) ;
2008-10-28 09:46:13 -07:00
if ( clipRect )
glDisable ( GL_SCISSOR_TEST ) ;
}
2011-05-22 13:25:05 -07:00
//! draws a set of 2d images, using a color and the alpha channel of the texture if desired.
2011-06-02 15:34:34 -07:00
void COGLES1Driver : : draw2DImageBatch ( const video : : ITexture * texture ,
2011-05-22 13:25:05 -07:00
const core : : array < core : : position2d < s32 > > & positions ,
const core : : array < core : : rect < s32 > > & sourceRects ,
const core : : rect < s32 > * clipRect ,
SColor color ,
bool useAlphaChannelOfTexture )
{
if ( ! texture )
return ;
const u32 drawCount = core : : min_ < u32 > ( positions . size ( ) , sourceRects . size ( ) ) ;
2012-07-19 04:31:32 -07:00
if ( ! drawCount )
return ;
2011-05-22 13:25:05 -07:00
const core : : dimension2d < u32 > & ss = texture - > getOriginalSize ( ) ;
2012-07-19 04:31:32 -07:00
if ( ! ss . Width | | ! ss . Height )
return ;
2011-05-22 13:25:05 -07:00
const f32 invW = 1.f / static_cast < f32 > ( ss . Width ) ;
const f32 invH = 1.f / static_cast < f32 > ( ss . Height ) ;
const core : : dimension2d < u32 > & renderTargetSize = getCurrentRenderTargetSize ( ) ;
disableTextures ( 1 ) ;
if ( ! setActiveTexture ( 0 , texture ) )
return ;
setRenderStates2DMode ( color . getAlpha ( ) < 255 , true , useAlphaChannelOfTexture ) ;
core : : array < S3DVertex > vertices ;
core : : array < u16 > quadIndices ;
vertices . reallocate ( drawCount * 4 ) ;
quadIndices . reallocate ( drawCount * 6 ) ;
for ( u32 i = 0 ; i < drawCount ; + + i )
{
if ( ! sourceRects [ i ] . isValid ( ) )
continue ;
core : : position2d < s32 > targetPos ( positions [ i ] ) ;
core : : position2d < s32 > sourcePos ( sourceRects [ i ] . UpperLeftCorner ) ;
// This needs to be signed as it may go negative.
core : : dimension2d < s32 > sourceSize ( sourceRects [ i ] . getSize ( ) ) ;
if ( clipRect )
{
if ( targetPos . X < clipRect - > UpperLeftCorner . X )
{
sourceSize . Width + = targetPos . X - clipRect - > UpperLeftCorner . X ;
if ( sourceSize . Width < = 0 )
continue ;
sourcePos . X - = targetPos . X - clipRect - > UpperLeftCorner . X ;
targetPos . X = clipRect - > UpperLeftCorner . X ;
}
if ( targetPos . X + sourceSize . Width > clipRect - > LowerRightCorner . X )
{
sourceSize . Width - = ( targetPos . X + sourceSize . Width ) - clipRect - > LowerRightCorner . X ;
if ( sourceSize . Width < = 0 )
continue ;
}
if ( targetPos . Y < clipRect - > UpperLeftCorner . Y )
{
sourceSize . Height + = targetPos . Y - clipRect - > UpperLeftCorner . Y ;
if ( sourceSize . Height < = 0 )
continue ;
sourcePos . Y - = targetPos . Y - clipRect - > UpperLeftCorner . Y ;
targetPos . Y = clipRect - > UpperLeftCorner . Y ;
}
if ( targetPos . Y + sourceSize . Height > clipRect - > LowerRightCorner . Y )
{
sourceSize . Height - = ( targetPos . Y + sourceSize . Height ) - clipRect - > LowerRightCorner . Y ;
if ( sourceSize . Height < = 0 )
continue ;
}
}
// clip these coordinates
if ( targetPos . X < 0 )
{
sourceSize . Width + = targetPos . X ;
if ( sourceSize . Width < = 0 )
continue ;
sourcePos . X - = targetPos . X ;
targetPos . X = 0 ;
}
if ( targetPos . X + sourceSize . Width > ( s32 ) renderTargetSize . Width )
{
sourceSize . Width - = ( targetPos . X + sourceSize . Width ) - renderTargetSize . Width ;
if ( sourceSize . Width < = 0 )
continue ;
}
if ( targetPos . Y < 0 )
{
sourceSize . Height + = targetPos . Y ;
if ( sourceSize . Height < = 0 )
continue ;
sourcePos . Y - = targetPos . Y ;
targetPos . Y = 0 ;
}
if ( targetPos . Y + sourceSize . Height > ( s32 ) renderTargetSize . Height )
{
sourceSize . Height - = ( targetPos . Y + sourceSize . Height ) - renderTargetSize . Height ;
if ( sourceSize . Height < = 0 )
continue ;
}
// ok, we've clipped everything.
const core : : rect < f32 > tcoords (
sourcePos . X * invW ,
sourcePos . Y * invH ,
( sourcePos . X + sourceSize . Width ) * invW ,
( sourcePos . Y + sourceSize . Height ) * invH ) ;
const core : : rect < s32 > poss ( targetPos , sourceSize ) ;
2011-06-03 04:32:53 -07:00
const u32 vstart = vertices . size ( ) ;
2011-05-22 13:25:05 -07:00
vertices . push_back ( S3DVertex ( ( f32 ) poss . UpperLeftCorner . X , ( f32 ) poss . UpperLeftCorner . Y , 0 , 0 , 0 , 1 , color , tcoords . UpperLeftCorner . X , tcoords . UpperLeftCorner . Y ) ) ;
vertices . push_back ( S3DVertex ( ( f32 ) poss . LowerRightCorner . X , ( f32 ) poss . UpperLeftCorner . Y , 0 , 0 , 0 , 1 , color , tcoords . LowerRightCorner . X , tcoords . UpperLeftCorner . Y ) ) ;
vertices . push_back ( S3DVertex ( ( f32 ) poss . LowerRightCorner . X , ( f32 ) poss . LowerRightCorner . Y , 0 , 0 , 0 , 1 , color , tcoords . LowerRightCorner . X , tcoords . LowerRightCorner . Y ) ) ;
vertices . push_back ( S3DVertex ( ( f32 ) poss . UpperLeftCorner . X , ( f32 ) poss . LowerRightCorner . Y , 0 , 0 , 0 , 1 , color , tcoords . UpperLeftCorner . X , tcoords . LowerRightCorner . Y ) ) ;
2011-06-02 15:34:34 -07:00
quadIndices . push_back ( vstart ) ;
quadIndices . push_back ( vstart + 1 ) ;
quadIndices . push_back ( vstart + 2 ) ;
quadIndices . push_back ( vstart ) ;
quadIndices . push_back ( vstart + 2 ) ;
quadIndices . push_back ( vstart + 3 ) ;
2011-05-22 13:25:05 -07:00
}
2012-07-19 04:31:32 -07:00
if ( vertices . size ( ) )
drawVertexPrimitiveList2d3d ( vertices . pointer ( ) , vertices . size ( ) ,
quadIndices . pointer ( ) , vertices . size ( ) / 2 ,
video : : EVT_STANDARD , scene : : EPT_TRIANGLES ,
EIT_16BIT , false ) ;
2011-05-22 13:25:05 -07:00
}
2008-10-28 09:46:13 -07:00
//! draw a 2d rectangle
2008-11-12 15:04:00 -08:00
void COGLES1Driver : : draw2DRectangle ( SColor color , const core : : rect < s32 > & position ,
2008-10-28 09:46:13 -07:00
const core : : rect < s32 > * clip )
{
disableTextures ( ) ;
setRenderStates2DMode ( color . getAlpha ( ) < 255 , false , false ) ;
core : : rect < s32 > pos = position ;
if ( clip )
pos . clipAgainst ( * clip ) ;
if ( ! pos . isValid ( ) )
return ;
u16 indices [ ] = { 0 , 1 , 2 , 3 } ;
S3DVertex vertices [ 4 ] ;
2008-11-12 15:04:00 -08:00
vertices [ 0 ] = S3DVertex ( ( f32 ) pos . UpperLeftCorner . X , ( f32 ) pos . UpperLeftCorner . Y , 0 , 0 , 0 , 1 , color , 0 , 0 ) ;
vertices [ 1 ] = S3DVertex ( ( f32 ) pos . LowerRightCorner . X , ( f32 ) pos . UpperLeftCorner . Y , 0 , 0 , 0 , 1 , color , 0 , 0 ) ;
vertices [ 2 ] = S3DVertex ( ( f32 ) pos . LowerRightCorner . X , ( f32 ) pos . LowerRightCorner . Y , 0 , 0 , 0 , 1 , color , 0 , 0 ) ;
vertices [ 3 ] = S3DVertex ( ( f32 ) pos . UpperLeftCorner . X , ( f32 ) pos . LowerRightCorner . Y , 0 , 0 , 0 , 1 , color , 0 , 0 ) ;
drawVertexPrimitiveList2d3d ( vertices , 4 , indices , 2 , video : : EVT_STANDARD , scene : : EPT_TRIANGLE_FAN , EIT_16BIT , false ) ;
2008-10-28 09:46:13 -07:00
}
//! draw an 2d rectangle
2008-11-12 15:04:00 -08:00
void COGLES1Driver : : draw2DRectangle ( const core : : rect < s32 > & position ,
2008-10-28 09:46:13 -07:00
SColor colorLeftUp , SColor colorRightUp , SColor colorLeftDown , SColor colorRightDown ,
const core : : rect < s32 > * clip )
{
core : : rect < s32 > pos = position ;
if ( clip )
pos . clipAgainst ( * clip ) ;
if ( ! pos . isValid ( ) )
return ;
disableTextures ( ) ;
setRenderStates2DMode ( colorLeftUp . getAlpha ( ) < 255 | |
colorRightUp . getAlpha ( ) < 255 | |
colorLeftDown . getAlpha ( ) < 255 | |
colorRightDown . getAlpha ( ) < 255 , false , false ) ;
u16 indices [ ] = { 0 , 1 , 2 , 3 } ;
S3DVertex vertices [ 4 ] ;
2008-11-12 15:04:00 -08:00
vertices [ 0 ] = S3DVertex ( ( f32 ) pos . UpperLeftCorner . X , ( f32 ) pos . UpperLeftCorner . Y , 0 , 0 , 0 , 1 , colorLeftUp , 0 , 0 ) ;
vertices [ 1 ] = S3DVertex ( ( f32 ) pos . LowerRightCorner . X , ( f32 ) pos . UpperLeftCorner . Y , 0 , 0 , 0 , 1 , colorRightUp , 0 , 0 ) ;
vertices [ 2 ] = S3DVertex ( ( f32 ) pos . LowerRightCorner . X , ( f32 ) pos . LowerRightCorner . Y , 0 , 0 , 0 , 1 , colorRightDown , 0 , 0 ) ;
vertices [ 3 ] = S3DVertex ( ( f32 ) pos . UpperLeftCorner . X , ( f32 ) pos . LowerRightCorner . Y , 0 , 0 , 0 , 1 , colorLeftDown , 0 , 0 ) ;
drawVertexPrimitiveList2d3d ( vertices , 4 , indices , 2 , video : : EVT_STANDARD , scene : : EPT_TRIANGLE_FAN , EIT_16BIT , false ) ;
2008-10-28 09:46:13 -07:00
}
//! Draws a 2d line.
2008-11-12 15:04:00 -08:00
void COGLES1Driver : : draw2DLine ( const core : : position2d < s32 > & start ,
2008-10-28 09:46:13 -07:00
const core : : position2d < s32 > & end ,
SColor color )
{
disableTextures ( ) ;
setRenderStates2DMode ( color . getAlpha ( ) < 255 , false , false ) ;
u16 indices [ ] = { 0 , 1 } ;
S3DVertex vertices [ 2 ] ;
2008-11-12 15:04:00 -08:00
vertices [ 0 ] = S3DVertex ( ( f32 ) start . X , ( f32 ) start . Y , 0 , 0 , 0 , 1 , color , 0 , 0 ) ;
vertices [ 1 ] = S3DVertex ( ( f32 ) end . X , ( f32 ) end . Y , 0 , 0 , 0 , 1 , color , 1 , 1 ) ;
drawVertexPrimitiveList2d3d ( vertices , 2 , indices , 1 , video : : EVT_STANDARD , scene : : EPT_LINES , EIT_16BIT , false ) ;
2008-10-28 09:46:13 -07:00
}
2011-06-09 07:56:17 -07:00
//! Draws a pixel
void COGLES1Driver : : drawPixel ( u32 x , u32 y , const SColor & color )
{
const core : : dimension2d < u32 > & renderTargetSize = getCurrentRenderTargetSize ( ) ;
if ( x > ( u32 ) renderTargetSize . Width | | y > ( u32 ) renderTargetSize . Height )
return ;
disableTextures ( ) ;
setRenderStates2DMode ( color . getAlpha ( ) < 255 , false , false ) ;
u16 indices [ ] = { 0 } ;
S3DVertex vertices [ 1 ] ;
vertices [ 0 ] = S3DVertex ( ( f32 ) x , ( f32 ) y , 0 , 0 , 0 , 1 , color , 0 , 0 ) ;
drawVertexPrimitiveList2d3d ( vertices , 1 , indices , 1 , video : : EVT_STANDARD , scene : : EPT_POINTS , EIT_16BIT , false ) ;
}
2008-10-28 09:46:13 -07:00
2011-06-03 04:32:53 -07:00
bool COGLES1Driver : : setActiveTexture ( u32 stage , const video : : ITexture * texture )
2008-10-28 09:46:13 -07:00
{
if ( stage > = MaxTextureUnits )
return false ;
if ( CurrentTexture [ stage ] = = texture )
return true ;
if ( MultiTextureExtension )
extGlActiveTexture ( GL_TEXTURE0 + stage ) ;
2014-05-22 10:07:49 -07:00
CurrentTexture . set ( stage , texture ) ;
2008-10-28 09:46:13 -07:00
if ( ! texture )
{
2013-08-03 08:59:18 -07:00
glBindTexture ( GL_TEXTURE_2D , 0 ) ;
2008-10-28 09:46:13 -07:00
glDisable ( GL_TEXTURE_2D ) ;
return true ;
}
else
{
if ( texture - > getDriverType ( ) ! = EDT_OGLES1 )
{
2014-05-22 10:07:49 -07:00
CurrentTexture . set ( stage , 0 ) ;
2008-10-28 09:46:13 -07:00
glDisable ( GL_TEXTURE_2D ) ;
os : : Printer : : log ( " Fatal Error: Tried to set a texture not owned by this driver. " , ELL_ERROR ) ;
return false ;
}
glEnable ( GL_TEXTURE_2D ) ;
glBindTexture ( GL_TEXTURE_2D ,
2008-11-12 15:04:00 -08:00
static_cast < const COGLES1Texture * > ( texture ) - > getOGLES1TextureName ( ) ) ;
2008-10-28 09:46:13 -07:00
}
return true ;
}
2008-11-12 15:04:00 -08:00
//! disables all textures beginning with the optional fromStage parameter.
bool COGLES1Driver : : disableTextures ( u32 fromStage )
2008-10-28 09:46:13 -07:00
{
bool result = true ;
for ( u32 i = fromStage ; i < MaxTextureUnits ; + + i )
2011-06-03 04:32:53 -07:00
result & = setActiveTexture ( i , 0 ) ;
2008-10-28 09:46:13 -07:00
return result ;
}
2008-11-12 15:04:00 -08:00
//! creates a matrix in supplied GLfloat array to pass to OGLES1
inline void COGLES1Driver : : createGLMatrix ( GLfloat gl_matrix [ 16 ] , const core : : matrix4 & m )
2008-10-28 09:46:13 -07:00
{
memcpy ( gl_matrix , m . pointer ( ) , 16 * sizeof ( f32 ) ) ;
}
//! creates a opengltexturematrix from a D3D style texture matrix
2008-11-12 15:04:00 -08:00
inline void COGLES1Driver : : createGLTextureMatrix ( GLfloat * o , const core : : matrix4 & m )
2008-10-28 09:46:13 -07:00
{
o [ 0 ] = m [ 0 ] ;
o [ 1 ] = m [ 1 ] ;
o [ 2 ] = 0.f ;
o [ 3 ] = 0.f ;
o [ 4 ] = m [ 4 ] ;
o [ 5 ] = m [ 5 ] ;
o [ 6 ] = 0.f ;
o [ 7 ] = 0.f ;
o [ 8 ] = 0.f ;
o [ 9 ] = 0.f ;
o [ 10 ] = 1.f ;
o [ 11 ] = 0.f ;
o [ 12 ] = m [ 8 ] ;
o [ 13 ] = m [ 9 ] ;
o [ 14 ] = 0.f ;
o [ 15 ] = 1.f ;
}
//! returns a device dependent texture from a software surface (IImage)
2010-01-23 17:44:36 -08:00
video : : ITexture * COGLES1Driver : : createDeviceDependentTexture ( IImage * surface , const io : : path & name , void * mipmapData )
2008-10-28 09:46:13 -07:00
{
2013-05-27 10:16:52 -07:00
COGLES1Texture * texture = 0 ;
if ( surface & & checkColorFormat ( surface - > getColorFormat ( ) , surface - > getDimension ( ) ) )
texture = new COGLES1Texture ( surface , name , this , mipmapData ) ;
return texture ;
2008-10-28 09:46:13 -07:00
}
2008-11-12 15:04:00 -08:00
//! Sets a material.
void COGLES1Driver : : setMaterial ( const SMaterial & material )
2008-10-28 09:46:13 -07:00
{
Material = material ;
2009-05-05 15:27:24 -07:00
OverrideMaterial . apply ( Material ) ;
2008-10-28 09:46:13 -07:00
for ( s32 i = MaxTextureUnits - 1 ; i > = 0 ; - - i )
{
setTransform ( ( E_TRANSFORMATION_STATE ) ( ETS_TEXTURE_0 + i ) ,
2009-05-05 15:27:24 -07:00
Material . getTextureMatrix ( i ) ) ;
2008-10-28 09:46:13 -07:00
}
}
//! prints error if an error happened.
2008-11-12 15:04:00 -08:00
bool COGLES1Driver : : testGLError ( )
2008-10-28 09:46:13 -07:00
{
# ifdef _DEBUG
GLenum g = glGetError ( ) ;
switch ( g )
{
case GL_NO_ERROR :
return false ;
case GL_INVALID_ENUM :
os : : Printer : : log ( " GL_INVALID_ENUM " , ELL_ERROR ) ; break ;
case GL_INVALID_VALUE :
os : : Printer : : log ( " GL_INVALID_VALUE " , ELL_ERROR ) ; break ;
case GL_INVALID_OPERATION :
os : : Printer : : log ( " GL_INVALID_OPERATION " , ELL_ERROR ) ; break ;
case GL_STACK_OVERFLOW :
os : : Printer : : log ( " GL_STACK_OVERFLOW " , ELL_ERROR ) ; break ;
case GL_STACK_UNDERFLOW :
os : : Printer : : log ( " GL_STACK_UNDERFLOW " , ELL_ERROR ) ; break ;
case GL_OUT_OF_MEMORY :
os : : Printer : : log ( " GL_OUT_OF_MEMORY " , ELL_ERROR ) ; break ;
} ;
2009-05-06 12:33:53 -07:00
// _IRR_DEBUG_BREAK_IF(true);
2008-10-28 09:46:13 -07:00
return true ;
# else
return false ;
# endif
}
//! sets the needed renderstates
2008-11-12 15:04:00 -08:00
void COGLES1Driver : : setRenderStates3DMode ( )
2008-10-28 09:46:13 -07:00
{
if ( CurrentRenderMode ! = ERM_3D )
{
// Reset Texture Stages
2014-05-10 14:47:14 -07:00
BridgeCalls - > setBlend ( false ) ;
2009-05-06 12:33:53 -07:00
glDisable ( GL_ALPHA_TEST ) ;
2014-05-10 14:47:14 -07:00
BridgeCalls - > setBlendFunc ( GL_ONE , GL_ONE_MINUS_SRC_COLOR ) ;
2008-10-28 09:46:13 -07:00
// switch back the matrices
glMatrixMode ( GL_MODELVIEW ) ;
glLoadMatrixf ( ( Matrices [ ETS_VIEW ] * Matrices [ ETS_WORLD ] ) . pointer ( ) ) ;
GLfloat glmat [ 16 ] ;
createGLMatrix ( glmat , Matrices [ ETS_PROJECTION ] ) ;
glmat [ 12 ] * = - 1.0f ;
glMatrixMode ( GL_PROJECTION ) ;
glLoadMatrixf ( glmat ) ;
ResetRenderStates = true ;
}
if ( ResetRenderStates | | LastMaterial ! = Material )
{
// unset old material
if ( LastMaterial . MaterialType ! = Material . MaterialType & &
static_cast < u32 > ( LastMaterial . MaterialType ) < MaterialRenderers . size ( ) )
MaterialRenderers [ LastMaterial . MaterialType ] . Renderer - > OnUnsetMaterial ( ) ;
// set new material.
if ( static_cast < u32 > ( Material . MaterialType ) < MaterialRenderers . size ( ) )
MaterialRenderers [ Material . MaterialType ] . Renderer - > OnSetMaterial (
Material , LastMaterial , ResetRenderStates , this ) ;
LastMaterial = Material ;
ResetRenderStates = false ;
}
if ( static_cast < u32 > ( Material . MaterialType ) < MaterialRenderers . size ( ) )
MaterialRenderers [ Material . MaterialType ] . Renderer - > OnRender ( this , video : : EVT_STANDARD ) ;
CurrentRenderMode = ERM_3D ;
}
2009-11-20 04:30:26 -08:00
GLint COGLES1Driver : : getTextureWrapMode ( u8 clamp ) const
{
switch ( clamp )
{
case ETC_CLAMP :
// return GL_CLAMP; not supported in ogl-es
return GL_CLAMP_TO_EDGE ;
break ;
case ETC_CLAMP_TO_EDGE :
return GL_CLAMP_TO_EDGE ;
break ;
case ETC_CLAMP_TO_BORDER :
// return GL_CLAMP_TO_BORDER; not supported in ogl-es
return GL_CLAMP_TO_EDGE ;
break ;
case ETC_MIRROR :
# ifdef GL_OES_texture_mirrored_repeat
if ( FeatureAvailable [ IRR_OES_texture_mirrored_repeat ] )
return GL_MIRRORED_REPEAT_OES ;
else
# endif
return GL_REPEAT ;
break ;
// the next three are not yet supported at all
case ETC_MIRROR_CLAMP :
case ETC_MIRROR_CLAMP_TO_EDGE :
case ETC_MIRROR_CLAMP_TO_BORDER :
# ifdef GL_OES_texture_mirrored_repeat
if ( FeatureAvailable [ IRR_OES_texture_mirrored_repeat ] )
return GL_MIRRORED_REPEAT_OES ;
else
# endif
return GL_CLAMP_TO_EDGE ;
break ;
case ETC_REPEAT :
default :
return GL_REPEAT ;
break ;
}
}
2008-11-12 15:04:00 -08:00
void COGLES1Driver : : setWrapMode ( const SMaterial & material )
2008-10-28 09:46:13 -07:00
{
// texture address mode
// Has to be checked always because it depends on the textures
for ( u32 u = 0 ; u < MaxTextureUnits ; + + u )
{
if ( MultiTextureExtension )
extGlActiveTexture ( GL_TEXTURE0 + u ) ;
else if ( u > 0 )
break ; // stop loop
2009-11-20 04:46:09 -08:00
// the APPLE npot restricted extension needs some care as it only supports CLAMP_TO_EDGE
if ( queryFeature ( EVDF_TEXTURE_NPOT ) & & ! FeatureAvailable [ IRR_OES_texture_npot ] & &
2009-11-20 09:20:43 -08:00
CurrentTexture [ u ] & & ( CurrentTexture [ u ] - > getSize ( ) ! = CurrentTexture [ u ] - > getOriginalSize ( ) ) )
2009-11-20 04:46:09 -08:00
{
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE ) ;
}
else
{
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , getTextureWrapMode ( material . TextureLayer [ u ] . TextureWrapU ) ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T , getTextureWrapMode ( material . TextureLayer [ u ] . TextureWrapV ) ) ;
}
2008-10-28 09:46:13 -07:00
}
}
//! Can be called by an IMaterialRenderer to make its work easier.
2008-11-12 15:04:00 -08:00
void COGLES1Driver : : setBasicRenderStates ( const SMaterial & material , const SMaterial & lastmaterial ,
2008-10-28 09:46:13 -07:00
bool resetAllRenderStates )
{
2009-05-05 15:27:24 -07:00
if ( resetAllRenderStates | |
lastmaterial . ColorMaterial ! = material . ColorMaterial )
{
// we only have diffuse_and_ambient in ogl-es
if ( material . ColorMaterial = = ECM_DIFFUSE_AND_AMBIENT )
glEnable ( GL_COLOR_MATERIAL ) ;
else
glDisable ( GL_COLOR_MATERIAL ) ;
}
2008-10-28 09:46:13 -07:00
if ( resetAllRenderStates | |
lastmaterial . AmbientColor ! = material . AmbientColor | |
lastmaterial . DiffuseColor ! = material . DiffuseColor | |
lastmaterial . EmissiveColor ! = material . EmissiveColor | |
2009-05-05 15:27:24 -07:00
lastmaterial . ColorMaterial ! = material . ColorMaterial )
2008-10-28 09:46:13 -07:00
{
GLfloat color [ 4 ] ;
const f32 inv = 1.0f / 255.0f ;
2009-05-05 15:27:24 -07:00
if ( ( material . ColorMaterial ! = video : : ECM_AMBIENT ) & &
( material . ColorMaterial ! = video : : ECM_DIFFUSE_AND_AMBIENT ) )
{
color [ 0 ] = material . AmbientColor . getRed ( ) * inv ;
color [ 1 ] = material . AmbientColor . getGreen ( ) * inv ;
color [ 2 ] = material . AmbientColor . getBlue ( ) * inv ;
color [ 3 ] = material . AmbientColor . getAlpha ( ) * inv ;
glMaterialfv ( GL_FRONT_AND_BACK , GL_AMBIENT , color ) ;
}
2008-10-28 09:46:13 -07:00
2009-05-05 15:27:24 -07:00
if ( ( material . ColorMaterial ! = video : : ECM_DIFFUSE ) & &
( material . ColorMaterial ! = video : : ECM_DIFFUSE_AND_AMBIENT ) )
{
color [ 0 ] = material . DiffuseColor . getRed ( ) * inv ;
color [ 1 ] = material . DiffuseColor . getGreen ( ) * inv ;
color [ 2 ] = material . DiffuseColor . getBlue ( ) * inv ;
color [ 3 ] = material . DiffuseColor . getAlpha ( ) * inv ;
glMaterialfv ( GL_FRONT_AND_BACK , GL_DIFFUSE , color ) ;
}
if ( material . ColorMaterial ! = video : : ECM_EMISSIVE )
{
color [ 0 ] = material . EmissiveColor . getRed ( ) * inv ;
color [ 1 ] = material . EmissiveColor . getGreen ( ) * inv ;
color [ 2 ] = material . EmissiveColor . getBlue ( ) * inv ;
color [ 3 ] = material . EmissiveColor . getAlpha ( ) * inv ;
glMaterialfv ( GL_FRONT_AND_BACK , GL_EMISSION , color ) ;
}
}
if ( resetAllRenderStates | |
lastmaterial . SpecularColor ! = material . SpecularColor | |
lastmaterial . Shininess ! = material . Shininess )
{
GLfloat color [ ] = { 0.f , 0.f , 0.f , 1.f } ;
const f32 inv = 1.0f / 255.0f ;
2008-10-28 09:46:13 -07:00
// disable Specular colors if no shininess is set
2009-05-05 15:27:24 -07:00
if ( ( material . Shininess ! = 0.0f ) & &
( material . ColorMaterial ! = video : : ECM_SPECULAR ) )
2008-10-28 09:46:13 -07:00
{
2010-01-24 12:26:32 -08:00
# ifdef GL_EXT_separate_specular_color
if ( FeatureAvailable [ IRR_EXT_separate_specular_color ] )
2008-10-28 09:46:13 -07:00
glLightModeli ( GL_LIGHT_MODEL_COLOR_CONTROL , GL_SEPARATE_SPECULAR_COLOR ) ;
# endif
glMaterialf ( GL_FRONT_AND_BACK , GL_SHININESS , material . Shininess ) ;
color [ 0 ] = material . SpecularColor . getRed ( ) * inv ;
color [ 1 ] = material . SpecularColor . getGreen ( ) * inv ;
color [ 2 ] = material . SpecularColor . getBlue ( ) * inv ;
color [ 3 ] = material . SpecularColor . getAlpha ( ) * inv ;
glMaterialfv ( GL_FRONT_AND_BACK , GL_SPECULAR , color ) ;
}
2010-01-24 12:26:32 -08:00
# ifdef GL_EXT_separate_specular_color
2008-10-28 09:46:13 -07:00
else
2010-01-24 12:26:32 -08:00
if ( FeatureAvailable [ IRR_EXT_separate_specular_color ] )
2008-10-28 09:46:13 -07:00
glLightModeli ( GL_LIGHT_MODEL_COLOR_CONTROL , GL_SINGLE_COLOR ) ;
# endif
}
// Texture filter
// Has to be checked always because it depends on the textures
// Filtering has to be set for each texture layer
for ( u32 i = 0 ; i < MaxTextureUnits ; + + i )
{
if ( MultiTextureExtension )
extGlActiveTexture ( GL_TEXTURE0 + i ) ;
else if ( i > 0 )
break ;
2009-11-20 05:03:04 -08:00
# ifdef GL_EXT_texture_lod_bias
if ( FeatureAvailable [ IRR_EXT_texture_lod_bias ] )
{
if ( material . TextureLayer [ i ] . LODBias )
{
const float tmp = core : : clamp ( material . TextureLayer [ i ] . LODBias * 0.125f , - MaxTextureLODBias , MaxTextureLODBias ) ;
glTexEnvf ( GL_TEXTURE_FILTER_CONTROL_EXT , GL_TEXTURE_LOD_BIAS_EXT , tmp ) ;
}
else
glTexEnvf ( GL_TEXTURE_FILTER_CONTROL_EXT , GL_TEXTURE_LOD_BIAS_EXT , 0.f ) ;
}
# endif
2008-10-28 09:46:13 -07:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER ,
( material . TextureLayer [ i ] . BilinearFilter | | material . TextureLayer [ i ] . TrilinearFilter ) ? GL_LINEAR : GL_NEAREST ) ;
if ( material . getTexture ( i ) & & material . getTexture ( i ) - > hasMipMaps ( ) )
2009-11-20 04:46:09 -08:00
// the npot extensions need some checks, because APPLE
// npot is somewhat restricted and only support non-mipmap filter
if ( queryFeature ( EVDF_TEXTURE_NPOT ) & & ! FeatureAvailable [ IRR_OES_texture_npot ] & &
( CurrentTexture [ i ] - > getSize ( ) ! = CurrentTexture [ i ] - > getOriginalSize ( ) ) )
{
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER ,
material . TextureLayer [ i ] . TrilinearFilter ? GL_LINEAR :
material . TextureLayer [ i ] . BilinearFilter ? GL_LINEAR :
GL_NEAREST ) ;
}
else
{
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER ,
material . TextureLayer [ i ] . TrilinearFilter ? GL_LINEAR_MIPMAP_LINEAR :
material . TextureLayer [ i ] . BilinearFilter ? GL_LINEAR_MIPMAP_NEAREST :
GL_NEAREST_MIPMAP_NEAREST ) ;
}
2008-10-28 09:46:13 -07:00
else
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER ,
( material . TextureLayer [ i ] . BilinearFilter | | material . TextureLayer [ i ] . TrilinearFilter ) ? GL_LINEAR : GL_NEAREST ) ;
2009-01-13 16:03:59 -08:00
# ifdef GL_EXT_texture_filter_anisotropic
2009-01-26 01:26:48 -08:00
if ( FeatureAvailable [ IRR_EXT_texture_filter_anisotropic ] )
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_MAX_ANISOTROPY_EXT ,
2009-05-08 14:50:11 -07:00
static_cast < GLfloat > ( material . TextureLayer [ i ] . AnisotropicFilter > 1 ? core : : min_ ( MaxAnisotropy , material . TextureLayer [ i ] . AnisotropicFilter ) : 1 ) ) ;
2008-10-28 09:46:13 -07:00
# endif
}
2008-11-12 15:04:00 -08:00
// TODO ogl-es
2008-10-28 09:46:13 -07:00
// fillmode
// if (resetAllRenderStates || (lastmaterial.Wireframe != material.Wireframe) || (lastmaterial.PointCloud != material.PointCloud))
// glPolygonMode(GL_FRONT_AND_BACK, material.Wireframe ? GL_LINE : material.PointCloud? GL_POINT : GL_FILL);
// shademode
if ( resetAllRenderStates | | ( lastmaterial . GouraudShading ! = material . GouraudShading ) )
{
if ( material . GouraudShading )
glShadeModel ( GL_SMOOTH ) ;
else
glShadeModel ( GL_FLAT ) ;
}
// lighting
if ( resetAllRenderStates | | ( lastmaterial . Lighting ! = material . Lighting ) )
{
if ( material . Lighting )
glEnable ( GL_LIGHTING ) ;
else
glDisable ( GL_LIGHTING ) ;
}
// zbuffer
if ( resetAllRenderStates | | lastmaterial . ZBuffer ! = material . ZBuffer )
{
switch ( material . ZBuffer )
{
2014-10-11 02:37:30 -07:00
case ECFN_DISABLED :
2008-10-28 09:46:13 -07:00
glDisable ( GL_DEPTH_TEST ) ;
break ;
2009-05-05 16:27:57 -07:00
case ECFN_LESSEQUAL :
2008-10-28 09:46:13 -07:00
glEnable ( GL_DEPTH_TEST ) ;
2009-05-05 16:27:57 -07:00
glDepthFunc ( GL_LEQUAL ) ;
2008-10-28 09:46:13 -07:00
break ;
2009-05-05 16:27:57 -07:00
case ECFN_EQUAL :
2008-10-28 09:46:13 -07:00
glEnable ( GL_DEPTH_TEST ) ;
2009-05-05 16:27:57 -07:00
glDepthFunc ( GL_EQUAL ) ;
break ;
case ECFN_LESS :
glEnable ( GL_DEPTH_TEST ) ;
glDepthFunc ( GL_LESS ) ;
break ;
case ECFN_NOTEQUAL :
glEnable ( GL_DEPTH_TEST ) ;
glDepthFunc ( GL_NOTEQUAL ) ;
break ;
case ECFN_GREATEREQUAL :
glEnable ( GL_DEPTH_TEST ) ;
glDepthFunc ( GL_GEQUAL ) ;
break ;
case ECFN_GREATER :
glEnable ( GL_DEPTH_TEST ) ;
glDepthFunc ( GL_GREATER ) ;
break ;
case ECFN_ALWAYS :
glEnable ( GL_DEPTH_TEST ) ;
glDepthFunc ( GL_ALWAYS ) ;
2008-10-28 09:46:13 -07:00
break ;
2014-10-11 02:37:30 -07:00
case ECFN_NEVER :
glEnable ( GL_DEPTH_TEST ) ;
glDepthFunc ( GL_NEVER ) ;
break ;
2008-10-28 09:46:13 -07:00
}
}
// zwrite
// if (resetAllRenderStates || lastmaterial.ZWriteEnable != material.ZWriteEnable)
{
2014-05-08 09:23:12 -07:00
if ( material . ZWriteEnable & & ( AllowZWriteOnTransparent | | ( material . BlendOperation = = EBO_NONE & &
! MaterialRenderers [ material . MaterialType ] . Renderer - > isTransparent ( ) ) ) )
2008-10-28 09:46:13 -07:00
{
glDepthMask ( GL_TRUE ) ;
}
else
glDepthMask ( GL_FALSE ) ;
}
// back face culling
if ( resetAllRenderStates | | ( lastmaterial . FrontfaceCulling ! = material . FrontfaceCulling ) | | ( lastmaterial . BackfaceCulling ! = material . BackfaceCulling ) )
{
if ( ( material . FrontfaceCulling ) & & ( material . BackfaceCulling ) )
{
glCullFace ( GL_FRONT_AND_BACK ) ;
glEnable ( GL_CULL_FACE ) ;
}
else
if ( material . BackfaceCulling )
{
glCullFace ( GL_BACK ) ;
glEnable ( GL_CULL_FACE ) ;
}
else
if ( material . FrontfaceCulling )
{
glCullFace ( GL_FRONT ) ;
glEnable ( GL_CULL_FACE ) ;
}
else
glDisable ( GL_CULL_FACE ) ;
}
// fog
if ( resetAllRenderStates | | lastmaterial . FogEnable ! = material . FogEnable )
{
if ( material . FogEnable )
glEnable ( GL_FOG ) ;
else
glDisable ( GL_FOG ) ;
}
// normalization
if ( resetAllRenderStates | | lastmaterial . NormalizeNormals ! = material . NormalizeNormals )
{
if ( material . NormalizeNormals )
glEnable ( GL_NORMALIZE ) ;
else
glDisable ( GL_NORMALIZE ) ;
}
2009-05-05 16:27:57 -07:00
// Color Mask
if ( resetAllRenderStates | | lastmaterial . ColorMask ! = material . ColorMask )
{
glColorMask (
( material . ColorMask & ECP_RED ) ? GL_TRUE : GL_FALSE ,
( material . ColorMask & ECP_GREEN ) ? GL_TRUE : GL_FALSE ,
( material . ColorMask & ECP_BLUE ) ? GL_TRUE : GL_FALSE ,
( material . ColorMask & ECP_ALPHA ) ? GL_TRUE : GL_FALSE ) ;
}
2014-05-08 09:23:12 -07:00
2014-05-10 14:47:14 -07:00
// Blend Equation
if ( material . BlendOperation = = EBO_NONE )
BridgeCalls - > setBlend ( false ) ;
else
{
BridgeCalls - > setBlend ( true ) ;
if ( queryFeature ( EVDF_BLEND_OPERATIONS ) )
{
switch ( material . BlendOperation )
{
case EBO_ADD :
# if defined(GL_OES_blend_subtract)
BridgeCalls - > setBlendEquation ( GL_FUNC_ADD_OES ) ;
# endif
break ;
case EBO_SUBTRACT :
# if defined(GL_OES_blend_subtract)
BridgeCalls - > setBlendEquation ( GL_FUNC_SUBTRACT_OES ) ;
# endif
break ;
case EBO_REVSUBTRACT :
# if defined(GL_OES_blend_subtract)
BridgeCalls - > setBlendEquation ( GL_FUNC_REVERSE_SUBTRACT_OES ) ;
# endif
break ;
default :
break ;
}
}
}
// Blend Factor
2014-05-26 09:40:42 -07:00
if ( IR ( material . BlendFactor ) & 0xFFFFFFFF )
2014-05-10 14:47:14 -07:00
{
E_BLEND_FACTOR srcRGBFact = EBF_ZERO ;
E_BLEND_FACTOR dstRGBFact = EBF_ZERO ;
E_BLEND_FACTOR srcAlphaFact = EBF_ZERO ;
E_BLEND_FACTOR dstAlphaFact = EBF_ZERO ;
E_MODULATE_FUNC modulo = EMFN_MODULATE_1X ;
u32 alphaSource = 0 ;
unpack_textureBlendFuncSeparate ( srcRGBFact , dstRGBFact , srcAlphaFact , dstAlphaFact , modulo , alphaSource , material . BlendFactor ) ;
if ( queryFeature ( EVDF_BLEND_SEPARATE ) )
{
BridgeCalls - > setBlendFuncSeparate ( getGLBlend ( srcRGBFact ) , getGLBlend ( dstRGBFact ) ,
getGLBlend ( srcAlphaFact ) , getGLBlend ( dstAlphaFact ) ) ;
}
else
{
BridgeCalls - > setBlendFunc ( getGLBlend ( srcRGBFact ) , getGLBlend ( dstRGBFact ) ) ;
}
}
2008-10-28 09:46:13 -07:00
// thickness
if ( resetAllRenderStates | | lastmaterial . Thickness ! = material . Thickness )
{
2010-01-24 12:26:32 -08:00
if ( AntiAlias )
{
// glPointSize(core::clamp(static_cast<GLfloat>(material.Thickness), DimSmoothedPoint[0], DimSmoothedPoint[1]));
// we don't use point smoothing
glPointSize ( core : : clamp ( static_cast < GLfloat > ( material . Thickness ) , DimAliasedPoint [ 0 ] , DimAliasedPoint [ 1 ] ) ) ;
glLineWidth ( core : : clamp ( static_cast < GLfloat > ( material . Thickness ) , DimSmoothedLine [ 0 ] , DimSmoothedLine [ 1 ] ) ) ;
}
else
{
glPointSize ( core : : clamp ( static_cast < GLfloat > ( material . Thickness ) , DimAliasedPoint [ 0 ] , DimAliasedPoint [ 1 ] ) ) ;
glLineWidth ( core : : clamp ( static_cast < GLfloat > ( material . Thickness ) , DimAliasedLine [ 0 ] , DimAliasedLine [ 1 ] ) ) ;
}
2008-10-28 09:46:13 -07:00
}
2009-05-05 16:27:57 -07:00
// Anti aliasing
if ( resetAllRenderStates | | lastmaterial . AntiAliasing ! = material . AntiAliasing )
{
// if (FeatureAvailable[IRR_ARB_multisample])
{
if ( material . AntiAliasing & EAAM_ALPHA_TO_COVERAGE )
glEnable ( GL_SAMPLE_ALPHA_TO_COVERAGE ) ;
else if ( lastmaterial . AntiAliasing & EAAM_ALPHA_TO_COVERAGE )
glDisable ( GL_SAMPLE_ALPHA_TO_COVERAGE ) ;
if ( ( AntiAlias > = 2 ) & & ( material . AntiAliasing & ( EAAM_SIMPLE | EAAM_QUALITY ) ) )
glEnable ( GL_MULTISAMPLE ) ;
else
glDisable ( GL_MULTISAMPLE ) ;
}
2010-01-24 12:26:32 -08:00
if ( ( material . AntiAliasing & EAAM_LINE_SMOOTH ) ! = ( lastmaterial . AntiAliasing & EAAM_LINE_SMOOTH ) )
2009-05-05 16:27:57 -07:00
{
if ( material . AntiAliasing & EAAM_LINE_SMOOTH )
glEnable ( GL_LINE_SMOOTH ) ;
else if ( lastmaterial . AntiAliasing & EAAM_LINE_SMOOTH )
glDisable ( GL_LINE_SMOOTH ) ;
2010-01-24 12:26:32 -08:00
}
if ( ( material . AntiAliasing & EAAM_POINT_SMOOTH ) ! = ( lastmaterial . AntiAliasing & EAAM_POINT_SMOOTH ) )
{
2009-05-05 16:27:57 -07:00
if ( material . AntiAliasing & EAAM_POINT_SMOOTH )
// often in software, and thus very slow
glEnable ( GL_POINT_SMOOTH ) ;
else if ( lastmaterial . AntiAliasing & EAAM_POINT_SMOOTH )
glDisable ( GL_POINT_SMOOTH ) ;
}
}
2008-10-28 09:46:13 -07:00
setWrapMode ( material ) ;
// be sure to leave in texture stage 0
if ( MultiTextureExtension )
extGlActiveTexture ( GL_TEXTURE0 ) ;
}
//! sets the needed renderstates
2008-11-12 15:04:00 -08:00
void COGLES1Driver : : setRenderStates2DMode ( bool alpha , bool texture , bool alphaChannel )
2008-10-28 09:46:13 -07:00
{
if ( CurrentRenderMode ! = ERM_2D | | Transformation3DChanged )
{
// unset last 3d material
if ( CurrentRenderMode = = ERM_3D )
{
if ( static_cast < u32 > ( LastMaterial . MaterialType ) < MaterialRenderers . size ( ) )
MaterialRenderers [ LastMaterial . MaterialType ] . Renderer - > OnUnsetMaterial ( ) ;
}
2011-05-22 13:25:05 -07:00
if ( Transformation3DChanged )
{
glMatrixMode ( GL_PROJECTION ) ;
2008-10-28 09:46:13 -07:00
2011-05-22 13:25:05 -07:00
const core : : dimension2d < u32 > & renderTargetSize = getCurrentRenderTargetSize ( ) ;
core : : matrix4 m ;
m . buildProjectionMatrixOrthoLH ( f32 ( renderTargetSize . Width ) , f32 ( - ( s32 ) ( renderTargetSize . Height ) ) , - 1.0 , 1.0 ) ;
m . setTranslation ( core : : vector3df ( - 1 , 1 , 0 ) ) ;
glLoadMatrixf ( m . pointer ( ) ) ;
2008-10-28 09:46:13 -07:00
2011-05-22 13:25:05 -07:00
glMatrixMode ( GL_MODELVIEW ) ;
glLoadIdentity ( ) ;
glTranslatef ( 0.375 , 0.375 , 0.0 ) ;
2008-10-28 09:46:13 -07:00
2011-05-22 13:25:05 -07:00
// Make sure we set first texture matrix
if ( MultiTextureExtension )
2011-06-02 15:34:34 -07:00
extGlActiveTexture ( GL_TEXTURE0 ) ;
2008-10-28 09:46:13 -07:00
2011-05-22 13:25:05 -07:00
glMatrixMode ( GL_TEXTURE ) ;
glLoadIdentity ( ) ;
2008-10-28 09:46:13 -07:00
2011-05-22 13:25:05 -07:00
Transformation3DChanged = false ;
}
if ( ! OverrideMaterial2DEnabled )
{
setBasicRenderStates ( InitMaterial2D , LastMaterial , true ) ;
LastMaterial = InitMaterial2D ;
}
}
if ( OverrideMaterial2DEnabled )
{
OverrideMaterial2D . Lighting = false ;
setBasicRenderStates ( OverrideMaterial2D , LastMaterial , false ) ;
LastMaterial = OverrideMaterial2D ;
2008-10-28 09:46:13 -07:00
}
if ( alphaChannel | | alpha )
{
2014-05-10 14:47:14 -07:00
BridgeCalls - > setBlend ( true ) ;
BridgeCalls - > setBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ;
2008-10-28 09:46:13 -07:00
glEnable ( GL_ALPHA_TEST ) ;
glAlphaFunc ( GL_GREATER , 0.f ) ;
}
else
{
2014-05-10 14:47:14 -07:00
BridgeCalls - > setBlend ( false ) ;
2008-10-28 09:46:13 -07:00
glDisable ( GL_ALPHA_TEST ) ;
}
if ( texture )
{
2011-06-03 16:17:23 -07:00
if ( ! OverrideMaterial2DEnabled )
2011-05-22 13:25:05 -07:00
{
2011-06-02 15:34:34 -07:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_NEAREST ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_NEAREST ) ;
2011-05-22 13:25:05 -07:00
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , GL_REPEAT ) ;
glTexParameterf ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T , GL_REPEAT ) ;
}
2008-10-28 09:46:13 -07:00
2011-05-22 13:25:05 -07:00
Material . setTexture ( 0 , const_cast < video : : ITexture * > ( CurrentTexture [ 0 ] ) ) ;
setTransform ( ETS_TEXTURE_0 , core : : IdentityMatrix ) ;
// Due to the transformation change, the previous line would call a reset each frame
// but we can safely reset the variable as it was false before
Transformation3DChanged = false ;
2008-10-28 09:46:13 -07:00
if ( alphaChannel )
{
// if alpha and alpha texture just modulate, otherwise use only the alpha channel
if ( alpha )
{
glTexEnvf ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_MODULATE ) ;
}
else
{
glTexEnvf ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_COMBINE ) ;
glTexEnvf ( GL_TEXTURE_ENV , GL_COMBINE_ALPHA , GL_REPLACE ) ;
glTexEnvf ( GL_TEXTURE_ENV , GL_SRC0_ALPHA , GL_TEXTURE ) ;
// rgb always modulates
glTexEnvf ( GL_TEXTURE_ENV , GL_COMBINE_RGB , GL_MODULATE ) ;
glTexEnvf ( GL_TEXTURE_ENV , GL_SRC0_RGB , GL_TEXTURE ) ;
glTexEnvf ( GL_TEXTURE_ENV , GL_SRC1_RGB , GL_PRIMARY_COLOR ) ;
}
}
else
{
if ( alpha )
{
glTexEnvf ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_COMBINE ) ;
glTexEnvf ( GL_TEXTURE_ENV , GL_COMBINE_ALPHA , GL_REPLACE ) ;
glTexEnvf ( GL_TEXTURE_ENV , GL_SRC0_ALPHA , GL_PRIMARY_COLOR ) ;
// rgb always modulates
glTexEnvf ( GL_TEXTURE_ENV , GL_COMBINE_RGB , GL_MODULATE ) ;
glTexEnvf ( GL_TEXTURE_ENV , GL_SRC0_RGB , GL_TEXTURE ) ;
glTexEnvf ( GL_TEXTURE_ENV , GL_SRC1_RGB , GL_PRIMARY_COLOR ) ;
}
else
{
glTexEnvi ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_MODULATE ) ;
}
}
}
CurrentRenderMode = ERM_2D ;
}
//! \return Returns the name of the video driver.
2008-11-12 15:04:00 -08:00
const wchar_t * COGLES1Driver : : getName ( ) const
2008-10-28 09:46:13 -07:00
{
return Name . c_str ( ) ;
}
//! deletes all dynamic lights there are
2008-11-12 15:04:00 -08:00
void COGLES1Driver : : deleteAllDynamicLights ( )
2008-10-28 09:46:13 -07:00
{
2009-05-05 15:27:24 -07:00
for ( s32 i = 0 ; i < MaxLights ; + + i )
2008-10-28 09:46:13 -07:00
glDisable ( GL_LIGHT0 + i ) ;
2009-01-27 05:45:17 -08:00
RequestedLights . clear ( ) ;
2008-10-28 09:46:13 -07:00
CNullDriver : : deleteAllDynamicLights ( ) ;
}
//! adds a dynamic light
2009-01-27 05:45:17 -08:00
s32 COGLES1Driver : : addDynamicLight ( const SLight & light )
2008-10-28 09:46:13 -07:00
{
2009-01-27 05:45:17 -08:00
CNullDriver : : addDynamicLight ( light ) ;
RequestedLights . push_back ( RequestedLight ( light ) ) ;
u32 newLightIndex = RequestedLights . size ( ) - 1 ;
// Try and assign a hardware light just now, but don't worry if I can't
assignHardwareLight ( newLightIndex ) ;
2008-10-28 09:46:13 -07:00
2009-01-27 05:45:17 -08:00
return ( s32 ) newLightIndex ;
}
void COGLES1Driver : : assignHardwareLight ( u32 lightIndex )
{
2008-10-28 09:46:13 -07:00
setTransform ( ETS_WORLD , core : : matrix4 ( ) ) ;
2009-01-27 05:45:17 -08:00
s32 lidx ;
for ( lidx = GL_LIGHT0 ; lidx < GL_LIGHT0 + MaxLights ; + + lidx )
{
if ( ! glIsEnabled ( lidx ) )
{
RequestedLights [ lightIndex ] . HardwareLightIndex = lidx ;
break ;
}
}
if ( lidx = = GL_LIGHT0 + MaxLights ) // There's no room for it just now
return ;
2008-10-28 09:46:13 -07:00
GLfloat data [ 4 ] ;
2009-01-27 05:45:17 -08:00
const SLight & light = RequestedLights [ lightIndex ] . LightData ;
2008-10-28 09:46:13 -07:00
switch ( light . Type )
{
case video : : ELT_SPOT :
data [ 0 ] = light . Direction . X ;
data [ 1 ] = light . Direction . Y ;
data [ 2 ] = light . Direction . Z ;
data [ 3 ] = 0.0f ;
glLightfv ( lidx , GL_SPOT_DIRECTION , data ) ;
// set position
data [ 0 ] = light . Position . X ;
data [ 1 ] = light . Position . Y ;
data [ 2 ] = light . Position . Z ;
data [ 3 ] = 1.0f ; // 1.0f for positional light
glLightfv ( lidx , GL_POSITION , data ) ;
glLightf ( lidx , GL_SPOT_EXPONENT , light . Falloff ) ;
glLightf ( lidx , GL_SPOT_CUTOFF , light . OuterCone ) ;
break ;
case video : : ELT_POINT :
// set position
data [ 0 ] = light . Position . X ;
data [ 1 ] = light . Position . Y ;
data [ 2 ] = light . Position . Z ;
data [ 3 ] = 1.0f ; // 1.0f for positional light
glLightfv ( lidx , GL_POSITION , data ) ;
glLightf ( lidx , GL_SPOT_EXPONENT , 0.0f ) ;
glLightf ( lidx , GL_SPOT_CUTOFF , 180.0f ) ;
break ;
case video : : ELT_DIRECTIONAL :
// set direction
data [ 0 ] = - light . Direction . X ;
data [ 1 ] = - light . Direction . Y ;
data [ 2 ] = - light . Direction . Z ;
data [ 3 ] = 0.0f ; // 0.0f for directional light
glLightfv ( lidx , GL_POSITION , data ) ;
glLightf ( lidx , GL_SPOT_EXPONENT , 0.0f ) ;
glLightf ( lidx , GL_SPOT_CUTOFF , 180.0f ) ;
break ;
2014-05-15 04:42:49 -07:00
case video : : ELT_COUNT :
return ;
2008-10-28 09:46:13 -07:00
}
// set diffuse color
data [ 0 ] = light . DiffuseColor . r ;
data [ 1 ] = light . DiffuseColor . g ;
data [ 2 ] = light . DiffuseColor . b ;
data [ 3 ] = light . DiffuseColor . a ;
glLightfv ( lidx , GL_DIFFUSE , data ) ;
// set specular color
data [ 0 ] = light . SpecularColor . r ;
data [ 1 ] = light . SpecularColor . g ;
data [ 2 ] = light . SpecularColor . b ;
data [ 3 ] = light . SpecularColor . a ;
glLightfv ( lidx , GL_SPECULAR , data ) ;
// set ambient color
data [ 0 ] = light . AmbientColor . r ;
data [ 1 ] = light . AmbientColor . g ;
data [ 2 ] = light . AmbientColor . b ;
data [ 3 ] = light . AmbientColor . a ;
glLightfv ( lidx , GL_AMBIENT , data ) ;
// 1.0f / (constant + linear * d + quadratic*(d*d);
// set attenuation
glLightf ( lidx , GL_CONSTANT_ATTENUATION , light . Attenuation . X ) ;
glLightf ( lidx , GL_LINEAR_ATTENUATION , light . Attenuation . Y ) ;
glLightf ( lidx , GL_QUADRATIC_ATTENUATION , light . Attenuation . Z ) ;
glEnable ( lidx ) ;
}
2009-01-27 05:45:17 -08:00
//! Turns a dynamic light on or off
//! \param lightIndex: the index returned by addDynamicLight
//! \param turnOn: true to turn the light on, false to turn it off
void COGLES1Driver : : turnLightOn ( s32 lightIndex , bool turnOn )
{
if ( lightIndex < 0 | | lightIndex > = ( s32 ) RequestedLights . size ( ) )
return ;
RequestedLight & requestedLight = RequestedLights [ lightIndex ] ;
requestedLight . DesireToBeOn = turnOn ;
if ( turnOn )
{
if ( - 1 = = requestedLight . HardwareLightIndex )
assignHardwareLight ( lightIndex ) ;
}
else
{
if ( - 1 ! = requestedLight . HardwareLightIndex )
{
// It's currently assigned, so free up the hardware light
glDisable ( requestedLight . HardwareLightIndex ) ;
requestedLight . HardwareLightIndex = - 1 ;
// Now let the first light that's waiting on a free hardware light grab it
for ( u32 requested = 0 ; requested < RequestedLights . size ( ) ; + + requested )
if ( RequestedLights [ requested ] . DesireToBeOn
& &
- 1 = = RequestedLights [ requested ] . HardwareLightIndex )
{
assignHardwareLight ( requested ) ;
break ;
}
}
}
}
2008-10-28 09:46:13 -07:00
//! returns the maximal amount of dynamic lights the device can handle
2008-11-12 15:04:00 -08:00
u32 COGLES1Driver : : getMaximalDynamicLightAmount ( ) const
2008-10-28 09:46:13 -07:00
{
return MaxLights ;
}
2008-11-12 15:04:00 -08:00
//! Sets the dynamic ambient light color.
void COGLES1Driver : : setAmbientLight ( const SColorf & color )
2008-10-28 09:46:13 -07:00
{
2014-09-24 16:51:06 -07:00
CNullDriver : : setAmbientLight ( color ) ;
2008-10-28 09:46:13 -07:00
GLfloat data [ 4 ] = { color . r , color . g , color . b , color . a } ;
glLightModelfv ( GL_LIGHT_MODEL_AMBIENT , data ) ;
}
2008-11-12 15:04:00 -08:00
// this code was sent in by Oliver Klems, thank you
void COGLES1Driver : : setViewPort ( const core : : rect < s32 > & area )
2008-10-28 09:46:13 -07:00
{
core : : rect < s32 > vp = area ;
core : : rect < s32 > rendert ( 0 , 0 , getCurrentRenderTargetSize ( ) . Width , getCurrentRenderTargetSize ( ) . Height ) ;
vp . clipAgainst ( rendert ) ;
if ( vp . getHeight ( ) > 0 & & vp . getWidth ( ) > 0 )
glViewport ( vp . UpperLeftCorner . X ,
getCurrentRenderTargetSize ( ) . Height - vp . UpperLeftCorner . Y - vp . getHeight ( ) ,
vp . getWidth ( ) , vp . getHeight ( ) ) ;
ViewPort = vp ;
}
2008-11-12 15:04:00 -08:00
//! Draws a shadow volume into the stencil buffer.
2014-07-23 12:08:16 -07:00
void COGLES1Driver : : drawStencilShadowVolume ( const core : : array < core : : vector3df > & triangles , bool zfail , u32 debugDataVisible )
2008-10-28 09:46:13 -07:00
{
2014-07-23 12:08:16 -07:00
const u32 count = triangles . size ( ) ;
2008-10-28 09:46:13 -07:00
if ( ! StencilBuffer | | ! count )
return ;
2014-07-23 12:08:16 -07:00
u8 colorMask = LastMaterial . ColorMask ;
2008-11-12 15:04:00 -08:00
const GLboolean lightingEnabled = glIsEnabled ( GL_LIGHTING ) ;
const GLboolean fogEnabled = glIsEnabled ( GL_FOG ) ;
const GLboolean cullFaceEnabled = glIsEnabled ( GL_CULL_FACE ) ;
2014-07-23 12:08:16 -07:00
GLint cullFaceMode = 0 ;
2008-10-28 09:46:13 -07:00
glGetIntegerv ( GL_CULL_FACE_MODE , & cullFaceMode ) ;
2014-07-23 12:08:16 -07:00
GLint depthFunc = 0 ;
2008-10-28 09:46:13 -07:00
glGetIntegerv ( GL_DEPTH_FUNC , & depthFunc ) ;
2014-07-23 12:08:16 -07:00
GLboolean depthMask = 0 ;
2008-10-28 09:46:13 -07:00
glGetBooleanv ( GL_DEPTH_WRITEMASK , & depthMask ) ;
glDisable ( GL_LIGHTING ) ;
glDisable ( GL_FOG ) ;
glDepthFunc ( GL_LEQUAL ) ;
2014-07-23 12:08:16 -07:00
glDepthMask ( GL_FALSE ) ;
if ( ! ( debugDataVisible & ( scene : : EDS_SKELETON | scene : : EDS_MESH_WIRE_OVERLAY ) ) )
{
glColorMask ( GL_FALSE , GL_FALSE , GL_FALSE , GL_FALSE ) ;
glEnable ( GL_STENCIL_TEST ) ;
}
2008-10-28 09:46:13 -07:00
glEnableClientState ( GL_VERTEX_ARRAY ) ;
2014-07-23 12:08:16 -07:00
glVertexPointer ( 3 , GL_FLOAT , sizeof ( core : : vector3df ) , triangles . const_pointer ( ) ) ;
2008-10-28 09:46:13 -07:00
glStencilMask ( ~ 0 ) ;
glStencilFunc ( GL_ALWAYS , 0 , ~ 0 ) ;
2009-05-11 05:20:23 -07:00
GLenum decr = GL_DECR ;
GLenum incr = GL_INCR ;
2014-07-23 12:08:16 -07:00
2009-05-11 05:26:40 -07:00
# if defined(GL_OES_stencil_wrap)
2009-05-11 05:20:23 -07:00
if ( FeatureAvailable [ IRR_OES_stencil_wrap ] )
{
decr = GL_DECR_WRAP_OES ;
incr = GL_INCR_WRAP_OES ;
2008-10-28 09:46:13 -07:00
}
# endif
2014-07-23 12:08:16 -07:00
2009-05-11 05:20:23 -07:00
glEnable ( GL_CULL_FACE ) ;
2014-07-23 12:08:16 -07:00
if ( zfail )
2008-10-28 09:46:13 -07:00
{
2014-07-23 12:08:16 -07:00
glCullFace ( GL_FRONT ) ;
glStencilOp ( GL_KEEP , incr , GL_KEEP ) ;
glDrawArrays ( GL_TRIANGLES , 0 , count ) ;
2008-10-28 09:46:13 -07:00
2014-07-23 12:08:16 -07:00
glCullFace ( GL_BACK ) ;
glStencilOp ( GL_KEEP , decr , GL_KEEP ) ;
glDrawArrays ( GL_TRIANGLES , 0 , count ) ;
}
else // zpass
{
2009-05-11 05:20:23 -07:00
glCullFace ( GL_BACK ) ;
glStencilOp ( GL_KEEP , GL_KEEP , incr ) ;
2014-07-23 12:08:16 -07:00
glDrawArrays ( GL_TRIANGLES , 0 , count ) ;
2008-10-28 09:46:13 -07:00
2009-05-11 05:20:23 -07:00
glCullFace ( GL_FRONT ) ;
glStencilOp ( GL_KEEP , GL_KEEP , decr ) ;
2014-07-23 12:08:16 -07:00
glDrawArrays ( GL_TRIANGLES , 0 , count ) ;
2008-10-28 09:46:13 -07:00
}
2014-07-23 12:08:16 -07:00
glDisableClientState ( GL_VERTEX_ARRAY ) ;
2008-10-28 09:46:13 -07:00
2014-07-23 12:08:16 -07:00
glColorMask ( ( colorMask & ECP_RED ) ? GL_TRUE : GL_FALSE ,
( colorMask & ECP_GREEN ) ? GL_TRUE : GL_FALSE ,
( colorMask & ECP_BLUE ) ? GL_TRUE : GL_FALSE ,
( colorMask & ECP_ALPHA ) ? GL_TRUE : GL_FALSE ) ;
2008-10-28 09:46:13 -07:00
glDisable ( GL_STENCIL_TEST ) ;
2014-07-23 12:08:16 -07:00
2008-10-28 09:46:13 -07:00
if ( lightingEnabled )
glEnable ( GL_LIGHTING ) ;
2014-07-23 12:08:16 -07:00
2008-10-28 09:46:13 -07:00
if ( fogEnabled )
glEnable ( GL_FOG ) ;
2014-07-23 12:08:16 -07:00
2008-10-28 09:46:13 -07:00
if ( cullFaceEnabled )
glEnable ( GL_CULL_FACE ) ;
else
glDisable ( GL_CULL_FACE ) ;
2014-07-23 12:08:16 -07:00
2008-10-28 09:46:13 -07:00
glCullFace ( cullFaceMode ) ;
glDepthFunc ( depthFunc ) ;
glDepthMask ( depthMask ) ;
}
2014-07-23 12:08:16 -07:00
void COGLES1Driver : : drawStencilShadow ( bool clearStencilBuffer ,
video : : SColor leftUpEdge , video : : SColor rightUpEdge ,
video : : SColor leftDownEdge , video : : SColor rightDownEdge )
2008-10-28 09:46:13 -07:00
{
if ( ! StencilBuffer )
return ;
disableTextures ( ) ;
2014-07-23 12:08:16 -07:00
u8 colorMask = LastMaterial . ColorMask ;
2008-11-12 15:04:00 -08:00
const GLboolean lightingEnabled = glIsEnabled ( GL_LIGHTING ) ;
const GLboolean fogEnabled = glIsEnabled ( GL_FOG ) ;
2014-07-23 12:08:16 -07:00
const GLboolean blendEnabled = glIsEnabled ( GL_BLEND ) ;
GLboolean depthMask = 0 ;
2008-10-28 09:46:13 -07:00
glGetBooleanv ( GL_DEPTH_WRITEMASK , & depthMask ) ;
2014-07-23 12:08:16 -07:00
GLint shadeModel = 0 ;
2008-10-28 09:46:13 -07:00
glGetIntegerv ( GL_SHADE_MODEL , & shadeModel ) ;
2014-07-23 12:08:16 -07:00
GLint blendSrc = 0 , blendDst = 0 ;
2008-10-28 09:46:13 -07:00
glGetIntegerv ( GL_BLEND_SRC , & blendSrc ) ;
glGetIntegerv ( GL_BLEND_DST , & blendDst ) ;
2014-07-23 12:08:16 -07:00
glDisable ( GL_LIGHTING ) ;
2008-10-28 09:46:13 -07:00
glDisable ( GL_FOG ) ;
glDepthMask ( GL_FALSE ) ;
2014-07-23 12:08:16 -07:00
glShadeModel ( GL_FLAT ) ;
glColorMask ( GL_TRUE , GL_TRUE , GL_TRUE , GL_TRUE ) ;
2008-10-28 09:46:13 -07:00
glEnable ( GL_BLEND ) ;
glBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ;
2014-07-23 12:08:16 -07:00
glEnable ( GL_STENCIL_TEST ) ;
2008-10-28 09:46:13 -07:00
glStencilFunc ( GL_NOTEQUAL , 0 , ~ 0 ) ;
glStencilOp ( GL_KEEP , GL_KEEP , GL_KEEP ) ;
glMatrixMode ( GL_MODELVIEW ) ;
glPushMatrix ( ) ;
glLoadIdentity ( ) ;
2009-05-05 15:27:24 -07:00
glMatrixMode ( GL_PROJECTION ) ;
glPushMatrix ( ) ;
glLoadIdentity ( ) ;
2008-10-28 09:46:13 -07:00
2014-07-23 12:08:16 -07:00
u16 indices [ ] = { 0 , 1 , 2 , 3 } ;
2008-10-28 09:46:13 -07:00
S3DVertex vertices [ 4 ] ;
2014-07-23 12:08:16 -07:00
vertices [ 0 ] = S3DVertex ( - 1.f , 1.f , 0.9f , 0 , 0 , 1 , leftDownEdge , 0 , 0 ) ;
vertices [ 1 ] = S3DVertex ( 1.f , 1.f , 0.9f , 0 , 0 , 1 , leftUpEdge , 0 , 0 ) ;
vertices [ 2 ] = S3DVertex ( 1.f , - 1.f , 0.9f , 0 , 0 , 1 , rightUpEdge , 0 , 0 ) ;
vertices [ 3 ] = S3DVertex ( - 1.f , - 1.f , 0.9f , 0 , 0 , 1 , rightDownEdge , 0 , 0 ) ;
drawVertexPrimitiveList2d3d ( vertices , 4 , indices , 2 , EVT_STANDARD , scene : : EPT_TRIANGLE_FAN , EIT_16BIT , false ) ;
2008-10-28 09:46:13 -07:00
if ( clearStencilBuffer )
glClear ( GL_STENCIL_BUFFER_BIT ) ;
2014-07-23 12:08:16 -07:00
glColorMask ( ( colorMask & ECP_RED ) ? GL_TRUE : GL_FALSE ,
( colorMask & ECP_GREEN ) ? GL_TRUE : GL_FALSE ,
( colorMask & ECP_BLUE ) ? GL_TRUE : GL_FALSE ,
( colorMask & ECP_ALPHA ) ? GL_TRUE : GL_FALSE ) ;
glDisable ( GL_STENCIL_TEST ) ;
2008-10-28 09:46:13 -07:00
glPopMatrix ( ) ;
2009-05-05 15:27:24 -07:00
glMatrixMode ( GL_MODELVIEW ) ;
glPopMatrix ( ) ;
2014-07-23 12:08:16 -07:00
2008-10-28 09:46:13 -07:00
if ( lightingEnabled )
glEnable ( GL_LIGHTING ) ;
2014-07-23 12:08:16 -07:00
2008-10-28 09:46:13 -07:00
if ( fogEnabled )
glEnable ( GL_FOG ) ;
2014-07-23 12:08:16 -07:00
2008-10-28 09:46:13 -07:00
if ( ! blendEnabled )
glDisable ( GL_BLEND ) ;
2014-07-23 12:08:16 -07:00
glDepthMask ( depthMask ) ;
glShadeModel ( shadeModel ) ;
2008-10-28 09:46:13 -07:00
glBlendFunc ( blendSrc , blendDst ) ;
}
//! Sets the fog mode.
2009-10-01 10:00:20 -07:00
void COGLES1Driver : : setFog ( SColor c , E_FOG_TYPE fogType , f32 start ,
2008-10-28 09:46:13 -07:00
f32 end , f32 density , bool pixelFog , bool rangeFog )
{
2009-10-01 10:00:20 -07:00
CNullDriver : : setFog ( c , fogType , start , end , density , pixelFog , rangeFog ) ;
2008-10-28 09:46:13 -07:00
2009-10-01 10:00:20 -07:00
glFogf ( GL_FOG_MODE , GLfloat ( ( fogType = = EFT_FOG_LINEAR ) ? GL_LINEAR : ( fogType = = EFT_FOG_EXP ) ? GL_EXP : GL_EXP2 ) ) ;
# ifdef GL_EXT_fog_coord
if ( FeatureAvailable [ IRR_EXT_fog_coord ] )
2008-10-28 09:46:13 -07:00
glFogi ( GL_FOG_COORDINATE_SOURCE , GL_FRAGMENT_DEPTH ) ;
# endif
2009-10-01 10:00:20 -07:00
if ( fogType = = EFT_FOG_LINEAR )
2008-10-28 09:46:13 -07:00
{
glFogf ( GL_FOG_START , start ) ;
glFogf ( GL_FOG_END , end ) ;
}
else
glFogf ( GL_FOG_DENSITY , density ) ;
if ( pixelFog )
glHint ( GL_FOG_HINT , GL_NICEST ) ;
else
glHint ( GL_FOG_HINT , GL_FASTEST ) ;
SColorf color ( c ) ;
GLfloat data [ 4 ] = { color . r , color . g , color . b , color . a } ;
glFogfv ( GL_FOG_COLOR , data ) ;
}
//! Draws a 3d line.
2008-11-12 15:04:00 -08:00
void COGLES1Driver : : draw3DLine ( const core : : vector3df & start ,
2008-10-28 09:46:13 -07:00
const core : : vector3df & end , SColor color )
{
setRenderStates3DMode ( ) ;
u16 indices [ ] = { 0 , 1 } ;
S3DVertex vertices [ 2 ] ;
vertices [ 0 ] = S3DVertex ( start . X , start . Y , start . Z , 0 , 0 , 1 , color , 0 , 0 ) ;
vertices [ 1 ] = S3DVertex ( end . X , end . Y , end . Z , 0 , 0 , 1 , color , 0 , 0 ) ;
2009-05-07 10:05:05 -07:00
drawVertexPrimitiveList2d3d ( vertices , 2 , indices , 1 , video : : EVT_STANDARD , scene : : EPT_LINES ) ;
2008-10-28 09:46:13 -07:00
}
//! Only used by the internal engine. Used to notify the driver that
//! the window was resized.
2009-01-27 05:45:17 -08:00
void COGLES1Driver : : OnResize ( const core : : dimension2d < u32 > & size )
2008-10-28 09:46:13 -07:00
{
CNullDriver : : OnResize ( size ) ;
glViewport ( 0 , 0 , size . Width , size . Height ) ;
}
//! Returns type of video driver
2008-11-12 15:04:00 -08:00
E_DRIVER_TYPE COGLES1Driver : : getDriverType ( ) const
2008-10-28 09:46:13 -07:00
{
return EDT_OGLES1 ;
}
//! returns color format
2008-11-12 15:04:00 -08:00
ECOLOR_FORMAT COGLES1Driver : : getColorFormat ( ) const
2008-10-28 09:46:13 -07:00
{
return ColorFormat ;
}
2013-04-05 05:53:10 -07:00
//! Get a vertex shader constant index.
s32 COGLES1Driver : : getVertexShaderConstantID ( const c8 * name )
{
return getPixelShaderConstantID ( name ) ;
}
//! Get a pixel shader constant index.
s32 COGLES1Driver : : getPixelShaderConstantID ( const c8 * name )
{
2014-05-15 03:13:14 -07:00
os : : Printer : : log ( " Error: Please use IMaterialRendererServices from IShaderConstantSetCallBack::OnSetConstants not VideoDriver->getPixelShaderConstantID(). " ) ;
2013-04-05 05:53:10 -07:00
return - 1 ;
}
//! Sets a constant for the vertex shader based on an index.
bool COGLES1Driver : : setVertexShaderConstant ( s32 index , const f32 * floats , int count )
{
//pass this along, as in GLSL the same routine is used for both vertex and fragment shaders
return setPixelShaderConstant ( index , floats , count ) ;
}
//! Int interface for the above.
bool COGLES1Driver : : setVertexShaderConstant ( s32 index , const s32 * ints , int count )
{
return setPixelShaderConstant ( index , ints , count ) ;
}
//! Sets a constant for the pixel shader based on an index.
bool COGLES1Driver : : setPixelShaderConstant ( s32 index , const f32 * floats , int count )
{
2014-05-15 03:13:14 -07:00
os : : Printer : : log ( " Error: Please use IMaterialRendererServices from IShaderConstantSetCallBack::OnSetConstants not VideoDriver->setPixelShaderConstant(). " ) ;
2013-04-05 05:53:10 -07:00
return false ;
}
//! Int interface for the above.
bool COGLES1Driver : : setPixelShaderConstant ( s32 index , const s32 * ints , int count )
{
2014-05-15 03:13:14 -07:00
os : : Printer : : log ( " Error: Please use IMaterialRendererServices from IShaderConstantSetCallBack::OnSetConstants not VideoDriver->setPixelShaderConstant(). " ) ;
2013-04-05 05:53:10 -07:00
return false ;
}
2008-10-28 09:46:13 -07:00
//! Sets a vertex shader constant.
2008-11-12 15:04:00 -08:00
void COGLES1Driver : : setVertexShaderConstant ( const f32 * data , s32 startRegister , s32 constantAmount )
2008-10-28 09:46:13 -07:00
{
# ifdef GL_vertex_program
for ( s32 i = 0 ; i < constantAmount ; + + i )
extGlProgramLocalParameter4fv ( GL_VERTEX_PROGRAM , startRegister + i , & data [ i * 4 ] ) ;
# endif
}
//! Sets a pixel shader constant.
2008-11-12 15:04:00 -08:00
void COGLES1Driver : : setPixelShaderConstant ( const f32 * data , s32 startRegister , s32 constantAmount )
2008-10-28 09:46:13 -07:00
{
# ifdef GL_fragment_program
for ( s32 i = 0 ; i < constantAmount ; + + i )
extGlProgramLocalParameter4fv ( GL_FRAGMENT_PROGRAM , startRegister + i , & data [ i * 4 ] ) ;
# endif
}
//! Adds a new material renderer to the VideoDriver, using pixel and/or
//! vertex shaders to render geometry.
2008-11-12 15:04:00 -08:00
s32 COGLES1Driver : : addShaderMaterial ( const c8 * vertexShaderProgram ,
2008-10-28 09:46:13 -07:00
const c8 * pixelShaderProgram ,
IShaderConstantSetCallBack * callback ,
E_MATERIAL_TYPE baseMaterial , s32 userData )
{
2008-11-12 15:04:00 -08:00
os : : Printer : : log ( " No shader support. " ) ;
return - 1 ;
2008-10-28 09:46:13 -07:00
}
//! Adds a new material renderer to the VideoDriver, using GLSL to render geometry.
2008-11-12 15:04:00 -08:00
s32 COGLES1Driver : : addHighLevelShaderMaterial (
2008-10-28 09:46:13 -07:00
const c8 * vertexShaderProgram ,
const c8 * vertexShaderEntryPointName ,
E_VERTEX_SHADER_TYPE vsCompileTarget ,
const c8 * pixelShaderProgram ,
const c8 * pixelShaderEntryPointName ,
E_PIXEL_SHADER_TYPE psCompileTarget ,
IShaderConstantSetCallBack * callback ,
E_MATERIAL_TYPE baseMaterial ,
s32 userData )
{
2008-11-12 15:04:00 -08:00
os : : Printer : : log ( " No shader support. " ) ;
return - 1 ;
2008-10-28 09:46:13 -07:00
}
//! Returns a pointer to the IVideoDriver interface. (Implementation for
//! IMaterialRendererServices)
2008-11-12 15:04:00 -08:00
IVideoDriver * COGLES1Driver : : getVideoDriver ( )
2008-10-28 09:46:13 -07:00
{
return this ;
}
//! Returns pointer to the IGPUProgrammingServices interface.
2008-11-12 15:04:00 -08:00
IGPUProgrammingServices * COGLES1Driver : : getGPUProgrammingServices ( )
2008-10-28 09:46:13 -07:00
{
return this ;
}
2009-10-01 10:00:20 -07:00
ITexture * COGLES1Driver : : addRenderTargetTexture ( const core : : dimension2d < u32 > & size ,
const io : : path & name ,
const ECOLOR_FORMAT format )
2008-10-28 09:46:13 -07:00
{
//disable mip-mapping
2008-12-28 06:35:16 -08:00
const bool generateMipLevels = getTextureCreationFlag ( ETCF_CREATE_MIP_MAPS ) ;
2008-10-28 09:46:13 -07:00
setTextureCreationFlag ( ETCF_CREATE_MIP_MAPS , false ) ;
video : : ITexture * rtt = 0 ;
2008-12-28 06:35:16 -08:00
# if defined(GL_OES_framebuffer_object)
// if driver supports FrameBufferObjects, use them
if ( queryFeature ( EVDF_FRAMEBUFFER_OBJECT ) )
2008-10-28 09:46:13 -07:00
{
2009-10-01 10:00:20 -07:00
rtt = new COGLES1FBOTexture ( size , name , this , format ) ;
2008-12-28 06:35:16 -08:00
if ( rtt )
{
2014-05-22 10:07:49 -07:00
bool success = false ;
2008-12-28 06:35:16 -08:00
addTexture ( rtt ) ;
2014-05-22 10:07:49 -07:00
2008-12-28 06:35:16 -08:00
ITexture * tex = createDepthTexture ( rtt ) ;
if ( tex )
{
2014-05-22 10:07:49 -07:00
success = static_cast < video : : COGLES1FBODepthTexture * > ( tex ) - > attach ( rtt ) ;
if ( ! success )
{
removeDepthTexture ( tex ) ;
}
2008-12-28 06:35:16 -08:00
tex - > drop ( ) ;
}
rtt - > drop ( ) ;
2014-05-22 10:07:49 -07:00
if ( ! success )
{
removeTexture ( rtt ) ;
rtt = 0 ;
}
2008-12-28 06:35:16 -08:00
}
}
else
# endif
{
// the simple texture is only possible for size <= screensize
// we try to find an optimal size with the original constraints
2009-01-27 05:45:17 -08:00
core : : dimension2du destSize ( core : : min_ ( size . Width , ScreenSize . Width ) , core : : min_ ( size . Height , ScreenSize . Height ) ) ;
2008-12-28 06:35:16 -08:00
destSize = destSize . getOptimalSize ( ( size = = size . getOptimalSize ( ) ) , false , false ) ;
rtt = addTexture ( destSize , name , ECF_A8R8G8B8 ) ;
if ( rtt )
static_cast < video : : COGLES1Texture * > ( rtt ) - > setIsRenderTarget ( true ) ;
2008-10-28 09:46:13 -07:00
}
//restore mip-mapping
setTextureCreationFlag ( ETCF_CREATE_MIP_MAPS , generateMipLevels ) ;
return rtt ;
}
2008-11-12 15:04:00 -08:00
//! Returns the maximum amount of primitives
u32 COGLES1Driver : : getMaximalPrimitiveCount ( ) const
2008-10-28 09:46:13 -07:00
{
2009-01-02 03:11:50 -08:00
return 65535 ;
2008-10-28 09:46:13 -07:00
}
//! set or reset render target
2008-11-12 15:04:00 -08:00
bool COGLES1Driver : : setRenderTarget ( video : : ITexture * texture , bool clearBackBuffer ,
2008-10-28 09:46:13 -07:00
bool clearZBuffer , SColor color )
{
// check for right driver type
if ( texture & & texture - > getDriverType ( ) ! = EDT_OGLES1 )
{
os : : Printer : : log ( " Fatal Error: Tried to set a texture not owned by this driver. " , ELL_ERROR ) ;
return false ;
}
// check if we should set the previous RT back
2011-06-03 04:32:53 -07:00
setActiveTexture ( 0 , 0 ) ;
2008-10-28 09:46:13 -07:00
ResetRenderStates = true ;
if ( RenderTargetTexture ! = 0 )
{
RenderTargetTexture - > unbindRTT ( ) ;
}
if ( texture )
{
// we want to set a new target. so do this.
2008-11-12 15:04:00 -08:00
RenderTargetTexture = static_cast < COGLES1Texture * > ( texture ) ;
2008-10-28 09:46:13 -07:00
RenderTargetTexture - > bindRTT ( ) ;
CurrentRendertargetSize = texture - > getSize ( ) ;
}
else
{
glViewport ( 0 , 0 , ScreenSize . Width , ScreenSize . Height ) ;
RenderTargetTexture = 0 ;
2009-01-27 05:45:17 -08:00
CurrentRendertargetSize = core : : dimension2d < u32 > ( 0 , 0 ) ;
2008-10-28 09:46:13 -07:00
}
GLbitfield mask = 0 ;
if ( clearBackBuffer )
{
2014-05-25 08:34:18 -07:00
glColorMask ( GL_TRUE , GL_TRUE , GL_TRUE , GL_TRUE ) ;
Material . ColorMask = ECP_ALL ;
2008-10-28 09:46:13 -07:00
const f32 inv = 1.0f / 255.0f ;
glClearColor ( color . getRed ( ) * inv , color . getGreen ( ) * inv ,
color . getBlue ( ) * inv , color . getAlpha ( ) * inv ) ;
mask | = GL_COLOR_BUFFER_BIT ;
}
if ( clearZBuffer )
{
glDepthMask ( GL_TRUE ) ;
2014-05-25 08:34:18 -07:00
Material . ZWriteEnable = true ;
2008-10-28 09:46:13 -07:00
mask | = GL_DEPTH_BUFFER_BIT ;
}
glClear ( mask ) ;
return true ;
}
// returns the current size of the screen or rendertarget
2009-01-27 05:45:17 -08:00
const core : : dimension2d < u32 > & COGLES1Driver : : getCurrentRenderTargetSize ( ) const
2008-10-28 09:46:13 -07:00
{
if ( CurrentRendertargetSize . Width = = 0 )
return ScreenSize ;
else
return CurrentRendertargetSize ;
}
//! Clears the ZBuffer.
2008-11-12 15:04:00 -08:00
void COGLES1Driver : : clearZBuffer ( )
2008-10-28 09:46:13 -07:00
{
glDepthMask ( GL_TRUE ) ;
2014-05-25 08:34:18 -07:00
Material . ZWriteEnable = true ;
2008-10-28 09:46:13 -07:00
2014-05-25 08:34:18 -07:00
glClear ( GL_DEPTH_BUFFER_BIT ) ;
2008-10-28 09:46:13 -07:00
}
//! Returns an image created from the last rendered frame.
2009-01-02 03:11:50 -08:00
// We want to read the front buffer to get the latest render finished.
2009-05-07 02:34:53 -07:00
// This is not possible under ogl-es, though, so one has to call this method
2009-01-02 03:11:50 -08:00
// outside of the render loop only.
2011-06-09 01:47:45 -07:00
IImage * COGLES1Driver : : createScreenShot ( video : : ECOLOR_FORMAT format , video : : E_RENDER_TARGET target )
2008-10-28 09:46:13 -07:00
{
2011-06-09 01:47:45 -07:00
if ( target = = video : : ERT_MULTI_RENDER_TEXTURES | | target = = video : : ERT_RENDER_TEXTURE | | target = = video : : ERT_STEREO_BOTH_BUFFERS )
return 0 ;
2011-06-09 07:53:26 -07:00
GLint internalformat = GL_RGBA ;
GLint type = GL_UNSIGNED_BYTE ;
if ( false & & ( FeatureAvailable [ IRR_IMG_read_format ] | | FeatureAvailable [ IRR_OES_read_format ] | | FeatureAvailable [ IRR_EXT_read_format_bgra ] ) )
2008-11-27 08:02:09 -08:00
{
# ifdef GL_IMPLEMENTATION_COLOR_READ_TYPE_OES
2011-06-09 07:53:26 -07:00
glGetIntegerv ( GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES , & internalformat ) ;
2008-11-27 08:02:09 -08:00
glGetIntegerv ( GL_IMPLEMENTATION_COLOR_READ_TYPE_OES , & type ) ;
# endif
2009-11-20 05:21:33 -08:00
// there are formats we don't support ATM
2008-11-27 08:02:09 -08:00
if ( GL_UNSIGNED_SHORT_4_4_4_4 = = type )
type = GL_UNSIGNED_SHORT_5_5_5_1 ;
2009-11-20 08:24:11 -08:00
# ifdef GL_EXT_read_format_bgra
2009-11-20 05:21:33 -08:00
else if ( GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT = = type )
type = GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT ;
2009-11-20 08:24:11 -08:00
# endif
2008-11-27 08:02:09 -08:00
}
IImage * newImage = 0 ;
2011-06-09 01:47:45 -07:00
if ( ( GL_RGBA = = internalformat )
2009-11-20 08:24:11 -08:00
# ifdef GL_EXT_read_format_bgra
2011-06-09 01:47:45 -07:00
| | ( GL_BGRA_EXT = = internalformat )
2009-11-20 08:24:11 -08:00
# endif
)
2008-11-27 08:02:09 -08:00
{
if ( GL_UNSIGNED_BYTE = = type )
newImage = new CImage ( ECF_A8R8G8B8 , ScreenSize ) ;
else
newImage = new CImage ( ECF_A1R5G5B5 , ScreenSize ) ;
}
else
{
if ( GL_UNSIGNED_BYTE = = type )
newImage = new CImage ( ECF_R8G8B8 , ScreenSize ) ;
else
newImage = new CImage ( ECF_R5G6B5 , ScreenSize ) ;
}
2008-10-28 09:46:13 -07:00
u8 * pixels = static_cast < u8 * > ( newImage - > lock ( ) ) ;
if ( ! pixels )
{
newImage - > drop ( ) ;
return 0 ;
}
2011-06-09 01:47:45 -07:00
glReadPixels ( 0 , 0 , ScreenSize . Width , ScreenSize . Height , internalformat , type , pixels ) ;
2008-10-28 09:46:13 -07:00
2008-11-12 15:04:00 -08:00
// opengl images are horizontally flipped, so we have to fix that here.
const s32 pitch = newImage - > getPitch ( ) ;
u8 * p2 = pixels + ( ScreenSize . Height - 1 ) * pitch ;
u8 * tmpBuffer = new u8 [ pitch ] ;
2009-01-27 05:45:17 -08:00
for ( u32 i = 0 ; i < ScreenSize . Height ; i + = 2 )
2008-10-28 09:46:13 -07:00
{
2008-11-12 15:04:00 -08:00
memcpy ( tmpBuffer , pixels , pitch ) ;
memcpy ( pixels , p2 , pitch ) ;
memcpy ( p2 , tmpBuffer , pitch ) ;
pixels + = pitch ;
p2 - = pitch ;
2008-10-28 09:46:13 -07:00
}
2008-11-12 15:04:00 -08:00
delete [ ] tmpBuffer ;
2008-10-28 09:46:13 -07:00
newImage - > unlock ( ) ;
if ( testGLError ( ) )
{
newImage - > drop ( ) ;
return 0 ;
}
return newImage ;
}
2008-12-28 06:35:16 -08:00
//! get depth texture for the given render target texture
ITexture * COGLES1Driver : : createDepthTexture ( ITexture * texture , bool shared )
{
if ( ( texture - > getDriverType ( ) ! = EDT_OGLES1 ) | | ( ! texture - > isRenderTarget ( ) ) )
return 0 ;
COGLES1Texture * tex = static_cast < COGLES1Texture * > ( texture ) ;
if ( ! tex - > isFrameBufferObject ( ) )
return 0 ;
if ( shared )
{
for ( u32 i = 0 ; i < DepthTextures . size ( ) ; + + i )
{
if ( DepthTextures [ i ] - > getSize ( ) = = texture - > getSize ( ) )
{
DepthTextures [ i ] - > grab ( ) ;
return DepthTextures [ i ] ;
}
}
DepthTextures . push_back ( new COGLES1FBODepthTexture ( texture - > getSize ( ) , " depth1 " , this ) ) ;
return DepthTextures . getLast ( ) ;
}
return ( new COGLES1FBODepthTexture ( texture - > getSize ( ) , " depth1 " , this ) ) ;
}
void COGLES1Driver : : removeDepthTexture ( ITexture * texture )
{
for ( u32 i = 0 ; i < DepthTextures . size ( ) ; + + i )
{
if ( texture = = DepthTextures [ i ] )
{
DepthTextures . erase ( i ) ;
return ;
}
}
}
2014-05-22 10:07:49 -07:00
void COGLES1Driver : : removeTexture ( ITexture * texture )
{
if ( ! texture )
return ;
CNullDriver : : removeTexture ( texture ) ;
CurrentTexture . remove ( texture ) ;
}
2008-10-28 09:46:13 -07:00
//! Set/unset a clipping plane.
2008-11-12 15:04:00 -08:00
bool COGLES1Driver : : setClipPlane ( u32 index , const core : : plane3df & plane , bool enable )
2008-10-28 09:46:13 -07:00
{
if ( index > = MaxUserClipPlanes )
return false ;
UserClipPlane [ index ] = plane ;
enableClipPlane ( index , enable ) ;
return true ;
}
2008-11-12 15:04:00 -08:00
void COGLES1Driver : : uploadClipPlane ( u32 index )
2008-10-28 09:46:13 -07:00
{
// opengl needs an array of doubles for the plane equation
float clip_plane [ 4 ] ;
clip_plane [ 0 ] = UserClipPlane [ index ] . Normal . X ;
clip_plane [ 1 ] = UserClipPlane [ index ] . Normal . Y ;
clip_plane [ 2 ] = UserClipPlane [ index ] . Normal . Z ;
clip_plane [ 3 ] = UserClipPlane [ index ] . D ;
glClipPlanef ( GL_CLIP_PLANE0 + index , clip_plane ) ;
}
//! Enable/disable a clipping plane.
2008-11-12 15:04:00 -08:00
void COGLES1Driver : : enableClipPlane ( u32 index , bool enable )
2008-10-28 09:46:13 -07:00
{
if ( index > = MaxUserClipPlanes )
return ;
if ( enable )
{
if ( ! UserClipPlaneEnabled [ index ] )
{
uploadClipPlane ( index ) ;
glEnable ( GL_CLIP_PLANE0 + index ) ;
}
}
else
glDisable ( GL_CLIP_PLANE0 + index ) ;
UserClipPlaneEnabled [ index ] = enable ;
}
2009-11-20 05:03:04 -08:00
core : : dimension2du COGLES1Driver : : getMaxTextureSize ( ) const
{
return core : : dimension2du ( MaxTextureSize , MaxTextureSize ) ;
}
2014-05-10 14:47:14 -07:00
GLenum COGLES1Driver : : getGLBlend ( E_BLEND_FACTOR factor ) const
{
GLenum r = 0 ;
switch ( factor )
{
case EBF_ZERO : r = GL_ZERO ; break ;
case EBF_ONE : r = GL_ONE ; break ;
case EBF_DST_COLOR : r = GL_DST_COLOR ; break ;
case EBF_ONE_MINUS_DST_COLOR : r = GL_ONE_MINUS_DST_COLOR ; break ;
case EBF_SRC_COLOR : r = GL_SRC_COLOR ; break ;
case EBF_ONE_MINUS_SRC_COLOR : r = GL_ONE_MINUS_SRC_COLOR ; break ;
case EBF_SRC_ALPHA : r = GL_SRC_ALPHA ; break ;
case EBF_ONE_MINUS_SRC_ALPHA : r = GL_ONE_MINUS_SRC_ALPHA ; break ;
case EBF_DST_ALPHA : r = GL_DST_ALPHA ; break ;
case EBF_ONE_MINUS_DST_ALPHA : r = GL_ONE_MINUS_DST_ALPHA ; break ;
case EBF_SRC_ALPHA_SATURATE : r = GL_SRC_ALPHA_SATURATE ; break ;
}
return r ;
}
COGLES1CallBridge * COGLES1Driver : : getBridgeCalls ( ) const
{
return BridgeCalls ;
}
COGLES1CallBridge : : COGLES1CallBridge ( COGLES1Driver * driver ) : Driver ( driver ) ,
# if defined(GL_OES_blend_subtract)
BlendEquation ( GL_FUNC_ADD_OES ) ,
# endif
BlendSourceRGB ( GL_ONE ) , BlendDestinationRGB ( GL_ZERO ) ,
BlendSourceAlpha ( GL_ONE ) , BlendDestinationAlpha ( GL_ZERO ) ,
Blend ( false )
{
// Initial OpenGL ES1.x values from specification.
if ( Driver - > queryFeature ( EVDF_BLEND_OPERATIONS ) )
{
# if defined(GL_OES_blend_subtract)
Driver - > extGlBlendEquation ( GL_FUNC_ADD_OES ) ;
# endif
}
glBlendFunc ( GL_ONE , GL_ZERO ) ;
glDisable ( GL_BLEND ) ;
}
void COGLES1CallBridge : : setBlendEquation ( GLenum mode )
{
if ( BlendEquation ! = mode )
{
Driver - > extGlBlendEquation ( mode ) ;
BlendEquation = mode ;
}
}
void COGLES1CallBridge : : setBlendFunc ( GLenum source , GLenum destination )
{
if ( BlendSourceRGB ! = source | | BlendDestinationRGB ! = destination | |
BlendSourceAlpha ! = source | | BlendDestinationAlpha ! = destination )
{
glBlendFunc ( source , destination ) ;
BlendSourceRGB = source ;
BlendDestinationRGB = destination ;
BlendSourceAlpha = source ;
BlendDestinationAlpha = destination ;
}
}
void COGLES1CallBridge : : setBlendFuncSeparate ( GLenum sourceRGB , GLenum destinationRGB , GLenum sourceAlpha , GLenum destinationAlpha )
{
if ( sourceRGB ! = sourceAlpha | | destinationRGB ! = destinationAlpha )
{
if ( BlendSourceRGB ! = sourceRGB | | BlendDestinationRGB ! = destinationRGB | |
BlendSourceAlpha ! = sourceAlpha | | BlendDestinationAlpha ! = destinationAlpha )
{
Driver - > extGlBlendFuncSeparate ( sourceRGB , destinationRGB , sourceAlpha , destinationAlpha ) ;
BlendSourceRGB = sourceRGB ;
BlendDestinationRGB = destinationRGB ;
BlendSourceAlpha = sourceAlpha ;
BlendDestinationAlpha = destinationAlpha ;
}
}
else
{
setBlendFunc ( sourceRGB , destinationRGB ) ;
}
}
void COGLES1CallBridge : : setBlend ( bool enable )
{
if ( Blend ! = enable )
{
if ( enable )
glEnable ( GL_BLEND ) ;
else
glDisable ( GL_BLEND ) ;
Blend = enable ;
}
}
2008-10-28 09:46:13 -07:00
} // end namespace
} // end namespace
# endif // _IRR_COMPILE_WITH_OGLES1_
namespace irr
{
namespace video
{
2013-10-20 13:38:20 -07:00
# ifndef _IRR_COMPILE_WITH_OGLES1_
2013-10-25 09:08:45 -07:00
class IVideoDriver ;
2013-10-26 05:13:26 -07:00
class IContextManager ;
2013-10-20 13:38:20 -07:00
# endif
2009-10-01 10:00:20 -07:00
IVideoDriver * createOGLES1Driver ( const SIrrlichtCreationParameters & params ,
2013-11-13 15:20:30 -08:00
io : : IFileSystem * io
2014-09-12 11:38:11 -07:00
# if defined(_IRR_COMPILE_WITH_X11_DEVICE_) || defined(_IRR_WINDOWS_API_) || defined(_IRR_COMPILE_WITH_ANDROID_DEVICE_) || defined(_IRR_COMPILE_WITH_FB_DEVICE_)
2013-10-25 17:02:19 -07:00
, IContextManager * contextManager
2013-10-16 23:50:30 -07:00
# elif defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_)
, CIrrDeviceIPhone * device
2008-11-12 15:04:00 -08:00
# endif
2013-10-16 23:50:30 -07:00
)
2008-10-28 09:46:13 -07:00
{
# ifdef _IRR_COMPILE_WITH_OGLES1_
2013-11-13 15:20:30 -08:00
return new COGLES1Driver ( params , io
2014-09-12 11:38:11 -07:00
# if defined(_IRR_COMPILE_WITH_X11_DEVICE_) || defined(_IRR_WINDOWS_API_) || defined(_IRR_COMPILE_WITH_ANDROID_DEVICE_) || defined(_IRR_COMPILE_WITH_FB_DEVICE_)
2013-10-25 17:02:19 -07:00
, contextManager
2013-10-16 23:50:30 -07:00
# elif defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_)
, device
# endif
) ;
2008-10-28 09:46:13 -07:00
# else
return 0 ;
# endif // _IRR_COMPILE_WITH_OGLES1_
}
2009-01-02 17:02:59 -08:00
2008-10-28 09:46:13 -07:00
} // end namespace
} // end namespace