1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120 |
- Namespace mojo3d
- #rem monkeydoc The mojo3d Renderer class.
- A renderer is an object that renders scenes. There is normally only ever one renderer created and it is created for you automatically when required so you don't normally need to worry about renderers at all.
- When a new renderer is created, the config setting `MOJO3D\_RENDERER` can be used to control the type of renderer created. Use "deferred" to create a deferred renderer and "foward" to create a forward renderer. See [[std:std.filesystem.SetConfig|SetConfig]] for more information about config settings. By default, a deferred renderer is created for desktop and web targets and a forward renderer for mobile targets.
- #end
- Class Renderer
- #rem monkeydoc Creates a new renderer.
- When a new renderer is created, the config setting `MOJO3D\_RENDERER` can be used to control the type of renderer created. Use "deferred" to create a deferred renderer and "foward" to create a forward renderer. See [[std:std.filesystem.SetConfig|SetConfig]] for more information about config settings. By default, a deferred renderer is created for desktop and web targets and a forward renderer for mobile targets.
-
- #end
- Method New()
-
- If Not _current _current=Self
-
- _direct=False
- _deferred=False
-
- Local cfg:=GetConfig( "MOJO3D_RENDERER" )
-
- Select cfg
- Case "deferred"
- _deferred=True
- Case "forward"
- _deferred=False
- Case ""
- #If __DESKTOP_TARGET__ Or __WEB_TARGET__
- _deferred=True
- #else
- _deferred=False
- #endif
- Default
- RuntimeError( "Unrecognized MOJO3D_RENDERER config setting value '"+cfg+"'" )
-
- End
-
- Print "GL_VERSION="+opengl.glGetString( opengl.GL_VERSION )
- Print "GL_VENDOR="+opengl.glGetString( opengl.GL_VENDOR )
-
- If _deferred
- Print "Renderer is using deferred rendering"
- Else
- Print "Renderer is using forward rendering"
- Endif
-
- If _deferred _defs="MX2_DEFERREDRENDERER" Else _defs="MX2_FORWARDRENDERER"
-
- _defs+=";MX2_LINEAROUTPUT"
- End
-
- #rem monkeydoc True if renderer is using deferred rendering.
- #end
- Property Deferred:Bool()
-
- Return _deferred
- End
- #rem monkeydoc @hidden
- #end
- Property ShaderDefs:String()
-
- Return _defs
- End
-
- #rem monkeydoc Size of the cascaded shadow map texture.
-
- Must be a power of 2 size. Defaults to 2048.
-
- #end
- Property CSMTextureSize:Int()
-
- Return _csmSize
-
- Setter( size:Int )
- Assert( Log2( size )=Floor( Log2( size ) ),"CSMTextureSize must be a power of 2" )
-
- _csmSize=size
- End
- #rem monkeydoc Size of the cube texture used for point light shadow mapping.
-
- Must be a power of 2. Defaults to 2048.
-
- #end
- Property PSMTextureSize:Int()
-
- Return _psmSize
-
- Setter( size:Int )
- Assert( Log2( size )=Floor( Log2( size ) ),"PSMTextureSize must be a power of 2" )
-
- _psmSize=size
- End
-
- #rem monkeydoc Gets the current renderer.
-
- If there is no current renderer and new renderer is created.
-
- #end
- Function GetCurrent:Renderer()
-
- If Not _current New Renderer
-
- Return _current
- End
-
- Method Render( target:RenderTarget,targetSize:Vec2i,viewport:Recti,scene:Scene,viewMatrix:AffineMat4f,projMatrix:Mat4f,near:Float,far:Float ) Virtual
-
- Init()
-
- ValidateCSMShadows()
-
- ValidatePSMShadows()
-
- SetOutputRenderTarget( target,targetSize,viewport )
- SetScene( scene )
-
- SetCamera( viewMatrix,projMatrix,near,far )
-
- RenderBackground()
-
- RenderOpaque()
-
- RenderTransparent()
-
- RenderPostEffects()
-
- RenderCopy()
- End
-
- Method RenderBackground()
-
- If _scene.SkyTexture
-
- _gdevice.ColorMask=ColorMask.None
- _gdevice.DepthMask=True
-
- _gdevice.Clear( Null,1.0 )
-
- _gdevice.ColorMask=ColorMask.All
- _gdevice.DepthMask=False
- _gdevice.DepthFunc=DepthFunc.Always
- _gdevice.BlendMode=BlendMode.Opaque
- _gdevice.CullMode=CullMode.None
- _gdevice.Shader=_skyboxShader
- _gdevice.RenderPass=0
-
- RenderQuad()
- Else
- _gdevice.ColorMask=ColorMask.All
- _gdevice.DepthMask=True
-
- Local color:=_scene.ClearColor
- color.r=Pow( color.r,2.2 )
- color.g=Pow( color.g,2.2 )
- color.b=Pow( color.b,2.2 )
-
- _gdevice.Clear( color,1.0 )
- Endif
- End
-
- Method RenderDeferredLighting( light:Light )
-
- Local renderPass:=0
-
- Local lvmatrix:=_viewMatrix * light.Matrix
-
- Local qscale:=New Vec2f( 1 )
- Local qtrans:=New Vec2f( 0 )
-
- Select light.Type
- Case LightType.Directional
-
- If light.CastsShadow RenderDirectionalShadows( light ) ; renderPass|=16
- renderPass|=4
-
- Case LightType.Point
- Local r:=light.Range
-
- If lvmatrix.t.z<-r
- ' Print "clip1, z="+lvmatrix.t.z
- Return
- Endif
-
- If lvmatrix.t.z>r
- Local box:=New Boxf( lvmatrix.t+New Vec3f( -r ),lvmatrix.t+New Vec3f( r ) )
- Local cmin:=New Vec2f( 1 ),cmax:=New Vec2f( 0 )
- For Local i:=0 Until 8
- Local v:=(_projMatrix * box.Corner( i ) ).XY * 0.5 + 0.5
- cmin.x=Min( cmin.x,v.x );cmin.y=Min( cmin.y,v.y )
- cmax.x=Max( cmax.x,v.x );cmax.y=Max( cmax.y,v.y )
- Next
- If cmin.x>=1.0 Or cmin.y>=1.0 Return
- If cmax.x<0.0 Or cmax.y<0.0 Return
- qscale=cmax-cmin
- qtrans=cmin
- Endif
-
- If light.CastsShadow RenderPointShadows( light ) ; renderPass|=16
- renderPass|=8
-
- Case LightType.Spot
-
- If light.CastsShadow RenderSpotShadows( light ) ; renderPass|=16
- renderPass|=12
- Default
- Return
- End
-
- _runiforms.SetVec2f( "QuadCoordScale",qscale )
- _runiforms.SetVec2f( "QuadCoordTrans",qtrans )
- _runiforms.SetMat4f( "LightViewMatrix",lvmatrix )
- _runiforms.SetMat4f( "InverseLightViewMatrix",-lvmatrix )
- _runiforms.SetColor( "LightColor",light.Color )
- _runiforms.SetFloat( "LightRange",light.Range )
- _runiforms.SetFloat( "LightInnerAngle",light.InnerAngle*Pi/180.0 )
- _runiforms.SetFloat( "LightOuterAngle",light.OuterAngle*Pi/180.0 )
- _runiforms.SetTexture( "LightCubeTexture",light.Texture ?Else _whiteCubeTexture )
- _runiforms.SetTexture( "LightTexture",light.Texture ?Else _whiteTexture )
-
- _gdevice.ColorMask=ColorMask.All
- _gdevice.DepthMask=False
- _gdevice.DepthFunc=DepthFunc.Always
- _gdevice.BlendMode=BlendMode.Additive
- _gdevice.RenderPass=renderPass
-
- _gdevice.Shader=_deferredLightingShader
- _gdevice.CullMode=CullMode.None
-
- _runiforms.SetMat4f( "InverseProjectionMatrix",_invProjMatrix )
-
- RenderQuad()
- End
-
- Method RenderDeferredFog()
-
- If _scene.FogColor.a=0 Return
-
- _gdevice.ColorMask=ColorMask.All
- _gdevice.DepthMask=False
- _gdevice.DepthFunc=DepthFunc.Always
- _gdevice.BlendMode=BlendMode.Alpha
- _gdevice.RenderPass=0
-
- _gdevice.Shader=_deferredFogShader
- _gdevice.CullMode=CullMode.None
-
- RenderQuad()
- End
-
- Method RenderOpaqueDeferred()
-
- _gdevice.ColorMask=ColorMask.All
- _gdevice.DepthMask=True
- _gdevice.DepthFunc=DepthFunc.LessEqual
- _gdevice.BlendMode=BlendMode.Opaque
- _gdevice.RenderPass=1
-
- RenderOpaqueOps()
-
- 'only write to accum buffer only from now on...
- _gdevice.RenderTarget=_renderTarget1
-
- For Local light:=Eachin _scene.Lights
-
- RenderDeferredLighting( light )
- Next
-
- RenderDeferredFog()
- End
-
- Method RenderOpaqueForward()
-
- Local first:=True
-
- For Local light:=Eachin _scene.Lights
-
- Local renderPass:=2
-
- Select light.Type
- Case LightType.Directional
- If light.CastsShadow RenderDirectionalShadows( light ) ; renderPass|=16
- renderPass|=4
- Case LightType.Point
- If light.CastsShadow RenderPointShadows( light ) ; renderPass|=16
- renderPass|=8
- Case LightType.Spot
- If light.CastsShadow RenderSpotShadows( light ) ; renderPass|=16
- renderPass|=12
- End
-
- Local lvmatrix:=_viewMatrix * light.Matrix
-
- _runiforms.SetMat4f( "LightViewMatrix",lvmatrix )
- _runiforms.SetMat4f( "InverseLightViewMatrix",-lvmatrix )
- _runiforms.SetColor( "LightColor",light.Color )
- _runiforms.SetFloat( "LightRange",light.Range )
- _runiforms.SetFloat( "LightInnerAngle",light.InnerAngle*Pi/180.0 )
- _runiforms.SetFloat( "LightOuterAngle",light.OuterAngle*Pi/180.0 )
- _runiforms.SetTexture( "LightCubeTexture",light.Texture ?Else _whiteCubeTexture )
- _runiforms.SetTexture( "LightTexture",light.Texture ?Else _whiteTexture )
- _gdevice.ColorMask=ColorMask.All
- _gdevice.DepthMask=first
- _gdevice.DepthFunc=DepthFunc.LessEqual
- _gdevice.BlendMode=first ? BlendMode.Opaque Else BlendMode.Additive
- _gdevice.RenderPass=renderPass
-
- RenderOpaqueOps()
-
- first=False
- Next
-
- If first
- _gdevice.ColorMask=ColorMask.All
- _gdevice.DepthMask=True
- _gdevice.DepthFunc=DepthFunc.LessEqual
- _gdevice.BlendMode=BlendMode.Opaque
- _gdevice.RenderPass=2
-
- RenderOpaqueOps()
- Endif
-
- End
-
- Method RenderOpaque()
-
- If _deferred
- RenderOpaqueDeferred()
- Else
- RenderOpaqueForward()
- Endif
- End
-
- Method RenderSelfIlluminated()
-
- _gdevice.ColorMask=ColorMask.All
- _gdevice.DepthMask=True
- _gdevice.DepthFunc=DepthFunc.LessEqual
- _gdevice.RenderPass=1
-
- RenderSelfIlluminatedOps()
- End
- Method RenderTransparent()
-
- If _deferred _gdevice.RenderTarget=_renderTarget0
- Local first:=True
-
- For Local light:=Eachin _scene.Lights
-
- Local renderPass:=2
-
- Select light.Type
- Case LightType.Directional
- ' If light.CastsShadow RenderDirectionalShadows( light ) ; renderPass|=16
- renderPass|=4
- Case LightType.Point
- ' If light.CastsShadow RenderPointShadows( light ) ; renderPass|=16
- renderPass|=8
- Case LightType.Spot
- ' If light.CastsShadow RenderSpotShadows( light ) ; renderPass|=16
- renderPass|=12
- End
-
- _runiforms.SetColor( "LightColor",light.Color )
- _runiforms.SetFloat( "LightRange",light.Range )
- _runiforms.SetMat4f( "LightViewMatrix",_viewMatrix * light.Matrix )
-
- _gdevice.ColorMask=ColorMask.All
- _gdevice.DepthMask=False
- _gdevice.DepthFunc=DepthFunc.LessEqual
- _gdevice.RenderPass=renderPass
-
- RenderTransparentOps()
-
- first=False
-
- Exit
- Next
-
- If first
- _gdevice.ColorMask=ColorMask.All
- _gdevice.DepthMask=False
- _gdevice.DepthFunc=DepthFunc.LessEqual
- _gdevice.RenderPass=2
-
- RenderTransparentOps()
- Endif
-
- End
-
- Method RenderDirectionalShadows( light:Light )
-
- 'Perhaps use a different device for CSM...?
- '
- Local t_rtarget:=_gdevice.RenderTarget
- Local t_viewport:=_gdevice.Viewport
- Local t_scissor:=_gdevice.Scissor
- _gdevice.RenderTarget=_csmTarget
- _gdevice.Viewport=New Recti( 0,0,_csmTexture.Size )
- _gdevice.Scissor=_gdevice.Viewport
- _gdevice.ColorMask=ColorMask.All
- _gdevice.DepthMask=True
-
- _gdevice.Clear( Color.White,1.0 )
-
- _gdevice.DepthFunc=DepthFunc.LessEqual
- _gdevice.BlendMode=BlendMode.Opaque
- _gdevice.CullMode=CullMode.Front
- _gdevice.RenderPass=3|4
- Local viewLight:=light.InverseMatrix * _invViewMatrix
-
- For Local i:=0 Until _csmSplitDepths.Length-1
-
- Local znear:=_csmSplitDepths[i]
- Local zfar:=_csmSplitDepths[i+1]
- Local splitProj:=_projMatrix
- splitProj.k.z=(zfar+znear)/(zfar-znear)
- splitProj.t.z=-(zfar*znear*2)/(zfar-znear)
-
- Local invSplitProj:=-splitProj
-
- Local bounds:=Boxf.EmptyBounds
-
- For Local z:=-1 To 1 Step 2
- For Local y:=-1 To 1 Step 2
- For Local x:=-1 To 1 Step 2
- Local c:=New Vec3f( x,y,z ) 'clip coords
- Local v:=invSplitProj * c 'clip->view
- Local l:=viewLight * v 'view->light
- bounds|=l
- Next
- Next
- Next
-
- bounds.min.z-=100
-
- Local lightProj:=Mat4f.Ortho( bounds.min.x,bounds.max.x,bounds.min.y,bounds.max.y,bounds.min.z,bounds.max.z )
-
- 'set matrices for next pass...
- _runiforms.SetMat4f( "ShadowMatrix"+i,lightProj * viewLight )
-
- Local size:=_csmTexture.Size,hsize:=size/2
-
- Select i
- Case 0 _gdevice.Viewport=New Recti( 0,0,hsize.x,hsize.y )
- Case 1 _gdevice.Viewport=New Recti( hsize.x,0,size.x,hsize.y )
- Case 2 _gdevice.Viewport=New Recti( 0,hsize.y,hsize.x,size.y )
- Case 3 _gdevice.Viewport=New Recti( hsize.x,hsize.y,size.x,size.y )
- End
-
- _gdevice.Scissor=_gdevice.Viewport
-
- RenderShadowOps( light.InverseMatrix,lightProj )
- Next
-
- _gdevice.RenderTarget=t_rtarget
- _gdevice.Viewport=t_viewport
- _gdevice.Scissor=t_scissor
- End
-
- Method RenderPointShadows( light:Light )
-
- 'Perhaps use a different device for CSM...?
- '
- Local t_rtarget:=_gdevice.RenderTarget
- Local t_viewport:=_gdevice.Viewport
- Local t_scissor:=_gdevice.Scissor
-
- _gdevice.Viewport=New Recti( 0,0,_psmTexture.Size )
- _gdevice.Scissor=_gdevice.Viewport
- _gdevice.ColorMask=ColorMask.All
- _gdevice.DepthMask=True
-
- _gdevice.DepthFunc=DepthFunc.LessEqual
- _gdevice.BlendMode=BlendMode.Opaque
- _gdevice.CullMode=CullMode.Back'Front
- _gdevice.RenderPass=3|8
-
- Local near:=0.1
- Local lightProj:=Mat4f.Frustum( -near,+near,-near,+near,near,light.Range )
- lightProj.k.z=1'(zfar+znear)/(zfar-znear)
- lightProj.t.z=0'-(zfar*znear*2)/(zfar-znear)
- Local viewLight:=light.InverseMatrix * _invViewMatrix
-
- _runiforms.SetFloat( "LightRange",light.Range )
- _runiforms.SetMat4f( "ShadowMatrix0",viewLight )
-
- For Local i:=0 Until 6
-
- _gdevice.RenderTarget=_psmTargets[i]
-
- _gdevice.Clear( Color.White,1.0 )
-
- Local viewMatrix:=New AffineMat4f( _psmFaceTransforms[i] ) * light.InverseMatrix
- RenderShadowOps( viewMatrix,lightProj )
- Next
- _gdevice.RenderTarget=t_rtarget
- _gdevice.Viewport=t_viewport
- _gdevice.Scissor=t_scissor
- End
-
- Method RenderSpotShadows( light:Light )
-
- Local t_rtarget:=_gdevice.RenderTarget
- Local t_viewport:=_gdevice.Viewport
- Local t_scissor:=_gdevice.Scissor
-
- Local near:=0.1
- Local lightProj:=Mat4f.Frustum( -near,+near,-near,+near,near,light.Range )
-
- Local viewLight:=light.InverseMatrix * _invViewMatrix
-
- _runiforms.SetFloat( "LightRange",light.Range )
- _runiforms.SetMat4f( "ShadowMatrix0",lightProj * viewLight )
-
- _gdevice.RenderTarget=_csmTarget
- _gdevice.Viewport=New Recti( 0,0,_csmTexture.Size/2 )
- _gdevice.Scissor=_gdevice.Viewport
- _gdevice.ColorMask=ColorMask.All
- _gdevice.DepthMask=True
-
- _gdevice.Clear( Color.White,1.0 )
- _gdevice.DepthFunc=DepthFunc.LessEqual
- _gdevice.BlendMode=BlendMode.Opaque
- _gdevice.CullMode=CullMode.Front'Back
- _gdevice.RenderPass=3|12
- RenderShadowOps( light.InverseMatrix,lightProj )
- _gdevice.RenderTarget=t_rtarget
- _gdevice.Viewport=t_viewport
- _gdevice.Scissor=t_scissor
- End
-
- Method RenderPostEffects()
-
- If _deferred _gdevice.RenderTarget=_renderTarget1
-
- PostEffect.BeginRendering( _gdevice,_runiforms )
-
- For Local effect:=Eachin _scene.PostEffects
-
- If Not effect.Enabled Continue
-
- _gdevice.ColorMask=ColorMask.All
- _gdevice.DepthMask=False
- _gdevice.CullMode=CullMode.None
- _gdevice.DepthFunc=DepthFunc.Always
- _gdevice.BlendMode=BlendMode.Opaque
- _gdevice.RenderPass=0
-
- effect.Render()
- Next
- PostEffect.EndRendering()
- End
-
- Method RenderCopy()
-
- If _direct Return
-
- Local rsize:=_gdevice.Viewport.Size
- Local rtarget:=_gdevice.RenderTarget
- Local rtexture:=rtarget.GetColorTexture( 0 )
- _runiforms.SetTexture( "SourceBuffer",rtexture )
- _runiforms.SetVec2f( "SourceBufferSize",Cast<Vec2f>( rsize ) )
- _runiforms.SetVec2f( "SourceBufferScale",Cast<Vec2f>( rsize )/Cast<Vec2f>( rtexture.Size ) )
- _gdevice.RenderTarget=_outputRenderTarget
- _gdevice.Resize( _outputRenderTargetSize )
- _gdevice.Viewport=_outputViewport
- _gdevice.Scissor=_outputViewport
- _gdevice.ColorMask=ColorMask.All
- _gdevice.DepthMask=False
- _gdevice.DepthFunc=DepthFunc.Always
- _gdevice.BlendMode=BlendMode.Opaque
- _gdevice.CullMode=CullMode.None
- _gdevice.Shader=_copyShader
- _gdevice.RenderPass=0
-
- RenderCopyQuad()
-
- _gdevice.RenderTarget=Null
- _gdevice.Resize( Null )
- End
-
- Method RenderCopyQuad() Virtual 'So VRRenderer can override, ie: cheeze it for now!
- If _outputRenderTarget
- RenderInvertedQuad()
- Else
- RenderQuad()
- Endif
- End
-
- Method RenderInvertedQuad()
- Global _vertices:=New VertexBuffer( New Vertex3f[](
- New Vertex3f( 0,1,0,0,0 ),
- New Vertex3f( 1,1,0,1,0, ),
- New Vertex3f( 1,0,0,1,1 ),
- New Vertex3f( 0,0,0,0,1 ) ) )
-
- _gdevice.VertexBuffer=_vertices
-
- _gdevice.Render( 4,1 )
- End
-
- Method RenderQuad()
- Global _vertices:=New VertexBuffer( New Vertex3f[](
- New Vertex3f( 0,1,0,0,1 ),
- New Vertex3f( 1,1,0,1,1 ),
- New Vertex3f( 1,0,0,1,0 ),
- New Vertex3f( 0,0,0,0,0 ) ) )
-
- _gdevice.VertexBuffer=_vertices
-
- _gdevice.Render( 4,1 )
- End
-
- Method SortTransparentOps()
-
- _renderQueue.TransparentOps.Sort( Lambda:Int( x:RenderOp,y:RenderOp )
-
- If y.distance<x.distance Return -1
- If x.distance<y.distance Return 1
- Return 0
- End )
- End
-
- Method SortSpriteOps()
-
- _renderQueue.SpriteOps.Sort( Lambda:Int( x:SpriteOp,y:SpriteOp )
-
- If y.distance<x.distance Return -1
- If x.distance<y.distance Return 1
- Return 0
- End )
- End
- Method RenderOpaqueOps()
-
- RenderRenderOps( _renderQueue.OpaqueOps,_viewMatrix,_projMatrix )
- End
-
- Method RenderSelfIlluminatedOps()
-
- RenderRenderOps( _renderQueue.SelfIlluminatedOps,_viewMatrix,_projMatrix )
- End
-
- Method RenderTransparentOps()
-
- RenderRenderOps( _renderQueue.TransparentOps,_viewMatrix,_projMatrix )
- End
- Method RenderRenderOps( ops:Stack<RenderOp>,viewMatrix:AffineMat4f,projMatrix:Mat4f )
-
- Local viewProjMatrix:=projMatrix * viewMatrix
-
- _runiforms.SetMat4f( "ViewMatrix",viewMatrix )
- _runiforms.SetMat4f( "ProjectionMatrix",projMatrix )
- _runiforms.SetMat4f( "ViewProjectionMatrix",viewProjMatrix )
- _runiforms.SetMat4f( "InverseProjectionMatrix",-projMatrix )
- Local instance:Entity=Null,first:=True
- Local material:Material
- Local bones:Mat4f[]
-
- For Local op:=Eachin ops
-
- If op.instance<>instance Or first
-
- first=False
-
- instance=op.instance
-
- Local modelMat:=instance ? instance.Matrix Else New AffineMat4f
- Local modelViewMat:=viewMatrix * modelMat
- Local modelViewNormMat:=modelViewMat.m.Cofactor()
- Local modelViewProjMat:=projMatrix * modelViewMat
-
- _iuniforms.SetMat4f( "ModelMatrix",modelMat )
- _iuniforms.SetMat4f( "ModelViewMatrix",modelViewMat )
- _iuniforms.SetMat3f( "ModelViewNormalMatrix",modelViewNormMat )
- _iuniforms.SetMat4f( "ModelViewProjectionMatrix",modelViewProjMat )
- _iuniforms.SetColor( "Color",instance ? instance.Color Else Color.White )
- _iuniforms.SetFloat( "Alpha",instance ? instance.Alpha Else 1.0 )
- Endif
-
- If op.bones
- _iuniforms.SetMat4fArray( "ModelBoneMatrices",op.bones )
- Endif
-
- If op.uniforms
- _gdevice.BindUniformBlock( op.uniforms )
- Endif
-
- If op.material<>material
- material=op.material
- _gdevice.Shader=op.shader
- _gdevice.BindUniformBlock( material.Uniforms )
- _gdevice.CullMode=material.CullMode
- Endif
- _gdevice.BlendMode=op.blendMode
-
- _gdevice.VertexBuffer=op.vbuffer
-
- If op.ibuffer
- _gdevice.IndexBuffer=op.ibuffer
- _gdevice.RenderIndexed( op.order,op.count,op.first )
- Else
- _gdevice.Render( op.order,op.count,op.first )
- Endif
-
- Next
- End
-
- Method RenderShadowOps( viewMatrix:AffineMat4f,projMatrix:Mat4f )
-
- Local ops:=_renderQueue.ShadowOps
-
- Local viewProjMatrix:=projMatrix * viewMatrix
-
- _runiforms.SetMat4f( "ViewMatrix",viewMatrix )
- _runiforms.SetMat4f( "ProjectionMatrix",projMatrix )
- _runiforms.SetMat4f( "ViewProjectionMatrix",viewProjMatrix )
- _runiforms.SetMat4f( "InverseProjectionMatrix",-projMatrix )
-
- Local instance:Entity=Null,first:=True
- Local material:Material
- Local bones:Mat4f[]
-
- For Local op:=Eachin ops
-
- If op.instance<>instance Or first
- first=False
- instance=op.instance
- Local modelMat:=instance ? instance.Matrix Else New AffineMat4f
- Local modelViewMat:=viewMatrix * modelMat
- Local modelViewNormMat:=modelViewMat.m.Cofactor()
- Local modelViewProjMat:=projMatrix * modelViewMat
- _iuniforms.SetMat4f( "ModelMatrix",modelMat )
- _iuniforms.SetMat4f( "ModelViewMatrix",modelViewMat )
- _iuniforms.SetMat3f( "ModelViewNormalMatrix",modelViewNormMat )
- _iuniforms.SetMat4f( "ModelViewProjectionMatrix",modelViewProjMat )
- Endif
-
- If op.bones _iuniforms.SetMat4fArray( "ModelBoneMatrices",op.bones )
-
- If op.uniforms _gdevice.BindUniformBlock( op.uniforms )
-
- If op.material<>material
- material=op.material
- _gdevice.Shader=material.GetRenderShader()
- _gdevice.BindUniformBlock( material.Uniforms )
- Endif
-
- _gdevice.VertexBuffer=op.vbuffer
-
- If op.ibuffer
- _gdevice.IndexBuffer=op.ibuffer
- _gdevice.RenderIndexed( op.order,op.count,op.first )
- Else
- _gdevice.Render( op.order,op.count,op.first )
- Endif
-
- Next
- End
-
- Private
-
- Field _direct:Bool=False
- Field _deferred:Bool=True
- Field _defs:String
-
- Field _gdevice:GraphicsDevice
-
- Field _runiforms:UniformBlock
- Field _iuniforms:UniformBlock
-
- Field _defaultEnv:Texture
-
- Field _skyboxShader:Shader
- Field _copyShader:Shader
-
- Field _deferredLightingShader:Shader
- Field _deferredFogShader:Shader
-
- Field _renderQueue:RenderQueue
-
- Field _spriteBuffer:=New SpriteBuffer
-
- Field _accumBuffer:Texture
- Field _colorBuffer:Texture
- Field _normalBuffer:Texture
- Field _depthBuffer:Texture
- Field _renderTarget0:RenderTarget 'all buffers
- Field _renderTarget1:RenderTarget 'accum buffer only
- Field _effectBuffer:Texture
- Field _effectTarget:RenderTarget
-
- Field _csmSize:=2048
- Field _csmSplits:Float[]
- Field _csmSplitDepths:=New Float[5]
- Field _csmTexture:Texture
- Field _csmDepth:Texture
- Field _csmTarget:RenderTarget
- Field _psmSize:=2048
- Field _psmTexture:Texture
- Field _psmDepth:Texture
- Field _psmTargets:=New RenderTarget[6]
- Field _psmFaceTransforms:Mat3f[]
-
- Field _outputRenderTarget:RenderTarget
- Field _outputRenderTargetSize:Vec2i
- Field _outputViewport:Recti
-
- Field _scene:Scene
-
- Field _viewMatrix:AffineMat4f
- Field _projMatrix:Mat4f
- Field _near:Float
- Field _far:Float
-
- Field _invViewMatrix:AffineMat4f
- Field _invProjMatrix:Mat4f
-
- Field _ambientRendered:Bool
-
- Field _whiteCubeTexture:Texture
- Field _whiteTexture:Texture
- Global _current:Renderer
-
- Method Init()
-
- Global inited:Bool
- If inited Return
- inited=True
-
- _gdevice=New GraphicsDevice( 0,0 )
-
- _runiforms=New UniformBlock( 1,True )
- _iuniforms=New UniformBlock( 2,True )
-
- _gdevice.BindUniformBlock( _runiforms )
- _gdevice.BindUniformBlock( _iuniforms )
-
- _defaultEnv=Texture.Load( "asset::textures/env_default.jpg",TextureFlags.FilterMipmap|TextureFlags.Cubemap|TextureFlags.Envmap )
-
- _skyboxShader=Shader.Open( "misc/skybox",ShaderDefs )
- _copyShader=Shader.Open( "misc/copy" )
-
- If _deferred
- _deferredLightingShader=Shader.Open( "misc/lighting-deferred",ShaderDefs )
- _deferredFogShader=Shader.Open( "misc/fog-deferred",ShaderDefs )
- Endif
- _renderQueue=New RenderQueue
-
- _psmFaceTransforms=New Mat3f[](
- New Mat3f( 0,0,+1, 0,-1,0, -1, 0,0 ), '+X
- New Mat3f( 0,0,-1, 0,-1,0, +1, 0,0 ), '-X
- New Mat3f( +1,0, 0, 0,0,+1, 0,+1,0 ), '+Y
- New Mat3f( +1,0, 0, 0,0,-1, 0,-1,0 ), '-Y
- New Mat3f( +1,0, 0, 0,-1,0, 0,0,+1 ), '+Z
- New Mat3f( -1,0, 0, 0,-1,0, 0,0,-1 ) ) '-Z
-
- Local pixmap:=New Pixmap( 1,1,PixelFormat.I8 )
- pixmap.Clear( Color.White )
- _whiteCubeTexture=New Texture( pixmap,TextureFlags.Cubemap )
-
- _whiteTexture=Texture.ColorTexture( Color.White )
-
- ValidateSize( New Vec2i( 1920,1080 ) )
- End
-
- Method ValidateSize( size:Vec2i )
-
- If _direct Return
-
- If _accumBuffer And size.x<=_accumBuffer.Size.x And size.y<=_accumBuffer.Size.y Return
-
- _accumBuffer?.Discard()
- _colorBuffer?.Discard()
- _normalBuffer?.Discard()
- _depthBuffer?.Discard()
- _renderTarget0?.Discard()
- _renderTarget1?.Discard()
-
- Local color_format:=PixelFormat.RGBA32F
- Local depth_format:=PixelFormat.Depth32
-
- If GetConfig("MOJO_OPENGL_PROFILE")="es"
- color_format=PixelFormat.RGBA8
- Endif
-
- If _deferred
-
- _accumBuffer=New Texture( size.x,size.y,color_format,TextureFlags.Dynamic|TextureFlags.Filter )
- _colorBuffer=New Texture( size.x,size.y,color_format,TextureFlags.Dynamic|TextureFlags.Filter )
- _normalBuffer=New Texture( size.x,size.y,color_format,TextureFlags.Dynamic|TextureFlags.Filter )
- _depthBuffer=New Texture( size.x,size.y,depth_format,TextureFlags.Dynamic )
-
- _renderTarget0=New RenderTarget( New Texture[]( _accumBuffer,_colorBuffer,_normalBuffer ),_depthBuffer )
- _renderTarget1=New RenderTarget( New Texture[]( _accumBuffer ),Null )
- _runiforms.SetTexture( "AccumBuffer",_accumBuffer )
- _runiforms.SetTexture( "ColorBuffer",_colorBuffer )
- _runiforms.SetTexture( "NormalBuffer",_normalBuffer )
- _runiforms.SetTexture( "DepthBuffer",_depthBuffer )
- Else
-
- _accumBuffer=New Texture( size.x,size.y,color_format,TextureFlags.Dynamic|TextureFlags.Filter )
- _depthBuffer=New Texture( size.x,size.y,depth_format,TextureFlags.Dynamic )
-
- _renderTarget0=New RenderTarget( New Texture[]( _accumBuffer ),_depthBuffer )
- _renderTarget1=New RenderTarget( New Texture[]( _accumBuffer ),Null )
- _runiforms.SetTexture( "AccumBuffer",_accumBuffer )
- _runiforms.SetTexture( "DepthBuffer",_depthBuffer )
- Endif
-
- End
-
- Method ValidateCSMShadows()
-
- If Not _csmTexture Or _csmSize*2<>_csmTexture.Size.x
-
- _csmTarget?.Discard()
- _csmTexture?.Discard()
- _csmDepth?.Discard()
- const depth_format:=PixelFormat.Depth32
-
- _csmTexture=New Texture( _csmSize*2,_csmSize*2,depth_format,TextureFlags.Dynamic )'|TextureFlags.Filter )
- _csmTarget=New RenderTarget( Null,_csmTexture )
- _csmDepth=Null
-
- _runiforms.SetTexture( "ShadowCSMTexture",_csmTexture )
- Endif
-
- End
- Method ValidatePSMShadows()
-
- If Not _psmTexture Or _psmSize<>_psmTexture.Size.x
-
- _psmTexture?.Discard()
- _psmDepth?.Discard()
- For Local i:=0 Until 6
- _psmTargets[i]?.Discard()
- Next
-
- const color_format:=PixelFormat.RGBA8
- const depth_format:=PixelFormat.Depth32
-
- _psmTexture=New Texture( _psmSize,_psmSize,color_format,TextureFlags.Cubemap|TextureFlags.Dynamic )
- _psmDepth=New Texture( _psmSize,_psmSize,depth_format,TextureFlags.Dynamic )
- For Local i:=0 Until 6
- Local face:=_psmTexture.GetCubeFace( Cast<CubeFace>( i ) )
- _psmTargets[i]=New RenderTarget( New Texture[]( face ),_psmDepth )
- Next
-
- _runiforms.SetTexture( "ShadowCubeTexture",_psmTexture )
- Endif
-
- End
-
- Method SetOutputRenderTarget( renderTarget:RenderTarget,renderTargetSize:Vec2i,viewport:Recti )
-
- _outputRenderTarget=renderTarget
- _outputRenderTargetSize=renderTargetSize
- _outputViewport=viewport
-
- ValidateSize( viewport.Size )
- If _direct
- _gdevice.RenderTarget=renderTarget
- _gdevice.Resize( renderTargetSize )
- _gdevice.Viewport=viewport
- _gdevice.Scissor=viewport
- Return
- Endif
-
- _gdevice.RenderTarget=_renderTarget0
- _gdevice.Viewport=New Recti( 0,0,viewport.Size )
- _gdevice.Scissor=_gdevice.Viewport
-
- _runiforms.SetVec2f( "BufferCoordScale",Cast<Vec2f>( viewport.Size )/Cast<Vec2f>( _accumBuffer.Size ) )
- End
-
- Method SetScene( scene:Scene )
-
- _scene=scene
-
- Local sky:=_scene.SkyTexture
-
- If sky
- _runiforms.SetColor( "SkyColor",_scene.SkyColor )
- If sky.Flags & TextureFlags.Cubemap
- _runiforms.SetTexture( "SkyTextureCube",sky )
- _runiforms.SetTexture( "SkyTexture2D",_whiteTexture )
- _runiforms.SetInt( "SkyCube",1 )
- Else
- _runiforms.SetTexture( "SkyTextureCube",_whiteCubeTexture )
- _runiforms.SetTexture( "SkyTexture2D",sky )
- _runiforms.SetInt( "SkyCube",0 )
- Endif
- Else
- _runiforms.SetTexture( "SkyTextureCube",Null )
- _runiforms.SetTexture( "SkyTexture2D",Null )
- Endif
-
- _runiforms.SetColor( "ClearColor",_scene.ClearColor )
- _runiforms.SetColor( "AmbientDiffuse",_scene.AmbientLight )
-
- Local env:=(_scene.EnvTexture ?Else _scene.SkyTexture) ?Else _defaultEnv
-
- If env.Flags & TextureFlags.Cubemap
- _runiforms.SetTexture( "EnvTextureCube",env )
- _runiforms.SetTexture( "EnvTexture2D",_whiteTexture )
- _runiforms.SetInt( "EnvCube",1 )
- Else
- _runiforms.SetTexture( "EnvTextureCube",_whiteCubeTexture )
- _runiforms.SetTexture( "EnvTexture2D",env )
- _runiforms.SetInt( "EnvCube",0 )
- Endif
-
- _runiforms.SetFloat( "EnvTextureMaxLod",Log2( env.Size.x ) )
- _runiforms.SetColor( "EnvColor",_scene.EnvColor )
-
- _runiforms.SetColor( "FogColor",_scene.FogColor )
- _runiforms.SetFloat( "FogNear",_scene.FogNear )
- _runiforms.SetFloat( "FogFar",_scene.FogFar )
-
- _runiforms.SetFloat( "ShadowAlpha",_scene.ShadowAlpha )
-
- _csmSplits=_scene.CSMSplits
-
- End
-
- Method SetCamera( viewMatrix:AffineMat4f,projMatrix:Mat4f,near:Float,far:Float )
-
- _viewMatrix=viewMatrix
- _projMatrix=projMatrix
- _near=near
- _far=far
-
- _invViewMatrix=-_viewMatrix
- _invProjMatrix=-_projMatrix
- _runiforms.SetMat3f( "EnvMatrix",_invViewMatrix.m )
- _runiforms.SetMat4f( "ProjectionMatrix",_projMatrix )
- _runiforms.SetMat4f( "InverseProjectionMatrix",_invProjMatrix )
- _runiforms.SetMat4f( "ViewMatrix",_viewMatrix )
- _runiforms.SetMat4f( "CameraMatrix",_invViewMatrix )
- _runiforms.SetFloat( "DepthNear",_near )
- _runiforms.SetFloat( "DepthFar",_far )
-
- _csmSplitDepths[0]=_near
-
- For Local i:=1 Until 5
- _csmSplitDepths[i]=Min( _csmSplitDepths[i-1]+_csmSplits[i-1],_far )
- Next
-
- _runiforms.SetVec4f( "ShadowCSMSplits",New Vec4f( _csmSplitDepths[1],_csmSplitDepths[2],_csmSplitDepths[3],_csmSplitDepths[4] ) )
-
- _renderQueue.Clear()
-
- Local time:=Float( Now() )
- _renderQueue.Time=time
-
- _runiforms.SetFloat( "Time",time )
-
- _renderQueue.EyePos=_invViewMatrix.t
-
- For Local r:=Eachin _scene.Renderables
-
- _renderQueue.AddShadowOps=r.CastsShadow
-
- r.OnRender( _renderQueue )
- Next
-
- SortTransparentOps()
-
- SortSpriteOps()
-
- _spriteBuffer.InsertRenderOps( _renderQueue,_invViewMatrix )
- End
-
- End
|