回答編集履歴

1

改造版シェーダーを追記

2019/11/08 19:45

投稿

Bongo
Bongo

スコア10807

test CHANGED
@@ -73,3 +73,307 @@
73
73
  }
74
74
 
75
75
  ```
76
+
77
+
78
+
79
+ **追記**
80
+
81
+ 外周部が引き延ばされる現象を防止する措置を加えてみました。
82
+
83
+ ```ShaderLab
84
+
85
+ Shader "Projector/LightClipped" {
86
+
87
+ Properties {
88
+
89
+ _Color ("Main Color", Color) = (1,1,1,1)
90
+
91
+ _ShadowTex ("Cookie", 2D) = "" {}
92
+
93
+ _FalloffTex ("FallOff", 2D) = "" {}
94
+
95
+ }
96
+
97
+
98
+
99
+ Subshader {
100
+
101
+ Tags {"Queue"="Transparent"}
102
+
103
+ Pass {
104
+
105
+ ZWrite Off
106
+
107
+ ColorMask RGB
108
+
109
+ Blend DstColor One
110
+
111
+ Offset -1, -1
112
+
113
+
114
+
115
+ CGPROGRAM
116
+
117
+ #pragma vertex vert
118
+
119
+ #pragma fragment frag
120
+
121
+ #pragma multi_compile_fog
122
+
123
+ #include "UnityCG.cginc"
124
+
125
+
126
+
127
+ struct v2f {
128
+
129
+ float4 uvShadow : TEXCOORD0;
130
+
131
+ float4 uvFalloff : TEXCOORD1;
132
+
133
+ UNITY_FOG_COORDS(2)
134
+
135
+ float4 pos : SV_POSITION;
136
+
137
+ };
138
+
139
+
140
+
141
+ float4x4 unity_Projector;
142
+
143
+ float4x4 unity_ProjectorClip;
144
+
145
+
146
+
147
+ v2f vert (float4 vertex : POSITION)
148
+
149
+ {
150
+
151
+ v2f o;
152
+
153
+ o.pos = UnityObjectToClipPos(vertex);
154
+
155
+ o.uvShadow = mul (unity_Projector, vertex);
156
+
157
+ o.uvFalloff = mul (unity_ProjectorClip, vertex);
158
+
159
+ UNITY_TRANSFER_FOG(o,o.pos);
160
+
161
+ return o;
162
+
163
+ }
164
+
165
+
166
+
167
+ fixed4 _Color;
168
+
169
+ sampler2D _ShadowTex;
170
+
171
+ sampler2D _FalloffTex;
172
+
173
+
174
+
175
+ fixed4 frag (v2f i) : SV_Target
176
+
177
+ {
178
+
179
+ // まずuvShadowをプロジェクション座標に直し...
180
+
181
+ float4 projCoord = UNITY_PROJ_COORD(i.uvShadow);
182
+
183
+
184
+
185
+ // 元のコードでは同次座標形式のままtex2Dprojでテクスチャサンプリングしているが、
186
+
187
+ // 代わりに事前にwで割ってしまい...
188
+
189
+ projCoord /= projCoord.w;
190
+
191
+
192
+
193
+ // 得られたUV座標を0~1にクランプ、さらにクランプ前の座標の絶対値を引くと
194
+
195
+ // 結果は座標が0~1の範囲内であれば0、範囲を外れていればマイナスになるはずなので
196
+
197
+ // これをclipに渡せば、値がマイナスのフラグメントは破棄される
198
+
199
+ clip(clamp(projCoord.xy, 0.0, 1.0) - abs(projCoord.xy));
200
+
201
+
202
+
203
+ // _ShadowTexからテクスチャサンプリングを行う
204
+
205
+ // projCoordはw除算済みなので、tex2Dprojの代わりにtex2Dを使う
206
+
207
+ fixed4 texS = tex2D (_ShadowTex, projCoord.xy);
208
+
209
+
210
+
211
+ texS.rgb *= _Color.rgb;
212
+
213
+ texS.a = 1.0-texS.a;
214
+
215
+
216
+
217
+ fixed4 texF = tex2Dproj (_FalloffTex, UNITY_PROJ_COORD(i.uvFalloff));
218
+
219
+ fixed4 res = texS * texF.a;
220
+
221
+
222
+
223
+ UNITY_APPLY_FOG_COLOR(i.fogCoord, res, fixed4(0,0,0,0));
224
+
225
+ return res;
226
+
227
+ }
228
+
229
+ ENDCG
230
+
231
+ }
232
+
233
+ }
234
+
235
+ }
236
+
237
+ ```
238
+
239
+ もし色合成方法を通常のUnlitシェーダー風にする場合、下記のようにしてみてはどうでしょうか。
240
+
241
+ ```ShaderLab
242
+
243
+ Shader "Projector/UnlitClipped" {
244
+
245
+ Properties {
246
+
247
+ _Color ("Main Color", Color) = (1,1,1,1)
248
+
249
+ _ShadowTex ("Cookie", 2D) = "white" {}
250
+
251
+ _FalloffTex ("FallOff", 2D) = "white" {}
252
+
253
+ }
254
+
255
+
256
+
257
+ Subshader {
258
+
259
+ Tags {"Queue"="Transparent"}
260
+
261
+ Pass {
262
+
263
+ ZWrite Off
264
+
265
+
266
+
267
+ // 合成方法を一般的なアルファブレンディングに変更
268
+
269
+ // カラーマスクも指定せず、アルファチャンネルへも通常通り書き込むようにする
270
+
271
+ Blend SrcAlpha OneMinusSrcAlpha
272
+
273
+
274
+
275
+ Offset -1, -1
276
+
277
+
278
+
279
+ CGPROGRAM
280
+
281
+ #pragma vertex vert
282
+
283
+ #pragma fragment frag
284
+
285
+ #pragma multi_compile_fog
286
+
287
+ #include "UnityCG.cginc"
288
+
289
+
290
+
291
+ struct v2f {
292
+
293
+ float4 uvShadow : TEXCOORD0;
294
+
295
+ float4 uvFalloff : TEXCOORD1;
296
+
297
+ UNITY_FOG_COORDS(2)
298
+
299
+ float4 pos : SV_POSITION;
300
+
301
+ };
302
+
303
+
304
+
305
+ float4x4 unity_Projector;
306
+
307
+ float4x4 unity_ProjectorClip;
308
+
309
+
310
+
311
+ v2f vert (float4 vertex : POSITION)
312
+
313
+ {
314
+
315
+ v2f o;
316
+
317
+ o.pos = UnityObjectToClipPos(vertex);
318
+
319
+ o.uvShadow = mul (unity_Projector, vertex);
320
+
321
+ o.uvFalloff = mul (unity_ProjectorClip, vertex);
322
+
323
+ UNITY_TRANSFER_FOG(o,o.pos);
324
+
325
+ return o;
326
+
327
+ }
328
+
329
+
330
+
331
+ fixed4 _Color;
332
+
333
+ sampler2D _ShadowTex;
334
+
335
+ sampler2D _FalloffTex;
336
+
337
+
338
+
339
+ fixed4 frag (v2f i) : SV_Target
340
+
341
+ {
342
+
343
+ // _ShadowTexのサンプリングはLightClippedと同様に行い...
344
+
345
+ float4 projCoord = UNITY_PROJ_COORD(i.uvShadow);
346
+
347
+ projCoord /= projCoord.w;
348
+
349
+ clip(clamp(projCoord.xy, 0.0, 1.0) - abs(projCoord.xy));
350
+
351
+ fixed4 texS = tex2D (_ShadowTex, projCoord.xy);
352
+
353
+
354
+
355
+ // 以降の色合成は通常のUnlitシェーダーと同様に
356
+
357
+ // 普通のアルファブレンディングを前提としたスタイルに変える
358
+
359
+ texS *= _Color;
360
+
361
+ fixed4 texF = tex2Dproj (_FalloffTex, UNITY_PROJ_COORD(i.uvFalloff));
362
+
363
+ fixed4 res = texS * fixed4(1.0, 1.0, 1.0, texF.a);
364
+
365
+ UNITY_APPLY_FOG(i.fogCoord, res);
366
+
367
+ return res;
368
+
369
+ }
370
+
371
+ ENDCG
372
+
373
+ }
374
+
375
+ }
376
+
377
+ }
378
+
379
+ ```