canvas.monkey2 38 KB

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