Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save smkplus/8df53c7262a91fe4a35a9ffb433b7cf4 to your computer and use it in GitHub Desktop.
Save smkplus/8df53c7262a91fe4a35a9ffb433b7cf4 to your computer and use it in GitHub Desktop.
To keep snippets of code for Shaders. Just some stuff that I often use but also often forget because brain=poo
//https://docs.unity3d.com/Manual/SL-UnityShaderVariables.html
//https://github.com/TwoTailsGames/Unity-Built-in-Shaders/blob/master/CGIncludes/UnityCG.cginc - Most interesting stuff ;)
//https://github.com/TwoTailsGames/Unity-Built-in-Shaders/tree/master/CGIncludes
//https://docs.unity3d.com/Manual/SL-Shader.html
//http://developer.download.nvidia.com/CgTutorial/cg_tutorial_appendix_e.html
//https://unity3d.com/how-to/shader-profiling-and-optimization-tips
//https://docs.unity3d.com/Manual/SL-UnityShaderVariables.html
//http://www.deepskycolors.com/archive/2010/04/21/formulas-for-Photoshop-blending-modes.html
//http://www.iquilezles.org/blog/
//Properties
[PerRendererData][NoScaleOffset]_MainTex("Albedo", 2D) = "white" {}
// Image UI elements throw error in Build if Material(It's Shader) doesn't have _MainTex, so keep it here even if not used.
// [PerRendererData] - For UI, to hide it from material inspector;
// [NoScaleOffset] - To Hide scale and offset editing window - usefult if the are not utilized in shader
// Alternative Default Values: "white", "black", "gray", "bump", "red"
_Color("Color", Color) = (1,1,1,1)
_SomeSlider("Reflectiveness or something", Range(0,1)) = 0
[HideInInspector]_ProjTexPos("Screen Space Position", Vector) = (0,0,0,0)
// [HideInInspector] - no need to show this in inspector
_Test("Any value", float) = 1
// MULTICOMPILE & SHADER FEATURE
[KeywordEnum(None, Regular, Combined)] _BUMP ("Bump Map", Float) = 0
#pragma shader_feature ___ _BUMP_NONE _BUMP_REGULAR _BUMP_COMBINED
//Toggle
[Toggle(_BLABLA)] thisDoesntMatter ("Some Bla Bla BLa", Float) = 0
#pragma multi_compile ____ _BLABLA // Will Build all variations. (For changing via script) (___ = Also compile a version without any defines )
#pragma shader_feature _FEATUREA _FEATUREB // Will Build only used variations. (To configure shader in Editor only)
//Management
// From script you can set this keywords
renderer.material.EnableKeyword("_BLABLABLA");
// or
Shader.EnableKeyword("_BLABLABLA")
// To Apply Offset
//#define TRANSFORM_TEX(uv,_NameTex) (uv.xy * _NameTex_ST.xy + _NameTex_ST.zw)
uv = uv*_MainTex_ST.xy + _MainTex_ST.zw; // _MainTex_ST needs to be defined in the variables section (not the Parameters section)
// Screen Position
float4 screenPos : TEXCOORD1; // v2f
o.screenPos = ComputeScreenPos(o.pos); // vert
float2 screenUV = i.screenPos.xy / i.screenPos.w; // frag (Returns in 01 range (if on screen))
// To do POINT Sampling:
float2 pointUV = (floor(uv * _MainTex_TexelSize.zw) + 0.5) * _MainTex_TexelSize.xy;
// Pixel Perfect Sampling (https://www.quizcanners.com/single-post/2018/10/03/Pixel-Perfect-Shader)
// To Feed _ProjTexPos to UI shader I use (in C# script):
var pos = RectTransformUtility.WorldToScreenPoint(mainCamera, rectTransform.position); // can pass null if there is only one camera
pos.Scale(new Vector2(1f / Screen.width, 1f / Screen.height));
Vector2 scale = rect.rect.size;
scale = new Vector2(Mathf.Max(0, (scale.x - scale.y) / scale.x), Mathf.Max(0, (scale.y - scale.x) / scale.y)); // Scale is for rounded courners
material.SetVector("_ProjTexPos", pos.ToVector4(scale));
// In Fragment
float2 inPix = (screenUV - _ProjTexPos.xy)*_ScreenParams.xy; // _ProjTexPos - UV position on screen of lower left edge (optional)
// _ScreenParams.xy - a Unity provided global variable (But you still need to declare it)
float2 texUV = inPix * _ProjTex_TexelSize.xy; // * _TexName_TexelSize - float4 Provided By Unity
//Optionally:
// If more then one texture needs to be sampled this way replace the previous line with
float2 tex1UV = inPix * tex1_TexelSize.xy
float2 tex2UV = inPix * tex2_TexelSize.xy
//if screen UV is the center of the object
texUV += 0.5;
// if There is a change that texture may have resolution that is not divisible by two:
texUV += _ProjTex_TexelSize.xy*0.5*(fmod(_ProjTex_TexelSize.zw, 2));
// For sampling you can use tex2Dlod since mip level will always be 0:
float4 col = tex2Dlod(_ProjTex, float4(texUV,0,0)); // Without lod Unity shader will have additional calculations for mip level (I think)
// Scaling Non Power of 2 texture to fit inside a square quad. (Keeping the correct relation of width and height)
// *To scale texture to fill the quad replace max with min
// v2f:
float2 mainTexScale : TEXCOORD8;
// vert:
float relation = _MainTex_TexelSize.w / _MainTex_TexelSize.z;
o.mainTexScale.x = max(1, relation);
o.mainTexScale.y = max(1, 1 / relation);
// frag:
float2 scaledUV = ((i.texcoord.xy-0.5) * i.mainTexScale.xy) + 0.5;
//* Note: The way Unity UI works is, if it looks like edges are being cut from your UI, set "Mesh Type" to "Full Rect"
// in import settings of your sprite.
// Smooth Pixelation Sampling
const float sharpness = 40;
float2 perfTex = (floor(IN.uv_MainTex.xy*_MainTex_TexelSize.z) + 0.5) * _MainTex_TexelSize.x;
float2 off = (IN.uv_MainTex.xy - perfTex);
float2 diff = (abs(off) * _MainTex_TexelSize.z);
float2 edge = saturate((diff * 2 - 1)*sharpness + 1);
perfTex += off * edge;
float2 diff = (abs(off) * _MainTex_TexelSize.z);
// To Also get the border:
edge = saturate((diff * 2 - 1)*sharpness*0.1 + 1); // In some usages the are between pixels contains other pixels, then border needs to be less sharp to fully cover that area.
float border = max(edge.x, edge.y);
// To Get MipLevel
_MainTex_TexelSize.zw *= modifier; // Optional
float2 px = _MainTex_TexelSize.z * ddx(uv);
float2 py = _MainTex_TexelSize.w * ddy(uv);
return (max(0, 0.5 * log2(max(dot(px, px), dot(py, py)))));
// Parallax
//vert:
float3x3 objectToTangent = float3x3(
v.tangent.xyz,
cross(v.normal, v.tangent.xyz) * v.tangent.w,
v.normal
);
tangentViewDir = mul(objectToTangent, ObjSpaceViewDir(v.vertex));
//frag
tangentViewDir = normalize(tangentViewDir);
i.tangentViewDir.xy /= (i.tangentViewDir.z + 0.42);
i.uv.xy += tangentViewDir.xy;
// Rounded Courners (i.texcootd.zw can be reaplced with _ProjTexPos.zw from above. If this shader is used with Pix Perfect Projection)
// struct v2f
float4 texcoord : TEXCOORD2;
// Vert:
float2 scale = _MainTex_TexelSize.zw;
o.texcoord.zw = float2 (max(0, (scale.x - scale.y) / scale.x), max(0, (scale.y - scale.x) / scale.y));
// Frag
// Stretch
float _Blur = (1 - i.color.a); // Using UI component color to fade out
float2 uv = abs(i.texcoord.xy - 0.5) * 2;
uv = max(0, uv - i.texcoord.zw) / (1 - i.texcoord.zw);
// Courners
uv -= _Courners;
float deCourners = 1 - _Courners;
uv = max(0, uv) / deCourners;
uv *= uv;
col.a = saturate((1 - uv.x - uv.y) * 20 * (1 - _Blur)*deCourners);
// Stretch Part Without texture (using object's scale transform):
// script:
Vector2 scale = transform.localScale;
if (stretch.x > 0)
stretch.x = scale.x > scale.y ? ((scale.x - scale.y) / scale.x) : 0;
else stretch.x = 0;
if (scale.y > 0)
stretch.y = scale.y > scale.x ? ((scale.y - scale.x) / scale.y) : 0;
else stretch.y = 0;
// Feed to material
renderer.material.SetVector("_Stretch", stretch);
// frag:
// Stretch
float2 uv = abs(i.texcoord.xy - 0.5) * 2;
uv -= _Stretch;
float2 upStretch = 1 - _Stretch;
uv = max(0, uv) / upStretch;
// Courners
// .... Same as Courners part above
// Fit Sprite Sampling to Fill Screen Without stretching the texture:
// In script:
float screenAspect = ((float)Screen.width) / Screen.height;
float texAspect = ((float)bgTex.width) / bgTex.height;
Vector2 aspectCorrection = Vector2.one;
if (screenAspect > texAspect)
aspectCorrection.y = (texAspect / screenAspect);
else
aspectCorrection.x = (screenAspect / texAspect);
// In Shader
float2 uv = (screenUV.xy - 0.5)*aspectCorrection.xy + 0.5;
// Tile/ Offset
float4 _MainTex_TexelSize; // Texture Size (zw = width,heigth ; xy = 1/width, 1/height)
uniform float4 _MainTex_ST; // Tile Offset
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); // Tile Offset needs to be declared (the line above)
// View Direction
float3 viewDir : TEXCOORD0;
o.viewDir.xyz = (WorldSpaceViewDir(v.vertex));
i.viewDir.xyz = normalize(i.viewDir.xyz);
// World Normal
o.normal.xyz = normalize(UnityObjectToWorldNormal(v.normal)); // can be done if vert
// World Position
float3 wpos : TEXCOORD3;
o.wpos = mul(unity_ObjectToWorld, v.vertex).xyz;
// ------- To Modify In World Space:
v.vertex += mul(unity_WorldToObject, offx,offy,offz, 0);
// Reflect:
float dotprod = max(0, dot(worldNormal, i.viewDir.xyz));
float3 reflected = normalize(i.viewDir.xyz - 2 * (dotprod)*worldNormal);
// Tangent Transformation:
float3 tspace0 : TEXCOORD3;
float3 tspace1 : TEXCOORD4;
float3 tspace2 : TEXCOORD5;
// ...... vert
float3 wTangent = UnityObjectToWorldDir(v.tangent.xyz);
float tangentSign = v.tangent.w * unity_WorldTransformParams.w;
float3 wBitangent = cross(wNormal, wTangent) * tangentSign;
o.tspace0 = half3(wTangent.x, wBitangent.x, wNormal.x);
o.tspace1 = half3(wTangent.y, wBitangent.y, wNormal.y);
o.tspace2 = half3(wTangent.z, wBitangent.z, wNormal.z);
// ..... frag
worldNormal.x = dot(i.tspace0, tnormal);
worldNormal.y = dot(i.tspace1, tnormal);
worldNormal.z = dot(i.tspace2, tnormal);
// Shadow
SHADOW_COORDS(2)
TRANSFER_SHADOW(o);
float shadow = SHADOW_ATTENUATION(i);
// Color Bleed (https://www.quizcanners.com/single-post/2018/04/02/Color-Bleeding-in-Shader)
float3 mix = col.gbr + col.brg;
col.rgb += mix * mix*amount;
// Rotation
float2 rotUV = i.texcoord.xy - 0.5;
float si = sin(angle);
float co = cos(angle);
float tx = rotUV.x;
float ty = rotUV.y;
rotUV.x = (co * tx) - (si * ty);
rotUV.y = (si * tx) + (co * ty);
rotUV += 0.5;
// Get Angle in 01 space
const float PI2 = 3.14159265359 * 2;
float angle = atan2(-uv.x, -uv.y)+0.001;
angle = saturate(max(angle,
PI2 + min(0, angle)
- max(0, angle*999999)
)/ PI2);
// Change Between two textures/Colors/States etc using Unity's time
float lerp = (_CosTime.z + 1) * 0.5; // Time.x,y,z,w - from slowest to fastest
// Lerp between two transparent textures
float rgbLerp = col2.a*lerp;
rgbLerp = saturate(rgbLerp * 2 / (col.a + rgbLerp + 0.0001)); // Add some value to avoid division by 0
col.a = col2.a * lerp + col.a * (1 - lerp);
col.rgb = col2.rgb * rgbLerp + col.rgb * (1 - rgbLerp);
// Color Light Bleed Effect
float3 mix = col.gbr + col.brg;
col.rgb += mix * mix*0.02; // Arbitrary value
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment