Files
2025-01-07 18:54:46 +02:00

96 lines
3.2 KiB
HLSL

// From: https://github.com/gkjohnson/unity-dithered-transparency-shader
// MIT License
//Copyright (c) 2017 Garrett Johnson
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
#ifndef __DITHER_FUNCTIONS__
#define __DITHER_FUNCTIONS__
#include "UnityCG.cginc"
// Returns > 0 if not clipped, < 0 if clipped based
// on the dither
// For use with the "clip" function
// pos is the fragment position in screen space from [0,1]
float isDithered(float2 pos, float alpha) {
pos *= _ScreenParams.xy;
// Define a dither threshold matrix which can
// be used to define how a 4x4 set of pixels
// will be dithered
float DITHER_THRESHOLDS[16] =
{
1.0 / 17.0, 9.0 / 17.0, 3.0 / 17.0, 11.0 / 17.0,
13.0 / 17.0, 5.0 / 17.0, 15.0 / 17.0, 7.0 / 17.0,
4.0 / 17.0, 12.0 / 17.0, 2.0 / 17.0, 10.0 / 17.0,
16.0 / 17.0, 8.0 / 17.0, 14.0 / 17.0, 6.0 / 17.0
};
uint index = (uint(pos.x) % 4) * 4 + uint(pos.y) % 4;
return alpha - DITHER_THRESHOLDS[index];
}
// Returns whether the pixel should be discarded based
// on the dither texture
// pos is the fragment position in screen space from [0,1]
float isDithered(float2 pos, float alpha, sampler2D tex, float scale) {
pos *= _ScreenParams.xy;
// offset so we're centered
pos.x -= _ScreenParams.x / 2;
pos.y -= _ScreenParams.y / 2;
// scale the texture
pos.x /= scale;
pos.y /= scale;
// ensure that we clip if the alpha is zero by
// subtracting a small value when alpha == 0, because
// the clip function only clips when < 0
return alpha - tex2D(tex, pos.xy).r - 0.0001 * (1 - ceil(alpha));
}
// Helpers that call the above functions and clip if necessary
void ditherClip(float2 pos, float alpha) {
clip(isDithered(pos, alpha));
}
sampler2D _BlueNoiseCrossfade;
float4 _BlueNoiseCrossfade_TexelSize;
float rand(float2 co){
return frac(sin(dot(co.xy ,float2(12.9898,78.233))) * 43758.5453);
}
void ditherClip(float2 pos, float alpha, float clipV) {
pos *= _ScreenParams.xy;
//clip(isDithered(pos, alpha));
float2 vpos = float2((pos.x + pos.y), alpha);
clip(tex2D(_BlueNoiseCrossfade, vpos).r - clipV);
}
void ditherClip(float2 pos, float alpha, sampler2D tex, float scale) {
clip(isDithered(pos, alpha, tex, scale));
}
#endif