Quantcast
Channel: C#タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9700

[Unity]PostEffectにUIのスプライトを利用する

$
0
0

PostEffectを掛ける際にUIのスプライト(テクスチャでもいい)を利用したかったメモ。
あまりにもニッチな内容だけど、なかなか苦労したのでメモ残しておきます。

何が問題なのか

ちょっとググれば出るけど、PostEffectを掛けるシェーダーを書く際はまずカメラに処理用のスクリプトを書く。
んで、処理中にRenderTextureを用意して、画面に映ったものをシェーダーで処理してRenderTextureに映す。
シェーダーで描画を実行するにはOnRenderImageで値を渡してGraphics.Blitで描画するんだけど、そのとき_MainTexとして画面のレンダリングイメージが送られる。

_MainTexのUVは画面全体を0-1として送られるので、UIの領域を参照するには画面全体からどうにかして算出しなければならない。

コード

とりあえず上手く行った(っぽい)コード。
説明の必要部分だけ抜粋します。
UIのポジション変換はこちらを参考にさせて頂きました。
http://karanokan.info/2019/02/03/post-2213/

UVは左下から0-1なので、そこに上手く合わせられるようにする。

スクリプト側

publicGameObjectimageobj=null;publicTextureAddTexture=null;publicMaterialmat=null;privateRectTransformtrfTarget=null;privateRectTransformrectCanvas=null;privateVector2ressize=newVector2(0f,0f);privateVector2piv=newVector2(0f,0f);privateVector4rct;voidOnValidate(){if(imageobj!=null){AddTexture=imageobj.GetComponent<Image>().sprite.texture;trfTarget=imageobj.GetComponent<RectTransform>();vartop=imageobj.GetComponent<RectTransform>().root;rectCanvas=top.GetComponent<RectTransform>();ressize=newVector2(rectCanvas.rect.width,rectCanvas.rect.height);piv=rectCanvas.pivot;}}privatevoidOnRenderImage(RenderTexturesource,RenderTexturedest){mat.SetTexture("_AddTex",AddTexture);mat.SetVector("_Rect",rct);Graphics.Blit(source,dest,mat);}privatevoidUpdate(){//World座標をUI座標へ変換Vector2spos=RectTransformUtility.WorldToScreenPoint(Camera.main,trfTarget.position);Vector2pos;RectTransformUtility.ScreenPointToLocalPointInRectangle(rectCanvas,spos,Camera.main,outpos);//左下を計算上のpivotにするvarimgsize=newVector2(trfTarget.rect.width*trfTarget.localScale.x,trfTarget.rect.height*trfTarget.localScale.y);varimgpiv=trfTarget.pivot;varimgpos=newVector2(pos.x-(imgsize.x*imgpiv.x),pos.y-(imgsize.y*imgpiv.y));//CanvasのRectTransformから解像度とピボットを取り、左下0にするvarresetpos=newVector2(imgpos.x+(ressize.x*piv.x),imgpos.y+(ressize.y*piv.y));//リニア化 (minx,miny,解像度xに対する横の割合,解像度yに対する高さの割合)rct=newVector4(resetpos.x/ressize.x,resetpos.y/ressize.y,imgsize.x/ressize.x,imgsize.y/ressize.y);}

シェーダー側

範囲が分かりやすいようにスプライト部分を黒で塗りつぶしてます。
取得したUIのRect情報でいかにしてUVをずらすか。

Shader"UIPostEffect"{Properties{_MainTex("Texture",2D)="white"{}_AddTex("AddTexture",2D)="white"{}}SubShader{CullOffZWriteOffZTestAlwaysPass{CGPROGRAM#pragma vertex vert_img
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D_MainTex;sampler2D_AddTex;float4_Rect;fixed4frag(v2f_imgi):SV_Target{fixed4col=tex2D(_MainTex,i.uv);float2uv=float2((i.uv.x-_Rect.x)/_Rect.z,(i.uv.y-_Rect.y)/_Rect.w);fixed4addcol=tex2D(_AddTex,uv);returnlerp(col,fixed4(0,0,0,1),addcol.a);}ENDCG}}FallbackOff}

正直上手く説明できない

数学苦手なんでツッコミあったらよろしくお願いします。


Viewing all articles
Browse latest Browse all 9700

Trending Articles