spritebuffer.monkey2 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. Namespace mojo3d
  2. #rem monkeydoc @hidden
  3. #end
  4. Class SpriteBuffer
  5. Method New()
  6. _vbuffer=New VertexBuffer( Vertex3f.Format,0 )
  7. _ibuffer=New IndexBuffer( IndexFormat.UINT32,0 )
  8. End
  9. Method InsertRenderOps( rq:RenderQueue,invViewMatrix:AffineMat4f )
  10. Local spriteOps:=rq.SpriteOps
  11. If spriteOps.Empty Return
  12. Local n:=spriteOps.Length
  13. If n*4>_vbuffer.Length
  14. Local len:=_vbuffer.Length
  15. _vbuffer.Resize( Max( _vbuffer.Length*3/2,n*4 ) )
  16. Endif
  17. If n*6>_ibuffer.Length
  18. Local i0:=_ibuffer.Length/6
  19. _ibuffer.Resize( Max( _ibuffer.Length*3/2,n*6 ) )
  20. Local ip:=Cast<UInt Ptr>( _ibuffer.Lock() )+i0*6
  21. For Local i:=i0 Until n
  22. ip[0]=i*4
  23. ip[1]=i*4+1
  24. ip[2]=i*4+2
  25. ip[3]=i*4
  26. ip[4]=i*4+2
  27. ip[5]=i*4+3
  28. ip+=6
  29. Next
  30. _ibuffer.Invalidate( i0*6,(n-i0)*6 )
  31. _ibuffer.Unlock()
  32. Endif
  33. Local vp:=Cast<Vertex3f Ptr>( _vbuffer.Lock() )
  34. Local renderOps:=rq.TransparentOps
  35. _renderOps.Clear()
  36. Local spritei:=0,renderi:=0
  37. _material=spriteOps[0].sprite.Material
  38. _distance=spriteOps[0].distance
  39. _i0=0
  40. _i=0
  41. Repeat
  42. 'out of sprites?
  43. If spritei=spriteOps.Length
  44. 'flush sprites
  45. Flush()
  46. 'copy remaining renderops
  47. For Local i:=renderi Until renderOps.Length
  48. _renderOps.Add( renderOps[i] )
  49. Next
  50. 'done!
  51. Exit
  52. Endif
  53. 'more renderops?
  54. If renderi<renderOps.Length
  55. 'sprite closer than next renderop?
  56. If spriteOps[spritei].distance<renderOps[renderi].distance
  57. 'flush sprites
  58. Flush()
  59. 'add renderop before any more sprites
  60. _renderOps.Add( renderOps[renderi] )
  61. renderi+=1
  62. 'next!
  63. Continue
  64. Endif
  65. Endif
  66. Local sprite:=spriteOps[spritei].sprite
  67. Local material:=sprite.Material
  68. If material<>_material
  69. 'flush sprites
  70. Flush()
  71. _material=material
  72. _distance=spriteOps[spritei].distance
  73. Endif
  74. 'done with spriteOp
  75. spritei+=1
  76. 'construct vertices...
  77. Local r:=invViewMatrix.m
  78. Select sprite.Mode
  79. Case SpriteMode.Upright
  80. r.j=New Vec3f( 0,1,0 ) ; r.i=r.j.Cross( r.k ).Normalize()
  81. End
  82. Local matrix:=New AffineMat4f( r.Scale( sprite.Scale ),sprite.Position )
  83. Local texrect:=sprite.TextureRect,handle:=sprite.Handle
  84. vp[0].position=matrix * New Vec3f( -handle.x,1-handle.y,0 )
  85. vp[0].texCoord0=New Vec2f( texrect.min.x,texrect.min.y )
  86. vp[0].color=~0
  87. vp[1].position=matrix * New Vec3f( 1-handle.x,1-handle.y,0 )
  88. vp[1].texCoord0=New Vec2f( texrect.max.x,texrect.min.y )
  89. vp[1].color=~0
  90. vp[2].position=matrix * New Vec3f( 1-handle.x,-handle.y,0 )
  91. vp[2].texCoord0=New Vec2f( texrect.max.x,texrect.max.y )
  92. vp[2].color=~0
  93. vp[3].position=matrix * New Vec3f( -handle.x,-handle.y,0 )
  94. vp[3].texCoord0=New Vec2f( texrect.min.x,texrect.max.y )
  95. vp[3].color=~0
  96. 'bump vertex/index
  97. vp+=4
  98. _i+=1
  99. Forever
  100. _vbuffer.Invalidate()
  101. _vbuffer.Unlock()
  102. renderOps.Swap( _renderOps )
  103. _renderOps.Clear()
  104. End
  105. Private
  106. Field _vbuffer:VertexBuffer
  107. Field _ibuffer:IndexBuffer
  108. Field _renderOps:=New Stack<RenderOp>
  109. Field _material:Material
  110. Field _distance:Float
  111. Field _i0:Int
  112. Field _i:Int
  113. Method Flush()
  114. If _i=_i0 Return
  115. Local op:=New RenderOp
  116. op.material=_material
  117. op.vbuffer=_vbuffer
  118. op.ibuffer=_ibuffer
  119. op.order=3
  120. op.count=(_i-_i0)*2
  121. op.first=_i0*6
  122. _i0=_i
  123. op.blendMode=_material.BlendMode
  124. op.distance=_distance
  125. op.shader=_material.GetRenderShader()
  126. _renderOps.Add( op )
  127. End
  128. End