NGUI의 Panel에 Spine을 클립 해 보았습니다.

앱에서 NGUI를 사용하고 있어 곤란한 이야기입니다. 이외에, 고민했기 때문에 메모도 겸해 투고합니다.

당시 상황



앱의 UI에는 NGUI를 사용했습니다.
또, 연출에는, Spine이 사용되고 있어 Unity의 Runtime으로 재생시키고 있습니다.
2D의 연출이나 이펙트에는 Spine이 사용되고 있는 곳이 많고, NGUI의 인스턴스에 AddComponent해 재생하고 있는 개소도 있습니다.

일어난 문제



NGUI로 View를 거듭했을 때, 뒤에서 재생되고 있는 Spine의 이펙트가, 전면에 있는 View에 숨기지 않고 표시되어 버렸습니다. 구체적으로는, UIScrollView에, UIGrid로 아이템을 늘어놓고 있어, 그 아이템의 아이에게 Spine의 Component가 있어, 재생되었을 때에 NGUI의 클립이 효과가 없고, 스크롤로 본래 숨어 보이지 않는 범위의 Spine의 연출 가 표시되는 상황이었습니다.

원인



NGUI는 아이의 오브젝트를 클립해, 묘화를 실시하고 있습니다만,Spine의 Runtime에서는 실시하고 있지 않습니다. 그 때문에, Spine에 클립하는 처리를 더합니다.

실시한 대응



이번에는 셰이더에 클립 영역을 전달하고 조각 셰이더로 클립합니다.

실제로 작성한 코드



UIPanel에는 localCorners와 worldCorners라는 멤버가 있습니다.
아래 이미지는 덤프를 시도한 로그입니다. 이미지에서 어떤 정보가 포함되어 있는지 상상할 수 있다고 생각합니다.


이번에는 Panel의 정점 좌표가 world 좌표계로 변환된 worldCorners를 그대로 사용할 수 있었습니다.
셰이더에 요소를 전달하는 코드입니다.
// MeshRendererは、MaterialにSetVectorする
meshRenderer = gameObject.GetComponent<MeshRenderer>();
// UIPanel は、GetComponentInParentしなくても、クリップする領域のpanelのインスタンスであれば、OK
worldCorners = gameObject.GetComponentInParent<UIPanel>().worldCorners;
mat = meshRenderer.material;

// _ClipArea
// x : UIPanel のxのworld座標系の左上のx座標
// y : UIPanel のyのworld座標系の左上のy座標
// z : UIPanel のxのworld座標系の右下のx座標
// w : UIPanel のyのworld座標系の右下のy座標
mat.SetVector("_ClipArea", new Vector4(worldCorners[0].x, worldCorners[0].y, worldCorners[2].x, worldCorners[2].y));

이번에는 Skeleton-Fog.shader를 수정했습니다.

정점 셰이더의 내용입니다.
worldPos에는 World 좌표로 변환한 vertex가 포함되어 있습니다. 2D의 UV 좌표계가 되어 있기 때문에 필요한 것은 x와 y의 값이 됩니다.
Skeleton-Fog.shader
------------------------------------------------
struct v2f {
    float4 vertex : SV_POSITION;
    float4 color : COLOR;
    float2 texcoord : TEXCOORD0;
    float2 worldPos : TEXCOORD1;
};

v2f vert(appdata_t v)
{
    v2f o;
    o.vertex = UnityObjectToClipPos(v.vertex);
    o.color = v.color;
    o.texcoord = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
    // クリップ領域をWorld座標に変換
    o.worldPos = mul(unity_ObjectToWorld, v.vertex).xy;
    return o;
}

프래그먼트 셰이더의 내용입니다.
worldPos에는 World 좌표로 변환된 vertex가 포함되어 있습니다.
또, _ClipArea에는, 클립 영역의 정보가 들어가 있을 것이므로, 이하와 같은 정보를 세트 하고 있으므로, x의 좌표의 판정은, x와 z로 체크해, y의 좌표의 판정은, y와 w로 체크하고 있습니다.
Skeleton-Fog.shader
------------------------------------------------
fixed4 frag(v2f i) : COLOR
{
    float inArea = (step(_ClipArea.x, i.worldPos.x) *
                    step(i.worldPos.x, _ClipArea.z) *
                    step(_ClipArea.y, i.worldPos.y) *
                    step(i.worldPos.y, _ClipArea.w));
    // クリップ領域に入っていなければ、inAreaが 0.0 になる為、色が出ない。
    return inArea * i.color * tex2D(_MainTex, i.texcoord);
}

이상이 됩니다.

좋은 웹페이지 즐겨찾기