Pages: [1]
  Print  
Author Topic: Custom implementation of glBegin, glVertexXX and the like  (Read 6729 times)
cheb
Lesser Nub


Cakes 3
Posts: 127



WWW
« on: April 15, 2017, 03:28:13 AM »

I was browsing sources of the legendary ZenGL library in search of enlightening when I suddenly realized that ZenGL has its own implementation of most common immediate mode functions to be used on top of GL ES (which, by design, doesn't support 'em).

And then I thought: could this be it? Could a well optimized custom implementation be faster than what compatibility layers of modern ICDs provide out of mercy?

All I know that immediate mode performance drops *sharply* after around 20 k vertexes.
Maybe that's artificial?  Lips Sealed

What if custom implementation packed that array's texture and color values to something more compact than  GL_FLOAT ? That would make uploading to video card during glEnd faster. And ZenGL does - it stores color values as GL_UNSIGNED_BYTE.

Or do OA sources *already* use something like this?  Undecided

The inspirational code (can only be used for inspiration, heh)

Just look at this little beauty! Kiss
Code:
procedure glEnd;
begin
  if bSize = 0 Then exit;

  if RenderTextured Then
    begin
      glEnableClientState( GL_TEXTURE_COORD_ARRAY );
      glTexCoordPointer( 2, GL_FLOAT, 24, @bVertices[ 0 ] );
    end;

  glEnableClientState( GL_COLOR_ARRAY );
  glColorPointer( 4, GL_UNSIGNED_BYTE, 24, @bVertices[ 0 ].Color );

  glEnableClientState( GL_VERTEX_ARRAY );
  glVertexPointer( 3, GL_FLOAT, 24, @bVertices[ 0 ].X );

  glDrawArrays( RenderMode, 0, bSize );

  glDisableClientState( GL_VERTEX_ARRAY );
  glDisableClientState( GL_COLOR_ARRAY );
  if RenderTextured Then
    glDisableClientState( GL_TEXTURE_COORD_ARRAY );
end;

The rest
Code:
procedure glBegin(mode: GLenum);
begin
  bSize := 0;
  RenderTextured := FALSE;

  if Mode = GL_QUADS Then
    begin
      RenderQuad  := TRUE;
      newTriangle := 0;
      RenderMode  := GL_TRIANGLES;
    end else
      begin
        RenderQuad := FALSE;
        RenderMode := Mode;
      end;
end;

procedure glColor4ub(red, green, blue, alpha: GLubyte);
begin
  PByteArray( @bColor )[ 0 ] := red;
  PByteArray( @bColor )[ 1 ] := green;
  PByteArray( @bColor )[ 2 ] := blue;
  PByteArray( @bColor )[ 3 ] := alpha;
end;

procedure glColor4ubv(v: PGLubyte);
begin
  bColor := PLongWord( v )^;
end;

procedure glColor4f(red, green, blue, alpha: GLfloat);
begin
  PByteArray( @bColor )[ 0 ] := Round( red * 255 );
  PByteArray( @bColor )[ 1 ] := Round( green * 255 );
  PByteArray( @bColor )[ 2 ] := Round( blue * 255 );
  PByteArray( @bColor )[ 3 ] := Round( alpha * 255 );
end;

{$IFDEF ANDROID}
function tan( x : Single ) : Single;
  var
    _sin,_cos : Single;
begin
  m_SinCos( x, _sin, _cos );
  tan := _sin / _cos;
end;
{$ENDIF}

procedure gluPerspective(fovy, aspect, zNear, zFar: GLdouble);
  var
    m : array[ 1..4, 1..4 ] of Single;
    f : Single;
begin
  f := 1 / tan( FOVY * pi / 360 );

  m[ 1, 1 ] := f / aspect;
  m[ 1, 2 ] := 0;
  m[ 1, 3 ] := 0;
  m[ 1, 4 ] := 0;

  m[ 2, 1 ] := 0;
  m[ 2, 2 ] := f;
  m[ 2, 3 ] := 0;
  m[ 2, 4 ] := 0;

  m[ 3, 1 ] := 0;
  m[ 3, 2 ] := 0;
  m[ 3, 3 ] := ( zFar + zNear ) / ( zNear - zFar );
  m[ 3, 4 ] := -1;

  m[ 4, 1 ] := 0;
  m[ 4, 2 ] := 0;
  m[ 4, 3 ] := 2 * zFar * zNear / ( zNear - zFar );
  m[ 4, 4 ] := 0;

  glLoadMatrixf( @m[ 1, 1 ] );
end;

procedure glVertex2f(x, y: GLfloat);
  var
    vertex : zglGLESPVertex;
begin
  if ( not RenderTextured ) and ( bSize = Length( bVertices ) ) Then
    SetLength( bVertices, bSize + 1024 );

  vertex       := @bVertices[ bSize ];
  vertex.X     := x;
  vertex.Y     := y;
  vertex.Z     := 0;
  vertex.Color := bColor;
  INC( bSize );
  if RenderQuad Then
    begin
      INC( newTriangle );
      if newTriangle = 3 Then
        begin
          if bSize = Length( bVertices ) Then
            SetLength( bVertices, bSize + 1024 );
          bVertices[ bSize ] := bVertices[ bSize - 1 ];

          INC( bSize );
        end else
          if newTriangle = 4 Then
            begin
              if bSize = Length( bVertices ) Then
                SetLength( bVertices, bSize + 1024 );
              bVertices[ bSize ] := bVertices[ bSize - 5 ];

              INC( bSize );
              newTriangle := 0;
            end;
    end;
end;

procedure glVertex2fv(v: PGLfloat);
  var
    vertex : zglGLESPVertex;
begin
  if ( not RenderTextured ) and ( bSize = Length( bVertices ) ) Then
    SetLength( bVertices, bSize + 1024 );

  vertex       := @bVertices[ bSize ];
  vertex.X     := zglPPoint2D( v ).X;
  vertex.Y     := zglPPoint2D( v ).Y;
  vertex.Z     := 0;
  vertex.Color := bColor;
  INC( bSize );
  if RenderQuad Then
    begin
      INC( newTriangle );
      if newTriangle = 3 Then
        begin
          if bSize = Length( bVertices ) Then
            SetLength( bVertices, bSize + 1024 );
          bVertices[ bSize ] := bVertices[ bSize - 1 ];

          INC( bSize );
        end else
          if newTriangle = 4 Then
            begin
              if bSize = Length( bVertices ) Then
                SetLength( bVertices, bSize + 1024 );
              bVertices[ bSize ] := bVertices[ bSize - 5 ];

              INC( bSize );
              newTriangle := 0;
            end;
    end;
end;

procedure glVertex3f(x, y, z: GLfloat);
  var
    vertex : zglGLESPVertex;
begin
  if ( not RenderTextured ) and ( bSize = Length( bVertices ) ) Then
    SetLength( bVertices, bSize + 1024 );

  vertex       := @bVertices[ bSize ];
  vertex.X     := x;
  vertex.Y     := y;
  vertex.Z     := z;
  vertex.Color := bColor;
  INC( bSize );
  if RenderQuad Then
    begin
      INC( newTriangle );
      if newTriangle = 3 Then
        begin
          if bSize = Length( bVertices ) Then
            SetLength( bVertices, bSize + 1024 );
          bVertices[ bSize ] := bVertices[ bSize - 1 ];

          INC( bSize );
        end else
          if newTriangle = 4 Then
            begin
              if bSize = Length( bVertices ) Then
                SetLength( bVertices, bSize + 1024 );
              bVertices[ bSize ] := bVertices[ bSize - 5 ];

              INC( bSize );
              newTriangle := 0;
            end;
    end;
end;

procedure glGetTexImage(target: GLenum; level: GLint; format: GLenum; atype: GLenum; pixels: Pointer);
begin
end;

procedure glTexCoord2f(s, t: GLfloat);
begin
  RenderTextured := TRUE;

  if bSize = Length( bVertices ) Then
    SetLength( bVertices, bSize + 1024 );
  bVertices[ bSize ].U := s;
  bVertices[ bSize ].V := t;
end;

procedure glTexCoord2fv(v: PGLfloat);
begin
  RenderTextured := TRUE;

  if bSize = Length( bVertices ) Then
    SetLength( bVertices, bSize + 1024 );
  bVertices[ bSize ].U := zglPPoint2D( v ).X;
  bVertices[ bSize ].V := zglPPoint2D( v ).Y;
end;
Logged

Imma lazy dreamer. I achieved nothing.
pelya
Member


Cakes 6
Posts: 399


WWW
« Reply #1 on: April 16, 2017, 05:24:21 AM »

Is this... Is this Pascal?  Shocked
Logged
Pages: [1]
  Print  
 
Jump to: