canvas.monkey2 39 KB

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