質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

1回答

5551閲覧

Shaderでの繰り返し処理

shiroshiro_me

総合スコア19

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2018/10/10 06:39

この移動平均フィルタのshaderプログラムにRepeatの回数フィルタ走査を繰り返して平滑化の度合いを上げる機能を追加したいと考えています。
しかし、一度処理をしたものをもう一度同じ処理をする方法が分かりません。どのように実装すればいいでしょうか。
回答よろしくお願いします。

shader

1Shader "Custom/RepeatAve" { 2 Properties 3 { 4 _Color("Color", Color) = (1, 1, 1, 1) 5 6 _MainTex("Diffuse", 2D) = "white" {} 7 _Noise("Noise", 2D) = "black" {} 8 9 _Range("Range", Float) = 0.025 10 _Blur("Blur", Float) = 0.005 11 _Repeat("Repeat", int) = 1 12 _Size("Size", int) = 3 13 } 14 15 SubShader 16 { 17 Cull Off 18 19 GrabPass{ "_Frost" } 20 21 CGINCLUDE 22 #include "UnityCG.cginc" 23 24 half4 _Color; 25 26 sampler2D _MainTex; 27 float4 _MainTex_ST; 28 29 sampler2D _Frost; 30 sampler2D _Noise; 31 float4 _Noise_ST; 32 33 half _Range; 34 half _Blur; 35 36 int _Size; 37 int _Repeat; 38 39 ENDCG 40 41 Pass 42 { 43 CGPROGRAM 44 #pragma target 3.0 45 #pragma vertex vert 46 #pragma fragment frag 47 48 struct v2f 49 { 50 float4 pos : SV_POSITION; 51 52 float3 uv : TEXCOORD; 53 float4 screenPos : TEXCOORD1; 54 float3 ray : TEXCOORD2; 55 }; 56 57 v2f vert(appdata_full v) 58 { 59 v2f o; 60 o.pos = UnityObjectToClipPos(v.vertex); 61 o.uv = v.texcoord; 62 o.screenPos = ComputeScreenPos(o.pos); 63 o.ray = UnityObjectToViewPos(v.vertex).xyz * float3(-1, -1, 1); 64 return o; 65 } 66 67 half4 frag(v2f i) : SV_Target 68 { 69 i.ray = i.ray * (_ProjectionParams.z / i.ray.z); 70 float2 uv = i.screenPos.xy / i.screenPos.w; 71 72 float2 frostUV = tex2D(_Noise, i.uv * _Noise_ST.xy + _Noise_ST.zw).xy; 73 74 frostUV -= 0.5; 75 frostUV *= _Range; 76 frostUV += uv; 77 78 half4 frost = tex2D(_Frost, frostUV); 79 for (int m = -(_Size - 1) / 2; m <= (_Size - 1) / 2; m++) { 80 for (int n = -(_Size - 1) / 2; n <= (_Size - 1) / 2; n++) { 81 frost += tex2D(_Frost, frostUV + float2(_Blur * m, _Blur * n)); 82 } 83 } 84 85 frost /= _Size * _Size; 86 87 half4 diffuse = tex2D(_MainTex, i.uv * _MainTex_ST.xy + _MainTex_ST.zw); 88 89 half alpha = _Color.a * diffuse.a; 90 91 return half4(frost.xyz + (diffuse.rgb * _Color.rgb * alpha), 1); 92 } 93 94 ENDCG 95 } 96 } 97 98 Fallback Off 99} 100

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Bongo

2018/10/10 21:25

固定回数の処理なら「グラブパス」→「移動平均パス」→「グラブパス」→「移動平均パス」→...といった具合に何度もグラブと移動平均を繰り返してやることができるかもしれませんが、可変回数だと困難そうに思います。シェーダーファイル単独ではなく、「ガウシアンブラーの実装」に投稿した新Frostのように、コマンドバッファ操作用の補助スクリプトがあってもいいなら可変回数対応にしやすいと思いますが、どうでしょうか...?
shiroshiro_me

2018/10/11 07:47

その方向で検索してみましたが、CommandBufferの具体的な使い方や紐づけの方法などいまいち分かりませんでした。c#側でshaderをfor文で何度も実行する形になるのでしょうか?
Bongo

2018/10/11 09:43

繰り返し部分はC#スクリプト側で面倒をみてやるのが順当な手段だろうと思います。ですが確かにCommandBufferは少々ややこしいかもしれません。もし、必ずしも曇りガラスのような3Dオブジェクトの特殊効果として利用する必要がなく、移動平均エフェクトが画面全体にかかってしまってもかまわないならば、イメージエフェクトシェーダーのやり方が使えるかと思います。こちらの方がCommandBufferよりシンプルですし、解説サイトも多いように思いますが、いかがでしょうか?
shiroshiro_me

2018/10/15 02:19

曇りガラスのような3Dオブジェクトで実装したいと考えています。難しいようなら固定回数のものをいくつか作成し、shaderをそのつど切り替える方向で考えたいと思います。固定回数処理の場合、下にいくつも同じ処理を書いていくやり方になるのでしょうか?
guest

回答1

0

ベストアンサー

「グラブ」→「平均化」→「グラブ」→「平均化」→...→「最終処理」方式だとこんな感じでしょうかね?
コードの再利用のため「RepeatAve.shader」ファイルと「RepeatAve.cginc」ファイルに分かれていますが、シェーダーとしては単一ですので、補助スクリプトなしでマテリアルをアタッチするだけとなります。ちょっと異様な形になってしまいましたが...

RepeatAve.cginc

ShaderLab

1sampler2D _GrabTexture; 2half _Blur; 3int _Size; 4struct v2fAve 5{ 6 float4 pos: SV_POSITION; 7 float4 screenPos: TEXCOORD1; 8}; 9v2fAve vertAve(appdata_full v) 10{ 11 v2fAve o; 12 o.pos = UnityObjectToClipPos(v.vertex); 13 o.screenPos = ComputeScreenPos(o.pos); 14 return o; 15} 16half4 fragAve(v2fAve i): SV_Target 17{ 18 float2 uv = i.screenPos.xy / i.screenPos.w; 19 half4 frost = 0.0; 20 #ifdef _AVE 21 for (int m = - (_Size - 1) / 2; m <= (_Size - 1) / 2; m ++) 22 { 23 for (int n = - (_Size - 1) / 2; n <= (_Size - 1) / 2; n ++) 24 { 25 frost += tex2D(_GrabTexture, uv + float2(_Blur * m, _Blur * n)); 26 } 27 } 28 frost /= _Size * _Size; 29 #else 30 frost = tex2D(_GrabTexture, uv); 31 #endif 32 return half4(frost.xyz, 1); 33}

RepeatAve.shader

ShaderLab

1Shader "Custom/RepeatAve" 2{ 3 Properties 4 { 5 _Color ("Color", Color) = (1, 1, 1, 1) 6 _MainTex ("Diffuse", 2D) = "white" {} 7 _Noise ("Noise", 2D) = "gray" {} 8 _Range ("Range", Float) = 0.025 9 _Blur ("Blur", Float) = 0.005 10 [KeywordEnum(R0,R1,R2,R3,R4,R5,R6,R7,R8)] _Repeat ("Repeat", Float) = 0 11 _Size ("Size", int) = 3 12 } 13 14 SubShader 15 { 16 Tags { "Queue" = "Transparent" } 17 Cull Off 18 19 CGINCLUDE 20 #pragma target 3.0 21 #include "UnityCG.cginc" 22 ENDCG 23 24 GrabPass{} 25 pass 26 { 27 CGPROGRAM 28 #pragma multi_compile _ _REPEAT_R1 _REPEAT_R2 _REPEAT_R3 _REPEAT_R4 _REPEAT_R5 _REPEAT_R6 _REPEAT_R7 _REPEAT_R8 29 #pragma vertex vertAve 30 #pragma fragment fragAve 31 #if _REPEAT_R1 | _REPEAT_R2 | _REPEAT_R3 | _REPEAT_R4 | _REPEAT_R5 | _REPEAT_R6 | _REPEAT_R7 | _REPEAT_R8 32 #define _AVE 33 #endif 34 #include "RepeatAve.cginc" 35 ENDCG 36 } 37 38 GrabPass{} 39 pass 40 { 41 CGPROGRAM 42 #pragma multi_compile _ _REPEAT_R2 _REPEAT_R3 _REPEAT_R4 _REPEAT_R5 _REPEAT_R6 _REPEAT_R7 _REPEAT_R8 43 #pragma vertex vertAve 44 #pragma fragment fragAve 45 #if _REPEAT_R2 | _REPEAT_R3 | _REPEAT_R4 | _REPEAT_R5 | _REPEAT_R6 | _REPEAT_R7 | _REPEAT_R8 46 #define _AVE 47 #endif 48 #include "RepeatAve.cginc" 49 ENDCG 50 } 51 52 GrabPass{} 53 pass 54 { 55 CGPROGRAM 56 #pragma multi_compile _ _REPEAT_R3 _REPEAT_R4 _REPEAT_R5 _REPEAT_R6 _REPEAT_R7 _REPEAT_R8 57 #pragma vertex vertAve 58 #pragma fragment fragAve 59 #if _REPEAT_R3 | _REPEAT_R4 | _REPEAT_R5 | _REPEAT_R6 | _REPEAT_R7 | _REPEAT_R8 60 #define _AVE 61 #endif 62 #include "RepeatAve.cginc" 63 ENDCG 64 } 65 66 GrabPass{} 67 pass 68 { 69 CGPROGRAM 70 #pragma multi_compile _ _REPEAT_R4 _REPEAT_R5 _REPEAT_R6 _REPEAT_R7 _REPEAT_R8 71 #pragma vertex vertAve 72 #pragma fragment fragAve 73 #if _REPEAT_R4 | _REPEAT_R5 | _REPEAT_R6 | _REPEAT_R7 | _REPEAT_R8 74 #define _AVE 75 #endif 76 #include "RepeatAve.cginc" 77 ENDCG 78 } 79 80 GrabPass{} 81 pass 82 { 83 CGPROGRAM 84 #pragma multi_compile _ _REPEAT_R5 _REPEAT_R6 _REPEAT_R7 _REPEAT_R8 85 #pragma vertex vertAve 86 #pragma fragment fragAve 87 #if _REPEAT_R5 | _REPEAT_R6 | _REPEAT_R7 | _REPEAT_R8 88 #define _AVE 89 #endif 90 #include "RepeatAve.cginc" 91 ENDCG 92 } 93 94 GrabPass{} 95 pass 96 { 97 CGPROGRAM 98 #pragma multi_compile _ _REPEAT_R6 _REPEAT_R7 _REPEAT_R8 99 #pragma vertex vertAve 100 #pragma fragment fragAve 101 #if _REPEAT_R6 | _REPEAT_R7 | _REPEAT_R8 102 #define _AVE 103 #endif 104 #include "RepeatAve.cginc" 105 ENDCG 106 } 107 108 GrabPass{} 109 pass 110 { 111 CGPROGRAM 112 #pragma multi_compile _ _REPEAT_R7 _REPEAT_R8 113 #pragma vertex vertAve 114 #pragma fragment fragAve 115 #if _REPEAT_R7 | _REPEAT_R8 116 #define _AVE 117 #endif 118 #include "RepeatAve.cginc" 119 ENDCG 120 } 121 122 GrabPass{} 123 pass 124 { 125 CGPROGRAM 126 #pragma multi_compile _ _REPEAT_R8 127 #pragma vertex vertAve 128 #pragma fragment fragAve 129 #if _REPEAT_R8 130 #define _AVE 131 #endif 132 #include "RepeatAve.cginc" 133 ENDCG 134 } 135 136 GrabPass{} 137 Pass 138 { 139 CGPROGRAM 140 #pragma vertex vert 141 #pragma fragment frag 142 half4 _Color; 143 sampler2D _MainTex; 144 float4 _MainTex_ST; 145 sampler2D _Noise; 146 float4 _Noise_ST; 147 sampler2D _GrabTexture; 148 half _Range; 149 struct v2f 150 { 151 float4 pos: SV_POSITION; 152 float3 uv: TEXCOORD; 153 float4 screenPos: TEXCOORD1; 154 float3 ray: TEXCOORD2; 155 }; 156 v2f vert(appdata_full v) 157 { 158 v2f o; 159 o.pos = UnityObjectToClipPos(v.vertex); 160 o.uv = v.texcoord; 161 o.screenPos = ComputeScreenPos(o.pos); 162 o.ray = UnityObjectToViewPos(v.vertex).xyz * float3(-1, -1, 1); 163 return o; 164 } 165 half4 frag(v2f i): SV_Target 166 { 167 i.ray = i.ray * (_ProjectionParams.z / i.ray.z); 168 float2 uv = i.screenPos.xy / i.screenPos.w; 169 float2 frostUV = tex2D(_Noise, i.uv * _Noise_ST.xy + _Noise_ST.zw).xy; 170 frostUV -= 0.5; 171 frostUV *= _Range; 172 frostUV += uv; 173 half4 frost = tex2D(_GrabTexture, frostUV); 174 half4 diffuse = tex2D(_MainTex, i.uv * _MainTex_ST.xy + _MainTex_ST.zw); 175 half alpha = _Color.a * diffuse.a; 176 return half4(frost.xyz + (diffuse.rgb * _Color.rgb * alpha), 1); 177 } 178 ENDCG 179 } 180 } 181 Fallback Off 182}

_Sizeは規定値の3、_Blurも規定値の0.005で、RepeatをR0~R8に切り替えると下図のようになりました。

反復回数切り替え

今回は単一のシェーダーとしましたので、反復回数を切り替えても常に「グラブ」→「描画」のプロセスが9回行われます(とはいえ設定した反復回数を超えた部分では「グラブ」→「そのまま描画」となりサンプリング回数が1回となるため、反復回数を小さくすれば負荷は小さくなるでしょう)。
ご質問者さんのおっしゃる「反復回数の異なる複数のシェーダーを作る」という方式なら、小反復回数のときの無駄な「グラブ」→「描画」部分を丸ごと削除することができるため、より高速化できると思います。

やはり、補助的なC#スクリプト抜きだとちょっと非効率的になってしまいますね。特に多数の曇りガラスオブジェクトがある場合は、オブジェクトの数だけグラブパスが増えますので負荷が気になりそうです。
ただ、この形ですと「曇りガラスオブジェクトの手前に別の曇りガラスオブジェクトがある場合、手前のオブジェクトを透かして見た背後の曇りガラスオブジェクトはさらにぼやけて見える」という視覚的もっともらしさがあると思います。

追記

1回目の平均化処理を行う部分までを下記のように変更してみました。

RepeatAve.shader

ShaderLab

1Shader "Custom/RepeatAve" 2{ 3 Properties 4 { 5 _Color ("Color", Color) = (1, 1, 1, 1) 6 _MainTex ("Diffuse", 2D) = "white" {} 7 _Noise ("Noise", 2D) = "gray" {} 8 _Range ("Range", Float) = 0.025 9 _Blur ("Blur", Float) = 0.005 10 [KeywordEnum(R0,R1,R2,R3,R4,R5,R6,R7,R8)] _Repeat ("Repeat", Float) = 0 11 _Size ("Size", int) = 3 12 } 13 14 SubShader 15 { 16 Tags { "Queue" = "Transparent" } 17 Cull Off 18 ZWrite Off 19 Stencil 20 { 21 Ref 0 22 Comp Equal 23 } 24 25 CGINCLUDE 26 #pragma target 3.0 27 #include "UnityCG.cginc" 28 ENDCG 29 30 GrabPass{"_FirstGrabTexture"} 31 pass 32 { 33 CGPROGRAM 34 #pragma multi_compile _ _REPEAT_R1 _REPEAT_R2 _REPEAT_R3 _REPEAT_R4 _REPEAT_R5 _REPEAT_R6 _REPEAT_R7 _REPEAT_R8 35 #pragma vertex vertAve 36 #pragma fragment fragAveFirst 37 #if _REPEAT_R1 | _REPEAT_R2 | _REPEAT_R3 | _REPEAT_R4 | _REPEAT_R5 | _REPEAT_R6 | _REPEAT_R7 | _REPEAT_R8 38 #define _AVE 39 #endif 40 #include "RepeatAve.cginc" 41 sampler2D _FirstGrabTexture; 42 half4 fragAveFirst(v2fAve i): SV_Target 43 { 44 float2 uv = i.screenPos.xy / i.screenPos.w; 45 half4 frost = 0.0; 46 #ifdef _AVE 47 for (int m = - (_Size - 1) / 2; m <= (_Size - 1) / 2; m ++) 48 { 49 for (int n = - (_Size - 1) / 2; n <= (_Size - 1) / 2; n ++) 50 { 51 frost += tex2D(_FirstGrabTexture, uv + float2(_Blur * m, _Blur * n)); 52 } 53 } 54 frost /= _Size * _Size; 55 #else 56 frost = tex2D(_FirstGrabTexture, uv); 57 #endif 58 return half4(frost.xyz, 1); 59 } 60 ENDCG 61 } 62 63 // 省略...残り7回のフィルタ処理および最終合成処理には変更なし 64 } 65 Fallback Off 66}

RepeatAve.cgincに変更はありません。
1回目のGrabPassのみグラブ先を_FirstGrabTextureとして平均化もそのテクスチャを参照するようにし、2回目以降は先と同様にテクスチャ名指定なしでグラブ・平均化しています。
テクスチャ名指定ありでグラブすると最初の1回だけグラブが行われるので、フィルタ処理の起点は毎回最初のグラブ結果となります。このため、後で描画されるマテリアルにそれまでのフィルタ処理の影響が及ばなくなり、「曇りガラスを重ねるほどぼけ幅が大きくなる」という現象を回避できるかと思います。
また、ついでにコメントで申し上げたZWrite Offを加え、さらにステンシルテストを有効にしてステンシルバッファの内容が0の場合だけ描画を行うようにしました。

これと併せて、ステンシル値を加算してステンシルバッファの内容を0でなくするマテリアルをマスク用オブジェクトに使用すれば、キューの大小に基づいたマスキングが可能かと思います。

StencilMask.shader

ShaderLab

1Shader "Custom/StencilMask" 2{ 3 Properties 4 { 5 } 6 7 SubShader 8 { 9 Tags { "Queue" = "Transparent" } 10 Cull Off 11 ZWrite Off 12 Stencil 13 { 14 Pass IncrSat 15 } 16 ColorMask 0 17 18 Pass 19 { 20 CGPROGRAM 21 #pragma target 3.0 22 #pragma vertex vert 23 #pragma fragment frag 24 #include "UnityCG.cginc" 25 struct v2f 26 { 27 float4 pos: SV_POSITION; 28 }; 29 v2f vert(appdata_full v) 30 { 31 v2f o; 32 o.pos = UnityObjectToClipPos(v.vertex); 33 return o; 34 } 35 half4 frag(v2f i): SV_Target 36 { 37 return 0.0; 38 } 39 ENDCG 40 } 41 } 42 Fallback Off 43}

テストとして、下記3種のマテリアルを作成し...

  • マテリアルA...赤ガラス、ぼけ幅中、ノイズ効果小、キュー2501
  • マテリアルB...緑ガラス、ぼけ幅大、ノイズ効果大、キュー2511
  • マテリアルC...青ガラス、ぼけ幅小、ノイズ効果なし、キュー2521

これらを、_FirstGrabTextureを使わない従来通りの方法で描画すると、下図のように先に描画した曇りガラスの影響が後段にも引き継がれますが...

旧描画方式

_FirstGrabTextureを使う方式にすると、下図のような結果となります。

新描画方式

また、キュー2510のマスクオブジェクト(Aの次に描画され、描画領域へのB・Cの描画を防止する)を左右に横切るよう配置、キュー2520のマスクオブジェクト(Bの次に描画され、描画領域へのCの描画を防止する)を上下に横切るよう配置して、描画過程を見てみると下図のようになります。

マスク処理

投稿2018/10/15 20:56

編集2018/10/18 21:58
Bongo

総合スコア10807

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shiroshiro_me

2018/10/16 06:13

回答ありがとうございます。 まさしく私がやりたいことを実装していただいており、大変助かりました。 一度実行してみましたが、そんなに負荷も気になりませんでした。 多くとも3,4回の繰り返しで済みそうなのでまた削りたいとも思います。 重ねてお礼申し上げます。本当にありがとうございました。
shiroshiro_me

2018/10/17 03:50

すいません、重ねて質問よろしいでしょうか? 回答者様は、”ただ、この形ですと「曇りガラスオブジェクトの手前に別の曇りガラスオブジェクトがある場合、手前のオブジェクトを透かして見た背後の曇りガラスオブジェクトはさらにぼやけて見える」という視覚的もっともらしさがあると思います。”とおっしゃられていましたが、 今までのプログラムですと、レンダリングの結果がRender Queueの値が大きいものに上書きされていたと思うのですが、なぜこのような形に変化したのでしょうか?
shiroshiro_me

2018/10/17 05:45

どうやらグラブパスが理由のようですね。グラブパスはそのshaderの描画結果を取得するのではなく、それまでレンダリングした結果をすべて取得する命令だ、という認識で合ってますでしょうか。 ということはグラブパスを使う以上は、今までのように、Render Queueの値が大きいものがレンダリングの結果を上書きしていくという形にはならない、ということでしょうか?
Bongo

2018/10/17 18:20

グラブパスについてはおっしゃる通り、「GrabPass」に到達するまでに画面に描画された結果がテクスチャへ写し取られることになります。 ただし、https://docs.unity3d.com/ja/current/Manual/SL-GrabPass.html にあるようにテクスチャ名を指定するかどうかで挙動が少し変わってきて、私の投稿したコードのようにテクスチャ名を指定しない場合は「GrabPass」に到達するたびにその時点の描画結果が「_GrabTexture」にグラブされますが、ご質問者さんご提示のように「GrabPass{ "_Frost" }」とすると、現在のフレームで一番最初に「GrabPass{ "_Frost" }」に到達したときだけ「_Frost」へのグラブが行われ、それ以降は無視されます(ちなみに、「GrabPass{ "_GrabTexture" }」とした場合はどうなるか試してみたところ、「GrabPass{ "_Frost" }」のときと同様に最初の一回だけグラブが行われるようでした)。 「Window」→「Analysis」→「Frame Debugger」を開き、「Enable」ボタンをオンにすると描画過程を一段階ずつ見ることができ、役立つかと思います。 Render Queueについてですが、「値が小さいものほど先にレンダリングされる」というルールはグラブパスを使っても依然として有効です。さらに、Render Queueが同じマテリアル同士の描画順序は、https://docs.unity3d.com/ja/current/Manual/SL-SubShaderTags.html に記述されている... 「2500 (“Geometry+500”) までのキューは「不透明」とみなされ、オブジェクトの描画順を最良パフォーマンスの為に最適化します。 これより大きいレンダリングキューは「透明なオブジェクト」用とみなされ、オブジェクトが距離によってソートされ、レンダリングは最も遠いものからを開始され最も近いもので終わります。スカイボックスは完全に不透明なオブジェクトと完全に透明なオブジェクトの中間で描画されます。」 のルールに従います。私のコードでは「Tags { "Queue" = "Transparent" }」としていますが、これはキューが3000で、2500より大きいため透明オブジェクトのルールに従い、カメラから遠い曇りガラスの方が先に描画されます。ですのでカメラに近い曇りガラスは「カメラから遠い曇りガラスの描画が完了した後の画面」をグラブすることになり、先に申し上げた「手前のオブジェクトを透かして見た背後の曇りガラスオブジェクトはさらにぼやけて見える」という結果になります。 距離によるソートのルールはキューが同じオブジェクト同士での話ですので、もしRepeatAveシェーダーを使ったマテリアルをもう一つ作ってRender Queueを3001に変えたとすると、それを使ったオブジェクトは他のRender Queueが3000のオブジェクトより奥に配置したとしても、それらより後に描画されるかと思います。
shiroshiro_me

2018/10/18 04:01

なるほど。分かりやすい回答ありがとうございます。グラブパスが分かりにくかったのですが、だいたい理解できたと思います。 では、それでは現時点のプログラムでは、例えば同じ座標にRender Queueとパラメータが違うRepeatAveを適用した2つのオブジェクトがあった場合、Render Queueが高い方のぼかしが採用されるという形にはならない、ということでしょうか?またそれに近い形にはならないのでしょうか?
Bongo

2018/10/18 07:24

すみません、お返事の前に、先のコメントでデプスの考慮のことを失念していたため補足いたします。 今はUnityが手元にないため実際に挙動確認できないのですが、コメントで申し上げた「もしRepeatAveシェーダーを使ったマテリアルを...~...それらより後に描画される」という動作になるには、「Cull Off」の次の行あたりにでも「ZWrite Off」を入れてやる必要がありそうです。 現状ではZWriteの指定がないため、デフォルトのOnになっているはずです。この状態では、先にキュー3000の曇りガラスが描画された後、キュー3001の曇りガラスをキュー3000ガラスの背後に隠れる位置に描画しようとしても、Zテストに失敗し描画されないでしょうね...すみませんでした。 話を戻しまして、同じ場所に2種類のRepeatAveマテリアルを使ったオブジェクトを置いたときにどうなるかという件についてお伺いしたいのですが、ご質問者さんの考える理想的挙動というのは、例示しますとこんな感じでしょうか? - ぼかし量の大きなマテリアルAを作る。キューは仮に3000とする。 - ぼかし量の小さなマテリアルBを作る。キューはAより大きい3001とする。 - マテリアルAを使ったオブジェクトとBを使ったオブジェクトを同じ位置に描画する。 - 現状では、キューの若いAが先に描画されると、Bが描画に取りかかる際にグラブされる画面にはすでにAが描き込まれており、Bはそれをさらにぼかしてしまい、ぼけ幅はさらに広がる。 - そうではなく、Bが描画される部分のぼけ幅は、たとえ背後にAがあろうがB本来の設定通りになってほしい。最終的にできあがった映像は、Bの部分がAよりもくっきりするようにしたい。 もしそういうことでしたら、先のコメントで言及しました「GrabPassにテクスチャ名を指定すると、そのフレームで初めてGrabPassに到達した時のみグラブが行われる」という特性を利用すれば実現できるかもしれません。あとでもうちょっと考えてみます。
shiroshiro_me

2018/10/18 13:06

説明不足ですみません。 私が実装したいこととしましてはキューの違う曇りガラスオブジェクトいくつか同じ座標に重ね、そこをある一定のキュー以上のオブジェクトをマスクするオブジェクトを用意し、マスクした部分はそのキュー以下で一番大きいキューのオブジェクトのぼかしが適用されるようにしたいと考えています。 例えばキューが2521,2511,2501のオブジェクトを重ね、2520以上をマスクする場合、2501のオブジェクトのぼかしが強くても、2511のぼかしが0であればマスク部分は高解像度になるようにしたいと考えています。
Bongo

2018/10/18 22:02

修正案を検討してみましたが、いかがでしょうか? こんな挙動だろうと想像して作りましたが、意図を読み違えていましたらお詫びします...
shiroshiro_me

2018/10/19 06:08

おかげ様でまさしく私がやりたいことを実装することができました。ありがとうございます。 ただ、Stencilを用いると、今回は実行前で例のブラーの消失が起こってしまったため、Stencilを用いない方法で実装をさせていただきました。しかし、Stencilやグラブパス、ZWriteなど知らないことばかりで大変勉強になりました。また、自分でも勉強していきたいと思います。 重ねてお礼申し上げます。誠にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問