Browse Source

Began work on ForwardRenderer.

Mark Sibly 8 years ago
parent
commit
f44c0ba353
32 changed files with 1109 additions and 421 deletions
  1. 1 1
      modules/mojo3d/graphics/bloomeffect.monkey2
  2. 218 0
      modules/mojo3d/graphics/deferredrenderer.monkey2
  3. 1 1
      modules/mojo3d/graphics/fogeffect.monkey2
  4. 201 0
      modules/mojo3d/graphics/forwardrenderer.monkey2
  5. 1 1
      modules/mojo3d/graphics/gltf2.monkey2
  6. 3 3
      modules/mojo3d/graphics/gltf2loader.monkey2
  7. 9 5
      modules/mojo3d/graphics/material.monkey2
  8. 1 1
      modules/mojo3d/graphics/monochromeeffect.monkey2
  9. 8 1
      modules/mojo3d/graphics/pbrmaterial.monkey2
  10. 13 2
      modules/mojo3d/graphics/posteffect.monkey2
  11. 140 350
      modules/mojo3d/graphics/renderer.monkey2
  12. 109 0
      modules/mojo3d/graphics/renderqueue.monkey2
  13. 14 1
      modules/mojo3d/graphics/scene.monkey2
  14. 0 0
      modules/mojo3d/graphics/shaders/effect-bloom.glsl
  15. 0 0
      modules/mojo3d/graphics/shaders/effect-fog.glsl
  16. 0 0
      modules/mojo3d/graphics/shaders/effect-monochrome.glsl
  17. 0 0
      modules/mojo3d/graphics/shaders/light-directional-deferred.glsl
  18. 0 0
      modules/mojo3d/graphics/shaders/light-point-deferred.glsl
  19. 4 5
      modules/mojo3d/graphics/shaders/material-pbr-deferred.glsl
  20. 330 0
      modules/mojo3d/graphics/shaders/material-pbr-forward.glsl
  21. 4 0
      modules/mojo3d/graphics/shaders/material-sprite.glsl
  22. 1 29
      modules/mojo3d/graphics/shaders/material-water.glsl
  23. 7 1
      modules/mojo3d/graphics/shaders/skybox.glsl
  24. 4 1
      modules/mojo3d/graphics/spritematerial.monkey2
  25. 3 1
      modules/mojo3d/graphics/watermaterial.monkey2
  26. 5 2
      modules/mojo3d/mojo3d.monkey2
  27. 0 1
      modules/mojo3d/tests/donut.monkey2
  28. 13 10
      modules/mojo3d/tests/ducks.monkey2
  29. 6 1
      modules/mojo3d/tests/pbrspheres.monkey2
  30. 6 1
      modules/mojo3d/tests/sprites.monkey2
  31. 2 2
      modules/mojo3d/tests/util.monkey2
  32. 5 1
      modules/mojo3d/tests/water.monkey2

+ 1 - 1
modules/mojo3d/graphics/bloomeffect.monkey2

@@ -12,7 +12,7 @@ Class BloomEffect Extends PostEffect
 	#end
 	Method New( passes:Int=2 )
 		
-		_shader=Shader.Open( "bloom" )
+		_shader=Shader.Open( "effect-bloom" )
 		
 		_uniforms=New UniformBlock( 3 )
 		

+ 218 - 0
modules/mojo3d/graphics/deferredrenderer.monkey2

@@ -0,0 +1,218 @@
+
+Namespace mojo3d.graphics
+
+#rem
+
+Material render passes:
+
+1 : opaque ambient
+
+4 : opaque shadow depth
+
+#end
+
+#rem monkeydoc The DeferredRenderer class.
+#end
+Class DeferredRenderer Extends Renderer
+
+	#rem monkeydoc @hidden
+	#end
+	Method New()
+		Super.New( "MX2_LINEAROUTPUT" )
+		
+		Print "Creating DeferredRenderer"
+	
+		_dlightShader=Shader.Open( "light-directional-deferred" )
+		_plightShader=Shader.Open( "light-point-deferred" )
+		_copyShader=Shader.Open( "copy" )
+		
+	End
+
+	Protected
+
+	Method OnValidateSize( size:Vec2i ) Override
+		
+		If Not _hdrTexture Or size.x>_hdrTexture.Size.x Or size.y>_hdrTexture.Size.y
+		
+			SafeDiscard( _hdrTexture )
+			SafeDiscard( _colorTexture )
+			SafeDiscard( _normalTexture )
+			SafeDiscard( _depthTexture )
+			SafeDiscard( _rpass0Target )
+			SafeDiscard( _rpass2Target )
+		
+			Const format:=PixelFormat.RGBA32F		'32 bit float
+				
+			_hdrTexture=New Texture( size.x,size.y,format,TextureFlags.Filter|TextureFlags.Dynamic )		'output hdr image
+			_colorTexture=New Texture( size.x,size.y,format,TextureFlags.Filter|TextureFlags.Dynamic )		'metalness in 'a'
+			_normalTexture=New Texture( size.x,size.y,format,TextureFlags.Filter|TextureFlags.Dynamic )		'roughness in 'a'
+			_depthTexture=New Texture( size.x,size.y,PixelFormat.Depth32F,TextureFlags.Dynamic )
+				
+			_rpass0Target=New RenderTarget( New Texture[]( _hdrTexture,_colorTexture,_normalTexture ),_depthTexture )
+			_rpass2Target=New RenderTarget( New Texture[]( _hdrTexture ),Null )
+			
+			_runiforms=RenderUniforms
+				
+			_runiforms.SetTexture( "ColorBuffer",_colorTexture )
+			_runiforms.SetTexture( "NormalBuffer",_normalTexture )
+			_runiforms.SetTexture( "DepthBuffer",_depthTexture )
+			
+		Endif
+	
+	End
+
+	Method OnRender( scene:Scene,camera:Camera,device:GraphicsDevice ) Override
+	
+		_device=Device
+		_runiforms=RenderUniforms
+		_renderTarget=device.RenderTarget
+		_renderTargetSize=device.RenderTargetSize
+		_renderViewport=device.Viewport
+	
+		_device.RenderTarget=_rpass0Target
+		_device.Viewport=New Recti( 0,0,_renderViewport.Size )
+		_device.Scissor=_device.Viewport
+
+		RenderBackground()
+		
+		RenderOpaque()
+
+		_device.RenderTarget=_rpass2Target
+		
+		_runiforms.SetVec2f( "BufferCoordScale",Cast<Vec2f>( _renderViewport.Size )/Cast<Vec2f>( _hdrTexture.Size ) )
+		
+		For Local light:=Eachin scene.Lights
+			
+			If light.Type=LightType.Point Continue
+
+			RenderCSMShadows( light )
+			
+			RenderLight( light,camera )
+		Next
+		
+		_device.RenderTarget=_rpass0Target
+		
+		RenderSprites()
+
+		_device.RenderTarget=_rpass2Target
+
+		RenderEffects( scene )
+		
+		_device.RenderTarget=_renderTarget
+		_device.Resize( _renderTargetSize )
+		_device.Viewport=_renderViewport
+		_device.Scissor=_device.Viewport
+
+		RenderCopy()
+	End
+		
+	Private
+	
+	Field _plightShader:Shader
+	Field _dlightShader:Shader
+	Field _copyShader:Shader
+	
+	Field _hdrTexture:Texture		'contains output linear HDR color
+	Field _colorTexture:Texture		'contains surface color/M
+	Field _normalTexture:Texture	'contains surface normal/R
+	Field _depthTexture:Texture		'contains surface depth
+	Field _rpass0Target:RenderTarget
+	Field _rpass2Target:RenderTarget
+	
+	Field _device:GraphicsDevice
+	Field _runiforms:UniformBlock
+	Field _renderTarget:RenderTarget
+	Field _renderTargetSize:Vec2i
+	Field _renderViewport:Recti
+	
+	Method RenderOpaque()
+		
+		_device.ColorMask=ColorMask.All
+		_device.DepthMask=True
+		_device.DepthFunc=DepthFunc.LessEqual
+		_device.BlendMode=BlendMode.Opaque
+		_device.RenderPass=1
+
+		Super.RenderOpaqueOps()
+	End
+	
+	Method RenderSprites()
+
+		_device.ColorMask=ColorMask.All
+		_device.DepthMask=False
+		_device.DepthFunc=DepthFunc.LessEqual
+		_device.RenderPass=0
+		
+		Super.RenderSpriteOps()
+	End
+	
+	Method RenderLight( light:Light,camera:Camera )
+	
+		_runiforms.SetVec4f( "LightColor",light.Color )
+		_runiforms.SetFloat( "LightRange",light.Range )
+		_runiforms.SetMat4f( "LightViewMatrix",camera.InverseMatrix * light.Matrix )
+		
+		_runiforms.SetMat4f( "InverseProjectionMatrix",-camera.ProjectionMatrix )
+		
+		_device.ColorMask=ColorMask.All
+		_device.DepthMask=False
+		_device.DepthFunc=DepthFunc.Always
+		_device.BlendMode=BlendMode.Additive
+		_device.CullMode=CullMode.None
+		_device.RenderPass=3
+		
+		Select light.Type
+		Case LightType.Directional
+		
+			_device.Shader=_dlightShader
+			
+			RenderQuad()
+		
+		Case LightType.Point
+
+			_device.Shader=_plightShader
+			
+			RenderQuad()
+		End
+
+	End
+
+	Method RenderEffects( scene:Scene )
+		
+		_device.ColorMask=ColorMask.All
+		_device.DepthMask=False
+		_device.DepthFunc=DepthFunc.Always
+		_device.CullMode=CullMode.None
+
+		For Local effect:=Eachin scene.PostEffects
+			
+			If Not effect.Enabled Continue
+			
+			_device.BlendMode=BlendMode.Opaque
+			_device.RenderPass=0
+			
+			effect.Render( _device )
+		Next
+		
+	End
+	
+	Method RenderCopy()
+	
+		_runiforms.SetTexture( "SourceTexture",_hdrTexture )
+		_runiforms.SetVec2f( "SourceCoordScale",Cast<Vec2f>( _renderViewport.Size )/Cast<Vec2f>( _hdrTexture.Size ) )
+
+		_device.ColorMask=ColorMask.All
+		_device.DepthMask=False
+		_device.DepthFunc=DepthFunc.Always
+		_device.BlendMode=BlendMode.Opaque
+		_device.CullMode=CullMode.None
+		_device.Shader=_copyShader
+		_device.RenderPass=0
+
+		Super.RenderQuad()
+		
+		_device.RenderTarget=Null
+		_device.Resize( Null )
+	End
+
+End

+ 1 - 1
modules/mojo3d/graphics/fogeffect.monkey2

@@ -12,7 +12,7 @@ Class FogEffect Extends PostEffect
 	#end	
 	Method New( color:Color=std.graphics.Color.Sky,near:Float=0,far:Float=1000 )
 
-		_shader=Shader.Open( "fog" )
+		_shader=Shader.Open( "effect-fog" )
 		
 		_uniforms=New UniformBlock( 3 )
 		

+ 201 - 0
modules/mojo3d/graphics/forwardrenderer.monkey2

@@ -0,0 +1,201 @@
+
+Namespace mojo3d.graphics
+
+#rem
+
+Render passes:
+
+1 : opaque ambient only
+
+2 : opaque lighting only
+
+3 : opaque ambient + lighting
+
+4 : shadow caster depth only
+
+#end
+
+#rem monkeydoc The ForwardRenderer class.
+#end
+Class ForwardRenderer Extends Renderer
+
+	#rem monkeydoc @hidden
+	#end
+	Method New( deferred:Bool )
+		Super.New( deferred ? "MX2_LINEAROUTPUT" Else "MX2_SRGBOUTPUT" )
+		
+		_deferred=deferred
+		
+		Print "Creating ForwardRenderer, deferred="+Int( _deferred )
+		
+		If _deferred _copyShader=Shader.Open( "copy" )
+	End
+	
+	Protected
+	
+	Method OnValidateSize( size:Vec2i ) Override 
+		
+		If Not _deferred Return
+
+		If Not _colorBuffer Or size.x>_colorBuffer.Size.x Or size.y>_colorBuffer.Size.y
+			
+			SafeDiscard( _colorBuffer )
+			SafeDiscard( _depthBuffer )
+			SafeDiscard( _colorTarget0 )
+			SafeDiscard( _colorTarget1 )
+			
+			Const format:=PixelFormat.RGBA32F
+				
+			_colorBuffer=New Texture( size.x,size.y,format,TextureFlags.Filter|TextureFlags.Dynamic )
+			_depthBuffer=New Texture( size.x,size.y,PixelFormat.Depth32F,TextureFlags.Dynamic )
+			_colorTarget0=New RenderTarget( New Texture[]( _colorBuffer ),_depthBuffer )
+			_colorTarget1=New RenderTarget( New Texture[]( _colorBuffer ),Null )
+			
+			_runiforms=RenderUniforms
+
+			_runiforms.SetTexture( "DepthBuffer",_depthBuffer )
+			
+		Endif
+		
+	End
+	
+	Method OnRender( scene:Scene,camera:Camera,device:GraphicsDevice ) Override
+		
+		_device=Device
+		_runiforms=RenderUniforms
+		
+		If _deferred
+			_renderTarget=device.RenderTarget
+			_renderTargetSize=device.RenderTargetSize
+			_renderViewport=device.Viewport
+			'
+			_device.RenderTarget=_colorTarget0
+			_device.Viewport=New Recti( 0,0,_renderViewport.Size )
+			_device.Scissor=_device.Viewport
+		Else
+			_device.RenderTarget=device.RenderTarget
+			_device.Resize( device.RenderTargetSize )
+			_device.Viewport=device.Viewport
+			_device.Scissor=_device.Viewport
+		Endif
+				
+		RenderBackground()
+		
+		Local rambient:=False
+		
+		For Local light:=Eachin scene.Lights
+			If light.Type<>LightType.Directional Continue
+			
+			RenderCSMShadows( light )
+
+			_runiforms.SetVec4f( "LightColor",light.Color )
+			_runiforms.SetFloat( "LightRange",light.Range )
+			_runiforms.SetMat4f( "LightViewMatrix",camera.InverseMatrix * light.Matrix )
+			
+			If rambient
+				RenderOpaque( BlendMode.Additive,2 )
+			Else
+				RenderOpaque( BlendMode.Opaque,3 )
+				rambient=True
+			Endif
+			
+		Next
+		
+		If Not rambient
+			RenderOpaque( BlendMode.Opaque,1 )
+		Endif
+		
+		RenderSprites()
+		
+		If _deferred
+		
+			_device.RenderTarget=_colorTarget1
+			RenderEffects( scene )
+
+			_device.RenderTarget=_renderTarget
+			_device.Resize( _renderTargetSize )
+			_device.Viewport=_renderViewport
+			_device.Scissor=_device.Viewport
+			RenderCopy()
+		Endif
+		
+	End
+	
+	Private
+	
+	Field _deferred:bool
+	
+	Field _copyShader:Shader
+	Field _colorBuffer:Texture
+	Field _depthBuffer:Texture
+	Field _colorTarget0:RenderTarget	'colorBuffer+depthBuffer
+	Field _colorTarget1:RenderTarget	'colorBuffer only
+
+	Field _renderTarget:RenderTarget
+	Field _renderTargetSize:Vec2i
+	Field _renderViewport:Recti
+	
+	Field _device:GraphicsDevice
+	Field _runiforms:UniformBlock
+	
+	Method RenderOpaque( blendMode:BlendMode,renderPass:Int )
+		
+		_device.ColorMask=ColorMask.All
+		_device.DepthMask=True
+		_device.DepthFunc=DepthFunc.LessEqual
+		_device.BlendMode=blendMode
+		_device.RenderPass=renderPass
+
+		Super.RenderOpaqueOps()
+	End
+	
+	Method RenderSprites()
+
+		_device.ColorMask=ColorMask.All
+		_device.DepthMask=False
+		_device.DepthFunc=DepthFunc.LessEqual
+		_device.RenderPass=0
+		
+		Super.RenderSpriteOps()
+	End
+	
+	Method RenderEffects( scene:Scene )
+		
+		_runiforms.SetVec2f( "BufferCoordScale",Cast<Vec2f>( _renderViewport.Size )/Cast<Vec2f>( _colorBuffer.Size ) )
+		
+		_device.ColorMask=ColorMask.All
+		_device.DepthMask=False
+		_device.DepthFunc=DepthFunc.Always
+		_device.CullMode=CullMode.None
+
+		For Local effect:=Eachin scene.PostEffects
+			
+			If Not effect.Enabled Continue
+			
+			_device.BlendMode=BlendMode.Opaque
+			_device.RenderPass=0
+			
+			effect.Render( _device )
+		Next
+		
+	End
+
+	Method RenderCopy()
+		
+		_runiforms.SetTexture( "SourceTexture",_colorBuffer )
+		_runiforms.SetVec2f( "SourceCoordScale",Cast<Vec2f>( _renderViewport.Size )/Cast<Vec2f>( _colorBuffer.Size ) )
+
+		_device.ColorMask=ColorMask.All
+		_device.DepthMask=False
+		_device.DepthFunc=DepthFunc.Always
+		_device.BlendMode=BlendMode.Opaque
+		_device.CullMode=CullMode.None
+		_device.Shader=_copyShader
+		_device.RenderPass=0
+		RenderQuad()
+		
+		_device.RenderTarget=Null
+		_device.Resize( Null )
+	End
+
+End

+ 1 - 1
modules/mojo3d/graphics/gltf2.monkey2

@@ -507,7 +507,7 @@ Class Gltf2Asset
 		If Not asset Return False
 		
 		Local version:=asset.GetString( "version" )
-		Print "Gtf2 version="+version
+'		Print "Gltf2 version="+version
 		
 		If Not LoadBuffers() Return False
 		If Not LoadBufferViews() Return False

+ 3 - 3
modules/mojo3d/graphics/gltf2loader.monkey2

@@ -89,7 +89,7 @@ Class Gltf2Loader
 		
 		Local tex:=Texture.Load( _dir+texture.source.uri,flags )
 		
-		Print "Opened texture:"+_dir+texture.source.uri
+'		Print "Opened texture:"+_dir+texture.source.uri
 		
 		_textureCache[texture]=tex
 		Return tex
@@ -148,7 +148,7 @@ Class Gltf2Loader
 		
 		If node.mesh
 			
-			Print "mesh="+node.mesh.name
+'			Print "mesh="+node.mesh.name
 			
 			Local matrix:=Cast<AffineMat4f>( GetMatrix( node ) )
 
@@ -239,7 +239,7 @@ Class Gltf2Loader
 					
 				Endif
 					
-				Print "Added "+vcount+" vertices, "+icount+" indices."
+'				Print "Added "+vcount+" vertices, "+icount+" indices."
 				
 			Next
 			

+ 9 - 5
modules/mojo3d/graphics/material.monkey2

@@ -5,14 +5,18 @@ Namespace mojo3d.graphics
 #end
 Class Material Extends Resource
 	
-	#rem monkeydoc Creates a new material
-	#end
-	Method New( shader:Shader=Null )
-		_shader=shader
-		_uniforms=New UniformBlock( 3 )
+	Method New()
 		_blendMode=BlendMode.Opaque
 		_cullMode=CullMode.Back
+		_uniforms=New UniformBlock( 3 )
 		TextureMatrix=New AffineMat3f
+	End		
+	
+	#rem monkeydoc Creates a new material
+	#end
+	Method New( shader:Shader )
+		Self.New()
+		_shader=shader
 	End
 	
 	#rem monkeydoc Creates a copy of the material.

+ 1 - 1
modules/mojo3d/graphics/monochromeeffect.monkey2

@@ -9,7 +9,7 @@ Class MonochromeEffect Extends PostEffect
 	#end
 	Method New( level:Float=1.0 )
 		
-		_shader=Shader.Open( "monochrome" )
+		_shader=Shader.Open( "effect-monochrome" )
 		
 		_uniforms=New UniformBlock( 3 )
 		

+ 8 - 1
modules/mojo3d/graphics/pbrmaterial.monkey2

@@ -31,7 +31,14 @@ Class PbrMaterial Extends Material
 		Endif
 		If boned defs+="MX2_BONED~n"
 			
-		SetShader( Shader.Open( "material",defs ) )
+		Local shader:="material-pbr-deferred"
+		defs+=Renderer.GetCurrent().ShaderDefs
+			
+		If Cast<ForwardRenderer>( Renderer.GetCurrent() )
+			shader="material-pbr-forward"
+		Endif
+			
+		SetShader( Shader.Open( shader,defs ) )
 		
 		ColorTexture=Texture.ColorTexture( Color.White )
 		ColorFactor=Color.White

+ 13 - 2
modules/mojo3d/graphics/posteffect.monkey2

@@ -59,8 +59,19 @@ Class PostEffect
 	#rem monkeydoc @hidden
 	#end	
 	Method RenderQuad()
-		
-		_device.Render( 4,1,0 )
+
+		Global _vertices:VertexBuffer
+	
+		If Not _vertices
+			_vertices=New VertexBuffer( New Vertex3f[](
+			New Vertex3f( 0,1,0 ),
+			New Vertex3f( 1,1,0 ),
+			New Vertex3f( 1,0,0 ),
+			New Vertex3f( 0,0,0 ) ) )
+		Endif
+			
+		_device.VertexBuffer=_vertices
+		_device.Render( 4,1 )
 	End
 		
 	Private

+ 140 - 350
modules/mojo3d/graphics/renderer.monkey2

@@ -1,164 +1,21 @@
 
 Namespace mojo3d.graphics
 
-#rem
-
-Renderpasses:
-
-1 : opaque ambient
-
-2 : opaque shadow depth
-
-3 : transparent
-
-#end
-
-#rem monkeydoc @hidden
-#end
-Class RenderOp
-	Field material:Material
-	Field vbuffer:VertexBuffer
-	Field ibuffer:IndexBuffer
-	Field instance:Entity
-	Field bones:Mat4f[]
-	Field order:Int
-	Field count:Int
-	Field first:Int
-End
-
-#rem monkeydoc @hidden
-#end
-Class RenderQueue
-	
-	Property OpaqueOps:Stack<RenderOp>()
-		
-		Return _opaqueOps
-	End
-	
-	Property TransparentOps:Stack<RenderOp>()
-	
-		Return _transparentOps
-	End
-	
-	Property ShadowOps:Stack<RenderOp>()
-		
-		Return _shadowOps
-	End
-	
-	Property AddShadowOps:Bool()
-		
-		Return _addShadowOps
-		
-	Setter( addShadowOps:Bool )
-		
-		_addShadowOps=addShadowOps
-	End
-	
-	Method Clear()
-		
-		_opaqueOps.Clear()
-		_shadowOps.Clear()
-		_transparentOps.Clear()
-	End
-	
-	Method AddRenderOp( op:RenderOp )
-		
-		If op.material.BlendMode<>BlendMode.Opaque
-			_transparentOps.Push( op )
-		Else
-			_opaqueOps.Push( op )
-		Endif
-		
-		If _addShadowOps _shadowOps.Push( op )
-	End
-	
-	Method AddRenderOp( material:Material,vbuffer:VertexBuffer,ibuffer:IndexBuffer,order:Int,count:Int,first:Int )
-		Local op:=New RenderOp
-		op.material=material
-		op.vbuffer=vbuffer
-		op.ibuffer=ibuffer
-		op.order=order
-		op.count=count
-		op.first=first
-		AddRenderOp( op )
-	End
-	
-	Method AddRenderOp( material:Material,vbuffer:VertexBuffer,ibuffer:IndexBuffer,instance:Entity,order:Int,count:Int,first:Int )
-		Local op:=New RenderOp
-		op.material=material
-		op.vbuffer=vbuffer
-		op.ibuffer=ibuffer
-		op.instance=instance
-		op.order=order
-		op.count=count
-		op.first=first
-		AddRenderOp( op )
-	End
-	
-	Method AddRenderOp( material:Material,vbuffer:VertexBuffer,ibuffer:IndexBuffer,instance:Entity,bones:Mat4f[],order:Int,count:Int,first:Int )
-		Local op:=New RenderOp
-		op.material=material
-		op.vbuffer=vbuffer
-		op.ibuffer=ibuffer
-		op.instance=instance
-		op.bones=bones
-		op.order=order
-		op.count=count
-		op.first=first
-		AddRenderOp( op )
-	End
-	
-	Private
-	
-	Field _opaqueOps:=New Stack<RenderOp>
-	Field _transparentOps:=New Stack<RenderOp>
-	Field _shadowOps:=New Stack<RenderOp>
-	
-	Field _addShadowOps:Bool
-End
-
 #rem monkeydoc The Renderer class.
 #end
 Class Renderer
-
+	
 	#rem monkeydoc @hidden
 	#end
-	Method New()
-	
-		_device=New GraphicsDevice( 0,0 )
-		
-		_runiforms=New UniformBlock( 1 )
-		_iuniforms=New UniformBlock( 2 )
-		
-		_device.BindUniformBlock( _runiforms )
-		_device.BindUniformBlock( _iuniforms )
-
-		_csmSplits=New Float[]( 1,20,60,180,1000 )
-
-		_quadVertices=New VertexBuffer( New Vertex3f[](
-			New Vertex3f( 0,1,0 ),
-			New Vertex3f( 1,1,0 ),
-			New Vertex3f( 1,0,0 ),
-			New Vertex3f( 0,0,0 ) ) )
-			
-		_defaultEnv=Texture.Load( "asset::textures/env_default.jpg",TextureFlags.FilterMipmap|TextureFlags.Cubemap )
+	Property ShaderDefs:String()
 		
-		_skyboxShader=Shader.Open( "skybox" )
-		_plightShader=Shader.Open( "point-light" )
-		_dlightShader=Shader.Open( "directional-light" )
-		_copyShader=Shader.Open( "copy" )
-
-		For Local i:=0 Until _nullBones.Length
-			_nullBones[i]=New Mat4f
-		Next
+		Return _shaderDefs
 	End
+
+	#rem monkeydoc Size of cascading shadow map texture.
 	
-	#rem monkeydoc Size of the cascading shadow map texture.
-	
-	Must be a power of 2 size.
+	Must be a power of 2 size. Defaults to 1024.
 	
-	Defaults to 4096.
-		
 	#end
 	Property CSMTextureSize:Float()
 		
@@ -189,32 +46,59 @@ Class Renderer
 	#end
 	Function GetCurrent:Renderer()
 		
-		Global _current:=New Renderer
+		Global _current:Renderer
+		
+		If Not _current
+			Select App.GetConfig( "mojo3d_renderer","" )
+			Case "deferred"
+				_current=New DeferredRenderer
+			Case "forward"
+				_current=New ForwardRenderer( False )
+			Default
+#If __DESKTOP_TARGET__					
+				If glexts.GL_draw_buffers
+					_current=New DeferredRenderer
+				Else
+					_current=New ForwardRenderer( True )
+				Endif
+#Endif
+			End
+			If Not _current _current=New ForwardRenderer( False )
+		Endif
 		
 		Return _current
 	End
 	
+	Internal
+
 	#rem monkeydoc @hidden
 	#end
 	Method Render( scene:Scene,camera:Camera,device:GraphicsDevice )
+
+		'***** validate stuff *****
+			
+		Local size:=device.Viewport.Size
+		size.x=Max( size.x,1920 )
+		size.y=Max( size.y,1080 )
 		
-		_renderTarget=device.RenderTarget
-		_renderTargetSize=device.RenderTargetSize
-		_renderViewport=device.Viewport
+		OnValidateSize( size )
+		
+		ValidateCSM()
+
+		_runiforms.SetFloat( "Time",Now() )
+
+		_runiforms.SetTexture( "ShadowTexture",_csmTexture )
+		_runiforms.SetVec4f( "ShadowSplits",New Vec4f( _csmSplits[1],_csmSplits[2],_csmSplits[3],_csmSplits[4] ) )
 		
-		ValidateSize( _renderViewport.Size )
+		'***** Set render scene *****
 		
 		_renderScene=scene
 
-		_runiforms.SetFloat( "Time",Now() )
 		_runiforms.SetTexture( "SkyTexture",_renderScene.SkyTexture )
 		
 		_runiforms.SetVec4f( "ClearColor",_renderScene.ClearColor )
 		_runiforms.SetVec4f( "AmbientDiffuse",_renderScene.AmbientLight )
 	
-		_runiforms.SetTexture( "ShadowTexture",_csmTexture )
-		_runiforms.SetVec4f( "ShadowSplits",New Vec4f( _csmSplits[1],_csmSplits[2],_csmSplits[3],_csmSplits[4] ) )
-		
 		Local env:Texture
 		
 		If _renderScene.SkyTexture
@@ -235,6 +119,8 @@ Class Renderer
 			
 			model.OnRender( _renderQueue )
 		Next
+		
+		'***** Set render camera *****
 
 		_renderCamera=camera
 
@@ -253,133 +139,67 @@ Class Renderer
 		
 		_spriteBuffer.AddSprites( _spriteQueue,_renderScene.Sprites,_renderCamera )
 		
-		OnRender()
+		OnRender( scene,camera,device )
 		
 		_renderCamera=Null
 		
 		_renderScene=null
 	End
 	
-	'***** INTERNAL *****
-	
 	Protected
 	
-	Field _device:GraphicsDevice
-	Field _runiforms:UniformBlock
-	Field _iuniforms:UniformBlock
-	
-	Field _csmSize:=4096
-	Field _csmSplits:=New Float[]( 1,20,60,180,1000 )
-	Field _csmTexture:Texture
-	Field _csmTarget:RenderTarget
-	Field _quadVertices:VertexBuffer
-	Field _skyboxShader:Shader
-	Field _plightShader:Shader
-	Field _dlightShader:Shader
-	Field _copyShader:Shader
-
-	Field _defaultEnv:Texture
-	
-	Field _hdrTexture:Texture		'contains output linear HDR color
-	Field _colorTexture:Texture		'contains surface color/M
-	Field _normalTexture:Texture	'contains surface normal/R
-	Field _depthTexture:Texture		'contains surface depth
-	Field _rpass0Target:RenderTarget
-	Field _rpass2Target:RenderTarget
-	
-	Field _renderQueue:=New RenderQueue
-	Field _spriteQueue:=New RenderQueue
-	Field _spriteBuffer:=New SpriteBuffer
-	
-	Field _nullBones:=New Mat4f[96]
+	Method OnValidateSize( size:Vec2i ) Virtual
+	End
 	
-	Field _renderTarget:RenderTarget
-	Field _renderTargetSize:Vec2i
-	Field _renderViewport:Recti
-	Field _renderScene:Scene
-	Field _renderCamera:Camera
-	Field _renderLight:Light
+	Method OnRender( scene:Scene,camera:Camera,device:GraphicsDevice ) Virtual
+	End
 
-	Method ValidateSize( size:Vec2i )
+	Method New( shaderDefs:String )
 		
-		size.x=Max( size.x,1920 )
-		size.y=Max( size.y,1080 )
+		_shaderDefs=shaderDefs
 		
-		If Not _hdrTexture Or size.x>_hdrTexture.Size.x Or size.y>_hdrTexture.Size.y
+		_device=New GraphicsDevice( 0,0 )
 		
-			SafeDiscard( _hdrTexture )
-			SafeDiscard( _colorTexture )
-			SafeDiscard( _normalTexture )
-			SafeDiscard( _depthTexture )
-			SafeDiscard( _rpass0Target )
-			SafeDiscard( _rpass2Target )
-	
-			Const format:=PixelFormat.RGBA32F		'32 bit float
-			
-			_hdrTexture=New Texture( size.x,size.y,format,TextureFlags.Filter|TextureFlags.Dynamic )		'output hdr image
-			_colorTexture=New Texture( size.x,size.y,format,TextureFlags.Filter|TextureFlags.Dynamic )		'metalness in 'a'
-			_normalTexture=New Texture( size.x,size.y,format,TextureFlags.Filter|TextureFlags.Dynamic )		'roughness in 'a'
-			_depthTexture=New Texture( size.x,size.y,PixelFormat.Depth32F,TextureFlags.Dynamic )
-			
-			_rpass0Target=New RenderTarget( New Texture[]( _hdrTexture,_colorTexture,_normalTexture ),_depthTexture )
-			_rpass2Target=New RenderTarget( New Texture[]( _hdrTexture ),Null )
-			
-			_runiforms.SetTexture( "ColorBuffer",_colorTexture )
-			_runiforms.SetTexture( "NormalBuffer",_normalTexture )
-			_runiforms.SetTexture( "DepthBuffer",_depthTexture )
+		_runiforms=New UniformBlock( 1 )
+		_iuniforms=New UniformBlock( 2 )
 		
-		Endif
+		_device.BindUniformBlock( _runiforms )
+		_device.BindUniformBlock( _iuniforms )
 
-		If Not _csmTexture Or _csmSize<>_csmTexture.Size.x
-			
-			SafeDiscard( _csmTexture )
-			SafeDiscard( _csmTarget )
-			
-			_csmTexture=New Texture( _csmSize,_csmSize,PixelFormat.Depth32F,TextureFlags.Dynamic )
-			_csmTarget=New RenderTarget( Null,_csmTexture )
-			
-		Endif
-		
-	End
+		_csmSplits=New Float[]( 1,20,60,180,1000 )
 
-	Method OnRender()
+		_defaultEnv=Texture.Load( "asset::textures/env_default.jpg",TextureFlags.FilterMipmap|TextureFlags.Cubemap )
 		
-		_device.RenderTarget=_rpass0Target
-		_device.Viewport=New Recti( 0,0,_renderViewport.Size )
-		_device.Scissor=_device.Viewport
+		_skyboxShader=Shader.Open( "skybox",_shaderDefs )
 
-		RenderBackground()
-		
-		RenderAmbient()
+	End
 
-		_device.RenderTarget=_rpass2Target
-		
-		_runiforms.SetVec2f( "BufferCoordScale",Cast<Vec2f>( _renderViewport.Size )/Cast<Vec2f>( _hdrTexture.Size ) )
-		
-		For Local light:=Eachin _renderScene.Lights
-			
-			If light.Type=LightType.Point Continue
+	Property Device:GraphicsDevice()
+	
+		Return _device
+	End
+	
+	Property RenderUniforms:UniformBlock()
+	
+		Return _runiforms
+	End
+	
+	Method RenderQuad()
 
-			_renderLight=light
-			
-			RenderCSMShadows()
+		Global _vertices:VertexBuffer
+	
+		If Not _vertices
+			_vertices=New VertexBuffer( New Vertex3f[](
+			New Vertex3f( 0,1,0 ),
+			New Vertex3f( 1,1,0 ),
+			New Vertex3f( 1,0,0 ),
+			New Vertex3f( 0,0,0 ) ) )
+		Endif
 			
-			RenderLight()
-		Next
-		
-		_renderLight=null
-		
-		_device.RenderTarget=_rpass0Target
-		
-		RenderSprites()
-
-		_device.RenderTarget=_rpass2Target
-
-		RenderEffects()
-		
-		RenderCopy()
+		_device.VertexBuffer=_vertices
+		_device.Render( 4,1 )
 	End
-	
+
 	Method RenderBackground()
 	
 		If _renderScene.SkyTexture
@@ -394,11 +214,10 @@ Class Renderer
 			_device.DepthFunc=DepthFunc.Always
 			_device.BlendMode=BlendMode.Opaque
 			_device.CullMode=CullMode.None
+			_device.Shader=_skyboxShader
 			_device.RenderPass=0
 			
-			_device.VertexBuffer=_quadVertices
-			_device.Shader=_skyboxShader
-			_device.Render( 4,1 )
+			RenderQuad()
 			
 		Else
 			_device.ColorMask=ColorMask.All
@@ -410,17 +229,40 @@ Class Renderer
 		
 	End
 	
+	Method RenderOpaqueOps()
+
+		RenderRenderOps( _renderQueue.OpaqueOps,_renderCamera.InverseMatrix,_renderCamera.ProjectionMatrix )
+	End
+
+	Method RenderSpriteOps()
+
+		RenderRenderOps( _spriteQueue.TransparentOps,_renderCamera.InverseMatrix,_renderCamera.ProjectionMatrix )
+	End
+	
+	#rem
 	Method RenderAmbient()
 		
 		_device.ColorMask=ColorMask.All
 		_device.DepthMask=True
 		_device.DepthFunc=DepthFunc.LessEqual
+		_device.BlendMode=BlendMode.Opaque
 		_device.RenderPass=1
-		
+
 		RenderRenderOps( _renderQueue.OpaqueOps,_renderCamera.InverseMatrix,_renderCamera.ProjectionMatrix )
 	End
 	
-	Method RenderCSMShadows()
+	Method RenderSprites()
+
+		_device.ColorMask=ColorMask.All
+		_device.DepthMask=False
+		_device.DepthFunc=DepthFunc.LessEqual
+		_device.RenderPass=0
+
+		RenderRenderOps( _spriteQueue.TransparentOps,_renderCamera.InverseMatrix,_renderCamera.ProjectionMatrix )
+	End
+	#end
+	
+	Method RenderCSMShadows( light:Light )
 	
 		'Perhaps use a different device for CSM...?
 		'
@@ -438,9 +280,9 @@ Class Renderer
 		_device.DepthFunc=DepthFunc.LessEqual
 		_device.BlendMode=BlendMode.Opaque
 		_device.CullMode=CullMode.Back
-		_device.RenderPass=2
+		_device.RenderPass=4
 
-		Local invLightMatrix:=_renderLight.InverseMatrix
+		Local invLightMatrix:=light.InverseMatrix
 		Local viewLight:=invLightMatrix * _renderCamera.Matrix
 		
 		For Local i:=0 Until _csmSplits.Length-1
@@ -483,7 +325,7 @@ Class Renderer
 			
 			_device.Scissor=_device.Viewport
 				
-			If _renderLight.ShadowsEnabled
+			If light.ShadowsEnabled
 				RenderRenderOps( _renderQueue.ShadowOps,invLightMatrix,lightProj )
 			Endif
 			
@@ -493,96 +335,44 @@ Class Renderer
 		_device.Viewport=t_viewport
 		_device.Scissor=t_scissor
 	End
+
+	Private
 	
-	Method RenderLight()
+	Field _shaderDefs:String
 	
-		_runiforms.SetVec4f( "LightColor",_renderLight.Color )
-		_runiforms.SetFloat( "LightRange",_renderLight.Range )
-		_runiforms.SetMat4f( "LightViewMatrix",_renderCamera.InverseMatrix * _renderLight.Matrix )
-		
-		_runiforms.SetMat4f( "InverseProjectionMatrix",-_renderCamera.ProjectionMatrix )
-		
-		_device.ColorMask=ColorMask.All
-		_device.DepthMask=False
-		_device.DepthFunc=DepthFunc.Always
-		_device.BlendMode=BlendMode.Additive
-		_device.CullMode=CullMode.None
-		_device.RenderPass=3
-		
-		Select _renderLight.Type
-		Case LightType.Directional
-		
-			_device.Shader=_dlightShader
-			_device.VertexBuffer=_quadVertices
-			_device.Render( 4,1,0 )
-		
-		Case LightType.Point
-
-			_device.Shader=_plightShader
-			_device.VertexBuffer=_quadVertices
-			_device.Render( 4,1,0 )
-		End
-
-	End
-
-	Method RenderSprites()
+	Field _device:GraphicsDevice
+	Field _runiforms:UniformBlock
+	Field _iuniforms:UniformBlock
 	
-		_device.ColorMask=ColorMask.All
-		_device.DepthMask=False
-		_device.DepthFunc=DepthFunc.LessEqual
-		_device.RenderPass=0
+	Field _csmSize:=4096
+	Field _csmSplits:=New Float[]( 1,20,60,180,1000 )
+	Field _csmTexture:Texture
+	Field _csmTarget:RenderTarget
+	Field _skyboxShader:Shader
 
-		RenderRenderOps( _spriteQueue.TransparentOps,_renderCamera.InverseMatrix,_renderCamera.ProjectionMatrix )
-	End
+	Field _defaultEnv:Texture
 	
-	Method RenderEffects()
-		
-		_device.ColorMask=ColorMask.All
-		_device.DepthMask=False
-		_device.DepthFunc=DepthFunc.Always
-		_device.CullMode=CullMode.None
-
-		_device.VertexBuffer=_quadVertices
+	Field _renderQueue:=New RenderQueue
+	Field _spriteQueue:=New RenderQueue
+	Field _spriteBuffer:=New SpriteBuffer
+	
+	Field _renderScene:Scene
+	Field _renderCamera:Camera
+	
+	Method ValidateCSM()
 		
-		For Local effect:=Eachin _renderScene.PostEffects
+		If Not _csmTexture Or _csmSize<>_csmTexture.Size.x
 			
-			If Not effect.Enabled Continue
+			SafeDiscard( _csmTexture )
+			SafeDiscard( _csmTarget )
 			
-			_device.BlendMode=BlendMode.Opaque
-			_device.RenderPass=0
+			_csmTexture=New Texture( _csmSize,_csmSize,PixelFormat.Depth32F,TextureFlags.Dynamic )
+			_csmTarget=New RenderTarget( Null,_csmTexture )
 			
-			effect.Render( _device )
-		Next
+		Endif
 		
 	End
-	
-	Method RenderCopy()
-		
-		Local source:=_device.RenderTarget.GetColorTexture( 0 )
-		
-		_runiforms.SetTexture( "SourceTexture",source )
-		_runiforms.SetVec2f( "SourceCoordScale",Cast<Vec2f>( _renderViewport.Size )/Cast<Vec2f>( source.Size ) )
 
-		_device.RenderTarget=_renderTarget
-		_device.Resize( _renderTargetSize )
-		_device.Viewport=_renderViewport
-		_device.Scissor=_device.Viewport
-		_device.ColorMask=ColorMask.All
-		_device.DepthMask=False
-		_device.DepthFunc=DepthFunc.Always
-		_device.BlendMode=BlendMode.Opaque
-		_device.CullMode=CullMode.None
-		_device.RenderPass=0
-		
-		_device.VertexBuffer=_quadVertices
-		_device.Shader=_copyShader
-		
-		_device.Render( 4,1 )
-		
-		_device.RenderTarget=Null
-		_device.Resize( Null )
-	End
-	
 	Method RenderRenderOps( ops:Stack<RenderOp>,viewMatrix:AffineMat4f,projMatrix:Mat4f )
 		
 		_runiforms.SetMat4f( "ViewMatrix",viewMatrix )
@@ -616,7 +406,7 @@ Class Renderer
 				
 				_device.Shader=material.Shader
 				_device.BindUniformBlock( material.Uniforms )
-				_device.BlendMode=material.BlendMode
+				If material.BlendMode<>BlendMode.Opaque _device.BlendMode=material.BlendMode
 				_device.CullMode=material.CullMode
 				
 			Endif

+ 109 - 0
modules/mojo3d/graphics/renderqueue.monkey2

@@ -0,0 +1,109 @@
+
+Namespace mojo3d.graphics
+
+#rem monkeydoc @hidden
+#end
+Class RenderOp
+	Field material:Material
+	Field vbuffer:VertexBuffer
+	Field ibuffer:IndexBuffer
+	Field instance:Entity
+	Field bones:Mat4f[]
+	Field order:Int
+	Field count:Int
+	Field first:Int
+End
+
+#rem monkeydoc @hidden
+#end
+Class RenderQueue
+	
+	Property OpaqueOps:Stack<RenderOp>()
+		
+		Return _opaqueOps
+	End
+	
+	Property TransparentOps:Stack<RenderOp>()
+	
+		Return _transparentOps
+	End
+	
+	Property ShadowOps:Stack<RenderOp>()
+		
+		Return _shadowOps
+	End
+	
+	Property AddShadowOps:Bool()
+		
+		Return _addShadowOps
+		
+	Setter( addShadowOps:Bool )
+		
+		_addShadowOps=addShadowOps
+	End
+	
+	Method Clear()
+		
+		_opaqueOps.Clear()
+		_shadowOps.Clear()
+		_transparentOps.Clear()
+	End
+	
+	Method AddRenderOp( op:RenderOp )
+		
+		If op.material.BlendMode<>BlendMode.Opaque
+			_transparentOps.Push( op )
+		Else
+			_opaqueOps.Push( op )
+		Endif
+		
+		If _addShadowOps 
+			If (op.material.Shader.RenderPassMask & 16) _shadowOps.Push( op )
+		Endif
+		
+	End
+	
+	Method AddRenderOp( material:Material,vbuffer:VertexBuffer,ibuffer:IndexBuffer,order:Int,count:Int,first:Int )
+		Local op:=New RenderOp
+		op.material=material
+		op.vbuffer=vbuffer
+		op.ibuffer=ibuffer
+		op.order=order
+		op.count=count
+		op.first=first
+		AddRenderOp( op )
+	End
+	
+	Method AddRenderOp( material:Material,vbuffer:VertexBuffer,ibuffer:IndexBuffer,instance:Entity,order:Int,count:Int,first:Int )
+		Local op:=New RenderOp
+		op.material=material
+		op.vbuffer=vbuffer
+		op.ibuffer=ibuffer
+		op.instance=instance
+		op.order=order
+		op.count=count
+		op.first=first
+		AddRenderOp( op )
+	End
+	
+	Method AddRenderOp( material:Material,vbuffer:VertexBuffer,ibuffer:IndexBuffer,instance:Entity,bones:Mat4f[],order:Int,count:Int,first:Int )
+		Local op:=New RenderOp
+		op.material=material
+		op.vbuffer=vbuffer
+		op.ibuffer=ibuffer
+		op.instance=instance
+		op.bones=bones
+		op.order=order
+		op.count=count
+		op.first=first
+		AddRenderOp( op )
+	End
+	
+	Private
+	
+	Field _opaqueOps:=New Stack<RenderOp>
+	Field _transparentOps:=New Stack<RenderOp>
+	Field _shadowOps:=New Stack<RenderOp>
+	
+	Field _addShadowOps:Bool
+End

+ 14 - 1
modules/mojo3d/graphics/scene.monkey2

@@ -86,8 +86,21 @@ Class Scene
 		_postEffects.Add( postEffect )
 	End
 	
-	#rem monkeydoc 	Destroys all entities in the scene.
+	#rem monkeydoc Removes a post effect from the scene
+	#end
+	Method RemovePostEffect( postEffect:PostEffect )
+		
+		_postEffects.Remove( postEffect )
+	End
+	
+	#rem monkeydocs Get all post effect that have been added to the scene
+	#end
+	Method GetPostEffects:PostEffect[]()
+		
+		Return _postEffects.ToArray()
+	End
 	
+	#rem monkeydoc Destroys all entities in the scene.
 	#end
 	Method DestroyAllEntities()
 		

+ 0 - 0
modules/mojo3d/graphics/shaders/bloom.glsl → modules/mojo3d/graphics/shaders/effect-bloom.glsl


+ 0 - 0
modules/mojo3d/graphics/shaders/fog.glsl → modules/mojo3d/graphics/shaders/effect-fog.glsl


+ 0 - 0
modules/mojo3d/graphics/shaders/monochrome.glsl → modules/mojo3d/graphics/shaders/effect-monochrome.glsl


+ 0 - 0
modules/mojo3d/graphics/shaders/directional-light.glsl → modules/mojo3d/graphics/shaders/light-directional-deferred.glsl


+ 0 - 0
modules/mojo3d/graphics/shaders/point-light.glsl → modules/mojo3d/graphics/shaders/light-point-deferred.glsl


+ 4 - 5
modules/mojo3d/graphics/shaders/material.glsl → modules/mojo3d/graphics/shaders/material-pbr-deferred.glsl

@@ -1,9 +1,8 @@
 
-//@renderpasses 1,2,3
+//@renderpasses 1,4
 
 #define MX2_AMBIENTPASS (MX2_RENDERPASS==1)
-#define MX2_CASTSHADOWPASS (MX2_RENDERPASS==2)
-#define MX2_TRANSPARENTPASS (MX2_RENDERPASS==3)
+#define MX2_CASTSHADOWPASS (MX2_RENDERPASS==4)
  
 //material uniforms
 
@@ -223,7 +222,7 @@ void main(){
 	vec3 normal=texture2D( m_NormalTexture,v_TexCoord0 ).xyz * 2.0 - 1.0;
 	normal=normalize( v_TanMatrix * normal );
 #else
-	vec3 normal=v_Normal;
+	vec3 normal=normalize( v_Normal );
 #endif
 	
 #else
@@ -233,7 +232,7 @@ void main(){
 	float metalness=m_MetalnessFactor;
 	float roughness=m_RoughnessFactor;
 	float occlusion=1.0;
-	vec3 normal=v_Normal;
+	vec3 normal=normalize( v_Normal );
 
 #endif
 

+ 330 - 0
modules/mojo3d/graphics/shaders/material-pbr-forward.glsl

@@ -0,0 +1,330 @@
+
+//@renderpasses 1,2,3,4
+
+#define MX2_COLORPASS (MX2_RENDERPASS&3)
+#define MX2_AMBIENTPASS (MX2_RENDERPASS&1)
+#define MX2_LIGHTINGPASS (MX2_RENDERPASS&2)
+ 
+//instance uniforms
+//
+uniform mat4 i_ModelViewMatrix;
+uniform mat4 i_ModelViewProjectionMatrix;
+uniform mat3 i_ModelViewNormalMatrix;
+
+#if defined( MX2_BONED )
+
+uniform mat4 i_ModelBoneMatrices[96];
+
+#endif
+
+//material uniforms
+
+#if MX2_COLORPASS && defined( MX2_TEXTURED )
+
+uniform mat3 m_TextureMatrix;
+
+#endif
+
+#if MX2_AMBIENTPASS
+
+//renderer uniforms
+//
+uniform vec4 r_AmbientDiffuse;
+uniform samplerCube r_EnvTexture;
+uniform mat3 r_EnvMatrix;
+
+#endif
+
+#if MX2_LIGHTINGPASS
+
+uniform sampler2D r_ShadowTexture;
+uniform mat4 r_ShadowMatrix0;
+uniform mat4 r_ShadowMatrix1;
+uniform mat4 r_ShadowMatrix2;
+uniform mat4 r_ShadowMatrix3;
+uniform vec4 r_ShadowSplits;
+
+uniform mat4 r_LightViewMatrix;
+uniform vec4 r_LightColor;
+uniform float r_LightRange;
+
+#endif
+
+//pbr varyings...
+//
+varying vec3 v_Position;
+varying vec3 v_Normal;
+#if MX2_COLORPASS && defined( MX2_TEXTURED )
+varying vec2 v_TexCoord0;
+#if defined( MX2_BUMPMAPPED )
+varying mat3 v_TanMatrix;
+#endif
+#endif
+
+//@vertex
+
+attribute vec4 a_Position;
+
+#if MX2_COLORPASS
+attribute vec3 a_Normal;
+#if defined( MX2_TEXTURED )
+attribute vec2 a_TexCoord0;
+#if defined( MX2_BUMPMAPPED )
+attribute vec4 a_Tangent;
+#endif
+#endif
+#endif
+	
+#if defined( MX2_BONED )
+
+attribute vec4 a_Weights;
+attribute vec4 a_Bones;
+
+void main(){
+
+	mat4 m0=i_ModelBoneMatrices[ int( a_Bones.x ) ];
+	mat4 m1=i_ModelBoneMatrices[ int( a_Bones.y ) ];
+	mat4 m2=i_ModelBoneMatrices[ int( a_Bones.z ) ];
+	mat4 m3=i_ModelBoneMatrices[ int( a_Bones.a ) ];
+	
+	vec4 b_Position=
+		m0 * a_Position * a_Weights.x +
+		m1 * a_Position * a_Weights.y +
+		m2 * a_Position * a_Weights.z +
+		m3 * a_Position * a_Weights.a;
+		
+#if MX2_COLORPASS
+
+	mat3 n0=mat3( m0[0].xyz,m0[1].xyz,m0[2].xyz );
+	mat3 n1=mat3( m1[0].xyz,m1[1].xyz,m1[2].xyz );
+	mat3 n2=mat3( m2[0].xyz,m2[1].xyz,m2[2].xyz );
+	mat3 n3=mat3( m3[0].xyz,m3[1].xyz,m3[2].xyz );
+
+	vec3 b_Normal=normalize( 
+		n0 * a_Normal * a_Weights.x +
+		n1 * a_Normal * a_Weights.y +
+		n2 * a_Normal * a_Weights.z +
+		n3 * a_Normal * a_Weights.a );
+		
+#if defined( MX2_BUMPMAPPED )
+	vec4 b_Tangent=vec4( normalize( 
+		n0 * a_Tangent.xyz * a_Weights.x +
+		n1 * a_Tangent.xyz * a_Weights.y +
+		n2 * a_Tangent.xyz * a_Weights.z +
+		n3 * a_Tangent.xyz * a_Weights.a ),a_Tangent.w );
+#endif
+
+	// view space position
+	v_Position=( i_ModelViewMatrix * b_Position ).xyz;
+
+	// viewspace normal
+	v_Normal=i_ModelViewNormalMatrix * b_Normal;
+	
+#if MX2_COLORPASS && defined( MX2_TEXTURED )
+	// texture coord0
+	v_TexCoord0=(m_TextureMatrix * vec3(a_TexCoord0,1.0)).st;
+#if defined( MX2_BUMPMAPPED )
+	// viewspace tangent matrix
+	v_TanMatrix[2]=v_Normal;
+	v_TanMatrix[0]=i_ModelViewNormalMatrix * b_Tangent.xyz;
+	v_TanMatrix[1]=cross( v_TanMatrix[0],v_TanMatrix[2] ) * b_Tangent.a;
+#endif
+#endif
+	
+#endif	//MX2_COLORPASS
+	
+	gl_Position=i_ModelViewProjectionMatrix * b_Position;
+}
+
+#else	//MX2_BONED
+
+void main(){
+
+	// view space position
+	v_Position=( i_ModelViewMatrix * a_Position ).xyz;
+
+#if MX2_COLORPASS
+
+	// viewspace normal
+	v_Normal=i_ModelViewNormalMatrix * a_Normal;
+	
+#if defined( MX2_TEXTURED )
+	// texture coord0
+	v_TexCoord0=(m_TextureMatrix * vec3(a_TexCoord0,1.0)).st;
+#if defined( MX2_BUMPMAPPED )
+	// viewspace tangent matrix
+	v_TanMatrix[2]=v_Normal;
+	v_TanMatrix[0]=i_ModelViewNormalMatrix * a_Tangent.xyz;
+	v_TanMatrix[1]=cross( v_TanMatrix[0],v_TanMatrix[2] ) * a_Tangent.a;
+#endif
+#endif
+
+#endif	//MX2_COLORPASS
+	
+	gl_Position=i_ModelViewProjectionMatrix * a_Position;
+}
+
+#endif	//MX2_BONED
+
+//@fragment
+
+#if MX2_LIGHTINGPASS
+
+float shadow_color( vec3 normal ){
+
+	vec4 vpos=vec4( v_Position + normal * .05,1.0 );
+//	vec4 vpos=vec4( v_Position,1.0 );
+	vec4 lpos;
+	vec2 off;
+	
+	if( vpos.z<r_ShadowSplits.x ){
+		lpos=r_ShadowMatrix0 * vpos;
+		off=vec2( 0.0,0.0 );
+	}else if( vpos.z<r_ShadowSplits.y ){
+		lpos=r_ShadowMatrix1 * vpos;
+		off=vec2( 0.5,0.0 );
+	}else if( vpos.z<r_ShadowSplits.z ){
+		lpos=r_ShadowMatrix2 * vpos;
+		off=vec2( 0.0,0.5 );
+	}else{
+		lpos=r_ShadowMatrix3 * vpos;
+		off=vec2( 0.5,0.5 );
+	}
+	
+	vec3 spos=lpos.xyz/lpos.w * vec3( 0.25,0.25,0.5 ) + vec3( 0.25,0.25,0.5 );
+
+//	spos.z*=0.999;
+	
+	float d=texture2D( r_ShadowTexture,spos.xy+off ).r;
+	
+	if( spos.z>d ) return 0.0;
+	
+	return 1.0;
+}
+
+#endif
+
+#if MX2_COLORPASS
+
+vec3 pbr_linear_frag_color( vec3 color,vec3 emissive,float metalness,float roughness,float occlusion,vec3 normal ){
+
+	float glosiness=1.0-roughness;
+	vec3 color0=vec3( 0.04,0.04,0.04 );
+	vec3 diffuse=color * (1.0-metalness);
+	vec3 specular=(color-color0) * metalness + color0;
+	vec3 vvec=normalize( -v_Position );
+	
+	vec3 frag_color=vec3( 0.0 );
+
+#if MX2_AMBIENTPASS
+	
+	//ambient color
+	
+	vec3 rvec=r_EnvMatrix * reflect( v_Position,normal );
+	float lod=textureCube( r_EnvTexture,rvec,10.0 ).a * 255.0 - 10.0;
+	if( lod>0.0 ) lod=textureCube( r_EnvTexture,rvec ).a * 255.0;
+	vec3 ambenv=pow( textureCube( r_EnvTexture,rvec,max( roughness*10.0-lod,0.0 ) ).rgb,vec3( 2.2 ) );
+	
+	float ndotv=max( dot( normal,vvec ),0.0 );
+
+	vec3 fschlick1=specular + (1.0-specular) * pow( 1.0-ndotv,5.0 ) * glosiness;
+
+	vec3 ambdiff=diffuse * r_AmbientDiffuse.rgb;
+	vec3 ambspec=ambenv * fschlick1;
+	frag_color+=(ambdiff+ambspec) * occlusion + emissive;
+
+#endif
+
+#if MX2_LIGHTINGPASS
+
+	//lighting color
+	
+	float spow=pow( 2.0,glosiness * 12.0 );				//specular power
+	float fnorm=(spow+2.0)/8.0;							//normalization factor
+	
+	vec3 lvec=normalize( -r_LightViewMatrix[2].xyz );	//vector to light
+	vec3 hvec=normalize( lvec+vvec );					//halfway vector
+
+	float hdotl=max( dot( hvec,lvec ),0.0 );
+	
+	vec3 fschlick2=specular + (1.0-specular) * pow( 1.0-hdotl,5.0 ) * glosiness;
+
+	float ndotl=max( dot( normal,lvec ),0.0 );
+	float ndoth=max( dot( normal,hvec ),0.0 );
+	
+	vec3 lightspec=pow( ndoth,spow ) * fschlick2 * fnorm;
+	
+	vec3 light=(diffuse+lightspec) * r_LightColor.rgb * ndotl;
+
+	float shadow=shadow_color( normal );
+
+	frag_color+=light*shadow;
+	
+#endif
+
+	return frag_color;
+}
+
+#endif
+
+#if MX2_COLORPASS
+ 
+#if defined( MX2_TEXTURED)
+uniform sampler2D m_ColorTexture;
+uniform sampler2D m_EmissiveTexture;
+uniform sampler2D m_MetalnessTexture;
+uniform sampler2D m_RoughnessTexture;
+uniform sampler2D m_OcclusionTexture;
+uniform sampler2D m_NormalTexture;
+#endif
+
+uniform vec4 m_ColorFactor;
+uniform vec4 m_EmissiveFactor;
+uniform float m_MetalnessFactor;
+uniform float m_RoughnessFactor;
+
+void main(){
+
+#if defined( MX2_TEXTURED )
+	vec3 color=pow( texture2D( m_ColorTexture,v_TexCoord0 ).rgb,vec3( 2.2 ) ) * m_ColorFactor.rgb;
+	vec3 emissive=pow( texture2D( m_EmissiveTexture,v_TexCoord0 ).rgb,vec3( 2.2 ) ) * m_EmissiveFactor.rgb;
+	float metalness=texture2D( m_MetalnessTexture,v_TexCoord0 ).b * m_MetalnessFactor;
+	float roughness=texture2D( m_RoughnessTexture,v_TexCoord0 ).g * m_RoughnessFactor;
+	float occlusion=texture2D( m_OcclusionTexture,v_TexCoord0 ).r;
+	
+#if defined( MX2_BUMPMAPPED )
+	vec3 normal=texture2D( m_NormalTexture,v_TexCoord0 ).xyz * 2.0 - 1.0;
+	normal=normalize( v_TanMatrix * normal );
+#else
+	vec3 normal=normalize( v_Normal );
+#endif
+	
+#else
+	vec3 color=m_ColorFactor.rgb;
+	vec3 emissive=m_EmissiveFactor.rgb;
+	float metalness=m_MetalnessFactor;
+	float roughness=m_RoughnessFactor;
+	float occlusion=1.0;
+	vec3 normal=normalize( v_Normal );
+#endif
+
+	vec3 frag_color=pbr_linear_frag_color( color,emissive,metalness,roughness,occlusion,normal );
+	
+#if defined( MX2_SRGBOUTPUT )
+	gl_FragColor=vec4( pow( frag_color,vec3( 1.0/2.2 ) ),1.0 );
+#else
+	gl_FragColor=vec4( frag_color,1.0 );
+#endif
+}
+
+#else	//MX2_COLORPASS
+
+void main(){
+
+	gl_FragColor=vec4( vec3( gl_FragCoord.z ),1.0 );
+
+}
+
+#endif	//MX2_COLORPASS
+
+

+ 4 - 0
modules/mojo3d/graphics/shaders/sprite3d.glsl → modules/mojo3d/graphics/shaders/material-sprite.glsl

@@ -37,5 +37,9 @@ void main(){
 	
 	float alpha=texture2D( m_ColorTexture,v_TexCoord0 ).a * m_ColorFactor.a;
 	
+#if defined( MX2_SRGBOUTPUT )
+	gl_FragColor=vec4( pow( color,vec3( 1.0/2.2 ) ),alpha );
+#else
 	gl_FragColor=vec4( color,alpha );
+#endif
 }

+ 1 - 29
modules/mojo3d/graphics/shaders/water.glsl → modules/mojo3d/graphics/shaders/material-water.glsl

@@ -1,5 +1,5 @@
 
-//@renderpasses 1,2
+//@renderpasses 1
 
 //material uniforms
 
@@ -11,8 +11,6 @@ uniform mat4 i_ModelViewMatrix;
 uniform mat4 i_ModelViewProjectionMatrix;
 uniform mat3 i_ModelViewNormalMatrix;
 
-#if MX2_RENDERPASS==1
-
 uniform vec4 r_AmbientDiffuse;
 uniform samplerCube r_EnvTexture;
 uniform mat3 r_EnvMatrix;
@@ -24,26 +22,18 @@ varying vec2 v_TexCoord0;
 varying vec3 v_Normal;
 varying mat3 v_TanMatrix;
 
-#endif
-
 //@vertex
 
 //vertex attribs....
 
 attribute vec4 a_Position;
 
-#if MX2_RENDERPASS==1 
-
 attribute vec2 a_TexCoord0;
 attribute vec3 a_Normal;
 attribute vec4 a_Tangent;
 
-#endif
-
 void main(){
 
-#if MX2_RENDERPASS==1
-
 	// texture coord0
 	v_TexCoord0=(m_TextureMatrix * vec3(a_TexCoord0,1.0)).st;
 
@@ -58,15 +48,11 @@ void main(){
 	v_TanMatrix[0]=i_ModelViewNormalMatrix * a_Tangent.xyz;
 	v_TanMatrix[1]=cross( v_TanMatrix[0],v_TanMatrix[2] ) * a_Tangent.a;
 	
-#endif
-	
 	gl_Position=i_ModelViewProjectionMatrix * a_Position;
 }
 
 //@fragment
 
-#if MX2_RENDERPASS==1
-
 void main0( vec3 color,vec3 emissive,float metalness,float roughness,float occlusion,vec3 normal ){
 
 	normal=normalize( v_TanMatrix * normal );
@@ -102,10 +88,6 @@ void main0( vec3 color,vec3 emissive,float metalness,float roughness,float occlu
 	gl_FragData[2]=vec4( normal * 0.5 + 0.5,roughness );
 }
 
-#endif
-
-#if MX2_RENDERPASS==1
-
 uniform float r_Time;
 
 uniform sampler2D m_ColorTexture;
@@ -120,12 +102,8 @@ uniform sampler2D m_NormalTexture1;
 uniform vec2 m_Velocity0;
 uniform vec2 m_Velocity1;
 
-#endif
-
 void main(){
 
-#if MX2_RENDERPASS==1
-
 	vec3 color=pow( texture2D( m_ColorTexture,v_TexCoord0 ).rgb,vec3( 2.2 ) ) * m_ColorFactor.rgb;
 
 	vec3 normal0=texture2D( m_NormalTexture0,v_TexCoord0 + m_Velocity0 * r_Time ).xyz * 2.0 - 1.0;
@@ -143,11 +121,5 @@ void main(){
 	float occlusion=1.0;
 
 	main0( color,emissive,metalness,roughness,occlusion,normal );
-	
-#else
-
-	gl_FragColor=vec4( vec3( gl_FragCoord.z ),1.0 );
-
-#endif
 
 }

+ 7 - 1
modules/mojo3d/graphics/shaders/skybox.glsl

@@ -28,5 +28,11 @@ void main(){
 
 	vec3 tv=r_EnvMatrix * (clip.xyz/clip.w);
 	
-	gl_FragColor=vec4( pow( textureCube( r_SkyTexture,tv ).rgb,vec3( 2.2 ) ),1.0 );
+	vec3 color=textureCube( r_SkyTexture,tv ).rgb;
+	
+#if !defined( MX2_SRGBOUTPUT )
+	gl_FragColor=vec4( pow( color,vec3( 2.2 ) ),1.0 );
+#else
+	gl_FragColor=vec4( color,1.0 );
+#endif
 }

+ 4 - 1
modules/mojo3d/graphics/spritematerial.monkey2

@@ -8,7 +8,10 @@ Class SpriteMaterial Extends Material
 	#rem monkeydoc Creates a new sprite material.
 	#end	
 	Method New()
-		Super.New( Shader.Open( "sprite3d" ) )
+		
+		Local shader:="material-sprite",defs:=Renderer.GetCurrent().ShaderDefs
+			
+		SetShader( Shader.Open( shader,defs ) )
 		
 		BlendMode=BlendMode.Alpha
 		CullMode=CullMode.None

+ 3 - 1
modules/mojo3d/graphics/watermaterial.monkey2

@@ -8,7 +8,9 @@ Class WaterMaterial Extends Material
 	#rem monkeydoc Creates a new water material.
 	#end
 	Method New()
-		Super.New( Shader.Open( "water" ) )
+		Assert( Cast<DeferredRenderer>( Renderer.GetCurrent() ),"Water material requires deferred renderer" )
+		
+		SetShader( Shader.Open( "material-water" ) )
 		
 		ColorTexture=Texture.ColorTexture( Color.SeaGreen )
 		ColorFactor=Color.White

+ 5 - 2
modules/mojo3d/mojo3d.monkey2

@@ -29,11 +29,14 @@ Using gles20..
 
 #Import "graphics/entityexts"
 
+#Import "graphics/renderqueue"
+#Import "graphics/renderer"
+#Import "graphics/deferredrenderer"
+#Import "graphics/forwardrenderer"
+
 #Import "graphics/animation"
 #Import "graphics/animator"
 
-#Import "graphics/renderer"
-
 #Import "graphics/posteffect"
 #Import "graphics/bloomeffect"
 #Import "graphics/fogeffect"

+ 0 - 1
modules/mojo3d/tests/donut.monkey2

@@ -41,7 +41,6 @@ Class MyWindow Extends Window
 		'create light
 		'
 		_light=New Light
-
 		_light.RotateX( 90 )
 		
 		'create donut - metallic silver...

+ 13 - 10
modules/mojo3d/tests/ducks.monkey2

@@ -44,12 +44,8 @@ Class MyWindow Extends Window
 		_fog=New FogEffect
 		_fog.Color=Color.Sky
 		_fog.Near=0
-		_fog.Far=100
-		
-		'monochrome effect - hit space to toggle
-		'
-		_monochrome=New MonochromeEffect
-		_monochrome.Enabled=False
+		_fog.Far=20
+		_scene.AddPostEffect( _fog )
 		
 		'_scene.SkyTexture=Texture.Load( "asset::miramar-skybox.jpg",TextureFlags.FilterMipmap|TextureFlags.Cubemap )
 		
@@ -64,7 +60,7 @@ Class MyWindow Extends Window
 		'
 		_light=New Light
 		_light.RotateX( 90 )	'aim directional light downwards
-		
+
 		'create ground
 		'
 		_ground=Model.CreateBox( New Boxf( -50,-1,-50,50,0,50 ),1,1,1,New PbrMaterial( Color.Green,0,1 ) )
@@ -73,7 +69,7 @@ Class MyWindow Extends Window
 		'		
 		Local duck:=Model.Load( "asset::duck.gltf/Duck.gltf" )
 		duck.Mesh.FitVertices( New Boxf( -1,1 ) )
-		'duck.CastsShadow=false
+'		duck.CastsShadow=False
 		
 		Local root:=duck.Copy()
 		root.Move( 0,10,0 )
@@ -120,9 +116,11 @@ Class MyWindow Extends Window
 			
 		'_monochrome.Level=Sin( Now()*3 ) * .5 + .5
 		
+		_ducks[0].RotateY( 1 )
+		
 		For Local duck:=Eachin _ducks
 			
-			duck.RotateY( 1 )
+			'duck.RotateY( 1 )
 		Next
 		
 		util.Fly( _camera,Self )
@@ -137,8 +135,13 @@ Class MyWindow Extends Window
 End
 
 Function Main()
+	
+	Local config:=New StringMap<String>
+
+	config["GL_depth_buffer_enabled"]=1
+	config["mojo3d_renderer"]="forward"
 
-	New AppInstance
+	New AppInstance( config )
 	
 	New MyWindow
 	

+ 6 - 1
modules/mojo3d/tests/pbrspheres.monkey2

@@ -76,7 +76,12 @@ End
 
 Function Main()
 
-	New AppInstance
+	Local config:=New StringMap<String>
+
+	config["mojo3d_renderer"]="forward"
+	config["GL_depth_buffer_enabled"]=1
+
+	New AppInstance( config )
 	
 	New MyWindow
 	

+ 6 - 1
modules/mojo3d/tests/sprites.monkey2

@@ -94,8 +94,13 @@ Class MyWindow Extends Window
 End
 
 Function Main()
+	
+	Local config:=New StringMap<String>
+
+	config["mojo3d_renderer"]="forward"
+	config["GL_depth_buffer_enabled"]=1
 
-	New AppInstance
+	New AppInstance( config )
 	
 	New MyWindow
 	

+ 2 - 2
modules/mojo3d/tests/util.monkey2

@@ -34,9 +34,9 @@ Function Fly( entity:Entity,view:View )
 	Endif
 	
 	If Keyboard.KeyDown( Key.A )
-		entity.MoveZ( .1 )	'( New Vec3f( 0,0,.1 ) )
+		entity.MoveZ( .1 )
 	Else If Keyboard.KeyDown( Key.Z )
-		entity.MoveZ( -.1 )	'( New Vec3f( 0,0,-.1 ) )
+		entity.MoveZ( -.1 )
 	Endif
 		
 End

+ 5 - 1
modules/mojo3d/tests/water.monkey2

@@ -79,7 +79,11 @@ End
 
 Function Main()
 
-	New AppInstance
+	Local config:=New StringMap<String>
+
+	config["mojo3d_renderer"]="deferred"
+
+	New AppInstance( config )
 	
 	New MyWindow