spritebuffer.monkey2 3.8 KB

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