-
Notifications
You must be signed in to change notification settings - Fork 229
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Very simple shadow mapping post processing effect.
- Loading branch information
1 parent
f156260
commit ee9cd9b
Showing
2 changed files
with
108 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
/* | ||
Very simple shadow mapping post processing effect. | ||
In Unity Editor: | ||
- Create New Scene; | ||
- Add ShadowMapping component to Main Camera | ||
- Assign "ShadowMapping" shader | ||
- Add "3D Object/Sphere" to the hierarchy window and assign as Light in ShadowMapping component | ||
- Add some geometry to the scene (for example terrain component) | ||
- Play (shadows will be only visible in Game View) | ||
- Light object now has added light camera component. Change light camera properties to change field of view etc. In scene view, see light camera frustum. | ||
- Play with Shadow Bias parameter | ||
*/ | ||
|
||
using UnityEngine; | ||
|
||
public class ShadowMapping : MonoBehaviour | ||
{ | ||
public Shader ShadowMappingShader; | ||
public GameObject Light; | ||
[Range(0.0f, 5.0f)] public float ShadowBias = 1.0f; | ||
public bool InvertY = true; | ||
|
||
private Camera _LightCamera; | ||
private Camera _MainCamera; | ||
private Material _Material; | ||
private RenderTexture _RenderTexture; | ||
|
||
void Start() | ||
{ | ||
_LightCamera = Light.AddComponent<Camera>(); | ||
_LightCamera.renderingPath = RenderingPath.DeferredShading; | ||
_MainCamera = this.gameObject.GetComponent<Camera>(); | ||
_MainCamera.depthTextureMode = _LightCamera.depthTextureMode = DepthTextureMode.Depth; | ||
_Material = new Material(ShadowMappingShader); | ||
_RenderTexture = new RenderTexture(4096, 4096, 32, RenderTextureFormat.Depth); | ||
_RenderTexture.Create(); | ||
_LightCamera.targetTexture = _RenderTexture; | ||
} | ||
|
||
void OnRenderImage (RenderTexture source, RenderTexture destination) | ||
{ | ||
_LightCamera.Render(); | ||
Matrix4x4 lightViewProjection = GL.GetGPUProjectionMatrix(_LightCamera.projectionMatrix, true) * _LightCamera.worldToCameraMatrix; | ||
_Material.SetMatrix("_LightViewProjection", lightViewProjection); | ||
_Material.SetFloat("_ShadowBias", ShadowBias); | ||
_Material.SetFloat("_InvertY", System.Convert.ToSingle(InvertY)); | ||
Matrix4x4 m = GL.GetGPUProjectionMatrix(_MainCamera.projectionMatrix, false); | ||
m[2, 3] = m[3, 2] = 0.0f; m[3, 3] = 1.0f; | ||
Matrix4x4 projectionToWorld = Matrix4x4.Inverse(m * _MainCamera.worldToCameraMatrix) * Matrix4x4.TRS(new Vector3(0, 0, -m[2,2]), Quaternion.identity, Vector3.one); | ||
_Material.SetMatrix("_ProjectionToWorld", projectionToWorld); | ||
Graphics.Blit (source, destination, _Material); | ||
} | ||
|
||
void OnDestroy() | ||
{ | ||
_RenderTexture.Release(); | ||
Destroy(_Material); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
Shader "ShadowMapping" | ||
{ | ||
Properties | ||
{ | ||
[HideInInspector] _MainTex ("Texture", 2D) = "black" {} | ||
} | ||
SubShader | ||
{ | ||
Pass | ||
{ | ||
CGPROGRAM | ||
#pragma vertex VSMain | ||
#pragma fragment PSMain | ||
#pragma target 5.0 | ||
|
||
float4x4 _ProjectionToWorld, _LightViewProjection; | ||
sampler2D _CameraDepthTexture, _LastCameraDepthTexture, _MainTex; | ||
float _ShadowBias, _InvertY; | ||
|
||
float4 VSMain (in float4 vertex : POSITION, inout float2 uv : TEXCOORD0, out float3 direction : TEXCOORD1) : SV_POSITION | ||
{ | ||
float4 position = UnityObjectToClipPos(vertex); | ||
direction = mul(_ProjectionToWorld, float4(position.xy, 0.0, 1.0)) - _WorldSpaceCameraPos; | ||
return position; | ||
} | ||
|
||
void PSMain (float4 vertex : SV_POSITION, float2 uv : TEXCOORD0, float3 direction : TEXCOORD1, out float4 fragColor : SV_TARGET) | ||
{ | ||
float sceneDepth = 1.0 / (_ZBufferParams.z * tex2D(_CameraDepthTexture, uv.xy) + _ZBufferParams.w); | ||
float3 worldSpace = direction * sceneDepth + _WorldSpaceCameraPos; | ||
float4 shadowCoord = mul(_LightViewProjection, float4(worldSpace, 1.0)); | ||
float2 projCoords = (shadowCoord.xy / shadowCoord.w) * 0.5 + 0.5; | ||
float depth = (shadowCoord.z / shadowCoord.w); | ||
if (_InvertY > 0.5f) projCoords.y = 1.0 - projCoords.y; | ||
float closestDepth = 1.0 / (_ZBufferParams.z * tex2D(_LastCameraDepthTexture, projCoords.xy).r + _ZBufferParams.w); | ||
float currentDepth = 1.0 / (_ZBufferParams.z * depth + _ZBufferParams.w); | ||
float shadow = ((currentDepth - _ShadowBias) < closestDepth) || (depth > 0.5) ? 0.0 : 1.0; | ||
float4 color = float4(1.0 - shadow.xxx, 1.0); | ||
bool isLightFrustum = depth > 0.0; | ||
isLightFrustum = isLightFrustum && projCoords.x >= 0.0 && projCoords.x <= 1.0; | ||
isLightFrustum = isLightFrustum && projCoords.y >= 0.0 && projCoords.y <= 1.0; | ||
isLightFrustum = isLightFrustum && sceneDepth <= (_ProjectionParams.z - _ProjectionParams.y); | ||
float4 baseColor = tex2D(_MainTex, uv); | ||
fragColor = isLightFrustum ? ((color.r > 0.5) ? baseColor * float4(1,1,1,1) : baseColor * float4(0,0,0,1)) : baseColor; | ||
} | ||
ENDCG | ||
} | ||
} | ||
} |