graphicsdevice.monkey2 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667
  1. Namespace mojo.graphics
  2. #rem monkeydoc Blend modes.
  3. Blend modes are used with the [[Canvas.BlendMode]] property.
  4. | BlendMode | Description
  5. |:----------|:-----------
  6. | Opaque | Blending disabled.
  7. | Alpha | Alpha blending.
  8. | Multiply | Multiply blending.
  9. | Additive | Additive blending.
  10. #end
  11. Enum BlendMode
  12. None=0
  13. Opaque=1
  14. Alpha=2
  15. Additive=3
  16. Multiply=4
  17. End
  18. #rem monkeydoc @hidden Color mask values.
  19. Color masks are used with the [[Canvas.ColorMask]] property.
  20. | ColorMask | Descripten
  21. |:----------|:----------
  22. | Red | Red color mask.
  23. | Green | Green color mask.
  24. | Blue | Blue color mask.
  25. | Alpha | Alpha color mask.
  26. #end
  27. Enum ColorMask
  28. None=0
  29. Red=1
  30. Green=2
  31. Blue=4
  32. Alpha=8
  33. All=15
  34. End
  35. Enum DepthFunc
  36. Never=0
  37. Less=1
  38. Equal=2
  39. LessEqual=3
  40. Greater=4
  41. NotEqual=5
  42. GreaterEqual=6
  43. Always=7
  44. End
  45. Enum CullMode
  46. None=0
  47. Back=1
  48. Front=2
  49. End
  50. #rem monkeydoc @hidden
  51. #end
  52. Class GraphicsDevice
  53. Method New()
  54. Init()
  55. End
  56. Method New( width:Int,height:Int )
  57. Init()
  58. _deviceSize=New Vec2i( width,height )
  59. _rtargetSize=_deviceSize
  60. End
  61. Method Resize( size:Vec2i )
  62. _deviceSize=size
  63. If Not _rtarget _rtargetSize=size
  64. _dirty|=Dirty.Viewport|Dirty.Scissor
  65. End
  66. Property RenderTargetSize:Vec2i()
  67. Return _rtargetSize
  68. End
  69. '***** PUBLIC *****
  70. Property RenderTarget:RenderTarget()
  71. Return _rtarget
  72. Setter( renderTarget:RenderTarget )
  73. FlushTarget()
  74. _rtarget=renderTarget
  75. _rtargetSize=_rtarget ? _rtarget.Size Else _deviceSize
  76. _dirty|=Dirty.RenderTarget|Dirty.Viewport|Dirty.Scissor
  77. End
  78. Property Viewport:Recti()
  79. Return _viewport
  80. Setter( viewport:Recti )
  81. If viewport=_viewport Return
  82. FlushTarget()
  83. _viewport=viewport
  84. _dirty|=Dirty.Viewport|Dirty.Scissor
  85. End
  86. Property Scissor:Recti()
  87. Return _scissor
  88. Setter( scissor:Recti )
  89. If scissor=_scissor Return
  90. FlushTarget()
  91. _scissor=scissor
  92. _dirty|=Dirty.Scissor
  93. End
  94. Property ColorMask:ColorMask()
  95. Return _colorMask
  96. Setter( colorMask:ColorMask )
  97. If colorMask=_colorMask Return
  98. _colorMask=colorMask
  99. _dirty|=Dirty.ColorMask
  100. End
  101. Property DepthMask:Bool()
  102. Return _depthMask
  103. Setter( depthMask:Bool )
  104. If depthMask=_depthMask Return
  105. _depthMask=depthMask
  106. _dirty|=Dirty.DepthMask
  107. End
  108. Property DepthFunc:DepthFunc()
  109. Return _depthFunc
  110. Setter( depthFunc:DepthFunc )
  111. If depthFunc=_depthFunc Return
  112. _depthFunc=depthFunc
  113. _dirty2|=Dirty.DepthFunc
  114. End
  115. Property BlendMode:BlendMode()
  116. Return _blendMode
  117. Setter( blendMode:BlendMode )
  118. If blendMode=_blendMode Return
  119. _blendMode=blendMode
  120. _dirty2|=Dirty.BlendMode
  121. End
  122. Property CullMode:CullMode()
  123. Return _cullMode
  124. Setter( cullMode:CullMode )
  125. If cullMode=_cullMode Return
  126. _cullMode=cullMode
  127. _dirty2|=Dirty.CullMode
  128. End
  129. Property RetroMode:Bool()
  130. Return _retroMode
  131. Setter( retroMode:Bool )
  132. If retroMode=_retroMode Return
  133. _retroMode=retroMode
  134. _dirty2|=Dirty.RetroMode
  135. End
  136. Property VertexBuffer:VertexBuffer()
  137. Return _vertexBuffer
  138. Setter( vbuffer:VertexBuffer )
  139. If vbuffer=_vertexBuffer Return
  140. _vertexBuffer=vbuffer
  141. _dirty2|=Dirty.VertexBuffer
  142. End
  143. Property IndexBuffer:IndexBuffer()
  144. Return _indexBuffer
  145. Setter( ibuffer:IndexBuffer )
  146. If ibuffer=_indexBuffer Return
  147. _indexBuffer=ibuffer
  148. _dirty2|=Dirty.IndexBuffer
  149. End
  150. Property RenderPass:Int()
  151. Return _rpass
  152. Setter( rpass:Int )
  153. If rpass=_rpass Return
  154. _rpass=rpass
  155. _dirty2|=Dirty.Shader
  156. End
  157. Property Shader:Shader()
  158. Return _shader
  159. Setter( shader:Shader )
  160. If shader=_shader Return
  161. _shader=shader
  162. _dirty2|=Dirty.Shader
  163. End
  164. Method BindUniformBlock( ublock:UniformBlock )
  165. _ublocks[ublock.BlockId]=ublock
  166. End
  167. Method GetUniformBlock:UniformBlock( block:Int )
  168. Return _ublocks[block]
  169. End
  170. Method CopyPixels( rect:Recti,pixmap:Pixmap,dstx:Int,dsty:Int )
  171. Validate()
  172. glReadPixels( rect.X,rect.Y,rect.Width,rect.Height,GL_RGBA,GL_UNSIGNED_BYTE,pixmap.PixelPtr( dstx,dsty ) )
  173. If Not _rtarget And rect.Height>1
  174. If rect.min.x<>0 Or rect.min.y<>0 Or rect.Size<>_rtargetSize
  175. pixmap.Window( rect.X,rect.Y,rect.Width,rect.Height ).FlipY()
  176. Else
  177. pixmap.FlipY()
  178. End
  179. Endif
  180. End
  181. Method Clear( color:Color,depth:Float=1 )
  182. Validate()
  183. If Not _scissorTest glEnable( GL_SCISSOR_TEST )
  184. Local mask:GLbitfield
  185. If _colorMask
  186. glClearColor( color.r,color.g,color.b,color.a )
  187. mask|=GL_COLOR_BUFFER_BIT
  188. Endif
  189. If _depthMask
  190. glClearDepth( depth )
  191. mask|=GL_DEPTH_BUFFER_BIT
  192. Endif
  193. glClear( mask )
  194. If Not _scissorTest glDisable( GL_SCISSOR_TEST )
  195. _modified=True
  196. glCheck()
  197. End
  198. Method Render( order:Int,count:Int,offset:Int=0 )
  199. Validate2()
  200. If Not _shaderValid Return
  201. Local n:=order*count
  202. Select order
  203. Case 1 glDrawArrays( GL_POINTS,offset,n )
  204. Case 2 glDrawArrays( GL_LINES,offset,n )
  205. Case 3 glDrawArrays( GL_TRIANGLES,offset,n )
  206. Default
  207. For Local i:=0 Until count
  208. glDrawArrays( GL_TRIANGLE_FAN,offset+i*order,order )
  209. Next
  210. End
  211. _modified=True
  212. glCheck()
  213. End
  214. Method RenderIndexed( order:Int,count:Int,offset:Int=0 )
  215. Validate2()
  216. If Not _shaderValid Return
  217. Local n:=order*count
  218. Local gltype:GLenum,pitch:Int
  219. Select _indexBuffer.Format
  220. Case IndexFormat.UINT16
  221. gltype=GL_UNSIGNED_SHORT
  222. pitch=2
  223. Case IndexFormat.UINT32
  224. gltype=GL_UNSIGNED_INT
  225. pitch=4
  226. Default
  227. RuntimeError( "Invalid index format" )
  228. End
  229. Local p:=Cast<UByte Ptr>( offset * pitch )
  230. Select order
  231. Case 1 glDrawElements( GL_POINTS,n,gltype,p )
  232. Case 2 glDrawElements( GL_LINES,n,gltype,p )
  233. Case 3 glDrawElements( GL_TRIANGLES,n,gltype,p )
  234. Default
  235. For Local i:=0 Until count
  236. glDrawElements( GL_TRIANGLE_FAN,order,gltype,p+i*order*pitch )
  237. Next
  238. End
  239. _modified=True
  240. glCheck()
  241. End
  242. Method FlushTarget()
  243. 'Print "GraphicsDevice.FlushTarget _modified="+_modified
  244. If Not _modified Return
  245. _modified=False
  246. If Not _rtarget Or Not _rtarget.NumColorTextures Return
  247. ' Validate()
  248. For Local i:=0 Until _rtarget.NumColorTextures
  249. Local texture:=_rtarget.GetColorTexture( i )
  250. texture.Modified( _viewport & _scissor )
  251. Next
  252. End
  253. Private
  254. Enum Dirty
  255. '
  256. 'stuff that affects Clear()
  257. RenderTarget= $0001
  258. Viewport= $0002
  259. Scissor= $0004
  260. ColorMask= $0008
  261. DepthMask= $0010
  262. '
  263. 'stuff that affects Render()
  264. DepthFunc= $0100
  265. BlendMode= $0200
  266. CullMode= $0400
  267. RetroMode= $0800
  268. VertexBuffer= $1000
  269. IndexBuffer= $2000
  270. Shader= $4000
  271. '
  272. All= $7fff
  273. '
  274. End
  275. Field _dirty:Dirty
  276. Field _dirty2:Dirty
  277. Field _modified:Bool
  278. Field _rtarget:RenderTarget
  279. Field _rtargetSize:Vec2i
  280. Field _deviceSize:Vec2i
  281. Field _viewport:Recti
  282. Field _scissor:Recti
  283. Field _scissorTest:Bool
  284. Field _colorMask:ColorMask
  285. Field _depthMask:Bool
  286. Field _depthFunc:DepthFunc
  287. Field _blendMode:BlendMode
  288. Field _cullMode:CullMode
  289. Field _retroMode:Bool
  290. Field _vertexBuffer:VertexBuffer
  291. Field _indexBuffer:IndexBuffer
  292. Field _ublocks:=New UniformBlock[8]
  293. Field _shader:Shader
  294. Field _shaderValid:Bool
  295. Field _rpass:Int
  296. Global _glSeq:Int
  297. Global _current:GraphicsDevice
  298. Global _defaultFbo:GLint
  299. Global _defaultDrawBuf:GLint
  300. Global _defaultReadBuf:GLint
  301. Method Init()
  302. _depthFunc=DepthFunc.Less
  303. _blendMode=BlendMode.Alpha
  304. _cullMode=CullMode.Back
  305. _colorMask=ColorMask.All
  306. _depthMask=True
  307. End
  308. Function InitGL()
  309. glCheck()
  310. glPixelStorei( GL_PACK_ALIGNMENT,1 )
  311. glPixelStorei( GL_UNPACK_ALIGNMENT,1 )
  312. glGetIntegerv( GL_FRAMEBUFFER_BINDING,Varptr _defaultFbo )
  313. If BBGL_seamless_cube_map glEnable( GL_TEXTURE_CUBE_MAP_SEAMLESS )
  314. If Not BBGL_ES
  315. glGetIntegerv( GL_DRAW_BUFFER,Varptr _defaultDrawBuf )
  316. glGetIntegerv( GL_READ_BUFFER,Varptr _defaultReadBuf )
  317. glEnable( GL_POINT_SPRITE )
  318. glEnable( GL_VERTEX_PROGRAM_POINT_SIZE )
  319. glEnable( GL_TEXTURE_CUBE_MAP_SEAMLESS )
  320. Endif
  321. glCheck()
  322. End
  323. Method Validate()
  324. glCheck()
  325. If _glSeq<>glGraphicsSeq
  326. _glSeq=glGraphicsSeq
  327. _current=Null
  328. InitGL()
  329. Endif
  330. If _current<>Self
  331. If _current _current.FlushTarget()
  332. _current=Self
  333. _dirty=Dirty.All
  334. _dirty2=Dirty.All
  335. Else
  336. If Not _dirty Return
  337. Endif
  338. If _dirty & Dirty.RenderTarget
  339. If _rtarget
  340. _rtarget.Bind()
  341. Else
  342. glBindFramebuffer( GL_FRAMEBUFFER,_defaultFbo )
  343. If Not BBGL_ES
  344. glDrawBuffer( _defaultDrawBuf )
  345. glReadBuffer( _defaultReadBuf )
  346. Endif
  347. Endif
  348. Endif
  349. If _dirty & Dirty.Viewport
  350. If _rtarget
  351. glViewport( _viewport.X,_viewport.Y,Max( _viewport.Width,0 ),Max( _viewport.Height,0 ) )
  352. Else
  353. glViewport( _viewport.X,_deviceSize.y-_viewport.Bottom,Max( _viewport.Width,0 ),Max( _viewport.Height,0 ) )
  354. End
  355. Endif
  356. If _dirty & Dirty.Scissor
  357. Local scissor:=_scissor & _viewport
  358. _scissorTest=scissor<>_viewport
  359. If _scissorTest glEnable( GL_SCISSOR_TEST ) Else glDisable( GL_SCISSOR_TEST )
  360. If _rtarget
  361. glScissor( scissor.X,scissor.Y,Max( scissor.Width,0 ),Max( scissor.Height,0 ) )
  362. Else
  363. glScissor( scissor.X,_rtargetSize.y-scissor.Bottom,Max( scissor.Width,0 ),Max( scissor.Height,0 ) )
  364. Endif
  365. Endif
  366. If _dirty & Dirty.ColorMask
  367. Local r:=Bool( _colorMask & ColorMask.Red )
  368. Local g:=Bool( _colorMask & ColorMask.Green )
  369. Local b:=Bool( _colorMask & ColorMask.Blue )
  370. Local a:=Bool( _colorMask & ColorMask.Alpha )
  371. glColorMask( r,g,b,a )
  372. Endif
  373. If _dirty & Dirty.DepthMask
  374. glDepthMask( _depthMask )
  375. Endif
  376. glCheck()
  377. _dirty=Null
  378. End
  379. Method Validate2()
  380. Validate()
  381. glCheck()
  382. If _dirty2 & Dirty.DepthFunc
  383. If _depthFunc=DepthFunc.Always
  384. glDisable( GL_DEPTH_TEST )
  385. Else
  386. glEnable( GL_DEPTH_TEST )
  387. Select _depthFunc
  388. Case DepthFunc.Never
  389. glDepthFunc( GL_NEVER )
  390. Case DepthFunc.Less
  391. glDepthFunc( GL_LESS )
  392. Case DepthFunc.Equal
  393. glDepthFunc( GL_EQUAL )
  394. Case DepthFunc.LessEqual
  395. glDepthFunc( GL_LEQUAL )
  396. Case DepthFunc.Greater
  397. glDepthFunc( GL_GREATER )
  398. Case DepthFunc.NotEqual
  399. glDepthFunc( GL_NOTEQUAL )
  400. Case DepthFunc.GreaterEqual
  401. glDepthFunc( GL_GEQUAL )
  402. Default
  403. RuntimeError( "Invalid DepthFunc" )
  404. End
  405. Endif
  406. Endif
  407. If _dirty2 & Dirty.BlendMode
  408. If _blendMode=BlendMode.Opaque
  409. glDisable( GL_BLEND )
  410. Else
  411. glEnable( GL_BLEND )
  412. Select _blendMode
  413. Case BlendMode.Alpha
  414. glBlendFunc( GL_ONE,GL_ONE_MINUS_SRC_ALPHA )
  415. Case BlendMode.Additive
  416. glBlendFunc( GL_ONE,GL_ONE )
  417. Case BlendMode.Multiply
  418. glBlendFunc( GL_DST_COLOR,GL_ONE_MINUS_SRC_ALPHA )
  419. Default
  420. RuntimeError( "Invalid BlendMode" )
  421. End
  422. Endif
  423. Endif
  424. If _dirty2 & Dirty.CullMode
  425. If _cullMode=CullMode.None
  426. glDisable( GL_CULL_FACE )
  427. Else
  428. glEnable( GL_CULL_FACE )
  429. Select _cullMode
  430. Case CullMode.Back
  431. glCullFace( GL_FRONT )
  432. Case CullMode.Front
  433. glCullFace( GL_BACK )
  434. Default
  435. RuntimeError( "Invalid CullMode" )
  436. End
  437. Endif
  438. Endif
  439. If _dirty2 & Dirty.RetroMode
  440. If _retroMode<>glRetroMode
  441. glRetroMode=_retroMode
  442. glRetroSeq+=1
  443. Endif
  444. Endif
  445. If _dirty2 & Dirty.VertexBuffer
  446. _vertexBuffer.Bind()
  447. Endif
  448. If _dirty2 & Dirty.IndexBuffer
  449. If _indexBuffer _indexBuffer.Bind()
  450. Endif
  451. If _dirty2 & Dirty.Shader
  452. _ublocks[0]=_shader.Uniforms
  453. _shaderValid=_shader.RenderPassMask & 1 Shl _rpass <> 0
  454. If _shaderValid _shader.Bind( _rpass )
  455. Endif
  456. _vertexBuffer.Validate()
  457. If _indexBuffer _indexBuffer.Validate()
  458. If _shaderValid _shader.ValidateUniforms( _rpass,_ublocks )
  459. glCheck()
  460. _dirty2=Null
  461. End
  462. End