diff --git a/README.md b/README.md index 0f06773..99453ba 100644 --- a/README.md +++ b/README.md @@ -44,12 +44,14 @@ Blurring followed by sharpening, followed by chromatic aberration. This is a mem Darkens the edges of the screen. Comes with "border blur", which also blurs said edges. +### Paint + +Makes the game look like an oil painting, if you somehow are interested in that. + ### RetroFX A combo of downscaling and palette reduction (with optional dither), which has been a staple of MariENB for years. There's a multitude of palettes available to choose from. Most IWADs are covered, along with some notable megawads, various DOS games, and a couple "standard" palettes. -Not available yet are the features for aspect ratio correction, overscan/underscan or the old CRT filter (which wasn't exactly all that good, really). - ## Missing Shaders ### Bloom @@ -68,10 +70,10 @@ Not needed, GZDoom implements its own. These aren't "general purpose" enough to be included. -### Paint Filter +### CRT Filter -Might add it, maybe??? +Screen curvature + aperture grille overlay. I'm not going to add this back because honestly, it's dumb and ugly. ### SMAA -This needs to be part of GZDoom, honestly. \ No newline at end of file +Can't be done due to the limited features of user shaders. It should be part of GZDoom itself, honestly. diff --git a/cvarinfo.marifx b/cvarinfo.marifx index 252f711..da38293 100644 --- a/cvarinfo.marifx +++ b/cvarinfo.marifx @@ -8,6 +8,14 @@ nosave float mfx_lsharpblend = 6.; nosave bool mfx_ne = false; nosave float mfx_ni = .05; nosave float mfx_ns = 0.; +nosave float mfx_nf = .05; +nosave float mfx_nm1_r = 2.05; +nosave float mfx_nm1_g = 3.11; +nosave float mfx_nm1_b = 2.22; +nosave float mfx_nk = .04; +nosave float mfx_nm2_r = 4.25; +nosave float mfx_nm2_g = 9.42; +nosave float mfx_nm2_b = 6.29; nosave float mfx_np = 4.; nosave float mfx_bnp = 1.5; nosave int mfx_nb = 2; @@ -98,6 +106,8 @@ nosave float mfx_vigbump = 0.; nosave int mfx_vigshape = 1; nosave int mfx_vigmode = 0; +nosave bool mfx_paintenable = false; + nosave bool mfx_retroenable = false; nosave int mfx_retroscalemode = 0; nosave int mfx_bres_x = 640; diff --git a/gldefs.txt b/gldefs.txt index c41ea43..65ac1f2 100644 --- a/gldefs.txt +++ b/gldefs.txt @@ -7,6 +7,32 @@ HardwareShader postprocess scene Uniform float sharpblend } +HardwareShader postprocess scene +{ + Name "mfx_grain" + Shader "shaders/glsl/mfx_grain.fp" 330 + Uniform float Timer + Uniform float nf + Uniform float ni + Uniform float ns + Uniform vec3 nm1 + Uniform float nk + Uniform vec3 nm2 + Uniform float np + Uniform float bnp + Uniform int nb + Texture NoiseTexture "textures/mfxnoise.png" +} + +HardwareShader postprocess scene +{ + Name "mfx_dirt" + Shader "shaders/glsl/mfx_dirt.fp" 330 + Uniform float dirtcfactor + Uniform float dirtmc + Texture NoiseTexture "textures/mfxdirt.png" +} + HardwareShader postprocess scene { Name "mfx_grading" @@ -74,6 +100,37 @@ HardwareShader postprocess scene Uniform float hsval_m } +HardwareShader postprocess scene +{ + Name "mfx_borderblur" + Shader "shaders/glsl/mfx_borderblur.fp" 330 + Uniform float vigpow + Uniform float vigmul + Uniform float vigbump + Uniform int vigshape + Uniform float bblurpow + Uniform float bblurmul + Uniform float bblurbump + Uniform float bblurradius + Texture VignetteTexture "textures/mfxvig.png" +} + +HardwareShader postprocess scene +{ + Name "mfx_paint_pass1" + Shader "shaders/glsl/mfx_paint_pass1.fp" 330 +} +HardwareShader postprocess scene +{ + Name "mfx_paint_pass2" + Shader "shaders/glsl/mfx_paint_pass2.fp" 330 +} +HardwareShader postprocess scene +{ + Name "mfx_paint_pass3" + Shader "shaders/glsl/mfx_paint_pass3.fp" 330 +} + HardwareShader postprocess scene { Name "mfx_bss_blur" @@ -93,44 +150,6 @@ HardwareShader postprocess scene Shader "shaders/glsl/mfx_bss_shift.fp" 330 Uniform float bssshiftradius } - -HardwareShader postprocess scene -{ - Name "mfx_borderblur" - Shader "shaders/glsl/mfx_borderblur.fp" 330 - Uniform float vigpow - Uniform float vigmul - Uniform float vigbump - Uniform int vigshape - Uniform float bblurpow - Uniform float bblurmul - Uniform float bblurbump - Uniform float bblurradius - Texture VignetteTexture "textures/mfxvig.png" -} - -HardwareShader postprocess scene -{ - Name "mfx_grain" - Shader "shaders/glsl/mfx_grain.fp" 330 - Uniform float Timer - Uniform float ni - Uniform float ns - Uniform float np - Uniform float bnp - Uniform int nb - Texture NoiseTexture "textures/mfxnoise.png" -} - -HardwareShader postprocess scene -{ - Name "mfx_dirt" - Shader "shaders/glsl/mfx_dirt.fp" 330 - Uniform float dirtcfactor - Uniform float dirtmc - Texture NoiseTexture "textures/mfxdirt.png" -} - HardwareShader postprocess scene { Name "mfx_vignette" diff --git a/language.txt b/language.txt index 4b27bdd..51005b7 100644 --- a/language.txt +++ b/language.txt @@ -1,8 +1,9 @@ [enu default] MFX_TITLE="MariFX Options"; -MFX_BLENDMODE1="Add"; -MFX_BLENDMODE2="Overlay"; -MFX_BLENDMODE3="Dark Mask"; +MFX_BLENDMODE1="Mix"; +MFX_BLENDMODE2="Add"; +MFX_BLENDMODE3="Overlay"; +MFX_BLENDMODE4="Dark Mask"; MFX_VIGSHAPE1="Circle"; MFX_VIGSHAPE2="Box"; MFX_VIGSHAPE3="Texture"; @@ -100,8 +101,16 @@ MFX_LSHARPRADIUS="Sharpen Radius"; MFX_LSHARPTRESHOLD="Sharpen Threshold"; MFX_LSHARPSTRENGTH="Sharpen Strength"; MFX_GRAIN="Film Grain"; +MFX_NF="Grain Speed"; MFX_NI="Grain Intensity"; MFX_NS="Grain Saturation"; +MFX_NM1_R="Grain Pass 1 Magnification 1"; +MFX_NM1_G="Grain Pass 1 Magnification 2"; +MFX_NM1_B="Grain Pass 1 Magnification 3"; +MFX_NK="Grain Two-Pass Factor"; +MFX_NM2_R="Grain Pass 2 Magnification 1"; +MFX_NM2_G="Grain Pass 2 Magnification 2"; +MFX_NM2_B="Grain Pass 2 Magnification 3"; MFX_NP="Grain Contrast"; MFX_NB="Grain Blend Mode"; MFX_BNP="Grain Dark Mask Contrast"; @@ -186,6 +195,7 @@ MFX_BBLURPOW="Blur Gamma"; MFX_BBLURMUL="Blur Intensity"; MFX_BBLURBUMP="Blur Offset"; MFX_BBLURRADIUS="Blur Radius"; +MFX_PAINT="Painting Filter"; MFX_RETROFX="Retro FX"; MFX_RETROENABLE="Enable Downscale"; MFX_RETROSCALEMODE="Scaling Mode"; diff --git a/menudef.txt b/menudef.txt index 2d78ffb..19c7444 100644 --- a/menudef.txt +++ b/menudef.txt @@ -12,6 +12,7 @@ OptionValue "MFXGrainBlend" 0, "$MFX_BLENDMODE1" 1, "$MFX_BLENDMODE2" 2, "$MFX_BLENDMODE3" + 3, "$MFX_BLENDMODE4" } OptionValue "MFXVigShape" @@ -145,10 +146,18 @@ OptionMenu "MFXOptionsMenu" StaticText " " Option "$MFX_ENABLE", "mfx_ne", "YesNo" MFXSlider "$MFX_NI", "mfx_ni", 0, 1, 0.01, 2 + MFXSlider "$MFX_NF", "mfx_nf", -10, 10, 0.01, 2 MFXSlider "$MFX_NS", "mfx_ns", -1, 1, 0.01, 2 - MFXSlider "$MFX_NP", "mfx_np", 0.5, 8, 0.01, 2 + MFXSlider "$MFX_NP", "mfx_np", 0, 8, 0.01, 2 + MFXSlider "$MFX_NM1_R", "mfx_nm1_r", 0, 10, 0.01, 2 + MFXSlider "$MFX_NM1_G", "mfx_nm1_g", 0, 10, 0.01, 2 + MFXSlider "$MFX_NM1_B", "mfx_nm1_b", 0, 10, 0.01, 2 + MFXSlider "$MFX_NK", "mfx_nk", 0, 1, 0.01, 2 + MFXSlider "$MFX_NM2_R", "mfx_nm2_r", 0, 10, 0.01, 2 + MFXSlider "$MFX_NM2_G", "mfx_nm2_g", 0, 10, 0.01, 2 + MFXSlider "$MFX_NM2_B", "mfx_nm2_b", 0, 10, 0.01, 2 Option "$MFX_NB", "mfx_nb", "MFXGrainBlend" - MFXSlider "$MFX_BNP", "mfx_bnp", 0.5, 10, 0.01, 2 + MFXSlider "$MFX_BNP", "mfx_bnp", 0, 10, 0.01, 2 SafeCommand "$MFX_RESET", "event resetmfxvars 0" StaticText " " StaticText "$MFX_DIRT", "Gold" @@ -263,6 +272,11 @@ OptionMenu "MFXOptionsMenu" MFXSlider "$MFX_BBLURRADIUS", "mfx_bblurradius", 0, 4, 0.01, 2 SafeCommand "$MFX_RESET", "event resetmfxvars 6" StaticText " " + StaticText "$MFX_PAINT", "Gold" + StaticText " " + Option "$MFX_ENABLE", "mfx_paintenable", "YesNo" + SafeCommand "$MFX_RESET", "event resetmfxvars 11" + StaticText " " StaticText "$MFX_RETROFX", "Gold" StaticText " " Option "$MFX_RETROENABLE", "mfx_retroenable", "YesNo" diff --git a/shaders/glsl/mfx_grading.fp b/shaders/glsl/mfx_grading.fp index 8e9b82a..abb6c2e 100644 --- a/shaders/glsl/mfx_grading.fp +++ b/shaders/glsl/mfx_grading.fp @@ -24,12 +24,12 @@ void main() { vec4 res = texture(InputTexture,TexCoord); res.rgb = pow(max(res.rgb,0.0),gradepow)*grademul; - float tonev = luminance(res.rgb); - vec3 tonecolor = gradecol*tonev; - res.rgb = res.rgb*(1.0-gradecolfact)+tonecolor*gradecolfact; vec3 hsv = rgb2hsv(res.rgb); hsv.y = clamp(pow(max(hsv.y,0.0),gradesatpow)*gradesatmul,0.0,1.0); hsv.z = pow(max(hsv.z,0.0),gradevalpow)*gradevalmul; res.rgb = hsv2rgb(hsv); + float tonev = luminance(res.rgb); + vec3 tonecolor = gradecol*tonev; + res.rgb = res.rgb*(1.0-gradecolfact)+tonecolor*gradecolfact; FragColor = res; } diff --git a/shaders/glsl/mfx_grain.fp b/shaders/glsl/mfx_grain.fp index 4fcf6fd..9da5fd8 100644 --- a/shaders/glsl/mfx_grain.fp +++ b/shaders/glsl/mfx_grain.fp @@ -2,24 +2,18 @@ Complex grain shader ported over from MariENB (C)2012-2021 Marisa Kirisame */ -const float nf = 0.0005; -const vec3 nm1 = vec3(2.05,3.11,2.22); -const float nk = 0.04; -const vec3 nm2 = vec3(4.25,9.42,6.29); - #define overlay(a,b) (a<0.5)?(2.0*a*b):(1.0-(2.0*(1.0-a)*(1.0-b))) #define darkmask(a,b) (a>0.5)?(2.0*a*(0.5+b)):(1.0-2.0*(1.0-a)*(1.0-((0.5+b)))) vec3 grain( in vec3 res, in vec2 coord ) { float ts = Timer*nf; - vec2 s1 = coord+vec2(0.0,ts); - vec2 s2 = coord+vec2(ts,0.0); + vec2 s1 = coord+vec2(0.,ts); + vec2 s2 = coord+vec2(ts,0.); vec2 s3 = coord+vec2(ts,ts); float n1, n2, n3; vec2 bresl = textureSize(InputTexture,0); - vec2 nr = vec2(7.5); - nr.y *= bresl.y/bresl.x; + vec2 nr = bresl/256.; n1 = texture(NoiseTexture,s1*nm1.x*nr).r; n2 = texture(NoiseTexture,s2*nm1.y*nr).g; n3 = texture(NoiseTexture,s3*nm1.z*nr).b; @@ -29,26 +23,27 @@ vec3 grain( in vec3 res, in vec2 coord ) n1 = texture(NoiseTexture,s1*nm2.x*nr).r; n2 = texture(NoiseTexture,s2*nm2.y*nr).g; n3 = texture(NoiseTexture,s3*nm2.z*nr).b; - float n4 = (n1+n2+n3)/3.0; + float n4 = (n1+n2+n3)/3.; vec3 ng = vec3(n4); vec3 nc = vec3(n1,n2,n3); - vec3 nt = pow(clamp(mix(ng,nc,ns),0.0,1.0),vec3(np)); - if ( nb == 0 ) res.rgb += nt*ni; - else if ( nb == 1 ) + vec3 nt = pow(clamp(mix(ng,nc,ns),.0,1.),vec3(np)); + if ( nb == 1 ) res.rgb += nt*ni; + else if ( nb == 2 ) { - res.r = overlay(res.r,(nt.r*ni+0.5)); - res.g = overlay(res.g,(nt.g*ni+0.5)); - res.b = overlay(res.b,(nt.b*ni+0.5)); + res.r = overlay(res.r,(nt.r*ni)); + res.g = overlay(res.g,(nt.g*ni)); + res.b = overlay(res.b,(nt.b*ni)); } - else + else if ( nb == 3 ) { - float bn = 1.0-clamp((res.r+res.g+res.b)/3.0,0.0,1.0); + float bn = 1.-clamp((res.r+res.g+res.b)/3.,0.,1.); bn = pow(bn,bnp); - vec3 nn = clamp(nt*bn,vec3(0.0),vec3(1.0)); + vec3 nn = clamp(nt*bn,vec3(0.),vec3(1.)); res.r = darkmask(res.r,(nn.r*ni)); res.g = darkmask(res.g,(nn.g*ni)); res.b = darkmask(res.b,(nn.b*ni)); } + else res.rgb = mix(res.rgb,nt,ni); return res; } diff --git a/shaders/glsl/mfx_paint_pass1.fp b/shaders/glsl/mfx_paint_pass1.fp new file mode 100644 index 0000000..5bb29f6 --- /dev/null +++ b/shaders/glsl/mfx_paint_pass1.fp @@ -0,0 +1,52 @@ +/* + Paint filter from MariENB (first pass Kuwahara filter) + (C)2012-2021 Marisa Kirisame +*/ + +void main() +{ + vec2 coord = TexCoord; + vec4 res = texture(InputTexture,coord); + vec2 bresl = textureSize(InputTexture,0); + vec2 bof = 1./bresl; + float n = 16.; + vec3 m[4] = vec3[](vec3(0.),vec3(0.),vec3(0.),vec3(0.)), + s[4] = vec3[](vec3(0.),vec3(0.),vec3(0.),vec3(0.)), + c; + int i, j; + for ( i=-3; i<=0; i++ ) for ( j=-3; j<=0; j++ ) + { + c = texture(InputTexture,coord+vec2(i,j)*bof).rgb; + m[0] += c; + s[0] += c*c; + } + for ( i=-3; i<=0; i++ ) for ( j=0; j<=3; j++ ) + { + c = texture(InputTexture,coord+vec2(i,j)*bof).rgb; + m[1] += c; + s[1] += c*c; + } + for ( i=0; i<=3; i++ ) for ( j=-3; j<=0; j++ ) + { + c = texture(InputTexture,coord+vec2(i,j)*bof).rgb; + m[2] += c; + s[2] += c*c; + } + for ( i=0; i<=3; i++ ) for ( j=0; j<=3; j++ ) + { + c = texture(InputTexture,coord+vec2(i,j)*bof).rgb; + m[3] += c; + s[3] += c*c; + } + float min_sigma2 = 1e+2, sigma2; + for ( i=0; i<4; i++ ) + { + m[i] /= n; + s[i] = abs(s[i]/n-m[i]*m[i]); + sigma2 = s[i].r+s[i].g+s[i].b; + if ( sigma2 >= min_sigma2 ) continue; + min_sigma2 = sigma2; + res.rgb = m[i]; + } + FragColor = res; +} diff --git a/shaders/glsl/mfx_paint_pass2.fp b/shaders/glsl/mfx_paint_pass2.fp new file mode 100644 index 0000000..bdda048 --- /dev/null +++ b/shaders/glsl/mfx_paint_pass2.fp @@ -0,0 +1,33 @@ +/* + Paint filter from MariENB (second pass median smoothing) + (C)2012-2021 Marisa Kirisame +*/ +#define luminance(x) dot(x,vec3(0.2126,0.7152,0.0722)) + +void main() +{ + vec2 coord = TexCoord; + vec4 res = vec4(1.); + vec2 bresl = textureSize(InputTexture,0); + vec2 bof = 1./bresl; + vec3 m1, m2, m3; + vec3 a, b, c; + a = texture(InputTexture,coord+vec2(-1,-1)*bof).rgb; + b = texture(InputTexture,coord+vec2( 0,-1)*bof).rgb; + c = texture(InputTexture,coord+vec2( 1,-1)*bof).rgb; + m1 = (luminance(a) lumaMax) ) res.rgb = rgbA; + else res.rgb = rgbB; + FragColor = res; +} diff --git a/zscript.txt b/zscript.txt index 54f0004..2a6d5a2 100644 --- a/zscript.txt +++ b/zscript.txt @@ -202,8 +202,12 @@ Class MariFXHandler : StaticEventHandler Shader.SetUniform1f(p,"mfx_lumasharp","sharpblend",mfx_lsharpblend); // FILM GRAIN Shader.SetEnabled(p,"mfx_grain",mfx_ne); + Shader.SetUniform1f(p,"mfx_grain","nf",mfx_nf/10.); Shader.SetUniform1f(p,"mfx_grain","ni",mfx_ni); Shader.SetUniform1f(p,"mfx_grain","ns",mfx_ns); + Shader.SetUniform3f(p,"mfx_grain","nm1",(mfx_nm1_r,mfx_nm1_g,mfx_nm1_b)); + Shader.SetUniform1f(p,"mfx_grain","nk",mfx_nk); + Shader.SetUniform3f(p,"mfx_grain","nm2",(mfx_nm2_r,mfx_nm2_g,mfx_nm2_b)); Shader.SetUniform1f(p,"mfx_grain","np",mfx_np); Shader.SetUniform1f(p,"mfx_grain","bnp",mfx_bnp); Shader.SetUniform1i(p,"mfx_grain","nb",mfx_nb); @@ -283,6 +287,10 @@ Class MariFXHandler : StaticEventHandler Shader.SetUniform1f(p,"mfx_vignette","vigbump",mfx_vigbump); Shader.SetUniform1i(p,"mfx_vignette","vigshape",mfx_vigshape); Shader.SetUniform1i(p,"mfx_vignette","vigmode",mfx_vigmode); + // PAINTING + Shader.SetEnabled(p,"mfx_paint_pass1",mfx_paintenable); + Shader.SetEnabled(p,"mfx_paint_pass2",mfx_paintenable); + Shader.SetEnabled(p,"mfx_paint_pass3",mfx_paintenable); // RETRO FX Vector2 rresl = (Screen.GetWidth(),Screen.GetHeight()); Vector2 bresl = rresl; @@ -330,8 +338,16 @@ Class MariFXHandler : StaticEventHandler case 0: CVar.FindCVar('mfx_ne').ResetToDefault(); CVar.FindCVar('mfx_ni').ResetToDefault(); + CVar.FindCVar('mfx_nf').ResetToDefault(); CVar.FindCVar('mfx_ns').ResetToDefault(); CVar.FindCVar('mfx_np').ResetToDefault(); + CVar.FindCVar('mfx_nm1_r').ResetToDefault(); + CVar.FindCVar('mfx_nm1_g').ResetToDefault(); + CVar.FindCVar('mfx_nm1_b').ResetToDefault(); + CVar.FindCVar('mfx_nk').ResetToDefault(); + CVar.FindCVar('mfx_nm2_r').ResetToDefault(); + CVar.FindCVar('mfx_nm2_g').ResetToDefault(); + CVar.FindCVar('mfx_nm2_b').ResetToDefault(); CVar.FindCVar('mfx_bnp').ResetToDefault(); CVar.FindCVar('mfx_nb').ResetToDefault(); break; @@ -447,6 +463,9 @@ Class MariFXHandler : StaticEventHandler CVar.FindCVar('mfx_techenable').ResetToDefault(); CVar.FindCVar('mfx_techblend').ResetToDefault(); break; + case 11: + CVar.FindCVar('mfx_paintenable').ResetToDefault(); + break; } } }