Browse Source

Shader fixes + first attempt at a godrays effect.

Mark Sibly 7 years ago
parent
commit
0667a05bca

+ 30 - 16
modules/mojo3d-loaders/tests/castle.monkey2

@@ -6,8 +6,8 @@ Namespace myapp
 #Import "<mojo3d-loaders>"
 
 #Import "assets/castle/@/castle"
-#Import "../../mojo3d/tests/assets/heightmap_256.BMP"
-#Import "../../mojo3d/tests/assets/mossy-ground1.pbr@/mossy-ground1.pbr"
+#Import "../../mojo3d/tests/assets/terrain_256.png"
+#Import "../../mojo3d/tests/assets/mossy.pbr@/mossy.pbr"
 
 '#Import "../../mojo3d/tests/assets/miramar-skybox.jpg"
 
@@ -226,13 +226,17 @@ Class MyWindow Extends Window
 	
 	Field _camera:Camera
 	
+	Field _light:Light
+	
+	Field _godrays:GodraysEffect
+	
 	Method CreateTerrain:Model()
 		
 		Local box:=New Boxf( -256,-32,-256,256,0,256 )
 		
-		Local hmap:=Pixmap.Load( "asset::heightmap_256.BMP",PixelFormat.I8 )
+		Local hmap:=Pixmap.Load( "asset::terrain_256.png",PixelFormat.I8 )
 
-		Local material:=PbrMaterial.Load( "asset::mossy-ground1.pbr" )
+		Local material:=PbrMaterial.Load( "asset::mossy.pbr" )
 		material.ScaleTextureMatrix( 64,64 )
 		
 		'model+mesh
@@ -288,11 +292,13 @@ Class MyWindow Extends Window
 	
 	Method CreateScene:Scene()
 		
-		Local scene:=New Scene
+		_scene=New Scene
+		
+		_scene.AmbientLight=Color.Black
+		_scene.ClearColor=Color.Black
+'		_scene.EnvColor=Color.Black
 		
-		Local light:=New Light
-		light.Rotate( 60,30,0 )	'aim directional light 'down' - Pi/2=90 degrees.
-		light.CastsShadow=True
+		_scene.ShadowAlpha=1
 		
 		Local terrain:=CreateTerrain()
 		
@@ -300,22 +306,30 @@ Class MyWindow Extends Window
 		
 		_player=CreatePlayer()
 		
-		Local camera:=New Camera( _player )
-		camera.View=Self
-		camera.LocalPosition=New Vec3f( 0,.5,0 )
-		camera.RotateX( 45 )
-		camera.Move( 0,0,-2 )
+		_camera=New Camera( _player )
+		_camera.View=Self
+		_camera.LocalPosition=New Vec3f( 0,.5,0 )
+		_camera.RotateX( 45 )
+		_camera.Move( 0,0,-2 )
+
+'		Return _scene
+		
+		_light=New Light
+		_light.Rotate( 60,30,0 )	'aim directional light 'down' - Pi/2=90 degrees.
+		_light.CastsShadow=True
 		
-		_camera=camera
+		_godrays=New GodraysEffect
+		_godrays.Light=_light
+		_scene.AddPostEffect( _godrays )
 		
-		Return scene
+		Return _scene
 	End
 	
 	Method New( title:String="Simple mojo app",width:Int=640,height:Int=480,flags:WindowFlags=WindowFlags.Resizable )
 
 		Super.New( title,width,height,flags )
 		
-		_scene=CreateScene()
+		CreateScene()
 	End
 		
 	Method OnRender( canvas:Canvas ) Override

+ 58 - 0
modules/mojo3d/assets/shaders/effects/godrays.glsl

@@ -0,0 +1,58 @@
+
+//@renderpasses 0
+
+uniform sampler2D r_SourceBuffer;
+uniform sampler2D r_DepthBuffer;
+
+uniform vec2 r_SourceBufferScale;
+
+varying vec2 v_SourceBufferCoords;
+
+//@vertex
+
+attribute vec2 a_Position;
+	
+void main(){
+
+	v_SourceBufferCoords=a_Position * r_SourceBufferScale;
+
+	gl_Position=vec4( a_Position * 2.0 - 1.0,-1.0,1.0 );
+}
+
+//@fragment
+
+uniform vec2 m_LightPosBufferCoords;
+
+uniform int m_NumSamples;
+
+uniform float m_Exposure;
+
+uniform float m_Decay;
+
+uniform float m_Density;
+
+uniform vec4 m_Color;
+
+void main(){
+
+	vec2 coords=v_SourceBufferCoords;
+
+	vec2 delta=m_LightPosBufferCoords-coords;
+	
+	delta*=1.0/float( m_NumSamples ) * m_Density;
+	
+	vec3 fragColor=vec3( 0.0 );
+	
+	for( int i=0;i<m_NumSamples;++i ){
+	
+		coords+=delta;
+
+		float depth=texture2D( r_DepthBuffer,coords ).r;
+		
+		vec3 sample=(depth==1.0) ? m_Color.rgb : vec3( 0.0 );
+		
+		fragColor+=sample;
+	}
+	
+	gl_FragColor=vec4( fragColor*m_Exposure,1.0 );
+}

+ 1 - 1
modules/mojo3d/assets/shaders/misc/fog-deferred.glsl

@@ -22,7 +22,7 @@ void main(){
 
 		depth=viewDepth( depth );
 		
-		vec4 vpos4=r_InverseProjectionMatrix * vec4( v_ClipPosition,-1.0,1.0 );
+		vec4 vpos4=r_InverseProjectionMatrix * vec4( v_ClipPosition*2.0-1.0,-1.0,1.0 );
 		
 		vec3 vpos=vpos4.xyz/vpos4.w;
 		

+ 1 - 1
modules/mojo3d/assets/shaders/misc/skybox.glsl

@@ -14,7 +14,7 @@ void main(){
 
 void main(){
 
-	vec4 clip=r_InverseProjectionMatrix * vec4( v_ClipPosition,1.0,1.0 );
+	vec4 clip=r_InverseProjectionMatrix * vec4( v_ClipPosition*2.0-1.0,1.0,1.0 );
 	
 	vec3 tv=r_EnvMatrix * (clip.xyz/clip.w);
 	

+ 1 - 0
modules/mojo3d/mojo3d.monkey2

@@ -53,6 +53,7 @@ Using reflection..
 #Import "scene/effects/bloomeffect"
 #Import "scene/effects/monochromeeffect"
 #Import "scene/effects/reflectioneffect"
+#Import "scene/effects/godrayseffect"
 
 #Import "scene/jsonifier/jsonifier"
 #Import "scene/jsonifier/invocation"

+ 145 - 0
modules/mojo3d/scene/effects/godrayseffect.monkey2

@@ -0,0 +1,145 @@
+
+Namespace mojo3d
+
+#rem monkeydoc The MonochromeEffect class.
+#end
+Class GodraysEffect Extends PostEffect
+
+	#rem monkeydoc Creates a new monochrome effect shader.
+	#end
+	Method New()
+		
+		_shader=Shader.Open( "effects/godrays" )
+		
+		_uniforms=New UniformBlock( 3 )
+		
+		NumSamples=100
+		Exposure=.0034
+		Decay=1.0
+		Density=0.84
+		Color=Color.White
+		Weight=.1
+	End
+	
+	Property Light:Light()
+		
+		Return _light
+	
+	Setter( light:Light )
+		
+		_light=light
+	End
+	
+	Property NumSamples:Int()
+		
+		Return _uniforms.GetInt( "NumSamples" )
+	
+	Setter( samples:Int )
+		
+		_uniforms.SetInt( "NumSamples",samples )
+	End
+	
+	Property Exposure:Float()
+		
+		Return _uniforms.GetFloat( "Exposure" )
+		
+	Setter( exposure:Float )
+		
+		_uniforms.SetFloat( "Exposure",exposure )
+	End
+	
+	Property Decay:Float()
+		
+		Return _uniforms.GetFloat( "Decay" )
+		
+	Setter( decay:Float )
+		
+		_uniforms.SetFloat( "Decay",decay )
+	End
+	
+	Property Density:Float()
+		
+		Return _uniforms.GetFloat( "Density" )
+		
+	Setter( density:Float )
+		
+		_uniforms.SetFloat( "Density",density )
+	End
+	
+	Property Color:Color()
+		
+		Return _color
+	
+	Setter( color:Color )
+		
+		_color=color
+		
+		_uniforms.SetColor( "Color",_color * _weight )
+	End
+	
+	Property Weight:Float()
+		
+		Return _weight
+	
+	Setter( weight:Float )
+		
+		_weight=weight
+		
+		_uniforms.SetColor( "Color",_color * _weight )
+	End
+	
+	Protected
+	
+	Method OnRender( target:RenderTarget,viewport:Recti ) Override
+		
+		If Not _light Return
+		
+		'computer light pos in buffer coords
+		Local viewProj:=Uniforms.GetMat4f( "ViewProjectionMatrix" )
+
+		Local lightClipPos:=viewProj * New Vec4f( -_light.Basis.k,0 )	'clip
+		
+		If lightClipPos.w<=0 return
+		
+'		If lightClipPos.x<-lightClipPos.w Or lightClipPos.x>lightClipPos.w Return
+'		If lightClipPos.y<-lightClipPos.w Or lightClipPos.y>lightClipPos.w Return
+		If lightClipPos.z<-lightClipPos.w Return 'Or lightClipPos.z>lightClipPos.w Return
+		
+		Local lightPos:=lightClipPos.XY/lightClipPos.w * 0.5 + 0.5		'NDC
+		
+		lightPos*=SourceBufferScale	'buffer
+		
+		'set effect uniforms
+		_uniforms.SetVec2f( "LightPosBufferCoords",lightPos )
+		
+		'render!
+		#rem
+		Local size:=viewport.Size
+		Local source:=target.GetColorTexture( 0 )
+		
+		If Not _target Or size.x>_target.Size.x Or size.y>_target.Size.y
+			_target=CreateRenderTarget( size,source.Format,TextureFlags.Dynamic )
+		End
+		
+		Super.SetRenderTarget( _target,New Recti( 0,0,size ) )
+		#end
+
+		Device.Shader=_shader
+		Device.BindUniformBlock( _uniforms )
+		
+		Device.BlendMode=BlendMode.Additive
+		
+		RenderQuad()
+	End
+	
+	Private
+	
+	Field _light:Light
+	Field _color:Color
+	Field _weight:Float
+	
+	Field _shader:Shader
+	Field _uniforms:UniformBlock
+	Field _target:RenderTarget
+	
+End

+ 37 - 7
modules/mojo3d/scene/posteffect.monkey2

@@ -31,6 +31,8 @@ Class PostEffect
 
 		_gdevice=gdevice
 		_runiforms=runiforms
+		
+		UpdateSourceBuffer()
 	End
 	
 	Function EndRendering()
@@ -50,6 +52,21 @@ Class PostEffect
 		Return _gdevice
 	End
 	
+	Property Uniforms:UniformBlock()
+		
+		Return _runiforms
+	End
+	
+	Property SourceBufferSize:Vec2f()
+		
+		Return _sourceBufferSize
+	End
+	
+	Property SourceBufferScale:Vec2f()
+		
+		Return _sourceBufferScale
+	End
+	
 	Method CreateRenderTarget:RenderTarget( size:Vec2i,format:PixelFormat,flags:TextureFlags )
 		
 		Local texture:=New Texture( size.x,size.y,format,flags )
@@ -59,14 +76,8 @@ Class PostEffect
 	
 	Method SetRenderTarget( target:RenderTarget,viewport:Recti )
 		
-		Local rsize:=_gdevice.Viewport.Size
-		Local rtarget:=_gdevice.RenderTarget
-		Local rtexture:=rtarget.GetColorTexture( 0 )
-		_runiforms.SetTexture( "SourceBuffer",rtexture )
-		_runiforms.SetVec2f( "SourceBufferSize",Cast<Vec2f>( rtexture.Size ) )'rsize ) )
-		_runiforms.SetVec2f( "SourceBufferScale",Cast<Vec2f>( rsize )/Cast<Vec2f>( rtexture.Size ) )
-		
 		_gdevice.RenderTarget=target
+		
 		_gdevice.Viewport=viewport
 	End
 	
@@ -85,6 +96,8 @@ Class PostEffect
 		_gdevice.VertexBuffer=_vertices
 		
 		_gdevice.Render( 4,1 )
+		
+		UpdateSourceBuffer()
 	End
 	
 	#rem monkeydoc @hidden
@@ -93,7 +106,24 @@ Class PostEffect
 	
 	Global _gdevice:GraphicsDevice
 	Global _runiforms:UniformBlock
+	Global _sourceBufferSize:Vec2f
+	Global _sourceBufferScale:Vec2f
 	
 	Field _enabled:Bool=True
 	
+	function UpdateSourceBuffer()
+
+		Local rsize:=_gdevice.Viewport.Size
+		Local rtarget:=_gdevice.RenderTarget
+		Local rtexture:=rtarget.GetColorTexture( 0 )
+		
+		_sourceBufferSize=Cast<Vec2f>( rtexture.Size )
+		_sourceBufferScale=Cast<Vec2f>( rsize )/Cast<Vec2f>( rtexture.Size )
+		
+		_runiforms.SetTexture( "SourceBuffer",rtexture )
+		_runiforms.SetVec2f( "SourceBufferSize",_sourceBufferSize )
+		_runiforms.SetVec2f( "SourceBufferScale",_sourceBufferScale )
+	End
+	
+	
 End

+ 24 - 11
modules/mojo3d/tests/effects.monkey2

@@ -24,6 +24,8 @@ Class MyWindow Extends Window
 	
 	Field _mono:MonochromeEffect
 	
+	Field _godrays:GodraysEffect
+	
 	Method New( title:String="Simple mojo app",width:Int=640,height:Int=480,flags:WindowFlags=WindowFlags.Resizable )
 
 		Super.New( title,width,height,flags )
@@ -31,14 +33,6 @@ Class MyWindow Extends Window
 		_scene=Scene.GetCurrent()
 		_scene.ClearColor=Color.Black
 		
-		_bloom=New BloomEffect
-		_bloom.Enabled=True
-		_scene.AddPostEffect( _bloom )
-		
-		_mono=New MonochromeEffect
-		_mono.Enabled=False
-		_scene.AddPostEffect( _mono )
-		
 		'create camera
 		'
 		_camera=New Camera( self )
@@ -48,7 +42,24 @@ Class MyWindow Extends Window
 		'create light
 		'
 		_light=New Light
-		_light.RotateX( 90 )
+		_light.Rotate( 120,0,0 )
+
+		'create effects
+		'
+		_bloom=New BloomEffect
+		_bloom.Enabled=True
+		_scene.AddPostEffect( _bloom )
+		
+		_mono=New MonochromeEffect
+		_mono.Enabled=False
+		_scene.AddPostEffect( _mono )
+
+		_godrays=New GodraysEffect
+		_godrays.Enabled=false
+		_godrays.Weight=4.0
+		_godrays.Light=_light
+		
+		_scene.AddPostEffect( _godrays )
 		
 		Local material:=New PbrMaterial( New Color( 2,.5,0,1 ),0,1 )
 		
@@ -63,14 +74,16 @@ Class MyWindow Extends Window
 		RequestRender()
 		
 		If Keyboard.KeyHit( Key.Key1 ) _bloom.Enabled=Not _bloom.Enabled
-
 		If Keyboard.KeyHit( Key.Key2 ) _mono.Enabled=Not _mono.Enabled
+		If Keyboard.KeyHit( Key.Key3 ) _godrays.Enabled=Not _godrays.Enabled
 		
 		_scene.Update()
 		
 		_scene.Render( canvas )
 		
-		canvas.DrawText( "Bloom="+_bloom.Enabled+" (1) monochrome="+_mono.Enabled+" (2)",0,0 )
+		canvas.DrawText( "(1) Bloom="+_bloom.Enabled,0,0 )
+		canvas.DrawText( "(2) Monochrome="+_mono.Enabled,0,16 )
+		canvas.DrawText( "(3) Godrays="+_godrays.Enabled,0,32 )
 	End
 	
 End