Browse Source

New mega-renderer added.

Mark Sibly 7 years ago
parent
commit
196e6642fa

+ 13 - 9
modules/mojo3d/components/collider.monkey2

@@ -499,25 +499,28 @@ Class MeshCollider Extends ConcaveCollider
 	Method OnCreate:btCollisionShape() Override
 	Method OnCreate:btCollisionShape() Override
 		
 		
 		Local vertices:=_mesh.GetVertices()
 		Local vertices:=_mesh.GetVertices()
-		_vertices=New btVector3[vertices.Length]
+		_vertices=New btScalar[vertices.Length*3]
 		
 		
 		For Local i:=0 Until vertices.Length
 		For Local i:=0 Until vertices.Length
-			_vertices[i].x=vertices[i].position.x
-			_vertices[i].y=vertices[i].position.y
-			_vertices[i].z=vertices[i].position.z
+			_vertices[i*3]=vertices[i].position.x
+			_vertices[i*3+1]=vertices[i].position.y
+			_vertices[i*3+2]=vertices[i].position.z
 		Next
 		Next
 		
 		
 		Local indices:=_mesh.GetAllIndices()
 		Local indices:=_mesh.GetAllIndices()
 		_indices=New Int[indices.Length]
 		_indices=New Int[indices.Length]
-		For Local i:=0 Until indices.Length
-			_indices[i]=indices[i]
+		
+		For Local i:=0 Until indices.Length Step 3
+			_indices[i+0]=indices[1]
+			_indices[i+1]=indices[i+1]
+			_indices[i+2]=indices[i+2]
 		Next
 		Next
 		
 		
-		_btmesh=New btTriangleIndexVertexArray( _indices.Length/3,_indices.Data,12,_vertices.Length,Cast<btScalar Ptr>( _vertices.Data ),16 )
+		_btmesh=New btTriangleIndexVertexArray( _indices.Length/3,_indices.Data,12,_vertices.Length,_vertices.Data,12 )
 		
 		
 		Local shape:=New btBvhTriangleMeshShape( _btmesh,True,True )
 		Local shape:=New btBvhTriangleMeshShape( _btmesh,True,True )
 		
 		
-		CreateInternalEdgeInfo( shape )
+'		CreateInternalEdgeInfo( shape )
 		
 		
 		Return shape
 		Return shape
 	End
 	End
@@ -525,7 +528,8 @@ Class MeshCollider Extends ConcaveCollider
 	Private
 	Private
 	
 	
 	Field _mesh:Mesh
 	Field _mesh:Mesh
-	Field _vertices:btVector3[]
+	Field _vertices:btScalar[]
+	'Field _vertices:btVector3[]
 	Field _indices:Int[]
 	Field _indices:Int[]
 	Field _btmesh:btTriangleIndexVertexArray
 	Field _btmesh:btTriangleIndexVertexArray
 	
 	

+ 6 - 2
modules/mojo3d/components/native/internaledges.cpp

@@ -7,11 +7,13 @@ namespace{
 
 
 	bool CustomMaterialCombinerCallback( btManifoldPoint& cp,const btCollisionObjectWrapper* colObj0Wrap,int partId0,int index0,const btCollisionObjectWrapper *colObj1Wrap,int partId1,int index1 ){
 	bool CustomMaterialCombinerCallback( btManifoldPoint& cp,const btCollisionObjectWrapper* colObj0Wrap,int partId0,int index0,const btCollisionObjectWrapper *colObj1Wrap,int partId1,int index1 ){
 	
 	
+//		printf( "contact added internal edge contacts!\n" );fflush( stdout );
+	
 		btAdjustInternalEdgeContacts( cp,colObj1Wrap,colObj0Wrap,partId1,index1 );
 		btAdjustInternalEdgeContacts( cp,colObj1Wrap,colObj0Wrap,partId1,index1 );
 		
 		
-//		cp.m_combinedRestitution=colObj0Wrap->getCollisionObject()->getRestitution() * colObj1Wrap->getCollisionObject()->getRestitution();
+//		cp.m_combinedRestitution=0;
 		
 		
-//		cp.m_combinedFriction=0;
+//		cp.m_combinedFriction=1;
 		
 		
 		return false;
 		return false;
 	}
 	}
@@ -21,6 +23,8 @@ namespace bbBullet{
 
 
 	void createInternalEdgeInfo( btBvhTriangleMeshShape *mesh ){
 	void createInternalEdgeInfo( btBvhTriangleMeshShape *mesh ){
 	
 	
+		printf( "create internal edge info!\n" );fflush( stdout );
+		
 		// enable callback
 		// enable callback
 		gContactAddedCallback=CustomMaterialCombinerCallback;
 		gContactAddedCallback=CustomMaterialCombinerCallback;
 
 

+ 26 - 0
modules/mojo3d/components/rigidbody.monkey2

@@ -58,6 +58,12 @@ Class RigidBody Extends Component
 		Local inertia:btVector3=collider?.CalculateLocalInertia( _mass )
 		Local inertia:btVector3=collider?.CalculateLocalInertia( _mass )
 		
 		
 		_btbody=New btRigidBody( _mass,_btmotion,collider?.Validate(),inertia )
 		_btbody=New btRigidBody( _mass,_btmotion,collider?.Validate(),inertia )
+
+'		If Cast<MeshCollider>( collider )
+'			_btbody.setCollisionFlags( _btbody.getCollisionFlags() | btCollisionObject.CF_CUSTOM_MATERIAL_CALLBACK )
+'		Else
+'			_btbody.setCollisionFlags( _btbody.getCollisionFlags() & ~btCollisionObject.CF_CUSTOM_MATERIAL_CALLBACK )
+'		Endif
 		
 		
 		Restitution=0
 		Restitution=0
 		RollingFriction=0
 		RollingFriction=0
@@ -194,31 +200,43 @@ Class RigidBody Extends Component
 	Method ApplyForce( force:Vec3f )
 	Method ApplyForce( force:Vec3f )
 		
 		
 		_btbody.applyCentralForce( force )
 		_btbody.applyCentralForce( force )
+		
+		_btbody.forceActivationState( ACTIVE_TAG )
 	End
 	End
 	
 	
 	Method ApplyForce( force:Vec3f,offset:Vec3f )
 	Method ApplyForce( force:Vec3f,offset:Vec3f )
 		
 		
 		_btbody.applyForce( force,offset )
 		_btbody.applyForce( force,offset )
+		
+		_btbody.forceActivationState( ACTIVE_TAG )
 	End
 	End
 	
 	
 	Method ApplyImpulse( impulse:Vec3f )
 	Method ApplyImpulse( impulse:Vec3f )
 		
 		
 		_btbody.applyCentralImpulse( impulse )
 		_btbody.applyCentralImpulse( impulse )
+		
+		_btbody.forceActivationState( ACTIVE_TAG )
 	End
 	End
 	
 	
 	Method ApplyImpulse( impulse:Vec3f,offset:Vec3f )
 	Method ApplyImpulse( impulse:Vec3f,offset:Vec3f )
 		
 		
 		_btbody.applyForce( impulse,offset )
 		_btbody.applyForce( impulse,offset )
+		
+		_btbody.forceActivationState( ACTIVE_TAG )
 	End
 	End
 	
 	
 	Method ApplyTorque( torque:Vec3f )
 	Method ApplyTorque( torque:Vec3f )
 		
 		
 		_btbody.applyTorque( torque )
 		_btbody.applyTorque( torque )
+		
+		_btbody.forceActivationState( ACTIVE_TAG )
 	End
 	End
 		
 		
 	Method ApplyTorqueImpulse( torque:Vec3f )
 	Method ApplyTorqueImpulse( torque:Vec3f )
 
 
 		_btbody.applyTorqueImpulse( torque )
 		_btbody.applyTorqueImpulse( torque )
+		
+		_btbody.forceActivationState( ACTIVE_TAG )
 	End
 	End
 	
 	
 	Protected
 	Protected
@@ -307,6 +325,14 @@ Class RigidBody Extends Component
 			Local collider:=Entity.Collider
 			Local collider:=Entity.Collider
 			
 			
 			_btbody.setCollisionShape( collider?.Validate() )
 			_btbody.setCollisionShape( collider?.Validate() )
+
+'			_btbody.setCollisionFlags( _btbody.getCollisionFlags() | btCollisionObject.CF_KINEMATIC_OBJECT )
+			
+'			If Cast<MeshCollider>( collider )
+'				_btbody.setCollisionFlags( _btbody.getCollisionFlags() | btCollisionObject.CF_CUSTOM_MATERIAL_CALLBACK )
+'			Else
+'				_btbody.setCollisionFlags( _btbody.getCollisionFlags() & ~btCollisionObject.CF_CUSTOM_MATERIAL_CALLBACK )
+'			Endif
 			
 			
 			Local inertia:btVector3=collider?.CalculateLocalInertia( _mass )
 			Local inertia:btVector3=collider?.CalculateLocalInertia( _mass )
 			
 			

+ 95 - 37
modules/mojo3d/entities/camera.monkey2

@@ -11,8 +11,19 @@ Class Camera Extends Entity
 		Super.New( parent )
 		Super.New( parent )
 		
 		
 		Viewport=New Recti( 0,0,640,480 )
 		Viewport=New Recti( 0,0,640,480 )
-		Near=1
-		Far=1000
+		Near=.1
+		Far=100
+		FOV=90
+		
+		Visible=True
+	End
+	
+	Method New( view:View,parent:Entity=Null )
+		Super.New( parent )
+		
+		View=view
+		Near=.1
+		Far=100
 		FOV=90
 		FOV=90
 		
 		
 		Visible=True
 		Visible=True
@@ -28,8 +39,27 @@ Class Camera Extends Entity
 		
 		
 		Return copy
 		Return copy
 	End
 	End
+	
+	#rem monkeydoc View camera is tracking.
+	#end
+	Property View:View()
+		
+		Return _view
+	
+	Setter( view:View )
+		
+		_view=view
+		
+		If _view SetViewport( _view.Rect )
+		
+	End
 
 
-	#rem monkeydoc @hidden
+	#rem monkeydoc Viewport.
+	
+	If [[View]] is non-null, this property will automatically track the view's rect.
+		
+	This property can only be modified if View is null.
+		
 	#end	
 	#end	
 	Property Viewport:Recti()
 	Property Viewport:Recti()
 		
 		
@@ -37,11 +67,9 @@ Class Camera Extends Entity
 		
 		
 	Setter( viewport:Recti )
 	Setter( viewport:Recti )
 		
 		
-		_viewport=viewport
-
-		_aspect=Float( _viewport.Width )/Float( _viewport.Height )
+		Assert( Not _view,"Viewport cannot be manually modified for a camera with view" )
 		
 		
-		'_dirty|=Dirty.ProjMatrix
+		SetViewport( viewport )
 	End
 	End
 	
 	
 	#rem monkeydoc Aspect ratio.
 	#rem monkeydoc Aspect ratio.
@@ -61,54 +89,58 @@ Class Camera Extends Entity
 	#end
 	#end
 	Property FOV:Float()
 	Property FOV:Float()
 	
 	
-		Return _fovy
+		Return _fov
 		
 		
-	Setter( fovy:Float )
-	
-		_fovy=fovy
+	Setter( fov:Float )
+		
+		_fov=fov
 		
 		
-		'_dirty|=Dirty.ProjMatrix
+		_dirty|=Dirty.ProjMatrix
 	End
 	End
 	
 	
 	#rem monkeydoc Near clip plane distance.
 	#rem monkeydoc Near clip plane distance.
 	
 	
-	Defaults to 1.0.
+	Defaults to 0.1 (10 cenitimetres).
+		
+	The ratio of Far/Near clip planes should be kept as low as possible to reduce numerical precision errors.
 	
 	
 	#end
 	#end
 	Property Near:Float()
 	Property Near:Float()
 	
 	
 		Return _near
 		Return _near
 	
 	
-	Setter( nearz:Float )
-	
-		_near=nearz
+	Setter( near:Float )
+		
+		_near=near
 		
 		
-		'_dirty|=Dirty.ProjMatrix
+		_dirty|=Dirty.ProjMatrix
 	End
 	End
 	
 	
 	#rem monkeydoc Far clip plane distance.
 	#rem monkeydoc Far clip plane distance.
 	
 	
-	Defaults to 1000.0.
+	Defaults to 100.0 (100 metres).
+	
+	The ratio of Far/Near clip planes should be kept as low as possible to reduce numerical precision errors.
 	
 	
 	#end
 	#end
 	Property Far:Float()
 	Property Far:Float()
 	
 	
-		Return _farz
-	
-	Setter( farz:Float )
+		Return _far
 	
 	
-		_farz=farz
+	Setter( far:Float )
+		
+		_far=far
 		
 		
-		'_dirty|=Dirty.ProjMatrix
+		_dirty|=Dirty.ProjMatrix
 	End
 	End
 	
 	
-	#rem monkeydoc @hidden
+	#rem monkeydoc The projection matrix.
 	#end	
 	#end	
 	Property ProjectionMatrix:Mat4f()
 	Property ProjectionMatrix:Mat4f()
 	
 	
 		If _dirty & Dirty.ProjMatrix
 		If _dirty & Dirty.ProjMatrix
 			
 			
-			_projMatrix=Mat4f.Perspective( _fovy,_aspect,_near,_farz )
+			_projMatrix=Mat4f.Perspective( _fov,_aspect,_near,_far )
 		
 		
 			_dirty&=~Dirty.ProjMatrix
 			_dirty&=~Dirty.ProjMatrix
 		Endif
 		Endif
@@ -122,6 +154,25 @@ Class Camera Extends Entity
 		_dirty&=~Dirty.ProjMatrix
 		_dirty&=~Dirty.ProjMatrix
 	End
 	End
 	
 	
+	#rem monkeydoc Renders the camera to a canvas.
+	#end
+	Method Render( canvas:Canvas )
+		
+		If _view SetViewport( _view.Rect )
+		
+		Local target:=canvas.GraphicsDevice.RenderTarget
+		
+		Local targetSize:=canvas.GraphicsDevice.RenderTargetSize
+		
+		Local viewport:=canvas.RenderBounds
+		
+		canvas.Flush()
+		
+		Local renderer:=Renderer.GetCurrent()
+		
+		renderer.Render( target,targetSize,viewport,Scene,InverseMatrix,ProjectionMatrix,Near,Far )
+	End
+	
 	#rem monkeydoc Converts a point from world coordinates to viewport coordinates.
 	#rem monkeydoc Converts a point from world coordinates to viewport coordinates.
 	#end
 	#end
 	Method ProjectToViewport:Vec2f( worldVertex:Vec3f )
 	Method ProjectToViewport:Vec2f( worldVertex:Vec3f )
@@ -171,6 +222,8 @@ Class Camera Extends Entity
 
 
 		If App.ActiveWindow mouse.y=App.ActiveWindow.Height-mouse.y
 		If App.ActiveWindow mouse.y=App.ActiveWindow.Height-mouse.y
 			
 			
+		If _view mouse=_view.TransformWindowPointToView( mouse )
+			
 		mouse.x-=Viewport.min.x
 		mouse.x-=Viewport.min.x
 		mouse.y-=Viewport.min.y
 		mouse.y-=Viewport.min.y
 		
 		
@@ -203,19 +256,24 @@ Class Camera Extends Entity
 	Enum Dirty
 	Enum Dirty
 		ProjMatrix=1
 		ProjMatrix=1
 	End
 	End
-	
-	Field _viewport:=New Recti( 0,0,640,480 )
-	
+
+	Field _view:View	
+	Field _viewport:Recti
 	Field _aspect:Float
 	Field _aspect:Float
-	
-	Field _fovy:Float
-	
+	Field _fov:Float
 	Field _near:Float
 	Field _near:Float
-	
-	Field _farz:Float
-	
-	Field _dirty:Dirty=Dirty.ProjMatrix
-	
+	Field _far:Float
 	Field _projMatrix:Mat4f
 	Field _projMatrix:Mat4f
-	
+	Field _dirty:Dirty=Dirty.ProjMatrix
+
+	Method SetViewport( viewport:Recti )
+		
+		If viewport=_viewport Return
+			
+		_viewport=viewport
+
+		_aspect=Float( _viewport.Width )/Float( _viewport.Height )
+		
+		_dirty|=Dirty.ProjMatrix
+	End
 End
 End

+ 1 - 1
modules/mojo3d/entities/particlebuffer.monkey2

@@ -154,7 +154,7 @@ Class ParticleBuffer
 
 
 		Endif
 		Endif
 		
 		
-		rq.AddSpriteOp( material,_uniforms,instance,_vbuffer,Null,1,_length,0 )
+		rq.AddRenderOp( material,_uniforms,instance,_vbuffer,Null,1,_length,0 )
 	End		
 	End		
 	
 	
 	Private
 	Private

+ 17 - 6
modules/mojo3d/entities/particlematerial.monkey2

@@ -9,11 +9,6 @@ Class ParticleMaterial Extends Material
 	#end	
 	#end	
 	Method New()
 	Method New()
 
 
-		Local shader:="material-particle"
-		Local defs:=Renderer.GetCurrent().ShaderDefs
-			
-		SetShader( Shader.Open( shader,defs ) )
-		
 		BlendMode=BlendMode.Additive
 		BlendMode=BlendMode.Additive
 		CullMode=CullMode.None
 		CullMode=CullMode.None
 		
 		
@@ -22,7 +17,6 @@ Class ParticleMaterial Extends Material
 		Gravity=New Vec3f( 0,-9.81,0 )
 		Gravity=New Vec3f( 0,-9.81,0 )
 		Duration=10.0
 		Duration=10.0
 		Fade=0.0
 		Fade=0.0
-		
 	End
 	End
 	
 	
 	Method New( material:ParticleMaterial )
 	Method New( material:ParticleMaterial )
@@ -37,6 +31,23 @@ Class ParticleMaterial Extends Material
 		Return New ParticleMaterial( Self )
 		Return New ParticleMaterial( Self )
 	End
 	End
 	
 	
+	Method GetTransparentShader:Shader() Override
+		
+		Global _shader:Shader
+		
+		If Not _shader
+			
+			Local shader:="material-particle"
+			Local defs:=Renderer.GetCurrent().ShaderDefs
+				
+			_shader=Shader.Open( shader,defs )
+		
+		Endif
+		
+		Return _shader
+		
+	End
+	
 	Property ColorTexture:Texture()
 	Property ColorTexture:Texture()
 		
 		
 		Return Uniforms.GetTexture( "ColorTexture" )
 		Return Uniforms.GetTexture( "ColorTexture" )

+ 1 - 2
modules/mojo3d/entities/sprite.monkey2

@@ -108,8 +108,7 @@ Class Sprite Extends Renderable
 	End
 	End
 	
 	
 	Method OnRender( rq:RenderQueue ) Override
 	Method OnRender( rq:RenderQueue ) Override
-	
-		rq.AddSprite( Self )
+		rq.AddSpriteOp( Self )
 	End
 	End
 	
 	
 	Private
 	Private

+ 5 - 2
modules/mojo3d/loader/gltf2.monkey2

@@ -71,10 +71,9 @@ Class Gltf2Material
 	Field metallicRoughnessTexture:Gltf2Texture
 	Field metallicRoughnessTexture:Gltf2Texture
 	Field metallicFactor:Float=1
 	Field metallicFactor:Float=1
 	Field roughnessFactor:Float=1
 	Field roughnessFactor:Float=1
-	Field occlusionTexture:Gltf2Texture
-	Field occlusionFactor:Vec3f=New Vec3f(1)
 	Field emissiveTexture:Gltf2Texture
 	Field emissiveTexture:Gltf2Texture
 	Field emissiveFactor:Vec3f=New Vec3f(0)
 	Field emissiveFactor:Vec3f=New Vec3f(0)
+	Field occlusionTexture:Gltf2Texture
 	Field normalTexture:Gltf2Texture
 	Field normalTexture:Gltf2Texture
 End
 End
 
 
@@ -412,6 +411,10 @@ Class Gltf2Asset
 			If jarr
 			If jarr
 				material.emissiveFactor=GetVec3f( jarr )
 				material.emissiveFactor=GetVec3f( jarr )
 			Endif
 			Endif
+			jobj=jmaterial.GetObject( "occlusionTexture" )
+			If jobj
+				material.occlusionTexture=textures[jobj.GetNumber( "index" )]
+			Endif
 			jobj=jmaterial.GetObject( "normalTexture" )
 			jobj=jmaterial.GetObject( "normalTexture" )
 			If jobj
 			If jobj
 				material.normalTexture=textures[jobj.GetNumber( "index" )]
 				material.normalTexture=textures[jobj.GetNumber( "index" )]

+ 23 - 10
modules/mojo3d/loader/gltf2loader.monkey2

@@ -166,17 +166,17 @@ Class Gltf2Loader
 		
 		
 		If _materialCache.Contains( material ) Return _materialCache[material]
 		If _materialCache.Contains( material ) Return _materialCache[material]
 		
 		
-		Local colorTexture:Texture
+		Local baseColorTexture:Texture
 		Local metallicRoughnessTexture:Texture
 		Local metallicRoughnessTexture:Texture
-		Local occlusionTexture:Texture
 		Local emissiveTexture:Texture
 		Local emissiveTexture:Texture
+		Local occlusionTexture:Texture
 		Local normalTexture:Texture
 		Local normalTexture:Texture
 		
 		
 		If textured
 		If textured
-			colorTexture=GetTexture( material.baseColorTexture )
+			baseColorTexture=GetTexture( material.baseColorTexture )
 			metallicRoughnessTexture=GetTexture( material.metallicRoughnessTexture )
 			metallicRoughnessTexture=GetTexture( material.metallicRoughnessTexture )
-			occlusionTexture=GetTexture( material.occlusionTexture )
 			emissiveTexture=GetTexture( material.emissiveTexture )
 			emissiveTexture=GetTexture( material.emissiveTexture )
+			occlusionTexture=GetTexture( material.occlusionTexture )
 			normalTexture=GetTexture( material.normalTexture )
 			normalTexture=GetTexture( material.normalTexture )
 		Endif
 		Endif
 			
 			
@@ -184,13 +184,17 @@ Class Gltf2Loader
 		
 		
 		mat.Uniforms.LinearColors=True
 		mat.Uniforms.LinearColors=True
 		
 		
-		mat.ColorFactor=New Color( material.baseColorFactor.x,material.baseColorFactor.y,material.baseColorFactor.z )
+		If baseColorTexture mat.ColorTexture=baseColorTexture
+		mat.ColorFactor=New Color( material.baseColorFactor )
+			
+		If metallicRoughnessTexture
+			mat.MetalnessTexture=metallicRoughnessTexture
+			mat.RoughnessTexture=metallicRoughnessTexture
+		Endif
+		
 		mat.MetalnessFactor=material.metallicFactor
 		mat.MetalnessFactor=material.metallicFactor
 		mat.RoughnessFactor=material.roughnessFactor
 		mat.RoughnessFactor=material.roughnessFactor
 
 
-		If colorTexture mat.ColorTexture=colorTexture
-		If metallicRoughnessTexture mat.MetalnessTexture=metallicRoughnessTexture ; mat.RoughnessTexture=metallicRoughnessTexture
-		If occlusionTexture mat.OcclusionTexture=occlusionTexture
 		If emissiveTexture 
 		If emissiveTexture 
 			mat.EmissiveTexture=emissiveTexture
 			mat.EmissiveTexture=emissiveTexture
  			If material.emissiveFactor<>Null
  			If material.emissiveFactor<>Null
@@ -202,7 +206,9 @@ Class Gltf2Loader
 			mat.EmissiveTexture=Texture.ColorTexture( Color.White )
 			mat.EmissiveTexture=Texture.ColorTexture( Color.White )
 			mat.EmissiveFactor=New Color( material.emissiveFactor.x,material.emissiveFactor.y,material.emissiveFactor.z )
 			mat.EmissiveFactor=New Color( material.emissiveFactor.x,material.emissiveFactor.y,material.emissiveFactor.z )
 		Endif
 		Endif
-		
+
+		If occlusionTexture mat.OcclusionTexture=occlusionTexture
+			
 		If normalTexture mat.NormalTexture=normalTexture
 		If normalTexture mat.NormalTexture=normalTexture
 			
 			
 		_materialCache[material]=mat
 		_materialCache[material]=mat
@@ -350,7 +356,13 @@ Class Gltf2Loader
 			Next
 			Next
 		Endif
 		Endif
 		
 		
-		Return New Mesh( vertices,indices )
+		Local mesh:=New Mesh( vertices,indices )
+		
+		If prim.TEXCOORD_0 And prim.NORMAL
+			mesh.UpdateTangents()
+		Endif
+		
+		Return mesh
 	End
 	End
 	
 	
 	Method LoadMesh( node:Gltf2Node,mesh:Mesh,materials:Stack<Material> )
 	Method LoadMesh( node:Gltf2Node,mesh:Mesh,materials:Stack<Material> )
@@ -708,6 +720,7 @@ Class Gltf2Mojo3dLoader Extends Mojo3dLoader
 		Case ".glb"
 		Case ".glb"
 			
 			
 			Local stream:=Stream.Open( path,"r" )
 			Local stream:=Stream.Open( path,"r" )
+			If Not stream Return Null
 			
 			
 			Local json:=""
 			Local json:=""
 				
 				

+ 3 - 4
modules/mojo3d/mojo3d.monkey2

@@ -29,8 +29,6 @@ Using bullet..
 #Import "entities/renderable"
 #Import "entities/renderable"
 #Import "entities/sprite"
 #Import "entities/sprite"
 
 
-#Import "render/deferredrenderer"
-#Import "render/forwardrenderer"
 #Import "render/material"
 #Import "render/material"
 #Import "render/renderer"
 #Import "render/renderer"
 #Import "render/renderqueue"
 #Import "render/renderqueue"
@@ -41,9 +39,8 @@ Using bullet..
 #Import "render/materials/spritematerial"
 #Import "render/materials/spritematerial"
 #Import "render/materials/watermaterial"
 #Import "render/materials/watermaterial"
 
 
-#Import "render/effects/fogeffect"
-#Import "render/effects/monochromeeffect"
 #Import "render/effects/bloomeffect"
 #Import "render/effects/bloomeffect"
+#Import "render/effects/monochromeeffect"
 
 
 #Import "scene/raycastresult"
 #Import "scene/raycastresult"
 #Import "scene/component"
 #Import "scene/component"
@@ -86,5 +83,7 @@ Function Main()
 	SetConfig( "MOJO_DEPTH_BUFFER_BITS",16 )
 	SetConfig( "MOJO_DEPTH_BUFFER_BITS",16 )
 	
 	
 #endif
 #endif
+
+	SetConfig( "MOJO_DEPTH_BUFFER_BITS",16 )
 	
 	
 End
 End

+ 0 - 253
modules/mojo3d/render/deferredrenderer.monkey2

@@ -1,253 +0,0 @@
-
-Namespace mojo3d
-
-#rem
-
-Material render passes:
-
-1 : opaque ambient
-
-4 : opaque shadow depth
-
-#end
-
-#rem monkeydoc The DeferredRenderer class.
-#end
-Class DeferredRenderer Extends Renderer
-
-	#rem monkeydoc Creates a deferred renderer.
-	#end
-	Method New()
-
-		Print "Creating DeferredRenderer"
-		
-		Super.Init( True )
-	
-		_lightShader=Shader.Open( "lighting-deferred",ShaderDefs )
-		
-		_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
-		
-			_hdrTexture?.Discard()
-			_colorTexture?.Discard()
-			_normalTexture?.Discard()
-			_depthTexture?.Discard()
-			_rpass0Target?.Discard()
-			_rpass2Target?.Discard()
-		
-			'look at this again later - surely we can rgba32f on some mobile targets, eg: nvidia shield?
-			#If Not __MOBILE_TARGET__
-			Const color_format:=PixelFormat.RGBA32F
-			Const depth_format:=PixelFormat.Depth32
-			#Else
-			Const color_format:=PixelFormat.RGBA8
-			Const depth_format:=PixelFormat.Depth32
-			#Endif
-				
-			_hdrTexture=New Texture( size.x,size.y,color_format,TextureFlags.Filter|TextureFlags.Dynamic )		'output hdr image
-			_colorTexture=New Texture( size.x,size.y,color_format,TextureFlags.Filter|TextureFlags.Dynamic )		'metalness in 'a'
-			_normalTexture=New Texture( size.x,size.y,color_format,TextureFlags.Filter|TextureFlags.Dynamic )		'roughness in 'a'
-			_depthTexture=New Texture( size.x,size.y,depth_format,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 ) )
-		
-		'directional with shadows
-		For Local light:=Eachin scene.Lights
-			If light.Type<>LightType.Directional Or Not light.CastsShadow Continue
-			
-			RenderLight( light,camera )
-		Next
-		
-		'point with shadows (not supported yet)
-		For Local light:=Eachin scene.Lights
-			If light.Type<>LightType.Point Or Not light.CastsShadow Continue
-			
-			RenderLight( light,camera )
-		Next
-		
-		'directional without  shadows
-		For Local light:=Eachin scene.Lights
-			If light.Type<>LightType.Directional Or light.CastsShadow Continue
-
-			RenderLight( light,camera )
-		Next
-		
-		'point without shadows
-		For Local light:=Eachin scene.Lights
-			If light.Type<>LightType.Point Or light.CastsShadow Continue
-
-			RenderLight( light,camera )
-		Next
-		
-		_device.RenderTarget=_rpass0Target
-		
-		RenderTransparent()
-		
-		RenderSprites()
-
-		_device.RenderTarget=_rpass2Target
-
-		RenderEffects( scene )
-		
-		_device.RenderTarget=_renderTarget
-		_device.Resize( _renderTargetSize )
-		_device.Viewport=_renderViewport
-		_device.Scissor=_device.Viewport
-
-		RenderCopy()
-	End
-		
-	Private
-	
-	Field _lightShader: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=0
-
-		Super.RenderOpaqueOps()
-	End
-	
-	Method RenderTransparent()
-		
-		_device.ColorMask=ColorMask.All
-		_device.DepthMask=True'false
-		_device.DepthFunc=DepthFunc.LessEqual
-		_device.RenderPass=0
-
-		Super.RenderTransparentOps()
-	End
-	
-	Method RenderSprites()
-		
-		_device.ColorMask=ColorMask.All
-		_device.DepthMask=True'False
-		_device.DepthFunc=DepthFunc.LessEqual
-		_device.RenderPass=0
-		
-		Super.RenderSpriteOps()
-	End
-	
-	Method RenderLight( light:Light,camera:Camera )
-		
-		Local pass:=0
-		
-		Select light.Type
-		Case LightType.Directional
-			If light.CastsShadow RenderCSMShadows( light ) ; pass|=2
-		Case LightType.Point
-			If light.CastsShadow RenderPointShadows( light ) ; pass|=2
-			pass|=1
-		End
-	
-		_runiforms.SetColor( "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.Shader=_lightShader
-		_device.RenderPass=pass
-		
-		RenderQuad()
-	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

+ 0 - 241
modules/mojo3d/render/forwardrenderer.monkey2

@@ -1,241 +0,0 @@
-
-Namespace mojo3d
-
-#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 Creates a forward renderer.
-	
-	If the config setting "MOJO3D\_FORWARD\_RENDERER\_DIRECT" is set to "1", the renderer will render directly to the render target when [[Render]] is invoked.
-
-	Config settings may be set using the [[std::std.filesystem.SetConfig|SetConfig]] function.
-
-	#end
-	Method New()
-		
-		_direct=Int( GetConfig( "MOJO3D_FORWARD_RENDERER_DIRECT" ) )
-
-		Print "Creating ForwardRenderer, direct="+_direct
-			
-		Super.Init( Not _direct )
-		
-		If Not _direct _copyShader=Shader.Open( "copy" )
-	End
-	
-	Protected
-	
-	Method OnValidateSize( size:Vec2i ) Override 
-		
-		If _direct Return
-
-		If Not _colorBuffer Or size.x>_colorBuffer.Size.x Or size.y>_colorBuffer.Size.y
-			
-			_colorBuffer?.Discard()
-			_depthBuffer?.Discard() 
-			_colorTarget0?.Discard()
-			_colorTarget1?.Discard()
-
-			'look again at this - surely we can rgb32f on some mobile target?
-			#If Not __MOBILE_TARGET__
-			Const color_format:=PixelFormat.RGBA32F
-			Const depth_format:=PixelFormat.Depth32
-			#Else
-			Const color_format:=PixelFormat.RGBA8
-			Const depth_format:=PixelFormat.Depth32
-			#Endif
-				
-			_colorBuffer=New Texture( size.x,size.y,color_format,TextureFlags.Dynamic|TextureFlags.Filter )
-			_depthBuffer=New Texture( size.x,size.y,depth_format,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 Not _direct
-			_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()
-		
-		_ambientRendered=False
-		
-		For Local light:=Eachin scene.Lights
-			If light.Type<>LightType.Directional Or Not light.CastsShadow Continue
-			
-			RenderOpaque( light,camera )
-		Next
-		
-		For Local light:=Eachin scene.Lights
-			If light.Type<>LightType.Point Or Not light.CastsShadow Continue
-			
-			RenderOpaque( light,camera )
-		Next
-		
-		For Local light:=Eachin scene.Lights
-			If light.Type<>LightType.Directional Or light.CastsShadow Continue
-			
-			RenderOpaque( light,camera )
-		Next
-		
-		For Local light:=Eachin scene.Lights
-			If light.Type<>LightType.Point Or light.CastsShadow Continue
-			
-			RenderOpaque( light,camera )
-		Next
-		
-		If Not _ambientRendered
-			
-			RenderOpaque( Null,camera )
-		Endif
-		
-		RenderSprites()
-		
-		If Not _direct
-		
-			_device.RenderTarget=_colorTarget1
-			RenderEffects( scene )
-
-			_device.RenderTarget=_renderTarget
-			_device.Resize( _renderTargetSize )
-			_device.Viewport=_renderViewport
-			_device.Scissor=_device.Viewport
-			RenderCopy()
-		Endif
-		
-	End
-	
-	Private
-	
-	Field _direct: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
-	
-	Field _ambientRendered:Bool
-	
-	Method RenderOpaque( light:Light,camera:Camera )
-		
-		Local pass:Int=_ambientRendered ? 0 Else 1
-		
-		If light
-			Select light.Type
-			Case LightType.Directional			
-				if light.CastsShadow RenderCSMShadows( light ) ; pass|=4
-			Case LightType.Point
-				if light.CastsShadow RenderPointShadows( light ) ; pass|=4
-				pass|=8
-			End
-			_runiforms.SetColor( "LightColor",light.Color )
-			_runiforms.SetFloat( "LightRange",light.Range )
-			_runiforms.SetMat4f( "LightViewMatrix",camera.InverseMatrix * light.Matrix )
-			pass|=2
-		Endif
-		
-		_device.ColorMask=ColorMask.All
-		_device.DepthMask=True
-		_device.DepthFunc=DepthFunc.LessEqual
-		_device.BlendMode=_ambientRendered ? BlendMode.Additive Else BlendMode.Opaque
-		_device.RenderPass=pass
-		
-		Super.RenderOpaqueOps()
-		
-		_ambientRendered=True
-	End
-	
-	Method RenderSprites()
-
-		_device.ColorMask=ColorMask.All
-		_device.DepthMask=True'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

+ 29 - 43
modules/mojo3d/render/material.monkey2

@@ -5,35 +5,10 @@ Namespace mojo3d
 #end
 #end
 Class Material Extends Resource
 Class Material Extends Resource
 	
 	
-	Method New()
-
-		_shader=Null	
-		_uniforms=New UniformBlock( 3,True )
-		_blendMode=BlendMode.Opaque
-		_cullMode=CullMode.Back
-		
-		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.
 	#rem monkeydoc Creates a copy of the material.
 	#end
 	#end
 	Method Copy:Material() abstract
 	Method Copy:Material() abstract
 	
 	
-	#rem monkeydoc The material shader.
-	#end
-	Property Shader:Shader()
-		
-		Return _shader
-	End
-	
 	#Rem monkeydoc @hidden The material uniforms.
 	#Rem monkeydoc @hidden The material uniforms.
 	
 	
 	TODO: Should really be protected...
 	TODO: Should really be protected...
@@ -43,7 +18,7 @@ Class Material Extends Resource
 	
 	
 		Return _uniforms
 		Return _uniforms
 	End
 	End
-
+	
 	#Rem monkeydoc The material blendmode.
 	#Rem monkeydoc The material blendmode.
 	#End
 	#End
 	Property BlendMode:BlendMode()
 	Property BlendMode:BlendMode()
@@ -107,36 +82,48 @@ Class Material Extends Resource
 		
 		
 		TextureMatrix=TextureMatrix.Scale( sx,sy )
 		TextureMatrix=TextureMatrix.Scale( sx,sy )
 	End
 	End
+
+	#rem monkeydoc Gets material's opaque shader.
+	#end
+	Method GetOpaqueShader:Shader() Virtual
 	
 	
-	Method ValidateShader:Shader()
-		
-		If Not _shader _shader=OnValidateShader()
-			
-		Return _shader
+		Return Null
 	End
 	End
-
-	Protected
 	
 	
-	Method OnValidateShader:Shader() Virtual
-		
-		RuntimeError( "Material.OnValidateShader unimplemented" )
+	#rem monkeydoc Gets material's transparent shader.
+	#end
+	Method GetTransparentShader:Shader() Virtual
 		
 		
 		Return Null
 		Return Null
 	End
 	End
 	
 	
-	Method InvalidateShader()
+	#rem monkeydoc Gets material's sprite shader.
+	#end
+	Method GetSpriteShader:Shader() Virtual
 		
 		
-		_shader=Null
+		Return GetTransparentShader()
 	End
 	End
 	
 	
-	Method SetShader( shader:Shader )
-		
-		_shader=shader
+	#rem monkeydoc Gets material's shadow shader.
+	#end
+	Method GetShadowShader:Shader() Virtual
+	
+		Return GetOpaqueShader()
 	End
 	End
 	
 	
+	Protected
+	
+	Method New()
+
+		_uniforms=New UniformBlock( 3,True )
+		_blendMode=BlendMode.Opaque
+		_cullMode=CullMode.Back
+		
+		TextureMatrix=New AffineMat3f
+	End		
+	
 	Method New( material:Material )
 	Method New( material:Material )
 
 
-		_shader=material._shader
 		_uniforms=New UniformBlock( material._uniforms )
 		_uniforms=New UniformBlock( material._uniforms )
 
 
 		_blendMode=material._blendMode
 		_blendMode=material._blendMode
@@ -147,7 +134,6 @@ Class Material Extends Resource
 	
 	
 	Private
 	Private
 
 
-	Field _shader:Shader
 	Field _uniforms:UniformBlock
 	Field _uniforms:UniformBlock
 	Field _blendMode:BlendMode
 	Field _blendMode:BlendMode
 	Field _cullMode:CullMode
 	Field _cullMode:CullMode

+ 49 - 17
modules/mojo3d/render/materials/pbrmaterial.monkey2

@@ -60,11 +60,11 @@ Class PbrMaterial Extends Material
 		
 		
 		ColorFactor=Color.White
 		ColorFactor=Color.White
 		EmissiveFactor=Color.Black
 		EmissiveFactor=Color.Black
-		MetalnessFactor=0.0
+		MetalnessFactor=1.0
 		RoughnessFactor=1.0
 		RoughnessFactor=1.0
 	End
 	End
 	
 	
-	Method New( color:Color,metalness:Float=0.0,roughness:Float=1.0,boned:Bool=False )
+	Method New( color:Color,metalness:Float=1.0,roughness:Float=1.0,boned:Bool=False )
 		Self.New( boned )
 		Self.New( boned )
 		
 		
 		ColorFactor=color
 		ColorFactor=color
@@ -87,6 +87,20 @@ Class PbrMaterial Extends Material
 		Return New PbrMaterial( Self )
 		Return New PbrMaterial( Self )
 	End
 	End
 	
 	
+	Method GetOpaqueShader:Shader() Override
+		
+		ValidateShaders()
+		
+		Return _opaqueShader
+	End
+	
+	Method GetTransparentShader:Shader() Override
+		
+		ValidateShaders()
+		
+		Return _transparentShader
+	End
+	
 	'***** textures *****
 	'***** textures *****
 	
 	
 	Property ColorTexture:Texture()
 	Property ColorTexture:Texture()
@@ -97,7 +111,7 @@ Class PbrMaterial Extends Material
 	
 	
 		Uniforms.SetTexture( "ColorTexture",texture )
 		Uniforms.SetTexture( "ColorTexture",texture )
 		
 		
-		If (Uniforms.NumTextures<>0)<>_textured InvalidateShader()
+		If (Uniforms.NumTextures<>0)<>_textured _dirty=True
 	End
 	End
 	
 	
 	Property EmissiveTexture:Texture()
 	Property EmissiveTexture:Texture()
@@ -108,7 +122,7 @@ Class PbrMaterial Extends Material
 	
 	
 		Uniforms.SetTexture( "EmissiveTexture",texture )
 		Uniforms.SetTexture( "EmissiveTexture",texture )
 		
 		
-		If (Uniforms.NumTextures<>0)<>_textured InvalidateShader()
+		If (Uniforms.NumTextures<>0)<>_textured _dirty=True
 	End
 	End
 	
 	
 	Property MetalnessTexture:Texture()
 	Property MetalnessTexture:Texture()
@@ -119,7 +133,7 @@ Class PbrMaterial Extends Material
 	
 	
 		Uniforms.SetTexture( "MetalnessTexture",texture )
 		Uniforms.SetTexture( "MetalnessTexture",texture )
 		
 		
-		If (Uniforms.NumTextures<>0)<>_textured InvalidateShader()
+		If (Uniforms.NumTextures<>0)<>_textured _dirty=true
 	End
 	End
 
 
 	Property RoughnessTexture:Texture()
 	Property RoughnessTexture:Texture()
@@ -130,7 +144,7 @@ Class PbrMaterial Extends Material
 	
 	
 		Uniforms.SetTexture( "RoughnessTexture",texture )
 		Uniforms.SetTexture( "RoughnessTexture",texture )
 		
 		
-		If (Uniforms.NumTextures<>0)<>_textured InvalidateShader()
+		If (Uniforms.NumTextures<>0)<>_textured _dirty=true
 	End
 	End
 	
 	
 	Property OcclusionTexture:Texture()
 	Property OcclusionTexture:Texture()
@@ -141,7 +155,7 @@ Class PbrMaterial Extends Material
 	
 	
 		Uniforms.SetTexture( "OcclusionTexture",texture )
 		Uniforms.SetTexture( "OcclusionTexture",texture )
 		
 		
-		If (Uniforms.NumTextures<>0)<>_textured InvalidateShader()
+		If (Uniforms.NumTextures<>0)<>_textured _dirty=true
 	End
 	End
 	
 	
 	Property NormalTexture:Texture()
 	Property NormalTexture:Texture()
@@ -152,7 +166,7 @@ Class PbrMaterial Extends Material
 	
 	
 		Uniforms.SetTexture( "NormalTexture",texture )
 		Uniforms.SetTexture( "NormalTexture",texture )
 		
 		
-		If (texture<>null)<>_bumpmapped InvalidateShader()
+		If (texture<>null)<>_bumpmapped _dirty=true
 	End
 	End
 	
 	
 	'***** factors *****
 	'***** factors *****
@@ -237,7 +251,7 @@ Class PbrMaterial Extends Material
 		Endif
 		Endif
 		
 		
 		texture=Texture.Load( path+"/normal.png",textureFlags )
 		texture=Texture.Load( path+"/normal.png",textureFlags )
-'		If Not texture texture=Texture.Load( path+"/unormal.png",textureFlags|TextureFlags.InvertGreen )
+		If Not texture texture=Texture.Load( path+"/unormal.png",textureFlags,True )
 		If texture
 		If texture
 			material.NormalTexture=texture
 			material.NormalTexture=texture
 		Endif
 		Endif
@@ -259,7 +273,15 @@ Class PbrMaterial Extends Material
 	Field _bumpmapped:Bool
 	Field _bumpmapped:Bool
 	Field _boned:Bool
 	Field _boned:Bool
 	
 	
-	Method OnValidateShader:Shader() Override
+	Field _opaqueShader:Shader
+	Field _transparentShader:Shader
+	Field _shadowShader:Shader
+	
+	Field _dirty:=True
+	
+	Method ValidateShaders()
+		
+		If Not _dirty Return
 		
 		
 		_textured=True'False
 		_textured=True'False
 		_bumpmapped=False
 		_bumpmapped=False
@@ -269,9 +291,7 @@ Class PbrMaterial Extends Material
 			_bumpmapped=(Uniforms.GetTexture( "NormalTexture" )<>null)
 			_bumpmapped=(Uniforms.GetTexture( "NormalTexture" )<>null)
 		Endif
 		Endif
 		
 		
-		Local renderer:=Renderer.GetCurrent()
-
-		Local defs:=renderer.ShaderDefs
+		Local defs:=Renderer.GetCurrent().ShaderDefs
 		
 		
 		If _textured
 		If _textured
 			defs+="MX2_TEXTURED~n"
 			defs+="MX2_TEXTURED~n"
@@ -279,13 +299,25 @@ Class PbrMaterial Extends Material
 				defs+="MX2_BUMPMAPPED~n"
 				defs+="MX2_BUMPMAPPED~n"
 			Endif
 			Endif
 		Endif
 		Endif
+		
 		If _boned defs+="MX2_BONED~n"
 		If _boned defs+="MX2_BONED~n"
 			
 			
-		Local shader:="material-pbr-deferred"
-		If Cast<ForwardRenderer>( renderer ) shader="material-pbr-forward"
+		_transparentShader=Shader.Open( "material-pbr-forward",defs )
+		
+		If Renderer.GetCurrent().Deferred
+			
+			_opaqueShader=Shader.Open( "material-pbr-deferred",defs )
+		
+		Else
+			
+			_opaqueShader=_transparentShader
 			
 			
-		Return Shader.Open( shader,defs )
+		Endif
+		
+		_shadowShader=_opaqueShader
+		
+		_dirty=False
+		
 	End
 	End
 	
 	
-	
 End
 End

+ 31 - 5
modules/mojo3d/render/materials/spritematerial.monkey2

@@ -9,11 +9,6 @@ Class SpriteMaterial Extends Material
 	#end	
 	#end	
 	Method New()
 	Method New()
 		
 		
-		Local shader:="material-sprite"
-		Local defs:=Renderer.GetCurrent().ShaderDefs
-			
-		SetShader( Shader.Open( shader,defs ) )
-		
 		BlendMode=BlendMode.Alpha
 		BlendMode=BlendMode.Alpha
 		CullMode=CullMode.None
 		CullMode=CullMode.None
 		
 		
@@ -35,6 +30,37 @@ Class SpriteMaterial Extends Material
 		Return New SpriteMaterial( Self )
 		Return New SpriteMaterial( Self )
 	End
 	End
 	
 	
+	Method GetOpaqueShader:Shader() Override
+		
+		Global _shader:Shader
+		
+		If Not _shader
+			
+			Local shader:="material-sprite"
+			
+			Local defs:=Renderer.GetCurrent().ShaderDefs
+				
+			_shader=Shader.Open( shader,defs )
+		Endif
+		
+		Return _shader
+	End
+	
+	Method GetTransparentShader:Shader() Override
+		
+		Return GetOpaqueShader()
+	End
+	
+	Method GetSpriteShader:Shader() Override
+		
+		Return GetOpaqueShader()
+	End
+	
+	Method GetShadowShader:Shader() Override
+		
+		Return GetOpaqueShader()
+	End
+	
 	Property ColorTexture:Texture()
 	Property ColorTexture:Texture()
 		
 		
 		Return Uniforms.GetTexture( "ColorTexture" )
 		Return Uniforms.GetTexture( "ColorTexture" )

+ 14 - 3
modules/mojo3d/render/materials/watermaterial.monkey2

@@ -8,9 +8,6 @@ Class WaterMaterial Extends Material
 	#rem monkeydoc Creates a new water material.
 	#rem monkeydoc Creates a new water material.
 	#end
 	#end
 	Method New()
 	Method New()
-		Assert( Cast<DeferredRenderer>( Renderer.GetCurrent() ),"Water material requires deferred renderer" )
-		
-		SetShader( Shader.Open( "material-water" ) )
 		
 		
 		ColorTexture=Texture.ColorTexture( Color.White )
 		ColorTexture=Texture.ColorTexture( Color.White )
 		ColorFactor=Color.SeaGreen
 		ColorFactor=Color.SeaGreen
@@ -37,6 +34,20 @@ Class WaterMaterial Extends Material
 		Return New WaterMaterial( Self )
 		Return New WaterMaterial( Self )
 	End
 	End
 	
 	
+	Method GetOpaqueShader:Shader() Override
+		
+		Global _shader:=Shader.Open( "material-water" )
+		
+		Assert( _shader )
+
+		Return _shader
+	End
+	
+	Method GetShadowShader:Shader() Override
+		
+		Return Null
+	End
+	
 	Property ColorTexture:Texture()
 	Property ColorTexture:Texture()
 		
 		
 		Return Uniforms.GetTexture( "ColorTexture" )
 		Return Uniforms.GetTexture( "ColorTexture" )

+ 697 - 386
modules/mojo3d/render/renderer.monkey2

@@ -1,13 +1,63 @@
 
 
 Namespace mojo3d
 Namespace mojo3d
 
 
-#rem monkeydoc The Renderer class.
-#end
 Class Renderer
 Class Renderer
+
+	#rem monkeydoc Creates a new renderer
+	#end
+	Method New()
+		
+		If Not _current _current=Self
+		
+		_direct=False
+		_deferred=False
+		
+		Select GetConfig( "MOJO3D_RENDERER" )
+		Case "deferred"
+			
+			_deferred=True
+			
+		Case "forward"
+			
+			_deferred=False
+		
+		Default
+			
+#If __DESKTOP_TARGET__ Or __WEB_TARGET__
+
+			_deferred=True
+#else
+
+			_deferred=False
+#endif
+		End
+		
+		Print "GL_VERSION="+opengl.glGetString( opengl.GL_VERSION )
+		
+		If _deferred
+			Print "Renderer is using deferred rendering"
+		Else
+			Print "Renderer is using forward rendering"
+		Endif
+	End
+	
+	#rem monkeydoc True if renderer is using deferred rendering.
+	#end
+	Property Deferred:Bool()
+		
+		Return _deferred
+	End
+
+	#rem monkeydoc @hidden
+	#end
+	Property ShaderDefs:String()
+		
+		Return "MX2_LINEAROUTPUT=1~n"'MX2_RGBADEPTHTEXTURES=1~n"
+	End
 	
 	
 	#rem monkeydoc Size of the cascaded shadow map texture.
 	#rem monkeydoc Size of the cascaded shadow map texture.
 	
 	
-	Must be a power of 2 size. Defaults to 1024.
+	Must be a power of 2 size. Defaults to 2048.
 	
 	
 	#end
 	#end
 	Property CSMTextureSize:Int()
 	Property CSMTextureSize:Int()
@@ -19,29 +69,10 @@ Class Renderer
 		
 		
 		_csmSize=size
 		_csmSize=size
 	End
 	End
-	
-	#rem monkeydoc Array containing the cascaded shadow map frustum splits for directional light shadows.
-	
-	Defaults to Float[]( 8.0,16.0,64.0,256.0 )
-	
-	Must have length 3.
-		
-	#end
-	Property CSMSplits:Float[]()
-		
-		Return _csmSplits
-		
-	Setter( splits:Float[] )
-		Assert( splits.Length=4,"CSMSplits array must have 4 elements" )
-		
-		_csmSplits=splits.Slice( 0 )
-	End
-	
+
 	#rem monkeydoc Size of the cube texture used for point light shadow mapping.
 	#rem monkeydoc Size of the cube texture used for point light shadow mapping.
 	
 	
-	Must be a power of 2.
-	
-	Defaults to 1024.
+	Must be a power of 2. Defaults to 2048.
 		
 		
 	#end
 	#end
 	Property PSMTextureSize:Int()
 	Property PSMTextureSize:Int()
@@ -54,314 +85,276 @@ Class Renderer
 		_psmSize=size
 		_psmSize=size
 	End
 	End
 	
 	
-'	Function SetCurrent( renderer:Renderer )
-		
-'		DebugAssert( Not _current,"Renderer.Current already set" )
-		
-'		_current=renderer
-'	End
-	
 	#rem monkeydoc Gets the current renderer.
 	#rem monkeydoc Gets the current renderer.
 	
 	
-	The config setting "MOJO3D\_DEFAULT\_RENDERER" can be used to override the default renderer created. It should be set to "deferred" or "forward".
-
-	Config settings may be changed using the [[std::std.filesystem.SetConfig|SetConfig]] function.
-	
+	If there is no current renderer and new renderer is created.
+		
 	#end
 	#end
 	Function GetCurrent:Renderer()
 	Function GetCurrent:Renderer()
 		
 		
-		If Not _current
-			
-			Select( GetConfig( "MOJO3D_DEFAULT_RENDERER" ) )
-			Case "deferred"
-				_current=New DeferredRenderer
-			Case "forward"
-				_current=New ForwardRenderer
-			Default
-	#If Not __MOBILE_TARGET__					
-				_current=New DeferredRenderer
-	#else
-				_current=New ForwardRenderer
-	#Endif
-			End
-		Endif
-		
+		If Not _current New Renderer
+			
 		Return _current
 		Return _current
 	End
 	End
 	
 	
-	#rem monkeydoc @hidden DON'T USE! WILL CHANGE!
-	#end
-	Method Render( scene:Scene,canvas:Canvas )
+	Method Render( target:RenderTarget,targetSize:Vec2i,viewport:Recti,scene:Scene,viewMatrix:AffineMat4f,projMatrix:Mat4f,near:Float,far:Float ) Virtual
 		
 		
-		Local viewport:=canvas.Viewport
+		Init()
 		
 		
-		For Local camera:=Eachin scene.Cameras
-			
-			canvas.Viewport=camera.Viewport
-			
-			canvas.Flush()
-			
-			Render( scene,camera,canvas.GraphicsDevice )
-		Next
+		ValidateCSMShadows()
 		
 		
-		canvas.Viewport=viewport
-	End
-	
-	
-	#rem monkeydoc @hidden DON'T USE! WILL CHANGE!
-	#end
-	Method Render( scene:Scene,camera:Camera,device:GraphicsDevice ) Virtual
+		ValidatePSMShadows()
+		
+		SetOutputRenderTarget( target,targetSize,viewport )
 
 
-		'***** validate stuff *****
-			
-		Local size:=device.Viewport.Size
-		size.x=Max( size.x,1920 )
-		size.y=Max( size.y,1080 )
+		SetScene( scene )
 		
 		
-		OnValidateSize( size )
+		SetCamera( viewMatrix,projMatrix,near,far )
 		
 		
-		ValidateShadowMaps()
+		RenderBackground()
 		
 		
-		_csmSplitDepths[0]=camera.Near
-		For Local i:=1 Until 5
-			_csmSplitDepths[i]=Min( _csmSplitDepths[i-1]+_csmSplits[i-1],camera.Far )
-		Next
+		RenderOpaque()
 		
 		
-		Local time:=Float( Now() )
-
-		_runiforms.SetFloat( "Time",time )
+		RenderTransparent()
 		
 		
-		_runiforms.SetTexture( "ShadowCSMTexture",_csmTexture )
-		_runiforms.SetVec4f( "ShadowCSMSplits",New Vec4f( _csmSplitDepths[1],_csmSplitDepths[2],_csmSplitDepths[3],_csmSplitDepths[4] ) )
-
-		_runiforms.SetTexture( "ShadowCubeTexture",_psmTexture )
+'		RenderSprites()
 		
 		
-		'***** Set render scene *****
+		RenderPostEffects()
 		
 		
-		_renderScene=scene
-
-		_runiforms.SetTexture( "SkyTexture",_renderScene.SkyTexture )
-		_runiforms.SetColor( "ClearColor",_renderScene.ClearColor )
-		_runiforms.SetColor( "AmbientDiffuse",_renderScene.AmbientLight )
+		RenderCopy()
+	End
 	
 	
-		Local env:Texture
+	Method RenderBackground()
+	
+		If _scene.SkyTexture
 		
 		
-		If _renderScene.EnvTexture
-			env=_renderScene.EnvTexture
-		ElseIf _renderScene.SkyTexture
-			env=_renderScene.SkyTexture
+			_gdevice.ColorMask=ColorMask.None
+			_gdevice.DepthMask=True
+			
+			_gdevice.Clear( Null,1.0 )
+			
+			_gdevice.ColorMask=ColorMask.All
+			_gdevice.DepthMask=False
+			_gdevice.DepthFunc=DepthFunc.Always
+			_gdevice.BlendMode=BlendMode.Opaque
+			_gdevice.CullMode=CullMode.None
+			_gdevice.Shader=_skyboxShader
+			_gdevice.RenderPass=0
+			
+			RenderQuad()
 		Else
 		Else
-			env=_defaultEnv
+			_gdevice.ColorMask=ColorMask.All
+			_gdevice.DepthMask=True
+			
+			Local color:=_scene.ClearColor
+			color.r=Pow( color.r,2.2 )
+			color.g=Pow( color.g,2.2 )
+			color.b=Pow( color.b,2.2 )
+		
+			_gdevice.Clear( color,1.0 )
+
 		Endif
 		Endif
+	End
+	
+	Method RenderDeferredLighting( light:Light )
 		
 		
-		_runiforms.SetTexture( "EnvTexture",env )
-		_runiforms.SetFloat( "EnvTextureMaxLod",Log2( env.Size.x ) )
-		_runiforms.SetColor( "EnvColor",_renderScene.EnvColor )
+		Local renderPass:=2
 		
 		
-		_renderQueue.Clear()
+		Select light.Type
+		Case LightType.Directional
+			If light.CastsShadow RenderCSMShadows( light ) ; renderPass|=4
+		Case LightType.Point
+			If light.CastsShadow RenderPSMShadows( light ) ; renderPass|=4
+			renderPass|=8
+		End
 		
 		
-		_renderQueue.Time=time
+		_runiforms.SetColor( "LightColor",light.Color )
+		_runiforms.SetFloat( "LightRange",light.Range )
+		_runiforms.SetMat4f( "LightViewMatrix",_viewMatrix * light.Matrix )
 		
 		
-		For Local r:=Eachin _renderScene.Renderables
+		_runiforms.SetMat4f( "InverseProjectionMatrix",_invProjMatrix )
 		
 		
-			_renderQueue.CastsShadow=r.CastsShadow
-			
-			r.OnRender( _renderQueue )
-		Next
+		_gdevice.ColorMask=ColorMask.All
+		_gdevice.DepthMask=False
+		_gdevice.DepthFunc=DepthFunc.Always
+		_gdevice.BlendMode=BlendMode.Additive
+		_gdevice.RenderPass=renderPass
 		
 		
-		Local ops:=_renderQueue.OpaqueOps
-
-#rem		
-		ops.Sort( Lambda:Int( x:RenderOp,y:RenderOp )
-			If x.instance<y.instance Return -1
-			If x.instance>y.instance Return 1
-			If x.material<y.material Return -1
-			If x.material>y.material Return 1
-			If x<y Return -1
-			If x>y Return 1
-			Return 0
-		End )
-#end
+		_gdevice.Shader=_deferredLightingShader
+		_gdevice.CullMode=CullMode.None
 		
 		
-		'***** Set render camera *****
-
-		_renderCamera=camera
-
-		Local envMat:=_renderCamera.Matrix.m
-		Local viewMat:=_renderCamera.InverseMatrix
-		Local projMat:=_renderCamera.ProjectionMatrix
-		Local invProjMat:=-projMat
-			
-		_runiforms.SetMat3f( "EnvMatrix",envMat )
-		_runiforms.SetMat4f( "ProjectionMatrix",projMat )
-		_runiforms.SetMat4f( "InverseProjectionMatrix",invProjMat )
-		_runiforms.SetMat4f( "ViewMatrix",_renderCamera.InverseMatrix )
-		_runiforms.SetMat4f( "CameraMatrix",_renderCamera.Matrix )
-		_runiforms.SetFloat( "DepthNear",_renderCamera.Near )
-		_runiforms.SetFloat( "DepthFar",_renderCamera.Far )
+		_gdevice.RenderTarget=_renderTarget1
 		
 		
-		_spriteBuffer.AddSprites( _renderQueue,_renderCamera )
+		RenderQuad()
 		
 		
-		OnRender( scene,camera,device )
+		_gdevice.RenderTarget=_renderTarget0
+	End
+	
+	Method RenderOpaqueDeferred()
+
+		_gdevice.ColorMask=ColorMask.All
+		_gdevice.DepthMask=True
+		_gdevice.DepthFunc=DepthFunc.LessEqual
+		_gdevice.BlendMode=BlendMode.Opaque
+		_gdevice.RenderPass=1
 		
 		
-		_renderCamera=Null
+		RenderOpaqueOps()
 		
 		
-		_renderScene=Null
-	End	
-	
-	Property ShaderDefs:String()
+		For Local light:=Eachin _scene.Lights
+			
+			RenderDeferredLighting( light )
+		Next
 		
 		
-		Return _linearOutput ? "MX2_LINEAROUTPUT~n" Else "MX2_SRGBOUTPUT~n"
-	End
-	
-	Protected
-	
-	Method OnValidateSize( size:Vec2i ) Virtual
-	End
-	
-	Method OnRender( scene:Scene,camera:Camera,device:GraphicsDevice ) Virtual
 	End
 	End
 	
 	
-	Method New()
+	Method RenderOpaqueForward()
 		
 		
-		_current=Self
-	End
-	
-	Method Init( linearOutput:Bool )
+		Local first:=True
 		
 		
-		_linearOutput=linearOutput
+		For Local light:=Eachin _scene.Lights
+			
+			Local renderPass:=first ? 3 Else 2
+			
+			Select light.Type
+			Case LightType.Directional			
+				If light.CastsShadow RenderCSMShadows( light ) ; renderPass|=4
+			Case LightType.Point
+				If light.CastsShadow RenderPSMShadows( light ) ; renderPass|=4
+				renderPass|=8
+			End
+			
+			_runiforms.SetColor( "LightColor",light.Color )
+			_runiforms.SetFloat( "LightRange",light.Range )
+			_runiforms.SetMat4f( "LightViewMatrix",_viewMatrix * light.Matrix )
 
 
-		_rgbaDepthTextures=False
+			_gdevice.ColorMask=ColorMask.All
+			_gdevice.DepthMask=first
+			_gdevice.DepthFunc=DepthFunc.LessEqual
+			_gdevice.BlendMode=first ? BlendMode.Opaque Else BlendMode.Additive
+			_gdevice.RenderPass=renderPass
+			
+			RenderOpaqueOps()
+			
+			first=False
+		Next
 		
 		
-		_device=New GraphicsDevice( 0,0 )
+		If first
+			_gdevice.ColorMask=ColorMask.All
+			_gdevice.DepthMask=True
+			_gdevice.DepthFunc=DepthFunc.LessEqual
+			_gdevice.BlendMode=BlendMode.Opaque
+			_gdevice.RenderPass=1
+			
+			RenderOpaqueOps()
+		Endif
 		
 		
-		_runiforms=New UniformBlock( 1,True )
-		_iuniforms=New UniformBlock( 2,True )
+	End
+	
+	Method RenderDeferredFog()
 		
 		
-		_device.BindUniformBlock( _runiforms )
-		_device.BindUniformBlock( _iuniforms )
-
-		_defaultEnv=Texture.Load( "asset::textures/env_default.jpg",TextureFlags.FilterMipmap|TextureFlags.Cubemap )
+		If _scene.FogColor.a=0 Return
 		
 		
-		_skyboxShader=Shader.Open( "skybox",_shaderDefs )
+		_gdevice.ColorMask=ColorMask.All
+		_gdevice.DepthMask=False
+		_gdevice.DepthFunc=DepthFunc.Always
+		_gdevice.BlendMode=BlendMode.Alpha
+		_gdevice.RenderPass=0
 		
 		
-		_psmFaceTransforms=New Mat3f[]( 
-			New Mat3f(  0,0,+1, 0,-1,0, -1, 0,0 ),	'+X
-			New Mat3f(  0,0,-1, 0,-1,0, +1, 0,0 ),	'-X
-			New Mat3f( +1,0, 0, 0,0,+1,  0,+1,0 ),	'+Y
-			New Mat3f( +1,0, 0, 0,0,-1,  0,-1,0 ),	'-Y
-			New Mat3f( +1,0, 0, 0,-1,0,  0,0,+1 ),	'+Z
-			New Mat3f( -1,0, 0, 0,-1,0,  0,0,-1 ) )	'-Z
-	
-	End
+		_gdevice.RenderTarget=_renderTarget1
+		_gdevice.Shader=_deferredFogShader
+		_gdevice.CullMode=CullMode.None
+		
+		RenderQuad()
 
 
-	Property Device:GraphicsDevice()
-	
-		Return _device
+		_gdevice.RenderTarget=_renderTarget0
 	End
 	End
 	
 	
-	Property RenderUniforms:UniformBlock()
-	
-		Return _runiforms
-	End
-	
-	Method RenderQuad()
-
-		Global _vertices:VertexBuffer
+	Method RenderOpaque()
 		
 		
-		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 ) ) )
+		If _deferred 
+			RenderOpaqueDeferred()
+			RenderDeferredFog()
+		Else 
+			RenderOpaqueForward()
 		Endif
 		Endif
-			
-		_device.VertexBuffer=_vertices
-		_device.Render( 4,1 )
 	End
 	End
 
 
-	Method RenderBackground()
-	
-		If _renderScene.SkyTexture
+	Method RenderTransparent()
+
+		Local first:=True
 		
 		
-			_device.ColorMask=ColorMask.None
-			_device.DepthMask=True
+		For Local light:=Eachin _scene.Lights
 			
 			
-			_device.Clear( Null,1.0 )
+			Local renderPass:=first ? 3 Else 2	'amgient+light or just light
 			
 			
-			_device.ColorMask=ColorMask.All
-			_device.DepthMask=False
-			_device.DepthFunc=DepthFunc.Always
-			_device.BlendMode=BlendMode.Opaque
-			_device.CullMode=CullMode.None
-			_device.Shader=_skyboxShader
-			_device.RenderPass=0
+			Select light.Type
+			Case LightType.Directional			
+	'			If light.CastsShadow RenderCSMShadows( light ) ; renderPass|=4
+			Case LightType.Point
+	'			If light.CastsShadow RenderPSMShadows( light ) ; renderPass|=4
+				renderPass|=8
+			End
 			
 			
-			RenderQuad()
+			_runiforms.SetColor( "LightColor",light.Color )
+			_runiforms.SetFloat( "LightRange",light.Range )
+			_runiforms.SetMat4f( "LightViewMatrix",_viewMatrix * light.Matrix )
 			
 			
-		Else
-			_device.ColorMask=ColorMask.All
-			_device.DepthMask=True
-			
-			Local color:=_renderScene.ClearColor
-			If _linearOutput
-				color.r=Pow( color.r,2.2 )
-				color.g=Pow( color.g,2.2 )
-				color.b=Pow( color.b,2.2 )
-			Endif
+			_gdevice.ColorMask=ColorMask.All
+			_gdevice.DepthMask=False
+			_gdevice.DepthFunc=DepthFunc.LessEqual
+			_gdevice.RenderPass=renderPass
+			
+			RenderTransparentOps()
+			
+			first=False
+			
+			Exit
+		Next
 		
 		
-			_device.Clear( color,1.0 )
-
+		If first
+			_gdevice.ColorMask=ColorMask.All
+			_gdevice.DepthMask=False
+			_gdevice.DepthFunc=DepthFunc.LessEqual
+			_gdevice.RenderPass=1
+			
+			RenderTransparentOps()
 		Endif
 		Endif
 		
 		
 	End
 	End
 	
 	
-	Method RenderOpaqueOps()
-
-		RenderRenderOps( _renderQueue.OpaqueOps,_renderCamera.InverseMatrix,_renderCamera.ProjectionMatrix )
-	End
-	
-	Method RenderTransparentOps()
-		
-		RenderRenderOps( _renderQueue.TransparentOps,_renderCamera.InverseMatrix,_renderCamera.ProjectionMatrix )
-	End
-
-	Method RenderSpriteOps()
-
-		RenderRenderOps( _renderQueue.SpriteOps,_renderCamera.InverseMatrix,_renderCamera.ProjectionMatrix )
-	End
-	
 	Method RenderCSMShadows( light:Light )
 	Method RenderCSMShadows( light:Light )
 		
 		
 		'Perhaps use a different device for CSM...?
 		'Perhaps use a different device for CSM...?
 		'
 		'
-		Local t_rtarget:=_device.RenderTarget
-		Local t_viewport:=_device.Viewport
-		Local t_scissor:=_device.Scissor
-
-		_device.RenderTarget=_csmTarget
-		_device.Viewport=New Recti( 0,0,_csmTarget.Size )
-		_device.Scissor=_device.Viewport
-		_device.ColorMask=ColorMask.All
-		_device.DepthMask=True
-		_device.Clear( Color.White,1.0 )
-		
-		_device.DepthFunc=DepthFunc.LessEqual
-		_device.BlendMode=BlendMode.Opaque
-		_device.CullMode=CullMode.Front	'CullMode.Back
-		_device.RenderPass=16
+		Local t_rtarget:=_gdevice.RenderTarget
+		Local t_viewport:=_gdevice.Viewport
+		Local t_scissor:=_gdevice.Scissor
+
+		_gdevice.RenderTarget=_csmTarget
+		_gdevice.Viewport=New Recti( 0,0,_csmTexture.Size )
+		_gdevice.Scissor=_gdevice.Viewport
+		_gdevice.ColorMask=ColorMask.All
+		_gdevice.DepthMask=True
+		
+		_gdevice.Clear( Color.White,1.0 )
+		
+		_gdevice.DepthFunc=DepthFunc.LessEqual
+		_gdevice.BlendMode=BlendMode.Opaque
+		_gdevice.CullMode=CullMode.Front
+		_gdevice.RenderPass=4
 
 
 		Local invLightMatrix:=light.InverseMatrix
 		Local invLightMatrix:=light.InverseMatrix
 		
 		
-		Local viewLight:=invLightMatrix * _renderCamera.Matrix
+		Local viewLight:=invLightMatrix * -_viewMatrix
 		
 		
 		For Local i:=0 Until _csmSplitDepths.Length-1
 		For Local i:=0 Until _csmSplitDepths.Length-1
 			
 			
 			Local znear:=_csmSplitDepths[i]
 			Local znear:=_csmSplitDepths[i]
 			Local zfar:=_csmSplitDepths[i+1]
 			Local zfar:=_csmSplitDepths[i+1]
-			
-			Local splitProj:=Mat4f.Perspective( _renderCamera.FOV,_renderCamera.Aspect,znear,zfar )
+
+			Local splitProj:=_projMatrix
+			splitProj.k.z=(zfar+znear)/(zfar-znear)
+			splitProj.t.z=-(zfar*znear*2)/(zfar-znear)
 						
 						
 			Local invSplitProj:=-splitProj
 			Local invSplitProj:=-splitProj
 			
 			
@@ -388,143 +381,150 @@ Class Renderer
 			Local size:=_csmTexture.Size,hsize:=size/2
 			Local size:=_csmTexture.Size,hsize:=size/2
 			
 			
 			Select i
 			Select i
-			Case 0 _device.Viewport=New Recti( 0,0,hsize.x,hsize.y )
-			Case 1 _device.Viewport=New Recti( hsize.x,0,size.x,hsize.y )
-			Case 2 _device.Viewport=New Recti( 0,hsize.y,hsize.x,size.y )
-			Case 3 _device.Viewport=New Recti( hsize.x,hsize.y,size.x,size.y )
+			Case 0 _gdevice.Viewport=New Recti( 0,0,hsize.x,hsize.y )
+			Case 1 _gdevice.Viewport=New Recti( hsize.x,0,size.x,hsize.y )
+			Case 2 _gdevice.Viewport=New Recti( 0,hsize.y,hsize.x,size.y )
+			Case 3 _gdevice.Viewport=New Recti( hsize.x,hsize.y,size.x,size.y )
 			End
 			End
 			
 			
-			_device.Scissor=_device.Viewport
+			_gdevice.Scissor=_gdevice.Viewport
 				
 				
-			RenderShadowOps( _renderQueue.ShadowOps,invLightMatrix,lightProj )
-			
+			RenderShadowOps( invLightMatrix,lightProj )
 		Next
 		Next
 		
 		
-		_device.RenderTarget=t_rtarget
-		_device.Viewport=t_viewport
-		_device.Scissor=t_scissor
+		_gdevice.RenderTarget=t_rtarget
+		_gdevice.Viewport=t_viewport
+		_gdevice.Scissor=t_scissor
 	End
 	End
-
-	Method RenderPointShadows( light:Light )
+	
+	Method RenderPSMShadows( light:Light )
 	
 	
 		'Perhaps use a different device for CSM...?
 		'Perhaps use a different device for CSM...?
 		'
 		'
-		Local t_rtarget:=_device.RenderTarget
-		Local t_viewport:=_device.Viewport
-		Local t_scissor:=_device.Scissor
+		Local t_rtarget:=_gdevice.RenderTarget
+		Local t_viewport:=_gdevice.Viewport
+		Local t_scissor:=_gdevice.Scissor
+		
+		_gdevice.Viewport=New Recti( 0,0,_psmTexture.Size )
+		_gdevice.Scissor=_gdevice.Viewport
+		_gdevice.ColorMask=ColorMask.All
+		_gdevice.DepthMask=True
 		
 		
-		_device.Viewport=New Recti( 0,0,_psmTexture.Size )
-		_device.Scissor=_device.Viewport
-		_device.ColorMask=ColorMask.All
-		_device.DepthMask=True
+		_gdevice.DepthFunc=DepthFunc.LessEqual
+		_gdevice.BlendMode=BlendMode.Opaque
+		_gdevice.CullMode=CullMode.Back'Front
+		_gdevice.RenderPass=12
 		
 		
-		_device.DepthFunc=DepthFunc.LessEqual
-		_device.BlendMode=BlendMode.Opaque
-		_device.CullMode=CullMode.Front
-		_device.RenderPass=17
+		Local lnear:=0.1
 		
 		
-		Local lightProj:=Mat4f.Frustum( -1,+1,-1,+1,1,light.Range )
+		Local lightProj:=Mat4f.Frustum( -lnear,+lnear,-lnear,+lnear,lnear,light.Range )
 		
 		
 		Local invLightMatrix:=light.InverseMatrix
 		Local invLightMatrix:=light.InverseMatrix
 		
 		
-		Local viewLight:=invLightMatrix * _renderCamera.Matrix
+		Local viewLight:=invLightMatrix * _invViewMatrix
 		
 		
 		_runiforms.SetFloat( "LightRange",light.Range )
 		_runiforms.SetFloat( "LightRange",light.Range )
 		_runiforms.SetMat4f( "ShadowMatrix0",viewLight )
 		_runiforms.SetMat4f( "ShadowMatrix0",viewLight )
 		
 		
 		For Local i:=0 Until 6
 		For Local i:=0 Until 6
 			
 			
-			_device.RenderTarget=_psmTargets[i]
-			_device.Clear( Color.White,1.0 )
+			_gdevice.RenderTarget=_psmTargets[i]
+			
+			_gdevice.Clear( Color.White,1.0 )
 			
 			
 			Local viewMatrix:=New AffineMat4f( _psmFaceTransforms[i] ) * invLightMatrix
 			Local viewMatrix:=New AffineMat4f( _psmFaceTransforms[i] ) * invLightMatrix
 
 
-			RenderShadowOps( _renderQueue.ShadowOps,viewMatrix,lightProj )
-			
+			RenderShadowOps( viewMatrix,lightProj )
 		Next
 		Next
 
 
-		_device.RenderTarget=t_rtarget
-		_device.Viewport=t_viewport
-		_device.Scissor=t_scissor
+		_gdevice.RenderTarget=t_rtarget
+		_gdevice.Viewport=t_viewport
+		_gdevice.Scissor=t_scissor
 	End
 	End
-
-	Private
-	
-	Global _current:Renderer
-	
-	Field _rgbaDepthTextures:=False
 	
 	
-	Field _shaderDefs:String
-	
-	Field _linearOutput:bool
-	
-	Field _device:GraphicsDevice
-	Field _runiforms:UniformBlock
-	Field _iuniforms:UniformBlock
+	Method RenderPostEffects()
+		
+		_gdevice.ColorMask=ColorMask.All
+		_gdevice.DepthMask=False
+		_gdevice.DepthFunc=DepthFunc.Always
+		_gdevice.CullMode=CullMode.None
 
 
-	Field _skyboxShader:Shader
-	
-	Field _psmFaceTransforms:Mat3f[]
-	
-	Field _csmSize:=4096
-	Field _csmSplits:=New Float[]( 8.0,16.0,64.0,256.0 )
-	Field _csmSplitDepths:=New Float[5]
-	Field _csmTexture:Texture
-	Field _csmDepth:Texture
-	Field _csmTarget:RenderTarget
+		For Local effect:=Eachin _scene.PostEffects
+			
+			If Not effect.Enabled Continue
+			
+			_gdevice.BlendMode=BlendMode.Opaque
+			_gdevice.RenderPass=0
+			
+			effect.Render( _gdevice )
+		Next
+		
+	End
 	
 	
-	Field _psmSize:=2048
-	Field _psmTexture:Texture
-	Field _psmDepth:Texture
-	Field _psmTargets:=New RenderTarget[6]
+	Method RenderCopy()
+		
+		If _direct Return
+		
+		_gdevice.RenderTarget=_outputRenderTarget
+		_gdevice.Resize( _outputRenderTargetSize )
+		_gdevice.Viewport=_outputViewport
+		_gdevice.Scissor=_outputViewport
 
 
-	Field _defaultEnv:Texture
-	
-	Field _renderQueue:=New RenderQueue
-	Field _spriteQueue:=New RenderQueue
-	Field _spriteBuffer:=New SpriteBuffer
-	
-	Field _renderScene:Scene
-	Field _renderCamera:Camera
-	
-	Method ValidateShadowMaps()
+		_gdevice.ColorMask=ColorMask.All
+		_gdevice.DepthMask=False
+		_gdevice.DepthFunc=DepthFunc.Always
+		_gdevice.BlendMode=BlendMode.Opaque
+		_gdevice.CullMode=CullMode.None
+		_gdevice.Shader=_copyShader
+		_gdevice.RenderPass=0
 		
 		
-		If Not _csmTexture Or _csmSize<>_csmTexture.Size.x
-			
-			_csmTarget?.Discard()
-			_csmTexture?.Discard()
-			_csmDepth?.Discard()
+		RenderQuad()
+		
+		_gdevice.RenderTarget=Null
+		_gdevice.Resize( Null )
+	End
 
 
-			const depth_format:=PixelFormat.Depth32
-			
-			_csmTexture=New Texture( _csmSize,_csmSize,depth_format,TextureFlags.Dynamic )
-			_csmTarget=New RenderTarget( Null,_csmTexture )
-			_csmDepth=Null
+	Method RenderQuad()
+
+		Global _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
+		_gdevice.VertexBuffer=_vertices
 		
 		
-		If Not _psmTexture Or _psmSize*2>_psmTexture.Size.x
-			
-			_psmTexture?.Discard()
-			_psmDepth?.Discard()
-			For Local i:=0 Until 6
-				_psmTargets[i]?.Discard()
-			Next
-			
-			Local size:=_psmSize*2
+		_gdevice.Render( 4,1 )
+	End
+	
+	Method SortTransparentOps()
+		
+		_renderQueue.TransparentOps.Sort( Lambda:Int( x:RenderOp,y:RenderOp )
+		
+			If y.distance<x.distance Return -1
+			If x.distance<y.distance Return 1
+			Return 0
+		End )
+	End
+	
+	Method SortSpriteOps()
+		
+		_renderQueue.SpriteOps.Sort( Lambda:Int( x:SpriteOp,y:SpriteOp )
+		
+			If y.distance<x.distance Return -1
+			If x.distance<y.distance Return 1
+			Return 0
+		End )
+	End
 
 
-			const color_format:=PixelFormat.RGBA8
-			const depth_format:=PixelFormat.Depth32
-			
-			_psmTexture=New Texture( size,size,color_format,TextureFlags.Cubemap|TextureFlags.Dynamic )
-			_psmDepth=New Texture( size,size,depth_format,TextureFlags.Dynamic )
-			For Local i:=0 Until 6
-				Local face:=_psmTexture.GetCubeFace( Cast<CubeFace>( i ) )
-				_psmTargets[i]=New RenderTarget( New Texture[]( face ),_psmDepth )
-			Next
+	Method RenderOpaqueOps()
 		
 		
-		Endif
+		RenderRenderOps( _renderQueue.OpaqueOps,_viewMatrix,_projMatrix )
+	End
+	
+	Method RenderTransparentOps()
 		
 		
+		RenderRenderOps( _renderQueue.TransparentOps,_viewMatrix,_projMatrix )
 	End
 	End
 
 
 	Method RenderRenderOps( ops:Stack<RenderOp>,viewMatrix:AffineMat4f,projMatrix:Mat4f )
 	Method RenderRenderOps( ops:Stack<RenderOp>,viewMatrix:AffineMat4f,projMatrix:Mat4f )
@@ -536,52 +536,67 @@ Class Renderer
 		_runiforms.SetMat4f( "ViewProjectionMatrix",viewProjMatrix )
 		_runiforms.SetMat4f( "ViewProjectionMatrix",viewProjMatrix )
 		_runiforms.SetMat4f( "InverseProjectionMatrix",-projMatrix )
 		_runiforms.SetMat4f( "InverseProjectionMatrix",-projMatrix )
 		
 		
-		'_iuniforms.SetMat4fArray( "ModelBoneMatrices",Null )
-		
-		Local instance:Entity=_renderCamera
-		Local bones:Mat4f[]
+		Local instance:Entity=Null,first:=True
 		Local material:Material
 		Local material:Material
+		Local bones:Mat4f[]
 		
 		
 		For Local op:=Eachin ops
 		For Local op:=Eachin ops
 			
 			
-			If op.instance<>instance
+			If op.instance<>instance Or first
+				
+				first=False
+				
 				instance=op.instance
 				instance=op.instance
+				
 				Local modelMat:=instance ? instance.Matrix Else New AffineMat4f
 				Local modelMat:=instance ? instance.Matrix Else New AffineMat4f
 				Local modelViewMat:=viewMatrix * modelMat
 				Local modelViewMat:=viewMatrix * modelMat
 				Local modelViewNormMat:=modelViewMat.m.Cofactor()
 				Local modelViewNormMat:=modelViewMat.m.Cofactor()
 				Local modelViewProjMat:=projMatrix * modelViewMat
 				Local modelViewProjMat:=projMatrix * modelViewMat
+				
 				_iuniforms.SetMat4f( "ModelMatrix",modelMat )
 				_iuniforms.SetMat4f( "ModelMatrix",modelMat )
 				_iuniforms.SetMat4f( "ModelViewMatrix",modelViewMat )
 				_iuniforms.SetMat4f( "ModelViewMatrix",modelViewMat )
 				_iuniforms.SetMat3f( "ModelViewNormalMatrix",modelViewNormMat )
 				_iuniforms.SetMat3f( "ModelViewNormalMatrix",modelViewNormMat )
 				_iuniforms.SetMat4f( "ModelViewProjectionMatrix",modelViewProjMat )
 				_iuniforms.SetMat4f( "ModelViewProjectionMatrix",modelViewProjMat )
+				_iuniforms.SetFloat( "Alpha",instance ? instance.Alpha Else 1.0 )
+				
 			Endif
 			Endif
 				
 				
 			If op.bones _iuniforms.SetMat4fArray( "ModelBoneMatrices",op.bones )
 			If op.bones _iuniforms.SetMat4fArray( "ModelBoneMatrices",op.bones )
 				
 				
-			If op.uniforms _device.BindUniformBlock( op.uniforms )
+			If op.uniforms _gdevice.BindUniformBlock( op.uniforms )
 						
 						
 			If op.material<>material
 			If op.material<>material
+				
 				material=op.material
 				material=op.material
-				_device.Shader=material.ValidateShader()
-				_device.BindUniformBlock( material.Uniforms )
-				If material.BlendMode<>BlendMode.Opaque
-					_device.BlendMode=material.BlendMode
+				
+				If op.blendMode=BlendMode.Opaque
+					_gdevice.Shader=material.GetOpaqueShader()
+				Else
+					_gdevice.Shader=material.GetTransparentShader()
 				Endif
 				Endif
-				_device.CullMode=material.CullMode
+				
+				_gdevice.BindUniformBlock( material.Uniforms )
+				_gdevice.CullMode=material.CullMode
+				
 			Endif
 			Endif
+
+			_gdevice.BlendMode=op.blendMode
+			
+			_gdevice.VertexBuffer=op.vbuffer
 			
 			
-			_device.VertexBuffer=op.vbuffer
 			If op.ibuffer
 			If op.ibuffer
-				_device.IndexBuffer=op.ibuffer
-				_device.RenderIndexed( op.order,op.count,op.first )
+				_gdevice.IndexBuffer=op.ibuffer
+				_gdevice.RenderIndexed( op.order,op.count,op.first )
 			Else
 			Else
-				_device.Render( op.order,op.count,op.first )
+				_gdevice.Render( op.order,op.count,op.first )
 			Endif
 			Endif
 			
 			
 		Next
 		Next
 	End
 	End
-
-	Method RenderShadowOps( ops:Stack<RenderOp>,viewMatrix:AffineMat4f,projMatrix:Mat4f )
+	
+	Method RenderShadowOps( viewMatrix:AffineMat4f,projMatrix:Mat4f )
+		
+		Local ops:=_renderQueue.ShadowOps
 		
 		
 		Local viewProjMatrix:=projMatrix * viewMatrix
 		Local viewProjMatrix:=projMatrix * viewMatrix
 		
 		
@@ -590,15 +605,14 @@ Class Renderer
 		_runiforms.SetMat4f( "ViewProjectionMatrix",viewProjMatrix )
 		_runiforms.SetMat4f( "ViewProjectionMatrix",viewProjMatrix )
 		_runiforms.SetMat4f( "InverseProjectionMatrix",-projMatrix )
 		_runiforms.SetMat4f( "InverseProjectionMatrix",-projMatrix )
 		
 		
-		'_iuniforms.SetMat4fArray( "ModelBoneMatrices",Null )
-		
-		Local instance:Entity=_renderCamera
-		Local bones:Mat4f[]
+		Local instance:Entity=Null,first:=True
 		Local material:Material
 		Local material:Material
+		Local bones:Mat4f[]
 		
 		
 		For Local op:=Eachin ops
 		For Local op:=Eachin ops
 			
 			
-			If op.instance<>instance
+			If op.instance<>instance Or first
+				first=False
 				instance=op.instance
 				instance=op.instance
 				Local modelMat:=instance ? instance.Matrix Else New AffineMat4f
 				Local modelMat:=instance ? instance.Matrix Else New AffineMat4f
 				Local modelViewMat:=viewMatrix * modelMat
 				Local modelViewMat:=viewMatrix * modelMat
@@ -612,24 +626,321 @@ Class Renderer
 				
 				
 			If op.bones _iuniforms.SetMat4fArray( "ModelBoneMatrices",op.bones )
 			If op.bones _iuniforms.SetMat4fArray( "ModelBoneMatrices",op.bones )
 			
 			
-			If op.uniforms _device.BindUniformBlock( op.uniforms )
+			If op.uniforms _gdevice.BindUniformBlock( op.uniforms )
 						
 						
 			If op.material<>material
 			If op.material<>material
 				material=op.material
 				material=op.material
-				_device.Shader=material.ValidateShader()
-				_device.BindUniformBlock( material.Uniforms )
+				_gdevice.Shader=material.GetShadowShader()
+				_gdevice.BindUniformBlock( material.Uniforms )
 			Endif
 			Endif
 			
 			
-			_device.VertexBuffer=op.vbuffer
+			_gdevice.VertexBuffer=op.vbuffer
+			
 			If op.ibuffer
 			If op.ibuffer
-				_device.IndexBuffer=op.ibuffer
-				_device.RenderIndexed( op.order,op.count,op.first )
+				_gdevice.IndexBuffer=op.ibuffer
+				_gdevice.RenderIndexed( op.order,op.count,op.first )
 			Else
 			Else
-				_device.Render( op.order,op.count,op.first )
+				_gdevice.Render( op.order,op.count,op.first )
 			Endif
 			Endif
 			
 			
 		Next
 		Next
 
 
 	End
 	End
+	
+	Private
+	
+	Field _direct:Bool=False
+	Field _deferred:Bool=True
+	
+	Field _gdevice:GraphicsDevice
+	
+	Field _runiforms:UniformBlock
+	Field _iuniforms:UniformBlock
+	
+	Field _defaultEnv:Texture
+	
+	Field _skyboxShader:Shader
+	Field _copyShader:Shader
+	
+	Field _deferredLightingShader:Shader
+	Field _deferredFogShader:Shader
+	
+	Field _renderQueue:RenderQueue
+	
+	Field _spriteBuffer:=New SpriteBuffer
+	
+	Field _accumBuffer:Texture
+	Field _colorBuffer:Texture
+	Field _normalBuffer:Texture
+	Field _depthBuffer:Texture
+
+	Field _renderTarget0:RenderTarget	'all buffers
+	Field _renderTarget1:RenderTarget	'accum buffer only
+	
+	Field _csmSize:=2048
+	Field _csmSplits:Float[]
+	Field _csmSplitDepths:=New Float[5]
+	Field _csmTexture:Texture
+	Field _csmDepth:Texture
+	Field _csmTarget:RenderTarget
+
+	Field _psmSize:=2048
+	Field _psmTexture:Texture
+	Field _psmDepth:Texture
+	Field _psmTargets:=New RenderTarget[6]
+	Field _psmFaceTransforms:Mat3f[]
+	
+	Field _outputRenderTarget:RenderTarget
+	Field _outputRenderTargetSize:Vec2i
+	Field _outputViewport:Recti
+	
+	Field _scene:Scene
+	
+	Field _viewMatrix:AffineMat4f
+	Field _projMatrix:Mat4f
+	Field _near:Float
+	Field _far:Float
+	
+	Field _invViewMatrix:AffineMat4f
+	Field _invProjMatrix:Mat4f
+	
+	Field _ambientRendered:Bool
+
+	Global _current:Renderer
+	
+	Method Init()
+		
+		Global inited:Bool
+		If inited Return
+		inited=True
+		
+		_gdevice=New GraphicsDevice( 0,0 )
+		
+		_runiforms=New UniformBlock( 1,True )
+		_iuniforms=New UniformBlock( 2,True )
+		
+		_gdevice.BindUniformBlock( _runiforms )
+		_gdevice.BindUniformBlock( _iuniforms )
+		
+		_defaultEnv=Texture.Load( "asset::textures/env_default.jpg",TextureFlags.FilterMipmap|TextureFlags.Cubemap )
+		
+		_copyShader=Shader.Open( "copy" )
+		
+		If _deferred 
+			_skyboxShader=Shader.Open( "skybox-deferred",ShaderDefs )
+			_deferredLightingShader=Shader.Open( "lighting-deferred",ShaderDefs )
+			_deferredFogShader=Shader.Open( "fog-deferred",ShaderDefs )
+		Else
+			_skyboxShader=Shader.Open( "skybox",ShaderDefs )
+		Endif
+		
+		_renderQueue=New RenderQueue
+		
+		_psmFaceTransforms=New Mat3f[]( 
+			New Mat3f(  0,0,+1, 0,-1,0, -1, 0,0 ),	'+X
+			New Mat3f(  0,0,-1, 0,-1,0, +1, 0,0 ),	'-X
+			New Mat3f( +1,0, 0, 0,0,+1,  0,+1,0 ),	'+Y
+			New Mat3f( +1,0, 0, 0,0,-1,  0,-1,0 ),	'-Y
+			New Mat3f( +1,0, 0, 0,-1,0,  0,0,+1 ),	'+Z
+			New Mat3f( -1,0, 0, 0,-1,0,  0,0,-1 ) )	'-Z
+			
+		ValidateSize( New Vec2i( 1920,1080 ) )
+	End
+
+	Method ValidateSize( size:Vec2i )
+		
+		If _direct Return
+		
+		If _accumBuffer And size.x<=_accumBuffer.Size.x And size.y<=_accumBuffer.Size.y Return
+		
+		_accumBuffer?.Discard()
+		_depthBuffer?.Discard()
+		_renderTarget0?.Discard()
+		_renderTarget1?.Discard()
+
+		#If Not __MOBILE_TARGET__
+		Const color_format:=PixelFormat.RGBA32F
+		Const depth_format:=PixelFormat.Depth32
+		#Else
+		Const color_format:=PixelFormat.RGBA8
+		Const depth_format:=PixelFormat.Depth32
+		#Endif
+		
+		If _deferred
+		
+			_accumBuffer=New Texture( size.x,size.y,color_format,TextureFlags.Dynamic|TextureFlags.Filter )
+			_colorBuffer=New Texture( size.x,size.y,color_format,TextureFlags.Dynamic|TextureFlags.Filter )
+			_normalBuffer=New Texture( size.x,size.y,color_format,TextureFlags.Dynamic|TextureFlags.Filter )
+			_depthBuffer=New Texture( size.x,size.y,depth_format,TextureFlags.Dynamic )
+			
+			_renderTarget0=New RenderTarget( New Texture[]( _accumBuffer,_colorBuffer,_normalBuffer ),_depthBuffer )
+			_renderTarget1=New RenderTarget( New Texture[]( _accumBuffer ),Null )
+
+			_runiforms.SetTexture( "AccumBuffer",_accumBuffer )
+			_runiforms.SetTexture( "ColorBuffer",_colorBuffer )
+			_runiforms.SetTexture( "NormalBuffer",_normalBuffer )
+			_runiforms.SetTexture( "DepthBuffer",_depthBuffer )
+		Else
+			
+			_accumBuffer=New Texture( size.x,size.y,color_format,TextureFlags.Dynamic|TextureFlags.Filter )
+			_depthBuffer=New Texture( size.x,size.y,depth_format,TextureFlags.Dynamic )
+			
+			_renderTarget0=New RenderTarget( New Texture[]( _accumBuffer ),_depthBuffer )
+			_renderTarget1=New RenderTarget( New Texture[]( _accumBuffer ),Null )
+
+			_runiforms.SetTexture( "AccumBuffer",_accumBuffer )
+			_runiforms.SetTexture( "DepthBuffer",_depthBuffer )
+		Endif
+		
+	End
+	
+	Method ValidateCSMShadows()
+		
+		If Not _csmTexture Or _csmSize*2<>_csmTexture.Size.x
+			
+			_csmTarget?.Discard()
+			_csmTexture?.Discard()
+			_csmDepth?.Discard()
+
+			const depth_format:=PixelFormat.Depth32
+			
+			_csmTexture=New Texture( _csmSize*2,_csmSize*2,depth_format,TextureFlags.Dynamic )'|TextureFlags.Filter )
+			_csmTarget=New RenderTarget( Null,_csmTexture )
+			_csmDepth=Null
+			
+			_runiforms.SetTexture( "ShadowCSMTexture",_csmTexture )
+		Endif
+		
+	End
 
 
+	Method ValidatePSMShadows()
+		
+		If Not _psmTexture Or _psmSize<>_psmTexture.Size.x
+			
+			_psmTexture?.Discard()
+			_psmDepth?.Discard()
+			For Local i:=0 Until 6
+				_psmTargets[i]?.Discard()
+			Next
+			
+			const color_format:=PixelFormat.RGBA8
+			const depth_format:=PixelFormat.Depth32
+			
+			_psmTexture=New Texture( _psmSize,_psmSize,color_format,TextureFlags.Cubemap|TextureFlags.Dynamic )
+			_psmDepth=New Texture( _psmSize,_psmSize,depth_format,TextureFlags.Dynamic )
+			For Local i:=0 Until 6
+				Local face:=_psmTexture.GetCubeFace( Cast<CubeFace>( i ) )
+				_psmTargets[i]=New RenderTarget( New Texture[]( face ),_psmDepth )
+			Next
+			
+			_runiforms.SetTexture( "ShadowCubeTexture",_psmTexture )
+		Endif
+		
+	End
+	
+	Method SetOutputRenderTarget( renderTarget:RenderTarget,renderTargetSize:Vec2i,viewport:Recti )
+		
+		_outputRenderTarget=renderTarget
+		_outputRenderTargetSize=renderTargetSize
+		_outputViewport=viewport
+		
+		ValidateSize( viewport.Size )
+
+		If _direct
+			_gdevice.RenderTarget=renderTarget
+			_gdevice.Resize( renderTargetSize )
+			_gdevice.Viewport=viewport
+			_gdevice.Scissor=viewport
+			Return
+		Endif
+		
+		_gdevice.RenderTarget=_renderTarget0
+		_gdevice.Viewport=New Recti( 0,0,viewport.Size )
+		_gdevice.Scissor=_gdevice.Viewport
+	
+		_runiforms.SetVec2f( "BufferCoordScale",Cast<Vec2f>( viewport.Size )/Cast<Vec2f>( _accumBuffer.Size ) )
+	End
+	
+	Method SetScene( scene:Scene )
+		
+		_scene=scene
+		
+		_runiforms.SetTexture( "SkyTexture",_scene.SkyTexture )
+		_runiforms.SetColor( "ClearColor",_scene.ClearColor )
+		_runiforms.SetColor( "AmbientDiffuse",_scene.AmbientLight )
+		
+		Local env:Texture
+		
+		If _scene.EnvTexture
+			env=_scene.EnvTexture
+		ElseIf _scene.SkyTexture
+			env=_scene.SkyTexture
+		Else
+			env=_defaultEnv
+		Endif
+		
+		_runiforms.SetTexture( "EnvTexture",env )
+		_runiforms.SetFloat( "EnvTextureMaxLod",Log2( env.Size.x ) )
+		_runiforms.SetColor( "EnvColor",_scene.EnvColor )
+		
+		_runiforms.SetColor( "FogColor",_scene.FogColor )
+		_runiforms.SetFloat( "FogNear",_scene.FogNear )
+		_runiforms.SetFloat( "FogFar",_scene.FogFar )
+		
+		_runiforms.SetFloat( "ShadowAlpha",_scene.ShadowAlpha )
+		
+		_csmSplits=_scene.CSMSplits
+		
+	End
+	
+	Method SetCamera( viewMatrix:AffineMat4f,projMatrix:Mat4f,near:Float,far:Float )
+		
+		_viewMatrix=viewMatrix
+		_projMatrix=projMatrix
+		_near=near
+		_far=far
+		
+		_invViewMatrix=-_viewMatrix
+		_invProjMatrix=-_projMatrix
+
+		_runiforms.SetMat3f( "EnvMatrix",_invViewMatrix.m )
+		_runiforms.SetMat4f( "ProjectionMatrix",_projMatrix )
+		_runiforms.SetMat4f( "InverseProjectionMatrix",_invProjMatrix )
+		_runiforms.SetMat4f( "ViewMatrix",_viewMatrix )
+		_runiforms.SetMat4f( "CameraMatrix",_invViewMatrix )
+		_runiforms.SetFloat( "DepthNear",_near )
+		_runiforms.SetFloat( "DepthFar",_far )
+		
+		_csmSplitDepths[0]=_near
+		
+		For Local i:=1 Until 5
+			_csmSplitDepths[i]=Min( _csmSplitDepths[i-1]+_csmSplits[i-1],_far )
+		Next
+		
+		_runiforms.SetVec4f( "ShadowCSMSplits",New Vec4f( _csmSplitDepths[1],_csmSplitDepths[2],_csmSplitDepths[3],_csmSplitDepths[4] ) )
+		
+		_renderQueue.Clear()
+		
+		Local time:=Float( Now() )
+
+		_renderQueue.Time=time
+		
+		_runiforms.SetFloat( "Time",time )
+		
+		_renderQueue.EyePos=_invViewMatrix.t
+		
+		For Local r:=Eachin _scene.Renderables
+		
+			_renderQueue.CastsShadow=r.CastsShadow
+			
+			r.OnRender( _renderQueue )
+		Next
+		
+		SortTransparentOps()
+		
+		SortSpriteOps()
+		
+		_spriteBuffer.InsertRenderOps( _renderQueue,_invViewMatrix )
+	End
+	
 End
 End

+ 84 - 76
modules/mojo3d/render/renderqueue.monkey2

@@ -3,16 +3,25 @@ Namespace mojo3d
 
 
 Internal
 Internal
 
 
+Struct SpriteOp
+	Field sprite:Sprite
+
+	Field distance:Float
+End
+
 Class RenderOp
 Class RenderOp
 	Field material:Material
 	Field material:Material
-	Field uniforms:UniformBlock
+	Field uniforms:UniformBlock	'could be in instance?
 	Field instance:Entity
 	Field instance:Entity
-	Field bones:Mat4f[]
+	Field bones:Mat4f[]			'should be in instance
 	Field vbuffer:VertexBuffer
 	Field vbuffer:VertexBuffer
 	Field ibuffer:IndexBuffer
 	Field ibuffer:IndexBuffer
 	Field order:Int
 	Field order:Int
 	Field count:Int
 	Field count:Int
 	Field first:Int
 	Field first:Int
+	
+	Field blendMode:BlendMode
+	Field distance:Float
 End
 End
 
 
 Public
 Public
@@ -28,12 +37,72 @@ Class RenderQueue
 		_time=time
 		_time=time
 	End
 	End
 	
 	
+	Property EyePos:Vec3f()
+		
+		Return _eyePos
+		
+	Setter( eyePos:Vec3f )
+		
+		_eyePos=eyePos
+		_eyeLen=_eyePos.Length
+	End
+	
+	Property CastsShadow:Bool()
+		
+		Return _castsShadow
+		
+	Setter( castsShadow:Bool )
+		
+		_castsShadow=castsShadow
+	End
+
+	Property OpaqueOps:Stack<RenderOp>()
+		
+		Return _opaqueOps
+	End
+	
+	Property TransparentOps:Stack<RenderOp>()
+	
+		Return _transparentOps
+	End
+	
+	Property ShadowOps:Stack<RenderOp>()
+		
+		Return _shadowOps
+	End
+
+	Property SpriteOps:Stack<SpriteOp>()
+	
+		Return _spriteOps
+	End
+
 	Method Clear()
 	Method Clear()
 		_opaqueOps.Clear()
 		_opaqueOps.Clear()
 		_transparentOps.Clear()
 		_transparentOps.Clear()
-		_spriteOps.Clear()
 		_shadowOps.Clear()
 		_shadowOps.Clear()
-		_sprites.Clear()	
+		_spriteOps.Clear()	
+	End
+	
+	Method AddRenderOp( op:RenderOp )
+		
+		op.blendMode=op.material.BlendMode
+		If op.instance And op.instance.Alpha<1 And op.blendMode=BlendMode.Opaque op.blendMode=BlendMode.Alpha
+			
+		If op.blendMode=BlendMode.Opaque
+			DebugAssert( op.material.GetOpaqueShader(),"Material has no opaque shader" )
+			_opaqueOps.Push( op )
+		Else
+			DebugAssert( op.material.GetTransparentShader(),"Material has no transparent shader" )
+			op.distance=op.instance ? op.instance.Position.Distance( _eyePos ) Else _eyeLen
+			_transparentOps.Push( op )
+		Endif
+			
+		If _castsShadow And op.material.GetShadowShader() _shadowOps.Push( op )
+	End
+	
+	Method AddSpriteOp( op:SpriteOp )
+		op.distance=op.sprite ? op.sprite.Position.Distance( _eyePos ) Else _eyeLen
+		_spriteOps.Add( op )
 	End
 	End
 	
 	
 	Method AddRenderOp( material:Material,uniforms:UniformBlock,instance:Entity,vbuffer:VertexBuffer,ibuffer:IndexBuffer,order:Int,count:Int,first:Int )
 	Method AddRenderOp( material:Material,uniforms:UniformBlock,instance:Entity,vbuffer:VertexBuffer,ibuffer:IndexBuffer,order:Int,count:Int,first:Int )
@@ -84,86 +153,25 @@ Class RenderQueue
 		AddRenderOp( op )
 		AddRenderOp( op )
 	End
 	End
 	
 	
-	Internal
-	
-	Property CastsShadow:Bool()
-		
-		Return _castsShadow
-		
-	Setter( castsShadow:Bool )
-		
-		_castsShadow=castsShadow
-	End
-	
-	Property OpaqueOps:Stack<RenderOp>()
-		
-		Return _opaqueOps
-	End
-	
-	Property TransparentOps:Stack<RenderOp>()
-	
-		Return _transparentOps
-	End
-	
-	Property SpriteOps:Stack<RenderOp>()
-	
-		Return _spriteOps
-	End
-	
-	Property ShadowOps:Stack<RenderOp>()
-		
-		Return _shadowOps
-	End
-	
-	'bit of a hack for now, but renderqueue should be able to handle sprites...	
-	Property Sprites:Stack<Sprite>()
-	
-		Return _sprites
-	End
-	
-	Method AddRenderOp( op:RenderOp )
-		
-		op.material.ValidateShader()
-		
-		If op.material.BlendMode<>BlendMode.Opaque
-			_transparentOps.Push( op )
-		Else
-			_opaqueOps.Push( op )
-		Endif
-		
-		If _castsShadow
-			If (op.material.Shader.RenderPassMask & $10000) _shadowOps.Push( op )
-		Endif
-		
-	End
-	
-	Method AddSpriteOp( material:Material,uniforms:UniformBlock,instance:Entity,vbuffer:VertexBuffer,ibuffer:IndexBuffer,order:Int,count:Int,first:Int )
-		Local op:=New RenderOp
-		op.material=material
-		op.uniforms=uniforms
-		op.instance=instance
-		op.vbuffer=vbuffer
-		op.ibuffer=ibuffer
-		op.order=order
-		op.count=count
-		op.first=first
-		_spriteOps.Add( op )
-	End
-	
-	Method AddSprite( sprite:Sprite )
-	
-		_sprites.Add( sprite )
+	Method AddSpriteOp( sprite:Sprite )
+		DebugAssert( sprite.Material.GetTransparentShader(),"Sprites must be transparent!" )
+		Local op:=New SpriteOp
+		op.sprite=sprite
+		AddSpriteOp( op )
 	End
 	End
 	
 	
 	Private
 	Private
 
 
 	Field _time:float	
 	Field _time:float	
+	
+	Field _eyePos:Vec3f
+	Field _eyeLen:Float
+	Field _castsShadow:Bool
+	
 	Field _opaqueOps:=New Stack<RenderOp>
 	Field _opaqueOps:=New Stack<RenderOp>
 	Field _transparentOps:=New Stack<RenderOp>
 	Field _transparentOps:=New Stack<RenderOp>
-	Field _spriteOps:=New Stack<RenderOp>
 	Field _shadowOps:=New Stack<RenderOp>
 	Field _shadowOps:=New Stack<RenderOp>
-	Field _sprites:=New Stack<Sprite>
 	
 	
-	Field _castsShadow:Bool
+	Field _spriteOps:=New Stack<SpriteOp>
 
 
 End
 End

+ 98 - 25
modules/mojo3d/render/spritebuffer.monkey2

@@ -6,18 +6,18 @@ Namespace mojo3d
 Class SpriteBuffer
 Class SpriteBuffer
 	
 	
 	Method New()
 	Method New()
+		
 		_vbuffer=New VertexBuffer( Vertex3f.Format,0 )
 		_vbuffer=New VertexBuffer( Vertex3f.Format,0 )
 		
 		
 		_ibuffer=New IndexBuffer( IndexFormat.UINT32,0 )
 		_ibuffer=New IndexBuffer( IndexFormat.UINT32,0 )
 	End
 	End
 	
 	
-	Method AddSprites( rq:RenderQueue,camera:Camera )
-	
-		Local sprites:=rq.Sprites
+	Method InsertRenderOps( rq:RenderQueue,invViewMatrix:AffineMat4f )
 		
 		
-		If sprites.Empty Return
+		Local spriteOps:=rq.SpriteOps
+		If spriteOps.Empty Return
 		
 		
-		Local n:=sprites.Length
+		Local n:=spriteOps.Length
 		
 		
 		If n*4>_vbuffer.Length
 		If n*4>_vbuffer.Length
 			_vbuffer.Resize( Max( _vbuffer.Length*3/2,n*4 ) )
 			_vbuffer.Resize( Max( _vbuffer.Length*3/2,n*4 ) )
@@ -42,29 +42,74 @@ Class SpriteBuffer
 		
 		
 		Local vp:=Cast<Vertex3f Ptr>( _vbuffer.Lock() )
 		Local vp:=Cast<Vertex3f Ptr>( _vbuffer.Lock() )
 		
 		
-		'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
+		Local renderOps:=rq.TransparentOps
+		
+		_renderOps.Clear()
 		
 		
-		For Local sprite:=Eachin sprites
+		Local spritei:=0,renderi:=0
+	
+		_material=spriteOps[0].sprite.Material
+		_distance=spriteOps[0].distance
+		_i0=0
+		_i=0
+		
+		Repeat
+			
+			'out of sprites?
+			If spritei=spriteOps.Length
+				
+				'flush sprites
+				Flush()
+
+				'copy remaining renderops
+				For Local i:=renderi Until renderOps.Length
+					_renderOps.Add( renderOps[i] )
+				Next
+				
+				'done!
+				Exit
+			Endif
+			
+			'more renderops?
+			If renderi<renderOps.Length
+				
+				'sprite closer than next renderop?
+				If spriteOps[spritei].distance<renderOps[renderi].distance
+
+					'flush sprites
+					Flush()
+				
+					'add renderop before any more sprites
+					_renderOps.Add( renderOps[renderi] )
+					renderi+=1
+					
+					'next!
+					Continue
+				Endif
+			
+			Endif
+
+			Local sprite:=spriteOps[spritei].sprite
 			
 			
 			Local material:=sprite.Material
 			Local material:=sprite.Material
-			If material<>cmaterial
-				rq.AddSpriteOp( cmaterial,Null,Null,_vbuffer,_ibuffer,3,(i-i0)*2,i0*6 )
-				cmaterial=material
-				i0=i
+			
+			If material<>_material
+				
+				'flush sprites
+				Flush()
+				
+				_material=material
+				_distance=spriteOps[spritei].distance
 			Endif
 			Endif
+	
+			'done with spriteOp
+			spritei+=1
 			
 			
-			Local r:=camera.Basis
+			'construct vertices...
+			Local r:=invViewMatrix.m
 			
 			
 			Select sprite.Mode
 			Select sprite.Mode
 			Case SpriteMode.Upright
 			Case SpriteMode.Upright
-	
 				r.j=New Vec3f( 0,1,0 ) ; r.i=r.j.Cross( r.k ).Normalize()
 				r.j=New Vec3f( 0,1,0 ) ; r.i=r.j.Cross( r.k ).Normalize()
 			End
 			End
 			
 			
@@ -84,21 +129,49 @@ Class SpriteBuffer
 			vp[3].position=matrix * New Vec3f( -handle.x,-handle.y,0 )
 			vp[3].position=matrix * New Vec3f( -handle.x,-handle.y,0 )
 			vp[3].texCoord0=New Vec2f( texrect.min.x,texrect.max.y )
 			vp[3].texCoord0=New Vec2f( texrect.min.x,texrect.max.y )
 			
 			
+			'bump vertex/index
 			vp+=4
 			vp+=4
-			i+=1
-		Next
-		
-		rq.AddSpriteOp( cmaterial,Null,Null,_vbuffer,_ibuffer,3,(i-i0)*2,i0*6 )
+			_i+=1
+
+		Forever
 		
 		
 		_vbuffer.Invalidate()
 		_vbuffer.Invalidate()
 		
 		
 		_vbuffer.Unlock()
 		_vbuffer.Unlock()
+		
+		renderOps.Swap( _renderOps )
+		
+		_renderOps.Clear()
 	End
 	End
 
 
 	Private
 	Private
 	
 	
 	Field _vbuffer:VertexBuffer
 	Field _vbuffer:VertexBuffer
-	
 	Field _ibuffer:IndexBuffer
 	Field _ibuffer:IndexBuffer
+	Field _renderOps:=New Stack<RenderOp>
+	Field _material:Material
+	Field _distance:Float
+	Field _i0:Int
+	Field _i:Int
+	
+	Method Flush()
+		
+		If _i=_i0 Return
+		
+		Local op:=New RenderOp
+		op.material=_material
+		op.vbuffer=_vbuffer
+		op.ibuffer=_ibuffer
+		op.order=3
+		op.count=(_i-_i0)*2
+		op.first=_i0*6
+		
+		_i0=_i
+		
+		op.blendMode=_material.BlendMode
+		op.distance=_distance
+		
+		_renderOps.Add( op )
+	End
 	
 	
 End
 End

+ 22 - 3
modules/mojo3d/scene/entity.monkey2

@@ -106,9 +106,12 @@ Class Entity Extends DynamicObject
 		
 		
 		Assert( Not parent Or parent._scene=_scene )
 		Assert( Not parent Or parent._scene=_scene )
 		
 		
+		Local matrix:AffineMat4f=parent ? LocalMatrix Else Matrix
+		
 		If _parent
 		If _parent
 			_parent._children.Remove( Self )
 			_parent._children.Remove( Self )
 		Else
 		Else
+			matrix=Matrix
 			_scene.RootEntities.Remove( Self )
 			_scene.RootEntities.Remove( Self )
 		Endif
 		Endif
 		
 		
@@ -116,13 +119,13 @@ Class Entity Extends DynamicObject
 		
 		
 		If _parent 
 		If _parent 
 			_parent._children.Add( Self )
 			_parent._children.Add( Self )
+			LocalMatrix=matrix
 		Else
 		Else
 			_scene.RootEntities.Add( Self )
 			_scene.RootEntities.Add( Self )
+			Matrix=matrix
 		Endif
 		Endif
 		
 		
 		UpdateVisibility()
 		UpdateVisibility()
-			
-		Invalidate()
 	End
 	End
 	
 	
 	#rem monkeydoc Number of child entities.
 	#rem monkeydoc Number of child entities.
@@ -167,7 +170,18 @@ Class Entity Extends DynamicObject
 		
 		
 		Return _lastCopy
 		Return _lastCopy
 	End
 	End
-
+	
+	#rem monkeydoc Master alpha level.
+	#end
+	Property Alpha:Float()
+		
+		Return _alpha
+		
+	Setter( alpha:Float )
+		
+		_alpha=alpha
+	End
+	
 	'***** World space properties *****
 	'***** World space properties *****
 	
 	
 	#rem monkeydoc World space transformation matrix.
 	#rem monkeydoc World space transformation matrix.
@@ -394,6 +408,8 @@ Class Entity Extends DynamicObject
 		Local c:=New T( Self )
 		Local c:=New T( Self )
 		
 		
 		AddComponent( c )
 		AddComponent( c )
+		
+		Return c
 	End
 	End
 	
 	
 	Protected
 	Protected
@@ -446,6 +462,8 @@ Class Entity Extends DynamicObject
 		
 		
 		copy.Visible=Visible
 		copy.Visible=Visible
 		
 		
+		copy.Alpha=Alpha
+		
 		Copied( copy )
 		Copied( copy )
 	End
 	End
 	
 	
@@ -526,6 +544,7 @@ Private
 	Field _lastCopy:Entity
 	Field _lastCopy:Entity
 	Field _rvisible:Bool
 	Field _rvisible:Bool
 	Field _visible:Bool
 	Field _visible:Bool
+	Field _alpha:Float=1
 	
 	
 	Field _t:Vec3f=New Vec3f
 	Field _t:Vec3f=New Vec3f
 	Field _r:Mat3f=New Mat3f
 	Field _r:Mat3f=New Mat3f

+ 3 - 3
modules/mojo3d/scene/entityexts.monkey2

@@ -32,7 +32,7 @@ Class Entity Extension
 	
 	
 	Setter( rotation:Vec3f )
 	Setter( rotation:Vec3f )
 		
 		
-		Basis=Mat3f.Rotation( rotation * DegreesToRadians )
+		LocalBasis=Mat3f.Rotation( rotation * DegreesToRadians )
 	End
 	End
 	
 	
 	#Rem monkeydoc World space rotation around the X axis in degrees.
 	#Rem monkeydoc World space rotation around the X axis in degrees.
@@ -425,13 +425,13 @@ Class Entity Extension
 	#end
 	#end
 	Method PointAt( target:Vec3f,up:Vec3f=New Vec3f( 0,1,0 ) )
 	Method PointAt( target:Vec3f,up:Vec3f=New Vec3f( 0,1,0 ) )
 		
 		
-		Local k:=(target-LocalPosition).Normalize()
+		Local k:=(target-Position).Normalize()
 		
 		
 		Local i:=up.Cross( k ).Normalize()
 		Local i:=up.Cross( k ).Normalize()
 		
 		
 		Local j:=k.Cross( i )
 		Local j:=k.Cross( i )
 		
 		
-		LocalBasis=New Mat3f( i,j,k )
+		Basis=New Mat3f( i,j,k )
 	End
 	End
 	
 	
 	Method PointAt( target:Entity,up:Vec3f=New Vec3f( 0,1,0 ) )
 	Method PointAt( target:Entity,up:Vec3f=New Vec3f( 0,1,0 ) )

+ 2 - 1
modules/mojo3d/scene/native/collisiondetect.cpp

@@ -75,7 +75,8 @@ void initCollisions( btDynamicsWorld *world ){
 
 
 	world->setInternalTickCallback( &collisionCallback,0,false );
 	world->setInternalTickCallback( &collisionCallback,0,false );
 	
 	
-	gContactAddedCallback=&contactAddedCallback;
+//	gContactAddedCallback=&contactAddedCallback;
+	
 //	gContactProcessedCallback=&contactProcessedCallback;
 //	gContactProcessedCallback=&contactProcessedCallback;
 //	gContactDestroyedCallback=&contactDestroyedCallback;
 //	gContactDestroyedCallback=&contactDestroyedCallback;
 }
 }

+ 0 - 2
modules/mojo3d/scene/native/collisiondetect.h

@@ -4,8 +4,6 @@
 
 
 #include "btBulletDynamicsCommon.h"
 #include "btBulletDynamicsCommon.h"
 
 
-
-
 void initCollisions( btDynamicsWorld *world );
 void initCollisions( btDynamicsWorld *world );
 void resetCollisions();
 void resetCollisions();
 int  getNumCollisions();
 int  getNumCollisions();

+ 77 - 22
modules/mojo3d/scene/scene.monkey2

@@ -6,9 +6,14 @@ Namespace mojo3d
 Class Scene
 Class Scene
 
 
 	#rem monkeydoc Creates a new scene.
 	#rem monkeydoc Creates a new scene.
+	
+	If there is no current scene when a new scene is created, the new scene becomes the current scene.
+		
 	#end
 	#end
 	Method New()
 	Method New()
 		
 		
+		If Not _current _current=Self
+		
 		_clearColor=Color.Sky
 		_clearColor=Color.Sky
 
 
 		_ambientDiffuse=Color.DarkGrey
 		_ambientDiffuse=Color.DarkGrey
@@ -84,6 +89,42 @@ Class Scene
 		_clearColor=color
 		_clearColor=color
 	End
 	End
 	
 	
+	Property FogColor:Color()
+		
+		Return _fogColor
+	
+	Setter( color:Color )
+		
+		_fogColor=color
+	End
+	
+	Property FogNear:Float()
+		
+		Return _fogNear
+	
+	Setter( near:Float )
+		
+		_fogNear=near
+	End
+	
+	Property FogFar:Float()
+		
+		Return _fogFar
+	
+	Setter( far:Float )
+		
+		_fogFar=far
+	End
+	
+	Property ShadowAlpha:Float()
+		
+		Return _shadowAlpha
+	
+	Setter( alpha:Float )
+		
+		_shadowAlpha=alpha
+	End
+	
 	#rem monkeydoc Scene update rate.
 	#rem monkeydoc Scene update rate.
 	#end
 	#end
 	Property UpdateRate:Float()
 	Property UpdateRate:Float()
@@ -106,6 +147,23 @@ Class Scene
 		_ambientDiffuse=color
 		_ambientDiffuse=color
 	End
 	End
 	
 	
+	#rem monkeydoc Array containing the cascaded shadow map frustum splits for directional light shadows.
+	
+	Defaults to Float[]( 8.0,16.0,64.0,256.0 )
+	
+	Must have length 4.
+		
+	#end
+	Property CSMSplits:Float[]()
+		
+		Return _csmSplits
+		
+	Setter( splits:Float[] )
+		Assert( splits.Length=4,"CSMSplits array must have 4 elements" )
+		
+		_csmSplits=splits.Slice( 0 )
+	End
+	
 	#rem monkeydoc Adds a post effect to the scene.
 	#rem monkeydoc Adds a post effect to the scene.
 	#end
 	#end
 	Method AddPostEffect( postEffect:PostEffect )
 	Method AddPostEffect( postEffect:PostEffect )
@@ -157,27 +215,12 @@ Class Scene
 	
 	
 	#rem monkeydoc Renders the scene to	a canvas.
 	#rem monkeydoc Renders the scene to	a canvas.
 	#end
 	#end
-	Method Render( canvas:Canvas,camera:Camera=Null )
+	Method Render( canvas:Canvas )
 		
 		
-		If camera
+		For Local camera:=Eachin _cameras
 			
 			
-			camera.Viewport=canvas.Viewport
-			
-			canvas.Flush()
-		
-			Local renderer:=Renderer.GetCurrent()
-		
-			renderer.Render( Self,camera,canvas.GraphicsDevice )	
-			
-			Return
-			
-		Endif
-		
-		canvas.Flush()
-		
-		Local renderer:=Renderer.GetCurrent()
-		
-		renderer.Render( Self,canvas )
+			camera.Render( canvas )
+		Next
 	End
 	End
 	
 	
 	Method RayCast:RayCastResult( rayFrom:Vec3f,rayTo:Vec3f,collisionMask:Int )
 	Method RayCast:RayCastResult( rayFrom:Vec3f,rayTo:Vec3f,collisionMask:Int )
@@ -193,6 +236,9 @@ Class Scene
 	End
 	End
 	
 	
 	#rem monkeydoc Sets the current scene.
 	#rem monkeydoc Sets the current scene.
+	
+	All newly created entities (including entites created using Entity.Copy]]) are automatically added to the current scene.
+	
 	#end
 	#end
 	Function SetCurrent( scene:Scene )
 	Function SetCurrent( scene:Scene )
 		
 		
@@ -200,10 +246,13 @@ Class Scene
 	End
 	End
 	
 	
 	#rem monkeydoc Gets the current scene.
 	#rem monkeydoc Gets the current scene.
+	
+	If there is no current scene, a new scene is automatically created and made current.
+		
 	#end
 	#end
 	Function GetCurrent:Scene()
 	Function GetCurrent:Scene()
 
 
-		If Not _current _current=New Scene
+		If Not _current New Scene
 			
 			
 		Return _current
 		Return _current
 	End
 	End
@@ -243,19 +292,25 @@ Class Scene
 	Private
 	Private
 	
 	
 	Global _current:Scene
 	Global _current:Scene
-	
 	Global _defaultEnv:Texture
 	Global _defaultEnv:Texture
 	
 	
 	Field _skyTexture:Texture
 	Field _skyTexture:Texture
-	
 	Field _envTexture:Texture
 	Field _envTexture:Texture
 	Field _envColor:Color
 	Field _envColor:Color
 	
 	
 	Field _clearColor:Color
 	Field _clearColor:Color
 	Field _ambientDiffuse:Color
 	Field _ambientDiffuse:Color
 	
 	
+	Field _fogColor:Color
+	Field _fogNear:Float
+	Field _fogFar:Float
+	
+	Field _shadowAlpha:Float=1
+
 	Field _updateRate:Float=60
 	Field _updateRate:Float=60
 	
 	
+	Field _csmSplits:=New Float[]( 8.0,16.0,64.0,256.0 )
+	
 	Field _rootEntities:=New Stack<Entity>
 	Field _rootEntities:=New Stack<Entity>
 	Field _cameras:=New Stack<Camera>
 	Field _cameras:=New Stack<Camera>
 	Field _lights:=New Stack<Light>
 	Field _lights:=New Stack<Light>