forked from keijiro/Prisma
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
287 additions
and
13 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
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,118 @@ | ||
using UnityEngine; | ||
using UnityEngine.Rendering; | ||
|
||
namespace Prisma | ||
{ | ||
// | ||
// Shadow Slicer | ||
// | ||
// In the previous versions of the Pepper's ghost rig, I used a secondary | ||
// camera to render shadows on the background wall. This is very costly | ||
// because it needs generating whole shadow maps twice (Unity never shares | ||
// shadow maps between cameras). | ||
// | ||
// This "Shadow Slicer" is designed to eliminate the cost of the secondary | ||
// camera. It renders the shadows on the wall with reusing the shadow maps | ||
// generated by the main camera. | ||
// | ||
// How it works: The shadow slicer renders the shadows by hijacking the | ||
// forward-opaque pass of the main camera -- the other parts of this | ||
// project only use the deferred shading pass, so we can safely mess it up! | ||
// | ||
// 1. (Before Forward Opaque) Make a backup of the color buffer. | ||
// 2. (Forward Base) Clear the color buffer with a full-screen quad. | ||
// 3. (Forward Add) Draw a full-screen quad with shadow maps. | ||
// 4. (After Forward Opaque) Retrieve the results and restore the backup. | ||
// | ||
// One of the biggest disadvantages of this approach is that we can't use | ||
// directional lights with it (in Unity 5.x, shadow maps with directional | ||
// lights are flatten into screen-space shadow masks while rendering, so | ||
// we can't "slice" these shadows in the later passes). | ||
// | ||
public class ShadowSlicer : MonoBehaviour | ||
{ | ||
#region Exposed attributes | ||
|
||
[SerializeField] Camera _baseCamera; | ||
[SerializeField] RenderTexture _targetTexture; | ||
[SerializeField, ColorUsage(false)] Color _albedo = Color.white; | ||
|
||
#endregion | ||
|
||
#region Built-in resources | ||
|
||
[SerializeField, HideInInspector] Mesh _quadMesh; | ||
[SerializeField, HideInInspector] Shader _slicerShader; | ||
|
||
#endregion | ||
|
||
#region Private objects | ||
|
||
Material _slicerMaterial; | ||
RenderTexture _backupBuffer; | ||
CommandBuffer _backupCommand; | ||
CommandBuffer _restoreCommand; | ||
|
||
#endregion | ||
|
||
#region MonoBehaviour functions | ||
|
||
void OnEnable() | ||
{ | ||
var width = _baseCamera.pixelWidth; | ||
var height = _baseCamera.pixelHeight; | ||
|
||
_backupBuffer = RenderTexture.GetTemporary(width, height, 0); | ||
|
||
if (_backupCommand == null) | ||
{ | ||
_backupCommand = new CommandBuffer(); | ||
_backupCommand.name = "Shadow Slicer (Backup)"; | ||
_backupCommand.Blit(BuiltinRenderTextureType.CurrentActive, _backupBuffer); | ||
} | ||
|
||
if (_restoreCommand == null) | ||
{ | ||
_restoreCommand = new CommandBuffer(); | ||
_restoreCommand.name = "Shadow Slicer (Restore)"; | ||
_restoreCommand.Blit(BuiltinRenderTextureType.CurrentActive, _targetTexture); | ||
_restoreCommand.Blit(_backupBuffer, BuiltinRenderTextureType.CameraTarget); | ||
} | ||
|
||
_baseCamera.AddCommandBuffer(CameraEvent.BeforeForwardOpaque, _backupCommand); | ||
_baseCamera.AddCommandBuffer(CameraEvent.AfterForwardOpaque, _restoreCommand); | ||
} | ||
|
||
void OnDisable() | ||
{ | ||
if (_baseCamera != null) | ||
{ | ||
_baseCamera.RemoveCommandBuffer(CameraEvent.BeforeForwardOpaque, _backupCommand); | ||
_baseCamera.RemoveCommandBuffer(CameraEvent.AfterForwardOpaque, _restoreCommand); | ||
} | ||
} | ||
|
||
void OnDestroy() | ||
{ | ||
if (_slicerMaterial != null) Destroy(_slicerMaterial); | ||
if (_backupBuffer != null) RenderTexture.ReleaseTemporary(_backupBuffer); | ||
if (_backupCommand != null) _backupCommand.Dispose(); | ||
if (_restoreCommand != null) _restoreCommand.Dispose(); | ||
} | ||
|
||
void Update() | ||
{ | ||
if (_slicerMaterial == null) | ||
_slicerMaterial = new Material(_slicerShader); | ||
|
||
_slicerMaterial.SetColor("_Color", _albedo); | ||
|
||
Graphics.DrawMesh( | ||
_quadMesh, transform.localToWorldMatrix, _slicerMaterial, | ||
gameObject.layer, _baseCamera | ||
); | ||
} | ||
|
||
#endregion | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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,83 @@ | ||
// Shadow Slicer shader: See ShadowSlicer.cs for details. | ||
|
||
Shader "Hidden/Prisma/ShadowSlicer" | ||
{ | ||
Properties | ||
{ | ||
_Color("", Color) = (1, 1, 1, 1) | ||
} | ||
SubShader | ||
{ | ||
ZTest always ZWrite off | ||
|
||
// Forward base: draws black full-screen quad. | ||
Pass | ||
{ | ||
Tags { "LightMode" = "ForwardBase" } | ||
|
||
CGPROGRAM | ||
|
||
#pragma vertex vert | ||
#pragma fragment frag | ||
|
||
#include "UnityCG.cginc" | ||
|
||
float4 vert(float4 vertex : POSITION) : SV_POSITION | ||
{ | ||
return float4(vertex.xy * float2(2, -2), 0, 1); | ||
} | ||
|
||
fixed4 frag() : SV_Target | ||
{ | ||
return 0; | ||
} | ||
|
||
ENDCG | ||
} | ||
|
||
// Forward add: | ||
// renders a slice of a shadow volume with a full-screen quad. | ||
Pass | ||
{ | ||
Tags { "LightMode" = "ForwardAdd" } | ||
|
||
Blend One One | ||
|
||
CGPROGRAM | ||
|
||
#pragma vertex vert | ||
#pragma fragment frag | ||
|
||
#pragma multi_compile_fwdadd_fullshadows | ||
#pragma skip_variants DIRECTIONAL SHADOWS_SCREEN POINT_COOKIE DIRECTIONAL_COOKIE | ||
|
||
#include "UnityCG.cginc" | ||
#include "Lighting.cginc" | ||
#include "AutoLight.cginc" | ||
|
||
fixed4 _Color; | ||
|
||
struct v2f | ||
{ | ||
float4 vertex : SV_POSITION; | ||
float3 worldPos : TEXCOORD0; | ||
}; | ||
|
||
v2f vert(float4 vertex : POSITION) | ||
{ | ||
v2f o; | ||
o.vertex = float4(vertex.xy * float2(2, -2), 0, 1); | ||
o.worldPos = mul(unity_ObjectToWorld, vertex).xyz; | ||
return o; | ||
} | ||
|
||
half4 frag(v2f IN) : SV_Target | ||
{ | ||
UNITY_LIGHT_ATTENUATION(atten, IN, IN.worldPos) | ||
return half4(_Color.rgb * _LightColor0.rgb * atten, 1); | ||
} | ||
|
||
ENDCG | ||
} | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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
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