Mark Sibly 8 years ago
parent
commit
f3146c907e

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

@@ -6,15 +6,15 @@ Namespace mojo3d.graphics
 Class Animator
 	
 	Method New( animations:Animation[],entities:Entity[] )
-		
+
+#rem		
 		For Local i:=0 Until animations.Length
 			Print "anim["+i+"].Channels="+animations[i].Channels.Length
 			Print "anim["+i+"].Duration="+animations[i].Duration
 			Print "anim["+i+"].Hertz="+animations[i].Hertz
 		Next			
-		
 		Print "entities="+entities.Length
-		
+#end		
 		_animations=animations
 		
 		_entities=entities

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

@@ -1,179 +0,0 @@
-
-Namespace mojo3d.graphics
-
-#rem monkeydoc @hidden The DeferredRenderer class.
-#end
-Class DeferredRenderer Extends Renderer
-	
-	Protected
-	
-	Method OnRender() Override
-		
-		Init()
-		
-		_device.RenderTarget=_rpass0Target
-		_device.Viewport=New Recti( 0,0,_renderViewport.Size )
-		_device.Scissor=_device.Viewport
-
-		RenderBackground()
-		
-		RenderAmbient()
-
-		_device.RenderTarget=_rpass2Target
-		
-		_uniforms.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 )
-		Next
-		
-		RenderSprites()
-
-		RenderEffects()
-		
-		RenderCopy()
-	End
-	
-	Method RenderLight( light:Light )
-	
-		_uniforms.SetVec4f( "LightColor",light.Color )
-		_uniforms.SetFloat( "LightRange",light.Range )
-		_uniforms.SetMat4f( "LightViewMatrix",_camera.InverseMatrix * light.Matrix )
-		
-		_uniforms.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
-			_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 RenderEffects()
-		
-		_device.ColorMask=ColorMask.All
-		_device.DepthMask=False
-		_device.DepthFunc=DepthFunc.Always
-		_device.CullMode=CullMode.None
-
-		_device.VertexBuffer=_quadVertices
-		
-		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()
-		
-		Local source:=_device.RenderTarget.GetColorTexture( 0 )
-		
-		_uniforms.SetTexture( "SourceTexture",source )
-		_uniforms.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
-	
-	Private
-	
-	Field _copyShader:Shader
-	Field _plightShader:Shader
-	Field _dlightShader: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 _shadowTexture:Texture
-	
-	Field _rpass0Target:RenderTarget
-	Field _rpass2Target:RenderTarget
-	
-	Method Init()
-		
-		Global _inited:=False
-		
-		If Not _inited
-			_copyShader=Shader.Open( "copy" )
-			_plightShader=Shader.Open( "point-light" )
-			_dlightShader=Shader.Open( "directional-light" )
-		Endif
-		
-		Local size:=_renderViewport.Size
-		size.x=Max( size.x,1920 )
-		size.y=Max( size.y,1080 )
-		
-		If Not _inited 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 )
-			
-			_uniforms.SetTexture( "ColorBuffer",_colorTexture )
-			_uniforms.SetTexture( "NormalBuffer",_normalTexture )
-			_uniforms.SetTexture( "DepthBuffer",_depthTexture )
-		
-		Endif
-		
-		_inited=true
-		
-	End
-	
-End

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

@@ -1,34 +0,0 @@
-
-Namespace mojo3d.graphics
-
-Class ForwardRenderer Extends Renderer
-
-	Method OnRender() Override
-	
-		_device.RenderTarget=_renderTarget
-		_device.Resize( _renderTargetSize )
-		
-		For Local camera:=Eachin _scene.Cameras
-		
-			SetCamera( camera )
-			
-			Local viewport:=_camera.Viewport+_renderViewport.Origin
-			Local scissor:=viewport & _renderViewport
-			
-			_device.Viewport=viewport
-			_device.Scissor=scissor
-			_device.ColorMask=ColorMask.All
-			_device.DepthMask=True
-			
-			_device.DepthFunc=DepthFunc.LessEqual
-			_device.BlendMode=BlendMode.Opaque
-			_device.CullMode=CullMode.Back
-			_device.RenderPass=0
-			
-			RenderModels( -_camera.WorldMatrix,_camera.ProjectionMatrix )
-			
-		Next
-			
-	End
-
-End

+ 12 - 13
modules/mojo3d/graphics/material.monkey2

@@ -7,7 +7,7 @@ Class Material Extends Resource
 	
 	#rem monkeydoc Creates a new material
 	#end
-	Method New( shader:Shader )
+	Method New( shader:Shader=Null )
 		_shader=shader
 		_uniforms=New UniformBlock( 2 )
 		_blendMode=BlendMode.Opaque
@@ -17,22 +17,16 @@ Class Material Extends Resource
 	
 	#rem monkeydoc Creates a copy of the material.
 	#end
-	Method Copy:Material() Virtual
-		
-		Return New Material( Self )
-	End
-
+	Method Copy:Material() abstract
+	
 	#rem monkeydoc The material shader.
 	#end
 	Property Shader:Shader()
 		
 		Return _shader
 		
-	Setter( shader:Shader )
-	
-		_shader=shader
 	End
-
+	
 	#Rem monkeydoc @hidden The material uniforms.
 	#End
 	Property Uniforms:UniformBlock()
@@ -105,9 +99,8 @@ Class Material Extends Resource
 	End
 
 	Protected
-	
 	#rem monkeydoc @hidden
-	#end	
+	#end
 	Method New( material:Material )
 		_shader=material._shader
 		_uniforms=New UniformBlock( material._uniforms )
@@ -116,10 +109,16 @@ Class Material Extends Resource
 		TextureMatrix=material.TextureMatrix
 	End
 	
-	Private
+	Method SetShader( shader:Shader )
+		
+		_shader=shader
+	End
 	
+	Private
+
 	Field _shader:Shader
 	Field _uniforms:UniformBlock
 	Field _blendMode:BlendMode
 	Field _cullMode:CullMode
+
 End

+ 13 - 0
modules/mojo3d/graphics/model.monkey2

@@ -83,6 +83,15 @@ Class Model Extends Entity
 		_bones=bones
 	End
 	
+	Property CastsShadow:Bool()
+		
+		Return _castsShadow
+		
+	Setter( castsShadow:Bool )
+	
+		_castsShadow=castsShadow
+	End
+	
 	#rem monkeydoc Loads a model from a file path.
 	
 	On its own, mojo3d can only load gltf2 format mesh and model files.
@@ -188,6 +197,8 @@ Class Model Extends Entity
 		
 		_materials=model._materials.Slice( 0 )
 		
+		_castsShadow=model._castsShadow
+		
 		Show()
 	End
 
@@ -214,4 +225,6 @@ Class Model Extends Entity
 	Field _bones:Bone[]
 	Field _boneMatrices:Mat4f[]
 	
+	Field _castsShadow:Bool=true
+	
 End

+ 31 - 22
modules/mojo3d/graphics/pbrmaterial.monkey2

@@ -18,10 +18,22 @@ Class PbrMaterial Extends Material
 	The above last 3 rules allow you to pack metalness, roughness and occlusion into a single texture.
 	
 	#end
-	Method New( boned:Bool=False )
-		Super.New( Shader.Open( boned ? "boned-material" Else "material" ) )
+	Method New( textured:Bool=True,bumpmapped:Bool=True,boned:Bool=False )
+		Super.New()	'WTF?
 		
-		ColorTexture=Texture.ColorTexture( Color.White )
+		Local defs:=""
+		
+		If textured
+			defs+="MX2_TEXTURED~n"
+			If bumpmapped
+				defs+="MX2_BUMPMAPPED~n"
+			Endif
+		Endif
+		If boned defs+="MX2_BONED~n"
+			
+		SetShader( Shader.Open( "material",defs ) )
+		
+		ColorTexture=Null'Textyure.ColorTexture( Color.White )
 		ColorFactor=Color.White
 		
 		EmissiveTexture=Texture.ColorTexture( Color.White )
@@ -35,23 +47,22 @@ Class PbrMaterial Extends Material
 		
 		OcclusionTexture=Texture.ColorTexture( Color.White )
 		
-		NormalTexture=Texture.ColorTexture( New Color( 0.5,0.5,1.0,0.0 ) )
-	End
-	
-	Method New( material:PbrMaterial )
-		
-		Super.New( material )
+		NormalTexture=Null'Texture.ColorTexture( New Color( 0.5,0.5,1.0,0.0 ) )
 	End
 	
 	Method New( color:Color,metalness:Float=0.0,roughness:Float=1.0 )
-	
-		Self.New()
+		Self.New( False,False,False )
 		
 		ColorFactor=color
 		MetalnessFactor=metalness
 		RoughnessFactor=roughness
 	End
 	
+	Method New( material:PbrMaterial )
+		
+		Super.New( material )
+	End
+	
 	#rem monkeydoc Creates a copy of the pbr material.
 	#end
 	Method Copy:PbrMaterial() Override
@@ -161,41 +172,38 @@ Class PbrMaterial Extends Material
 	normal.png
 	
 	#end
-	Function Load:PbrMaterial( path:String )
-		
-		Local flags:TextureFlags=TextureFlags.WrapST|TextureFlags.FilterMipmap
-		
+	Function Load:PbrMaterial( path:String,textureFlags:TextureFlags=TextureFlags.WrapST|TextureFlags.FilterMipmap )
 		
 		Local material:=New PbrMaterial
 		
-		Local texture:=Texture.Load( path+"/color.png",flags )
+		Local texture:=Texture.Load( path+"/color.png",textureFlags )
 		If texture
 			material.ColorTexture=texture
 		Endif
 		
-		texture=Texture.Load( path+"/emissive.png",flags )
+		texture=Texture.Load( path+"/emissive.png",textureFlags )
 		If texture
 			material.EmissiveTexture=texture
 			material.EmissiveFactor=Color.White
 		Endif
 		
-		texture=Texture.Load( path+"/metalness.png",flags )
+		texture=Texture.Load( path+"/metalness.png",textureFlags )
 		If texture
 			material.MetalnessTexture=texture
 		Endif
 		
-		texture=Texture.Load( path+"/roughness.png",flags )
+		texture=Texture.Load( path+"/roughness.png",textureFlags )
 		If texture
 			material.RoughnessTexture=texture
 		Endif
 		
-		texture=Texture.Load( path+"/occlusion.png",flags )
+		texture=Texture.Load( path+"/occlusion.png",textureFlags )
 		If texture
 			material.OcclusionTexture=texture
 		Endif
 		
-		texture=Texture.Load( path+"/normal.png",flags )
-'		If Not texture texture=Texture.Load( path+"/unormal.png",flags|TextureFlags.InvertGreen )
+		texture=Texture.Load( path+"/normal.png",textureFlags )
+'		If Not texture texture=Texture.Load( path+"/unormal.png",textureFlags|TextureFlags.InvertGreen )
 		If texture
 			material.NormalTexture=texture
 		Endif
@@ -203,4 +211,5 @@ Class PbrMaterial Extends Material
 		Return material
 	End
 	
+	
 End

+ 271 - 109
modules/mojo3d/graphics/renderer.monkey2

@@ -5,13 +5,11 @@ Namespace mojo3d.graphics
 
 Renderpasses:
 
-0 : render background.
+1 : opaque ambient
 
-1 : render deferred MRT.
+2 : opaque shadow depth
 
-2 : render shadow map.
-
-3 : render deferred light quad.
+3 : transparent
 
 #end
 
@@ -33,18 +31,47 @@ 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
@@ -53,7 +80,7 @@ Class RenderQueue
 		op.order=order
 		op.count=count
 		op.first=first
-		_opaqueOps.Push( op )
+		AddRenderOp( op )
 	End
 	
 	Method AddRenderOp( material:Material,vbuffer:VertexBuffer,ibuffer:IndexBuffer,instance:Entity,order:Int,count:Int,first:Int )
@@ -65,7 +92,7 @@ Class RenderQueue
 		op.order=order
 		op.count=count
 		op.first=first
-		_opaqueOps.Push( op )
+		AddRenderOp( op )
 	End
 	
 	Method AddRenderOp( material:Material,vbuffer:VertexBuffer,ibuffer:IndexBuffer,instance:Entity,bones:Mat4f[],order:Int,count:Int,first:Int )
@@ -78,14 +105,16 @@ Class RenderQueue
 		op.order=order
 		op.count=count
 		op.first=first
-		_opaqueOps.Push( op )
+		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.
@@ -113,7 +142,10 @@ Class Renderer
 		_defaultEnv=Texture.Load( "asset::textures/env_default.jpg",TextureFlags.FilterMipmap|TextureFlags.Cubemap )
 		
 		_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
@@ -155,7 +187,7 @@ Class Renderer
 	#end
 	Function GetCurrent:Renderer()
 		
-		Global _current:=New DeferredRenderer
+		Global _current:=New Renderer
 		
 		Return _current
 	End
@@ -164,120 +196,190 @@ Class Renderer
 	#end
 	Method Render( scene:Scene,camera:Camera,device:GraphicsDevice )
 		
-		Validate()
-	
 		_renderTarget=device.RenderTarget
 		_renderTargetSize=device.RenderTargetSize
 		_renderViewport=device.Viewport
 		
-		SetScene( scene )
+		ValidateSize( _renderViewport.Size )
+		
+		_renderScene=scene
+
+		_uniforms.SetFloat( "Time",Now() )
+		_uniforms.SetTexture( "SkyTexture",_renderScene.SkyTexture )
+		
+		_uniforms.SetVec4f( "ClearColor",_renderScene.ClearColor )
+		_uniforms.SetVec4f( "AmbientDiffuse",_renderScene.AmbientLight )
+	
+		_uniforms.SetTexture( "ShadowTexture",_csmTexture )
+		_uniforms.SetVec4f( "ShadowSplits",New Vec4f( _csmSplits[1],_csmSplits[2],_csmSplits[3],_csmSplits[4] ) )
+		
+		Local env:Texture
+		
+		If _renderScene.SkyTexture
+			env=_renderScene.SkyTexture
+		Else If _renderScene.EnvTexture
+			env=_renderScene.EnvTexture
+		Else
+			env=_defaultEnv
+		Endif
+		
+		_uniforms.SetTexture( "EnvTexture",env )
 		
-		SetCamera( camera )
+		_renderQueue.Clear()
+		
+		For Local model:=Eachin _renderScene.Models
+			
+			_renderQueue.AddShadowOps=model.CastsShadow
+			
+			model.OnRender( _renderQueue )
+		Next
+
+		_renderCamera=camera
+
+		Local envMat:=_renderCamera.Matrix.m
+		Local viewMat:=_renderCamera.InverseMatrix
+		Local projMat:=_renderCamera.ProjectionMatrix
+		Local invProjMat:=-projMat
+			
+		_uniforms.SetMat3f( "EnvMatrix",envMat )
+		_uniforms.SetMat4f( "ProjectionMatrix",projMat )
+		_uniforms.SetMat4f( "InverseProjectionMatrix",invProjMat )
+		_uniforms.SetFloat( "DepthNear",_renderCamera.Near )
+		_uniforms.SetFloat( "DepthFar",_renderCamera.Far )
+		
+		_spriteQueue.Clear()
+		
+		_spriteBuffer.AddSprites( _spriteQueue,_renderScene.Sprites,_renderCamera )
 		
 		OnRender()
+		
+		_renderCamera=Null
+		
+		_renderScene=null
 	End
 	
 	'***** INTERNAL *****
 	
 	Protected
-
-	Field _csmSize:=4096
-	Field _csmSplits:=New Float[]( 1,20,60,180,1000 )
 	
-	Field _uniforms:UniformBlock
 	Field _device:GraphicsDevice
+	Field _uniforms: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[64]
+	Field _nullBones:=New Mat4f[96]
 	
-	'Per render...
-	'
 	Field _renderTarget:RenderTarget
 	Field _renderTargetSize:Vec2i
 	Field _renderViewport:Recti
-	
-	Field _scene:Scene
-	Field _camera:Camera
-	
-'	Field _projectionMatrix:Mat4f
-'	Field _viewMatrix:AffineMat4f
-'	Field _viewProjectionMatrix:Mat4f
-	
-	Method OnRender() Virtual
-	End
+	Field _renderScene:Scene
+	Field _renderCamera:Camera
+	Field _renderLight:Light
 
-	Method SetScene( scene:Scene )
-	
-		_scene=scene
+	Method ValidateSize( size:Vec2i )
 		
-		_uniforms.SetFloat( "Time",Now() )
-		_uniforms.SetTexture( "SkyTexture",_scene.SkyTexture )
+		size.x=Max( size.x,1920 )
+		size.y=Max( size.y,1080 )
 		
-		_uniforms.SetVec4f( "ClearColor",_scene.ClearColor )
-		_uniforms.SetVec4f( "AmbientDiffuse",_scene.AmbientLight )
-	
-		_uniforms.SetTexture( "ShadowTexture",_csmTexture )
-		_uniforms.SetVec4f( "ShadowSplits",New Vec4f( _csmSplits[1],_csmSplits[2],_csmSplits[3],_csmSplits[4] ) )
+		If Not _hdrTexture Or size.x>_hdrTexture.Size.x Or size.y>_hdrTexture.Size.y
 		
-		Local env:Texture
+			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 )
+			
+			_uniforms.SetTexture( "ColorBuffer",_colorTexture )
+			_uniforms.SetTexture( "NormalBuffer",_normalTexture )
+			_uniforms.SetTexture( "DepthBuffer",_depthTexture )
 		
-		If _scene.SkyTexture
-			env=_scene.SkyTexture
-		Else If _scene.EnvTexture
-			env=_scene.EnvTexture
-		Else
-			env=_defaultEnv
+		Endif
+
+		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
 		
-		_uniforms.SetTexture( "EnvTexture",env )
+	End
+
+	Method OnRender()
 		
-		_renderQueue.Clear()
+		_device.RenderTarget=_rpass0Target
+		_device.Viewport=New Recti( 0,0,_renderViewport.Size )
+		_device.Scissor=_device.Viewport
+
+		RenderBackground()
 		
-		For Local model:=Eachin _scene.Models
-			
-			model.OnRender( _renderQueue )
-		Next
+		RenderAmbient()
+
+		_device.RenderTarget=_rpass2Target
+		
+		_uniforms.SetVec2f( "BufferCoordScale",Cast<Vec2f>( _renderViewport.Size )/Cast<Vec2f>( _hdrTexture.Size ) )
 		
-		For Local terrain:=Eachin _scene.Terrains
+		For Local light:=Eachin _renderScene.Lights
 			
-			terrain.OnRender( _renderQueue )
-		Next
-	End
+			If light.Type=LightType.Point Continue
 
-	Method SetCamera( camera:Camera )
-	
-		_camera=camera
-		
-		Local envMat:=_camera.Matrix.m
-		Local viewMat:=_camera.InverseMatrix
-		Local projMat:=_camera.ProjectionMatrix
-		Local invProjMat:=-projMat
+			_renderLight=light
 			
-		_uniforms.SetMat3f( "EnvMatrix",envMat )
-		_uniforms.SetMat4f( "ProjectionMatrix",projMat )
-		_uniforms.SetMat4f( "InverseProjectionMatrix",invProjMat )
-		_uniforms.SetFloat( "DepthNear",_camera.Near )
-		_uniforms.SetFloat( "DepthFar",_camera.Far )
+			RenderCSMShadows()
+			
+			RenderLight()
+		Next
 		
-		_spriteQueue.Clear()
+		_renderLight=null
 		
-		_spriteBuffer.AddSprites( _spriteQueue,_scene.Sprites,_camera )
+		_device.RenderTarget=_rpass0Target
+		
+		RenderSprites()
+
+		_device.RenderTarget=_rpass2Target
+
+		RenderEffects()
+		
+		RenderCopy()
 	End
 	
-	'MX2_RENDERPASS 0
-	'
-	Method RenderBackground() Virtual
+	Method RenderBackground()
 	
-		If _scene.SkyTexture
+		If _renderScene.SkyTexture
 		
 			_device.ColorMask=ColorMask.None
 			_device.DepthMask=True
@@ -299,39 +401,23 @@ Class Renderer
 			_device.ColorMask=ColorMask.All
 			_device.DepthMask=True
 		
-			_device.Clear( _scene.ClearColor,1.0 )
+			_device.Clear( _renderScene.ClearColor,1.0 )
 
 		Endif
 		
 	End
 	
-	'MX2_RNDERPASS 1
-	'
-	Method RenderAmbient() Virtual
+	Method RenderAmbient()
 		
 		_device.ColorMask=ColorMask.All
 		_device.DepthMask=True
 		_device.DepthFunc=DepthFunc.LessEqual
 		_device.RenderPass=1
 		
-		RenderRenderOps( _renderQueue.OpaqueOps,_camera.InverseMatrix,_camera.ProjectionMatrix )
+		RenderRenderOps( _renderQueue.OpaqueOps,_renderCamera.InverseMatrix,_renderCamera.ProjectionMatrix )
 	End
 	
-	'MX2_RENDERPASS 0
-	'
-	Method RenderSprites()
-	
-		_device.ColorMask=ColorMask.All
-		_device.DepthMask=False
-		_device.DepthFunc=DepthFunc.Always
-		_device.RenderPass=0
-
-		RenderRenderOps( _spriteQueue.OpaqueOps,_camera.InverseMatrix,_camera.ProjectionMatrix )
-	End
-	
-	'MX2_RENDERPASS 2
-	'
-	Method RenderCSMShadows( light:Light )
+	Method RenderCSMShadows()
 	
 		'Perhaps use a different device for CSM...?
 		'
@@ -351,15 +437,15 @@ Class Renderer
 		_device.CullMode=CullMode.Back
 		_device.RenderPass=2
 
-		Local invLightMatrix:=light.InverseMatrix
-		Local viewLight:=invLightMatrix * _camera.Matrix
+		Local invLightMatrix:=_renderLight.InverseMatrix
+		Local viewLight:=invLightMatrix * _renderCamera.Matrix
 		
 		For Local i:=0 Until _csmSplits.Length-1
 			
 			Local znear:=_csmSplits[i]
 			Local zfar:=_csmSplits[i+1]
 			
-			Local splitProj:=Mat4f.Perspective( _camera.Fov,_camera.Aspect,znear,zfar )
+			Local splitProj:=Mat4f.Perspective( _renderCamera.Fov,_renderCamera.Aspect,znear,zfar )
 						
 			Local invSplitProj:=-splitProj
 			
@@ -394,8 +480,8 @@ Class Renderer
 			
 			_device.Scissor=_device.Viewport
 				
-			If light.ShadowsEnabled
-				RenderRenderOps( _renderQueue.OpaqueOps,invLightMatrix,lightProj )
+			If _renderLight.ShadowsEnabled
+				RenderRenderOps( _renderQueue.ShadowOps,invLightMatrix,lightProj )
 			Endif
 			
 		Next
@@ -404,18 +490,94 @@ Class Renderer
 		_device.Viewport=t_viewport
 		_device.Scissor=t_scissor
 	End
+	
+	Method RenderLight()
+	
+		_uniforms.SetVec4f( "LightColor",_renderLight.Color )
+		_uniforms.SetFloat( "LightRange",_renderLight.Range )
+		_uniforms.SetMat4f( "LightViewMatrix",_renderCamera.InverseMatrix * _renderLight.Matrix )
+		
+		_uniforms.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()
+	
+		_device.ColorMask=ColorMask.All
+		_device.DepthMask=False
+		_device.DepthFunc=DepthFunc.LessEqual
+		_device.RenderPass=0
+
+		RenderRenderOps( _spriteQueue.TransparentOps,_renderCamera.InverseMatrix,_renderCamera.ProjectionMatrix )
+	End
+	
+	Method RenderEffects()
+		
+		_device.ColorMask=ColorMask.All
+		_device.DepthMask=False
+		_device.DepthFunc=DepthFunc.Always
+		_device.CullMode=CullMode.None
 
-	Method Validate()
+		_device.VertexBuffer=_quadVertices
 		
-		If Not _csmTexture Or _csmSize<>_csmTexture.Size.x
+		For Local effect:=Eachin _renderScene.PostEffects
 			
-			If _csmTexture _csmTexture.Discard()
-			If _csmTarget _csmTarget.Discard()
+			If Not effect.Enabled Continue
 			
-			_csmTexture=New Texture( _csmSize,_csmSize,PixelFormat.Depth32F,TextureFlags.Dynamic )
-			_csmTarget=New RenderTarget( Null,_csmTexture )
+			_device.BlendMode=BlendMode.Opaque
+			_device.RenderPass=0
 			
-		Endif
+			effect.Render( _device )
+		Next
+		
+	End
+	
+	Method RenderCopy()
+		
+		Local source:=_device.RenderTarget.GetColorTexture( 0 )
+		
+		_uniforms.SetTexture( "SourceTexture",source )
+		_uniforms.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 )

+ 0 - 184
modules/mojo3d/graphics/shaders/boned-material.glsl

@@ -1,184 +0,0 @@
-//@renderpasses 1,2
-
-//material uniforms
-
-uniform mat3 m_TextureMatrix;
-
-//renderer uniforms...
-
-uniform mat4 r_ModelViewMatrix;
-uniform mat4 r_ModelViewProjectionMatrix;
-uniform mat3 r_ModelViewNormalMatrix;
-
-#if MX2_RENDERPASS==1
-
-uniform vec4 r_AmbientDiffuse;
-uniform samplerCube r_EnvTexture;
-uniform mat3 r_EnvMatrix;
-
-//pbr varyings...
-
-varying vec3 v_Position;
-varying vec2 v_TexCoord0;
-varying vec3 v_Normal;
-varying mat3 v_TanMatrix;
-
-#endif
-
-//@vertex
-
-uniform mat4 r_BoneMatrices[96];
-
-//vertex attribs....
-
-attribute vec4 a_Position;
-attribute vec4 a_Weights;
-attribute vec4 a_Bones;
-
-#if MX2_RENDERPASS==1 
-
-attribute vec2 a_TexCoord0;
-attribute vec3 a_Normal;
-attribute vec4 a_Tangent;
-
-#endif
-
-void main(){
-
-	mat4 m0=r_BoneMatrices[ int( a_Bones.x ) ];
-	mat4 m1=r_BoneMatrices[ int( a_Bones.y ) ];
-	mat4 m2=r_BoneMatrices[ int( a_Bones.z ) ];
-	mat4 m3=r_BoneMatrices[ 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_RENDERPASS==1
-
-	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 );
-		
-	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 );
-
-	// texture coord0
-	v_TexCoord0=(m_TextureMatrix * vec3(a_TexCoord0,1.0)).st;
-
-	// view space position
-	v_Position=( r_ModelViewMatrix * b_Position ).xyz;
-
-	// viewspace normal
-	v_Normal=r_ModelViewNormalMatrix * b_Normal;
-	
-	// viewspace tangent matrix
-	v_TanMatrix[2]=v_Normal;
-	v_TanMatrix[0]=r_ModelViewNormalMatrix * b_Tangent.xyz;
-	v_TanMatrix[1]=cross( v_TanMatrix[0],v_TanMatrix[2] ) * b_Tangent.a;
-	
-#endif
-	
-	gl_Position=r_ModelViewProjectionMatrix * b_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 );
-
-	vec3 color0=vec3( 0.04,0.04,0.04 );
-	
-	vec3 diffuse=color * (1.0-metalness);
-	
-	vec3 specular=(color-color0) * metalness + color0;
-	
-	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 env=pow( textureCube( r_EnvTexture,rvec,max( roughness*10.0-lod,0.0 ) ).rgb,vec3( 2.2 ) );
-
-	vec3 vvec=normalize( -v_Position );
-	
-	float ndotv=max( dot( normal,vvec ),0.0 );
-	
-	vec3 fschlick=specular + (1.0-specular) * pow( 1.0-ndotv,5.0 ) * (1.0-roughness);
-
-	vec3 ambdiff=diffuse * r_AmbientDiffuse.rgb;
-		
-	vec3 ambspec=env * fschlick;
-
-	gl_FragData[0]=vec4( min( (ambdiff+ambspec) * occlusion + emissive,8.0 ),1.0 );
-	
-	gl_FragData[1]=vec4( color,metalness );
-	
-	gl_FragData[2]=vec4( normal * 0.5 + 0.5,roughness );
-}
-
-#endif
-
-#if MX2_RENDERPASS==1
-
-uniform sampler2D m_ColorTexture;
-uniform vec4 m_ColorFactor;
-
-uniform sampler2D m_EmissiveTexture;
-uniform vec4 m_EmissiveFactor;
-
-uniform sampler2D m_MetalnessTexture;
-uniform float m_MetalnessFactor;
-
-uniform sampler2D m_RoughnessTexture;
-uniform float m_RoughnessFactor;
-
-uniform sampler2D m_OcclusionTexture;
-
-uniform sampler2D m_NormalTexture;
-
-#endif
-
-void main(){
-
-#if MX2_RENDERPASS==1
-
-	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;
-
-	vec3 normal=texture2D( m_NormalTexture,v_TexCoord0 ).xyz * 2.0 - 1.0;
-	
-	main0( color,emissive,metalness,roughness,occlusion,normal );
-	
-//	gl_FragColor=vec4( 1.0,0.5,0.0,1.0 );	
-	
-#else
-
-	gl_FragColor=vec4( vec3( gl_FragCoord.z ),1.0 );
-
-#endif
-
-}

+ 127 - 33
modules/mojo3d/graphics/shaders/material.glsl

@@ -1,9 +1,15 @@
 
-//@renderpasses 1,2
+//@renderpasses 1,2,3
 
+#define MX2_AMBIENTPASS (MX2_RENDERPASS==1)
+#define MX2_CASTSHADOWPASS (MX2_RENDERPASS==2)
+#define MX2_TRANSPARENTPASS (MX2_RENDERPASS==3)
+ 
 //material uniforms
 
+#ifdef MX2_TEXTURED
 uniform mat3 m_TextureMatrix;
+#endif
 
 //renderer uniforms...
 
@@ -11,7 +17,7 @@ uniform mat4 r_ModelViewMatrix;
 uniform mat4 r_ModelViewProjectionMatrix;
 uniform mat3 r_ModelViewNormalMatrix;
 
-#if MX2_RENDERPASS==1
+#if MX2_AMBIENTPASS
 
 uniform vec4 r_AmbientDiffuse;
 uniform samplerCube r_EnvTexture;
@@ -20,32 +26,105 @@ uniform mat3 r_EnvMatrix;
 //pbr varyings...
 
 varying vec3 v_Position;
-varying vec2 v_TexCoord0;
 varying vec3 v_Normal;
+#ifdef MX2_TEXTURED
+varying vec2 v_TexCoord0;
+#ifdef MX2_BUMPMAPPED
 varying mat3 v_TanMatrix;
-
+#endif
 #endif
 
+#endif	//MX2_AMBIENTPASS
+
 //@vertex
 
+#ifdef MX2_BONED
+uniform mat4 r_BoneMatrices[96];
+#endif
+
 //vertex attribs....
 
 attribute vec4 a_Position;
+#ifdef MX2_BONED
+attribute vec4 a_Weights;
+attribute vec4 a_Bones;
+#endif
 
-#if MX2_RENDERPASS==1 
+#if MX2_AMBIENTPASS
 
-attribute vec2 a_TexCoord0;
 attribute vec3 a_Normal;
+#ifdef MX2_TEXTURED
+attribute vec2 a_TexCoord0;
+#ifdef MX2_BUMPMAPPED
 attribute vec4 a_Tangent;
-
 #endif
+#endif
+
+#endif	//MX2_AMBIENTPASS
+
+#ifdef MX2_BONED
 
 void main(){
 
-#if MX2_RENDERPASS==1
+	mat4 m0=r_BoneMatrices[ int( a_Bones.x ) ];
+	mat4 m1=r_BoneMatrices[ int( a_Bones.y ) ];
+	mat4 m2=r_BoneMatrices[ int( a_Bones.z ) ];
+	mat4 m3=r_BoneMatrices[ 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_AMBIENTPASS
+
+	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 );
+		
+#ifdef 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=( r_ModelViewMatrix * b_Position ).xyz;
+
+	// viewspace normal
+	v_Normal=r_ModelViewNormalMatrix * b_Normal;
+	
+#ifdef MX2_TEXTURED
 	// texture coord0
 	v_TexCoord0=(m_TextureMatrix * vec3(a_TexCoord0,1.0)).st;
+#ifdef MX2_BUMPMAPPED
+	// viewspace tangent matrix
+	v_TanMatrix[2]=v_Normal;
+	v_TanMatrix[0]=r_ModelViewNormalMatrix * b_Tangent.xyz;
+	v_TanMatrix[1]=cross( v_TanMatrix[0],v_TanMatrix[2] ) * b_Tangent.a;
+#endif
+#endif
+	
+#endif	//MX2_AMBIENTPASS
+	
+	gl_Position=r_ModelViewProjectionMatrix * b_Position;
+}
+
+#else	//MX2_BONED
+
+void main(){
+
+#if MX2_AMBIENTPASS
 
 	// view space position
 	v_Position=( r_ModelViewMatrix * a_Position ).xyz;
@@ -53,23 +132,29 @@ void main(){
 	// viewspace normal
 	v_Normal=r_ModelViewNormalMatrix * a_Normal;
 	
+#ifdef MX2_TEXTURED
+	// texture coord0
+	v_TexCoord0=(m_TextureMatrix * vec3(a_TexCoord0,1.0)).st;
+#ifdef MX2_BUMPMAPPED
 	// viewspace tangent matrix
 	v_TanMatrix[2]=v_Normal;
 	v_TanMatrix[0]=r_ModelViewNormalMatrix * a_Tangent.xyz;
 	v_TanMatrix[1]=cross( v_TanMatrix[0],v_TanMatrix[2] ) * a_Tangent.a;
-	
 #endif
+#endif
+
+#endif	//MX2_AMBIENTPASS
 	
 	gl_Position=r_ModelViewProjectionMatrix * a_Position;
 }
 
-//@fragment
+#endif	//MX2_BONED
 
-#if MX2_RENDERPASS==1
+//@fragment
 
-void main0( vec3 color,vec3 emissive,float metalness,float roughness,float occlusion,vec3 normal ){
+#if MX2_AMBIENTPASS
 
-	normal=normalize( v_TanMatrix * normal );
+void pbr_WriteFragData( vec3 color,vec3 emissive,float metalness,float roughness,float occlusion,vec3 normal ){
 
 	vec3 color0=vec3( 0.04,0.04,0.04 );
 	
@@ -104,50 +189,59 @@ void main0( vec3 color,vec3 emissive,float metalness,float roughness,float occlu
 
 #endif
 
-#if MX2_RENDERPASS==1
+#if MX2_AMBIENTPASS
 
+#ifdef MX2_TEXTURED
 uniform sampler2D m_ColorTexture;
-uniform vec4 m_ColorFactor;
-
 uniform sampler2D m_EmissiveTexture;
-uniform vec4 m_EmissiveFactor;
-
 uniform sampler2D m_MetalnessTexture;
-uniform float m_MetalnessFactor;
-
 uniform sampler2D m_RoughnessTexture;
-uniform float m_RoughnessFactor;
-
 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;
 
 #endif
 
 void main(){
 
-#if MX2_RENDERPASS==1
+#if MX2_AMBIENTPASS
+
+#ifdef 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;
-
-	vec3 normal=texture2D( m_NormalTexture,v_TexCoord0 ).xyz * 2.0 - 1.0;
 	
-	main0( color,emissive,metalness,roughness,occlusion,normal );
+#ifdef MX2_BUMPMAPPED
+	vec3 normal=texture2D( m_NormalTexture,v_TexCoord0 ).xyz * 2.0 - 1.0;
+	normal=normalize( v_TanMatrix * normal );
+#else
+	vec3 normal=v_Normal;
+#endif
 	
-//	gl_FragColor=vec4( 1.0,0.5,0.0,1.0 );	
+#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=v_Normal;
+
+#endif
+
+	pbr_WriteFragData( color,emissive,metalness,roughness,occlusion,normal );
 	
 #else
 
 	gl_FragColor=vec4( vec3( gl_FragCoord.z ),1.0 );
 
 #endif
-
 }

+ 13 - 0
modules/mojo3d/graphics/sprite.monkey2

@@ -56,6 +56,18 @@ Class Sprite Extends Entity
 		
 		_material=material
 	End
+
+	#rem monkeydoc Rect within texture to draw.
+	
+	#end	
+	Property TextureRect:Rectf()
+		
+		Return _textureRect
+	
+	Setter( textureRect:Rectf )
+		
+		_textureRect=textureRect
+	End
 	
 	#rem monkeydoc Sprite handle.
 	
@@ -116,6 +128,7 @@ Class Sprite Extends Entity
 	Private
 	
 	Field _material:Material
+	Field _textureRect:=New Rectf( 0,0,1,1 )
 	Field _handle:Vec2f=New Vec2f( .5,.5 )
 	Field _mode:SpriteMode=Null
 	

+ 18 - 5
modules/mojo3d/graphics/spritebuffer.monkey2

@@ -14,6 +14,14 @@ Class SpriteBuffer
 		_spriteIndices=New IndexBuffer( IndexFormat.UINT32,0 )
 	End
 	
+	Method AddSpriteops:Vertex3f ptr( vp:Vertex3f Ptr,rq:RenderQueue,sprites:Stack<Sprite>,camera:Camera )
+		
+		If Not sprites.Length Return vp
+		
+		
+		Return vp
+	end		
+	
 	Method AddSprites( rq:RenderQueue,sprites:Stack<Sprite>,camera:Camera )
 		
 		If sprites.Empty Return
@@ -37,10 +45,12 @@ Class SpriteBuffer
 			Next
 		Endif
 		
+		'Sort sprites by distance from camera. Only really need to do this for transparent sprites, but meh...
+		'
 		sprites.Sort( Lambda:Int( x:Sprite,y:Sprite )
 			Return camera.Position.Distance( y.Position ) <=> camera.Position.Distance( x.Position )
 		End )
-		
+
 		Local cmaterial:=sprites[0].Material
 		Local i0:=0,i:=0
 		
@@ -63,25 +73,28 @@ Class SpriteBuffer
 			
 			Local matrix:=New AffineMat4f( r.Scale( sprite.Scale ),sprite.Position )
 			
+			Local texrect:=sprite.TextureRect
+			
 			Local handle:=sprite.Handle
 			
 			vp[0].position=matrix * New Vec3f( -handle.x,1-handle.y,0 )
-			vp[0].texCoord0=New Vec2f( 0,0 )
+			vp[0].texCoord0=New Vec2f( texrect.min.x,texrect.min.y )
 			
 			vp[1].position=matrix * New Vec3f( 1-handle.x,1-handle.y,0 )
-			vp[1].texCoord0=New Vec2f( 1,0 )
+			vp[1].texCoord0=New Vec2f( texrect.max.x,texrect.min.y )
 
 			vp[2].position=matrix * New Vec3f( 1-handle.x,-handle.y,0 )
-			vp[2].texCoord0=New Vec2f( 1,1 )
+			vp[2].texCoord0=New Vec2f( texrect.max.x,texrect.max.y )
 			
 			vp[3].position=matrix * New Vec3f( -handle.x,-handle.y,0 )
-			vp[3].texCoord0=New Vec2f( 0,1 )
+			vp[3].texCoord0=New Vec2f( texrect.min.x,texrect.max.y )
 			
 			vp+=4
 			i+=1
 		Next
 		
 		rq.AddRenderOp( cmaterial,_spriteVertices,_spriteIndices,Null,3,(i-i0)*2,i0*6 )
+		
 	End
 
 	Private

+ 7 - 11
modules/mojo3d/graphics/spritematerial.monkey2

@@ -17,6 +17,11 @@ Class SpriteMaterial Extends Material
 		ColorFactor=Color.White
 	End
 	
+	Method New( material:SpriteMaterial )
+	
+		Super.New( material )
+	End
+	
 	#rem monkeydoc Creates a copy of the sprite material.
 	#end
 	Method Copy:SpriteMaterial() Override
@@ -44,9 +49,9 @@ Class SpriteMaterial Extends Material
 
 	#rem monkeydoc Loads a sprite material from an image file.
 	#end	
-	Function Load:SpriteMaterial( path:String )
+	Function Load:SpriteMaterial( path:String,textureFlags:TextureFlags=TextureFlags.FilterMipmap )
 		
-		Local texture:=Texture.Load( path,TextureFlags.FilterMipmap )
+		Local texture:=Texture.Load( path,textureFlags )
 		If Not texture texture=Texture.ColorTexture( Color.Magenta )
 		
 		Local material:=New SpriteMaterial
@@ -55,14 +60,5 @@ Class SpriteMaterial Extends Material
 		Return material
 	End
 	
-	Protected
-	
-	#rem monkeydoc @hidden
-	#end
-	Method New( material:SpriteMaterial )
-	
-		Super.New( material )
-	End
-	
 End
 

+ 5 - 8
modules/mojo3d/graphics/watermaterial.monkey2

@@ -23,6 +23,11 @@ Class WaterMaterial Extends Material
 		Velocities=New Vec2f[]( New Vec2f( 0,0 ),New Vec2f( 0,0 ) )
 	End
 	
+	Method New( material:WaterMaterial )
+		
+		Super.New( material )
+	End
+	
 	#rem monkeydoc Creates a copy of the water material.
 	#end
 	Method Copy:WaterMaterial() Override
@@ -87,13 +92,5 @@ Class WaterMaterial Extends Material
 		Uniforms.SetVec2f( "Velocity0",velocities[0] )
 		Uniforms.SetVec2f( "Velocity1",velocities[1] )
 	End
-
-	Protected
-		
-	#rem monkeydoc @hidden
-	#end
-	Method New( material:WaterMaterial )
-		Super.New( material )
-	End
 	
 End

+ 1 - 2
modules/mojo3d/mojo3d.monkey2

@@ -33,7 +33,6 @@ Using gles20..
 #Import "graphics/animator"
 
 #Import "graphics/renderer"
-#Import "graphics/deferredrenderer"
 
 #Import "graphics/posteffect"
 #Import "graphics/bloomeffect"
@@ -42,5 +41,5 @@ Using gles20..
 
 #Import "graphics/material"
 #Import "graphics/pbrmaterial"
-#Import "graphics/spritematerial"
 #Import "graphics/watermaterial"
+#Import "graphics/spritematerial"

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

@@ -73,6 +73,7 @@ Class MyWindow Extends Window
 		'		
 		Local duck:=Model.Load( "asset::duck.gltf/Duck.gltf" )
 		duck.Mesh.FitVertices( New Boxf( -1,1 ) )
+		'duck.CastsShadow=false
 		
 		Local root:=duck.Copy()
 		root.Move( 0,10,0 )

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

@@ -43,7 +43,7 @@ Class MyWindow Extends Window
 		'create light
 		'
 		_light=New Light
-		_light.RotateX( Pi/2 )	'aim directional light 'down' - Pi/2=90 degrees.
+		_light.Rotate( 60,45,0 )	'aim directional light 'down' - Pi/2=90 degrees.
 		
 		'create ground
 		'
@@ -53,6 +53,8 @@ Class MyWindow Extends Window
 		'
 		Local material:=SpriteMaterial.Load( "asset::Acadia-Tree-Sprite.png" )
 		
+		material.ColorTexture.Flags=TextureFlags.None
+		
 		For Local i:=0 Until 1000
 			
 			Local sprite:=New Sprite( material )
@@ -68,6 +70,14 @@ Class MyWindow Extends Window
 			_sprites.Push( sprite )
 		Next
 		
+		For Local i:=0 Until 10
+			
+			Local box:=Model.CreateBox( New Boxf( -5,0,-5,5,Rnd(2,10),5 ),1,1,1,New PbrMaterial( New Color( Rnd(),Rnd(),Rnd() ) ) )
+			
+			box.Move( Rnd(-50,50),0,Rnd(-50,50) )
+
+		next			
+		
 	End
 	
 	Method OnRender( canvas:Canvas ) Override