teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

5

初期テクスチャサイズが1の時エラーを起こすため、縮小ループをdo-whileからwhileに変更

2017/11/18 10:26

投稿

Bongo
Bongo

スコア10816

answer CHANGED
@@ -102,7 +102,7 @@
102
102
  this.material.SetFloat(this.referenceColorThresholdId, this.referenceColorThreshold);
103
103
  Graphics.Blit(src, previousLevelTexture, this.material, 0); // パス0...入力イメージから目的色を抽出し、結果をlevel0TextureSize四方のテクスチャに出力
104
104
 
105
- do
105
+ while (scaledSize > 1)
106
106
  {
107
107
  scaledSize >>= 1;
108
108
 
@@ -112,7 +112,6 @@
112
112
  RenderTexture.ReleaseTemporary(previousLevelTexture);
113
113
  previousLevelTexture = scaledTexture;
114
114
  }
115
- while (scaledSize > 1);
116
115
 
117
116
  var currentActiveTexture = RenderTexture.active;
118
117
 

4

他環境での不具合を修正

2017/11/18 10:25

投稿

Bongo
Bongo

スコア10816

answer CHANGED
@@ -21,6 +21,9 @@
21
21
 
22
22
  ※余談ですが、「シェーダーで音を鳴らす」のではなく「シェーダーで音データを加工する」ケースはあり得ると思います。RGB画像は3チャンネル2次元の波、ステレオ音声は2チャンネル1次元の波だと思えば、画像加工も音声加工も似たようなことをやっている気がしませんかね?
23
23
 
24
+ [追記]
25
+ 当初のカメラスクリプトではテクスチャ生成時にテクスチャフォーマットを指定していましたが、それをやめてサイズだけ指定するようにしました(最初のコードはMac版OpenGL上でしか動作確認していなかったのですが、後で試したらMetalやWindows版で正しい結果が得られませんでした...)。また併せて、シェーダーコードで返していたフラグメントの色を`fixed4(result, 0.0, 0.0, 1.0)`から`fixed4(result, result, result, 1.0)`に変えました。動作上は変える必要はないのですが、縮小過程をフレームデバッガで見た時に、前者だと目的色部分が赤色になってしまいます。上記のコード概要説明では抽出結果を白だの黒だのと表現していますので、それに合わせるようにしてみました。
26
+
24
27
  - カメラのスクリプト
25
28
  ```C#
26
29
  using UnityEngine;
@@ -89,11 +92,11 @@
89
92
 
90
93
  if (this.queryResultTexture == null)
91
94
  {
92
- this.queryResultTexture = new Texture2D(1, 1, TextureFormat.RGB24, false);
95
+ this.queryResultTexture = new Texture2D(1, 1);
93
96
  }
94
97
 
95
98
  var scaledSize = this.level0TextureSize;
96
- var previousLevelTexture = RenderTexture.GetTemporary(scaledSize, scaledSize, 0, RenderTextureFormat.R8);
99
+ var previousLevelTexture = RenderTexture.GetTemporary(scaledSize, scaledSize);
97
100
 
98
101
  this.material.SetColor(this.referenceColorId, this.referenceColor);
99
102
  this.material.SetFloat(this.referenceColorThresholdId, this.referenceColorThreshold);
@@ -103,7 +106,7 @@
103
106
  {
104
107
  scaledSize >>= 1;
105
108
 
106
- var scaledTexture = RenderTexture.GetTemporary(scaledSize, scaledSize, 0, RenderTextureFormat.R8);
109
+ var scaledTexture = RenderTexture.GetTemporary(scaledSize, scaledSize);
107
110
 
108
111
  Graphics.Blit(previousLevelTexture, scaledTexture, this.material, 1); // パス1...抽出結果を段階的に1ピクセル四方まで縮小
109
112
  RenderTexture.ReleaseTemporary(previousLevelTexture);
@@ -168,101 +171,101 @@
168
171
  ```
169
172
  Shader "Hidden/Color Extractor"
170
173
  {
171
- Properties
174
+ Properties
172
- {
175
+ {
173
- _MainTex ("Texture", 2D) = "white" {}
176
+ _MainTex ("Texture", 2D) = "white" {}
174
- _ReferenceColor ("Reference Color", Color) = (1.0, 0.0, 0.0, 1.0)
177
+ _ReferenceColor ("Reference Color", Color) = (1.0, 0.0, 0.0, 1.0)
175
- _ReferenceColorThreshold ("Reference Color Threshold", Range(0.0, 1.0)) = 0.5
178
+ _ReferenceColorThreshold ("Reference Color Threshold", Range(0.0, 1.0)) = 0.5
176
- }
179
+ }
177
-
178
- SubShader
179
- {
180
- Cull Off ZWrite Off ZTest Always
181
180
 
182
- // 抽出パス
183
- Pass
181
+ SubShader
184
- {
182
+ {
185
- CGPROGRAM
186
- #pragma vertex vert
187
- #pragma fragment frag
188
-
189
- #include "UnityCG.cginc"
183
+ Cull Off ZWrite Off ZTest Always
190
184
 
191
- struct appdata
185
+ // 抽出パス
186
+ Pass
192
- {
187
+ {
188
+ CGPROGRAM
193
- float4 vertex : POSITION;
189
+ #pragma vertex vert
194
- float2 uv : TEXCOORD0;
190
+ #pragma fragment frag
195
- };
196
191
 
197
- struct v2f
198
- {
199
- float2 uv : TEXCOORD0;
200
- float4 vertex : SV_POSITION;
192
+ #include "UnityCG.cginc"
201
- };
202
193
 
203
- sampler2D _MainTex;
194
+ struct appdata
195
+ {
204
- float4 _ReferenceColor;
196
+ float4 vertex : POSITION;
205
- float _ReferenceColorThreshold;
197
+ float2 uv : TEXCOORD0;
198
+ };
206
199
 
207
- v2f vert(appdata v)
200
+ struct v2f
208
- {
201
+ {
209
- v2f o;
210
- o.vertex = UnityObjectToClipPos(v.vertex);
211
- o.uv = v.uv;
202
+ float2 uv : TEXCOORD0;
212
- return o;
203
+ float4 vertex : SV_POSITION;
213
- }
204
+ };
214
205
 
206
+ sampler2D _MainTex;
215
- fixed4 frag(v2f i) : SV_Target
207
+ float4 _ReferenceColor;
216
- {
217
- // ピクセル色と目的色の距離がしきい値未満なら1、さもなくば0
208
+ float _ReferenceColorThreshold;
218
- float result = sign(max(_ReferenceColorThreshold - length(_ReferenceColor.rgb - tex2D(_MainTex, i.uv).rgb), 0.0));
219
209
 
210
+ v2f vert(appdata v)
211
+ {
212
+ v2f o;
220
- return fixed4(result, 0.0, 0.0, 1.0);
213
+ o.vertex = UnityObjectToClipPos(v.vertex);
214
+ o.uv = v.uv;
215
+ return o;
221
- }
216
+ }
222
- ENDCG
223
- }
224
217
 
225
- // 縮小パス
218
+ fixed4 frag(v2f i) : SV_Target
226
- Pass
227
- {
219
+ {
228
- CGPROGRAM
229
- #pragma vertex vert
230
- #pragma fragment frag
231
-
232
- #include "UnityCG.cginc"
220
+ // ピクセル色と目的色の距離がしきい値未満なら1、さもなくば0
221
+ float result = sign(max(_ReferenceColorThreshold - length(_ReferenceColor.rgb - tex2D(_MainTex, i.uv).rgb), 0.0));
233
222
 
234
- struct appdata
235
- {
236
- float4 vertex : POSITION;
223
+ return fixed4(result, result, result, 1.0);
237
- float2 uv : TEXCOORD0;
238
- };
224
+ }
225
+ ENDCG
226
+ }
239
227
 
240
- struct v2f
228
+ // 縮小パス
229
+ Pass
241
- {
230
+ {
242
- float2 uv : TEXCOORD0;
231
+ CGPROGRAM
243
- float4 vertex : SV_POSITION;
232
+ #pragma vertex vert
244
- };
233
+ #pragma fragment frag
245
234
 
246
- sampler2D _MainTex;
235
+ #include "UnityCG.cginc"
247
236
 
248
- v2f vert(appdata v)
237
+ struct appdata
249
- {
238
+ {
250
- v2f o;
251
- o.vertex = UnityObjectToClipPos(v.vertex);
239
+ float4 vertex : POSITION;
252
- o.uv = v.uv;
240
+ float2 uv : TEXCOORD0;
253
- return o;
254
- }
241
+ };
255
242
 
256
- fixed4 frag(v2f i) : SV_Target
243
+ struct v2f
257
- {
244
+ {
258
- // 近傍4テクセルの中心からサンプリング、ピクセル色が0より大きければ(1のテクセルが1つ以上あれば)1、さもなくば0
245
+ float2 uv : TEXCOORD0;
259
- float result = sign(tex2D(_MainTex, i.uv).r);
246
+ float4 vertex : SV_POSITION;
247
+ };
260
248
 
249
+ sampler2D _MainTex;
250
+
251
+ v2f vert(appdata v)
252
+ {
253
+ v2f o;
261
- return fixed4(result, 0.0, 0.0, 1.0);
254
+ o.vertex = UnityObjectToClipPos(v.vertex);
255
+ o.uv = v.uv;
256
+ return o;
262
- }
257
+ }
258
+
259
+ fixed4 frag(v2f i) : SV_Target
260
+ {
261
+ // 近傍4テクセルの中心からサンプリング、ピクセル色が0より大きければ(1のテクセルが1つ以上あれば)1、さもなくば0
262
+ float result = sign(tex2D(_MainTex, i.uv).r);
263
+
264
+ return fixed4(result, result, result, 1.0);
265
+ }
263
- ENDCG
266
+ ENDCG
264
- }
267
+ }
265
- }
268
+ }
266
269
  }
267
270
  ```
268
271
 

3

マテリアルをHideFlags.DontSave指定する必要はなかった気がしたので削除

2017/11/18 03:04

投稿

Bongo
Bongo

スコア10816

answer CHANGED
@@ -83,7 +83,6 @@
83
83
  if (this.material == null)
84
84
  {
85
85
  this.material = new Material(Shader.Find("Hidden/Color Extractor"));
86
- this.material.hideFlags = HideFlags.DontSave;
87
86
  this.referenceColorId = Shader.PropertyToID("_ReferenceColor");
88
87
  this.referenceColorThresholdId = Shader.PropertyToID("_ReferenceColorThreshold");
89
88
  }

2

リファレンスのリンク先を修正

2017/11/17 23:39

投稿

Bongo
Bongo

スコア10816

answer CHANGED
@@ -11,7 +11,7 @@
11
11
  自身の勉強も兼ねて、下記のような方法での色判定を試してみました。
12
12
 
13
13
  - 画面をレンダリングする。天球画像の代用としてシーンに赤い球を配置し、カメラに赤色が写り込んでいるかを判定することにした。
14
- - [ポストプロセッシングエフェクト](https://docs.unity3d.com/Manual/PostProcessingWritingEffects.html)のやり方を参考に、カメラにアタッチしたスクリプトの[OnRenderImage](https://docs.unity3d.com/ScriptReference/Camera.OnRenderImage.html)内で色判定処理を行う。
14
+ - [ポストプロセッシングエフェクト](https://docs.unity3d.com/Manual/PostProcessingWritingEffects.html)のやり方を参考に、カメラにアタッチしたスクリプトの[OnRenderImage](https://docs.unity3d.com/ScriptReference/MonoBehaviour.OnRenderImage.html)内で色判定処理を行う。
15
15
  - レンダリング結果を適当な2の冪乗サイズの一時レンダーテクスチャに写す。この時色判定を行い、目的の色であれば白、そうでなければ黒として写す。
16
16
  ※色判定はピクセル色と目的色の距離が一定以下なら真とすることにしましたが、他にも色相の一致度を見るなどでもいいと思います。
17
17
  - 先の白黒画像を縦横1/2の一時レンダーテクスチャに写す。この時、白黒画像からサンプリングした色が真っ黒でなければ、サンプリングされた4テクセルの内1つ以上白テクセルがあるものと考え、出力する色を白とする。そうでなければ黒とする。

1

リンクを追加、機能名を訂正

2017/11/17 23:02

投稿

Bongo
Bongo

スコア10816

answer CHANGED
@@ -271,6 +271,6 @@
271
271
 
272
272
  ![プレビュー](fc352991ff1d69d69f435c1946ceb3c3.gif)
273
273
 
274
- - フレームデバッで見た描画の過程
274
+ - [フレームデバッガ](https://docs.unity3d.com/Manual/FrameDebugger.html)で見た描画の過程
275
275
 
276
- ![フレームデバッ](ce43511581e94bfc1e5fc171a31dba0a.gif)
276
+ ![フレームデバッ](ce43511581e94bfc1e5fc171a31dba0a.gif)