現在スマートフォンのアクションゲームで、プレイヤーに画面上にある特定のオブジェクトがタッチできることを知らせるようなエフェクトを実装したいと考えています。
エフェクトの方針としては、↓画像のようなタッチできる特定のオブジェクトの後ろにパーティクルを発生させる、というものを考えています。
3Dのパーティクルを実際のシーンに置くにあたり、ここで問題が起こります。
例えば後ろに壁等がある場合、壁にエフェクト対象オブジェクトが密着していた場合、↓画像のようにパーティクルがめり込んでしまいます。
そこで、パーティクルとエフェクト対象オブジェクトのレイヤーを変更し、それのみを移すカメラを用意して実装しようと考えたのですが、そうするとどんな状況でも壁を貫通してしまい、画面上で不自然に描画されてしまいます。
実装したいイメージとしては、ゲームでよくあるゲームオブジェクトのアウトラインUIがパーティクルで表現されているようなイメージなのですが、このような「特定のオブジェクトの前だけ描画されないエフェクト」を作成するには、どのような方法があるでしょうか?
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/07/19 05:03
2020/07/19 05:47
2020/07/19 06:15
回答2件
0
ベストアンサー
パーティクルやオブジェクトのマテリアルに変更を加えてもかまわなければ、それらにステンシルの設定を追加することで何とかならないでしょうか?
bboydaisukeさんの案のようにパーティクルをモデルの全身から放射させるようにした上で、モデル側の描画時にはステンシルバッファに何らかの値を書き込み、パーティクル側の描画時にはステンシルバッファ上の値が書き換えられていないピクセルだけに描画を行うことにすれば、モデルの前面にかぶらせずにパーティクルを描画できるんじゃないかと思います。
たとえば下記のようにパーティクル側、モデル側の双方にステンシル設定を調整できるように改修を加え(いずれもメイン部分には手を加えておらず、単にプロパティとStencil
ブロックを追加しただけです)...
ShaderLab
1// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt) 2 3Shader "Particles/Alpha Blended Premultiply (Stencil)" { 4 Properties { 5 _MainTex ("Particle Texture", 2D) = "white" {} 6 _InvFade ("Soft Particles Factor", Range(0.01,3.0)) = 1.0 7 8 // ステンシル用プロパティを追加 9 _StencilComp ("Stencil Comparison", Float) = 8 10 _Stencil ("Stencil ID", Float) = 0 11 _StencilOp ("Stencil Operation", Float) = 0 12 _StencilWriteMask ("Stencil Write Mask", Float) = 255 13 _StencilReadMask ("Stencil Read Mask", Float) = 255 14 15 // _StencilCompはUnityEngine.Rendering.CompareFunctionの値をとる 16 // 0: Disabled 17 // 1: Never 18 // 2: Less 19 // 3: Equal 20 // 4: LessEqual 21 // 5: Greater 22 // 6: NotEqual 23 // 7: GreaterEqual 24 // 8: Always 25 26 // _StencilOpはUnityEngine.Rendering.StencilOpの値をとる 27 // 0: Keep 28 // 1: Zero 29 // 2: Replace 30 // 3: IncrementSaturate 31 // 4: DecrementSaturate 32 // 5: Invert 33 // 6: IncrementWrap 34 // 7: DecrementWrap 35 } 36 37 Category { 38 Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "PreviewType"="Plane" } 39 Blend One OneMinusSrcAlpha 40 ColorMask RGB 41 Cull Off Lighting Off ZWrite Off 42 43 // ステンシル設定を追加 44 Stencil 45 { 46 Ref [_Stencil] 47 Comp [_StencilComp] 48 Pass [_StencilOp] 49 ReadMask [_StencilReadMask] 50 WriteMask [_StencilWriteMask] 51 } 52 53 SubShader { 54 Pass { 55 56 CGPROGRAM 57 #pragma vertex vert 58 #pragma fragment frag 59 #pragma target 2.0 60 #pragma multi_compile_particles 61 62 #include "UnityCG.cginc" 63 64 sampler2D _MainTex; 65 fixed4 _TintColor; 66 67 struct appdata_t { 68 float4 vertex : POSITION; 69 fixed4 color : COLOR; 70 float2 texcoord : TEXCOORD0; 71 UNITY_VERTEX_INPUT_INSTANCE_ID 72 }; 73 74 struct v2f { 75 float4 vertex : SV_POSITION; 76 fixed4 color : COLOR; 77 float2 texcoord : TEXCOORD0; 78 #ifdef SOFTPARTICLES_ON 79 float4 projPos : TEXCOORD1; 80 #endif 81 UNITY_VERTEX_OUTPUT_STEREO 82 }; 83 84 float4 _MainTex_ST; 85 86 v2f vert (appdata_t v) 87 { 88 v2f o; 89 UNITY_SETUP_INSTANCE_ID(v); 90 UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); 91 o.vertex = UnityObjectToClipPos(v.vertex); 92 #ifdef SOFTPARTICLES_ON 93 o.projPos = ComputeScreenPos (o.vertex); 94 COMPUTE_EYEDEPTH(o.projPos.z); 95 #endif 96 o.color = v.color; 97 o.texcoord = TRANSFORM_TEX(v.texcoord,_MainTex); 98 return o; 99 } 100 101 UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture); 102 float _InvFade; 103 104 fixed4 frag (v2f i) : SV_Target 105 { 106 #ifdef SOFTPARTICLES_ON 107 float sceneZ = LinearEyeDepth (SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(i.projPos))); 108 float partZ = i.projPos.z; 109 float fade = saturate (_InvFade * (sceneZ-partZ)); 110 i.color.a *= fade; 111 #endif 112 113 return i.color * tex2D(_MainTex, i.texcoord) * i.color.a; 114 } 115 ENDCG 116 } 117 } 118 } 119}
ShaderLab
1Shader "Custom/Standard Surface Shader (Stencil)" 2{ 3 Properties 4 { 5 _Color ("Color", Color) = (1,1,1,1) 6 _MainTex ("Albedo (RGB)", 2D) = "white" {} 7 _Glossiness ("Smoothness", Range(0,1)) = 0.5 8 _Metallic ("Metallic", Range(0,1)) = 0.0 9 10 // ステンシル用プロパティを追加 11 _StencilComp ("Stencil Comparison", Float) = 8 12 _Stencil ("Stencil ID", Float) = 0 13 _StencilOp ("Stencil Operation", Float) = 0 14 _StencilWriteMask ("Stencil Write Mask", Float) = 255 15 _StencilReadMask ("Stencil Read Mask", Float) = 255 16 } 17 SubShader 18 { 19 Tags { "RenderType"="Opaque" } 20 21 // ステンシル設定を追加 22 Stencil 23 { 24 Ref [_Stencil] 25 Comp [_StencilComp] 26 Pass [_StencilOp] 27 ReadMask [_StencilReadMask] 28 WriteMask [_StencilWriteMask] 29 } 30 31 LOD 200 32 33 CGPROGRAM 34 // Physically based Standard lighting model, and enable shadows on all light types 35 #pragma surface surf Standard fullforwardshadows 36 37 // Use shader model 3.0 target, to get nicer looking lighting 38 #pragma target 3.0 39 40 sampler2D _MainTex; 41 42 struct Input 43 { 44 float2 uv_MainTex; 45 }; 46 47 half _Glossiness; 48 half _Metallic; 49 fixed4 _Color; 50 51 // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader. 52 // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing. 53 // #pragma instancing_options assumeuniformscaling 54 UNITY_INSTANCING_BUFFER_START(Props) 55 // put more per-instance properties here 56 UNITY_INSTANCING_BUFFER_END(Props) 57 58 void surf (Input IN, inout SurfaceOutputStandard o) 59 { 60 // Albedo comes from a texture tinted by color 61 fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color; 62 o.Albedo = c.rgb; 63 // Metallic and smoothness come from slider variables 64 o.Metallic = _Metallic; 65 o.Smoothness = _Glossiness; 66 o.Alpha = c.a; 67 } 68 ENDCG 69 } 70 FallBack "Diffuse" 71}
モデル側はステンシルバッファの下1桁に1を書き込み...
パーティクル側はステンシルバッファの下1桁が1でない場合だけ描画することにすれば...
下図のような見え方になりました。
※ちなみに、上から見たときにティーポットの注ぎ口やフタの縁の隙間からパーティクルや背景が見えてしまっているのは、モデルの作りのせいです...
これは単純に注ぎ口の内面やフタと本体の隙間に面が作られていないためなのです。メッシュ表面に破れがないモデルならば、どの方角から見ても大丈夫だろうと思います。
投稿2020/07/19 11:00
総合スコア10811
0
こんな感じでしょうか。
設定のポイントとしては以下の通りです。
Shape モジュール
Shape: Mesh Renderer
Mesh: 自分自身のメッシュ
Type: Triangle
Collision モジュール
Type: World
Collide With: 自分の Layer には当たらず、相手(板)のレイヤーに当たるようにする
後は適当です。Shape モジュールにより「メッシュの表面から湧き出るような効果」を与え、Collision モジュールにより衝突判定をしています。
設定については「どのモジュールにどんな機能があり、各パラメータを操作すると何が起きるのか」といったことを一通り学ぶとよいでしょう。『Unity ゲームエフェクト入門』にそのあたりの事がステップバイステップで載ってます。
あとは Particle にテクスチャを使ったり重ねたりする事でさらに細かい表現ができます。
投稿2020/07/18 17:17
総合スコア5308
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/07/19 02:10
2020/07/19 08:20
2020/07/19 09:39
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。