fbgfx versus opengl graphics

Post your FreeBASIC tips and tricks here. Please don’t post your code without including an explanation.
dodicat
Posts: 6728
Joined: Jan 10, 2006 20:30
Location: Scotland

fbgfx versus opengl graphics

Postby dodicat » Mar 31, 2020 14:58

Windows
Using cubes and painting openGL to an FB screen.
Which one is FBGFX and which one is OpenGL?

Code: Select all


#include "windows.bi"
#include "GL\glu.bi"

Sub glinit(xres As Long,yres As Long)
    glViewport 0, 0, xres, yres                      '' Reset The Current Viewport
   glMatrixMode GL_PROJECTION                     '' Select The Projection Matrix
   glLoadIdentity                                 '' Reset The Projection Matrix
   gluPerspective 45.0, xres/yres, 0.1, 100.0   '' Calculate The Aspect Ratio Of The Window
   glMatrixMode GL_MODELVIEW                      '' Select The Modelview Matrix
   glLoadIdentity                                 '' Reset The Modelview Matrix
   
   '' All Setup For OpenGL Goes Here
   glShadeModel GL_SMOOTH                         '' Enable Smooth Shading
   glClearColor 0.0, 0.0, 0.0, 0.5                '' Black Background
   glClearDepth 1.0                               '' Depth Buffer Setup
   glEnable GL_DEPTH_TEST                         '' Enables Depth Testing
   glDepthFunc GL_LEQUAL                          '' The Type Of Depth Testing To Do
   glHint GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST 
   
End Sub

Sub gLcube(angle As Single)
    glLoadIdentity                                          '' Reset The Current Modelview Matrix
    glTranslatef 1.6, 0.0, -7.5                             '' Move Right 1.6 Units And Into The Screen 7.5
    glRotatef angle,1.0, 1.0, 1.0                           '' Rotate The Quad On The X axis
   
    glClear GL_COLOR_BUFFER_BIT Or GL_DEPTH_BUFFER_BIT
    glBegin GL_QUADS                                       
    glColor3f 0.0, 1.0, 0.0                             
    glVertex3f 1.0, 1.0, -1.0                           
    glVertex3f -1.0, 1.0, -1.0
    glVertex3f -1.0, 1.0, 1.0                           
    glVertex3f 1.0, 1.0, 1.0
   
    glColor3f 1.0, 0.5, 0.0                             
    glVertex3f 1.0, -1.0, 1.0                           
    glVertex3f -1.0, -1.0, 1.0
    glVertex3f -1.0, -1.0, -1.0                       
    glVertex3f 1.0, -1.0, -1.0
   
    glColor3f 1.0, 0.0, 0.0                             
    glVertex3f 1.0, 1.0, 1.0                           
    glVertex3f -1.0, 1.0, 1.0
    glVertex3f -1.0, -1.0, 1.0                         
    glVertex3f 1.0, -1.0, 1.0
   
    glColor3f 1.0, 1.0, 0.0                           
    glVertex3f 1.0, -1.0, -1.0                           
    glVertex3f -1.0, -1.0, -1.0
    glVertex3f -1.0, 1.0, -1.0                       
    glVertex3f 1.0, 1.0, -1.0 
   
    glColor3f 0.0, .5, 1.0                             
    glVertex3f -1.0, 1.0, 1.0                         
    glVertex3f -1.0, 1.0, -1.0
    glVertex3f -1.0, -1.0, -1.0                       
    glVertex3f -1.0, -1.0, 1.0
   
    glColor3f 1.0, 0.0, 1.0                             
    glVertex3f 1.0, 1.0, -1.0 
    glVertex3f 1.0, 1.0, 1.0                         
    glVertex3f 1.0, -1.0, 1.0                           
    glVertex3f 1.0, -1.0, -1.0                         
    glEnd                       
    glFlush()
   
End Sub

Dim Shared As Integer refresh_rate

Dim Shared As Integer w,h

Type screendata
    As Integer w,h,depth,pitch
    As Any Pointer row
End Type

Type V3
    As Single x,y,z
    As Ulong col
    As Single grad
    As Long xi
End Type

Sub fillpolygon(a() As V3, c As Ulong,miny As Long,maxy As Long,s As screendata)
    'source of c code: http://code-heaven.blogspot.it/2009/10/simple-c-program-for-scan-line-polygon.html
    'Mostly translated by forum member Pitto
    #define ppset32(_x,_y,colour)    *Cptr(Ulong Ptr,s.row+ (_y)*s.pitch+ (_x) Shl 2)  =(colour)
    #define onscreen ((x1)>=0) Andalso ((x1)<(s.w-1)) Andalso ((y1)>=0) Andalso ((y1)<(s.h-1))
    Dim As Long LB=Lbound(a),UB=Ubound(a)
    For i As Long=lb To Ub - 1
        Var dy=a(i+1).y-a(i).y
        Var dx=a(i+1).x-a(i).x
        If dy=0 Then a(i).grad=1
        If dx=0 Then a(i).grad=0
       
        If dy <> 0 Andalso dx <> 0 Then
            a(i).grad = dx / dy
        End If
    Next i
   
    For y As Long=miny To maxy
        Var k = lb
        For i As Long=lb To Ub - 1
            If ( a(i).y<=y Andalso a(i+1).y>y)  Orelse (a(i).y>y  Andalso a(i+1).y<=y) Then
                a(k).xi= (a(i).x+a(i).grad*(y-a(i).y))
                k +=1
            End If
        Next i
       
        For j As Long = lb To k-2 -1
            For i As Long = lb +1 To k-2
                If a(i).xi > a(i+1).xi Then
                    Swap a(i).xi,a(i+1).xi
                End If
            Next i
        Next j
        Dim As Long e
        For i As Long = lb To k - 2 Step 2
            'bressenham line inlined
            Dim As Long x1= a(i).xi ,y1= y,x2=a(i+1).xi+1,y2= y
            Var dx=Abs(x2-x1),dy=0,sx=Sgn(x2-x1),sy=0
            If dx<dy Then  e=dx\2 Else e=dy\2
            Do
                If onscreen Then
                    ppset32((x1),(y1),c)
                End If
                If x1 = x2 Then If y1 = y2 Then Exit Do
                If dx > dy Then
                    x1 += sx : e -= dy : If e < 0 Then e += dx : y1 += sy
                Else
                    y1 += sy : e -= dx : If e < 0 Then e += dy : x1 += sx
                End If
            Loop 
        Next i
    Next y
   
End Sub

Sub drawpolygon(p() As V3,i As Long,s As screendata)
    Static As Single miny=1e6,maxy=-1e6
    Static As v3 V(1 To  Ubound(p,2)+1)
    For n As Long=1 To Ubound(p,2)
        If miny>p(i,n).y Then miny=p(i,n).y
        If maxy<p(i,n).y Then maxy=p(i,n).y
        V(n)=p(i,n)
    Next
    v(Ubound(v))=v(Lbound(v))
    fillpolygon(v(),p(i,1).col,miny,maxy,s)
End Sub

Function Rotate(c As V3,p As V3,angle As V3,scale As V3=Type<V3>(1,1,1)) As V3
    Dim As Single sx=Sin(angle.x),sy=Sin(angle.y),sz=Sin(angle.z)
    Dim As Single cx=Cos(angle.x),cy=Cos(angle.y),cz=Cos(angle.z)
    Dim As Single dx=p.x-c.x,dy=p.y-c.y,dz=p.z-c.z
    Return Type<V3>((scale.x)*((cy*cz)*dx+(-cx*sz+sx*sy*cz)*dy+(sx*sz+cx*sy*cz)*dz)+c.x,_
    (scale.y)*((cy*sz)*dx+(cx*cz+sx*sy*sz)*dy+(-sx*cz+cx*sy*sz)*dz)+c.y,_
    (scale.z)*((-sy)*dx+(sx*cy)*dy+(cx*cy)*dz)+c.z,p.col)
End Function

Function perspective(p As V3,eyepoint As V3) As V3
    Dim As Single   w=1+(p.z/eyepoint.z)
    Return Type<V3>((p.x-eyepoint.x)/w+eyepoint.x,_
    (p.y-eyepoint.y)/w+eyepoint.y,_
    (p.z-eyepoint.z)/w+eyepoint.z,p.col)
End Function 

Sub sort(array() As V3,painter() As Long)
    For p1 As Long  = 1 To Ubound(array,1) - 1
        For p2 As Long  = p1 + 1 To Ubound(array,1) 
            If array(p1,0).z<array(p2,0).z Then Swap painter(p1),painter(p2):Swap array(p1,0),array(p2,0)
        Next p2
    Next p1
End Sub

Sub Expand(p() As V3,b As Single,shift As V3,i As Long)
    For n As Long=Lbound(p,2) To Ubound(p,2)
        p(i,n).x=b*p(i,n).x+shift.x
        p(i,n).y=b*p(i,n).y+shift.y
        p(i,n).z=b*p(i,n).z+shift.z
    Next n
End Sub

'=========================================================
'set the cube faces on (0,0,0) as centre
Dim Shared As V3 g1(1 To ...,1 To ...)={{(-1,-1,-1),(1,-1,-1),(1,1,-1),(-1,1,-1)},_'front
{(1,-1,-1),(1,-1,1),(1,1,1),(1,1,-1)},_ 'right
{(-1,-1,1),(1,-1,1),(1,1,1),(-1,1,1)},_'back
{(-1,-1,-1),(-1,-1,1),(-1,1,1),(-1,1,-1)},_'left
{(1,1,-1),(1,1,1),(-1,1,1),(-1,1,-1)},_'top
{(1,-1,-1),(1,-1,1),(-1,-1,1),(-1,-1,-1)}}'base
'set colours,save in 1st. index
g1(1,1).col=Rgb(0,255,0):g1(2,1).col=Rgb(255,255\2,0):g1(3,1).col=Rgb(255,0,0):g1(4,1).col=Rgb(255,255,0):g1(5,1).col=Rgb(0,255\2,255):g1(6,1).col=Rgb(255,0,255)


Screen 20,32
Dim Shared As screendata S
With S
    Screeninfo .w,.h,.depth,,.pitch
    .row=Screenptr
End With
'blow up and translate the cube to screen centre
For i As Long=Lbound(g1,1) To Ubound(g1,1)
    Expand (g1(),120,Type<v3>(s.w\4,s.h\2,0),i)
Next i
Dim Shared As Long painter(1 To 6)
For n As Long=1 To 6:painter(n)=n:Next n
   
    Dim Shared As V3 eye:eye= Type<V3>(s.w\4,s.h\2,800) 
    Dim As String i
    Dim Shared As V3 fulcrum:fulcrum=Type<V3>(s.w\4,s.h\2,0)            ' middle of cube
    Dim Shared As Long fps
   
    Sub fbcube(angle As V3)
        Dim As Long cx,cy,cz                     'centriods
        Static As V3 tmp1(1 To Ubound(g1,1),0 To Ubound(g1,2))'the working array
        For m As Long=Lbound(g1,1) To Ubound(g1,1)
            cx=0:cy=0:cz=0
            For n As Long=1 To Ubound(g1,2)
                tmp1(m,n)=Rotate(fulcrum,g1(m,n),angle)
                tmp1(m,n)=perspective(tmp1(m,n),eye)  'apply the eye (perspective)
                cx+=tmp1(m,n).x:cy+=tmp1(m,n).y:cz+=tmp1(m,n).z
            Next n
            cx=cx/4:cy=cy/4:cz=cz/4
            'get face centroid into zero'th index
            tmp1(m,0)=Type<v3>(cx,cy,cz)
        Next m
        'sort the faces by centriods
        sort(tmp1(),painter())
        For z As Long=Lbound(tmp1,1)+3 To Ubound(tmp1,1)'Paint only the closest three faces
            Var p=painter(z)
            Select Case p
            Case 1: drawpolygon(tmp1(),p,s)
            Case 2: drawpolygon(tmp1(),p,s)
            Case 3: drawpolygon(tmp1(),p,s)
            Case 4: drawpolygon(tmp1(),p,s)
            Case 5: drawpolygon(tmp1(),p,s)
            Case 6: drawpolygon(tmp1(),p,s)
            End Select
        Next z
        'reset painter
        For n As Long=1 To 6:painter(n)=n:Next n
        End Sub
       
        Function Regulate(Byval MyFps As Long,Byref fps As Long=0) As Long
            Static As Double timervalue,_lastsleeptime,t3,frames
            Var t=Timer
            frames+=1
            If (t-t3)>=1 Then t3=t:fps=frames:frames=0
            Var sleeptime=_lastsleeptime+((1/myfps)-T+timervalue)*1000
            If sleeptime<1 Then sleeptime=1
            _lastsleeptime=sleeptime
            timervalue=T
            Return sleeptime
        End Function
       
        'from glwin2
        Sub SetUpglTOfbscreen(Byref pPixels As Ubyte Ptr,x As Long,y As Long )
            Dim As Any Ptr     MemoryDC,ScreenDC 'HDC
            Dim As Any Ptr     RenderContext 'HGLRC
            Dim As Any Ptr     Bitmap
            Dim As BITMAPINFO BI
            Dim As PIXELFORMATDESCRIPTOR PfD
            Dim As Integer    PixelFormat
            ScreenDC=GetDC(0) 'CreateDC("DISPLAY",NULL,NULL,NULL)
            MemoryDC=CreateCompatibleDC(ScreenDC)
            With BI.bmiHeader
                .biSize          = Sizeof(BITMAPINFOHEADER)
                .biWidth         = x
                .biHeight        =-y
                '.biSizeImage     = 512*512*2
                .biPlanes        =   1
                .biBitCount      =  24
                .biCompression   = BI_RGB
                .biXPelsPerMeter = 0
                .biYPelsPerMeter = 0
                .biClrUsed       = 0
                .biClrImportant  = 0
            End With
            Bitmap=CreateDIBSection(MemoryDC,@BI,DIB_RGB_COLORS,@pPixels,NULL,0)
            SelectObject(MemoryDC,Bitmap)
            With PfD
                .nSize = Sizeof(PIXELFORMATDESCRIPTOR)
                .nVersion     = 1
                .dwFlags      = PFD_DRAW_TO_BITMAP Or PFD_SUPPORT_OPENGL Or PFD_SUPPORT_GDI
                .iPixelType   = PFD_TYPE_RGBA
                .iLayerType   = PFD_MAIN_PLANE
                .cColorBits   = 24
                .cDepthBits   = 24
                .cAlphaBits   = 8
                '.cAccumBits   = 0
                '.cStencilBits = 0
            End With
            PixelFormat = ChoosePixelFormat(MemoryDC,@PfD)
            SetPixelFormat(MemoryDC,PixelFormat,@PfD)
            RenderContext=wglCreateContext(MemoryDC)
            wglMakeCurrent(MemoryDC,RenderContext)
        End Sub
       
        'superimpose via screenptr
        Sub Drawgl(p As Ubyte Ptr,pPixels As Ubyte Ptr,xx As Long,yy As Long)
            Dim As Long i
            For y As Long=0 To xx-1
                For x As Long=0 To yy-1
                    p[i*4+0]= pPixels[i*3+0]
                    p[i*4+1]= pPixels[i*3+1]
                    p[i*4+2]= pPixels[i*3+2]
                    i+=1
                Next
            Next
        End Sub
       
        Sub Start()
            Screen 20,32
            Screeninfo w,h
            Screencontrol 8,refresh_rate
            Dim As Any Ptr pPixels
            'Dim Win As Any Ptr=Screenptr
            Var Ip = Cptr(Integer Ptr,@ppixels )
            Screencontrol 2,*Ip
            Print ppixels
            '==== opengl ===========
           
            SetUpglTOfbscreen(pPixels,w,h) 'gl to fb     
            glinit(w,h)                    'initialize the open gl
            '========================
            Const pi=4*Atn(1)
            Dim As Long fps
            Dim As v3 a
            a.y=pi
            Dim As Single gla
           
            While 1
                gla+=1
                a.x+=.01/2
                a.y+=.02/2
                a.z+=.03/2
                Screenlock
                Cls
                glClear GL_COLOR_BUFFER_BIT Or GL_DEPTH_BUFFER_BIT
                DrawGl(Screenptr,pPixels,w,h) 'transfer openGL to fb screen
               
                GLcube(gla)
                FBcube(a)
               
                Draw String(50, 10), " Press escape key to end", Rgb(255, 200, 0)
                Draw String(50, 55), "framerate " &fps , Rgb(0, 200, 0)
                'Draw String(w\4-50,110),"fbgfx cube"
                'Draw String(3*w\4-50,110),"openGL cube"
                Screenunlock
                glflush
                Sleep regulate(refresh_rate, fps)
                If Inkey=Chr(27) Then Exit While
            Wend
        End Sub
       
        start
       
         
BasicCoder2
Posts: 3598
Joined: Jan 01, 2009 7:03
Location: Australia

Re: fbgfx versus opengl graphics

Postby BasicCoder2 » Mar 31, 2020 18:49

Another nice demo :)

I made two copies of your program. I deleted the include window.bi and gl\glu.bi and what I believe was OpenGL code from one copy and deleted what I believe was mainly fb code from the other copy. The frame rate for the fb only code was steady around 58 and 59 frames per second while the OpenGL version had a wider range of frame rates between 35 and 50 as returned by your regulate routine.
Tourist Trap
Posts: 2958
Joined: Jun 02, 2015 16:24

Re: fbgfx versus opengl graphics

Postby Tourist Trap » Mar 31, 2020 19:01

Very nice. Hard to say what side is what graphics.
BasicCoder2
Posts: 3598
Joined: Jan 01, 2009 7:03
Location: Australia

Re: fbgfx versus opengl graphics

Postby BasicCoder2 » Mar 31, 2020 19:07

@Tourist Trap
Remove the comment symbol from,

Code: Select all

                'Draw String(w\4-50,110),"fbgfx cube"
                'Draw String(3*w\4-50,110),"openGL cube"


Personally I couldn't pick the difference. However I assume openGL can easily do a lot more than rotate a simple cube?

Love dodicat's demo code even though I don't understand how much of it actually works :)
Tourist Trap
Posts: 2958
Joined: Jun 02, 2015 16:24

Re: fbgfx versus opengl graphics

Postby Tourist Trap » Mar 31, 2020 19:19

BasicCoder2 wrote:@Tourist Trap
Remove the comment symbol from

It confirms that there is not any difference.
The thing that is really nice, is that we can mix up both, fbgfx and openGl.
Imortis
Moderator
Posts: 1734
Joined: Jun 02, 2005 15:10
Location: USA
Contact:

Re: fbgfx versus opengl graphics

Postby Imortis » Mar 31, 2020 21:12

You can use OpenGL as the backend for FBGFX by using the flag for in screenres:
https://www.freebasic.net/wiki/wikka.php?wakka=KeyPgScreenres
paul doe
Posts: 1334
Joined: Jul 25, 2017 17:22
Location: Argentina

Re: fbgfx versus opengl graphics

Postby paul doe » Mar 31, 2020 22:14

Tourist Trap wrote:...
It confirms that there is not any difference.
...

You'll only notice if you slow down the rotation speed. The left cube has no subpixel accuracy. With plain colors the difference is subtle, but with textures applied you'll pick it immediately.
dodicat
Posts: 6728
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: fbgfx versus opengl graphics

Postby dodicat » Apr 02, 2020 14:23

Comparing speeds,
fb direct pixel (with clipping) is the fastest here (by a good margin)
openGL is slightly slower than pset.
Just tap a key to toggle through.

Code: Select all


#include "windows.bi"
#include "gl/glu.bi"

Screen 20,32
Dim Shared As Integer xres,yres
Dim Shared As Any Ptr row:row=Screenptr
Dim Shared As Integer pitch
Screeninfo xres,yres,,,pitch
color ,rgb(255,255,255)


Const red=Rgb(200,0,0)
Const green=Rgb(0,200,0)
Const blue=Rgb(0,0,200)
const black=rgb(0,0,0)
'from glwin2
Sub SetUpglTOfbscreen(Byref pPixels As Ubyte Ptr,x As Long,y As Long )
    Dim As Any Ptr     MemoryDC,ScreenDC 'HDC
    Dim As Any Ptr     RenderContext 'HGLRC
    Dim As Any Ptr     Bitmap
    Dim As BITMAPINFO BI
    Dim As PIXELFORMATDESCRIPTOR PfD
    Dim As Integer    PixelFormat
    ScreenDC=GetDC(0)
    MemoryDC=CreateCompatibleDC(ScreenDC)
    With BI.bmiHeader
        .biSize          = Sizeof(BITMAPINFOHEADER)
        .biWidth         = x
        .biHeight        =-y
        '.biSizeImage     = 512*512*2
        .biPlanes        =   1
        .biBitCount      =  24
        .biCompression   = BI_RGB
        .biXPelsPerMeter = 0
        .biYPelsPerMeter = 0
        .biClrUsed       = 0
        .biClrImportant  = 0
    End With
    Bitmap=CreateDIBSection(MemoryDC,@BI,DIB_RGB_COLORS,@pPixels,NULL,0)
    SelectObject(MemoryDC,Bitmap)
    With PfD
        .nSize = Sizeof(PIXELFORMATDESCRIPTOR)
        .nVersion     = 1
        .dwFlags      = PFD_DRAW_TO_BITMAP Or PFD_SUPPORT_OPENGL Or PFD_SUPPORT_GDI
        .iPixelType   = PFD_TYPE_RGBA
        .iLayerType   = PFD_MAIN_PLANE
        .cColorBits   = 24
        .cDepthBits   = 24
        .cAlphaBits   = 8
        '.cAccumBits   = 0
        '.cStencilBits = 0
    End With
    PixelFormat = ChoosePixelFormat(MemoryDC,@PfD)
    SetPixelFormat(MemoryDC,PixelFormat,@PfD)
    RenderContext=wglCreateContext(MemoryDC)
    wglMakeCurrent(MemoryDC,RenderContext)
End Sub

'superimpose via screenptr
Sub Drawgl(p As Ubyte Ptr,pPixels As Ubyte Ptr,xx As Long,yy As Long)
    Dim As Long i
    For y As Long=0 To xx-1
        For x As Long=0 To yy-1
            p[i*4+0]= pPixels[i*3+0]
            p[i*4+1]= pPixels[i*3+1]
            p[i*4+2]= pPixels[i*3+2]
            i+=1
        Next
    Next
End Sub

Sub glinit(x As Long,y As Long)
    glOrtho 0,x,y, 0,-1, 1
    glclearcolor 1,1,1,1
End Sub


Type Circle
    As Single x,y
    As Long  radius
    Dim As Single dx,dy
    As Ulong c 'colour
End Type

Sub fbcircledirect(b As Circle)
    #define incircle(cx,cy,radius,x,y) (cx-x)*(cx-x) +(cy-y)*(cy-y)<= radius*radius
    #define onscreen x>=0 And x<xres And y>.0 And y<yres
    #define putpixel(_x,_y,colour)    *Cptr(Ulong Ptr,row+ (_y)*pitch+ (_x) Shl 2)  =(colour)
    Dim As Ulong tc
    For x As Long=b.x-b.radius To b.x+b.radius
        For y As Long=b.y-b.radius To b.y+b.radius
            If incircle(b.x,b.y,b.radius,x,y) Andalso onscreen Then
                putpixel(x,y,Rgb(Cast(Ubyte Ptr,@b.c)[2],Cast(Ubyte Ptr,@b.c)[1],Cast(Ubyte Ptr,@b.c)[0]))
            End If
        Next
    Next
End Sub

Sub fbcirclepset(b As Circle)
    #define incircle(cx,cy,radius,x,y) (cx-x)*(cx-x) +(cy-y)*(cy-y)<= radius*radius
    #define onscreen x>=0 And x<xres And y>.0 And y<yres
    #define putpixel(_x,_y,colour)    *Cptr(Ulong Ptr,row+ (_y)*pitch+ (_x) Shl 2)  =(colour)
    Dim As Ulong tc
    For x As Long=b.x-b.radius To b.x+b.radius
        For y As Long=b.y-b.radius To b.y+b.radius
            If incircle(b.x,b.y,b.radius,x,y) Then
                Pset(x,y),Rgb(Cast(Ubyte Ptr,@b.c)[2],Cast(Ubyte Ptr,@b.c)[1],Cast(Ubyte Ptr,@b.c)[0])
            End If
        Next
    Next
End Sub

Sub glcircle(b As Circle)
    glbegin gl_points
    #define incircle(cx,cy,radius,x,y) (cx-x)*(cx-x) +(cy-y)*(cy-y)<= radius*radius
    glcolor3ub(Cast(Ubyte Ptr,@b.c)[2],Cast(Ubyte Ptr,@b.c)[1],Cast(Ubyte Ptr,@b.c)[0])
    For x As Long=b.x-b.radius To b.x+b.radius
        For y As Long=b.y-b.radius To b.y+b.radius
            If incircle(b.x,b.y,b.radius,x,y) Then
                glvertex2i x,yres-y   
            End If
        Next
    Next
    glend
End Sub

Sub move(c As Circle)
    c.x+=c.dx
    c.y+=c.dy
    If c.x<c.radius Then c.dx=-c.dx
    If c.x>xres-c.radius Then c.dx=-c.dx
    If c.y<c.radius Then c.dy=-c.dy
    If c.y>yres-c.radius Then c.dy=-c.dy
End Sub

Dim As Any Ptr pPixels
SetUpglTOfbscreen(pPixels,xres,yres) 'gl to fb     
glinit(xres,yres)

Randomize 4
Dim As Double t
Dim As Circle c=Type(xres/2,yres/2,300,(Rnd-Rnd)*5,(Rnd-Rnd)*5)
Dim As Long k=1
Dim As String i
windowtitle "TAP A KEY TO SEE TIME FOR EACH METHOD TO DRAW A FILLED CIRCLE"
Do
    i=Inkey
    If Len(i) Then k+=1
    If k>3 Then k=1
    move(c)
    Screenlock
    Cls
    glClear GL_COLOR_BUFFER_BIT Or GL_DEPTH_BUFFER_BIT
     DrawGl(Screenptr,pPixels,xres,yres)
    Select Case k
    Case 1
        t=Timer
        c.c=red   :fbcircledirect(c)
        Draw String(10,10),"fbgfx direct pixels   " &(Timer-t),black
    Case 2
        t=Timer
        c.c=green :glcircle(c)
        Draw String(10,10),"opengl                " &(Timer-t),black
    Case 3
        t=Timer
        c.c=blue  :fbcirclepset(c)
        Draw String(10,10),"fbgfx pset            " &(Timer-t),black
    End Select
    Screenunlock
    glflush
    Sleep 1
Loop Until i=Chr(27)

 
caseih
Posts: 1562
Joined: Feb 26, 2007 5:32

Re: fbgfx versus opengl graphics

Postby caseih » Apr 02, 2020 15:45

I'm not surprised this kind of use of OpenGL is not fast. One is far better off setting individual pixels in a buffer, and then pushing that rapidly to the screen with OpenGL, which is what fbgfx is doing when you use the OpenGL backend.
dodicat
Posts: 6728
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: fbgfx versus opengl graphics

Postby dodicat » Apr 03, 2020 14:04

Caseih, I am testing like for like as fairly as possible.
But you will be pleased to know that openGL quad beats fb line and boxfill.
It does for a single large quad (as tested here), but not for multiple small quads (tested elsewhere)

Code: Select all

#include "windows.bi"
#include "gl/glu.bi"
Screen 20,32
Dim Shared As Integer xres,yres
Screeninfo xres,yres
window(0,0)-(xres,yres)
color ,rgb(255,255,255)

Const red=Rgb(200,0,0)
Const green=Rgb(0,200,0)
const black=rgb(0,0,0)
 
 Sub glinit(x As Long,y As Long)
    glOrtho 0,x,y, 0,-1, 1
    glclearcolor 1,1,1,1
End Sub
  'from glwin2
        Sub SetUpglTOfbscreen(Byref pPixels As Ubyte Ptr,x As Long,y As Long )
            Dim As Any Ptr     MemoryDC,ScreenDC 'HDC
            Dim As Any Ptr     RenderContext 'HGLRC
            Dim As Any Ptr     Bitmap
            Dim As BITMAPINFO BI
            Dim As PIXELFORMATDESCRIPTOR PfD
            Dim As Integer    PixelFormat
            ScreenDC=GetDC(0)
            MemoryDC=CreateCompatibleDC(ScreenDC)
            With BI.bmiHeader
                .biSize          = Sizeof(BITMAPINFOHEADER)
                .biWidth         = x
                .biHeight        =-y
                '.biSizeImage     = 512*512*2
                .biPlanes        =   1
                .biBitCount      =  24
                .biCompression   = BI_RGB
                .biXPelsPerMeter = 0
                .biYPelsPerMeter = 0
                .biClrUsed       = 0
                .biClrImportant  = 0
            End With
            Bitmap=CreateDIBSection(MemoryDC,@BI,DIB_RGB_COLORS,@pPixels,NULL,0)
            SelectObject(MemoryDC,Bitmap)
            With PfD
                .nSize = Sizeof(PIXELFORMATDESCRIPTOR)
                .nVersion     = 1
                .dwFlags      = PFD_DRAW_TO_BITMAP Or PFD_SUPPORT_OPENGL Or PFD_SUPPORT_GDI
                .iPixelType   = PFD_TYPE_RGBA
                .iLayerType   = PFD_MAIN_PLANE
                .cColorBits   = 24
                .cDepthBits   = 24
                .cAlphaBits   = 8
                '.cAccumBits   = 0
                '.cStencilBits = 0
            End With
            PixelFormat = ChoosePixelFormat(MemoryDC,@PfD)
            SetPixelFormat(MemoryDC,PixelFormat,@PfD)
            RenderContext=wglCreateContext(MemoryDC)
            wglMakeCurrent(MemoryDC,RenderContext)
        End Sub
       
        'superimpose via screenptr
        Sub Drawgl(p As Ubyte Ptr,pPixels As Ubyte Ptr,xx As Long,yy As Long)
            Dim As Long i
            For y As Long=0 To xx-1
                For x As Long=0 To yy-1
                    p[i*4+0]= pPixels[i*3+0]
                    p[i*4+1]= pPixels[i*3+1]
                    p[i*4+2]= pPixels[i*3+2]
                    i+=1
                Next
            Next
        End Sub
 
type box
    as short x,y,w,h
    as single dx,dy
    as ulong c
    declare sub fbdraw()                        'drawing methods
    declare sub gldraw()
    declare sub gl
    declare sub fb
     declare sub fbdrawdirect()
end type

sub box.fbdraw()
    line(x,y)-(x+w,y+h),rgba(cast(ubyte ptr,@c)[2],cast(ubyte ptr,@c)[1],cast(ubyte ptr,@c)[0],cast(ubyte ptr,@c)[3]),bf
end sub

sub box.gldraw()
    glcolor4ub(cast(ubyte ptr,@c)[2],cast(ubyte ptr,@c)[1],cast(ubyte ptr,@c)[0],cast(ubyte ptr,@c)[3])
    glbegin gl_quads
    glvertex2i(x,y)
    glvertex2i(x,y+h)
    glvertex2i(x+w,y+h)
    glvertex2i(x+w,y)
    glend
end sub

sub box.fb
    end sub

Sub move(c As box)
    c.x+=c.dx
    c.y+=c.dy
    If c.x<0 Then c.dx=-c.dx
    If c.x>xres-c.w Then c.dx=-c.dx
    If c.y<0 Then c.dy=-c.dy
    If c.y>yres-c.h Then c.dy=-c.dy
End Sub

randomize 4
Dim As box c=Type(100,100,600,600,(Rnd-Rnd)*5,(Rnd-Rnd)*5)
  Dim As Any Ptr pPixels
            SetUpglTOfbscreen(pPixels,xres,yres) 'gl to fb     
            glinit(xres,yres)
Dim As Double t

Dim As Long k=1
Dim As String i
windowtitle "TAP A KEY TO SEE TIME FOR EACH METHOD TO DRAW A FILLED RECTANGLE"

Do
    i=Inkey
    If Len(i) Then k+=1
    If k>2 Then k=1
    move(c)
    Screenlock
    Cls
   
    glClear GL_COLOR_BUFFER_BIT Or GL_DEPTH_BUFFER_BIT
     DrawGl(Screenptr,pPixels,xres,yres)
    Select Case k
    Case 1
        t=Timer
        c.c=red   :c.fbdraw
        Draw String(10,700),"fbgfx    " &(Timer-t)*1000,black
    Case 2
        t=Timer
        c.c=green :c.gldraw
        Draw String(10,700),"opengl    " &(Timer-t)*1000,black
   
    End Select
   
    Screenunlock
    glflush
    Sleep 1
Loop Until i=Chr(27)

 

Imortis.
I am not sure what you mean
"You can use OpenGL as the backend for FBGFX by using the flag for in screenres"

I see two new constants in fbgfx.bi

'Constants for OpenGL 2D render
const as integer OGL_2D_NONE = 0, _
OGL_2D_MANUAL_SYNC = 1, _
OGL_2D_AUTO_SYNC = 2

But I see no reference in the help files.
Imortis
Moderator
Posts: 1734
Joined: Jun 02, 2005 15:10
Location: USA
Contact:

Re: fbgfx versus opengl graphics

Postby Imortis » Apr 03, 2020 15:28

dodicat wrote:Imortis.
I am not sure what you mean
"You can use OpenGL as the backend for FBGFX by using the flag for in screenres"

I see two new constants in fbgfx.bi

'Constants for OpenGL 2D render
const as integer OGL_2D_NONE = 0, _
OGL_2D_MANUAL_SYNC = 1, _
OGL_2D_AUTO_SYNC = 2

But I see no reference in the help files.


My Mistake: Here in the Screen Control:
https://www.freebasic.net/wiki/wikka.php?wakka=KeyPgScreencontrol

You can set OpenGL as the backend driver for FBGFX.
caseih
Posts: 1562
Joined: Feb 26, 2007 5:32

Re: fbgfx versus opengl graphics

Postby caseih » Apr 03, 2020 17:26

I guess my point is that when 2D graphics libraries use OpenGL as a backend, they typically aren't using OpenGL to draw individual pixels or lines. And the FB graphics library isn't either. In fact OpenGL's support for 2D primitives is nearly nonexistent, especially in more modern variants that are pipelined. Rather they are using OpenGL to accelerate the blitting of an entire frame to the screen, possibly compositing different images or layers together rapidly. In the FB graphics library source code, all pixel operations occur on in a buffer in memory, and the the backend uses the appropriate means to copy it to the screen at a certain frame rate. Operations like sprites and working with images can be done with OpenGL, where each of these things is texture that's then composited together in the GPU. This is where OpenGL can really accelerate 2D things.

I just spent a few minutes browsing the FB graphics library source code and with OpenGL as the backend, it is defining the FB framebuffer as a texture, and then painting it on the screen by applying it to two triangles. PSET, LINE, etc, are all just manipulating that texture buffer.
h4tt3n
Posts: 694
Joined: Oct 22, 2005 21:12
Location: Denmark

Re: fbgfx versus opengl graphics

Postby h4tt3n » Apr 09, 2020 16:10

Imortis wrote:My Mistake: Here in the Screen Control:
https://www.freebasic.net/wiki/wikka.php?wakka=KeyPgScreencontrol

You can set OpenGL as the backend driver for FBGFX.


I'm having a little trouble deciphering the info from the link and getting this to work. I keep getting the following error.

"error 42: Variable not declared, SET_GL_2D_MODE"

Could you please provide a simple proof-of-concept example?


Cheers, Mike
SARG
Posts: 1165
Joined: May 27, 2005 7:15
Location: FRANCE

Re: fbgfx versus opengl graphics

Postby SARG » Apr 09, 2020 16:36

With lang fb it's in namespace FB

fb.GET_WINDOW_TITLE works.
paul doe
Posts: 1334
Joined: Jul 25, 2017 17:22
Location: Argentina

Re: fbgfx versus opengl graphics

Postby paul doe » Apr 09, 2020 19:51

h4tt3n wrote:...
I'm having a little trouble deciphering the info from the link and getting this to work. I keep getting the following error.

"error 42: Variable not declared, SET_GL_2D_MODE"
...

Are you using the latest 'public' release of FreeBasic (1.07.1)?

Return to “Tips and Tricks”

Who is online

Users browsing this forum: No registered users and 7 guests