回答編集履歴

1

反転対策案を追記

2020/02/21 21:08

投稿

Bongo
Bongo

スコア10807

test CHANGED
@@ -1,3 +1,429 @@
1
1
  もしかして「Edit」→「Project Settings...」の「Other Settings」→「Graphics APIs for Mac」が「Metal」の時だけ反転したりしますかね?
2
2
 
3
3
  試しに`ScreenShot`スクリプトの「Camera Event」を一段階手前の「After Forward Alpha」に変更してみるとどうでしょうか。もしそれでは改善しない、あるいは他の問題が発生するようでしたら何か別の手を考えてみます。
4
+
5
+
6
+
7
+ **ScreenShot改造案**
8
+
9
+
10
+
11
+ まず下記のようなY軸反転シェーダーを用意して...
12
+
13
+
14
+
15
+ ```ShaderLab
16
+
17
+ Shader "Hidden/FlipY"
18
+
19
+ {
20
+
21
+ Properties
22
+
23
+ {
24
+
25
+ _MainTex ("Texture", 2D) = "white" {}
26
+
27
+ }
28
+
29
+ SubShader
30
+
31
+ {
32
+
33
+ Cull Off ZWrite Off ZTest Always
34
+
35
+
36
+
37
+ Pass
38
+
39
+ {
40
+
41
+ CGPROGRAM
42
+
43
+ #pragma vertex vert
44
+
45
+ #pragma fragment frag
46
+
47
+
48
+
49
+ #include "UnityCG.cginc"
50
+
51
+
52
+
53
+ struct appdata
54
+
55
+ {
56
+
57
+ float4 vertex : POSITION;
58
+
59
+ float2 uv : TEXCOORD0;
60
+
61
+ };
62
+
63
+
64
+
65
+ struct v2f
66
+
67
+ {
68
+
69
+ float2 uv : TEXCOORD0;
70
+
71
+ float4 vertex : SV_POSITION;
72
+
73
+ };
74
+
75
+
76
+
77
+ v2f vert(appdata v)
78
+
79
+ {
80
+
81
+ v2f o;
82
+
83
+ o.vertex = UnityObjectToClipPos(v.vertex);
84
+
85
+ o.uv = v.uv;
86
+
87
+ o.uv.y = 1.0 - o.uv.y;
88
+
89
+ return o;
90
+
91
+ }
92
+
93
+
94
+
95
+ sampler2D _MainTex;
96
+
97
+
98
+
99
+ fixed4 frag(v2f i) : SV_Target
100
+
101
+ {
102
+
103
+ return tex2D(_MainTex, i.uv);
104
+
105
+ }
106
+
107
+ ENDCG
108
+
109
+ }
110
+
111
+ }
112
+
113
+ }
114
+
115
+ ```
116
+
117
+
118
+
119
+ `ScreenShot`にフィールドを追加、`CreateBuffer`メソッド中にY軸反転処理を組み込んでみました。
120
+
121
+
122
+
123
+ ```C#
124
+
125
+ using System.Collections;
126
+
127
+ using System.Collections.Generic;
128
+
129
+ using UnityEngine;
130
+
131
+ using System.IO;
132
+
133
+ using UnityEngine.Rendering;
134
+
135
+ using System;
136
+
137
+
138
+
139
+ public class ScreenShot : MonoBehaviour
140
+
141
+ {
142
+
143
+
144
+
145
+ public event System.Action<RenderTexture> OnCaptured;
146
+
147
+
148
+
149
+ [SerializeField, Tooltip("GUIをレンダリングしているカメラ")]
150
+
151
+ private Camera _guiCamera = null;
152
+
153
+
154
+
155
+ [SerializeField, Tooltip("キャプチャするタイミング")]
156
+
157
+ private CameraEvent _cameraEvent = CameraEvent.BeforeImageEffects;
158
+
159
+
160
+
161
+ [SerializeField, Tooltip("合成時に無視されるUIのレイヤー")]
162
+
163
+ private LayerMask _captureTargetLayer = -1;
164
+
165
+
166
+
167
+ [SerializeField, Tooltip("ARカメラ")]
168
+
169
+ private Camera _mainCamera = null;
170
+
171
+
172
+
173
+ // ここに前述のY反転シェーダーをセットしておく
174
+
175
+ [SerializeField, Tooltip("Y反転シェーダー")]
176
+
177
+ private Shader _flipYShader;
178
+
179
+ private Material _flipYMaterial;
180
+
181
+
182
+
183
+ private RenderTexture _buf = null;
184
+
185
+ private CommandBuffer _commandBuffer = null;
186
+
187
+
188
+
189
+ #region ### MonoBehaviour ###
190
+
191
+
192
+
193
+ private void Awake()
194
+
195
+ {
196
+
197
+ CreateBuffer();
198
+
199
+ }
200
+
201
+ /// <summary>
202
+
203
+ /// 動作確認用にGizmoでテクスチャを表示する
204
+
205
+ /// </summary>
206
+
207
+ private void OnGUI()
208
+
209
+ {
210
+
211
+ if (_buf == null) return;
212
+
213
+ GUI.DrawTexture(new Rect(5f, 5f, Screen.width * 0.5f, Screen.height * 0.5f), _buf);
214
+
215
+ }
216
+
217
+
218
+
219
+ public void OnClick()
220
+
221
+ {
222
+
223
+ TakeScreenshot();
224
+
225
+ }
226
+
227
+
228
+
229
+ #endregion ### MonoBehaviour ###
230
+
231
+
232
+
233
+ /// <summary>
234
+
235
+ /// バッファを生成する
236
+
237
+ /// </summary>
238
+
239
+ private void CreateBuffer()
240
+
241
+ {
242
+
243
+ _buf = new RenderTexture(Screen.width, Screen.height, 0);
244
+
245
+
246
+
247
+ _commandBuffer = new CommandBuffer();
248
+
249
+ _commandBuffer.name = "CaptureScene";
250
+
251
+ if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Metal)
252
+
253
+ {
254
+
255
+ // Metal上で動作している場合、CurrentActiveを一旦別のレンダーテクスチャに写し取り
256
+
257
+ // それをさらにY反転シェーダーを通して_bufにレンダリングする
258
+
259
+ if (_flipYMaterial == null)
260
+
261
+ {
262
+
263
+ _flipYMaterial = new Material(_flipYShader);
264
+
265
+ }
266
+
267
+ int tempTexture = Shader.PropertyToID("_TempTex");
268
+
269
+ _commandBuffer.GetTemporaryRT(tempTexture, -1, -1);
270
+
271
+ _commandBuffer.Blit(BuiltinRenderTextureType.CurrentActive, tempTexture);
272
+
273
+ _commandBuffer.Blit(tempTexture, _buf, _flipYMaterial);
274
+
275
+ _commandBuffer.ReleaseTemporaryRT(tempTexture);
276
+
277
+ }
278
+
279
+ else
280
+
281
+ {
282
+
283
+ _commandBuffer.Blit(BuiltinRenderTextureType.CurrentActive, _buf);
284
+
285
+ }
286
+
287
+ }
288
+
289
+
290
+
291
+ /// <summary>
292
+
293
+ /// スクリーンショットを撮影する
294
+
295
+ /// </summary>
296
+
297
+ public void TakeScreenshot()
298
+
299
+ {
300
+
301
+ AddCommandBuffer();
302
+
303
+
304
+
305
+ StartCoroutine(WaitCapture());
306
+
307
+ }
308
+
309
+
310
+
311
+ /// <summary>
312
+
313
+ /// コマンドバッファの処理を待つ
314
+
315
+ /// </summary>
316
+
317
+ private IEnumerator WaitCapture()
318
+
319
+ {
320
+
321
+ yield return new WaitForEndOfFrame();
322
+
323
+
324
+
325
+ BlendGUI();
326
+
327
+
328
+
329
+ if (OnCaptured != null)
330
+
331
+ {
332
+
333
+ OnCaptured.Invoke(_buf);
334
+
335
+ }
336
+
337
+
338
+
339
+ RemoveCommandBuffer();
340
+
341
+ }
342
+
343
+
344
+
345
+ /// <summary>
346
+
347
+ /// GUI要素をブレンドする
348
+
349
+ /// </summary>
350
+
351
+ private void BlendGUI()
352
+
353
+ {
354
+
355
+ _guiCamera.targetTexture = _buf;
356
+
357
+
358
+
359
+ int tmp = _guiCamera.cullingMask;
360
+
361
+ _guiCamera.cullingMask = _captureTargetLayer;
362
+
363
+
364
+
365
+ _guiCamera.Render();
366
+
367
+
368
+
369
+ _guiCamera.cullingMask = tmp;
370
+
371
+
372
+
373
+ _guiCamera.targetTexture = null;
374
+
375
+ }
376
+
377
+
378
+
379
+ /// <summary>
380
+
381
+ /// メインカメラにコマンドバッファを追加する
382
+
383
+ /// </summary>
384
+
385
+ private void AddCommandBuffer()
386
+
387
+ {
388
+
389
+ _mainCamera.AddCommandBuffer(_cameraEvent, _commandBuffer);
390
+
391
+ }
392
+
393
+
394
+
395
+ /// <summary>
396
+
397
+ /// メインカメラからコマンドバッファを削除する
398
+
399
+ /// </summary>
400
+
401
+ private void RemoveCommandBuffer()
402
+
403
+ {
404
+
405
+ if (_mainCamera == null)
406
+
407
+ {
408
+
409
+ return;
410
+
411
+ }
412
+
413
+
414
+
415
+ _mainCamera.RemoveCommandBuffer(_cameraEvent, _commandBuffer);
416
+
417
+ }
418
+
419
+
420
+
421
+ }
422
+
423
+ ```
424
+
425
+
426
+
427
+ `_commandBuffer.Blit(BuiltinRenderTextureType.CurrentActive, _buf, _flipYMaterial);`とせずにわざわざ`tempTexture`に写してから反転していますが、これは`CurrentActive`がテクスチャではなくレンダーバッファであるケースを考慮したものです。
428
+
429
+ どうやら`Blit`はソース側がテクスチャでない場合、シェーダーを通してのレンダリングができないために代わりに単純な[ビットブリット](https://en.wikipedia.org/wiki/Bit_blit)的な処理([Texture2D.ReadPixels](https://docs.unity3d.com/jp/current/ScriptReference/Texture2D.ReadPixels.html)のようなもの?)を行うらしく、独自のマテリアルを使っての加工ができなそうだったためあのようにしました。