回答編集履歴
1
反転対策案を追記
answer
CHANGED
@@ -1,2 +1,215 @@
|
|
1
1
|
もしかして「Edit」→「Project Settings...」の「Other Settings」→「Graphics APIs for Mac」が「Metal」の時だけ反転したりしますかね?
|
2
|
-
試しに`ScreenShot`スクリプトの「Camera Event」を一段階手前の「After Forward Alpha」に変更してみるとどうでしょうか。もしそれでは改善しない、あるいは他の問題が発生するようでしたら何か別の手を考えてみます。
|
2
|
+
試しに`ScreenShot`スクリプトの「Camera Event」を一段階手前の「After Forward Alpha」に変更してみるとどうでしょうか。もしそれでは改善しない、あるいは他の問題が発生するようでしたら何か別の手を考えてみます。
|
3
|
+
|
4
|
+
**ScreenShot改造案**
|
5
|
+
|
6
|
+
まず下記のようなY軸反転シェーダーを用意して...
|
7
|
+
|
8
|
+
```ShaderLab
|
9
|
+
Shader "Hidden/FlipY"
|
10
|
+
{
|
11
|
+
Properties
|
12
|
+
{
|
13
|
+
_MainTex ("Texture", 2D) = "white" {}
|
14
|
+
}
|
15
|
+
SubShader
|
16
|
+
{
|
17
|
+
Cull Off ZWrite Off ZTest Always
|
18
|
+
|
19
|
+
Pass
|
20
|
+
{
|
21
|
+
CGPROGRAM
|
22
|
+
#pragma vertex vert
|
23
|
+
#pragma fragment frag
|
24
|
+
|
25
|
+
#include "UnityCG.cginc"
|
26
|
+
|
27
|
+
struct appdata
|
28
|
+
{
|
29
|
+
float4 vertex : POSITION;
|
30
|
+
float2 uv : TEXCOORD0;
|
31
|
+
};
|
32
|
+
|
33
|
+
struct v2f
|
34
|
+
{
|
35
|
+
float2 uv : TEXCOORD0;
|
36
|
+
float4 vertex : SV_POSITION;
|
37
|
+
};
|
38
|
+
|
39
|
+
v2f vert(appdata v)
|
40
|
+
{
|
41
|
+
v2f o;
|
42
|
+
o.vertex = UnityObjectToClipPos(v.vertex);
|
43
|
+
o.uv = v.uv;
|
44
|
+
o.uv.y = 1.0 - o.uv.y;
|
45
|
+
return o;
|
46
|
+
}
|
47
|
+
|
48
|
+
sampler2D _MainTex;
|
49
|
+
|
50
|
+
fixed4 frag(v2f i) : SV_Target
|
51
|
+
{
|
52
|
+
return tex2D(_MainTex, i.uv);
|
53
|
+
}
|
54
|
+
ENDCG
|
55
|
+
}
|
56
|
+
}
|
57
|
+
}
|
58
|
+
```
|
59
|
+
|
60
|
+
`ScreenShot`にフィールドを追加、`CreateBuffer`メソッド中にY軸反転処理を組み込んでみました。
|
61
|
+
|
62
|
+
```C#
|
63
|
+
using System.Collections;
|
64
|
+
using System.Collections.Generic;
|
65
|
+
using UnityEngine;
|
66
|
+
using System.IO;
|
67
|
+
using UnityEngine.Rendering;
|
68
|
+
using System;
|
69
|
+
|
70
|
+
public class ScreenShot : MonoBehaviour
|
71
|
+
{
|
72
|
+
|
73
|
+
public event System.Action<RenderTexture> OnCaptured;
|
74
|
+
|
75
|
+
[SerializeField, Tooltip("GUIをレンダリングしているカメラ")]
|
76
|
+
private Camera _guiCamera = null;
|
77
|
+
|
78
|
+
[SerializeField, Tooltip("キャプチャするタイミング")]
|
79
|
+
private CameraEvent _cameraEvent = CameraEvent.BeforeImageEffects;
|
80
|
+
|
81
|
+
[SerializeField, Tooltip("合成時に無視されるUIのレイヤー")]
|
82
|
+
private LayerMask _captureTargetLayer = -1;
|
83
|
+
|
84
|
+
[SerializeField, Tooltip("ARカメラ")]
|
85
|
+
private Camera _mainCamera = null;
|
86
|
+
|
87
|
+
// ここに前述のY反転シェーダーをセットしておく
|
88
|
+
[SerializeField, Tooltip("Y反転シェーダー")]
|
89
|
+
private Shader _flipYShader;
|
90
|
+
private Material _flipYMaterial;
|
91
|
+
|
92
|
+
private RenderTexture _buf = null;
|
93
|
+
private CommandBuffer _commandBuffer = null;
|
94
|
+
|
95
|
+
#region ### MonoBehaviour ###
|
96
|
+
|
97
|
+
private void Awake()
|
98
|
+
{
|
99
|
+
CreateBuffer();
|
100
|
+
}
|
101
|
+
/// <summary>
|
102
|
+
/// 動作確認用にGizmoでテクスチャを表示する
|
103
|
+
/// </summary>
|
104
|
+
private void OnGUI()
|
105
|
+
{
|
106
|
+
if (_buf == null) return;
|
107
|
+
GUI.DrawTexture(new Rect(5f, 5f, Screen.width * 0.5f, Screen.height * 0.5f), _buf);
|
108
|
+
}
|
109
|
+
|
110
|
+
public void OnClick()
|
111
|
+
{
|
112
|
+
TakeScreenshot();
|
113
|
+
}
|
114
|
+
|
115
|
+
#endregion ### MonoBehaviour ###
|
116
|
+
|
117
|
+
/// <summary>
|
118
|
+
/// バッファを生成する
|
119
|
+
/// </summary>
|
120
|
+
private void CreateBuffer()
|
121
|
+
{
|
122
|
+
_buf = new RenderTexture(Screen.width, Screen.height, 0);
|
123
|
+
|
124
|
+
_commandBuffer = new CommandBuffer();
|
125
|
+
_commandBuffer.name = "CaptureScene";
|
126
|
+
if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Metal)
|
127
|
+
{
|
128
|
+
// Metal上で動作している場合、CurrentActiveを一旦別のレンダーテクスチャに写し取り
|
129
|
+
// それをさらにY反転シェーダーを通して_bufにレンダリングする
|
130
|
+
if (_flipYMaterial == null)
|
131
|
+
{
|
132
|
+
_flipYMaterial = new Material(_flipYShader);
|
133
|
+
}
|
134
|
+
int tempTexture = Shader.PropertyToID("_TempTex");
|
135
|
+
_commandBuffer.GetTemporaryRT(tempTexture, -1, -1);
|
136
|
+
_commandBuffer.Blit(BuiltinRenderTextureType.CurrentActive, tempTexture);
|
137
|
+
_commandBuffer.Blit(tempTexture, _buf, _flipYMaterial);
|
138
|
+
_commandBuffer.ReleaseTemporaryRT(tempTexture);
|
139
|
+
}
|
140
|
+
else
|
141
|
+
{
|
142
|
+
_commandBuffer.Blit(BuiltinRenderTextureType.CurrentActive, _buf);
|
143
|
+
}
|
144
|
+
}
|
145
|
+
|
146
|
+
/// <summary>
|
147
|
+
/// スクリーンショットを撮影する
|
148
|
+
/// </summary>
|
149
|
+
public void TakeScreenshot()
|
150
|
+
{
|
151
|
+
AddCommandBuffer();
|
152
|
+
|
153
|
+
StartCoroutine(WaitCapture());
|
154
|
+
}
|
155
|
+
|
156
|
+
/// <summary>
|
157
|
+
/// コマンドバッファの処理を待つ
|
158
|
+
/// </summary>
|
159
|
+
private IEnumerator WaitCapture()
|
160
|
+
{
|
161
|
+
yield return new WaitForEndOfFrame();
|
162
|
+
|
163
|
+
BlendGUI();
|
164
|
+
|
165
|
+
if (OnCaptured != null)
|
166
|
+
{
|
167
|
+
OnCaptured.Invoke(_buf);
|
168
|
+
}
|
169
|
+
|
170
|
+
RemoveCommandBuffer();
|
171
|
+
}
|
172
|
+
|
173
|
+
/// <summary>
|
174
|
+
/// GUI要素をブレンドする
|
175
|
+
/// </summary>
|
176
|
+
private void BlendGUI()
|
177
|
+
{
|
178
|
+
_guiCamera.targetTexture = _buf;
|
179
|
+
|
180
|
+
int tmp = _guiCamera.cullingMask;
|
181
|
+
_guiCamera.cullingMask = _captureTargetLayer;
|
182
|
+
|
183
|
+
_guiCamera.Render();
|
184
|
+
|
185
|
+
_guiCamera.cullingMask = tmp;
|
186
|
+
|
187
|
+
_guiCamera.targetTexture = null;
|
188
|
+
}
|
189
|
+
|
190
|
+
/// <summary>
|
191
|
+
/// メインカメラにコマンドバッファを追加する
|
192
|
+
/// </summary>
|
193
|
+
private void AddCommandBuffer()
|
194
|
+
{
|
195
|
+
_mainCamera.AddCommandBuffer(_cameraEvent, _commandBuffer);
|
196
|
+
}
|
197
|
+
|
198
|
+
/// <summary>
|
199
|
+
/// メインカメラからコマンドバッファを削除する
|
200
|
+
/// </summary>
|
201
|
+
private void RemoveCommandBuffer()
|
202
|
+
{
|
203
|
+
if (_mainCamera == null)
|
204
|
+
{
|
205
|
+
return;
|
206
|
+
}
|
207
|
+
|
208
|
+
_mainCamera.RemoveCommandBuffer(_cameraEvent, _commandBuffer);
|
209
|
+
}
|
210
|
+
|
211
|
+
}
|
212
|
+
```
|
213
|
+
|
214
|
+
`_commandBuffer.Blit(BuiltinRenderTextureType.CurrentActive, _buf, _flipYMaterial);`とせずにわざわざ`tempTexture`に写してから反転していますが、これは`CurrentActive`がテクスチャではなくレンダーバッファであるケースを考慮したものです。
|
215
|
+
どうやら`Blit`はソース側がテクスチャでない場合、シェーダーを通してのレンダリングができないために代わりに単純な[ビットブリット](https://en.wikipedia.org/wiki/Bit_blit)的な処理([Texture2D.ReadPixels](https://docs.unity3d.com/jp/current/ScriptReference/Texture2D.ReadPixels.html)のようなもの?)を行うらしく、独自のマテリアルを使っての加工ができなそうだったためあのようにしました。
|