96 lines
3.2 KiB
HLSL
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
|