This article describes the possible side effects of state handling and proposes new code style which should help you write modular graphic code of better quality.
To demonstrate the issue, let's presume this model case with 2 drawing functions, DrawPositionMarker and DrawGrid:
FUNCTION DrawPositionMarker(x As Single, y As Single) TBGL_PushMatrix ' -- Enable red color TBGL_Color(255, 0, 0) TBGL_Translate(x, y) ' -- Draw the cross TBGL_BeginPoly(%GL_LINES) TBGL_Vertex(-1, 0 ) TBGL_Vertex( 1, 0 ) TBGL_Vertex( 0,-1 ) TBGL_Vertex( 0, 1 ) TBGL_EndPoly TBGL_PopMatrix END FUNCTION FUNCTION DrawGrid(width As Single, height As Single, gridStep As single) Single i TBGL_BeginPoly(%GL_LINES) FOR i = -width/2 to width/2 step gridStep TBGL_Vertex( i, -height/2 ) TBGL_Vertex( i, height/2 ) NEXT FOR i = -height/2 to height/2 step gridStep TBGL_Vertex( -width/2, i ) TBGL_Vertex( width/2, i ) NEXT TBGL_EndPoly END FUNCTION
DrawPositionMarker(1, 1) DrawGrid(10, 5, 1)
State leaking can cause unexpected results and graphical glitches as well, take for example this reversed case:
DrawGrid(10, 5, 1) DrawPositionMarker(1, 1)
TBGL state handling
To prevent this group of problems, TBGL present in ThinBASIC 1.9.1.0 (and newer) introduces new safe state functionality.
The whole concept is based on Push/Pop pairs of commands. The Push command sets some state, and remembers the previous value. Once the matching Pop command is executed, everything is returned back to previous state.
Little illustration:
TBGL_PushColor(255, 0, 0) ' -- Pushing red color as active, remembering previous color tbgl_Sphere 1 ' -- Therefore this sphere will be rendered in red TBGL_PushColor(0, 255, 0) ' -- Pushing blue color as active, remembering previous red TBGL_Box 1, 1, 1 ' -- This box will be rendered in blue TBGL_PopColor ' -- Pop command will restore the color back to previous = red tbgl_Torus 0.5, 2 ' -- Therefore this torus will be rendered in red again TBGL_PopColor ' -- Pop command will restore the color back to previous, whatever it was
- Creating code block isolating transformations (present in OpenGL as well):
- TBGL_PushMatrix / TBGL_PopMatrix
- Creating code block with forced use states (TBGL specific):
- TBGL_PushState / TBGL_PopState
- Creating code block with disabled specified states (TBGL specific):
- TBGL_PushStateProtect / TBGL_PopStateProtect
- Creating code block with specific numeric state (TBGL specific, new in ThinBASIC 1.9.0.0):
- tbgl_PushAlphaFunc / tbgl_PopAlphaFunc
- tbgl_PushBlendFunc / tbgl_PopBlendFunc
- tbgl_PushColor / tbgl_PopColor
- tbgl_PushDepthFunc / tbgl_PopDepthFunc
- tbgl_PushLineWidth / tbgl_PopLineWidth
- tbgl_PushLineStipple / tbgl_PopLineStipple
- tbgl_PushPointSize / tbgl_PopPointSize
- tbgl_PushPolygonLook / tbgl_PopPolygonLook
- tbgl_PushTexture / tbgl_PopTexture
Conclusion
While using direct state changes is tempting and straightforward, everybody writing code units or routines meant to be reused without state conflicts should consider taking advantage of arsenal of TBGL Push/Pop state safe commands. The syntax is the same as for direct calls, except the additional Push and enclosing Pop, and it can really save some time otherwise spent investigating where the state change occurred.
Message