Skip to content

Instantly share code, notes, and snippets.

@jpsarda
Last active July 20, 2020 08:40
Show Gist options
  • Save jpsarda/ddc4343ad220787c4a7e to your computer and use it in GitHub Desktop.
Save jpsarda/ddc4343ad220787c4a7e to your computer and use it in GitHub Desktop.
Holes with futile, see usage.cs
public class FSpriteHolesShader : FShader
{
private Texture _hole0Texture=null;
private Vector4 _hole0LocalToUVParams;
private Vector4 _hole0MatrixABCD;
private Vector4 _hole0MatrixTxTy;
private Vector4 _hole0UVRect;
private FSprite _hole0Sprite=null;
static private Vector4 _screenParams;
public Texture hole0Texture
{
get {return _hole0Texture;}
}
public void SetHole0(FSprite spriteHole) {
_hole0Sprite=spriteHole;
_hole0Texture=spriteHole.element.atlas.texture;
spriteHole.UpdateMatrix();
float factorX=Futile.resourceScale/spriteHole.element.atlas.textureSize.x;
float factorY=Futile.resourceScale/spriteHole.element.atlas.textureSize.y;
//do this if you have modified version of FElement that keeps the frame info
//_hole0LocalToUVParams=new Vector4( factorX , (spriteHole.element.frame.x+(-spriteHole.textureRect.x-spriteHole.element.sourceRect.x)*Futile.resourceScale)/spriteHole.element.atlas.textureSize.x , factorY , 1+(-(spriteHole.element.frame.y+spriteHole.element.frame.height)+(-spriteHole.textureRect.y-spriteHole.element.sourceRect.y)*Futile.resourceScale)/spriteHole.element.atlas.textureSize.y );
float elementFrameX=spriteHole.element.uvRect.x*spriteHole.element.atlas.textureSize.x;
float elementFrameY=-spriteHole.element.uvRect.y*spriteHole.element.atlas.textureSize.y+spriteHole.element.atlas.textureSize.y-spriteHole.element.uvRect.height*spriteHole.element.atlas.textureSize.y;
_hole0LocalToUVParams=new Vector4( factorX , (elementFrameX+(-spriteHole.textureRect.x-spriteHole.element.sourceRect.x)*Futile.resourceScale)/spriteHole.element.atlas.textureSize.x , factorY , 1+(-(elementFrameY+spriteHole.element.frame.height)+(-spriteHole.textureRect.y-spriteHole.element.sourceRect.y)*Futile.resourceScale)/spriteHole.element.atlas.textureSize.y );
_hole0UVRect.x=spriteHole.element.uvRect.xMin;
_hole0UVRect.y=spriteHole.element.uvRect.yMin;
_hole0UVRect.z=spriteHole.element.uvRect.xMax;
_hole0UVRect.w=spriteHole.element.uvRect.yMax;
Hole0NeedUpdate();
needsApply = true;
}
private bool updateEveryFrameHole0=false;
public void UpdateEveryFrameHole0(bool b) {
if (b!=updateEveryFrameHole0) {
updateEveryFrameHole0=b;
if (updateEveryFrameHole0) {
Futile.instance.SignalUpdate+=Hole0NeedUpdate;
} else {
Futile.instance.SignalUpdate-=Hole0NeedUpdate;
}
}
}
public void Hole0NeedUpdate() {
FSprite spriteHole=_hole0Sprite;
//mattrix from vertices
_hole0MatrixABCD.x=_screenParams.z*spriteHole.inverseConcatenatedMatrix.a*_hole0LocalToUVParams.x;
_hole0MatrixABCD.z=_screenParams.z*spriteHole.inverseConcatenatedMatrix.c*_hole0LocalToUVParams.x;
_hole0MatrixTxTy.x=(_screenParams.x*_screenParams.z*spriteHole.inverseConcatenatedMatrix.a + _screenParams.y*_screenParams.z*spriteHole.inverseConcatenatedMatrix.c + spriteHole.inverseConcatenatedMatrix.tx)*_hole0LocalToUVParams.x + _hole0LocalToUVParams.y;
_hole0MatrixABCD.y=_screenParams.z*spriteHole.inverseConcatenatedMatrix.b*_hole0LocalToUVParams.z;
_hole0MatrixABCD.w=_screenParams.z*spriteHole.inverseConcatenatedMatrix.d*_hole0LocalToUVParams.z;
_hole0MatrixTxTy.y=(_screenParams.x*_screenParams.z*spriteHole.inverseConcatenatedMatrix.b + _screenParams.y*_screenParams.z*spriteHole.inverseConcatenatedMatrix.d + spriteHole.inverseConcatenatedMatrix.ty)*_hole0LocalToUVParams.z + _hole0LocalToUVParams.w;
needsApply = true;
}
public FSpriteHolesShader() : base("SpriteHolesShader", Shader.Find("Futile/SpriteHoles"))
{
//no fx screenParams
_screenParams.x=_screenParams.y=0;
_screenParams.z=1;
_screenParams.w=0;
needsApply=true;
}
override public void Apply(Material mat)
{
if (_hole0Texture!=null) {
mat.SetTexture("_Hole0Tex",_hole0Texture);
mat.SetVector("_Hole0MatrixABCD",_hole0MatrixABCD);
mat.SetVector("_Hole0MatrixTxTy",_hole0MatrixTxTy);
mat.SetVector("_Hole0UVRect",_hole0UVRect);
}
}
}
Shader "Futile/SpriteHoles"
{
Properties
{
_MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
_Color ("Main Color", Color) = (1,1,1,1)
_Hole0Tex ("Hole (RGB) Trans (A)", 2D) = "white" {}
_Hole0MatrixABCD ("Matrix part 1 : a b c d", Color) = (1,0,0,1)
_Hole0MatrixTxTy ("Matrix part 2 : tx ty unused unsued", Color) = (0,0,0,0)
_Hole0UVRect ("UVRect : uMin vMin uMax vMax", Color) = (0,0,0,0)
}
Category
{
Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Opaque"}
ZWrite Off
//Alphatest Greater 0
Blend SrcAlpha OneMinusSrcAlpha
Fog { Color(0,0,0,0) }
Lighting Off
Cull Off //we can turn backface culling off because we know nothing will be facing backwards
BindChannels
{
Bind "Vertex", vertex
Bind "texcoord", texcoord
Bind "Color", color
}
SubShader
{
Pass
{
CGPROGRAM
// Upgrade NOTE: excluded shader from DX11 and Xbox360; has structs without semantics (struct v2f members scrPos)
#pragma exclude_renderers d3d11 xbox360
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#pragma profileoption NumTemps=64
float4 _Color;
sampler2D _MainTex;
sampler2D _Hole0Tex;
float4 _Hole0MatrixABCD;
float4 _Hole0MatrixTxTy;
float4 _Hole0UVRect;
struct v2f {
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float2 hole0uv : TEXCOORD1;
};
float4 _MainTex_ST;
float4 _Hole0Tex_ST;
v2f vert (appdata_base v)
{
v2f o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
o.uv = TRANSFORM_TEX (v.texcoord, _MainTex);
//TANSFORM_TEXT is same as this
//o.uv = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
//Maybe could use a matrixfor performances?
o.hole0uv.x=v.vertex.x*_Hole0MatrixABCD.x + v.vertex.y*_Hole0MatrixABCD.z + _Hole0MatrixTxTy.x;
o.hole0uv.y=v.vertex.x*_Hole0MatrixABCD.y + v.vertex.y*_Hole0MatrixABCD.w + _Hole0MatrixTxTy.y;
return o;
}
half4 frag (v2f i) : COLOR
{
half4 texcol = tex2D (_MainTex, i.uv) * _Color;
//hole
if ((i.hole0uv.x>_Hole0UVRect.x)&&(i.hole0uv.x<_Hole0UVRect.z)&&(i.hole0uv.y>_Hole0UVRect.y)&&(i.hole0uv.y<_Hole0UVRect.w)) {
texcol.a *= (1-tex2D(_Hole0Tex, i.hole0uv).a) ;
}
//mask (comment hole section and uncomment mask section to turn this shader into masking)
//if ((i.hole0uv.x>_Hole0UVRect.x)&&(i.hole0uv.x<_Hole0UVRect.z)&&(i.hole0uv.y>_Hole0UVRect.y)&&(i.hole0uv.y<_Hole0UVRect.w)) {
// texcol.a *= tex2D(_Hole0Tex, i.hole0uv).a ;
//} else {
// texcol.a=0;
//}
return texcol;
}
ENDCG
}
}
}
}
//Background image (just for making masking/hole demo more obvious)
FSprite bg =new FSprite("Images/mur");
AddChild(bg);
//Dug sprite
FSprite dugSprite =new FSprite("Images/colorgrid");
AddChild(dugSprite);
//Animate it a bit
GoTweenConfig config=new GoTweenConfig().oscillateFloatProp("rotation",90,1.5f,false,1);
Go.to(dugSprite,1000000,config);
//Hole sprite
FSprite hole=new FSprite("sun");
hole.scale=2;
hole.alpha=0f; //alpha 0 as we don't want this sprite to appear on the screen, its purpose is to dig a hole in dugSprite
AddChild(hole);
//Create shader
FSpriteHolesShader shader=new FSpriteHolesShader();
shader.SetHole0(hole);
shader.UpdateEveryFrameHole0(true);
//Animate hole a bit
config=new GoTweenConfig().oscillateFloatProp("y",120,5.5f,false,1);
Go.to(hole,1000000,config);
config=new GoTweenConfig().oscillateFloatProp("rotation",180,10.5f,false,1);
Go.to(hole,1000000,config);
//Set the dugSprite shader
dugSprite.shader=shader;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment