evas gl - experiment with dithered gl rendering

this adds a dither func (4x4 dither matrix) to experiment with higher
quality rendering in gl - this assumes you have a normal 8bit per
channel buffer for now (99% of people) and will approximate values in
between the 256 steps 8 bits provides by using the dither matrix based
on gl_FragCoord position. it's just a flag in the shader flags for now
so can be turned on/off in code. this definitely makes blurs look much
better... everything else seems basicall the same. let's see how this
goes.

@feat
This commit is contained in:
Carsten Haitzler 2020-11-27 15:02:58 +00:00
parent f08f0548da
commit b59b605021
4 changed files with 113 additions and 9 deletions

View File

@ -13,9 +13,9 @@
#define I(p) ((int)(intptr_t)p)
#ifdef WORDS_BIGENDIAN
# define BASEFLAG SHADER_FLAG_BIGENDIAN
# define BASEFLAG SHADER_FLAG_DITHER | SHADER_FLAG_BIGENDIAN
#else
# define BASEFLAG 0
# define BASEFLAG SHADER_FLAG_DITHER
#endif
typedef enum {
@ -47,8 +47,9 @@ typedef enum {
SHADER_FLAG_FILTER_ALPHA_ONLY = (1 << 25),
SHADER_FLAG_FILTER_GRAYSCALE = (1 << 26),
SHADER_FLAG_FILTER_INVERSE_COLOR = (1 << 27),
SHADER_FLAG_DITHER = (1 << 28),
} Shader_Flag;
#define SHADER_FLAG_COUNT 28
#define SHADER_FLAG_COUNT 29
static const char *_shader_flags[SHADER_FLAG_COUNT] = {
"TEX",
@ -79,6 +80,7 @@ static const char *_shader_flags[SHADER_FLAG_COUNT] = {
"ALPHA_ONLY",
"FILTER_GRAYSCALE",
"FILTER_INVERSE_COLOR",
"DITHER",
};
static Eina_Bool compiler_released = EINA_FALSE;

View File

@ -98,6 +98,33 @@ static const char fragment_glsl[] =
"uniform float blur_div;\n"
"#endif\n"
"// ----------------------------------------------------------------------------\n"
"#ifdef SHD_DITHER\n"
"const mat4 dm = mat4(vec4( 0, 8, 2, 10),\n"
" vec4(12, 4, 14, 6),\n"
" vec4( 3, 11, 1, 9),\n"
" vec4(15, 7, 13, 5));\n"
"float dither_closest(vec2 pos, float val)\n"
"{\n"
" float limit = dm[int(pos.x)][int(pos.y)] / 16.0;\n"
" if (val <= limit) return 0.0;\n"
" return 1.0;\n"
"}\n"
"float dither_8bit(vec2 modpos, float val)\n"
"{\n"
" float val_quant = float(floor(val * 255.0)) / 255.0;\n"
" float val_delta = (val - val_quant) / (1.0 / 256.0);\n"
" float val_roundup = dither_closest(modpos, val_delta);\n"
" return val_quant + (val_roundup * (1.0 / 256.0));\n"
"}\n"
"vec4 dither(vec4 col, vec2 pos)\n"
"{\n"
" vec2 modpos = vec2(mod(float(pos.x), 4.0), mod(float(pos.y), 4.0));\n"
" return vec4(dither_8bit(modpos, col.r),\n"
" dither_8bit(modpos, col.g),\n"
" dither_8bit(modpos, col.b),\n"
" dither_8bit(modpos, col.a));\n"
"}\n"
"#endif\n"
"#ifndef SHD_FILTER_BLUR\n"
"void main()\n"
"{\n"
@ -220,10 +247,13 @@ static const char fragment_glsl[] =
" c.b = c.r;\n"
"#endif\n"
"#ifdef SHD_FILTER_INVERSE_COLOR\n"
" c.rgb = c.a - c.rgb;\n"
" c.rgb = c.a - c.rgba;\n"
"#endif\n"
"#ifndef SHD_FILTER_BLUR\n"
" gl_FragColor =\n"
"#ifdef SHD_DITHER\n"
" dither(\n"
"#endif\n"
" c\n"
"#ifndef SHD_NOMUL\n"
" * col\n"
@ -234,6 +264,9 @@ static const char fragment_glsl[] =
"#ifdef SHD_FILTER_DISPLACE\n"
" * fa\n"
"#endif\n"
"#ifdef SHD_DITHER\n"
" , gl_FragCoord.xy)\n"
"#endif\n"
" ;\n"
"}\n"
"#else // SHD_FILTER_BLUR\n"
@ -278,9 +311,25 @@ static const char fragment_glsl[] =
" acc += (px1 + px2) * weight;\n"
" }\n"
"#ifndef SHD_NOMUL\n"
" gl_FragColor = (acc / blur_div) * col;\n"
" gl_FragColor =\n"
"#ifdef SHD_DITHER\n"
" dither(\n"
"#endif\n"
" (acc / blur_div) * col, gl_FragCoord.xy\n"
"#ifdef SHD_DITHER\n"
" )\n"
"#endif\n"
" ;\n"
"#else\n"
" gl_FragColor = (acc / blur_div);\n"
" gl_FragColor =\n"
"#ifdef SHD_DITHER\n"
" dither(\n"
"#endif\n"
" (acc / blur_div), gl_FragCoord.xy\n"
"#ifdef SHD_DITHER\n"
" )\n"
"#endif\n"
" ;\n"
"#endif\n"
"}\n"
"#endif // SHD_FILTER_BLUR\n";

View File

@ -97,6 +97,37 @@ uniform float blur_div;
// ----------------------------------------------------------------------------
#ifdef SHD_DITHER
const mat4 dm = mat4(vec4( 0, 8, 2, 10),
vec4(12, 4, 14, 6),
vec4( 3, 11, 1, 9),
vec4(15, 7, 13, 5));
float dither_closest(vec2 pos, float val)
{
float limit = dm[int(pos.x)][int(pos.y)] / 16.0;
if (val <= limit) return 0.0;
return 1.0;
}
float dither_8bit(vec2 modpos, float val)
{
float val_quant = float(floor(val * 255.0)) / 255.0;
float val_delta = (val - val_quant) / (1.0 / 256.0);
float val_roundup = dither_closest(modpos, val_delta);
return val_quant + (val_roundup * (1.0 / 256.0));
}
vec4 dither(vec4 col, vec2 pos)
{
vec2 modpos = vec2(mod(float(pos.x), 4.0), mod(float(pos.y), 4.0));
return vec4(dither_8bit(modpos, col.r),
dither_8bit(modpos, col.g),
dither_8bit(modpos, col.b),
dither_8bit(modpos, col.a));
}
#endif
#ifndef SHD_FILTER_BLUR
void main()
{
@ -243,6 +274,9 @@ vec4 fetch_pixel(float ox, float oy)
#ifndef SHD_FILTER_BLUR
gl_FragColor =
#ifdef SHD_DITHER
dither(
#endif
c
#ifndef SHD_NOMUL
* col
@ -252,6 +286,9 @@ vec4 fetch_pixel(float ox, float oy)
#endif
#ifdef SHD_FILTER_DISPLACE
* fa
#endif
#ifdef SHD_DITHER
, gl_FragCoord.xy)
#endif
;
}
@ -312,9 +349,25 @@ void main()
}
#ifndef SHD_NOMUL
gl_FragColor = (acc / blur_div) * col;
gl_FragColor =
#ifdef SHD_DITHER
dither(
#endif
(acc / blur_div) * col, gl_FragCoord.xy
#ifdef SHD_DITHER
)
#endif
;
#else
gl_FragColor = (acc / blur_div);
gl_FragColor =
#ifdef SHD_DITHER
dither(
#endif
(acc / blur_div), gl_FragCoord.xy
#ifdef SHD_DITHER
)
#endif
;
#endif
}

View File

@ -3,7 +3,7 @@
# This script will generate a C file containing all the shaders used by Evas
DIR=`dirname $0`
cd $DIR/../../../../../
#cd $DIR/../../../../../
OUTPUT="$DIR/evas_gl_shaders.x"