mirror of
https://github.com/Merlin1809/Eclipse-Shader.git
synced 2026-10-10 13:03:06 +08:00
Merge Xonk's latest commits
This commit is contained in:
@@ -546,110 +546,92 @@ void Emission(
|
||||
#include "/lib/indirect_lighting_effects.glsl"
|
||||
#include "/lib/PhotonGTAO.glsl"
|
||||
|
||||
void BilateralUpscale_REUSE_Z(sampler2D tex1, sampler2D tex2, sampler2D depth, vec2 coord, float referenceDepth, inout vec2 ambientEffects, inout vec3 filteredShadow, bool hand){
|
||||
ivec2 scaling = ivec2(1.0);
|
||||
ivec2 posDepth = ivec2(coord) * scaling;
|
||||
ivec2 posColor = ivec2(coord);
|
||||
ivec2 pos = ivec2(gl_FragCoord.xy*texelSize + 1);
|
||||
|
||||
ivec2 getRadius[4] = ivec2[](
|
||||
ivec2(-1,-1),
|
||||
ivec2( 1,-1),
|
||||
ivec2( 1, 1),
|
||||
ivec2(-1, 1)
|
||||
// ivec2( 0, 1),
|
||||
// ivec2( 0,-1),
|
||||
// ivec2(-1, 0),
|
||||
// ivec2( 1, 0)
|
||||
);
|
||||
|
||||
#ifdef DISTANT_HORIZONS
|
||||
float diffThreshold = 0.0005;
|
||||
#else
|
||||
float diffThreshold = 0.005;
|
||||
#endif
|
||||
|
||||
void doEdgeAwareBlur(
|
||||
sampler2D tex1, sampler2D tex2, sampler2D depth,
|
||||
float referenceDepth, bool hand,
|
||||
inout vec2 ambientEffects, inout vec3 filteredShadow
|
||||
){
|
||||
float threshold = clamp(referenceDepth*referenceDepth*0.5,0.0001,0.005);
|
||||
vec3 shadow_RESULT = vec3(0.0);
|
||||
vec2 ssao_RESULT = vec2(0.0);
|
||||
float SUM = 1.0;
|
||||
float edgeSum = 0.0;
|
||||
|
||||
#ifdef LIGHTING_EFFECTS_BLUR_FILTER
|
||||
for (int i = 0; i < 4; i++) {
|
||||
vec2 coord = gl_FragCoord.xy - 1.5;
|
||||
ivec2 UV = ivec2(coord);
|
||||
ivec2 UV_NOISE = ivec2(gl_FragCoord.xy*texelSize + 1);
|
||||
|
||||
ivec2 radius = getRadius[i];
|
||||
|
||||
#ifdef DISTANT_HORIZONS
|
||||
float offsetDepth = sqrt(texelFetch2D(depth, posDepth + radius * scaling + pos * scaling,0).a/65000.0);
|
||||
#else
|
||||
float offsetDepth = ld(texelFetch2D(depth, posDepth + radius * scaling + pos * scaling, 0).r);
|
||||
#endif
|
||||
|
||||
float EDGES = abs(offsetDepth - referenceDepth) < diffThreshold ? 1.0 : 1e-5;
|
||||
|
||||
#ifdef Variable_Penumbra_Shadows
|
||||
shadow_RESULT += texelFetch2D(tex1, posColor + radius + pos, 0).rgb * EDGES;
|
||||
#endif
|
||||
|
||||
// #if indirect_effect == 1
|
||||
ssao_RESULT += texelFetch2D(tex2, posColor + radius + pos, 0).rg * EDGES;
|
||||
// #endif
|
||||
|
||||
SUM += EDGES;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef Variable_Penumbra_Shadows
|
||||
shadow_RESULT += texture2D(tex1, gl_FragCoord.xy*texelSize).rgb;
|
||||
filteredShadow = shadow_RESULT/SUM;
|
||||
#endif
|
||||
|
||||
// #if indirect_effect == 1
|
||||
ssao_RESULT += texture2D(tex2, gl_FragCoord.xy*texelSize).rg;
|
||||
ambientEffects = ssao_RESULT/SUM;
|
||||
// #endif
|
||||
}
|
||||
|
||||
vec4 BilateralUpscale_VLFOG(sampler2D tex, sampler2D depth, vec2 coord, float referenceDepth){
|
||||
ivec2 scaling = ivec2(1.0/VL_RENDER_RESOLUTION);
|
||||
ivec2 posDepth = ivec2(coord*VL_RENDER_RESOLUTION) * scaling;
|
||||
ivec2 posColor = ivec2(coord*VL_RENDER_RESOLUTION);
|
||||
ivec2 pos = ivec2(gl_FragCoord.xy*texelSize + 1);
|
||||
|
||||
ivec2 getRadius[5] = ivec2[](
|
||||
ivec2(-1,-1),
|
||||
ivec2( 1, 1),
|
||||
ivec2(-1, 1),
|
||||
ivec2( 1,-1),
|
||||
ivec2( 0, 0)
|
||||
);
|
||||
|
||||
#ifdef DISTANT_HORIZONS
|
||||
float diffThreshold = 0.01;
|
||||
#else
|
||||
float diffThreshold = zMults.x;
|
||||
#endif
|
||||
|
||||
vec4 RESULT = vec4(0.0);
|
||||
float SUM = 0.0;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
|
||||
ivec2 radius = getRadius[i];
|
||||
ivec2 OFFSET[4] = ivec2[](
|
||||
ivec2(-1,-1),
|
||||
ivec2( 1, 1),
|
||||
ivec2(-1, 1),
|
||||
ivec2( 1,-1)
|
||||
);
|
||||
|
||||
for(int i = 0; i < 4; i++) {
|
||||
#ifdef DISTANT_HORIZONS
|
||||
float offsetDepth = sqrt(texelFetch2D(depth, posDepth + radius * scaling + pos * scaling,0).a/65000.0);
|
||||
float offsetDepth = sqrt(texelFetch2D(depth, UV + OFFSET[i] + UV_NOISE,0).a/65000.0);
|
||||
#else
|
||||
float offsetDepth = ld(texelFetch2D(depth, posDepth + radius * scaling + pos * scaling, 0).r);
|
||||
float offsetDepth = ld(convertHandDepth_2(texelFetch2D(depth, UV + OFFSET[i] + UV_NOISE, 0).r,hand));
|
||||
#endif
|
||||
|
||||
float EDGES = abs(offsetDepth - referenceDepth) < diffThreshold ? 1.0 : 1e-5;
|
||||
|
||||
RESULT += texelFetch2D(tex, posColor + radius + pos, 0) * EDGES;
|
||||
|
||||
SUM += EDGES;
|
||||
float edgeDiff = abs(offsetDepth - referenceDepth) < threshold ? 1.0 : 1e-7;
|
||||
|
||||
#ifdef Variable_Penumbra_Shadows
|
||||
shadow_RESULT += texelFetch2D(tex1, UV + OFFSET[i] + UV_NOISE, 0).rgb*edgeDiff;
|
||||
#endif
|
||||
// #if indirect_effect == 1
|
||||
ssao_RESULT += texelFetch2D(tex2, UV + OFFSET[i] + UV_NOISE, 0).rg*edgeDiff;
|
||||
// #endif
|
||||
|
||||
edgeSum += edgeDiff;
|
||||
}
|
||||
// sample without an offset with texture filtering to get a slightly blurred sample. make sure to average without skewing the rest of the average.
|
||||
filteredShadow = shadow_RESULT/edgeSum * 0.8 + 0.2 * texture2D(tex1, texelSize*gl_FragCoord.xy).rgb;
|
||||
ambientEffects = ssao_RESULT/edgeSum * 0.8 + 0.2 * texture2D(tex2, texelSize*gl_FragCoord.xy).rg;
|
||||
// ambientEffects.x = edgeSum / 4.0;
|
||||
|
||||
}
|
||||
|
||||
vec4 BilateralUpscale_VLFOG(sampler2D tex, sampler2D depth, float referenceDepth){
|
||||
|
||||
vec4 colorSum = vec4(0.0);
|
||||
float edgeSum = 0.0;
|
||||
|
||||
#ifdef DISTANT_HORIZONS
|
||||
float threshold = referenceDepth * mix(0.5, 0.05, min(max(0.1 - referenceDepth,0)/0.1,1));
|
||||
#else
|
||||
float threshold = referenceDepth * 0.05;
|
||||
#endif
|
||||
|
||||
vec2 coord = gl_FragCoord.xy - 1.5;
|
||||
vec2 UV = coord;
|
||||
const ivec2 SCALE = ivec2(1.0/VL_RENDER_RESOLUTION);
|
||||
ivec2 UV_DEPTH = ivec2(UV*VL_RENDER_RESOLUTION)*SCALE;
|
||||
ivec2 UV_COLOR = ivec2(UV*VL_RENDER_RESOLUTION);
|
||||
ivec2 UV_NOISE = ivec2(gl_FragCoord.xy*texelSize + 1);
|
||||
|
||||
ivec2 OFFSET[5] = ivec2[](
|
||||
ivec2(-1,-1),
|
||||
ivec2( 1, 1),
|
||||
ivec2(-1, 1),
|
||||
ivec2( 1,-1),
|
||||
ivec2( 0, 0)
|
||||
);
|
||||
|
||||
for(int i = 0; i < 4; i++) {
|
||||
#ifdef DISTANT_HORIZONS
|
||||
float offsetDepth = sqrt(texelFetch2D(depth, UV_DEPTH + (OFFSET[i] + UV_NOISE) * SCALE,0).a/65000.0);
|
||||
#else
|
||||
float offsetDepth = ld(texelFetch2D(depth, UV_DEPTH + (OFFSET[i] + UV_NOISE) * SCALE, 0).r);
|
||||
#endif
|
||||
|
||||
float edgeDiff = abs(offsetDepth - referenceDepth) < threshold ? 1.0 : 1e-7;
|
||||
vec4 offsetColor = texelFetch2D(tex, UV_COLOR + OFFSET[i] + UV_NOISE, 0).rgba;
|
||||
colorSum += offsetColor*edgeDiff;
|
||||
edgeSum += edgeDiff;
|
||||
}
|
||||
|
||||
return RESULT / SUM;
|
||||
return colorSum/edgeSum;
|
||||
}
|
||||
|
||||
#ifdef OVERWORLD_SHADER
|
||||
@@ -1089,9 +1071,9 @@ void main() {
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined DISTANT_HORIZONS && defined DH_AMBIENT_OCCLUSION
|
||||
BilateralUpscale_REUSE_Z(colortex3, colortex14, colortex12, gl_FragCoord.xy-1.5, DH_mixedLinearZ, SSAO_SSS, filteredShadow, hand);
|
||||
doEdgeAwareBlur(colortex3, colortex14, colortex12, DH_mixedLinearZ, hand, SSAO_SSS, filteredShadow);
|
||||
#else
|
||||
BilateralUpscale_REUSE_Z(colortex3, colortex14, depthtex0, gl_FragCoord.xy-1.5, ld(z0), SSAO_SSS, filteredShadow, hand);
|
||||
doEdgeAwareBlur(colortex3, colortex14, depthtex0, ld(z0), hand, SSAO_SSS, filteredShadow);
|
||||
#endif
|
||||
|
||||
float ShadowBlockerDepth = filteredShadow.y;
|
||||
@@ -1504,7 +1486,12 @@ void main() {
|
||||
// water absorbtion will impact ALL light coming up from terrain underwater.
|
||||
gl_FragData[0].rgb *= Absorbtion;
|
||||
|
||||
vec4 vlBehingTranslucents = BilateralUpscale_VLFOG(colortex13, depthtex1, gl_FragCoord.xy - 1.5, ld(z));
|
||||
#ifdef DISTANT_HORIZONS
|
||||
float DH_mixedLinearZ = sqrt(texelFetch2D(colortex12,ivec2(gl_FragCoord.xy),0).a/65000.0);
|
||||
vec4 vlBehingTranslucents = BilateralUpscale_VLFOG(colortex13, colortex12, DH_mixedLinearZ);
|
||||
#else
|
||||
vec4 vlBehingTranslucents = BilateralUpscale_VLFOG(colortex13, depthtex1, ld(z));
|
||||
#endif
|
||||
|
||||
gl_FragData[0].rgb = gl_FragData[0].rgb * vlBehingTranslucents.a + vlBehingTranslucents.rgb;
|
||||
}
|
||||
|
||||
@@ -47,6 +47,10 @@ vec4 Weather_properties = Moon_Weather_properties;
|
||||
// #include "/lib/biome_specifics.glsl"
|
||||
#include "/lib/bokeh.glsl"
|
||||
|
||||
#if WHITE_BALANCE != 6500
|
||||
#include "/lib/util.glsl"
|
||||
#endif
|
||||
|
||||
float cdist(vec2 coord) {
|
||||
return max(abs(coord.s-0.5),abs(coord.t-0.5))*2.0;
|
||||
}
|
||||
@@ -273,6 +277,10 @@ void main() {
|
||||
|
||||
col = mix(lum * vec3(Purkinje_R, Purkinje_G, Purkinje_B) * Purkinje_Multiplier, col, rodCurve);
|
||||
|
||||
#if WHITE_BALANCE != 6500
|
||||
col *= blackbody(WHITE_BALANCE);
|
||||
#endif
|
||||
|
||||
#ifndef USE_ACES_COLORSPACE_APPROXIMATION
|
||||
col = LinearTosRGB(TONEMAP(col));
|
||||
#else
|
||||
@@ -316,6 +324,6 @@ void main() {
|
||||
#endif
|
||||
|
||||
// focus = gl_FragCoord.x * 0.1;
|
||||
if( hideGUI < 1) gl_FragData[0].rgb += laserColor * pow( clamp( 1.0-abs(focus-abs(depth)) ,0,1),25) ;
|
||||
if (hideGUI < 1) gl_FragData[0].rgb += laserColor * pow( clamp( 1.0-abs(focus-abs(depth)) ,0,1),25) ;
|
||||
#endif
|
||||
}
|
||||
@@ -239,12 +239,12 @@ vec2 clampUV(in vec2 uv, vec2 texcoord){
|
||||
return clamp(mix(uv, texcoord, vignette),0.0,0.9999999);
|
||||
}
|
||||
|
||||
vec3 doRefractionEffect( inout vec2 texcoord, vec2 normal, float linearDistance, bool isReflectiveEntity){
|
||||
vec3 doRefractionEffect( inout vec2 texcoord, vec2 normal, float linearDistance, bool isReflectiveEntity, bool underwater){
|
||||
|
||||
// make the tangent space normals match the directions of the texcoord UV, this greatly improves the refraction effect.
|
||||
vec2 UVNormal = vec2(normal.x,-normal.y);
|
||||
|
||||
float refractionMult = 0.5 / (1.0 + pow(linearDistance,0.8));
|
||||
float refractionMult = 0.5 / (1.0 + pow(linearDistance,0.8) * (underwater ? 0.1 : 1.0));
|
||||
float diffractionMult = 0.035;
|
||||
float smudgeMult = 1.0;
|
||||
if(isReflectiveEntity) refractionMult *= 0.5;
|
||||
@@ -360,7 +360,7 @@ vec3 toScreenSpace_DH_special(vec3 POS, bool depthCheck ) {
|
||||
return viewPos.xyz;
|
||||
}
|
||||
|
||||
vec4 bilateralUpsample(out float outerEdgeResults, float referenceDepth, sampler2D depth){
|
||||
vec4 bilateralUpsample(out float outerEdgeResults, float referenceDepth, sampler2D depth, bool hand){
|
||||
|
||||
vec4 colorSum = vec4(0.0);
|
||||
float edgeSum = 0.0;
|
||||
@@ -399,12 +399,12 @@ vec4 bilateralUpsample(out float outerEdgeResults, float referenceDepth, sampler
|
||||
|
||||
}
|
||||
|
||||
outerEdgeResults = outerEdgeResults > referenceDepth*0.05 + 0.1 ? 1.0 : 0.0;
|
||||
outerEdgeResults = outerEdgeResults > (hand ? 0.005 : referenceDepth*0.05 + 0.1) ? 1.0 : 0.0;
|
||||
|
||||
return colorSum / edgeSum;
|
||||
}
|
||||
|
||||
vec4 VLTemporalFiltering(vec3 viewPos, in float referenceDepth, sampler2D depth){
|
||||
vec4 VLTemporalFiltering(vec3 viewPos, in float referenceDepth, sampler2D depth, bool hand){
|
||||
vec2 offsetTexcoord = gl_FragCoord.xy*texelSize;
|
||||
vec2 VLtexCoord = offsetTexcoord * VL_RENDER_RESOLUTION;
|
||||
|
||||
@@ -421,7 +421,7 @@ vec4 VLTemporalFiltering(vec3 viewPos, in float referenceDepth, sampler2D depth)
|
||||
// to fill pixel gaps in geometry edges, do a bilateral upsample.
|
||||
// pass a mask to only show upsampled color around the edges of blocks. this is so it doesnt blur reprojected results.
|
||||
float outerEdgeResults = 0.0;
|
||||
vec4 upsampledCurrentFrame = bilateralUpsample(outerEdgeResults, referenceDepth, depth);
|
||||
vec4 upsampledCurrentFrame = bilateralUpsample(outerEdgeResults, referenceDepth, depth, hand);
|
||||
// vec4 upsampledCurrentFrame = BilateralUpscale(colortex0, depth, gl_FragCoord.xy - 1.5, referenceDepth);
|
||||
|
||||
// return vec4(outerEdgeResults,0,0,1);
|
||||
@@ -464,7 +464,10 @@ void main() {
|
||||
////// --------------- SETUP STUFF --------------- //////
|
||||
vec2 texcoord = gl_FragCoord.xy*texelSize;
|
||||
|
||||
float z = texelFetch2D(depthtex0, ivec2(gl_FragCoord.xy),0).x;//texture2D(depthtex0, texcoord).x;
|
||||
float depth = texelFetch2D(depthtex0, ivec2(gl_FragCoord.xy),0).x;
|
||||
bool hand = depth < 0.56;
|
||||
float z = depth;
|
||||
|
||||
float z2 = texture2D(depthtex1, texcoord).x;
|
||||
float frDepth = linearize(z);
|
||||
|
||||
@@ -534,9 +537,9 @@ void main() {
|
||||
////// --------------- get volumetrics
|
||||
#ifdef DISTANT_HORIZONS
|
||||
float DH_mixedLinearZ = sqrt(texelFetch2D(colortex12,ivec2(gl_FragCoord.xy),0).a/65000.0);
|
||||
vec4 temporallyFilteredVL = VLTemporalFiltering(viewPos, DH_mixedLinearZ, colortex12);
|
||||
vec4 temporallyFilteredVL = VLTemporalFiltering(viewPos, DH_mixedLinearZ, colortex12, hand);
|
||||
#else
|
||||
vec4 temporallyFilteredVL = VLTemporalFiltering(viewPos, frDepth, depthtex0);
|
||||
vec4 temporallyFilteredVL = VLTemporalFiltering(viewPos, frDepth, depthtex0, hand);
|
||||
#endif
|
||||
|
||||
gl_FragData[2] = temporallyFilteredVL;
|
||||
@@ -551,7 +554,7 @@ void main() {
|
||||
#ifdef FAKE_REFRACTION_EFFECT
|
||||
// ApplyDistortion(refractedCoord, tangentNormals, linearDistance, isEntity);
|
||||
// vec3 color = texture2D(colortex3, refractedCoord).rgb;
|
||||
vec3 color = doRefractionEffect(refractedCoord, tangentNormals.xy, linearDistance, isReflectiveEntity);
|
||||
vec3 color = doRefractionEffect(refractedCoord, tangentNormals.xy, linearDistance, isReflectiveEntity, isWater && isEyeInWater == 1);
|
||||
#else
|
||||
// vec3 color = texture2D(colortex3, refractedCoord).rgb;
|
||||
vec3 color = texelFetch2D(colortex3, ivec2(refractedCoord/texelSize),0).rgb;
|
||||
|
||||
@@ -88,7 +88,7 @@ void main() {
|
||||
#ifdef CLOUD_SSR
|
||||
gl_FragData[0] = vec4(oldTex, 64000.0);
|
||||
#else
|
||||
gl_FragData[0] = vec4(oldTex, 600000.0);
|
||||
gl_FragData[0] = vec4(oldTex, 650000.0);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -619,6 +619,7 @@ uniform int moonPhase;
|
||||
#define SATURATION 0.0 // [-1.0 -0.98 -0.96 -0.94 -0.92 -0.9 -0.88 -0.86 -0.84 -0.82 -0.8 -0.78 -0.76 -0.74 -0.72 -0.7 -0.68 -0.66 -0.64 -0.62 -0.6 -0.58 -0.56 -0.54 -0.52 -0.5 -0.48 -0.46 -0.44 -0.42 -0.4 -0.38 -0.36 -0.34 -0.32 -0.3 -0.28 -0.26 -0.24 -0.22 -0.2 -0.18 -0.16 -0.14 -0.12 -0.1 -0.08 -0.06 -0.04 -0.02 0.0 0.02 0.04 0.06 0.08 0.1 0.12 0.14 0.16 0.18 0.2 0.22 0.24 0.26 0.28 0.3 0.32 0.34 0.36 0.38 0.4 0.42 0.44 0.46 0.48 0.5 0.52 0.54 0.56 0.58 0.6 0.62 0.64 0.66 0.68 0.7 0.72 0.74 0.76 0.78 0.8 0.82 0.84 0.86 0.88 0.9 0.92 0.94 0.96 0.98 1.0 ]=
|
||||
#define CROSSTALK 0.0 // [-1.0 -0.98 -0.96 -0.94 -0.92 -0.9 -0.88 -0.86 -0.84 -0.82 -0.8 -0.78 -0.76 -0.74 -0.72 -0.7 -0.68 -0.66 -0.64 -0.62 -0.6 -0.58 -0.56 -0.54 -0.52 -0.5 -0.48 -0.46 -0.44 -0.42 -0.4 -0.38 -0.36 -0.34 -0.32 -0.3 -0.28 -0.26 -0.24 -0.22 -0.2 -0.18 -0.16 -0.14 -0.12 -0.1 -0.08 -0.06 -0.04 -0.02 0.0 0.02 0.04 0.06 0.08 0.1 0.12 0.14 0.16 0.18 0.2 0.22 0.24 0.26 0.28 0.3 0.32 0.34 0.36 0.38 0.4 0.42 0.44 0.46 0.48 0.5 0.52 0.54 0.56 0.58 0.6 0.62 0.64 0.66 0.68 0.7 0.72 0.74 0.76 0.78 0.8 0.82 0.84 0.86 0.88 0.9 0.92 0.94 0.96 0.98 1.0 ]
|
||||
|
||||
#define WHITE_BALANCE 6500 // [1000 1100 1200 1300 1400 1500 1600 1700 1800 1900 2000 2100 2200 2300 2400 2500 2600 2700 2800 2900 3000 3100 3200 3300 3400 3500 3600 3700 3800 3900 4000 4100 4200 4300 4400 4500 4600 4700 4800 4900 5000 5100 5200 5300 5400 5500 5600 5700 5800 5900 6000 6100 6200 6300 6400 6500 6600 6700 6800 6900 7000 7100 7200 7300 7400 7500 7600 7700 7800 7900 8000 8100 8200 8300 8400 8500 8600 8700 8800 8900 9000 9100 9200 9300 9400 9500 9600 9700 9800 9900 10000 15000 20000 25000 50000]
|
||||
// #define LUMINANCE_CURVE
|
||||
#define UPPER_CURVE 0.0 // [-2.0 -1.9 -1.8 -1.7 -1.6 -1.5 -1.4 -1.3 -1.2 -1.1 -1.0 -0.9 -0.8 -0.7 -0.6 -0.5 -0.4 -0.3 -0.2 -0.1 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2.0]
|
||||
#define LOWER_CURVE 0.0 // [-2.0 -1.9 -1.8 -1.7 -1.6 -1.5 -1.4 -1.3 -1.2 -1.1 -1.0 -0.9 -0.8 -0.7 -0.6 -0.5 -0.4 -0.3 -0.2 -0.1 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2.0]
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user