renderer.bmx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. '
  2. ' BlitzMax port, 2015 Bruce A Henderson
  3. '
  4. ' Copyright (c) 2015 Mark Sibly
  5. '
  6. ' This software is provided 'as-is', without any express or implied
  7. ' warranty. In no event will the authors be held liable for any damages
  8. ' arising from the use of this software.
  9. '
  10. ' Permission is granted to anyone to use this software for any purpose,
  11. ' including commercial applications, and to alter it and redistribute it
  12. ' freely, subject to the following restrictions:
  13. '
  14. ' 1. The origin of this software must not be misrepresented; you must not
  15. ' claim that you wrote the original software. If you use this software
  16. ' in a product, an acknowledgement in the product documentation would be
  17. ' appreciated but is not required.
  18. ' 2. Altered source versions must be plainly marked as such, and must not be
  19. ' misrepresented as being the original software.
  20. ' 3. This notice may not be removed or altered from any source distribution.
  21. '
  22. SuperStrict
  23. Import "graphics.bmx"
  24. Type TLayerData
  25. Field matrix:Float[]=Mat4New()
  26. Field invMatrix:Float[]=Mat4New()
  27. Field drawList:TDrawList
  28. End Type
  29. Global lvector:Float[4]
  30. Global tvector:Float[4]
  31. Public
  32. ?bmxng
  33. Interface ILight
  34. Method LightMatrix:Float[]()
  35. Method LightType:Int()
  36. Method LightColor:Float[]()
  37. Method LightRange:Float()
  38. Method LightImage:TImage()
  39. End Interface
  40. Interface ILayer
  41. Method LayerMatrix:Float[]()
  42. Method LayerFogColor:Float[]()
  43. Method LayerLightMaskImage:TImage()
  44. Method EnumLayerLights( lights:TILightStack )
  45. Method OnRenderLayer( drawLists:TDrawListStack )
  46. End Interface
  47. ?Not bmxng
  48. Type ILight
  49. Method LightMatrix:Float[]() Abstract
  50. Method LightType:Int() Abstract
  51. Method LightColor:Float[]() Abstract
  52. Method LightRange:Float() Abstract
  53. Method LightImage:TImage() Abstract
  54. End Type
  55. Type ILayer
  56. Method LayerMatrix:Float[]() Abstract
  57. Method LayerFogColor:Float[]() Abstract
  58. Method LayerLightMaskImage:TImage() Abstract
  59. Method EnumLayerLights( lights:TILightStack ) Abstract
  60. Method OnRenderLayer( drawLists:TDrawListStack ) Abstract
  61. End Type
  62. ?
  63. Type TRenderer
  64. Method SetClearMode( clearMode:Int )
  65. _clearMode=clearMode
  66. End Method
  67. Method SetClearColor( clearColor:Float[] )
  68. _clearColor=clearColor
  69. End Method
  70. Method SetAmbientLight( AmbientLight:Float[] )
  71. _ambientLight=AmbientLight
  72. End Method
  73. Method SetCameraMatrix( cameraMatrix:Float[] )
  74. _cameraMatrix=cameraMatrix
  75. End Method
  76. Method SetProjectionMatrix( projectionMatrix:Float[] )
  77. _projectionMatrix=projectionMatrix
  78. End Method
  79. Method Layers:TILayerStack()
  80. Return _layers
  81. End Method
  82. Method Render(dcanvas:TCanvas)
  83. Local canvas:TCanvas=dcanvas
  84. _canvas=canvas
  85. _viewport=canvas.Viewport()
  86. _projectionMatrix=canvas.ProjectionMatrix()
  87. Local vwidth:Int=_viewport[2]
  88. Local vheight:Int=_viewport[3]
  89. If vwidth<=0 Or vheight<=0 Return
  90. Mat4Inverse( _projectionMatrix,_invProjMatrix )
  91. lvector[0]=-1;lvector[1]=-1;lvector[2]=-1;lvector[3]=1
  92. Mat4Project( _invProjMatrix,lvector,tvector )
  93. Local px0:Float=tvector[0]
  94. Local py0:Float=tvector[1]
  95. lvector[0]=1;lvector[1]=1;lvector[2]=-1;lvector[3]=1
  96. Mat4Project( _invProjMatrix,lvector,tvector )
  97. Local px1:Float=tvector[0]
  98. Local py1:Float=tvector[1]
  99. Local twidth:Int=px1-px0,theight:Int=py1-py0
  100. If Not _timage Or _timage.Width()<>twidth Or _timage.Height()<>theight
  101. _timage=New TImage.Create( twidth,theight,0,0 )
  102. End If
  103. If Not _timage2 Or _timage2.Width()<>twidth Or _timage2.Height()<>theight
  104. _timage2=New TImage.Create( twidth,theight,0,0 )
  105. End If
  106. If Not _tcanvas
  107. _tcanvas=New TCanvas.CreateCanvas( _timage )
  108. EndIf
  109. _tcanvas.SetProjectionMatrix( _projectionMatrix )
  110. _tcanvas.SetViewport( 0,0,twidth,theight )
  111. _tcanvas.SetScissor( 0,0,twidth,theight )
  112. Mat4Inverse _cameraMatrix,_viewMatrix
  113. Local invProj:Int=False
  114. 'Clear!
  115. '_canvas.SetRenderTarget _image
  116. '_canvas.SetViewport _viewport[0],_viewport[1],_viewport[2],_viewport[3]
  117. Select _clearMode
  118. Case 1
  119. _canvas.Clear _clearColor[0],_clearColor[1],_clearColor[2],_clearColor[3]
  120. End Select
  121. For Local layerId:Int=0 Until _layers.Length
  122. Local layer:ILayer=ILayer(_layers.Get( layerId ))
  123. Local fog:Float[]=layer.LayerFogColor()
  124. Local layerMatrix:Float[]=layer.LayerMatrix()
  125. Mat4Inverse layerMatrix,_invLayerMatrix
  126. _drawLists.Clear
  127. layer.OnRenderLayer( _drawLists )
  128. Local lights:TILightStack=New TILightStack
  129. layer.EnumLayerLights( lights )
  130. If Not lights.Length
  131. For Local i:Int=0 Until 4
  132. canvas.SetLightType i,0
  133. Next
  134. canvas.SetShadowMap Null'_timage
  135. canvas.SetViewMatrix _viewMatrix
  136. canvas.SetModelMatrix layerMatrix
  137. canvas.SetAmbientLight _ambientLight[0],_ambientLight[1],_ambientLight[2],1
  138. canvas.SetFogColor fog[0],fog[1],fog[2],fog[3]
  139. canvas.SetColor 1,1,1,1
  140. For Local i:Int=0 Until _drawLists.Length
  141. canvas.RenderDrawList _drawLists.Get( i )
  142. Next
  143. canvas.Flush
  144. Continue
  145. EndIf
  146. Local light0:Int=0
  147. Repeat
  148. Local numLights:Int=Min(lights.Length-light0,4)
  149. 'Shadows
  150. '
  151. canvas=_tcanvas
  152. canvas.SetRenderTarget _timage
  153. canvas.SetShadowMap Null
  154. canvas.SetViewMatrix _viewMatrix
  155. canvas.SetModelMatrix layerMatrix
  156. canvas.SetAmbientLight 0,0,0,0
  157. canvas.SetFogColor 0,0,0,0
  158. canvas.Clear 1,1,1,1
  159. canvas.SetBlendMode 0
  160. canvas.SetColor 0,0,0,0
  161. canvas.SetDefaultMaterial TShader.ShadowShader().DefaultMaterial()
  162. For Local i:Int=0 Until numLights
  163. Local light:ILight=lights.Get(light0+i)
  164. Local matrix:Float[]=light.LightMatrix()
  165. Vec4CopySrcDst matrix,lvector,12,0
  166. Mat4Transform _invLayerMatrix,lvector,tvector
  167. Local lightx:Float=tvector[0]
  168. Local lighty:Float=tvector[1]
  169. canvas.SetColorMask i=0,i=1,i=2,i=3
  170. Local image:TImage=light.LightImage()
  171. If image
  172. canvas.Clear 0,0,0,0
  173. canvas.PushMatrix
  174. canvas.SetMatrix matrix[0],matrix[1],matrix[4],matrix[5],lightx,lighty
  175. canvas.DrawImageImage image
  176. canvas.PopMatrix
  177. EndIf
  178. For Local j:Int=0 Until _drawLists.Length
  179. canvas.DrawShadows lightx,lighty,_drawLists.Get( j )
  180. Next
  181. Next
  182. canvas.SetDefaultMaterial TShader.FastShader().DefaultMaterial()
  183. canvas.SetColorMask True,True,True,True
  184. canvas.Flush
  185. 'LightMask
  186. '
  187. Rem
  188. Local lightMask:TImage=layer.LayerLightMaskImage()
  189. If lightMask
  190. If Not invProj
  191. Mat4Inverse _projectionMatrix,_invProjMatrix
  192. Mat4Project( _invProjMatrix,[-1.0,-1.0,-1.0,1.0],_ptl )
  193. Mat4Project( _invProjMatrix,[ 1.0, 1.0,-1.0,1.0],_pbr )
  194. EndIf
  195. Local fwidth:Float=(_pbr[0]-_ptl[0])
  196. Local fheight:Float=(_pbr[1]-_ptl[1])
  197. If _projectionMatrix[15]=0
  198. Local scz:Float=(layerMatrix[14]-_cameraMatrix[14])/_ptl[2]
  199. fwidth:*scz
  200. fheight:*scz
  201. EndIf
  202. _canvas.SetProjection2d 0,fwidth,0,fheight
  203. _canvas.SetViewMatrix Mat4Identity
  204. _canvas.SetModelMatrix Mat4Identity
  205. 'test...
  206. '_canvas.SetBlendMode 0
  207. '_canvas.SetColor 1,1,1,1
  208. '_canvas.DrawRect 0,0,fwidth,fheight
  209. _canvas.SetBlendMode 4
  210. Local w:Float=lightMask.Width()
  211. Local h:Float=lightMask.Height()
  212. Local x:Int:-w
  213. While x<fwidth+w
  214. Local y:Int:-h
  215. While y<fheight+h
  216. _canvas.DrawImage lightMask,x,y
  217. y:+h
  218. Wend
  219. x:+w
  220. Wend
  221. _canvas.Flush
  222. EndIf
  223. end rem
  224. 'Enable lights
  225. '
  226. canvas=_canvas
  227. If light0 canvas=_tcanvas
  228. For Local i:Int=0 Until numLights
  229. Local light:ILight=lights.Get(light0+i)
  230. Local c:Float[]=light.LightColor()
  231. Local m:Float[]=light.LightMatrix()
  232. canvas.SetLightType i,1
  233. canvas.SetLightColor i,c[0],c[1],c[2],c[3]
  234. canvas.SetLightPosition i,m[12],m[13],m[14]
  235. canvas.SetLightRange i,light.LightRange()
  236. Next
  237. For Local i:Int=numLights Until 4
  238. canvas.SetLightType i,0
  239. Next
  240. If light0=0 'first pass?
  241. 'render lights+ambient to output
  242. '
  243. canvas=_canvas
  244. canvas.SetShadowMap _timage
  245. canvas.SetViewMatrix _viewMatrix
  246. canvas.SetModelMatrix layerMatrix
  247. canvas.SetAmbientLight _ambientLight[0],_ambientLight[1],_ambientLight[2],1
  248. canvas.SetFogColor fog[0],fog[1],fog[2],fog[3]
  249. canvas.SetColor 1,1,1,1
  250. For Local i:Int=0 Until _drawLists.Length
  251. canvas.RenderDrawList _drawLists.Get( i )
  252. Next
  253. canvas.Flush
  254. Else
  255. 'render lights only
  256. '
  257. canvas=_tcanvas
  258. canvas.SetRenderTarget _timage2
  259. canvas.SetShadowMap _timage
  260. canvas.SetViewMatrix _viewMatrix
  261. canvas.SetModelMatrix layerMatrix
  262. canvas.SetAmbientLight 0,0,0,0
  263. canvas.SetFogColor 0,0,0,fog[3]
  264. canvas.Clear 0,0,0,1
  265. canvas.SetColor 1,1,1,1
  266. For Local i:Int=0 Until _drawLists.Length
  267. canvas.RenderDrawList _drawLists.Get( i )
  268. Next
  269. canvas.Flush
  270. 'add light to output
  271. '
  272. '_canvas.SetRenderTarget _image
  273. canvas=_canvas
  274. canvas.SetShadowMap Null
  275. canvas.SetViewMatrix Mat4Identity
  276. canvas.SetModelMatrix Mat4Identity
  277. canvas.SetAmbientLight 0,0,0,1
  278. canvas.SetFogColor 0,0,0,0
  279. canvas.SetBlendMode 2
  280. canvas.SetColor 1,1,1,1
  281. canvas.DrawImageImage _timage2
  282. canvas.Flush
  283. EndIf
  284. light0:+4
  285. Until light0>=lights.Length
  286. Next
  287. End Method
  288. 'Protected
  289. Field _canvas:TCanvas
  290. Field _tcanvas:TCanvas
  291. Field _timage:TImage 'tmp lighting texture
  292. Field _timage2:TImage 'another tmp lighting image for >4 lights
  293. Field _viewport:Int[]=[0,0,640,480]
  294. Field _clearMode:Int=1
  295. Field _clearColor:Float[]=[0.0,0.0,0.0,1.0]
  296. Field _ambientLight:Float[]=[1.0,1.0,1.0,1.0]
  297. Field _projectionMatrix:Float[]=Mat4New()
  298. Field _cameraMatrix:Float[]=Mat4New()
  299. Field _viewMatrix:Float[]=Mat4New()
  300. Field _layers:TILayerStack=New TILayerStack
  301. Field _invLayerMatrix:Float[16]
  302. Field _drawLists:TDrawListStack=New TDrawListStack
  303. Field _invProjMatrix:Float[16]
  304. Field _ptl:Float[4]
  305. Field _pbr:Float[4]
  306. End Type
  307. Type TILightStack
  308. Field data:ILight[]
  309. Field length:Int
  310. Method Push( value:ILight )
  311. If length=data.Length
  312. data=data[..length*2+10]
  313. EndIf
  314. data[length]=value
  315. length:+1
  316. End Method
  317. Method Pop:ILight()
  318. length:-1
  319. Local v:ILight=data[length]
  320. data[length]=Null
  321. Return v
  322. End Method
  323. Method Top:ILight()
  324. Return data[length-1]
  325. End Method
  326. Method Get:ILight(index:Int)
  327. Return data[index]
  328. End Method
  329. Method Clear()
  330. For Local i:Int=0 Until length
  331. data[i]=Null
  332. Next
  333. length=0
  334. End Method
  335. End Type
  336. Type TILayerStack
  337. Field data:ILayer[]
  338. Field length:Int
  339. Method Push( value:ILayer )
  340. If length=data.Length
  341. data=data[..length*2+10]
  342. EndIf
  343. data[length]=value
  344. length:+1
  345. End Method
  346. Method Pop:ILayer()
  347. length:-1
  348. Local v:ILayer=data[length]
  349. data[length]=Null
  350. Return v
  351. End Method
  352. Method Top:ILayer()
  353. Return data[length-1]
  354. End Method
  355. Method Get:ILayer(index:Int)
  356. Return data[index]
  357. End Method
  358. Method Clear()
  359. For Local i:Int=0 Until length
  360. data[i]=Null
  361. Next
  362. length=0
  363. End Method
  364. End Type