public override void Render( RenderOperation op )
{
GLESConfig.GlCheckError( this );
base.Render( op );
IntPtr pBufferData = IntPtr.Zero;
bool multitexturing = ( _rsCapabilities.TextureUnitCount > 1 );
List<VertexElement> decl = op.vertexData.vertexDeclaration.Elements;
List<int> attribsBound = new List<int>();
for ( int i = 0; i < decl.Count; i++ )
{
VertexElement elem = decl[ i ];
if ( !op.vertexData.vertexBufferBinding.Bindings.ContainsKey( elem.Source ) )
{
continue; //skip unbound elements
}
HardwareVertexBuffer vertexBuffer = op.vertexData.vertexBufferBinding.GetBuffer( elem.Source );
if ( _rsCapabilities.HasCapability( Capabilities.VertexBuffer ) )
{
OpenGL.BindBuffer( All.ArrayBuffer, ( (GLESHardwareVertexBuffer)vertexBuffer ).BufferID );
GLESConfig.GlCheckError( this );
pBufferData = new IntPtr( elem.Offset );//VBOBufferOffset( elem.Offset );
}
else
{
pBufferData = ( (GLESDefaultHardwareVertexBuffer)vertexBuffer ).GetData( elem.Offset );
}
if ( op.vertexData.vertexStart != 0 )
{
unsafe
{
pBufferData = (IntPtr)( (byte*)pBufferData + ( op.vertexData.vertexStart * vertexBuffer.VertexSize ) );
}
}
int unit = 0;
VertexElementSemantic sem = elem.Semantic;
GLESConfig.GlCheckError( this );
// fixed-function & builtin attribute support
switch ( sem )
{
case VertexElementSemantic.Position:
OpenGL.VertexPointer( VertexElement.GetTypeCount( elem.Type ), GLESHardwareBufferManager.GetGLType( elem.Type ), VertexElement.GetTypeSize( elem.Type ), pBufferData );
GLESConfig.GlCheckError( this );
OpenGL.EnableClientState( All.VertexArray );
GLESConfig.GlCheckError( this );
break;
case VertexElementSemantic.Normal:
OpenGL.NormalPointer( GLESHardwareBufferManager.GetGLType( elem.Type ), VertexElement.GetTypeSize( elem.Type ), pBufferData );
GLESConfig.GlCheckError( this );
OpenGL.EnableClientState( All.NormalArray );
GLESConfig.GlCheckError( this );
break;
case VertexElementSemantic.Diffuse:
OpenGL.ColorPointer( 4, GLESHardwareBufferManager.GetGLType( elem.Type ), VertexElement.GetTypeSize( elem.Type ), pBufferData );
GLESConfig.GlCheckError( this );
OpenGL.EnableClientState( All.ColorArray );
GLESConfig.GlCheckError( this );
break;
case VertexElementSemantic.Specular:
break;
case VertexElementSemantic.TexCoords:
{
// fixed function matching to units based on tex_coord_set
for ( unit = 0; unit < disabledTexUnitsFrom; i++ )
{
// Only set this texture unit's texcoord pointer if it
// is supposed to be using this element's index
if ( _textureCoodIndex[ i ] == elem.Index && i < _fixedFunctionTextureUnits )
{
GLESConfig.GlCheckError( this );
if ( multitexturing )
{
OpenGL.ClientActiveTexture( All.Texture0 + unit );
}
GLESConfig.GlCheckError( this );
OpenGL.TexCoordPointer( VertexElement.GetTypeCount( elem.Type ), GLESHardwareBufferManager.GetGLType( elem.Type ), VertexElement.GetTypeSize( elem.Type ), pBufferData );
GLESConfig.GlCheckError( this );
OpenGL.EnableClientState( All.TextureCoordArray );
GLESConfig.GlCheckError( this );
}
}
}
break;
default:
break;
}
}
if ( multitexturing )
{
OpenGL.ClientActiveTexture( All.Texture0 );
}
GLESConfig.GlCheckError( this );
// Find the correct type to render
All primType = 0;
switch ( op.operationType )
{
case OperationType.PointList:
primType = All.Points;
break;
case OperationType.LineList:
primType = All.Lines;
break;
case OperationType.LineStrip:
primType = All.LineStrip;
break;
case OperationType.TriangleList:
primType = All.Triangles;
break;
case OperationType.TriangleStrip:
primType = All.TriangleStrip;
break;
case OperationType.TriangleFan:
primType = All.TriangleFan;
break;
default:
primType = All.Triangles;
break;
}
if ( op.useIndices )
{
if ( _rsCapabilities.HasCapability( Capabilities.FrameBufferObjects ) )
{
OpenGL.BindBuffer( All.ElementArrayBuffer, ( (GLESHardwareIndexBuffer)op.indexData.indexBuffer ).BufferID );
GLESConfig.GlCheckError( this );
pBufferData = VBOBufferOffset( op.indexData.indexStart * op.indexData.indexBuffer.IndexSize );
}
else
{
pBufferData = ( (GLESDefaultHardwareIndexBuffer)op.indexData.indexBuffer ).GetData( op.indexData.indexStart * op.indexData.indexBuffer.IndexSize );
}
All indexType = ( op.indexData.indexBuffer.Type == IndexType.Size16 ) ? All.UnsignedShort : All.UnsignedByte;
do
{
if ( derivedDepthBias && currentPassIterationCount > 0 )
{
SetDepthBias( derivedDepthBiasBase + derivedDepthBiasMultiplier * currentPassIterationCount, derivedDepthBiasSlopeScale );
}
GLESConfig.GlCheckError( this );
OpenGL.DrawElements( ( _polygonMode == GLFill ) ? primType : (All)_polygonMode, op.indexData.indexCount, indexType, pBufferData );
GLESConfig.GlCheckError( this );
}
while ( UpdatePassIterationRenderState() );
}
else
{
do
{
if ( derivedDepthBias && currentPassIterationCount > 0 )
{
SetDepthBias( derivedDepthBiasBase + derivedDepthBiasMultiplier * currentPassIterationCount, derivedDepthBiasSlopeScale );
}
OpenGL.DrawArrays( primType, 0, op.vertexData.vertexCount );
GLESConfig.GlCheckError( this );
}
while ( UpdatePassIterationRenderState() );
}
OpenGL.DisableClientState( All.VertexArray );
GLESConfig.GlCheckError( this );
// Only valid up to GL_MAX_TEXTURE_UNITS, which is recorded in mFixedFunctionTextureUnits
if ( multitexturing )
{
for ( int i = 0; i < _fixedFunctionTextureUnits; i++ )
{
OpenGL.ClientActiveTexture( All.Texture0 + i );
OpenGL.DisableClientState( All.TextureCoordArray );
}
OpenGL.ClientActiveTexture( All.Texture0 );
}
else
{
OpenGL.DisableClientState( All.TextureCoordArray );
}
GLESConfig.GlCheckError( this );
OpenGL.DisableClientState( All.NormalArray );
GLESConfig.GlCheckError( this );
OpenGL.DisableClientState( All.ColorArray );
GLESConfig.GlCheckError( this );
OpenGL.Color4( 1.0f, 1.0f, 1.0f, 1.0f );
GLESConfig.GlCheckError( this );
}