  #compact
  $ title     "Shaders and Index Buffer Objects"
  $ FileName  "t.exe"
' uses RTL64
  uses Axial

  'globals
  '=====
  '
  indexbase 1
  sys  VertBuf,NormBuf,TexBuf,IndexBuf
  int  ShaderShn,ShaderSky,ShaderRfl,ShaderFlat
  int  VBOs 'flag VBOs in use
  int  vbo[16]
  int  VertCount
  '
  int    cube,sphere,cylinder,tors,helix,vessel
  int    TexSky
  int    ShnUL[4]
  int    SkyUL[4]
  int    RflUL[4]
  float  cameraPosition[3]
  float  NormalMatrix[9]
  float  ModelMatrix[16]
  float  ModelMatrixInverse[16]
  float  Tint
  '
  string glExt
  '
  '
  sub BuildVertexArrays()
  =======================
   '
  indexbase 1
  '
  'CREATE DATA BUFFERS
  '
  VertCount=4
  sys n=100
  '
  VertBuf=getmemory n*sizeof vert
  NormBuf=getmemory n*sizeof vert
  TexBuf=getmemory n*sizeof tex
  IndexBuf=getmemory n*sizeof int

  '
  vert v at VertBuf
  v={-1.0,-1.0,0.0, 1.0, 0.-1,0.0,  1.0,1.0,0.0, -1.0,1.0,0.0}
  vert v at NormBuf
  v={0.0,0.0,1.0, 0.0,0.0,1.0, 0.0,0.0,1.0, 0.0,0.0,1.0}
  tex v at Texbuf
  v={ 0.0,0.0,  1.0, 0.0,  1.0,1.0,  0.0,1.0}
  int i at IndexBuf
  i={0,1,2,3}
  '
  if VBOs
    '
    glGenBuffers( 4, vbo )
    '
    macro setup(i,n,type,buf,m)
      glBindBuffer m, vbo[i]
      glBufferData m, n*sizeof(type), buf, GL_STATIC_DRAW
    end macro
    '
    n=VertCount
    setup 1,n,Vert,VertBuf,GL_ARRAY_BUFFER
    setup 2,n,Vert,NormBuf,GL_ARRAY_BUFFER
    setup 3,n,Tex,TexBuf,GL_ARRAY_BUFFER
    setup 4,n,Int,IndexBuf,GL_ELEMENT_ARRAY_BUFFER
    '
    freememory VertBuf
    freememory NormBuf
    freememory TexBuf
    freememory IndexBuf
  end if
  end sub

  sub DrawVertexArrays(optional int m)
  ====================================
  '
  sys ib 'index buffer
  glClientActiveTexture(GL_TEXTURE0)
  '
  glEnableClientState( GL_VERTEX_ARRAY )						// Enable Vertex Arrays
  glEnableClientState( GL_NORMAL_ARRAY )						// Enable Vertex Arrays
  glEnableClientState( GL_TEXTURE_COORD_ARRAY )
  '
  if VBOs
    static int loaded
    if m then loaded=0 'reload buffers
    if not loaded
      glBindBuffer( GL_ARRAY_BUFFER, vbo[1] )
      glVertexPointer( 3, GL_FLOAT, 0, null )
      '
      glBindBuffer( GL_ARRAY_BUFFER, vbo[2] )
      glNormalPointer( GL_FLOAT, 0, null )
      '
      glBindBuffer( GL_ARRAY_BUFFER, vbo[3] )
      glTexCoordPointer( 2, GL_FLOAT, 0, null )
      '
      glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, vbo[4] )
      loaded=1
    end if
    ib=0
    '
  else
    glVertexPointer  ( 3, GL_FLOAT, 0, VertBuf )
    glNormalPointer  (    GL_FLOAT, 0, NormBuf )
    glTexCoordPointer( 2, GL_FLOAT, 0, TexBuf )
    ib=IndexBuf
  end if
  'glDrawArrays( GL_QUADS, 0, VertCount )
  glDrawElements( GL_QUADS, VertCount, GL_UNSIGNED_INT, ib )
  'Disable Pointers
  glDisableClientState( GL_VERTEX_ARRAY )
  glDisableClientState( GL_NORMAL_ARRAY )						// Enable Vertex Arrays
  glClientActiveTexture(GL_TEXTURE0)
  glDisableClientState( GL_TEXTURE_COORD_ARRAY )
  end sub



  sub initialize(sys hWnd)
  '=======================
  '
  finit
  int a
  SetupExtFunctions
  '
  GDIplus 1
  '
 ' glClientActiveTexture(GL_TEXTURE0)
  '
  LoadCubicTextures (
  "..\..\images\SkyBox\left.jpg",
  "..\..\images\SkyBox\right.jpg",
  "..\..\images\SkyBox\bottom.jpg",
  "..\..\images\SkyBox\top.jpg",
  "..\..\images\SkyBox\front.jpg",
  "..\..\images\SkyBox\back.jpg",
  TexSkY
  )
  'COMPILED GEOMETRY LISTS
  cube=CompileList   : CubeForm 1      : glEndList
  sphere=CompileList : Spheric 1,1,6 : glEndList
  cylinder = CompileList
  'glRotatef 180,1,0,0
  'Conefaces  18,0,0,1 'BASE CAP 
  'glRotatef 180,1,0,0
  Conefaces  18,1,1,1,1 'SIDE
  'glTranslatef 0,1,0 
  'Conefaces  18,0,0,1 'TOP CAP 
  'glTranslatef 0,-1,0 
  glEndList
  tors=CompileList   : torus 1.,.20  : glEndList
  helix=CompileList : toroid 1.,.25,.8,.16,5.,6. : glEndList
  vessel = CompileList
  glRotatef 180,1,0,0
  Conefaces  32,0,0.5,1,1 'BASE CAP 
  glRotatef 180,1,0,0
  Conefaces  32,1,1,1,1   'SIDE
  glTranslatef 0,1,0 
  Conefaces  18,0,1,1,1   'TOP CAP 
  glTranslatef 0,-1,0 
  glEndList
  '
  zstring z at glGetString GL_EXTENSIONS
  glExt=replace(z, chr(32),chr(13,10))
  'putfile "s.txt", glExt
  '
  '
  shaders()
  '1  'MINIMAL
  '2  'PER PIXEL
  '3  'PHONG
  '4  'MULTIPLE LIGHTS 
  '5  'MULTIPLE LIGHTS AND TEXTURING
  '6  'SWAP COLORS
  '7  'COMBINED MULTIPLE LIGHTS AND TEXTURING AND REFLECTION
  '8  'SKY BOX
  '9  'CUBIC REFLECTION 1
  '10 'CUBIC REFLECTION 2
  '11 'CUBIC REFLECTION 3
  '12 '3.3 LIGHT MATERIAL AND CUBIC REFLECTION ALPHA SHADER
  '13 'SKY BOX using own Projection & ModelView
  '14 'FLAT COLOR
  
  '
  CreateShaderProg ps[1]
  CreateShaderProg ps[4]
  CreateShaderProg ps[5]
  CreateShaderProg ps[7]
  CreateShaderProg ps[8]
  CreateShaderProg ps[9]
  CreateShaderProg ps[10]
  CreateShaderProg ps[11]
  CreateShaderProg ps[12]
  CreateShaderProg ps[14]
  '
  ShaderShn=ps[5].ph
  ShaderSky=ps[8].ph
  ShaderRfl=ps[11].ph
  ShaderFlat=ps[14].ph
  '
  '
  SkyUL[4] = glGetUniformLocation(ps[8].ph, "CubeMap")
  '
  'RflUL[1] = glGetUniformLocation(ps[9].ph, "CameraPosition") 
  'RflUL[2] = glGetUniformLocation(ps[9].ph, "NormalMatrix")
  'RflUL[3] = glGetUniformLocation(ps[9].ph, "ModelMatrix")
  'RflUL[4] = glGetUniformLocation(ps[9].ph, "CubeMap")
  '
  RflUL[1] = glGetUniformLocation(ps[11].ph, "CameraPosition") 
  RflUL[2] = glGetUniformLocation(ps[11].ph, "ModelMatrix")
  RflUL[3] = glGetUniformLocation(ps[11].ph, "ModelMatrixInverse")
  RflUL[4] = glGetUniformLocation(ps[11].ph, "CubeMap")
  '
  VBOs=instrword glExt, "GL_ARB_vertex_buffer_object"
  'itr GL_ARB_half_float_pixel
  'itr GL_ARB_half_float_vertex
  'BuildVertexArrays()
  BuildSkyBox()
  '
  end sub


  sub Release(sys hwnd)
  '====================
  sys i
  DeleteAllGlCompiled
  Gdiplus 0
  glDeleteTextures 1,TexSky
  glDeleteBuffers  2, SkyBoxVBO
  if VBOs
    glDeleteBuffers  4, vbo 
  else
    freememory VertBuf
    freememory NormBuf
    freememory TexBuf
    freememory IndexBuf
  end if
  for i=1 to 32
    ReleaseShaderProg ps[i]
  next
  end sub


  sub scene(sys hWnd)
  '==================
  '
  static float s1,s2,ang1,angi1=.5
  '
  BeginPick
  ActiveFrame
 '
  int sky=1, rfl=1, shn=1 'SELECTOR
  '
  if ShaderError then exit sub
  '
  glpopmatrix
  '
  '
  'SKY BOX RENDER
  '==============
  '
  if not pick
    if sky
  '
    'SKY BOX RENDER
    '==============
    '
    glPushMatrix
    glLoadIdentity
    glRotatef 30,-1,0,0 'tilt
    glRotatef Ang1*.4,0,1,0
    glScalef 1000,1000,1000
    DrawSkyBox(TexSky,ShaderSky)
    glPopMatrix

    'glBindTexture(GL_TEXTURE_CUBE_MAP, 0)
    '
    endif 'sky
  endif
  '
  '
  '
  '
  'SHINY RENDER
  '============
  '
  static float tint0={.0,.0,.0,1.}
  static float tint1={.2,.8,.0,1.}
  static float tint2={.0,.4,.2,1.}
  static float tint3={.0,.0,.0,1.}
  static float tint4={.0,.5,.7,1.}
  static float tint5={.3,.5,.3,.6}
  '
  if shn
  '
  int slTint,slTex,slCam,slCube,slCubeMap 'UNIFORM LOCATIONS
  int sh=12 '5 7 or 12 'shiny shader
  int fl=14 'flat color shader index
  '
  if pick
    glUseProgram ps[fl].ph 'FLAT SHADER
  else
    glUseProgram ps[sh].ph 'SHINY SHADER
  endif
  '
  slTint = glGetUniformLocation ps[sh].ph, "Tint"
  slTex  = glGetUniformLocation ps[sh].ph, "TextureUnit"
  slCam  = glGetUniformLocation ps[sh].ph, "CameraPosition"
  slCube = glGetUniformLocation ps[sh].ph, "CubeMap"
  slFlat = glGetUniformLocation ps[fl].ph, "Tint"
  '
  glClientActiveTexture GL_TEXTURE0+0
  glBindTexture GL_TEXTURE_CUBE_MAP, TexSky
  '
  CameraPosition={0,0,0}
  '
  glUniform4fv slCam,  1, CameraPosition
  glUniform1i  slTex,  0  'TEXTURE UNIT
 'glUniform1i slCube,  0  'TEXTURE UNIT

  float a=.5

  'TUMBLING OBJECT
  '---------------

  static moveableobject mu
  if opening
    mu.id=0x12345
  endif
  'picked=0x12345
  '
  glUniform4fv slFlat, 1, tint0
  glUniform4fv slTint, 1, tint2
  '
  glPushMatrix
  glLoadIdentity
  glTranslatef 0.0, 0, -20.0
  'DYNAMIC ROTATIONS:
  'glrotatef ang1*.1, 0,0,1
  'glrotatef ang1*.2, 0,1,0
  'glrotatef ang1*.1, 1,0,0
  mu.act
  'BEFORE TRANSFORMS
  float pq[16]
  glGetFloatv GL_MODELVIEW_MATRIX,pq

  'CALC AXIS
  float rd,rr
  float xt,yt,zt 'translate
  float xs,ys,zs 'scale
  float x1,y1,z1 'base position
  float x2,y2,z2 'end position
  float ax,ay,az 'rotation angles
  'initial
  'SCALE ( cylinder profile)
  xs=0.2
  ys=5.0
  zs=0.2
  'TRANSLATION
  xt=-0.0
  yt=-0.0
  zt=-0.0
  'ORIGIN
  x1=0.0
  y1=0.0
  z1=0.0
  y2=ys
  rd=y2-y1
  rr=rd 'radius
  'ROTATION
  ax=rad(00.0)
  ay=rad(00.0)
  az=rad(00.0)
  'END
  y2=rd*cos(ax)
  z2=rd*sin(ax)
  rd=y2
  y2=rd*cos(az)
  x2=-rd*sin(az)
  'TRANSLATE
  x1+=xt : x2+=xt
  y1+=yt : y2+=yt
  z1+=zt : z2+=zt
  '

  'RENDER AXIS
  glUseProgram ps[fl].ph 'FLAT COLOR SHADER
  picklabel 4
  thickness 5.0
  glbegin GL_LINES
    glvertex3f x1,y1,z1
    glvertex3f x2,y2,z2
  glend
  '
  if pick
    glUseProgram ps[fl].ph 'FLAT COLOR SHADER
  else
    glUseProgram ps[sh].ph 'SHINY SHADER
  endif
  '
  float mt[16]
  TransformToAxis mt,x1,y1,z1,x2,y2,z2,ay
  glLoadIdentity
  glMultMatrixf pq
  float rc=5.0  'radius of circle
  float vh=4.0  'verticals height
  float sa=30.0 'splay angle
  int i
  float ro=0 '
  picklabel 0x12345
  'VERTICALS
  for i=1 to 30
    glpushmatrix
    glrotatef ro,0,1,0
    gltranslatef rc,0,0    'radius of circle
    'glMultMatrixf mt
    'picklabel (10+i)
    '
    glrotatef -sa,0,0,1 'splay
    '
    'glscalef .20,.20,.20
    'go sphere
    'glscalef 5.0,5.0,5.0
    '
    glscalef 0.2,vh,0.2  'shape of cylinder
    go cylinder           'each vertical cylinder
    glpopmatrix
    ro+=12
  next
  '
  'BOTTOM RING
  '
  ro=0
  glLoadIdentity
  glMultMatrixf pq
  float ri=12  'step angle
  float rah=sin(rad(.5*ri))*rc*2.0
 'length of horiz cylinder
  for i=1 to 30
    glpushmatrix
    glrotatef ro,0,1,0
    gltranslatef rc,0,0    'radius of circle
    'glMultMatrixf mt
    'picklabel (10+i)
    glrotatef   0.5*ri,0,1,0 'adust y angle
    glrotatef -90.0,1,0,0 'horizontal
    '
    glscalef 0.1,rah,0.1  'shape of cylinder
    go cylinder           'each cylinder
    glpopmatrix
    ro+=ri
  next
  picklabel 0
  '
  'TOP RING
  '
  rc=5.0+(vh*sin(rad(sa)) ) 'adj for splay angle
  rah=sin(rad(.5*ri))*rc*2.0
  float rh=vh*cos(rad(sa))
  ro=0
  for i=1 to 30
    glpushmatrix
    glrotatef ro,0,1,0
    gltranslatef rc,rh,0    'radius and height of circle
    'glMultMatrixf mt
    'picklabel (10+i)
    glrotatef   0.5*ri,0,1,0 'adust y angle
    glrotatef -90.0,1,0,0 'horizontal
    '
    glscalef 0.1,rah,0.1  'shape of cylinder
    go cylinder           'each cylinder
    glpopmatrix
    ro+=ri
  next
  picklabel 0
  '
  '
  glPopMatrix
  '
  glUseProgram ps[fl].ph 'FLAT COLOR SHADER
  glUniform4fv slFlat, 1, tint1
  glLoadIdentity
  gltranslatef .25,0,-1.0
  glscalef .125,.125,.125
  picklabel 3
  gprint hex picked
  picklabel 0
  '
  glUseProgram -1
  '
  end if 'shn
  '
  EndPick

  'UPDATE ROTATION ANGLES
  '----------------------
  ang1+=.25
  'if ang1>360.0 then ang1-=360.0
  '
  end sub
  MainWindow width,height,WS_OVERLAPPEDWINDOW
