ポーズ中にゲーム画面を見られないように、ぼかしを掛ける処理を書いてみました。
処理の流れ
元画像を縮小し、横方向にガウスぼかしを掛けます。
1 |
command.Blit((RenderTargetIdentifier)source, rt1, material, 0); |
1 2 3 4 5 6 7 8 9 10 11 12 |
fixed4 fragHorizon(v2f i) : SV_Target { float4 col = float4(0, 0, 0, 0); col += tex2D(_MainTex, i.uv + _PixelSize * float2(-3, 0)) * 0.053; col += tex2D(_MainTex, i.uv + _PixelSize * float2(-2, 0)) * 0.123; col += tex2D(_MainTex, i.uv + _PixelSize * float2(-1, 0)) * 0.203; col += tex2D(_MainTex, i.uv) * 0.240; col += tex2D(_MainTex, i.uv + _PixelSize * float2(1, 0)) * 0.203; col += tex2D(_MainTex, i.uv + _PixelSize * float2(2, 0)) * 0.123; col += tex2D(_MainTex, i.uv + _PixelSize * float2(3, 0)) * 0.053; return col; } |
1 2 3 4 5 6 7 8 9 10 |
Pass { CGPROGRAM #pragma vertex vert #pragma fragment fragHorizon #include "UnityCG.cginc" ENDCG } |
更に縦方向にもぼかしを掛け、拡大すると良い感じになります。
1 2 |
command.Blit(rt1, rt2, material, 1); command.Blit(rt2, destination); |
1 2 3 4 5 6 7 8 9 10 11 12 |
fixed4 fragVertical(v2f i) : SV_Target { float4 col = float4(0, 0, 0, 0); col += tex2D(_MainTex, i.uv + _PixelSize * float2(0, -3)) * 0.053; col += tex2D(_MainTex, i.uv + _PixelSize * float2(0, -2)) * 0.123; col += tex2D(_MainTex, i.uv + _PixelSize * float2(0, -1)) * 0.203; col += tex2D(_MainTex, i.uv) * 0.240; col += tex2D(_MainTex, i.uv + _PixelSize * float2(0, 1)) * 0.203; col += tex2D(_MainTex, i.uv + _PixelSize * float2(0, 2)) * 0.123; col += tex2D(_MainTex, i.uv + _PixelSize * float2(0, 3)) * 0.053; return col; } |
1 2 3 4 5 6 7 8 9 10 |
Pass { CGPROGRAM #pragma vertex vert #pragma fragment fragVertical #include "UnityCG.cginc" ENDCG } |
ポーズ処理はTime.timescaleを0に設定し、Time.realtimeSinceStartupを参照してポーズ時のΔtを取得することで実装しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
public class Pause : MonoBehaviour { [SerializeField] GameObject pauseUI; [SerializeField] Gauss gauss; bool pauseFlag = false; float intencity = 0; float prevTime; void Update () { var deltaTime = Time.realtimeSinceStartup - prevTime; if (Input.GetButtonDown("Pause")) { pauseFlag = !pauseFlag; } if (pauseFlag) { pauseUI.SetActive(true); intencity += deltaTime * 8; Time.timeScale = 0; } else { pauseUI.SetActive(false); intencity -= deltaTime * 8; Time.timeScale = 1; } intencity = Mathf.Clamp01(intencity); gauss.Resolution = (int)(intencity * 10); prevTime = Time.realtimeSinceStartup; } } |
コード全文
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
using UnityEngine; using UnityEngine.Rendering; [RequireComponent(typeof(Camera))] [ExecuteInEditMode] public class Gauss : MonoBehaviour { Material material; [SerializeField] [Range(0, 20)] int resolution = 0; public int Resolution { get { return resolution; } set { resolution = value; } } void Awake() { var shader = Shader.Find("Hidden/Gauss"); material = new Material(shader); } // 今回はシェーダーに定数をベタ打ちしているため未使用 // シェーダー内ではCalcWeight(3.0f, 4)の値を使用 float[] CalcWeight(float dispersion, int count) { float[] weight = new float[count]; float total = 0; for (int i = 0; i < weight.Length; i++) { weight[i] = Mathf.Exp(-0.5f * (i * i) / dispersion); total += weight[i] * ((0 == i) ? 1 : 2); } for (int i = 0; i < weight.Length; ++i) weight[i] /= total; return weight; } void OnRenderImage(RenderTexture source, RenderTexture destination) { if (resolution == 0) { Graphics.Blit(source, destination); return; } CommandBuffer command = new CommandBuffer(); int rt1 = Shader.PropertyToID("RT1"); command.GetTemporaryRT(rt1, -resolution, -resolution, 0, FilterMode.Point); int rt2 = Shader.PropertyToID("rt2"); command.GetTemporaryRT(rt2, -resolution, -resolution, 0, FilterMode.Trilinear); var weight = CalcWeight(4, 8); command.SetGlobalVector(Shader.PropertyToID("_PixelSize"), new Vector4((float)resolution / Screen.width, (float)resolution / Screen.height, 0, 0)); command.Blit((RenderTargetIdentifier)source, rt1, material, 0); command.Blit(rt1, rt2, material, 1); command.Blit(rt2, destination); Graphics.ExecuteCommandBuffer(command); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
Shader "Hidden/Gauss" { Properties { _MainTex ("Texture", 2D) = "white" {} } SubShader { // No culling or depth Cull Off ZWrite Off ZTest Always CGINCLUDE struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; v2f vert(appdata v) { v2f o; o.vertex = mul(UNITY_MATRIX_MVP, v.vertex); o.uv = v.uv; return o; } sampler2D _MainTex; float2 _PixelSize; fixed4 fragHorizon(v2f i) : SV_Target { float4 col = float4(0, 0, 0, 0); col += tex2D(_MainTex, i.uv + _PixelSize * float2(-3, 0)) * 0.053; col += tex2D(_MainTex, i.uv + _PixelSize * float2(-2, 0)) * 0.123; col += tex2D(_MainTex, i.uv + _PixelSize * float2(-1, 0)) * 0.203; col += tex2D(_MainTex, i.uv) * 0.240; col += tex2D(_MainTex, i.uv + _PixelSize * float2(1, 0)) * 0.203; col += tex2D(_MainTex, i.uv + _PixelSize * float2(2, 0)) * 0.123; col += tex2D(_MainTex, i.uv + _PixelSize * float2(3, 0)) * 0.053; return col; } fixed4 fragVertical(v2f i) : SV_Target { float4 col = float4(0, 0, 0, 0); col += tex2D(_MainTex, i.uv + _PixelSize * float2(0, -3)) * 0.053; col += tex2D(_MainTex, i.uv + _PixelSize * float2(0, -2)) * 0.123; col += tex2D(_MainTex, i.uv + _PixelSize * float2(0, -1)) * 0.203; col += tex2D(_MainTex, i.uv) * 0.240; col += tex2D(_MainTex, i.uv + _PixelSize * float2(0, 1)) * 0.203; col += tex2D(_MainTex, i.uv + _PixelSize * float2(0, 2)) * 0.123; col += tex2D(_MainTex, i.uv + _PixelSize * float2(0, 3)) * 0.053; return col; } ENDCG Pass { CGPROGRAM #pragma vertex vert #pragma fragment fragHorizon #include "UnityCG.cginc" ENDCG } Pass { CGPROGRAM #pragma vertex vert #pragma fragment fragVertical #include "UnityCG.cginc" ENDCG } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
using UnityEngine; using System.Collections; public class Pause : MonoBehaviour { [SerializeField] GameObject pauseUI; [SerializeField] Gauss gauss; bool pauseFlag = false; float intencity = 0; float prevTime; void Start () { } void Update () { var deltaTime = Time.realtimeSinceStartup - prevTime; if (Input.GetButtonDown("Pause")) { pauseFlag = !pauseFlag; } if (pauseFlag) { pauseUI.SetActive(true); intencity += deltaTime * 8; Time.timeScale = 0; } else { pauseUI.SetActive(false); intencity -= deltaTime * 8; Time.timeScale = 1; } intencity = Mathf.Clamp01(intencity); gauss.Resolution = (int)(intencity * 10); prevTime = Time.realtimeSinceStartup; } } |
このコンテンツは、『ユニティちゃんライセンス』で提供されています。
コメントを残す