Mark Sibly 8 years ago
parent
commit
a9b994abfa

+ 4 - 4
modules/mojo3d/graphics/camera.monkey2

@@ -11,9 +11,9 @@ Class Camera Extends Entity
 		Super.New( parent )
 		
 		Viewport=New Recti( 0,0,640,480 )
-		Fov=90
 		Near=1
 		Far=1000
+		FOV=90
 		
 		Show()
 	End
@@ -56,10 +56,10 @@ Class Camera Extends Entity
 	
 	#rem monkeydoc Vertical field of view in degrees.
 	
-	Defaults to 90.0
+	Defaults to 90.0.
 	
 	#end
-	Property Fov:Float()
+	Property FOV:Float()
 	
 		Return _fovy
 		
@@ -124,9 +124,9 @@ Class Camera Extends Entity
 		Super.New( camera,parent )
 		
 		Viewport=camera.Viewport
-		Fov=camera.Fov
 		Near=camera.Near
 		Far=camera.Far
+		FOV=camera.FOV
 		
 		Show()
 	End

+ 38 - 23
modules/mojo3d/graphics/deferredrenderer.monkey2

@@ -22,8 +22,7 @@ Class DeferredRenderer Extends Renderer
 		
 		Print "Creating DeferredRenderer"
 	
-		_dlightShader=Shader.Open( "light-directional-deferred" )
-		_plightShader=Shader.Open( "light-point-deferred" )
+		_lightShader=Shader.Open( "lighting-deferred",ShaderDefs )
 		_copyShader=Shader.Open( "copy" )
 		
 	End
@@ -81,15 +80,34 @@ Class DeferredRenderer Extends Renderer
 		
 		_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.ShadowsEnabled Continue
 			
-			If light.Type=LightType.Point Continue
-
-			RenderCSMShadows( light )
+			RenderLight( light,camera )
+		Next
+		
+		'point with shadows (not supported yet)
+		For Local light:=Eachin scene.Lights
+			If light.Type<>LightType.Point Or Not light.ShadowsEnabled Continue
 			
 			RenderLight( light,camera )
 		Next
 		
+		'directional without  shadows
+		For Local light:=Eachin scene.Lights
+			If light.Type<>LightType.Directional Or light.ShadowsEnabled Continue
+
+			RenderLight( light,camera )
+		Next
+		
+		'point without shadows
+		For Local light:=Eachin scene.Lights
+			If light.Type<>LightType.Point Or light.ShadowsEnabled Continue
+
+			RenderLight( light,camera )
+		Next
+		
 		_device.RenderTarget=_rpass0Target
 		
 		RenderSprites()
@@ -108,8 +126,7 @@ Class DeferredRenderer Extends Renderer
 		
 	Private
 	
-	Field _plightShader:Shader
-	Field _dlightShader:Shader
+	Field _lightShader:Shader
 	Field _copyShader:Shader
 	
 	Field _hdrTexture:Texture		'contains output linear HDR color
@@ -131,7 +148,7 @@ Class DeferredRenderer Extends Renderer
 		_device.DepthMask=True
 		_device.DepthFunc=DepthFunc.LessEqual
 		_device.BlendMode=BlendMode.Opaque
-		_device.RenderPass=1
+		_device.RenderPass=0
 
 		Super.RenderOpaqueOps()
 	End
@@ -147,6 +164,16 @@ Class DeferredRenderer Extends Renderer
 	End
 	
 	Method RenderLight( light:Light,camera:Camera )
+		
+		Local pass:=0
+		
+		Select light.Type
+		Case LightType.Directional
+			If light.ShadowsEnabled RenderCSMShadows( light ) ; pass|=2
+		Case LightType.Point
+			If light.ShadowsEnabled RenderPointShadows( light ) ; pass|=2
+			pass|=1
+		End
 	
 		_runiforms.SetVec4f( "LightColor",light.Color )
 		_runiforms.SetFloat( "LightRange",light.Range )
@@ -159,21 +186,9 @@ Class DeferredRenderer Extends Renderer
 		_device.DepthFunc=DepthFunc.Always
 		_device.BlendMode=BlendMode.Additive
 		_device.CullMode=CullMode.None
-		_device.RenderPass=3
-		
-		Select light.Type
-		Case LightType.Directional
-		
-			_device.Shader=_dlightShader
-			
-			RenderQuad()
-		
-		Case LightType.Point
-
-			_device.Shader=_plightShader
-			
-			RenderQuad()
-		End
+		_device.Shader=_lightShader
+		_device.RenderPass=pass
+		RenderQuad()
 
 	End
 

+ 55 - 28
modules/mojo3d/graphics/forwardrenderer.monkey2

@@ -21,21 +21,21 @@ Class ForwardRenderer Extends Renderer
 
 	#rem monkeydoc @hidden
 	#end
-	Method New( deferred:Bool )
-		Super.New( deferred ? "MX2_LINEAROUTPUT" Else "MX2_SRGBOUTPUT" )
+	Method New( direct:Bool )
+		Super.New( direct ? "MX2_SRGBOUTPUT" Else "MX2_LINEAROUTPUT" )
 		
-		_deferred=deferred
+		_direct=direct
 		
-		Print "Creating ForwardRenderer, deferred="+Int( _deferred )
+		Print "Creating ForwardRenderer, direct="+Int( _direct )
 		
-		If _deferred _copyShader=Shader.Open( "copy" )
+		If Not _direct _copyShader=Shader.Open( "copy" )
 	End
 	
 	Protected
 	
 	Method OnValidateSize( size:Vec2i ) Override 
 		
-		If Not _deferred Return
+		If _direct Return
 
 		If Not _colorBuffer Or size.x>_colorBuffer.Size.x Or size.y>_colorBuffer.Size.y
 			
@@ -64,7 +64,7 @@ Class ForwardRenderer Extends Renderer
 		_device=Device
 		_runiforms=RenderUniforms
 		
-		If _deferred
+		If Not _direct
 			_renderTarget=device.RenderTarget
 			_renderTargetSize=device.RenderTargetSize
 			_renderViewport=device.Viewport
@@ -81,33 +81,40 @@ Class ForwardRenderer Extends Renderer
 				
 		RenderBackground()
 		
-		Local rambient:=False
+		_ambientRendered=False
 		
 		For Local light:=Eachin scene.Lights
-			If light.Type<>LightType.Directional Continue
+			If light.Type<>LightType.Directional Or Not light.ShadowsEnabled Continue
 			
-			RenderCSMShadows( light )
-
-			_runiforms.SetVec4f( "LightColor",light.Color )
-			_runiforms.SetFloat( "LightRange",light.Range )
-			_runiforms.SetMat4f( "LightViewMatrix",camera.InverseMatrix * light.Matrix )
+			RenderOpaque( light,camera )
+		Next
+		
+		For Local light:=Eachin scene.Lights
+			If light.Type<>LightType.Point Or Not light.ShadowsEnabled Continue
 			
-			If rambient
-				RenderOpaque( BlendMode.Additive,2 )
-			Else
-				RenderOpaque( BlendMode.Opaque,3 )
-				rambient=True
-			Endif
+			RenderOpaque( light,camera )
+		Next
+		
+		For Local light:=Eachin scene.Lights
+			If light.Type<>LightType.Directional Or light.ShadowsEnabled Continue
 			
+			RenderOpaque( light,camera )
 		Next
 		
-		If Not rambient
-			RenderOpaque( BlendMode.Opaque,1 )
+		For Local light:=Eachin scene.Lights
+			If light.Type<>LightType.Point Or light.ShadowsEnabled Continue
+			
+			RenderOpaque( light,camera )
+		Next
+		
+		If Not _ambientRendered
+			
+			RenderOpaque( Null,camera )
 		Endif
 		
 		RenderSprites()
 		
-		If _deferred
+		If Not _direct
 		
 			_device.RenderTarget=_colorTarget1
 			RenderEffects( scene )
@@ -123,7 +130,7 @@ Class ForwardRenderer Extends Renderer
 	
 	Private
 	
-	Field _deferred:bool
+	Field _direct:Bool
 	
 	Field _copyShader:Shader
 	Field _colorBuffer:Texture
@@ -138,15 +145,35 @@ Class ForwardRenderer Extends Renderer
 	Field _device:GraphicsDevice
 	Field _runiforms:UniformBlock
 	
-	Method RenderOpaque( blendMode:BlendMode,renderPass:Int )
+	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.ShadowsEnabled RenderCSMShadows( light ) ; pass|=4
+			Case LightType.Point
+				if light.ShadowsEnabled RenderPointShadows( light ) ; pass|=4
+				pass|=8
+			End
+			_runiforms.SetVec4f( "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=blendMode
-		_device.RenderPass=renderPass
-
+		_device.BlendMode=_ambientRendered ? BlendMode.Additive Else BlendMode.Opaque
+		_device.RenderPass=pass
+		
 		Super.RenderOpaqueOps()
+		
+		_ambientRendered=True
 	End
 	
 	Method RenderSprites()

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

@@ -12,9 +12,9 @@ Note: Only directional lights are currently fully supported.
 | `Spot`		| Spot light.
 #end
 Enum LightType
-	Directional=0
-	Point=1
-	Spot=2
+	Directional=1
+	Point=2
+	Spot=3
 End
 
 #rem monkeydoc The Light class.

+ 182 - 40
modules/mojo3d/graphics/renderer.monkey2

@@ -12,34 +12,53 @@ Class Renderer
 		Return _shaderDefs
 	End
 
-	#rem monkeydoc Size of cascading shadow map texture.
+	#rem monkeydoc Size of the cascaded shadow map texture.
 	
 	Must be a power of 2 size. Defaults to 1024.
 	
 	#end
-	Property CSMTextureSize:Float()
+	Property CSMTextureSize:Int()
 		
 		Return _csmSize
 		
-	Setter( size:Float )
+	Setter( size:Int )
 		Assert( Log2( size )=Floor( Log2( size ) ),"CSMTextureSize must be a power of 2" )
 		
 		_csmSize=size
 	End
 	
-	#rem monkeydoc Array containing the Z depths of the cascading shadow map frustum splits.
+	#rem monkeydoc Array containing the cascaded shadow map frustum splits for directional light shadows.
 	
-	Defaults to Float[]( 1,20,60,180,1000 ).
+	Defaults to Float[]( 1.0/64.0,1.0/16.0,1.0/4.0 )
+	
+	Must have length 3.
 		
 	#end
-	Property CSMSplitDepths:Float[]()
+	Property CSMSplits:Float[]()
 		
 		Return _csmSplits
-	
+		
 	Setter( splits:Float[] )
-		Assert( splits.Length=5,"CSMSplitDepths array must have 5 elements" )
+		Assert( splits.Length=3,"CSMSplits array must have 3 elements" )
+		
+		_csmSplits=splits.Slice( 0 )
+	End
+	
+	#rem monkeydoc Size of the cube texture used for point light shadow mapping.
+	
+	Must be a power of 2.
+	
+	Defaults to 1024.
+		
+	#end
+	Property PSMTextureSize:Int()
 		
-		_csmSplits=splits
+		Return _psmSize
+		
+	Setter( size:Int )
+		Assert( Log2( size )=Floor( Log2( size ) ),"PSMTextureSize must be a power of 2" )
+		
+		_psmSize=size
 	End
 	
 	#rem monkeydoc Gets the current renderer.
@@ -49,21 +68,22 @@ Class Renderer
 		Global _current:Renderer
 		
 		If Not _current
+			
+			Local hasDepth:=Int( App.GetConfig( "GL_depth_buffer_enabled","0" ) )<>0
+			
 			Select App.GetConfig( "mojo3d_renderer","" )
 			Case "deferred"
 				_current=New DeferredRenderer
+			Case "forward-direct"
+				_current=New ForwardRenderer( True )
 			Case "forward"
 				_current=New ForwardRenderer( False )
 			Default
-#If __DESKTOP_TARGET__					
-				If glexts.GL_draw_buffers
-					_current=New DeferredRenderer
-				Else
-					_current=New ForwardRenderer( True )
-				Endif
+#If Not __MOBILE_TARGET__					
+				If glexts.GL_draw_buffers _current=New DeferredRenderer
 #Endif
 			End
-			If Not _current _current=New ForwardRenderer( False )
+			If Not _current _current=New ForwardRenderer( hasDepth )
 		Endif
 		
 		Return _current
@@ -83,12 +103,20 @@ Class Renderer
 		
 		OnValidateSize( size )
 		
-		ValidateCSM()
+		ValidateShadowMaps()
+		
+		_csmSplitDepths[0]=camera.Near
+		For Local i:=1 Until 4
+			_csmSplitDepths[i]=camera.Near+_csmSplits[i-1]*(camera.Far-camera.Near)
+		Next
+		_csmSplitDepths[4]=camera.Far
 
 		_runiforms.SetFloat( "Time",Now() )
+		
+		_runiforms.SetTexture( "ShadowCSMTexture",_csmTexture )
+		_runiforms.SetVec4f( "ShadowCSMSplits",New Vec4f( _csmSplitDepths[1],_csmSplitDepths[2],_csmSplitDepths[3],_csmSplitDepths[4] ) )
 
-		_runiforms.SetTexture( "ShadowTexture",_csmTexture )
-		_runiforms.SetVec4f( "ShadowSplits",New Vec4f( _csmSplits[1],_csmSplits[2],_csmSplits[3],_csmSplits[4] ) )
+		_runiforms.SetTexture( "ShadowCubeTexture",_psmTexture )
 		
 		'***** Set render scene *****
 		
@@ -143,7 +171,7 @@ Class Renderer
 		
 		_renderCamera=Null
 		
-		_renderScene=null
+		_renderScene=Null
 	End
 	
 	Protected
@@ -157,6 +185,14 @@ Class Renderer
 	Method New( shaderDefs:String )
 		
 		_shaderDefs=shaderDefs
+
+		_rgbaDepthTextures=False	'True'	Not glexts.GL_depth_texture
+		
+'		If Int( App.GetConfig( "mojod3_rgba_depth_textures","" ) ) _rgbaDepthTextures=True
+			
+		Print "RGBA depth textures="+Int( _rgbaDepthTextures )
+		
+		If _rgbaDepthTextures _shaderDefs+="~nMX2_RGBADEPTHTEXTURES"
 		
 		_device=New GraphicsDevice( 0,0 )
 		
@@ -166,12 +202,31 @@ Class Renderer
 		_device.BindUniformBlock( _runiforms )
 		_device.BindUniformBlock( _iuniforms )
 
-		_csmSplits=New Float[]( 1,20,60,180,1000 )
-
 		_defaultEnv=Texture.Load( "asset::textures/env_default.jpg",TextureFlags.FilterMipmap|TextureFlags.Cubemap )
 		
 		_skyboxShader=Shader.Open( "skybox",_shaderDefs )
-
+		
+		_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
+			
+		#rem
+		Matxf tforms[]={
+		{ {0,0,+1},{0,-1,0},{-1,0,0},{0,0,0} },	//+X
+		{ {0,0,-1},{0,-1,0},{+1,0,0},{0,0,0} },	//-X
+		{ {+1,0,0},{0,0,+1},{0,+1,0},{0,0,0} },	//+Y test me!
+		{ {+1,0,0},{0,0,-1},{0,-1,0},{0,0,0} },	//-Y
+		{ {+1,0,0},{0,-1,0},{0,0,+1},{0,0,0} },	//+Z
+		{ {-1,0,0},{0,-1,0},{0,0,-1},{0,0,0} }	//-Z
+	};		
+		
+		#end
+	
+	
 	End
 
 	Property Device:GraphicsDevice()
@@ -273,24 +328,28 @@ Class Renderer
 		_device.RenderTarget=_csmTarget
 		_device.Viewport=New Recti( 0,0,_csmTarget.Size )
 		_device.Scissor=_device.Viewport
-		_device.ColorMask=ColorMask.None
+		_device.ColorMask=ColorMask.All
 		_device.DepthMask=True
-		_device.Clear( Null,1.0 )
+		_device.Clear( Color.White,1.0 )
+'		_device.ColorMask=ColorMask.None
+'		_device.DepthMask=True
+'		_device.Clear( Null,1.0 )
 		
 		_device.DepthFunc=DepthFunc.LessEqual
 		_device.BlendMode=BlendMode.Opaque
 		_device.CullMode=CullMode.Back
-		_device.RenderPass=4
+		_device.RenderPass=16
 
 		Local invLightMatrix:=light.InverseMatrix
+		
 		Local viewLight:=invLightMatrix * _renderCamera.Matrix
 		
-		For Local i:=0 Until _csmSplits.Length-1
+		For Local i:=0 Until _csmSplitDepths.Length-1
 			
-			Local znear:=_csmSplits[i]
-			Local zfar:=_csmSplits[i+1]
+			Local znear:=_csmSplitDepths[i]
+			Local zfar:=_csmSplitDepths[i+1]
 			
-			Local splitProj:=Mat4f.Perspective( _renderCamera.Fov,_renderCamera.Aspect,znear,zfar )
+			Local splitProj:=Mat4f.Perspective( _renderCamera.FOV,_renderCamera.Aspect,znear,zfar )
 						
 			Local invSplitProj:=-splitProj
 			
@@ -325,9 +384,7 @@ Class Renderer
 			
 			_device.Scissor=_device.Viewport
 				
-			If light.ShadowsEnabled
-				RenderRenderOps( _renderQueue.ShadowOps,invLightMatrix,lightProj )
-			Endif
+			RenderRenderOps( _renderQueue.ShadowOps,invLightMatrix,lightProj )
 			
 		Next
 		
@@ -336,19 +393,74 @@ Class Renderer
 		_device.Scissor=t_scissor
 	End
 
+	Method RenderPointShadows( light:Light )
+	
+		'Perhaps use a different device for CSM...?
+		'
+		Local t_rtarget:=_device.RenderTarget
+		Local t_viewport:=_device.Viewport
+		Local t_scissor:=_device.Scissor
+		
+		_device.Viewport=New Recti( 0,0,_psmTexture.Size )
+		_device.Scissor=_device.Viewport
+		_device.ColorMask=ColorMask.All
+		_device.DepthMask=True
+		_device.DepthFunc=DepthFunc.LessEqual
+		'
+		_device.BlendMode=BlendMode.Opaque
+		_device.CullMode=CullMode.Back
+		_device.RenderPass=17
+		
+		Local lightProj:=Mat4f.Frustum( -1,+1,-1,+1,1,light.Range )
+		
+		Local invLightMatrix:=light.InverseMatrix
+		
+		Local viewLight:=invLightMatrix * _renderCamera.Matrix
+		
+		_runiforms.SetFloat( "LightRange",light.Range )
+		_runiforms.SetMat4f( "ShadowMatrix0",viewLight )
+		
+		For Local i:=0 Until 6
+			
+			_device.RenderTarget=_psmTargets[i]
+			_device.Clear( Color.White,1.0 )
+			
+			Local viewMatrix:=New AffineMat4f( _psmFaceTransforms[i] ) * invLightMatrix
+
+			RenderRenderOps( _renderQueue.ShadowOps,viewMatrix,lightProj )
+			
+		Next
+
+		_device.RenderTarget=t_rtarget
+		_device.Viewport=t_viewport
+		_device.Scissor=t_scissor
+	End
+
 	Private
 	
+	Field _rgbaDepthTextures:=False
+	
 	Field _shaderDefs:String
 	
 	Field _device:GraphicsDevice
 	Field _runiforms:UniformBlock
 	Field _iuniforms:UniformBlock
+
+	Field _skyboxShader:Shader
 	
-	Field _csmSize:=4096
-	Field _csmSplits:=New Float[]( 1,20,60,180,1000 )
+	Field _psmFaceTransforms:Mat3f[]
+	
+	Field _csmSize:=2048
+	Field _csmSplits:=New Float[]( 1.0/64.0,1.0/16.0,1.0/4.0 )
+	Field _csmSplitDepths:=New Float[5]
 	Field _csmTexture:Texture
+	Field _csmDepth:Texture
 	Field _csmTarget:RenderTarget
-	Field _skyboxShader:Shader
+	
+	Field _psmSize:=2048
+	Field _psmTexture:Texture
+	Field _psmDepth:Texture
+	Field _psmTargets:=New RenderTarget[6]
 
 	Field _defaultEnv:Texture
 	
@@ -359,16 +471,46 @@ Class Renderer
 	Field _renderScene:Scene
 	Field _renderCamera:Camera
 	
-	Method ValidateCSM()
+	Method ValidateShadowMaps()
 		
 		If Not _csmTexture Or _csmSize<>_csmTexture.Size.x
 			
-			SafeDiscard( _csmTexture )
 			SafeDiscard( _csmTarget )
+			SafeDiscard( _csmTexture )
+			SafeDiscard( _csmDepth )
 			
-			_csmTexture=New Texture( _csmSize,_csmSize,PixelFormat.Depth32F,TextureFlags.Dynamic )
-			_csmTarget=New RenderTarget( Null,_csmTexture )
+			If _rgbaDepthTextures
+				_csmTexture=New Texture( _csmSize,_csmSize,PixelFormat.RGBA8,TextureFlags.Dynamic )
+				_csmDepth=New Texture( _csmSize,_csmSize,PixelFormat.Depth32F,TextureFlags.Dynamic )
+				_csmTarget=New RenderTarget( New Texture[]( _csmTexture ),_csmDepth )
+			Else
+				_csmTexture=New Texture( _csmSize,_csmSize,PixelFormat.Depth32F,TextureFlags.Dynamic )
+				_csmTarget=New RenderTarget( Null,_csmTexture )
+				_csmDepth=Null
+			Endif
+			
+		Endif
+		
+		If Not _psmTexture Or _psmSize*2>_psmTexture.Size.x
+			
+			SafeDiscard( _psmTexture )
+			SafeDiscard( _psmDepth )
+			For Local i:=0 Until 6
+				SafeDiscard( _psmTargets[i] )
+			Next
+			
+			Local size:=_psmSize*2
 			
+			_psmTexture=New Texture( size,size,PixelFormat.RGBA8,TextureFlags.Cubemap|TextureFlags.Dynamic )
+'			_psmTexture=New Texture( size,size,PixelFormat.Depth32F,TextureFlags.Cubemap|TextureFlags.Dynamic )
+			_psmDepth=New Texture( size,size,PixelFormat.Depth32F,TextureFlags.Dynamic )
+			For Local i:=0 Until 6
+				Local face:=_psmTexture.GetCubeFace( Cast<CubeFace>( i ) )
+				_psmTargets[i]=New RenderTarget( New Texture[]( face ),_psmDepth )
+			Next
+			
+			glCheck()
+		
 		Endif
 		
 	End

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

@@ -58,7 +58,7 @@ Class RenderQueue
 		Endif
 		
 		If _addShadowOps 
-			If (op.material.Shader.RenderPassMask & 16) _shadowOps.Push( op )
+			If (op.material.Shader.RenderPassMask & $10000) _shadowOps.Push( op )
 		Endif
 		
 	End

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

@@ -1,118 +0,0 @@
-
-//@renderpasses 2
-
-uniform mat4 r_InverseProjectionMatrix;
-
-uniform vec2 r_BufferCoordScale;
-uniform sampler2D r_ColorBuffer;
-uniform sampler2D r_NormalBuffer;
-uniform sampler2D r_DepthBuffer;
-
-uniform float r_DepthNear;
-uniform float r_DepthFar;
-
-uniform mat4 r_LightViewMatrix;
-uniform vec4 r_LightColor;
-uniform float r_LightRange;
-
-varying vec2 v_ClipPosition;
-varying vec2 v_TexCoord0;
-
-//@vertex
-
-attribute vec2 a_Position;
-	
-void main(){
-
-	v_ClipPosition=a_Position * 2.0 - 1.0;
-	
-	v_TexCoord0=a_Position * r_BufferCoordScale;
-	
-	gl_Position=vec4( v_ClipPosition,-1.0,1.0 );
-}
-
-//@fragment
-
-vec3 v_Position;
-vec3 v_Normal;
-
-float viewDepth( float depth ){
-
-	return r_DepthFar * r_DepthNear / ( r_DepthFar + depth * ( r_DepthNear - r_DepthFar ) );
-}
-
-vec3 evalLight( vec3 color,float metalness,float roughness ){
-
-	vec3 normal=v_Normal;
-	
-	float glosiness=1.0-roughness;
-	
-	vec3 color0=vec3( 0.04,0.04,0.04 );
-	
-	vec3 diffuse=color * (1.0-metalness);
-	
-	vec3 specular=(color-color0) * metalness + color0;
-	
-	//lighting
-	
-	vec3 lightDir=r_LightViewMatrix[3].xyz-v_Position;
-
-	//Cool! https://imdoingitwrong.wordpress.com/2011/01/31/light-attenuation/
-	//	
-	float atten=1.0/( pow( length( lightDir/r_LightRange ),2.0 ) );
-	
-	vec3 vvec=normalize( -v_Position );
-	vec3 lvec=normalize( lightDir );
-	vec3 hvec=normalize( lvec+vvec );
-
-	float spow=pow( 2.0,glosiness * 12.0 );
-//	float spow=pow( 4096.0,glosiness );
-//	float spow=exp2( 12.0 * glosiness + 1.0 );
-
-	float fnorm=(spow+2.0)/8.0;
-	
-	float hdotl=max( dot( hvec,lvec ),0.0 );
-	vec3 fschlick=specular + (1.0-specular) * pow( 1.0-hdotl,5.0 ) * glosiness;
-	
-	float ndotl=max( dot( normal,lvec ),0.0 );
-	float ndoth=max( dot( normal,hvec ),0.0 );
-	
-	vec3 lightColor=r_LightColor.rgb * ndotl * atten;
-	
-	specular=pow( ndoth,spow ) * fnorm * fschlick;
-	
-	return (diffuse+specular) * lightColor;
-}
-
-void main(){
-
-	vec4 color_m=texture2D( r_ColorBuffer,v_TexCoord0 );
-	
-	vec4 normal_r=texture2D( r_NormalBuffer,v_TexCoord0 );
-	
-	float depth=viewDepth( texture2D( r_DepthBuffer,v_TexCoord0 ).r );
-
-	vec4 vpos4=r_InverseProjectionMatrix * vec4( v_ClipPosition,-1.0,1.0 );
-	
-	vec3 vpos=vpos4.xyz/vpos4.w;
-
-	/*	
-	if( abs( vpos.z-r_DepthNear)>0.00001 ){
-		gl_FragColor=vec4( 1.0,0.0,0.0,1.0 );
-		return;
-	}
-	if( abs( vpos.x )>=1.0 || abs( vpos.y )>=1.0 ){
-		gl_FragColor=vec4( 0.0,1.0,0.0,1.0 );
-		return;
-	}
-	*/
-	
-	v_Position=vpos/vpos.z*depth;
-	
-	v_Normal=normalize( normal_r.xyz * 2.0 - 1.0 );
-	
-	vec3 light=evalLight( color_m.rgb,color_m.a,normal_r.a );
-	
-	gl_FragColor=vec4( min( light,8.0 ),1.0 );
-}
-

+ 92 - 30
modules/mojo3d/graphics/shaders/light-directional-deferred.glsl → modules/mojo3d/graphics/shaders/lighting-deferred.glsl

@@ -1,8 +1,16 @@
+//@renderpasses 0,1,2,3
 
-//@renderpasses 3
+//renderpasses:
+// 0=directional light without shadow.
+// 1=point light without shadow.
+// 2=directional light with shadow.
+// 3=point light with shadow.
 
 uniform mat4 r_InverseProjectionMatrix;
 
+#define MX2_DIRECTIONALPASS (MX2_RENDERPASS==0 || MX2_RENDERPASS==2)
+#define MX2_SHADOWEDPASS (MX2_RENDERPASS==2 || MX2_RENDERPASS==3)
+
 uniform vec2 r_BufferCoordScale;
 uniform sampler2D r_ColorBuffer;
 uniform sampler2D r_NormalBuffer;
@@ -12,15 +20,20 @@ uniform float r_DepthNear;
 uniform float r_DepthFar;
 
 uniform mat4 r_LightViewMatrix;
-uniform vec4 r_LightColor;
 uniform float r_LightRange;
+uniform vec4 r_LightColor;
 
-uniform sampler2D r_ShadowTexture;
+#if MX2_RENDERPASS==2
+uniform sampler2D r_ShadowCSMTexture;
+uniform vec4 r_ShadowCSMSplits;
 uniform mat4 r_ShadowMatrix0;
 uniform mat4 r_ShadowMatrix1;
 uniform mat4 r_ShadowMatrix2;
 uniform mat4 r_ShadowMatrix3;
-uniform vec4 r_ShadowSplits;
+#elif MX2_RENDERPASS==3
+uniform samplerCube r_ShadowCubeTexture;
+uniform mat4 r_ShadowMatrix0;
+#endif
 
 varying vec2 v_ClipPosition;
 varying vec2 v_TexCoord0;
@@ -43,25 +56,44 @@ void main(){
 vec3 v_Position;
 vec3 v_Normal;
 
+//can't handle 1!
+vec4 FloatToRGBA( float value ){
+
+	const float MaxFloat=0.9999999;
+
+	value=clamp( value,0.0,MaxFloat );
+
+	vec4 rgba=fract( vec4( 1.0, 255.0, 65025.0, 16581375.0 ) * value );
+	
+	return rgba-rgba.yzww * vec4( 1.0/255.0, 1.0/255.0, 1.0/255.0, 0.0 );
+}
+
+float RGBAToFloat( vec4 rgba ){
+
+	return dot( rgba,vec4( 1.0, 1.0/255.0, 1.0/65025.0, 1.0/16581375.0 ) );
+}
+
 float viewDepth( float depth ){
 
 	return r_DepthFar * r_DepthNear / ( r_DepthFar + depth * ( r_DepthNear - r_DepthFar ) );
 }
 
-float evalShadow(){
+#if MX2_RENDERPASS==2
 
-	vec4 vpos=vec4( v_Position + v_Normal * .05,1.0 );
-//	vec4 vpos=vec4( v_Position,1.0 );
+float shadowColor(){
+
+//	vec4 vpos=vec4( v_Position + v_Normal * .05,1.0 );
+	vec4 vpos=vec4( v_Position + v_Normal * .06,1.0 );
 	vec4 lpos;
 	vec2 off;
 	
-	if( vpos.z<r_ShadowSplits.x ){
+	if( vpos.z<r_ShadowCSMSplits.x ){
 		lpos=r_ShadowMatrix0 * vpos;
 		off=vec2( 0.0,0.0 );
-	}else if( vpos.z<r_ShadowSplits.y ){
+	}else if( vpos.z<r_ShadowCSMSplits.y ){
 		lpos=r_ShadowMatrix1 * vpos;
 		off=vec2( 0.5,0.0 );
-	}else if( vpos.z<r_ShadowSplits.z ){
+	}else if( vpos.z<r_ShadowCSMSplits.z ){
 		lpos=r_ShadowMatrix2 * vpos;
 		off=vec2( 0.0,0.5 );
 	}else{
@@ -73,46 +105,81 @@ float evalShadow(){
 
 //	spos.z*=0.999;
 	
-	float d=texture2D( r_ShadowTexture,spos.xy+off ).r;
+#if defined( MX2_RGBADEPTHTEXTURES )
+	float d=RGBAToFloat( texture2D( r_ShadowCSMTexture,spos.xy+off ) );
+#else
+	float d=texture2D( r_ShadowCSMTexture,spos.xy+off ).r;
+#endif
 	
 	if( spos.z>d ) return 0.0;
 	
 	return 1.0;
 }
 
-vec3 evalLight( vec3 color,float metalness,float roughness ){
+#elif MX2_RENDERPASS==3
 
-	vec3 normal=v_Normal;
+float shadowColor(){
+
+	vec4 vpos=vec4( v_Position + v_Normal * .05,1.0 );
+	vec3 lpos=(r_ShadowMatrix0 * vpos).xyz;
 	
-	float glosiness=1.0-roughness;
+	float d=RGBAToFloat( textureCube( r_ShadowCubeTexture,lpos ) );
 	
-	vec3 color0=vec3( 0.04,0.04,0.04 );
+	if( length( lpos )>=d*r_LightRange ) return 0.0;
 	
+	return 1.0;
+}
+
+#endif
+
+vec3 lightColor( vec3 color,float metalness,float roughness ){
+
+	vec3 normal=v_Normal;
+	float glosiness=1.0-roughness;
+	vec3 color0=vec3( 0.04,0.04,0.04 );
 	vec3 diffuse=color * (1.0-metalness);
-	
 	vec3 specular=(color-color0) * metalness + color0;
+	float atten=1.0;
 	
-	//lighting
-	
-	vec3 vvec=normalize( -v_Position );
+#if MX2_DIRECTIONALPASS
 	vec3 lvec=normalize( -r_LightViewMatrix[2].xyz );
+#else
+	// https://imdoingitwrong.wordpress.com/2011/01/31/light-attenuation/
+	//
+	vec3 lvec=r_LightViewMatrix[3].xyz-v_Position;
+	float ldist=length( lvec );
+    lvec/=ldist;
+	atten=max( 1.0-(ldist/r_LightRange),0.0 );
+    
+//    atten=1.0;
+	
+//	atten=1.0/( pow( length( lvec/r_LightRange ),2.0 ) );	//Cool! https://imdoingitwrong.wordpress.com/2011/01/31/light-attenuation/
+//	atten=1.0/( pow( length( lvec )/r_LightRange,2.0 ) );	//Cool! https://imdoingitwrong.wordpress.com/2011/01/31/light-attenuation/
+//	lvec=normalize( lvec );
+
+#endif
+	vec3 vvec=normalize( -v_Position );
 	vec3 hvec=normalize( lvec+vvec );
 
 	float spow=pow( 2.0,glosiness * 12.0 );
 //	float spow=pow( 4096.0,glosiness );
 //	float spow=exp2( 12.0 * glosiness + 1.0 );
-
 	float fnorm=(spow+2.0)/8.0;
 	
 	float hdotl=max( dot( hvec,lvec ),0.0 );
+	
 	vec3 fschlick=specular + (1.0-specular) * pow( 1.0-hdotl,5.0 ) * glosiness;
 	
 	float ndotl=max( dot( normal,lvec ),0.0 );
 	float ndoth=max( dot( normal,hvec ),0.0 );
 	
-	vec3 light=r_LightColor.rgb * ndotl;
-	
 	specular=pow( ndoth,spow ) * fnorm * fschlick;
+
+	vec3 light=r_LightColor.rgb * ndotl * atten;
+	
+#if MX2_SHADOWEDPASS
+	light*=shadowColor();
+#endif
 	
 	return (diffuse+specular) * light;
 }
@@ -147,12 +214,7 @@ void main(){
 	
 	v_Normal=normalize( normal_r.xyz * 2.0 - 1.0 );
 	
-	float shadow=evalShadow();
-	
-	vec3 light=evalLight( color_m.rgb,color_m.a,normal_r.a );
-	
-	gl_FragColor=vec4( min( light * shadow,8.0 ),1.0 );
-	
-//	gl_FragColor=vec4( light * shadow,1.0 );
-}
+	vec3 light=lightColor( color_m.rgb,color_m.a,normal_r.a );
 
+	gl_FragColor=vec4( min( light,8.0 ),1.0 );
+}

+ 66 - 29
modules/mojo3d/graphics/shaders/material-pbr-deferred.glsl

@@ -1,8 +1,13 @@
 
-//@renderpasses 1,4
+//@renderpasses 0,16,17
 
-#define MX2_AMBIENTPASS (MX2_RENDERPASS==1)
-#define MX2_CASTSHADOWPASS (MX2_RENDERPASS==4)
+//renderpasses:
+//
+// 0 = ambient + gbuffers.
+// 16 = directional light shadowcasters.
+// 17 = point light shadowcasters.
+
+#define MX2_COLORPASS (MX2_RENDERPASS==0)
  
 //material uniforms
 
@@ -16,7 +21,7 @@ uniform mat4 i_ModelViewMatrix;
 uniform mat4 i_ModelViewProjectionMatrix;
 uniform mat3 i_ModelViewNormalMatrix;
 
-#if MX2_AMBIENTPASS
+#if MX2_COLORPASS
 
 uniform vec4 r_AmbientDiffuse;
 uniform samplerCube r_EnvTexture;
@@ -33,7 +38,15 @@ varying mat3 v_TanMatrix;
 #endif
 #endif
 
-#endif	//MX2_AMBIENTPASS
+#else	//MX2_COLORPASS
+
+#if MX2_RENDERPASS==17
+uniform float r_LightRange;
+#endif
+
+varying vec3 v_Position;
+
+#endif	//MX2_COLORPASS
 
 //@vertex
 
@@ -49,7 +62,7 @@ attribute vec4 a_Weights;
 attribute vec4 a_Bones;
 #endif
 
-#if MX2_AMBIENTPASS
+#if MX2_COLORPASS
 
 attribute vec3 a_Normal;
 #ifdef MX2_TEXTURED
@@ -59,7 +72,7 @@ attribute vec4 a_Tangent;
 #endif
 #endif
 
-#endif	//MX2_AMBIENTPASS
+#endif	//MX2_COLORPASS
 
 #ifdef MX2_BONED
 
@@ -76,7 +89,10 @@ void main(){
 		m2 * a_Position * a_Weights.z +
 		m3 * a_Position * a_Weights.a;
 		
-#if MX2_AMBIENTPASS
+	// view space position
+	v_Position=( i_ModelViewMatrix * b_Position ).xyz;
+
+#if MX2_COLORPASS
 
 	mat3 n0=mat3( m0[0].xyz,m0[1].xyz,m0[2].xyz );
 	mat3 n1=mat3( m1[0].xyz,m1[1].xyz,m1[2].xyz );
@@ -97,9 +113,6 @@ void main(){
 		n3 * a_Tangent.xyz * a_Weights.a ),a_Tangent.w );
 #endif
 
-	// view space position
-	v_Position=( i_ModelViewMatrix * b_Position ).xyz;
-
 	// viewspace normal
 	v_Normal=i_ModelViewNormalMatrix * b_Normal;
 	
@@ -114,7 +127,7 @@ void main(){
 #endif
 #endif
 	
-#endif	//MX2_AMBIENTPASS
+#endif	//MX2_COLORPASS
 	
 	gl_Position=i_ModelViewProjectionMatrix * b_Position;
 }
@@ -123,11 +136,11 @@ void main(){
 
 void main(){
 
-#if MX2_AMBIENTPASS
-
 	// view space position
 	v_Position=( i_ModelViewMatrix * a_Position ).xyz;
 
+#if MX2_COLORPASS
+
 	// viewspace normal
 	v_Normal=i_ModelViewNormalMatrix * a_Normal;
 	
@@ -142,7 +155,7 @@ void main(){
 #endif
 #endif
 
-#endif	//MX2_AMBIENTPASS
+#endif	//MX2_COLORPASS
 	
 	gl_Position=i_ModelViewProjectionMatrix * a_Position;
 }
@@ -151,14 +164,29 @@ void main(){
 
 //@fragment
 
-#if MX2_AMBIENTPASS
+vec4 FloatToRGBA( float value ){
 
-void pbr_WriteFragData( vec3 color,vec3 emissive,float metalness,float roughness,float occlusion,vec3 normal ){
+	const float MaxFloat=0.9999999;
 
-	vec3 color0=vec3( 0.04,0.04,0.04 );
+	value=clamp( value,0.0,MaxFloat );
+
+	vec4 rgba=fract( vec4( 1.0, 255.0, 65025.0, 16581375.0 ) * value );
 	
+	return rgba-rgba.yzww * vec4( 1.0/255.0, 1.0/255.0, 1.0/255.0, 0.0 );
+}
+
+float RGBAToFloat( vec4 rgba ){
+
+	return dot( rgba,vec4( 1.0, 1.0/255.0, 1.0/65025.0, 1.0/16581375.0 ) );
+}
+
+#if MX2_COLORPASS
+
+void pbrWriteFragData( vec3 color,vec3 emissive,float metalness,float roughness,float occlusion,vec3 normal ){
+
+	float glosiness=1.0-roughness;
+	vec3 color0=vec3( 0.04,0.04,0.04 );
 	vec3 diffuse=color * (1.0-metalness);
-	
 	vec3 specular=(color-color0) * metalness + color0;
 	
 	vec3 rvec=r_EnvMatrix * reflect( v_Position,normal );
@@ -173,22 +201,25 @@ void pbr_WriteFragData( vec3 color,vec3 emissive,float metalness,float roughness
 	
 	float ndotv=max( dot( normal,vvec ),0.0 );
 	
-	vec3 fschlick=specular + (1.0-specular) * pow( 1.0-ndotv,5.0 ) * (1.0-roughness);
+	vec3 fschlick=specular + (1.0-specular) * pow( 1.0-ndotv,5.0 ) * glosiness;
 
 	vec3 ambdiff=diffuse * r_AmbientDiffuse.rgb;
 		
 	vec3 ambspec=env * fschlick;
 
+	//write ambient
 	gl_FragData[0]=vec4( min( (ambdiff+ambspec) * occlusion + emissive,8.0 ),1.0 );
-
+	
+	//write color/metalness
 	gl_FragData[1]=vec4( color,metalness );
 	
+	//write normal/roughness
 	gl_FragData[2]=vec4( normal * 0.5 + 0.5,roughness );
 }
 
 #endif
 
-#if MX2_AMBIENTPASS
+#if MX2_COLORPASS
 
 #ifdef MX2_TEXTURED
 uniform sampler2D m_ColorTexture;
@@ -204,12 +235,8 @@ uniform vec4 m_EmissiveFactor;
 uniform float m_MetalnessFactor;
 uniform float m_RoughnessFactor;
 
-#endif
-
 void main(){
 
-#if MX2_AMBIENTPASS
-
 #ifdef MX2_TEXTURED
 
 	vec3 color=pow( texture2D( m_ColorTexture,v_TexCoord0 ).rgb,vec3( 2.2 ) ) * m_ColorFactor.rgb;
@@ -236,11 +263,21 @@ void main(){
 
 #endif
 
-	pbr_WriteFragData( color,emissive,metalness,roughness,occlusion,normal );
+	pbrWriteFragData( color,emissive,metalness,roughness,occlusion,normal );
+}
 	
-#else
+#else	//MX2_COLORPASS
 
-	gl_FragColor=vec4( vec3( gl_FragCoord.z ),1.0 );
+void main(){
 
+#if MX2_RENDERPASS==17
+	gl_FragColor=FloatToRGBA( length( v_Position )/r_LightRange );
+#elif defined( MX2_RGBADEPTHTEXTURES )
+	gl_FragColor=FloatToRGBA( gl_FragCoord.z );
+#else
+	gl_FragColor=vec4( vec3( gl_FragCoord.z ),1.0 );
 #endif
+
 }
+
+#endif

+ 115 - 44
modules/mojo3d/graphics/shaders/material-pbr-forward.glsl

@@ -1,9 +1,20 @@
 
-//@renderpasses 1,2,3,4
+//@renderpasses 1,2,3,6,7,10,11,14,15,16,17
 
-#define MX2_COLORPASS (MX2_RENDERPASS&3)
+//render passes:
+//
+// 1  = ambient.
+// 2  = lighting.
+// 4  = shadowed.
+// 8  = light type - 0=directional, 1=point
+// 16 = directional shadow casters.
+// 17 = point shadow casters.
+
+#define MX2_COLORPASS ((MX2_RENDERPASS&16)==0)
 #define MX2_AMBIENTPASS (MX2_RENDERPASS&1)
 #define MX2_LIGHTINGPASS (MX2_RENDERPASS&2)
+#define MX2_SHADOWEDPASS (MX2_RENDERPASS&4)
+#define MX2_DIRECTIONALLIGHT ((MX2_RENDERPASS&8)==0)
  
 //instance uniforms
 //
@@ -12,17 +23,13 @@ uniform mat4 i_ModelViewProjectionMatrix;
 uniform mat3 i_ModelViewNormalMatrix;
 
 #if defined( MX2_BONED )
-
 uniform mat4 i_ModelBoneMatrices[96];
-
 #endif
 
 //material uniforms
 
 #if MX2_COLORPASS && defined( MX2_TEXTURED )
-
 uniform mat3 m_TextureMatrix;
-
 #endif
 
 #if MX2_AMBIENTPASS
@@ -37,17 +44,30 @@ uniform mat3 r_EnvMatrix;
 
 #if MX2_LIGHTINGPASS
 
-uniform sampler2D r_ShadowTexture;
+uniform mat4 r_LightViewMatrix;
+uniform vec4 r_LightColor;
+uniform float r_LightRange;
+
+#if MX2_SHADOWEDPASS
+
+#if MX2_DIRECTIONALLIGHT
+uniform sampler2D r_ShadowCSMTexture;
+uniform vec4 r_ShadowCSMSplits;
 uniform mat4 r_ShadowMatrix0;
 uniform mat4 r_ShadowMatrix1;
 uniform mat4 r_ShadowMatrix2;
 uniform mat4 r_ShadowMatrix3;
-uniform vec4 r_ShadowSplits;
+#else
+uniform samplerCube r_ShadowCubeTexture;
+uniform mat4 r_ShadowMatrix0;
+#endif
 
-uniform mat4 r_LightViewMatrix;
-uniform vec4 r_LightColor;
-uniform float r_LightRange;
+#endif	//MX2_SHADOWEDPASS
+
+#endif	//MX2_LIGHTINGPASS
 
+#if MX2_RENDERPASS==17
+uniform float r_LightRange;
 #endif
 
 //pbr varyings...
@@ -93,6 +113,9 @@ void main(){
 		m2 * a_Position * a_Weights.z +
 		m3 * a_Position * a_Weights.a;
 		
+	// view space position
+	v_Position=( i_ModelViewMatrix * b_Position ).xyz;
+
 #if MX2_COLORPASS
 
 	mat3 n0=mat3( m0[0].xyz,m0[1].xyz,m0[2].xyz );
@@ -114,9 +137,6 @@ void main(){
 		n3 * a_Tangent.xyz * a_Weights.a ),a_Tangent.w );
 #endif
 
-	// view space position
-	v_Position=( i_ModelViewMatrix * b_Position ).xyz;
-
 	// viewspace normal
 	v_Normal=i_ModelViewNormalMatrix * b_Normal;
 	
@@ -141,7 +161,7 @@ void main(){
 void main(){
 
 	// view space position
-	v_Position=( i_ModelViewMatrix * a_Position ).xyz;
+	v_Position=(i_ModelViewMatrix * a_Position).xyz;
 
 #if MX2_COLORPASS
 
@@ -168,22 +188,41 @@ void main(){
 
 //@fragment
 
-#if MX2_LIGHTINGPASS
+vec4 FloatToRGBA( float value ){
+
+	const float MaxFloat=0.9999999;
+
+	value=clamp( value,0.0,MaxFloat );
+
+	vec4 rgba=fract( vec4( 1.0, 255.0, 65025.0, 16581375.0 ) * value );
+	
+	return rgba-rgba.yzww * vec4( 1.0/255.0, 1.0/255.0, 1.0/255.0, 0.0 );
+}
+
+float RGBAToFloat( vec4 rgba ){
+
+	return dot( rgba,vec4( 1.0, 1.0/255.0, 1.0/65025.0, 1.0/16581375.0 ) );
+}
+
+#if MX2_COLORPASS
+
+#if MX2_SHADOWEDPASS
+
+#if MX2_DIRECTIONALLIGHT
 
-float shadow_color( vec3 normal ){
+float shadowColor( vec3 normal ){
 
 	vec4 vpos=vec4( v_Position + normal * .05,1.0 );
-//	vec4 vpos=vec4( v_Position,1.0 );
 	vec4 lpos;
 	vec2 off;
 	
-	if( vpos.z<r_ShadowSplits.x ){
+	if( vpos.z<r_ShadowCSMSplits.x ){
 		lpos=r_ShadowMatrix0 * vpos;
 		off=vec2( 0.0,0.0 );
-	}else if( vpos.z<r_ShadowSplits.y ){
+	}else if( vpos.z<r_ShadowCSMSplits.y ){
 		lpos=r_ShadowMatrix1 * vpos;
 		off=vec2( 0.5,0.0 );
-	}else if( vpos.z<r_ShadowSplits.z ){
+	}else if( vpos.z<r_ShadowCSMSplits.z ){
 		lpos=r_ShadowMatrix2 * vpos;
 		off=vec2( 0.0,0.5 );
 	}else{
@@ -194,19 +233,38 @@ float shadow_color( vec3 normal ){
 	vec3 spos=lpos.xyz/lpos.w * vec3( 0.25,0.25,0.5 ) + vec3( 0.25,0.25,0.5 );
 
 //	spos.z*=0.999;
-	
-	float d=texture2D( r_ShadowTexture,spos.xy+off ).r;
+
+#if defined( MX2_RGBADEPTHTEXTURES )
+	float d=RGBAToFloat( texture2D( r_ShadowCSMTexture,spos.xy+off ) );
+#else
+	float d=texture2D( r_ShadowCSMTexture,spos.xy+off ).r;
+#endif
 	
 	if( spos.z>d ) return 0.0;
 	
 	return 1.0;
 }
 
-#endif
+#else	//MX2_DIRECTIONALLIGHT
 
-#if MX2_COLORPASS
+float shadowColor( vec3 normal ){
+
+	vec4 vpos=vec4( v_Position + normal * .05,1.0 );
+	
+	vec3 lpos=(r_ShadowMatrix0 * vpos).xyz;
+	
+	float d=RGBAToFloat( textureCube( r_ShadowCubeTexture,lpos ) );
+	
+	if( length(lpos) > d * r_LightRange ) return 0.0;
+	
+	return 1.0;
+}
 
-vec3 pbr_linear_frag_color( vec3 color,vec3 emissive,float metalness,float roughness,float occlusion,vec3 normal ){
+#endif	//MX2_DIRECTIONALLIGHT
+
+#endif	//MX2_SHADOWEDPASS
+
+vec3 fragColor( vec3 color,vec3 emissive,float metalness,float roughness,float occlusion,vec3 normal ){
 
 	float glosiness=1.0-roughness;
 	vec3 color0=vec3( 0.04,0.04,0.04 );
@@ -214,7 +272,7 @@ vec3 pbr_linear_frag_color( vec3 color,vec3 emissive,float metalness,float rough
 	vec3 specular=(color-color0) * metalness + color0;
 	vec3 vvec=normalize( -v_Position );
 	
-	vec3 frag_color=vec3( 0.0 );
+	vec3 frag=vec3( 0.0 );
 
 #if MX2_AMBIENTPASS
 	
@@ -231,9 +289,9 @@ vec3 pbr_linear_frag_color( vec3 color,vec3 emissive,float metalness,float rough
 
 	vec3 ambdiff=diffuse * r_AmbientDiffuse.rgb;
 	vec3 ambspec=ambenv * fschlick1;
-	frag_color+=(ambdiff+ambspec) * occlusion + emissive;
+	frag+=(ambdiff+ambspec) * occlusion + emissive;
 
-#endif
+#endif	//MX2_AMBIENTPASS
 
 #if MX2_LIGHTINGPASS
 
@@ -241,8 +299,17 @@ vec3 pbr_linear_frag_color( vec3 color,vec3 emissive,float metalness,float rough
 	
 	float spow=pow( 2.0,glosiness * 12.0 );				//specular power
 	float fnorm=(spow+2.0)/8.0;							//normalization factor
+	float atten=1.0;
+	
+#if MX2_DIRECTIONALLIGHT
+	vec3 lvec=normalize( -r_LightViewMatrix[2].xyz );
+#else
+	vec3 lvec=r_LightViewMatrix[3].xyz-v_Position;
+	float ldist=length( lvec );
+    lvec/=ldist;
+	atten=max( 1.0-(ldist/r_LightRange),0.0 );
+#endif
 	
-	vec3 lvec=normalize( -r_LightViewMatrix[2].xyz );	//vector to light
 	vec3 hvec=normalize( lvec+vvec );					//halfway vector
 
 	float hdotl=max( dot( hvec,lvec ),0.0 );
@@ -254,21 +321,21 @@ vec3 pbr_linear_frag_color( vec3 color,vec3 emissive,float metalness,float rough
 	
 	vec3 lightspec=pow( ndoth,spow ) * fschlick2 * fnorm;
 	
-	vec3 light=(diffuse+lightspec) * r_LightColor.rgb * ndotl;
-
-	float shadow=shadow_color( normal );
+	vec3 light=(diffuse+lightspec) * r_LightColor.rgb * ndotl * atten;
 
-	frag_color+=light*shadow;
+#if MX2_SHADOWEDPASS
+	float shadow=shadowColor( normal );
 	
+	light*=shadow;
 #endif
 
-	return frag_color;
-}
+	frag+=light;
+	
+#endif	//MX2_LIGHTINGPASS
 
-#endif
+	return frag;
+}
 
-#if MX2_COLORPASS
- 
 #if defined( MX2_TEXTURED)
 uniform sampler2D m_ColorTexture;
 uniform sampler2D m_EmissiveTexture;
@@ -308,12 +375,12 @@ void main(){
 	vec3 normal=normalize( v_Normal );
 #endif
 
-	vec3 frag_color=pbr_linear_frag_color( color,emissive,metalness,roughness,occlusion,normal );
+	vec3 frag=fragColor( color,emissive,metalness,roughness,occlusion,normal );
 	
 #if defined( MX2_SRGBOUTPUT )
-	gl_FragColor=vec4( pow( frag_color,vec3( 1.0/2.2 ) ),1.0 );
+	gl_FragColor=vec4( pow( frag,vec3( 1.0/2.2 ) ),1.0 );
 #else
-	gl_FragColor=vec4( frag_color,1.0 );
+	gl_FragColor=vec4( frag,1.0 );
 #endif
 }
 
@@ -321,10 +388,14 @@ void main(){
 
 void main(){
 
+#if MX2_RENDERPASS==17
+	gl_FragColor=FloatToRGBA( min( length( v_Position )/r_LightRange,1.0 ) );
+#elif defined( MX2_RGBADEPTHTEXTURES )
+	gl_FragColor=FloatToRGBA( gl_FragCoord.z ),1.0 );
+#else
 	gl_FragColor=vec4( vec3( gl_FragCoord.z ),1.0 );
+#endif
 
 }
 
 #endif	//MX2_COLORPASS
-
-

+ 31 - 26
modules/mojo3d/tests/ducks.monkey2

@@ -17,18 +17,18 @@ Class MyWindow Extends Window
 	
 	Field _scene:Scene
 	
+	Field _fog:FogEffect
+
 	Field _camera:Camera
 	
 	Field _light:Light
 	
+	Field _light2:Light
+	
 	Field _ground:Model
 	
 	Field _ducks:=New Stack<Model>
 	
-	Field _fog:FogEffect
-	
-	Field _monochrome:MonochromeEffect
-	
 	Method New( title:String="Simple mojo app",width:Int=640,height:Int=480,flags:WindowFlags=WindowFlags.Resizable )
 
 		Super.New( title,width,height,flags )
@@ -39,37 +39,43 @@ Class MyWindow Extends Window
 		'		
 		_scene=Scene.GetCurrent()
 
-		'fog effect
+		'add fog effect to scene
 		'		
 		_fog=New FogEffect
 		_fog.Color=Color.Sky
 		_fog.Near=0
-		_fog.Far=20
+		_fog.Far=50
 		_scene.AddPostEffect( _fog )
 		
-		'_scene.SkyTexture=Texture.Load( "asset::miramar-skybox.jpg",TextureFlags.FilterMipmap|TextureFlags.Cubemap )
-		
 		'create camera
 		'
 		_camera=New Camera
 		_camera.Near=.1
-		_camera.Far=100
+		_camera.Far=50
+		_camera.FOV=90
 		_camera.Move( 0,15,-20 )
 		
 		'create light
 		'
-		_light=New Light
-		_light.RotateX( 90 )	'aim directional light downwards
+'		_light=New Light
+'		_light.Type=LightType.Directional
+'		_light.RotateX( 75 )	'aim directional light downwards
+		
+		_light2=New Light
+		_light2.Type=LightType.Point
+		_light2.Move( 0,20,0 )
+		_light2.Range=40
+		_light2.ShadowsEnabled=True
 
 		'create ground
 		'
-		_ground=Model.CreateBox( New Boxf( -50,-1,-50,50,0,50 ),1,1,1,New PbrMaterial( Color.Green,0,1 ) )
+		_ground=Model.CreateBox( New Boxf( -50,-1,-50,50,0,50 ),10,10,10,New PbrMaterial( Color.Green,0,1 ) )
+		_ground.CastsShadow=False
 		
 		'create ducks
 		'		
 		Local duck:=Model.Load( "asset::duck.gltf/Duck.gltf" )
 		duck.Mesh.FitVertices( New Boxf( -1,1 ) )
-'		duck.CastsShadow=False
 		
 		Local root:=duck.Copy()
 		root.Move( 0,10,0 )
@@ -77,6 +83,8 @@ Class MyWindow Extends Window
 		
 		_ducks.Push( root )
 		
+		'#rem
+		
 		For Local m:=0.0 To 1.0 Step .125
 		
 			For Local i:=0.0 Until 360.0 Step 24
@@ -104,6 +112,8 @@ Class MyWindow Extends Window
 			Next
 		Next
 		
+		'#End
+		
 		duck.Destroy()
 	End
 	
@@ -111,18 +121,8 @@ Class MyWindow Extends Window
 
 		RequestRender()
 		
-		'Space to toggle monochrome mode!
-		If Keyboard.KeyHit( Key.Space ) _monochrome.Enabled=Not _monochrome.Enabled
-			
-		'_monochrome.Level=Sin( Now()*3 ) * .5 + .5
-		
 		_ducks[0].RotateY( 1 )
-		
-		For Local duck:=Eachin _ducks
-			
-			'duck.RotateY( 1 )
-		Next
-		
+
 		util.Fly( _camera,Self )
 		
 		_scene.Render( canvas,_camera )
@@ -138,9 +138,14 @@ Function Main()
 	
 	Local config:=New StringMap<String>
 
-	config["GL_depth_buffer_enabled"]=1
-	config["mojo3d_renderer"]="forward"
+'	config["mojo3d_renderer"]="deffered"		'defeault on non-mobile targets.
 
+'	config["mojo3d_renderer"]="forward-direct"	'default on mobile targets. depth buffer must be enabled.
+ 
+'	config["mojo3d_renderer"]="forward"
+
+'	config["GL_depth_buffer_enabled"]=1
+	
 	New AppInstance( config )
 	
 	New MyWindow