canvas.monkey2 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571
  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. If Not text.Length Return
  569. tx-=_font.TextWidth( text ) * handleX
  570. ty-=_font.Height * handleY
  571. Local gpage:=_font.GetGlyphPage( text[0] )
  572. If Not gpage gpage=_font.GetGlyphPage( 0 )
  573. Local sx:Float,sy:Float
  574. Local tw:Float,th:Float
  575. Local i0:=0
  576. while i0<text.Length
  577. Local i1:=i0+1
  578. Local page:GlyphPage
  579. While i1<text.Length
  580. page=_font.GetGlyphPage( text[i1] )
  581. If page And page<>gpage Exit
  582. i1+=1
  583. Wend
  584. Local image:=gpage.image
  585. sx=image.Rect.min.x;sy=image.Rect.min.y
  586. tw=image.Texture.Width;th=image.Texture.Height
  587. AddDrawOp( image.Shader,image.Material,image.BlendMode,image.TextureFilter,4,i1-i0 )
  588. For Local i:=i0 Until i1
  589. Local g:=_font.GetGlyph( text[i] )
  590. Local s0:=Float(g.rect.min.x+sx)/tw
  591. Local t0:=Float(g.rect.min.y+sy)/th
  592. Local s1:=Float(g.rect.max.x+sx)/tw
  593. Local t1:=Float(g.rect.max.y+sy)/th
  594. Local x0:=Round( tx+g.offset.x )
  595. Local y0:=Round( ty+g.offset.y )
  596. Local x1:=x0+g.rect.Width
  597. Local y1:=y0+g.rect.Height
  598. AddVertex( x0,y0,s0,t0 )
  599. AddVertex( x1,y0,s1,t0 )
  600. AddVertex( x1,y1,s1,t1 )
  601. AddVertex( x0,y1,s0,t1 )
  602. tx+=g.advance
  603. Next
  604. gpage=page
  605. i0=i1
  606. Wend
  607. End
  608. #rem monkeydoc Adds a light to the canvas.
  609. This method must only be called while the canvas is in lighting mode, ie: between calls to [[BeginLighting]] and [[EndLighting]].
  610. #end
  611. Method AddLight( light:Image,tx:Float,ty:Float )
  612. DebugAssert( _lighting,"Canvas.AddLight() can only be used while lighting" )
  613. If Not _lighting Return
  614. Local lx:=_matrix.i.x * tx + _matrix.j.x * ty + _matrix.t.x
  615. Local ly:=_matrix.i.y * tx + _matrix.j.y * ty + _matrix.t.y
  616. _vp=_lightVB.AddVertices( 4 )
  617. If Not _vp Return
  618. Local op:=New LightOp
  619. op.light=light
  620. op.lightPos=New Vec2f( lx,ly )
  621. op.textureFilter=light.TextureFilter<>TextureFilter.None ? light.TextureFilter Else _textureFilter
  622. op.primOffset=_lightVB.Length-4
  623. _lightOps.Push( op )
  624. Local vs:=light.Vertices
  625. Local ts:=light.TexCoords
  626. AddVertex( vs.min.x+tx,vs.min.y+ty,ts.min.x,ts.min.y,lx,ly,_pmcolor )
  627. AddVertex( vs.max.x+tx,vs.min.y+ty,ts.max.x,ts.min.y,lx,ly,_pmcolor )
  628. AddVertex( vs.max.x+tx,vs.max.y+ty,ts.max.x,ts.max.y,lx,ly,_pmcolor )
  629. AddVertex( vs.min.x+tx,vs.max.y+ty,ts.min.x,ts.max.y,lx,ly,_pmcolor )
  630. End
  631. Method AddLight( light:Image,tx:Float,ty:Float,rz:Float )
  632. Local matrix:=Matrix
  633. Matrix=matrix.Translate( tx,ty ).Rotate( rz )
  634. AddLight( light,0,0 )
  635. Matrix=matrix
  636. End
  637. Method AddLight( light:Image,tx:Float,ty:Float,rz:Float,sx:Float,sy:Float )
  638. Local matrix:=Matrix
  639. Matrix=matrix.Translate( tx,ty ).Rotate( rz ).Scale( sx,sy )
  640. AddLight( light,0,0 )
  641. Matrix=matrix
  642. End
  643. Method AddLight( light:Image,tv:Vec2f )
  644. AddLight( light,tv.x,tv.y )
  645. End
  646. Method AddLight( light:Image,tv:Vec2f,rz:Float )
  647. AddLight( light,tv.x,tv.y,rz )
  648. End
  649. Method AddLight( light:Image,tv:Vec2f,rz:Float,sv:Vec2f )
  650. AddLight( light,tv.x,tv.y,rz,sv.x,sv.y )
  651. End
  652. #rem monkeydoc Adds a shadow caster to the canvas.
  653. This method must only be called while the canvas is in lighting mode, ie: between calls to [[BeginLighting]] and [[EndLighting]].
  654. #end
  655. Method AddShadowCaster( caster:ShadowCaster,tx:Float,ty:Float )
  656. DebugAssert( _lighting,"Canvas.AddShadowCaster() can only be used while lighting" )
  657. If Not _lighting Return
  658. Local op:=New ShadowOp
  659. op.caster=caster
  660. op.firstVert=_shadowVerts.Length
  661. _shadowOps.Push( op )
  662. Local tv:=New Vec2f( tx,ty )
  663. For Local sv:=Eachin caster.Vertices
  664. sv+=tv
  665. Local lv:=New Vec2f(
  666. _matrix.i.x * sv.x + _matrix.j.x * sv.y + _matrix.t.x,
  667. _matrix.i.y * sv.x + _matrix.j.y * sv.y + _matrix.t.y )
  668. _shadowVerts.Push( lv )
  669. Next
  670. End
  671. Method AddShadowCaster( caster:ShadowCaster,tx:Float,ty:Float,rz:float )
  672. Local matrix:=Matrix
  673. Matrix=matrix.Translate( tx,ty ).Rotate( rz )
  674. AddShadowCaster( caster,0,0 )
  675. Matrix=matrix
  676. End
  677. Method AddShadowCaster( caster:ShadowCaster,tx:Float,ty:Float,rz:Float,sx:Float,sy:Float )
  678. Local matrix:=Matrix
  679. Matrix=matrix.Translate( tx,ty ).Rotate( rz ).Scale( sx,sy )
  680. AddShadowCaster( caster,0,0 )
  681. Matrix=matrix
  682. End
  683. Method AddShadowCaster( caster:ShadowCaster,tv:Vec2f )
  684. AddShadowCaster( caster,tv.x,tv.y )
  685. End
  686. Method AddShadowCaster( caster:ShadowCaster,tv:Vec2f,rz:Float )
  687. AddShadowCaster( caster,tv.x,tv.y,rz )
  688. End
  689. Method AddShadowCaster( caster:ShadowCaster,tv:Vec2f,rz:Float,sv:Vec2f )
  690. AddShadowCaster( caster,tv.x,tv.y,rz,sv.x,sv.y )
  691. End
  692. #rem monkeydoc Copies a pixmap from the rendertarget.
  693. This method must not be called while the canvas is in lighting mode.
  694. @param rect The rect to copy.
  695. #end
  696. Method CopyPixmap:Pixmap( rect:Recti )
  697. DebugAssert( Not _lighting,"Canvas.CopyPixmap() cannot be used while lighting" )
  698. If _lighting Return Null
  699. Flush()
  700. rect=TransformRecti( rect,_rmatrix ) & _rbounds
  701. Local pixmap:=_device.CopyPixmap( rect )
  702. Return pixmap
  703. End
  704. #rem monkeydoc Clears the viewport.
  705. Clears the current viewport to `color`.
  706. This method must not be called while the canvas is in lighting mode.
  707. @param color Color to clear the viewport to.
  708. #end
  709. Method Clear( color:Color )
  710. DebugAssert( Not _lighting,"Canvas.Clear() cannot be used while lighting" )
  711. If _lighting Return
  712. Flush()
  713. _device.Clear( color )
  714. End
  715. #rem monkeydoc Flushes drawing commands.
  716. Flushes any outstanding drawing commands in the draw buffer.
  717. This is only generally necessary if you are drawing to an image.
  718. #end
  719. Method Flush()
  720. Validate()
  721. If _drawOps.Empty Return
  722. 'Render ambient
  723. '
  724. RenderDrawOps( 0 )
  725. If _lighting
  726. 'render diffuse gbuffer
  727. '
  728. _device.RenderTarget=_gbuffers[0]
  729. RenderDrawOps( 1 )
  730. 'render normal gbuffer
  731. '
  732. _device.RenderTarget=_gbuffers[1]
  733. RenderDrawOps( 2 )
  734. 'back to rendertarget
  735. '
  736. _device.RenderTarget=_rtarget ? _rtarget.Texture Else Null
  737. Endif
  738. _drawVB.Clear()
  739. _drawOps.Clear()
  740. _drawOp=New DrawOp
  741. End
  742. #rem monkeydoc True if canvas is in lighting mode.
  743. #end
  744. Property IsLighting:Bool()
  745. Return _lighting
  746. End
  747. #rem monkeydoc Puts the canvas into lighting mode.
  748. While in lighting mode, you can add lights and shadow casters to the cavas using [[AddLight]] and [[AddShadowCaster]]. Lights and shadows
  749. are later rendered by calling [[EndLighting]].
  750. Each call to BeginLighting must be matched with a corresponding call to EndLighting.
  751. The following properties must not be modified while in lighting mode: [[Viewport]], [[Scissor]], [[AmbientLight]]. Attempting to
  752. modify these properties while in lighting mode will result in a runtime error in debug builds.
  753. The following methods must not be called in lighting mode: [[Clear]], [[BeginLighting]]. Attepting to call these methods while in
  754. lighting mode will result in a runtime error in debug builds.
  755. #end
  756. Method BeginLighting()
  757. DebugAssert( Not _lighting,"Already lighting" )
  758. If _lighting Return
  759. _lighting=True
  760. If Not _gbuffers[0]
  761. Local gbufferSize:=New Vec2i( 1920,1080 )
  762. Local gbufferScale:=New Vec2f( 1 )/Cast<Vec2f>( gbufferSize )
  763. _gbuffers[0]=New Texture( gbufferSize.x,gbufferSize.y,PixelFormat.RGBA32,TextureFlags.Dynamic )
  764. _gbuffers[1]=New Texture( gbufferSize.x,gbufferSize.y,PixelFormat.RGBA32,TextureFlags.Dynamic )
  765. _uniforms.SetVector( "mx2_GBufferScale",gbufferScale )
  766. _uniforms.SetTexture( "mx2_GBuffer0",_gbuffers[0] )
  767. _uniforms.SetTexture( "mx2_GBuffer1",_gbuffers[1] )
  768. Endif
  769. Validate()
  770. _uniforms.SetVector( "mx2_AmbientLight",_ambientLight )
  771. _device.RenderTarget=_gbuffers[0]
  772. _device.Clear( Color.Black )
  773. _device.RenderTarget=_gbuffers[1]
  774. _device.Clear( New Color( .5,.5,0 ) )
  775. _device.RenderTarget=_rtarget ? _rtarget.Texture Else Null
  776. End
  777. #rem monkeydoc Renders lighting and ends lighting mode.
  778. Renders any lights and shadows casters added to the canvas through calls to [[AddLight]] and [[AddShadowCaster]] and ends lighting mode.
  779. 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.
  780. This method must be called while the canvas is in lighting mode.
  781. #end
  782. Method EndLighting()
  783. DebugAssert( _lighting,"Not lighting" )
  784. If Not _lighting Return
  785. Flush()
  786. RenderLighting()
  787. _lightVB.Clear()
  788. _lightOps.Clear()
  789. _shadowOps.Clear()
  790. _shadowVerts.Clear()
  791. _lighting=False
  792. End
  793. Private
  794. Enum Dirty
  795. GBuffer=1
  796. Viewport=2
  797. Scissor=4
  798. End
  799. Class DrawOp
  800. Field shader:Shader
  801. Field material:UniformBlock
  802. Field blendMode:BlendMode
  803. Field textureFilter:TextureFilter
  804. Field primOrder:Int
  805. Field primCount:Int
  806. Field primOffset:Int
  807. End
  808. Class LightOp
  809. Field light:Image
  810. Field lightPos:Vec2f
  811. Field textureFilter:TextureFilter
  812. Field primOrder:Int
  813. Field primOffset:Int
  814. End
  815. Class ShadowOp
  816. Field caster:ShadowCaster
  817. Field firstVert:Int
  818. End
  819. Global _quadIndices:IndexBuffer
  820. Global _defaultFont:Font
  821. Global _shadowVB:VertexBuffer
  822. Global _lighting:Bool=False
  823. Global _gbuffers:=New Texture[2]
  824. Field _rtarget:Image
  825. Field _device:GraphicsDevice
  826. Field _uniforms:UniformBlock
  827. Field _shader:Shader
  828. Field _material:UniformBlock
  829. Field _viewport:Recti
  830. Field _scissor:Recti
  831. Field _ambientLight:Color
  832. Field _blendMode:BlendMode
  833. Field _textureFilter:TextureFilter
  834. Field _font:Font
  835. Field _alpha:Float
  836. Field _color:Color
  837. Field _pmcolor:UInt=~0
  838. Field _pointSize:Float=1
  839. Field _lineWidth:Float=1
  840. Field _matrix:=New AffineMat3f
  841. Field _tanvec:Vec2f=New Vec2f( 1,0 )
  842. Field _matrixStack:=New Stack<AffineMat3f>
  843. Field _rmatrix:=New AffineMat3f
  844. Field _rbounds:=New Recti( 0,0,$40000000,$40000000 )
  845. Field _rmatrixStack:=New Stack<AffineMat3f>
  846. Field _rboundsStack:=New Stack<Recti>
  847. Field _dirty:Dirty
  848. Field _projMatrix:Mat4f
  849. Field _rviewport:Recti
  850. Field _rviewportClip:Vec2i
  851. Field _rscissor:Recti
  852. Field _vp:Vertex2f Ptr
  853. Field _drawVB:VertexBuffer
  854. Field _drawOps:=New Stack<DrawOp>
  855. Field _drawOp:=New DrawOp
  856. Field _lightVB:VertexBuffer
  857. Field _lightOps:=New Stack<LightOp>
  858. Field _shadowOps:=New Stack<ShadowOp>
  859. Field _shadowVerts:=New Stack<Vec2f>
  860. Const MaxVertices:=65536
  861. Const MaxShadowVertices:=16384
  862. Const MaxLights:=1024
  863. Function Init2()
  864. Global inited:=False
  865. If inited Return
  866. inited=True
  867. Local nquads:=MaxVertices/4
  868. _quadIndices=New IndexBuffer( nquads*6 )
  869. Local ip:=_quadIndices.AddIndices( nquads*6 )
  870. For Local i:=0 Until nquads*4 Step 4
  871. ip[0]=i
  872. ip[1]=i+1
  873. ip[2]=i+2
  874. ip[3]=i
  875. ip[4]=i+2
  876. ip[5]=i+3
  877. ip+=6
  878. Next
  879. _shadowVB=New VertexBuffer( MaxShadowVertices )
  880. _defaultFont=mojo.graphics.Font.Load( "font::DejaVuSans.ttf",16 )
  881. End
  882. Method Init( rtarget:Image,device:GraphicsDevice )
  883. Init2()
  884. _rtarget=rtarget
  885. _device=device
  886. _device.RenderTarget=_rtarget ? _rtarget.Texture Else Null
  887. _uniforms=New UniformBlock
  888. _device.SetUniformBlock( 0,_uniforms )
  889. _drawVB=New VertexBuffer( MaxVertices )
  890. _lightVB=New VertexBuffer( MaxLights*4 )
  891. _shadowVB=New VertexBuffer( 65536 )
  892. _device.IndexBuffer=_quadIndices
  893. _shader=Shader.GetShader( "null" )
  894. _material=New UniformBlock
  895. _viewport=New Recti( 0,0,640,480 )
  896. _ambientLight=Color.Black
  897. _blendMode=BlendMode.Alpha
  898. _font=_defaultFont
  899. _alpha=1
  900. _color=Color.White
  901. _pmcolor=$ffffffff
  902. _matrix=New AffineMat3f
  903. End
  904. 'Vertices
  905. '
  906. #rem
  907. Method AddVertex( x:Float,y:Float,s0:Float,t0:Float,s1:Float,t1:Float,color:UInt )
  908. _vp->position.x=x
  909. _vp->position.y=y
  910. _vp->texCoord0.x=s0
  911. _vp->texCoord0.y=t0
  912. _vp->texCoord1.x=s1
  913. _vp->texCoord1.y=t1
  914. _vp->color=color
  915. _vp+=1
  916. End
  917. #end
  918. Method AddVertex( tx:Float,ty:Float,s0:Float,t0:Float,s1:Float,t1:Float,color:UInt )
  919. _vp->position.x=_matrix.i.x * tx + _matrix.j.x * ty + _matrix.t.x
  920. _vp->position.y=_matrix.i.y * tx + _matrix.j.y * ty + _matrix.t.y
  921. _vp->texCoord0.x=s0
  922. _vp->texCoord0.y=t0
  923. _vp->texCoord1.x=s1
  924. _vp->texCoord1.y=t1
  925. _vp->color=color
  926. _vp+=1
  927. End
  928. Method AddVertex( tx:Float,ty:Float,s0:Float,t0:Float,color:UInt )
  929. _vp->position.x=_matrix.i.x * tx + _matrix.j.x * ty + _matrix.t.x
  930. _vp->position.y=_matrix.i.y * tx + _matrix.j.y * ty + _matrix.t.y
  931. _vp->texCoord0.x=s0
  932. _vp->texCoord0.y=t0
  933. _vp->texCoord1.x=_tanvec.x
  934. _vp->texCoord1.y=_tanvec.y
  935. _vp->color=color
  936. _vp+=1
  937. End
  938. Method AddVertex( tx:Float,ty:Float,s0:Float,t0:Float )
  939. _vp->position.x=_matrix.i.x * tx + _matrix.j.x * ty + _matrix.t.x
  940. _vp->position.y=_matrix.i.y * tx + _matrix.j.y * ty + _matrix.t.y
  941. _vp->texCoord0.x=s0
  942. _vp->texCoord0.y=t0
  943. _vp->texCoord1.x=_tanvec.x
  944. _vp->texCoord1.y=_tanvec.y
  945. _vp->color=_pmcolor
  946. _vp+=1
  947. End
  948. 'Drawing
  949. '
  950. Method AddDrawOp( shader:Shader,material:UniformBlock,blendMode:BlendMode,textureFilter:TextureFilter,primOrder:int,primCount:Int )
  951. If _drawVB.Length+primCount*primOrder>_drawVB.Capacity
  952. Flush()
  953. Endif
  954. If blendMode=BlendMode.None blendMode=_blendMode
  955. If textureFilter=TextureFilter.None textureFilter=_textureFilter
  956. If shader<>_drawOp.shader Or material<>_drawOp.material Or blendMode<>_drawOp.blendMode Or textureFilter<>_drawOp.textureFilter Or primOrder<>_drawOp.primOrder
  957. 'pad quads so primOffset always on a 4 vert boundary
  958. If primOrder=4 And _drawVB.Length & 3 _drawVB.AddVertices( 4-(_drawVB.Length&3) )
  959. _drawOp=New DrawOp
  960. _drawOp.shader=shader
  961. _drawOp.material=material
  962. _drawOp.blendMode=blendMode
  963. _drawOp.textureFilter=textureFilter
  964. _drawOp.primOrder=primOrder
  965. _drawOp.primCount=primCount
  966. _drawOp.primOffset=_drawVB.Length
  967. _drawOps.Push( _drawOp )
  968. Else
  969. _drawOp.primCount+=primCount
  970. Endif
  971. _vp=_drawVB.AddVertices( primOrder*primCount )
  972. End
  973. Method Validate()
  974. If _dirty & Dirty.Viewport
  975. Local tviewport:=TransformRecti( _viewport,_rmatrix )
  976. _rviewport=tviewport & _rbounds
  977. _rviewportClip=tviewport.Origin-_rviewport.Origin
  978. Local rmatrix:=New Mat4f
  979. rmatrix.i.x=_rmatrix.i.x
  980. rmatrix.j.y=_rmatrix.j.y
  981. rmatrix.t.x=_rviewportClip.x
  982. rmatrix.t.y=_rviewportClip.y
  983. If _rtarget
  984. _projMatrix=Mat4f.Ortho( 0,_rviewport.Width,0,_rviewport.Height,-1,1 ) * rmatrix
  985. Else
  986. _projMatrix=Mat4f.Ortho( 0,_rviewport.Width,_rviewport.Height,0,-1,1 ) * rmatrix
  987. Endif
  988. _uniforms.SetMatrix( "mx2_ModelViewProjectionMatrix",_projMatrix )
  989. _uniforms.SetVector( "mx2_ViewportOrigin",_rviewport.Origin )
  990. _uniforms.SetVector( "mx2_ViewportSize",_rviewport.Size )
  991. _uniforms.SetVector( "mx2_ViewportClip",_rviewportClip )
  992. _device.Viewport=_rviewport
  993. Endif
  994. If _dirty & Dirty.Scissor
  995. _rscissor=TransformRecti( _scissor+_viewport.Origin,_rmatrix ) & _rviewport
  996. _device.Scissor=_rscissor
  997. Endif
  998. _dirty=Null
  999. End
  1000. Method RenderDrawOps( rpass:Int )
  1001. _device.RenderPass=rpass
  1002. _device.VertexBuffer=_drawVB
  1003. Local rpassMask:=1 Shl rpass
  1004. For Local op:=Eachin _drawOps
  1005. Local shader:=op.shader
  1006. If Not (shader.RenderPassMask & rpassMask) Continue
  1007. _device.Shader=shader
  1008. _device.BlendMode=op.blendMode
  1009. _device.TextureFilter=op.textureFilter
  1010. _device.SetUniformBlock( 1,op.material )
  1011. Select op.primOrder
  1012. Case 4
  1013. _device.RenderIndexed( 3,op.primCount*2,op.primOffset/4*6 )
  1014. Default
  1015. _device.Render( op.primOrder,op.primCount,op.primOffset )
  1016. End
  1017. ' _device.Render( op.primOrder,op.primCount,op.primOffset )
  1018. Next
  1019. End
  1020. 'Shadows
  1021. '
  1022. Method DrawShadows( lightOp:LightOp )
  1023. Const EXTRUDE:=1024.0
  1024. Local lv:=lightOp.lightPos
  1025. _shadowVB.Clear()
  1026. For Local op:=Eachin _shadowOps
  1027. Local vert0:=op.firstVert
  1028. Local nverts:=op.caster.Vertices.Length
  1029. Local tv:=_shadowVerts[vert0+nverts-1]
  1030. For Local iv:=0 Until nverts
  1031. Local pv:=tv
  1032. tv=_shadowVerts[vert0+iv]
  1033. Local dv:=tv-pv
  1034. Local nv:=dv.Normal.Normalize()
  1035. Local pd:=-pv.Dot( nv )
  1036. Local d:=lv.Dot( nv )+pd
  1037. If d<0 Continue
  1038. Local tp:=_shadowVB.AddVertices( 9 )
  1039. If Not tp Exit
  1040. Local hv:=(pv+tv)/2
  1041. Local pv2:=pv + (pv-lv).Normalize() * EXTRUDE
  1042. Local tv2:=tv + (tv-lv).Normalize() * EXTRUDE
  1043. Local hv2:=hv + (hv-lv).Normalize() * EXTRUDE
  1044. tp[0].position=tv;tp[1].position=tv2;tp[2].position=hv2
  1045. tp[3].position=tv;tp[4].position=hv2;tp[5].position=pv
  1046. tp[6].position=hv2;tp[7].position=pv2;tp[8].position=pv
  1047. tp+=9
  1048. Next
  1049. Next
  1050. End
  1051. 'Lighting
  1052. '
  1053. Method RenderLighting()
  1054. _device.BlendMode=BlendMode.Additive
  1055. _device.VertexBuffer=_lightVB
  1056. For Local op:=Eachin _lightOps
  1057. DrawShadows( op )
  1058. If _shadowVB.Length
  1059. #rem
  1060. _device.RenderTarget=Null
  1061. _device.BlendMode=BlendMode.Opaque
  1062. _device.ColorMask=ColorMask.All
  1063. _device.VertexBuffer=_shadowVB
  1064. _device.Shader=Shader.GetShader( "shadow" )
  1065. _device.Clear( Color.Blue )
  1066. _device.Render( 3,_shadowVB.Length/3,0 )
  1067. Continue
  1068. #end
  1069. _device.RenderPass=4
  1070. _device.RenderTarget=_gbuffers[0]
  1071. _device.BlendMode=BlendMode.Opaque
  1072. _device.ColorMask=ColorMask.Alpha
  1073. _device.VertexBuffer=_shadowVB
  1074. _device.Shader=Shader.GetShader( "shadow" )
  1075. _device.Clear( Color.White )
  1076. _device.Render( 3,_shadowVB.Length/3,0 )
  1077. _device.RenderPass=5
  1078. _device.RenderTarget=_rtarget ? _rtarget.Texture Else Null
  1079. _device.BlendMode=BlendMode.Additive
  1080. _device.ColorMask=ColorMask.All
  1081. _device.VertexBuffer=_lightVB
  1082. Else
  1083. _device.RenderPass=4
  1084. Endif
  1085. Local light:=op.light
  1086. _device.Shader=light.Shader
  1087. _device.TextureFilter=op.textureFilter
  1088. _device.SetUniformBlock( 1,light.Material )
  1089. _device.Render( 4,1,op.primOffset )
  1090. Next
  1091. End
  1092. End