Announcement

Collapse

Maintenance

The forum could be offline for 30-60 minutes in the very near future for maintenance (said 3pm Pacific). I was behind on getting this notice. I do apologize.
See more
See less

%pfd_doublebuffer

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Doug Hitchens
    replied
    I know this is an old post, but I'm working on print previews for opengl code, and this ties into it. The following is Gary's code above, modified to draw opengl into a dibsection. While the pixel format is set up as single buffer, the dibsection is essentially the new "back buffer". Using this technique:

    1. Essentially double buffers..
    2. Can directly draw your opengl scene to the dibsection, ALONG with GDI commands. For my purpose, these will generally be pretty simple uses, map legend, map heading, north arrow etc.
    3. Most print drivers support StretchDIBits function, which allows direct copying to a printer context (you would want to make sure the glClearColor is white).

    Code:
    'Compilable Example:
    #COMPILE EXE
    #DIM ALL
    #INCLUDE "win32api.inc"
    #INCLUDE "gl.inc"
    #INCLUDE "glu.inc"
    
    %ID_Timer = 1000
    
    %backred=100
    %backgrn=100
    %backblu=100
    
    %timerms=50
    
    FUNCTION PBMAIN() AS LONG
      LOCAL hDlg AS DWORD
      DIALOG NEW PIXELS, 0, "OpenGL DIBSection Example",,, 320, 240, %WS_OVERLAPPEDWINDOW TO hDlg
      DIALOG SHOW MODAL hdlg CALL dlgproc
    END FUNCTION
    
    CALLBACK FUNCTION dlgproc()
       STATIC SpinInWork,XLast,YLast AS LONG
       STATIC DibPtr, memDC, hDC, hRC, hDIB AS DWORD
       STATIC bmInfo AS BITMAPINFO
       STATIC scalefactor AS SINGLE
       LOCAL pt AS POINT
       LOCAL XDelta, YDelta AS SINGLE
       LOCAL rc AS rect
    
       SELECT CASE CB.MSG
          CASE %WM_INITDIALOG
            ogerr(1)
            GetClientRect(CB.HNDL, rc)
            hDC=GetDC(CB.HNDL)
            hDIB=CreateDIB(rc.right*3, rc.bottom*3, DibPtr, memDC, bminfo)
            SetBkMode(memDC, %TRANSPARENT)
            hRC=GetRenderContext(CB.HNDL, memDC, hDIB)
            IF ISFALSE(hRC) THEN
              ? "Couldn't Create Render Context, Exiting."
              DestroyWindow(CB.HNDL)
              EXIT FUNCTION
            END IF
            InitializeScene
            ScaleFactor=1
            ResizeScene(bminfo)
            ogerr(0)
            SetTimer(CB.HNDL, %ID_Timer, %timerms, %NULL)
          CASE %WM_TIMER, %WM_SIZE : DrawScene(CB.HNDL, 1,1,1, scalefactor, DibPtr, bminfo)  'redraw with rotation on all 3 axes
          CASE %WM_PAINT : RefreshScene(CB.HNDL, DibPtr, bminfo)
          CASE %WM_CLOSE
            wglmakecurrent %null, %null 'unselect rendering context
            wgldeletecontext hRC        'delete the rendering context
            IF hDib THEN DeleteObject(hDIB) 'delete the DIB object handle
            ReleaseDC(CB.HNDL, hDC)         'release device context
          CASE %WM_MOUSEWHEEL
             SELECT CASE HI(INTEGER,CB.WPARAM)
                CASE > 0
                  ScaleFactor = ScaleFactor + 0.1
                  DrawScene(CB.HNDL,0,0,0, scalefactor, DibPtr, bminfo)
                CASE < 0
                  ScaleFactor = ScaleFactor - 0.1
                  DrawScene(CB.HNDL,0,0,0, scalefactor, DibPtr, bminfo)
             END SELECT
          CASE %WM_LBUTTONDOWN
             KillTimer CB.HNDL, %ID_Timer
             SpinInWork = 1
             GetCursorPos(pt)              'pt has xy screen coordinates
             ScreenToClient(hDC, pt)       'pt now has dialog client coordinates
             XLast = Pt.x
             YLast = Pt.y
          CASE %WM_MOUSEMOVE
             IF SpinInWork THEN
                GetCursorPos(pt)           'pt has xy screen coordinates
                ScreenToClient(hDC, pt)    'pt now has dialog client coordinates
                XDelta = XLast - Pt.x
                YDelta = YLast - Pt.y
                DrawScene(CB.HNDL,-YDelta, -XDelta, 0, scalefactor, DibPtr, bminfo)
                XLast = pt.x
                YLast = pt.y
             END IF
          CASE %WM_LBUTTONUP
             SetTimer(CB.HNDL, %ID_Timer, %timerms, %NULL)
             SpinInWork = 0
       END SELECT
    END FUNCTION
    
    FUNCTION GetRenderContext(BYVAL hwnd AS DWORD, memDC AS DWORD, BYVAL hDib AS DWORD) AS DWORD
       LOCAL lresult  AS LONG
       LOCAL pfd      AS PIXELFORMATDESCRIPTOR   'pixel format properties for device context
       LOCAL hRC    AS DWORD
    
       pfd.nSize       =  SIZEOF(PIXELFORMATDESCRIPTOR)
       pfd.nVersion    =  1
       pfd.dwFlags     = %PFD_DRAW_TO_WINDOW OR %PFD_SUPPORT_OPENGL OR %PFD_DRAW_TO_BITMAP OR %PFD_SUPPORT_GDI
       pfd.dwlayermask = %pfd_main_plane
       pfd.iPixelType  = %pfd_type_rgba
       pfd.ccolorbits  = 24
       pfd.cdepthbits  = 32
    
       SelectObject(memDC, hDIB)
       SetPixelFormat(memDC, ChoosePixelFormat(memDC, pfd), pfd)
    
       hRC=wglCreateContext(memDC)      'get rendering context
       IF hRC THEN wglMakeCurrent memDC, hRC  'Make the RC current
       FUNCTION=hRC
    END FUNCTION
    
    SUB InitializeScene
       glClearColor(%backred/255,%backgrn/255,%backblu/255,0)
       glClearDepth 1           'sets zvalue to be used with glClear
       glEnable %gl_depth_test                             'enable depth testing
       glHint %gl_perspective_correction_hint, %gl_nicest  'best quality rendering
       BuildDisplayList 1
    END SUB
    
    SUB ResizeScene (BYREF bminfo AS BITMAPINFO)
       glViewport 0, 0, bmInfo.bmiHeader.biWidth, bmInfo.bmiHeader.biHeight 'resize viewport to match DIBSECTION size
       glMatrixMode %gl_projection         'select the projection matrix
       glLoadIdentity                    'reset the projection matrix
       gluPerspective 45, bmInfo.bmiHeader.biWidth/bmInfo.bmiHeader.biHeight, 0.1, 100  'set frustum using viewport aspect ratio
       glMatrixMode %gl_modelview          'select the modelview matrix
    END SUB
    
    SUB DrawScene (BYVAL hWnd AS DWORD, dx AS SINGLE, dy AS SINGLE, dz AS SINGLE, scalef AS SINGLE, BYVAL DibPtr AS DWORD, BYREF bminfo AS BITMAPINFO)
       STATIC errcnt AS LONG
       STATIC anglex, angley, anglez AS SINGLE
       LOCAL rc AS rect
       glClear(%gl_color_buffer_bit OR %gl_depth_buffer_bit)  'clear buffers
       glLoadIdentity               'clear the modelview matrix
    
       gluLookAt 0,0,6,0,0,0,0,1,0
    
       glScalef scalef, scalef, scalef
    
       anglex = anglex + dx : glRotatef anglex, 1,0,0
       angley = angley + dy : glRotatef angley, 0,1,0
       anglez = anglez + dz : glRotatef anglez, 0,0,1
    
       glCallList 1
       IF DibPtr THEN
         glFinish
         Draw_GDI(wglGetCurrentDC(), 1, bminfo) : GdiFlush()
         RefreshScene(hWnd, DibPtr, bminfo)
       END IF
       IF errcnt=0 THEN errcnt=ogerr(0) 'for testing, check oglerr, but just display once..
    END SUB
    
    SUB RefreshScene(BYVAL hWnd AS DWORD, BYVAL DibPtr AS DWORD, BYREF bminfo AS BITMAPINFO)
      'just simply copies dib to screen DC, call on
      'an updated scene, or a wm_paint
      'This will stretch the bitmap to screen, so some distortion may be seen
      'when resizing the screen.  To combat this, one would need to delete the current
      'DIB, create a new one with the new screen aspect, and delete and create a new render context
      ' OR
      'allow resize, but keep original aspect ratio (like with a print preview)
      LOCAL rc AS rect
      LOCAL hDC AS DWORD
      GetClientRect(hWnd, rc)
      hDC=GetDC(hWnd)
      StretchDIBits(hDC, _
                    0, _
                    0, _
                    rc.right, _
                    rc.bottom, _
                    0, _
                    0, _
                    bmInfo.bmiHeader.biWidth, _
                    bmInfo.bmiHeader.biHeight, _
                    BYVAL DibPtr, _
                    BYVAL VARPTR(bminfo), _
                    %DIB_RGB_COLORS, _
                    %SRCCOPY)
      ReleaseDC(hWnd, hDC)
    END SUB
    
    SUB DRAW_GDI(BYVAL hDibDC AS DWORD, BYVAL inc AS LONG, BYREF bminfo AS BITMAPINFO)  '<<<<<<<<<<<DH
      'Draw GDI Stuff here...for testing
      LOCAL teststr AS STRING
      LOCAL TXT AS SIZE
      STATIC dflg AS LONG
      STATIC x AS LONG
    
      teststr="THIS IS A HAPPY LITTLE GDI TEST.."
    
      GetTextExtentPoint32(hDibDC, BYVAL STRPTR(teststr), LEN(teststr), TXT)
      IF dflg THEN
        x-=inc
        IF x<0 THEN x=0 : dflg=0
      ELSE
        x+=inc
        IF (x+txt.cx)>bmInfo.bmiHeader.biWidth THEN x=bmInfo.bmiHeader.biWidth-txt.cx : dflg=1
      END IF
      Textout(hDibDC, X, 100, BYVAL STRPTR(teststr), LEN(teststr))
    END SUB
    
    SUB BuildDisplayList(ListNumber AS LONG)
       glNewList ListNumber, %gl_compile
          glBegin %GL_QUADS
             glColor3f   0.0,  1.0,  0.0         ' Set the color to green
             glVertex3f  1.0,  1.0, -1.0         ' Top right of the quad (Top)
             glVertex3f -1.0,  1.0, -1.0         ' Top left of the quad (Top)
             glVertex3f -1.0,  1.0,  1.0         ' Bottom left of the quad (Top)
             glVertex3f  1.0,  1.0,  1.0         ' Bottom right of the quad (Top)
    
             glColor3f   1.0,  0.5,  0.0         ' Set the color to orange
             glVertex3f  1.0, -1.0,  1.0         ' Top right of the quad (Bottom)
             glVertex3f -1.0, -1.0,  1.0         ' Top left of the quad (Bottom)
             glVertex3f -1.0, -1.0, -1.0         ' Bottom left of the quad (Bottom)
             glVertex3f  1.0, -1.0, -1.0         ' Bottom right of the quad (Bottom)
    
             glColor3f   1.0,  0.0,  0.0         ' Set the color to red
             glVertex3f  1.0,  1.0,  1.0         ' Top right of the quad (Front)
             glVertex3f -1.0,  1.0,  1.0         ' Top left of the quad (Front)
             glVertex3f -1.0, -1.0,  1.0         ' Bottom left of the quad (Front)
             glVertex3f  1.0, -1.0,  1.0         ' Bottom right of the quad (Front)
    
             glColor3f   1.0,  1.0,  0.0         ' Set the color to yellow
             glVertex3f  1.0, -1.0, -1.0         ' Top right of the quad (Back)
             glVertex3f -1.0, -1.0, -1.0         ' Top left of the quad (Back)
             glVertex3f -1.0,  1.0, -1.0         ' Bottom left of the quad (Back)
             glVertex3f  1.0,  1.0, -1.0         ' Bottom right of the quad (Back)
    
             glColor3f   0.0,  0.0,  1.0         ' Set the color to blue
             glVertex3f -1.0,  1.0,  1.0         ' Top right of the quad (Left)
             glVertex3f -1.0,  1.0, -1.0         ' Top left of the quad (Left)
             glVertex3f -1.0, -1.0, -1.0         ' Bottom left of the quad (Left)
             glVertex3f -1.0, -1.0,  1.0         ' Bottom right of the quad (Left)
    
             glColor3f   1.0,  0.0,  1.0         ' Set the color to violet
             glVertex3f  1.0,  1.0, -1.0         ' Top right of the quad (Right)
             glVertex3f  1.0,  1.0,  1.0         ' Top left of the quad (Right)
             glVertex3f  1.0, -1.0,  1.0         ' Bottom left of the quad (Right)
             glVertex3f  1.0, -1.0, -1.0         ' Bottom right of the quad (Right)
          glEnd
       glEndList
    END SUB
    
    FUNCTION CreateDIB(BYVAL w AS LONG, BYVAL h AS LONG, BYREF DibPtr AS DWORD, BYREF memDC AS DWORD, BYREF bminfo AS BITMAPINFO) AS DWORD '(byval tpg as dword) AS LONG
      memDC=CreateCompatibleDC(0) : IF memDC=0 THEN EXIT FUNCTION
      bmInfo.bmiHeader.biSize        = SIZEOF(bmInfo.bmiHeader)
      bmInfo.bmiHeader.biWidth       = w
      bmInfo.bmiHeader.biHeight      = h
      bmInfo.bmiHeader.biPlanes      = 1
      bmInfo.bmiHeader.biBitCount    = 32
      bmInfo.bmiHeader.biCompression = %BI_RGB
      bmInfo.bmiHeader.biSizeImage   = 0 'since BI_RGB, set to 0 (no compression)
      FUNCTION=CreateDIBSection(memDC, bmInfo, %DIB_RGB_COLORS, BYVAL VARPTR(DibPtr), %null, %null)
    END FUNCTION
    
    FUNCTION ogerr(BYVAL silent AS LONG) AS LONG
        LOCAL lresult AS LONG
        lresult=glGetError()
        FUNCTION=lresult
        IF silent THEN EXIT FUNCTION
        SELECT CASE lresult
            CASE %GL_INVALID_ENUM      : ? "Invalid Value as enumeration"
            CASE %GL_INVALID_VALUE     : ? "value out of range"
            CASE %GL_INVALID_OPERATION : ? "Invalid Operation"
            CASE %GL_NO_ERROR
            CASE %GL_STACK_OVERFLOW    : ? "stack overflow"
            CASE %GL_STACK_UNDERFLOW   : ? "stack underflow"
            CASE %GL_OUT_OF_MEMORY     : ? "Out of Memory"
        END SELECT
    END FUNCTION

    Leave a comment:


  • Gary Beene
    replied
    But Jose,
    Thinking on it a bit more ...

    When replacing %pfd_doublebuffer with %pfd_support_gdi, so I can use Graphic drawing statements on a graphic control, I can see flickering in the Graphic control during animation (code example below).

    That means if I want both OpenGL and Graphic statements, I'll have to implement my own buffering. One more constraint to be aware of.

    Example of flickering (imperfectly formed cube in image):



    Code:
    'Compilable Example:
    #Compile Exe
    #Dim All
    #Include "win32api.inc"
    #Include "gl.inc"
    #Include "glu.inc"
    
    %ID_Timer = 1000
    
    Global hDlg, hDC, hRC As Dword
    Global anglex, angley, anglez, scalefactor As Single
    
    Function PBMain() As Long
      Dialog New Pixels, 0, "OpenGL Example",,, 320, 240,%WS_OverlappedWindow To hDlg
      Dialog Show Modal hdlg Call dlgproc
    End Function
    
    CallBack Function dlgproc()
       Local pt As Point
       Local XDelta, YDelta As Single
       Static SpinInWork,XLast,YLast As Long
    
       Select Case Cb.Msg
          Case %WM_InitDialog : GetRenderContext
                                InitializeScene
                                SetTimer(hDlg, %ID_Timer, 50, %NULL)
                                ScaleFactor = 1
          Case %WM_Timer      : DrawScene 1,1,1  'redraw with rotation on all 3 axes
          Case %WM_Paint      : DrawScene 0,0,0  'redraw with no rotation
          Case %WM_Size       : ResizeScene Lo(Word, Cb.LParam), Hi(Word, Cb.LParam)
                                DrawScene 0,0,0  'redraw with no rotation
          Case %WM_Close      : wglmakecurrent %null, %null 'unselect rendering context
                                wgldeletecontext hRC        'delete the rendering context
                                releasedc hDlg, hDC         'release device context
          Case %WM_MouseWheel
             Select Case Hi(Integer,Cb.WParam)
                Case > 0  : ScaleFactor = ScaleFactor + 0.1 : DrawScene 0,0,0
                Case < 0  : ScaleFactor = ScaleFactor - 0.1 : DrawScene 0,0,0
             End Select
          Case %WM_SetCursor
             Select Case Hi(Word, Cb.LParam)
                Case %WM_LButtonDown
                   KillTimer Cb.Hndl, %ID_Timer
                   SpinInWork = 1
                   GetCursorPos pt              'pt has xy screen coordinates
                   ScreenToClient hDC, pt       'pt now has dialog client coordinates
                   XLast = Pt.x
                   YLast = Pt.y
                Case %WM_MouseMove
                   If SpinInWork Then
                      GetCursorPos pt           'pt has xy screen coordinates
                      ScreenToClient hDC, pt    'pt now has dialog client coordinates
                      XDelta = XLast - Pt.x
                      YDelta = YLast - Pt.y
                      DrawScene -YDelta, -XDelta, 0
                      XLast = pt.x
                      YLast = pt.y
                   End If
                Case %WM_LButtonUp
                   SetTimer(hDlg, %ID_Timer, 50, %NULL)
                   SpinInWork = 0
             End Select
       End Select
    End Function
    
    Sub GetRenderContext
       Local pfd As PIXELFORMATDESCRIPTOR   'pixel format properties for device context
       pfd.nSize       =  SizeOf(PIXELFORMATDESCRIPTOR)
       pfd.nVersion    =  1
       pfd.dwFlags     = %pfd_draw_to_window Or %pfd_support_opengl Or %pfd_support_gdi
       pfd.dwlayermask = %pfd_main_plane
       pfd.iPixelType  = %pfd_type_rgba
       pfd.ccolorbits  = 24
       pfd.cdepthbits  = 24
    
       hDC = GetDC(hDlg)                                      'DC for dialog
       SetPixelFormat(hDC, ChoosePixelFormat(hDC, pfd), pfd)  'set properties of device context
       hRC = wglCreateContext (hDC)                           'get rendering context
       wglMakeCurrent hDC, hRC                                'make the RC current
    End Sub
    
    Sub InitializeScene
       glClearColor 0,0,0,0     'sets color to be used with glClear
       glClearDepth 1           'sets zvalue to be used with glClear
       glEnable %gl_depth_test                             'enable depth testing
       glHint %gl_perspective_correction_hint, %gl_nicest  'best quality rendering
       BuildDisplayList 1
    End Sub
    
    Sub ResizeScene (w As Long, h As Long)
       glViewport 0, 0, w, h               'resize viewport to match window size
       glMatrixMode %gl_projection         'select the projection matrix
       glLoadIdentity                    'reset the projection matrix
       gluPerspective 45, w/h, 0.1, 100  'set frustum using viewport aspect ratio
       glMatrixMode %gl_modelview          'select the modelview matrix
    End Sub
    
    Sub DrawScene (dx As Single, dy As Single, dz As Single)
       glClear %gl_color_buffer_bit Or %gl_depth_buffer_bit  'clear buffers
       glLoadIdentity               'clear the modelview matrix
    
       gluLookAt 0,0,6,0,0,0,0,1,0
    
       glScalef scalefactor, scalefactor, scalefactor
    
       anglex = anglex + dx : glRotatef anglex, 1,0,0
       angley = angley + dy : glRotatef angley, 0,1,0
       anglez = anglez + dz : glRotatef anglez, 0,0,1
    
       glCallList 1
    
       SwapBuffers hDC              'display the buffer (image)
    End Sub
    
    Sub BuildDisplayList(ListNumber As Long)
       glNewList ListNumber, %gl_compile
          glBegin %GL_QUADS
             glColor3f   0.0,  1.0,  0.0         ' Set the color to green
             glVertex3f  1.0,  1.0, -1.0         ' Top right of the quad (Top)
             glVertex3f -1.0,  1.0, -1.0         ' Top left of the quad (Top)
             glVertex3f -1.0,  1.0,  1.0         ' Bottom left of the quad (Top)
             glVertex3f  1.0,  1.0,  1.0         ' Bottom right of the quad (Top)
    
             glColor3f   1.0,  0.5,  0.0         ' Set the color to orange
             glVertex3f  1.0, -1.0,  1.0         ' Top right of the quad (Bottom)
             glVertex3f -1.0, -1.0,  1.0         ' Top left of the quad (Bottom)
             glVertex3f -1.0, -1.0, -1.0         ' Bottom left of the quad (Bottom)
             glVertex3f  1.0, -1.0, -1.0         ' Bottom right of the quad (Bottom)
    
             glColor3f   1.0,  0.0,  0.0         ' Set the color to red
             glVertex3f  1.0,  1.0,  1.0         ' Top right of the quad (Front)
             glVertex3f -1.0,  1.0,  1.0         ' Top left of the quad (Front)
             glVertex3f -1.0, -1.0,  1.0         ' Bottom left of the quad (Front)
             glVertex3f  1.0, -1.0,  1.0         ' Bottom right of the quad (Front)
    
             glColor3f   1.0,  1.0,  0.0         ' Set the color to yellow
             glVertex3f  1.0, -1.0, -1.0         ' Top right of the quad (Back)
             glVertex3f -1.0, -1.0, -1.0         ' Top left of the quad (Back)
             glVertex3f -1.0,  1.0, -1.0         ' Bottom left of the quad (Back)
             glVertex3f  1.0,  1.0, -1.0         ' Bottom right of the quad (Back)
    
             glColor3f   0.0,  0.0,  1.0         ' Set the color to blue
             glVertex3f -1.0,  1.0,  1.0         ' Top right of the quad (Left)
             glVertex3f -1.0,  1.0, -1.0         ' Top left of the quad (Left)
             glVertex3f -1.0, -1.0, -1.0         ' Bottom left of the quad (Left)
             glVertex3f -1.0, -1.0,  1.0         ' Bottom right of the quad (Left)
    
             glColor3f   1.0,  0.0,  1.0         ' Set the color to violet
             glVertex3f  1.0,  1.0, -1.0         ' Top right of the quad (Right)
             glVertex3f  1.0,  1.0,  1.0         ' Top left of the quad (Right)
             glVertex3f  1.0, -1.0,  1.0         ' Bottom left of the quad (Right)
             glVertex3f  1.0, -1.0, -1.0         ' Bottom right of the quad (Right)
          glEnd
       glEndList
    End Sub
    Last edited by Gary Beene; 20 Mar 2013, 06:36 PM.

    Leave a comment:


  • Gary Beene
    replied
    Hi Jose,
    I've gone to MSDN, here, and read of the constraint. Thanks for pointing me there.

    Leave a comment:


  • José Roca
    replied
    These flags are mutually exclusive in the current implementation of OpenGL.

    Leave a comment:


  • Gary Beene
    started a topic %pfd_doublebuffer

    %pfd_doublebuffer

    When using %pfd_support_gdi, to allow Graphic statements to draw to a Graphic control that is used as the OpenGL rendering context, I noticed that I cannot use %pfd_doublebuffer. If I do, the Graphic statements are not drawn.

    However (trying to head off an expected response), let's not jump to the conclusion of "Well, then, don't use a Graphic control!".

    I'd like to understand all the limitations first. A couple of constraints (DC source and %pfd_doublebuffer) aren't enough to make a no-use decision.
Working...
X