canvas.monkey2 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602
  1. Namespace mojo.graphics
  2. #rem monkeydoc The Canvas class.
  3. Canvas objects are used to perform rendering to either a mojo [[app.View]] or an 'off screen' [[mojo.graphics.Image]].
  4. To draw to a canvas, use one of the 'Draw' methods. Drawing is affected by a number of draw states, including:
  5. * [[Color]] - the current drawing color. This is combined with the current alpha to produce the final rendering color and alpha values.
  6. * [[Alpha]] - the current drawing alpha level.
  7. * [[Matrix]] - the current drawing matrix. All drawing coordinates are multiplied by this matrix before rendering.
  8. * [[BlendMode]] - the blending mode for drawing, eg: opaque, alpha, additive, multiply.
  9. * [[Viewport]] - the current viewport. All drawing coordinates are relative to the top-left of the viewport.
  10. * [[Scissor]] - the current scissor rect. All rendering is clipped to the union of the viewport and the scissor rect.
  11. * [[Font]] - The current font to use when drawing text with [[DrawText]].
  12. Drawing does not occur immediately. Drawing commands are 'buffered' to reduce the overhead of sending lots of draw calls to the lower level graphics API. You can force all drawing commands in the buffer to actually render using [[Flush]].
  13. #end
  14. Class Canvas
  15. #rem monkeydoc Creates a canvas that renders to an image.
  16. #end
  17. Method New( renderTarget:Image )
  18. Init( renderTarget,New GraphicsDevice )
  19. Local texture:=renderTarget.Texture
  20. BeginRender( New Recti( 0,0,texture.Rect.Size ),AffineMat3f.Translation( texture.Rect.Origin ) )
  21. End
  22. #rem monkeydoc @hidden Creates a canvas that renders to the backbuffer.
  23. #end
  24. Method New( width:Int,height:Int )
  25. Init( Null,New GraphicsDevice( width,height ) )
  26. End
  27. #rem monkeydoc @hidden Resizes a canvas that renders to the backbuffer.
  28. #end
  29. Method Resize( size:Vec2i )
  30. _device.Resize( size )
  31. End
  32. #rem monkeydoc @hidden
  33. #end
  34. Method BeginRender( bounds:Recti,matrix:AffineMat3f )
  35. Flush()
  36. _rmatrixStack.Push( _rmatrix )
  37. _rboundsStack.Push( _rbounds )
  38. _rmatrix*=matrix
  39. _rbounds&=TransformRecti( bounds,_rmatrix )
  40. Viewport=bounds
  41. Scissor=New Recti( 0,0,bounds.Size )
  42. AmbientLight=Color.Black
  43. BlendMode=BlendMode.Alpha
  44. TextureFilter=graphics.TextureFilter.Mipmap
  45. PointSize=0
  46. LineWidth=0
  47. LineSmoothing=False
  48. ClearMatrix()
  49. End
  50. #rem monkeydoc @hidden
  51. #end
  52. Method EndRender()
  53. If _lighting EndLighting()
  54. Flush()
  55. _rbounds=_rboundsStack.Pop()
  56. _rmatrix=_rmatrixStack.Pop()
  57. End
  58. #rem monkeydoc @hidden
  59. #end
  60. Property Device:GraphicsDevice()
  61. Return _device
  62. End
  63. #rem monkeydoc The current render target.
  64. #end
  65. Property RenderTarget:Image()
  66. Return _rtarget
  67. End
  68. #rem monkeydoc The current viewport.
  69. The viewport describes the rect within the render target that rendering occurs in.
  70. All rendering is relative to the top-left of the viewport, and is clipped to the intersection of the viewport and scissor rects.
  71. This property must not be modified if the canvas is in lighting mode.
  72. #end
  73. Property Viewport:Recti()
  74. Return _viewport
  75. Setter( viewport:Recti )
  76. DebugAssert( Not _lighting,"Canvas.Viewport property cannot be modified while lighting" )
  77. If _lighting return
  78. Flush()
  79. _viewport=viewport
  80. _dirty|=Dirty.Viewport|Dirty.Scissor
  81. End
  82. #rem monkeydoc The current scissor rect.
  83. The scissor rect is a rect within the viewport that can be used for additional clipping.
  84. Scissor rect coordinates are relative to the current viewport rect, but are not affected by the current drawing matrix.
  85. This property must not be modified if the canvas is in lighting mode.
  86. #end
  87. Property Scissor:Recti()
  88. Return _scissor
  89. Setter( scissor:Recti )
  90. DebugAssert( Not _lighting,"Canvas.Scissor property cannot be modified while lighting" )
  91. If _lighting return
  92. Flush()
  93. _scissor=scissor
  94. _dirty|=Dirty.Scissor
  95. End
  96. #rem monkeydoc Ambient light color for lighting mode.
  97. Sets the ambient light color for lighting.
  98. This property cannot be modified if the canvas is already in lighting mode.
  99. #end
  100. Property AmbientLight:Color()
  101. Return _ambientLight
  102. Setter( ambient:Color )
  103. DebugAssert( Not _lighting,"Canvas.AmbientLight property cannot be modified while lighting" )
  104. If _lighting return
  105. _ambientLight=ambient
  106. End
  107. #rem monkeydoc The current drawing blend mode.
  108. #end
  109. Property BlendMode:BlendMode()
  110. Return _blendMode
  111. Setter( blendMode:BlendMode )
  112. _blendMode=blendMode
  113. End
  114. #rem monkeydoc The current texture filter.
  115. #end
  116. Property TextureFilter:TextureFilter()
  117. Return _textureFilter
  118. Setter( filter:TextureFilter )
  119. _textureFilter=filter
  120. End
  121. #rem monkeydoc Deprecated - use TextureFilter instead.
  122. Use TextureFilter instead.
  123. #end
  124. Property TextureFilteringEnabled:Bool()
  125. Return TextureFilter=TextureFilter.Mipmap
  126. Setter( enabled:Bool )
  127. TextureFilter=enabled ? TextureFilter.Mipmap Else TextureFilter.Nearest
  128. End
  129. #rem monkeydoc The current point size for use with DrawPoint.
  130. #end
  131. Property PointSize:Float()
  132. Return _pointSize
  133. Setter( pointSize:Float )
  134. _pointSize=pointSize
  135. End
  136. #rem monkeydoc The current line width for use with DrawLine.
  137. #end
  138. Property LineWidth:Float()
  139. Return _lineWidth
  140. Setter( lineWidth:Float )
  141. _lineWidth=lineWidth
  142. End
  143. #rem monkeydoc Smoothing enabled for DrawLine.
  144. #end
  145. Property LineSmoothing:Bool()
  146. Return _lineSmoothing
  147. Setter( smoothing:Bool )
  148. _lineSmoothing=smoothing
  149. End
  150. #rem monkeydoc The current font for use with DrawText.
  151. Set font to null to use the default mojo font.
  152. #end
  153. Property Font:Font()
  154. Return _font
  155. Setter( font:Font )
  156. If Not font font=_defaultFont
  157. _font=font
  158. End
  159. #rem monkeydoc The current drawing alpha level.
  160. Note that [[Alpha]] and the alpha component of [[Color]] are multiplied together to produce the final alpha value for rendering.
  161. This allows you to use [[Alpha]] as a 'master' alpha level.
  162. #end
  163. Property Alpha:Float()
  164. Return _alpha
  165. Setter( alpha:Float )
  166. _alpha=alpha
  167. Local a:=_color.a * _alpha * 255.0
  168. _pmcolor=UInt(a) Shl 24 | UInt(_color.b*a) Shl 16 | UInt(_color.g*a) Shl 8 | UInt(_color.r*a)
  169. End
  170. #rem monkeydoc The current drawing color.
  171. Note that [[Alpha]] and the alpha component of [[Color]] are multiplied together to produce the final alpha value for rendering.
  172. This allows you to use [[Alpha]] as a 'master' alpha level.
  173. #end
  174. Property Color:Color()
  175. Return _color
  176. Setter( color:Color )
  177. _color=color
  178. Local a:=_color.a * _alpha * 255.0
  179. _pmcolor=UInt(a) Shl 24 | UInt(_color.b*a) Shl 16 | UInt(_color.g*a) Shl 8 | UInt(_color.r*a)
  180. End
  181. #rem monkeydoc The current drawing matrix.
  182. All coordinates passed to draw methods are multiplied by this matrix for rendering.
  183. #end
  184. Property Matrix:AffineMat3f()
  185. Return _matrix
  186. Setter( matrix:AffineMat3f )
  187. _matrix=matrix
  188. _tanvec=_matrix.i.Normalize()
  189. End
  190. #rem monkeydoc Pushes the drawing matrix onto the internal matrix stack.
  191. #end
  192. Method PushMatrix()
  193. _matrixStack.Push( _matrix )
  194. End
  195. #rem monkeydoc Pops the drawing matrix off the internal matrix stack.
  196. #end
  197. Method PopMatrix()
  198. _matrix=_matrixStack.Pop()
  199. End
  200. #rem monkeydoc Clears the internal matrix stack and sets the drawing matrix to the identitity matrix.
  201. #end
  202. Method ClearMatrix()
  203. _matrixStack.Clear()
  204. _matrix=New AffineMat3f
  205. End
  206. #rem monkeydoc Translates the drawing matrix.
  207. Translates the drawing matrix. This has the effect of translating all drawing coordinates by `tx` and `ty`.
  208. @param tx X translation.
  209. @param ty Y translation.
  210. @param tv X/Y translation.
  211. #end
  212. Method Translate( tx:Float,ty:Float )
  213. Matrix=Matrix.Translate( tx,ty )
  214. End
  215. Method Translate( tv:Vec2f )
  216. Matrix=Matrix.Translate( tv )
  217. End
  218. #rem monkeydoc Rotates the drawing matrix.
  219. Rotates the drawing matrix. This has the effect of rotating all drawing coordinates by the angle `rz'.
  220. @param rz Rotation angle in radians.
  221. #end
  222. Method Rotate( rz:Float )
  223. Matrix=Matrix.Rotate( rz )
  224. End
  225. #rem monkeydoc Scales the drawing matrix.
  226. Scales the drawing matrix. This has the effect of scaling all drawing coordinates by `sx` and `sy`.
  227. @param sx X scale factor.
  228. @param sy Y scale factor.
  229. @param sv X/Y scale factor.
  230. #end
  231. Method Scale( sx:Float,sy:Float )
  232. Matrix=Matrix.Scale( sx,sy )
  233. End
  234. Method Scale( sv:Vec2f )
  235. Matrix=Matrix.Scale( sv )
  236. End
  237. #rem monkeydoc Draws a point.
  238. Draws a point in the current [[Color]] using the current [[BlendMode]].
  239. The point coordinates are transformed by the current [[Matrix]] and clipped to the current [[Viewport]] and [[Scissor]].
  240. @param x Point x coordinate.
  241. @param y Point y coordinate.
  242. @param v Point coordinates.
  243. #end
  244. Method DrawPoint( x:Float,y:Float )
  245. If _pointSize<=0
  246. AddDrawOp( _shader,_material,_blendMode,_textureFilter,1,1 )
  247. AddPointVertex( x,y,0,0 )
  248. Return
  249. Endif
  250. Local d:=_pointSize/2
  251. AddDrawOp( _shader,_material,_blendMode,_textureFilter,4,1 )
  252. AddVertex( x-d,y-d,0,0 )
  253. AddVertex( x+d,y-d,1,0 )
  254. AddVertex( x+d,y+d,1,1 )
  255. AddVertex( x-d,y+d,0,1 )
  256. End
  257. Method DrawPoint( v:Vec2f )
  258. DrawPoint( v.x,v.y )
  259. End
  260. #rem monkeydoc Draws a line.
  261. Draws a line in the current [[Color]] using the current [[BlendMode]].
  262. The line coordinates are transformed by the current [[Matrix]] and clipped to the current [[Viewport]] and [[Scissor]].
  263. @param x0 X coordinate of first endpoint of the line.
  264. @param y0 Y coordinate of first endpoint of the line.
  265. @param x1 X coordinate of first endpoint of the line.
  266. @param y1 Y coordinate of first endpoint of the line.
  267. @param v0 First endpoint of the line.
  268. @param v1 Second endpoint of the line.
  269. #end
  270. Method DrawLine( x0:Float,y0:Float,x1:Float,y1:Float )
  271. If _lineWidth<=0
  272. AddDrawOp( _shader,_material,_blendMode,_textureFilter,2,1 )
  273. AddPointVertex( x0,y0,0,0 )
  274. AddPointVertex( x1,y1,1,1 )
  275. Return
  276. Endif
  277. ' x0+=.5
  278. ' y0+=.5
  279. ' x1+=.5
  280. ' y1+=.5
  281. Local dx:=y0-y1,dy:=x1-x0
  282. Local sc:=0.5/Sqrt( dx*dx+dy*dy )*_lineWidth
  283. dx*=sc;dy*=sc
  284. If Not _lineSmoothing
  285. AddDrawOp( _shader,_material,_blendMode,_textureFilter,4,1 )
  286. AddPointVertex( x0-dx,y0-dy,0,0 )
  287. AddPointVertex( x0+dx,y0+dy,0,0 )
  288. AddPointVertex( x1+dx,y1+dy,0,0 )
  289. AddPointVertex( x1-dx,y1-dy,0,0 )
  290. Return
  291. End
  292. Local pmcolor:=_pmcolor
  293. AddDrawOp( _shader,_material,_blendMode,_textureFilter,4,2 )
  294. AddPointVertex( x0,y0,0,0 )
  295. AddPointVertex( x1,y1,0,0 )
  296. _pmcolor=0
  297. AddPointVertex( x1-dx,y1-dy,0,0 )
  298. AddPointVertex( x0-dx,y0-dy,0,0 )
  299. AddPointVertex( x0+dx,y0+dy,0,0 )
  300. AddPointVertex( x1+dx,y1+dy,0,0 )
  301. _pmcolor=pmcolor
  302. AddPointVertex( x1,y1,0,0 )
  303. AddPointVertex( x0,y0,0,0 )
  304. End
  305. Method DrawLine( v0:Vec2f,v1:Vec2f )
  306. DrawLine( v0.x,v0.y,v1.x,v1.y )
  307. End
  308. #rem monkeydoc Draws a triangle.
  309. Draws a triangle in the current [[Color]] using the current [[BlendMode]].
  310. The triangle vertex coordinates are also transform by the current [[Matrix]].
  311. #End
  312. Method DrawTriangle( x0:Float,y0:Float,x1:Float,y1:Float,x2:Float,y2:Float )
  313. AddDrawOp( _shader,_material,_blendMode,_textureFilter,3,1 )
  314. AddVertex( x0,y0,0,0 )
  315. AddVertex( x1,y1,1,0 )
  316. AddVertex( x2,y2,1,1 )
  317. End
  318. Method DrawTriangle( v0:Vec2f,v1:Vec2f,v2:Vec2f )
  319. DrawTriangle( v0.x,v0.y,v1.x,v1.y,v2.x,v2.y )
  320. End
  321. #rem monkeydoc Draws a quad.
  322. Draws a quad in the current [[Color]] using the current [[BlendMode]].
  323. The quad vertex coordinates are also transform by the current [[Matrix]].
  324. #end
  325. Method DrawQuad( x0:Float,y0:Float,x1:Float,y1:Float,x2:Float,y2:Float,x3:Float,y3:Float )
  326. AddDrawOp( _shader,_material,_blendMode,_textureFilter,4,1 )
  327. AddVertex( x0,y0,0,0 )
  328. AddVertex( x1,y1,1,0 )
  329. AddVertex( x2,y2,1,1 )
  330. AddVertex( x3,y3,0,1 )
  331. End
  332. Method DrawQuad( v0:Vec2f,v1:Vec2f,v2:Vec2f,v3:Vec2f )
  333. DrawQuad( v0.x,v0.y,v1.x,v1.y,v2.x,v2.y,v3.x,v3.y )
  334. End
  335. #rem monkeydoc Draws a rectangle.
  336. Draws a rectangle in the current [[Color]] using the current [[BlendMode]].
  337. The rectangle vertex coordinates are also transform by the current [[Matrix]].
  338. #end
  339. Method DrawRect( x:Float,y:Float,w:Float,h:Float )
  340. Local x0:=x,y0:=y,x1:=x+w,y1:=y+h
  341. AddDrawOp( _shader,_material,_blendMode,_textureFilter,4,1 )
  342. AddVertex( x0,y0,0,0 )
  343. AddVertex( x1,y0,1,0 )
  344. AddVertex( x1,y1,1,1 )
  345. AddVertex( x0,y1,0,1 )
  346. End
  347. Method DrawRect( rect:Rectf )
  348. DrawRect( rect.X,rect.Y,rect.Width,rect.Height )
  349. End
  350. Method DrawRect( rect:Rectf,srcImage:Image )
  351. Local tc:=srcImage.TexCoords
  352. AddDrawOp( srcImage.Shader,srcImage.Material,srcImage.BlendMode,srcImage.TextureFilter,4,1 )
  353. AddVertex( rect.min.x,rect.min.y,tc.min.x,tc.min.y )
  354. AddVertex( rect.max.x,rect.min.y,tc.max.x,tc.min.y )
  355. AddVertex( rect.max.x,rect.max.y,tc.max.x,tc.max.y )
  356. AddVertex( rect.min.x,rect.max.y,tc.min.x,tc.max.y )
  357. End
  358. Method DrawRect( x:Float,y:Float,width:Float,height:Float,srcImage:Image )
  359. DrawRect( New Rectf( x,y,x+width,y+height ),srcImage )
  360. End
  361. Method DrawRect( rect:Rectf,srcImage:Image,srcRect:Recti )
  362. Local s0:=Float(srcImage.Rect.min.x+srcRect.min.x)/srcImage.Texture.Width
  363. Local t0:=Float(srcImage.Rect.min.y+srcRect.min.y)/srcImage.Texture.Height
  364. Local s1:=Float(srcImage.Rect.min.x+srcRect.max.x)/srcImage.Texture.Width
  365. Local t1:=Float(srcImage.Rect.min.y+srcRect.max.y)/srcImage.Texture.Height
  366. AddDrawOp( srcImage.Shader,srcImage.Material,srcImage.BlendMode,srcImage.TextureFilter,4,1 )
  367. AddVertex( rect.min.x,rect.min.y,s0,t0 )
  368. AddVertex( rect.max.x,rect.min.y,s1,t0 )
  369. AddVertex( rect.max.x,rect.max.y,s1,t1 )
  370. AddVertex( rect.min.x,rect.max.y,s0,t1 )
  371. End
  372. Method DrawRect( x:Float,y:Float,width:Float,height:Float,srcImage:Image,srcX:Int,srcY:Int )
  373. DrawRect( New Rectf( x,y,x+width,y+height ),srcImage,New Recti( srcX,srcY,srcX+width,srcY+height ) )
  374. End
  375. Method DrawRect( x:Float,y:Float,width:Float,height:Float,srcImage:Image,srcX:Int,srcY:Int,srcWidth:Int,srcHeight:Int )
  376. DrawRect( New Rectf( x,y,x+width,y+height ),srcImage,New Recti( srcX,srcY,srcX+srcWidth,srcY+srcHeight ) )
  377. End
  378. #rem monkeydoc Draws an oval.
  379. Draws an oval in the current [[Color]] using the current [[BlendMode]].
  380. The oval vertex coordinates are also transform by the current [[Matrix]].
  381. @param x Top left x coordinate for the oval.
  382. @param y Top left y coordinate for the oval.
  383. @param width Width of the oval.
  384. @param height Height of the oval.
  385. #end
  386. Method DrawOval( x:Float,y:Float,width:Float,height:Float )
  387. Local xr:=width/2,yr:=height/2
  388. Local dx_x:=xr*_matrix.i.x
  389. Local dx_y:=xr*_matrix.i.y
  390. Local dy_x:=yr*_matrix.j.x
  391. Local dy_y:=yr*_matrix.j.y
  392. Local dx:=Sqrt( dx_x*dx_x+dx_y*dx_y )
  393. Local dy:=Sqrt( dy_x*dy_x+dy_y*dy_y )
  394. Local n:=Max( Int( dx+dy ),12 ) & ~3
  395. Local x0:=x+xr,y0:=y+yr
  396. AddDrawOp( _shader,_material,_blendMode,_textureFilter,n,1 )
  397. For Local i:=0 Until n
  398. Local th:=(i+.5)*Pi*2/n
  399. Local px:=x0+Cos( th ) * xr
  400. Local py:=y0+Sin( th ) * yr
  401. AddPointVertex( px,py,0,0 )
  402. Next
  403. End
  404. #rem monkeydoc Draws an ellipse.
  405. Draws an ellipse in the current [[Color]] using the current [[BlendMode]].
  406. The ellipse is also transformed by the current [[Matrix]].
  407. @param x Center x coordinate for the ellipse.
  408. @param y Center y coordinate for the ellipse.
  409. @param xRadius X axis radius for the ellipse.
  410. @param yRadius Y axis radius for the ellipse.
  411. #end
  412. Method DrawEllipse( x:Float,y:Float,xRadius:Float,yRadius:Float )
  413. DrawOval( x-xRadius,y-yRadius,xRadius*2,yRadius*2 )
  414. End
  415. #rem monkeydoc Draws a circle.
  416. Draws a circle in the current [[Color]] using the current [[BlendMode]] and transformed by the current [[Matrix]].
  417. @param x Center x coordinate for the circle.
  418. @param y Center y coordinate for the circle.
  419. @param radius The circle radius.
  420. #end
  421. Method DrawCircle( x:Float,y:Float,radius:Float )
  422. DrawOval( x-radius,y-radius,radius*2,radius*2 )
  423. End
  424. #rem monkeydoc Draws a polygon.
  425. Draws a polygon using the current [[Color]], [[BlendMode]] and [[Matrix]].
  426. @param vertices Array of x/y vertex coordinate pairs.
  427. #end
  428. Method DrawPoly( vertices:Float[] )
  429. Local order:=vertices.Length/2
  430. DebugAssert( order>0,"Invalid polygon" )
  431. AddDrawOp( _shader,_material,_blendMode,_textureFilter,order,1 )
  432. For Local i:=0 Until order*2 Step 2
  433. AddVertex( vertices[i],vertices[i+1],0,0 )
  434. Next
  435. End
  436. #rem monkeydoc Draws a sequence of polygons.
  437. Draws a sequence of polygons using the current [[Color]], [[BlendMode]] and [[Matrix]].
  438. @param order The type of polygon: 1=points, 2=lines, 3=triangles, 4=quads, >4=n-gons.
  439. @param count The number of polygons.
  440. @param vertices Array of x/y vertex coordinate pairs.
  441. #end
  442. Method DrawPolys( order:Int,count:Int,vertices:Float[] )
  443. DebugAssert( order>0 And count>0 And order*count<=vertices.Length,"Invalid polyon" )
  444. AddDrawOp( _shader,_material,_blendMode,_textureFilter,order,count )
  445. For Local i:=0 Until order*count*2 Step 2
  446. AddVertex( vertices[i],vertices[i+1],0,0 )
  447. Next
  448. End
  449. #rem monkeydoc Draws a sequence of primtives.
  450. Draws a sequence of convex primtives using the current [[Color]], [[BlendMode]] and [[Matrix]].
  451. @param order The type of primitive: 1=points, 2=lines, 3=triangles, 4=quads, >4=n-gons.
  452. @param count The number of primitives to draw.
  453. @param vertices Pointer to the first vertex x,y pair.
  454. @param verticesPitch Number of bytes from one vertex x,y pair to the next. Set to 8 for 'tightly packed' vertices.
  455. @param texCoords Pointer to the first texCoord s,t pair. This can be null.
  456. @param texCoordsPitch Number of bytes from one texCoord s,y to the next. Set to 8 for 'tightly packed' texCoords.
  457. @param colors Pointer to the first RGBA uint color value. This can be null.
  458. @param colorsPitch Number of bytes from one RGBA color to the next. Set to 4 for 'tightly packed' colors.
  459. @param image Source image for rendering. This can be null.
  460. @param indices Pointer to sequence of integer indices for indexed drawing. This can by null for non-indexed drawing.
  461. #end
  462. Method DrawPrimitives( order:Int,count:Int,vertices:Float Ptr,verticesPitch:Int,texCoords:Float Ptr,texCoordsPitch:Int,colors:UInt Ptr,colorsPitch:Int,image:Image,indices:Int Ptr )
  463. DebugAssert( order>0 And count>0,"Illegal primitive" )
  464. If image
  465. AddDrawOp( image.Shader,image.Material,image.BlendMode,image.TextureFilter,order,count )
  466. Else
  467. AddDrawOp( _shader,_material,_blendMode,_textureFilter,order,count )
  468. Endif
  469. Local n:=order*count
  470. If indices
  471. If texCoords And colors
  472. For Local i:=0 Until n
  473. Local j:=indices[i]
  474. Local vp:=Cast<Float Ptr>( Cast<UByte Ptr>( vertices )+j*verticesPitch )
  475. Local tp:=Cast<Float Ptr>( Cast<UByte Ptr>( texCoords )+j*texCoordsPitch )
  476. Local cp:=Cast<UInt Ptr>( Cast<UByte Ptr>( texCoords )+j*colorsPitch )
  477. AddVertex( vp[0],vp[1],tp[0],tp[1],cp[0] )
  478. Next
  479. Else If texCoords
  480. For Local i:=0 Until n
  481. Local j:=indices[i]
  482. Local vp:=Cast<Float Ptr>( Cast<UByte Ptr>( vertices )+j*verticesPitch )
  483. Local tp:=Cast<Float Ptr>( Cast<UByte Ptr>( texCoords )+j*texCoordsPitch )
  484. AddVertex( vp[0],vp[1],tp[0],tp[1] )
  485. Next
  486. Else If colors
  487. For Local i:=0 Until n
  488. Local j:=indices[i]
  489. Local vp:=Cast<Float Ptr>( Cast<UByte Ptr>( vertices )+j*verticesPitch )
  490. Local cp:=Cast<UInt Ptr>( Cast<UByte Ptr>( texCoords )+j*colorsPitch )
  491. AddVertex( vp[0],vp[1],0,0,cp[0] )
  492. Next
  493. Else
  494. For Local i:=0 Until n
  495. Local j:=indices[i]
  496. Local vp:=Cast<Float Ptr>( Cast<UByte Ptr>( vertices )+j*verticesPitch )
  497. AddVertex( vp[0],vp[1],0,0 )
  498. Next
  499. Endif
  500. Else
  501. If texCoords And colors
  502. For Local i:=0 Until n
  503. Local vp:=Cast<Float Ptr>( Cast<UByte Ptr>( vertices )+i*verticesPitch )
  504. Local tp:=Cast<Float Ptr>( Cast<UByte Ptr>( texCoords )+i*texCoordsPitch )
  505. Local cp:=Cast<UInt Ptr>( Cast<UByte Ptr>( texCoords )+i*colorsPitch )
  506. AddVertex( vp[0],vp[1],tp[0],tp[1],cp[0] )
  507. Next
  508. Else If texCoords
  509. For Local i:=0 Until n
  510. Local vp:=Cast<Float Ptr>( Cast<UByte Ptr>( vertices )+i*verticesPitch )
  511. Local tp:=Cast<Float Ptr>( Cast<UByte Ptr>( texCoords )+i*texCoordsPitch )
  512. AddVertex( vp[0],vp[1],tp[0],tp[1] )
  513. Next
  514. Else If colors
  515. For Local i:=0 Until n
  516. Local vp:=Cast<Float Ptr>( Cast<UByte Ptr>( vertices )+i*verticesPitch )
  517. Local cp:=Cast<UInt Ptr>( Cast<UByte Ptr>( texCoords )+i*colorsPitch )
  518. AddVertex( vp[0],vp[1],0,0,cp[0] )
  519. Next
  520. Else
  521. For Local i:=0 Until n
  522. Local vp:=Cast<Float Ptr>( Cast<UByte Ptr>( vertices )+i*verticesPitch )
  523. AddVertex( vp[0],vp[1],0,0 )
  524. Next
  525. Endif
  526. Endif
  527. End
  528. #rem monkeydoc Draws an image.
  529. Draws an image using the current [[Color]], [[BlendMode]] and [[Matrix]].
  530. @param tx X coordinate to draw image at.
  531. @param ty Y coordinate to draw image at.
  532. @param tv X/Y coordinates to draw image at.
  533. @param rz Rotation angle, in radians, for drawing.
  534. @param sx X axis scale factor for drawing.
  535. @param sy Y axis scale factor for drawing.
  536. @param sv X/Y scale factor for drawing.
  537. #end
  538. Method DrawImage( image:Image,tx:Float,ty:Float )
  539. Local vs:=image.Vertices
  540. Local ts:=image.TexCoords
  541. AddDrawOp( image.Shader,image.Material,image.BlendMode,image.TextureFilter,4,1 )
  542. AddVertex( vs.min.x+tx,vs.min.y+ty,ts.min.x,ts.min.y )
  543. AddVertex( vs.max.x+tx,vs.min.y+ty,ts.max.x,ts.min.y )
  544. AddVertex( vs.max.x+tx,vs.max.y+ty,ts.max.x,ts.max.y )
  545. AddVertex( vs.min.x+tx,vs.max.y+ty,ts.min.x,ts.max.y )
  546. If _lighting And image.ShadowCaster
  547. AddShadowCaster( image.ShadowCaster,tx,ty )
  548. Endif
  549. End
  550. Method DrawImage( image:Image,tx:Float,ty:Float,rz:Float )
  551. Local matrix:=Matrix
  552. Matrix=matrix.Translate( tx,ty ).Rotate( rz )
  553. DrawImage( image,0,0 )
  554. Matrix=matrix
  555. End
  556. Method DrawImage( image:Image,tx:Float,ty:Float,rz:Float,sx:Float,sy:Float )
  557. Local matrix:=Matrix
  558. Matrix=matrix.Translate( tx,ty ).Rotate( rz ).Scale( sx,sy )
  559. DrawImage( image,0,0 )
  560. Matrix=matrix
  561. End
  562. Method DrawImage( image:Image,tv:Vec2f )
  563. DrawImage( image,tv.x,tv.y )
  564. End
  565. Method DrawImage( image:Image,tv:Vec2f,rz:Float )
  566. DrawImage( image,tv.x,tv.y,rz )
  567. End
  568. Method DrawImage( image:Image,tv:Vec2f,rz:Float,sv:Vec2f )
  569. DrawImage( image,tv.x,tv.y,rz,sv.x,sv.y )
  570. End
  571. #rem monkeydoc Draws text.
  572. Draws text using the current [[Color]], [[BlendMode]] and [[Matrix]].
  573. @param text The text to draw.
  574. @param tx X coordinate to draw text at.
  575. @param ty Y coordinate to draw text at.
  576. @param handleX X handle for drawing.
  577. @param handleY Y handle for drawing.
  578. #end
  579. Method DrawText( text:String,tx:Float,ty:Float,handleX:Float=0,handleY:Float=0 )
  580. If Not text.Length Return
  581. tx-=_font.TextWidth( text ) * handleX
  582. ty-=_font.Height * handleY
  583. Local gpage:=_font.GetGlyphPage( text[0] )
  584. If Not gpage gpage=_font.GetGlyphPage( 0 )
  585. Local sx:Float,sy:Float
  586. Local tw:Float,th:Float
  587. Local i0:=0
  588. while i0<text.Length
  589. Local i1:=i0+1
  590. Local page:GlyphPage
  591. While i1<text.Length
  592. page=_font.GetGlyphPage( text[i1] )
  593. If page And page<>gpage Exit
  594. i1+=1
  595. Wend
  596. Local image:=gpage.image
  597. sx=image.Rect.min.x;sy=image.Rect.min.y
  598. tw=image.Texture.Width;th=image.Texture.Height
  599. AddDrawOp( image.Shader,image.Material,image.BlendMode,image.TextureFilter,4,i1-i0 )
  600. For Local i:=i0 Until i1
  601. Local g:=_font.GetGlyph( text[i] )
  602. Local s0:=Float(g.rect.min.x+sx)/tw
  603. Local t0:=Float(g.rect.min.y+sy)/th
  604. Local s1:=Float(g.rect.max.x+sx)/tw
  605. Local t1:=Float(g.rect.max.y+sy)/th
  606. Local x0:=Round( tx+g.offset.x )
  607. Local y0:=Round( ty+g.offset.y )
  608. Local x1:=x0+g.rect.Width
  609. Local y1:=y0+g.rect.Height
  610. AddVertex( x0,y0,s0,t0 )
  611. AddVertex( x1,y0,s1,t0 )
  612. AddVertex( x1,y1,s1,t1 )
  613. AddVertex( x0,y1,s0,t1 )
  614. tx+=g.advance
  615. Next
  616. gpage=page
  617. i0=i1
  618. Wend
  619. End
  620. #rem monkeydoc Adds a light to the canvas.
  621. This method must only be called while the canvas is in lighting mode, ie: between calls to [[BeginLighting]] and [[EndLighting]].
  622. #end
  623. Method AddLight( light:Image,tx:Float,ty:Float )
  624. DebugAssert( _lighting,"Canvas.AddLight() can only be used while lighting" )
  625. If Not _lighting Return
  626. Local lx:=_matrix.i.x * tx + _matrix.j.x * ty + _matrix.t.x
  627. Local ly:=_matrix.i.y * tx + _matrix.j.y * ty + _matrix.t.y
  628. _vp=_lightVB.AddVertices( 4 )
  629. If Not _vp Return
  630. Local op:=New LightOp
  631. op.light=light
  632. op.lightPos=New Vec2f( lx,ly )
  633. op.textureFilter=light.TextureFilter<>TextureFilter.None ? light.TextureFilter Else _textureFilter
  634. op.primOffset=_lightVB.Length-4
  635. _lightOps.Push( op )
  636. Local vs:=light.Vertices
  637. Local ts:=light.TexCoords
  638. AddVertex( vs.min.x+tx,vs.min.y+ty,ts.min.x,ts.min.y,lx,ly,_pmcolor )
  639. AddVertex( vs.max.x+tx,vs.min.y+ty,ts.max.x,ts.min.y,lx,ly,_pmcolor )
  640. AddVertex( vs.max.x+tx,vs.max.y+ty,ts.max.x,ts.max.y,lx,ly,_pmcolor )
  641. AddVertex( vs.min.x+tx,vs.max.y+ty,ts.min.x,ts.max.y,lx,ly,_pmcolor )
  642. End
  643. Method AddLight( light:Image,tx:Float,ty:Float,rz:Float )
  644. Local matrix:=Matrix
  645. Matrix=matrix.Translate( tx,ty ).Rotate( rz )
  646. AddLight( light,0,0 )
  647. Matrix=matrix
  648. End
  649. Method AddLight( light:Image,tx:Float,ty:Float,rz:Float,sx:Float,sy:Float )
  650. Local matrix:=Matrix
  651. Matrix=matrix.Translate( tx,ty ).Rotate( rz ).Scale( sx,sy )
  652. AddLight( light,0,0 )
  653. Matrix=matrix
  654. End
  655. Method AddLight( light:Image,tv:Vec2f )
  656. AddLight( light,tv.x,tv.y )
  657. End
  658. Method AddLight( light:Image,tv:Vec2f,rz:Float )
  659. AddLight( light,tv.x,tv.y,rz )
  660. End
  661. Method AddLight( light:Image,tv:Vec2f,rz:Float,sv:Vec2f )
  662. AddLight( light,tv.x,tv.y,rz,sv.x,sv.y )
  663. End
  664. #rem monkeydoc Adds a shadow caster to the canvas.
  665. This method must only be called while the canvas is in lighting mode, ie: between calls to [[BeginLighting]] and [[EndLighting]].
  666. #end
  667. Method AddShadowCaster( caster:ShadowCaster,tx:Float,ty:Float )
  668. DebugAssert( _lighting,"Canvas.AddShadowCaster() can only be used while lighting" )
  669. If Not _lighting Return
  670. Local op:=New ShadowOp
  671. op.caster=caster
  672. op.firstVert=_shadowVerts.Length
  673. _shadowOps.Push( op )
  674. Local tv:=New Vec2f( tx,ty )
  675. For Local sv:=Eachin caster.Vertices
  676. sv+=tv
  677. Local lv:=New Vec2f(
  678. _matrix.i.x * sv.x + _matrix.j.x * sv.y + _matrix.t.x,
  679. _matrix.i.y * sv.x + _matrix.j.y * sv.y + _matrix.t.y )
  680. _shadowVerts.Push( lv )
  681. Next
  682. End
  683. Method AddShadowCaster( caster:ShadowCaster,tx:Float,ty:Float,rz:float )
  684. Local matrix:=Matrix
  685. Matrix=matrix.Translate( tx,ty ).Rotate( rz )
  686. AddShadowCaster( caster,0,0 )
  687. Matrix=matrix
  688. End
  689. Method AddShadowCaster( caster:ShadowCaster,tx:Float,ty:Float,rz:Float,sx:Float,sy:Float )
  690. Local matrix:=Matrix
  691. Matrix=matrix.Translate( tx,ty ).Rotate( rz ).Scale( sx,sy )
  692. AddShadowCaster( caster,0,0 )
  693. Matrix=matrix
  694. End
  695. Method AddShadowCaster( caster:ShadowCaster,tv:Vec2f )
  696. AddShadowCaster( caster,tv.x,tv.y )
  697. End
  698. Method AddShadowCaster( caster:ShadowCaster,tv:Vec2f,rz:Float )
  699. AddShadowCaster( caster,tv.x,tv.y,rz )
  700. End
  701. Method AddShadowCaster( caster:ShadowCaster,tv:Vec2f,rz:Float,sv:Vec2f )
  702. AddShadowCaster( caster,tv.x,tv.y,rz,sv.x,sv.y )
  703. End
  704. #rem monkeydoc Copies a pixmap from the rendertarget.
  705. This method must not be called while the canvas is in lighting mode.
  706. @param rect The rect to copy.
  707. #end
  708. Method CopyPixmap:Pixmap( rect:Recti )
  709. DebugAssert( Not _lighting,"Canvas.CopyPixmap() cannot be used while lighting" )
  710. If _lighting Return Null
  711. Flush()
  712. rect=TransformRecti( rect,_rmatrix ) & _rbounds
  713. Local pixmap:=_device.CopyPixmap( rect )
  714. Return pixmap
  715. End
  716. #rem monkeydoc Clears the viewport.
  717. Clears the current viewport to `color`.
  718. This method must not be called while the canvas is in lighting mode.
  719. @param color Color to clear the viewport to.
  720. #end
  721. Method Clear( color:Color )
  722. DebugAssert( Not _lighting,"Canvas.Clear() cannot be used while lighting" )
  723. If _lighting Return
  724. Flush()
  725. _device.Clear( color )
  726. End
  727. #rem monkeydoc Flushes drawing commands.
  728. Flushes any outstanding drawing commands in the draw buffer.
  729. This is only generally necessary if you are drawing to an image.
  730. #end
  731. Method Flush()
  732. Validate()
  733. If _drawOps.Empty Return
  734. 'Render ambient
  735. '
  736. RenderDrawOps( 0 )
  737. If _lighting
  738. 'render diffuse gbuffer
  739. '
  740. _device.RenderTarget=_gbuffers[0]
  741. RenderDrawOps( 1 )
  742. 'render normal gbuffer
  743. '
  744. _device.RenderTarget=_gbuffers[1]
  745. RenderDrawOps( 2 )
  746. 'back to rendertarget
  747. '
  748. _device.RenderTarget=_rtarget ? _rtarget.Texture Else Null
  749. Endif
  750. _drawVB.Clear()
  751. _drawOps.Clear()
  752. _drawOp=New DrawOp
  753. End
  754. #rem monkeydoc True if canvas is in lighting mode.
  755. #end
  756. Property IsLighting:Bool()
  757. Return _lighting
  758. End
  759. #rem monkeydoc Puts the canvas into lighting mode.
  760. While in lighting mode, you can add lights and shadow casters to the cavas using [[AddLight]] and [[AddShadowCaster]]. Lights and shadows
  761. are later rendered by calling [[EndLighting]].
  762. Each call to BeginLighting must be matched with a corresponding call to EndLighting.
  763. The following properties must not be modified while in lighting mode: [[Viewport]], [[Scissor]], [[AmbientLight]]. Attempting to
  764. modify these properties while in lighting mode will result in a runtime error in debug builds.
  765. The following methods must not be called in lighting mode: [[Clear]], [[BeginLighting]]. Attepting to call these methods while in
  766. lighting mode will result in a runtime error in debug builds.
  767. #end
  768. Method BeginLighting()
  769. DebugAssert( Not _lighting,"Already lighting" )
  770. If _lighting Return
  771. _lighting=True
  772. If Not _gbuffers[0]
  773. Local gbufferSize:=New Vec2i( 1920,1080 )
  774. Local gbufferScale:=New Vec2f( 1 )/Cast<Vec2f>( gbufferSize )
  775. _gbuffers[0]=New Texture( gbufferSize.x,gbufferSize.y,PixelFormat.RGBA32,TextureFlags.Dynamic )
  776. _gbuffers[1]=New Texture( gbufferSize.x,gbufferSize.y,PixelFormat.RGBA32,TextureFlags.Dynamic )
  777. _uniforms.SetVector( "mx2_GBufferScale",gbufferScale )
  778. _uniforms.SetTexture( "mx2_GBuffer0",_gbuffers[0] )
  779. _uniforms.SetTexture( "mx2_GBuffer1",_gbuffers[1] )
  780. Endif
  781. Validate()
  782. _uniforms.SetVector( "mx2_AmbientLight",_ambientLight )
  783. _device.RenderTarget=_gbuffers[0]
  784. _device.Clear( Color.Black )
  785. _device.RenderTarget=_gbuffers[1]
  786. _device.Clear( New Color( .5,.5,0 ) )
  787. _device.RenderTarget=_rtarget ? _rtarget.Texture Else Null
  788. End
  789. #rem monkeydoc Renders lighting and ends lighting mode.
  790. Renders any lights and shadows casters added to the canvas through calls to [[AddLight]] and [[AddShadowCaster]] and ends lighting mode.
  791. Any lights and shadow casters added to the canvas are also removed and must be added again later if you want to render them again.
  792. This method must be called while the canvas is in lighting mode.
  793. #end
  794. Method EndLighting()
  795. DebugAssert( _lighting,"Not lighting" )
  796. If Not _lighting Return
  797. Flush()
  798. RenderLighting()
  799. _lightVB.Clear()
  800. _lightOps.Clear()
  801. _shadowOps.Clear()
  802. _shadowVerts.Clear()
  803. _lighting=False
  804. End
  805. Private
  806. Enum Dirty
  807. GBuffer=1
  808. Viewport=2
  809. Scissor=4
  810. End
  811. Class DrawOp
  812. Field shader:Shader
  813. Field material:UniformBlock
  814. Field blendMode:BlendMode
  815. Field textureFilter:TextureFilter
  816. Field primOrder:Int
  817. Field primCount:Int
  818. Field primOffset:Int
  819. End
  820. Class LightOp
  821. Field light:Image
  822. Field lightPos:Vec2f
  823. Field textureFilter:TextureFilter
  824. Field primOrder:Int
  825. Field primOffset:Int
  826. End
  827. Class ShadowOp
  828. Field caster:ShadowCaster
  829. Field firstVert:Int
  830. End
  831. Global _quadIndices:IndexBuffer
  832. Global _defaultFont:Font
  833. Global _shadowVB:VertexBuffer
  834. Global _lighting:Bool=False
  835. Global _gbuffers:=New Texture[2]
  836. Field _rtarget:Image
  837. Field _device:GraphicsDevice
  838. Field _uniforms:UniformBlock
  839. Field _shader:Shader
  840. Field _material:UniformBlock
  841. Field _viewport:Recti
  842. Field _scissor:Recti
  843. Field _ambientLight:Color
  844. Field _blendMode:BlendMode
  845. Field _textureFilter:TextureFilter
  846. Field _font:Font
  847. Field _alpha:Float
  848. Field _color:Color
  849. Field _pmcolor:UInt=~0
  850. Field _pointSize:Float=1
  851. Field _lineWidth:Float=1
  852. Field _lineSmoothing:Bool
  853. Field _matrix:=New AffineMat3f
  854. Field _tanvec:Vec2f=New Vec2f( 1,0 )
  855. Field _matrixStack:=New Stack<AffineMat3f>
  856. Field _rmatrix:=New AffineMat3f
  857. Field _rbounds:=New Recti( 0,0,$40000000,$40000000 )
  858. Field _rmatrixStack:=New Stack<AffineMat3f>
  859. Field _rboundsStack:=New Stack<Recti>
  860. Field _dirty:Dirty
  861. Field _projMatrix:Mat4f
  862. Field _rviewport:Recti
  863. Field _rviewportClip:Vec2i
  864. Field _rscissor:Recti
  865. Field _vp:Vertex2f Ptr
  866. Field _drawVB:VertexBuffer
  867. Field _drawOps:=New Stack<DrawOp>
  868. Field _drawOp:=New DrawOp
  869. Field _lightVB:VertexBuffer
  870. Field _lightOps:=New Stack<LightOp>
  871. Field _shadowOps:=New Stack<ShadowOp>
  872. Field _shadowVerts:=New Stack<Vec2f>
  873. Const MaxVertices:=65536
  874. Const MaxShadowVertices:=16384
  875. Const MaxLights:=1024
  876. Function Init2()
  877. Global inited:=False
  878. If inited Return
  879. inited=True
  880. Local nquads:=MaxVertices/4
  881. _quadIndices=New IndexBuffer( nquads*6 )
  882. Local ip:=_quadIndices.AddIndices( nquads*6 )
  883. For Local i:=0 Until nquads*4 Step 4
  884. ip[0]=i
  885. ip[1]=i+1
  886. ip[2]=i+2
  887. ip[3]=i
  888. ip[4]=i+2
  889. ip[5]=i+3
  890. ip+=6
  891. Next
  892. _shadowVB=New VertexBuffer( MaxShadowVertices )
  893. _defaultFont=mojo.graphics.Font.Load( "font::DejaVuSans.ttf",16 )
  894. End
  895. Method Init( rtarget:Image,device:GraphicsDevice )
  896. Init2()
  897. _rtarget=rtarget
  898. _device=device
  899. _device.RenderTarget=_rtarget ? _rtarget.Texture Else Null
  900. _uniforms=New UniformBlock
  901. _device.SetUniformBlock( 0,_uniforms )
  902. _drawVB=New VertexBuffer( MaxVertices )
  903. _lightVB=New VertexBuffer( MaxLights*4 )
  904. _shadowVB=New VertexBuffer( 65536 )
  905. _device.IndexBuffer=_quadIndices
  906. _shader=Shader.GetShader( "null" )
  907. _material=New UniformBlock
  908. _viewport=New Recti( 0,0,640,480 )
  909. _ambientLight=Color.Black
  910. _blendMode=BlendMode.Alpha
  911. _font=_defaultFont
  912. _alpha=1
  913. _color=Color.White
  914. _pmcolor=$ffffffff
  915. _matrix=New AffineMat3f
  916. End
  917. 'Vertices
  918. '
  919. #rem
  920. Method AddVertex( x:Float,y:Float,s0:Float,t0:Float,s1:Float,t1:Float,color:UInt )
  921. _vp->position.x=x
  922. _vp->position.y=y
  923. _vp->texCoord0.x=s0
  924. _vp->texCoord0.y=t0
  925. _vp->texCoord1.x=s1
  926. _vp->texCoord1.y=t1
  927. _vp->color=color
  928. _vp+=1
  929. End
  930. #end
  931. Method AddVertex( tx:Float,ty:Float,s0:Float,t0:Float,s1:Float,t1:Float,color:UInt )
  932. _vp->position.x=_matrix.i.x * tx + _matrix.j.x * ty + _matrix.t.x
  933. _vp->position.y=_matrix.i.y * tx + _matrix.j.y * ty + _matrix.t.y
  934. _vp->texCoord0.x=s0
  935. _vp->texCoord0.y=t0
  936. _vp->texCoord1.x=s1
  937. _vp->texCoord1.y=t1
  938. _vp->color=color
  939. _vp+=1
  940. End
  941. Method AddVertex( tx:Float,ty:Float,s0:Float,t0:Float,color:UInt )
  942. _vp->position.x=_matrix.i.x * tx + _matrix.j.x * ty + _matrix.t.x
  943. _vp->position.y=_matrix.i.y * tx + _matrix.j.y * ty + _matrix.t.y
  944. _vp->texCoord0.x=s0
  945. _vp->texCoord0.y=t0
  946. _vp->texCoord1.x=_tanvec.x
  947. _vp->texCoord1.y=_tanvec.y
  948. _vp->color=color
  949. _vp+=1
  950. End
  951. Method AddPointVertex( tx:Float,ty:Float,s0:Float,t0:Float )
  952. _vp->position.x=_matrix.i.x * tx + _matrix.j.x * ty + _matrix.t.x + .5
  953. _vp->position.y=_matrix.i.y * tx + _matrix.j.y * ty + _matrix.t.y + .5
  954. _vp->texCoord0.x=s0
  955. _vp->texCoord0.y=t0
  956. _vp->texCoord1.x=_tanvec.x
  957. _vp->texCoord1.y=_tanvec.y
  958. _vp->color=_pmcolor
  959. _vp+=1
  960. End
  961. Method AddVertex( tx:Float,ty:Float,s0:Float,t0:Float )
  962. _vp->position.x=_matrix.i.x * tx + _matrix.j.x * ty + _matrix.t.x
  963. _vp->position.y=_matrix.i.y * tx + _matrix.j.y * ty + _matrix.t.y
  964. _vp->texCoord0.x=s0
  965. _vp->texCoord0.y=t0
  966. _vp->texCoord1.x=_tanvec.x
  967. _vp->texCoord1.y=_tanvec.y
  968. _vp->color=_pmcolor
  969. _vp+=1
  970. End
  971. 'Drawing
  972. '
  973. Method AddDrawOp( shader:Shader,material:UniformBlock,blendMode:BlendMode,textureFilter:TextureFilter,primOrder:int,primCount:Int )
  974. If _drawVB.Length+primCount*primOrder>_drawVB.Capacity
  975. Flush()
  976. Endif
  977. If blendMode=BlendMode.None blendMode=_blendMode
  978. If textureFilter=TextureFilter.None textureFilter=_textureFilter
  979. If shader<>_drawOp.shader Or material<>_drawOp.material Or blendMode<>_drawOp.blendMode Or textureFilter<>_drawOp.textureFilter Or primOrder<>_drawOp.primOrder
  980. 'pad quads so primOffset always on a 4 vert boundary
  981. If primOrder=4 And _drawVB.Length & 3 _drawVB.AddVertices( 4-(_drawVB.Length&3) )
  982. _drawOp=New DrawOp
  983. _drawOp.shader=shader
  984. _drawOp.material=material
  985. _drawOp.blendMode=blendMode
  986. _drawOp.textureFilter=textureFilter
  987. _drawOp.primOrder=primOrder
  988. _drawOp.primCount=primCount
  989. _drawOp.primOffset=_drawVB.Length
  990. _drawOps.Push( _drawOp )
  991. Else
  992. _drawOp.primCount+=primCount
  993. Endif
  994. _vp=_drawVB.AddVertices( primOrder*primCount )
  995. End
  996. Method Validate()
  997. If _dirty & Dirty.Viewport
  998. Local tviewport:=TransformRecti( _viewport,_rmatrix )
  999. _rviewport=tviewport & _rbounds
  1000. _rviewportClip=tviewport.Origin-_rviewport.Origin
  1001. Local rmatrix:=New Mat4f
  1002. rmatrix.i.x=_rmatrix.i.x
  1003. rmatrix.j.y=_rmatrix.j.y
  1004. rmatrix.t.x=_rviewportClip.x
  1005. rmatrix.t.y=_rviewportClip.y
  1006. If _rtarget
  1007. _projMatrix=Mat4f.Ortho( 0,_rviewport.Width,0,_rviewport.Height,-1,1 ) * rmatrix
  1008. Else
  1009. _projMatrix=Mat4f.Ortho( 0,_rviewport.Width,_rviewport.Height,0,-1,1 ) * rmatrix
  1010. Endif
  1011. _uniforms.SetMatrix( "mx2_ModelViewProjectionMatrix",_projMatrix )
  1012. _uniforms.SetVector( "mx2_ViewportOrigin",_rviewport.Origin )
  1013. _uniforms.SetVector( "mx2_ViewportSize",_rviewport.Size )
  1014. _uniforms.SetVector( "mx2_ViewportClip",_rviewportClip )
  1015. _device.Viewport=_rviewport
  1016. Endif
  1017. If _dirty & Dirty.Scissor
  1018. _rscissor=TransformRecti( _scissor+_viewport.Origin,_rmatrix ) & _rviewport
  1019. _device.Scissor=_rscissor
  1020. Endif
  1021. _dirty=Null
  1022. End
  1023. Method RenderDrawOps( rpass:Int )
  1024. _device.RenderPass=rpass
  1025. _device.VertexBuffer=_drawVB
  1026. Local rpassMask:=1 Shl rpass
  1027. For Local op:=Eachin _drawOps
  1028. Local shader:=op.shader
  1029. If Not (shader.RenderPassMask & rpassMask) Continue
  1030. _device.Shader=shader
  1031. _device.BlendMode=op.blendMode
  1032. _device.TextureFilter=op.textureFilter
  1033. _device.SetUniformBlock( 1,op.material )
  1034. Select op.primOrder
  1035. Case 4
  1036. _device.RenderIndexed( 3,op.primCount*2,op.primOffset/4*6 )
  1037. Default
  1038. _device.Render( op.primOrder,op.primCount,op.primOffset )
  1039. End
  1040. ' _device.Render( op.primOrder,op.primCount,op.primOffset )
  1041. Next
  1042. End
  1043. 'Shadows
  1044. '
  1045. Method DrawShadows( lightOp:LightOp )
  1046. Const EXTRUDE:=1024.0
  1047. Local lv:=lightOp.lightPos
  1048. _shadowVB.Clear()
  1049. For Local op:=Eachin _shadowOps
  1050. Local vert0:=op.firstVert
  1051. Local nverts:=op.caster.Vertices.Length
  1052. Local tv:=_shadowVerts[vert0+nverts-1]
  1053. For Local iv:=0 Until nverts
  1054. Local pv:=tv
  1055. tv=_shadowVerts[vert0+iv]
  1056. Local dv:=tv-pv
  1057. Local nv:=dv.Normal.Normalize()
  1058. Local pd:=-pv.Dot( nv )
  1059. Local d:=lv.Dot( nv )+pd
  1060. If d<0 Continue
  1061. Local tp:=_shadowVB.AddVertices( 9 )
  1062. If Not tp Exit
  1063. Local hv:=(pv+tv)/2
  1064. Local pv2:=pv + (pv-lv).Normalize() * EXTRUDE
  1065. Local tv2:=tv + (tv-lv).Normalize() * EXTRUDE
  1066. Local hv2:=hv + (hv-lv).Normalize() * EXTRUDE
  1067. tp[0].position=tv;tp[1].position=tv2;tp[2].position=hv2
  1068. tp[3].position=tv;tp[4].position=hv2;tp[5].position=pv
  1069. tp[6].position=hv2;tp[7].position=pv2;tp[8].position=pv
  1070. tp+=9
  1071. Next
  1072. Next
  1073. End
  1074. 'Lighting
  1075. '
  1076. Method RenderLighting()
  1077. _device.BlendMode=BlendMode.Additive
  1078. _device.VertexBuffer=_lightVB
  1079. For Local op:=Eachin _lightOps
  1080. DrawShadows( op )
  1081. If _shadowVB.Length
  1082. #rem
  1083. _device.RenderTarget=Null
  1084. _device.BlendMode=BlendMode.Opaque
  1085. _device.ColorMask=ColorMask.All
  1086. _device.VertexBuffer=_shadowVB
  1087. _device.Shader=Shader.GetShader( "shadow" )
  1088. _device.Clear( Color.Blue )
  1089. _device.Render( 3,_shadowVB.Length/3,0 )
  1090. Continue
  1091. #end
  1092. _device.RenderPass=4
  1093. _device.RenderTarget=_gbuffers[0]
  1094. _device.BlendMode=BlendMode.Opaque
  1095. _device.ColorMask=ColorMask.Alpha
  1096. _device.VertexBuffer=_shadowVB
  1097. _device.Shader=Shader.GetShader( "shadow" )
  1098. _device.Clear( Color.White )
  1099. _device.Render( 3,_shadowVB.Length/3,0 )
  1100. _device.RenderPass=5
  1101. _device.RenderTarget=_rtarget ? _rtarget.Texture Else Null
  1102. _device.BlendMode=BlendMode.Additive
  1103. _device.ColorMask=ColorMask.All
  1104. _device.VertexBuffer=_lightVB
  1105. Else
  1106. _device.RenderPass=4
  1107. Endif
  1108. Local light:=op.light
  1109. _device.Shader=light.Shader
  1110. _device.TextureFilter=op.textureFilter
  1111. _device.SetUniformBlock( 1,light.Material )
  1112. _device.Render( 4,1,op.primOffset )
  1113. Next
  1114. End
  1115. End