From c13d0fda06455ade957362eb500e16022cf59337 Mon Sep 17 00:00:00 2001 From: hunterk Date: Wed, 27 Mar 2019 16:28:59 -0500 Subject: [PATCH] more work on mame hlsl port --- .../shaders/mame/aperture-grille.png | Bin 0 -> 19734 bytes .../shaders/mame/mame_bloom.slang | 266 ++++++------ .../shaders/mame/mame_chroma.slang | 41 +- .../shaders/mame/mame_color.slang | 38 +- .../shaders/mame/mame_deconverge.slang | 39 +- .../shaders/mame/mame_distortion.slang | 168 ++++---- .../shaders/mame/mame_focus.slang | 12 +- .../shaders/mame/mame_hlsl.slangp | 66 +++ .../shaders/mame/mame_ntsc.slang | 221 ++++++++++ .../shaders/mame/mame_ntsc.slang.ps.hlsl | 379 ++++++++++++++++++ .../shaders/mame/mame_ntsc.slang.vs.hlsl | 60 +++ .../shaders/mame/mame_parameters.inc | 295 ++++++++++++++ .../shaders/mame/mame_phosphor.slang | 56 +++ .../shaders/mame/mame_post.slang | 197 +++++++++ .../shaders/mame/mame_scanline.slang | 124 ++++++ .../shaders/mame/mame_vector.slang | 102 +++++ test/nonfunctional/shaders/mame/primary.slang | 71 ++++ .../shaders/mame/shadow-mask.png | Bin 0 -> 20397 bytes .../shaders/mame/slot-mask-aligned.png | Bin 0 -> 26638 bytes test/nonfunctional/shaders/mame/slot-mask.png | Bin 0 -> 19768 bytes 20 files changed, 1805 insertions(+), 330 deletions(-) create mode 100644 test/nonfunctional/shaders/mame/aperture-grille.png create mode 100644 test/nonfunctional/shaders/mame/mame_hlsl.slangp create mode 100644 test/nonfunctional/shaders/mame/mame_ntsc.slang create mode 100644 test/nonfunctional/shaders/mame/mame_ntsc.slang.ps.hlsl create mode 100644 test/nonfunctional/shaders/mame/mame_ntsc.slang.vs.hlsl create mode 100644 test/nonfunctional/shaders/mame/mame_parameters.inc create mode 100644 test/nonfunctional/shaders/mame/mame_phosphor.slang create mode 100644 test/nonfunctional/shaders/mame/mame_post.slang create mode 100644 test/nonfunctional/shaders/mame/mame_scanline.slang create mode 100644 test/nonfunctional/shaders/mame/mame_vector.slang create mode 100644 test/nonfunctional/shaders/mame/primary.slang create mode 100644 test/nonfunctional/shaders/mame/shadow-mask.png create mode 100644 test/nonfunctional/shaders/mame/slot-mask-aligned.png create mode 100644 test/nonfunctional/shaders/mame/slot-mask.png diff --git a/test/nonfunctional/shaders/mame/aperture-grille.png b/test/nonfunctional/shaders/mame/aperture-grille.png new file mode 100644 index 0000000000000000000000000000000000000000..052b300f241b8ac0ee27e041bc5ba150da807789 GIT binary patch literal 19734 zcmeHPX;c&0wk{f*Nf{hb5j%hbBAG)VF$5uu0wNFuoQtFqB4jX$2Czj?K^$5{R3@QO zTN%XxMG;g)!~p@(b_Asr5YYx-gEqDbyb5DP>}#!F_r7=6O07UD=j{FMbH2ULKKs;< z+O}w+leX4WEdT(tU7YQ`;BTD#PvblI|HD;++whmB$k|^406JyzKb3uRbqoMN%Y(;Y zELs#OlnNz*LJ`V^!9a<`LJlt&0)UXmsoq?scgrN}&ZlqfTw@~kx(dA}YM{LAc0^2w zn`LICskb1;=-{J?o|nfuIE*s5o*tvRYgfe1iJsXV-sD#`dtpSv{r>YJY%Bf0Hf9etFD`vgaBKTfC-N6 zzO+B)=IJ$?!AvEcq7}}dI7BYhK(A5v^~Fp#t#Z+yJAn*-2PV(Ql!hivAw-gNf9tpf z0O@fP;n{X{g;eR}RaKF973i!)zq+K>V;m6B(A`v>BbpBY&!pis-R9W*sS)$kBKX~h zX10wATroO*ZRZZoDc$*Jfb^Efz8xYtHx37P7e0E_)Y$lNL7ClB@TTvEZf@zy65p=i zzrtysI^X?v@%fBM!tzL`QSW~%z4g}Z$h7J`np*-5#dEN;C z?M1@NznW^OMg(qtRxRs!W7Fl7J`;%Gxa?U204wZgV3;@aZLVnmfPH$T*$G>Nx0ffI zm#9s<{C(Z!(Vte4x7f`nE49^9@NQo`KQvA{|Vr z&p91yk?sdjBki(jair!b+v^(RL8HepDgoR5Om=DLCq=zCy6ik^+>RNj8!;0+ja}m` zobg`UnJ6D;!**-&ca*Km9M8wiyABXGeTpu2!taedioeCV8snl^(p_OYg=rs@{Y(%HuGnXad2 zoge#G+2jBMeyg9exyk);vE#9N>th&YmNUj}V-RK+?*7i@UDGVf+RZ_u?dXY{uf=dpr=(0)pUj;in|wUc?dX)dJEmM?;w*$wQs?`S^Esku*|INquEchNBea6R4`++R(Nm7bMzs4H)Lu4 zx!#X?bAca9(K=jS`>e$P%QEy0G^ZtNzp=PsbMnXsU z_NNox%y~Y?;3&zh5DzU2%HE%_-!I2G$1}(2^#yWXYewqP3l2s8A0u^auPvCpY_=0O zw(9%TX75MdPcpPJCb?Tv-{oPlgN_&+EV7qf5@fU`rd?bSk>)1Mcp7@4`NOmg*e+%l z|3k(*r!jtN`D13N)sCr}OuK5aMo2TnUaS4Xld=5De8v%QADHlLOI%?M?eIOvpB!~} z^2(Pr%xK`3^UDv_^HcUU3=>zogBj@ zhT)Ra;tABn)ThZ+2ij~lTz$L01YZ}eiL1{olx*&Z*|E)a zQw1i0j!7{ne{%go;{xfsHOrrc-FcUqlAluAnpu0ijoij-+gkVYEz-|(()@{%+gGkL ze)DXqu^IjIK3q_JZny`-Ba(Zj*#yhN#`zw5aN_I{S#~G*MxXvCUHo$cy@6)=l&UT8bfHg?moO-+}N83kVdefKe=&gR6bxGJ7b)S~d0_iw9%FTfpF!pF>x+8X5> zZL>=h<2SVipI{-Ysbfg$?LXM>w||<##d}bWqZe41(X%nDX^$<>lg`_eV>te|?)jzq zxdgjTqhQSP$b#UD^`BZhwmwgNKDuGOej@hza#85Ps?xVn8I!UwgcG zwY%6&+wDmTHEmMzIuxH^O}&8MyeDq=8oO*G_xJ+tEA9)Qwht!H%=o>HE}g z1m*9}{oWs~RbY4YC3A`C12gqgT*#MmsdC#*%Kn_Rxs|QA@^9Aewmk6W=bqMarQ@FM zDL4}C>Wen?dvPImHRTj-O=zuF!^H3BMlV*&rJdVeV8*}ak<;p%kQaVoR+xKGh_+_$|);kS99)gT3$Rwr!CdlpPld`K}Vqd=<#Xo`o*VP-~H)Oi%qCBtu5MIz$iR? ziFU3S%D7QgInRdq3-c}W1C!i#=gArH!FxeXo5A|xKS{set6f^$*+su`vDQb$$Ne7X z9`w=WV}7Si-nQ(P_xnHcmmgcmU(b}$s;h4YbR@ELVSl`U5 zs$Z=ud~;q;`s|KF&yMDK#q+9`wV#u=pQ>#d?|aTS`8ahY|CRI=tvmj%$F-sZMag-E z%Yq8q!Y-Uy&*^M2NVBYZ^7caLACr3S-%F!dKe^BmChWZ0`L2G_lW_6uuBwWnN3z*% z$BI3QSH7L!YWs-sWa~YfrQLN8-_&hfT_Q{GsHt=6REyeN-5vKXR+sU8Y*K7Rw089C zG%GrV^4vz;)$%EWQO&NNm8Rc)sJkLhe-bwQ{k_)@s%jEz4kolG#9!k7c%B=>{HExVF^b2w zHukk}$GM9bP$17aObmI4Eo8F7f>;!`u?<~|7D9yq_>dGth46y~5^9LGaW5_vzLz&+ zjZwWK(jaSNTe(4$pZg*dLnww&78naO3rE1CEGZbg1&M;ko1+LgJQ0h>VF?s89#17% zQt@O||7A?qg70WzHiznE@7Qk+{$*_(D3yw+SgcGY!^nsjp_q%sQz#THj({Z)(69tr z5-N~_A!vcbqz_~O#~zZf#5|FdClsLMxL|;At<>7sSZ-+W>Yo>1G-ya5>E{k+5gP)E zuy_m(JCYKcHK-$6D-P}*8k>cMf+0R6kV;@Z{D^v@f#QEq{WFt;-Cs2f`^4RSWaWYJ z^7$j0mPj4e!4&jU`kC1QO$jqp1Yx}(iEyo$1v#vPr(!bF>?Kk!XvjO?00oPW2qfik zzJep~`6>xe2=6Ou@}54m-k9ohH4P?>$`C`KR48T&g~9Z`a2+~`!RIhjU!H(1lu72$ zu*0Q?VrB>kvInIQ9gb-{8c#qIC`=rlN~BONNOR#E98LkGPjVQByO7P}gbrX>pmFer zD90e-sCdh{IKm)?g5+=vcnz{aDfmq&in0ngY!;Ox6!SqToyP~c5LP7M(y&8~3X+47 zNo5Fwg<^PE5S>WFj?_G&7JSxS)OXaSOT3)yP%aJ(GM+*vqX`(iB8-CEh&c8_)>`=z zvlXx)3G7daf}de;_a+fLko$S-Ku0i-4m%ga=CP>(1Pc}!M)-_K{A_w z#)BY>fFqFDAc0K7%2NldG&B-9Qg7?$HWX*@cO#Sskh?q8MIe!a@C01!d&k3r$Acqt z2t+F@BH9Y%;L#)^$r5da$CKc@0FZ#=P*@fOnC>sshep;9Jz%{b`rD`42d$v~1+<5l z2X7x>u!0OSHv3GB0P}?@XP(@*p~Hxmd&3)A^Lgu#Z+jEH2oy^oc^b1e9>`;ZI|D2_ zc+q;(Ar)lFw+K2*o*W=H4f|Q^(6EN9@xFB6w*^!mzJmJKZO8&4!QW+=KB!))uY*X0 z9H|TxL$+La&HRhJ*9Z8y#&G13mjp~t@4^e_{R1CJz;*x310c!D3bcaoXrd*^MsqAl z9JCeD!V(SQ0xYdqWD>`M#2N4~A`g&yb3BfT!%+$F2hPuZIsX5|19GnW46_130T*J^ zu>+GDX!s90jU^PUgTzRd4!l4?xO{}*%*_!C`6y5%3g)pu`7*?=6R`X1ufcrD`5Nw=gNk}JR~8iFv>xiQ2%9f{>O_FPYU30h*lt)LdJvW01gR{206q4G-yS_ zTd`Oy0?X2JAbypLQohgpKggutR*dwmMMO^fTBZBnok{yP#m_5~fm-d$N@k!?>&qsN z@*F5HZ2ooO0;hfW97R`G%=~mOJ~=+5Po3;`*^~a0==pp$q?M3E5|5 z1ehUf1I*hG5v))#(&PtADqMrY^-%AoLx+zaU$iNp_4fJ6YsuiXy|p5RjDs)uQ3ibV zt15O6SM~pURmJY%szaJS0-lsk=(jekSwTyF`t3WPdBab9AoS3gRP_IvqC!W%V&5WBcrMfHl)hH@sSo_X2|M`2Nx@(8jQDT5hGz6{ zG9ZUl8bL&^k}f4(h!{X5tc)%tU5FS!B&>`sC0&RZKqRb;E+t)v7(gVfj4mZzh!{X5 ztc)%tU5FS!B&>`sC0&RZKqRb;E+t)v7(gVfj4mZzh!{X5tc)%tU5FS!B&>`sC0&RZ zKqRb;E+t)v7(gVfj4mZzh!{X5tc)%tU5FS!B&>`sC0&RZKqRb;E+t)v7(gVfj4mZz zh!{X5tc)%tU5FS!B&>`sC0&RZKqUOP(WN!?4hKj8zqmmLzoDUdn_)Ekb_W#8*~=XO z!e# 0.5) - { - texelI = texture(BloomSamplerI, BloomCoord.xy).rgb; - texelJ = texture(BloomSamplerJ, BloomCoord.xy).rgb; - texelK = texture(BloomSamplerK, BloomCoord.xy).rgb; - texelL = texture(BloomSamplerL, BloomCoord.xy).rgb; - texelM = texture(BloomSamplerM, BloomCoord.xy).rgb; - texelN = texture(BloomSamplerN, BloomCoord.xy).rgb; - texelO = texture(BloomSamplerO, BloomCoord.xy).rgb; - } + // vector screen uses twice -1 as many bloom levels + if (VectorScreen) + { + texelI = textureLod(BloomSamplerI, BloomCoord.xy, 1.0).rgb; + texelJ = textureLod(BloomSamplerJ, BloomCoord.xy, 1.0).rgb; + texelK = textureLod(BloomSamplerK, BloomCoord.xy, 1.0).rgb; + texelL = textureLod(BloomSamplerL, BloomCoord.xy, 1.0).rgb; + texelM = textureLod(BloomSamplerM, BloomCoord.xy, 1.0).rgb; + texelN = textureLod(BloomSamplerN, BloomCoord.xy, 1.0).rgb; + texelO = textureLod(BloomSamplerO, BloomCoord.xy, 1.0).rgb; + } - vec3 blend; + vec3 blend; - // brighten - if (params.BloomBlendMode < 0.5) - { - vec3 bloom = vec3(0.0f, 0.0f, 0.0f); + // brighten + if (BloomBlendMode < 0.5) + { + vec3 bloom = vec3(0.0f, 0.0f, 0.0f); - texel *= params.Level0Weight; + texel *= Level0Weight; - if (params.VectorScreen < 0.5) - { - bloom += texelA * params.Level1Weight; - bloom += texelB * params.Level2Weight; - bloom += texelC * params.Level3Weight; - bloom += texelD * params.Level4Weight; - bloom += texelE * params.Level5Weight; - bloom += texelF * params.Level6Weight; - bloom += texelG * params.Level7Weight; - bloom += texelH * params.Level8Weight; - } - // vector screen uses twice -1 as many bloom levels - else - { - bloom += texelA * (params.Level1Weight); - bloom += texelB * (params.Level1Weight + params.Level2Weight) * 0.5f; - bloom += texelC * (params.Level2Weight); - bloom += texelD * (params.Level2Weight + params.Level3Weight) * 0.5f; - bloom += texelE * (params.Level3Weight); - bloom += texelF * (params.Level3Weight + params.Level4Weight) * 0.5f; - bloom += texelG * (params.Level4Weight); - bloom += texelH * (params.Level4Weight + params.Level5Weight) * 0.5f; - bloom += texelI * (params.Level5Weight); - bloom += texelJ * (params.Level5Weight + params.Level6Weight) * 0.5f; - bloom += texelK * (params.Level6Weight); - bloom += texelL * (params.Level6Weight + params.Level7Weight) * 0.5f; - bloom += texelM * (params.Level7Weight); - bloom += texelN * (params.Level7Weight + params.Level8Weight) * 0.5f; - bloom += texelO * (params.Level8Weight); - } + if (VectorScreen) + { + bloom += texelA * Level1Weight; + bloom += texelB * Level2Weight; + bloom += texelC * Level3Weight; + bloom += texelD * Level4Weight; + bloom += texelE * Level5Weight; + bloom += texelF * Level6Weight; + bloom += texelG * Level7Weight; + bloom += texelH * Level8Weight; + } + // vector screen uses twice -1 as many bloom levels + else + { + bloom += texelA * (Level1Weight); + bloom += texelB * (Level1Weight + Level2Weight) * 0.5f; + bloom += texelC * (Level2Weight); + bloom += texelD * (Level2Weight + Level3Weight) * 0.5f; + bloom += texelE * (Level3Weight); + bloom += texelF * (Level3Weight + Level4Weight) * 0.5f; + bloom += texelG * (Level4Weight); + bloom += texelH * (Level4Weight + Level5Weight) * 0.5f; + bloom += texelI * (Level5Weight); + bloom += texelJ * (Level5Weight + Level6Weight) * 0.5f; + bloom += texelK * (Level6Weight); + bloom += texelL * (Level6Weight + Level7Weight) * 0.5f; + bloom += texelM * (Level7Weight); + bloom += texelN * (Level7Weight + Level8Weight) * 0.5f; + bloom += texelO * (Level8Weight); + } - bloom *= params.BloomScale; + bloom *= BloomScale; - vec3 bloomOverdrive; - bloomOverdrive.r = max(0.0f, texel.r + bloom.r - 1.0f) * params.BloomOverdrive_r; - bloomOverdrive.g = max(0.0f, texel.g + bloom.g - 1.0f) * params.BloomOverdrive_g; - bloomOverdrive.b = max(0.0f, texel.b + bloom.b - 1.0f) * params.BloomOverdrive_b; + vec3 bloomOverdrive; + bloomOverdrive.r = max(0.0f, texel.r + bloom.r - 1.0f) * BloomOverdrive.r; + bloomOverdrive.g = max(0.0f, texel.g + bloom.g - 1.0f) * BloomOverdrive.g; + bloomOverdrive.b = max(0.0f, texel.b + bloom.b - 1.0f) * BloomOverdrive.b; - bloom.r += bloomOverdrive.g * 0.5f; - bloom.r += bloomOverdrive.b * 0.5f; - bloom.g += bloomOverdrive.r * 0.5f; - bloom.g += bloomOverdrive.b * 0.5f; - bloom.b += bloomOverdrive.r * 0.5f; - bloom.b += bloomOverdrive.g * 0.5f; + bloom.r += bloomOverdrive.g * 0.5f; + bloom.r += bloomOverdrive.b * 0.5f; + bloom.g += bloomOverdrive.r * 0.5f; + bloom.g += bloomOverdrive.b * 0.5f; + bloom.b += bloomOverdrive.r * 0.5f; + bloom.b += bloomOverdrive.g * 0.5f; - vec2 NoiseCoord = vTexCoord; - vec3 NoiseFactor = GetNoiseFactor(bloom, random(NoiseCoord)); + vec2 NoiseCoord = vTexCoord; + vec3 NoiseFactor = GetNoiseFactor(bloom, random(NoiseCoord)); - blend = texel + bloom * NoiseFactor; - } + blend = texel + bloom * NoiseFactor; + } - // darken - else - { - texelA = min(texel, texelA); - texelB = min(texel, texelB); - texelC = min(texel, texelC); - texelD = min(texel, texelD); - texelE = min(texel, texelE); - texelF = min(texel, texelF); - texelG = min(texel, texelG); - texelH = min(texel, texelH); + // darken + else + { + texelA = min(texel, texelA); + texelB = min(texel, texelB); + texelC = min(texel, texelC); + texelD = min(texel, texelD); + texelE = min(texel, texelE); + texelF = min(texel, texelF); + texelG = min(texel, texelG); + texelH = min(texel, texelH); - blend = texel * params.Level0Weight; - blend = mix(blend, texelA, params.Level1Weight * params.BloomScale); - blend = mix(blend, texelB, params.Level2Weight * params.BloomScale); - blend = mix(blend, texelC, params.Level3Weight * params.BloomScale); - blend = mix(blend, texelD, params.Level4Weight * params.BloomScale); - blend = mix(blend, texelE, params.Level5Weight * params.BloomScale); - blend = mix(blend, texelF, params.Level6Weight * params.BloomScale); - blend = mix(blend, texelG, params.Level7Weight * params.BloomScale); - blend = mix(blend, texelH, params.Level8Weight * params.BloomScale); - } + blend = texel * Level0Weight; + blend = mix(blend, texelA, Level1Weight * BloomScale); + blend = mix(blend, texelB, Level2Weight * BloomScale); + blend = mix(blend, texelC, Level3Weight * BloomScale); + blend = mix(blend, texelD, Level4Weight * BloomScale); + blend = mix(blend, texelE, Level5Weight * BloomScale); + blend = mix(blend, texelF, Level6Weight * BloomScale); + blend = mix(blend, texelG, Level7Weight * BloomScale); + blend = mix(blend, texelH, Level8Weight * BloomScale); + } - FragColor = vec4(blend, 1.0); + FragColor = vec4(blend, 1.0); + } } diff --git a/test/nonfunctional/shaders/mame/mame_chroma.slang b/test/nonfunctional/shaders/mame/mame_chroma.slang index 6740c5d..61cd58b 100644 --- a/test/nonfunctional/shaders/mame/mame_chroma.slang +++ b/test/nonfunctional/shaders/mame/mame_chroma.slang @@ -14,10 +14,7 @@ layout(push_constant) uniform Push uint FrameCount; } params; -layout(std140, set = 0, binding = 0) uniform UBO -{ - mat4 MVP; -} global; +#include "mame_parameters.inc" #pragma stage vertex layout(location = 0) in vec4 Position; @@ -38,10 +35,10 @@ layout(set = 0, binding = 2) uniform sampler2D Source; #define DiffuseSampler Source #define mul(a,b) (b*a) -const vec3 YGain = vec3(0.2126, 0.7152, 0.0722); -const vec2 ChromaA = vec2(0.630, 0.340); -const vec2 ChromaB = vec2(0.310, 0.595); -const vec2 ChromaC = vec2(0.155, 0.070); +vec3 YGain = vec3(global.ygain_r, global.ygain_g, global.ygain_b); +vec2 ChromaA = vec2(global.chromaa_x, global.chromaa_y); +vec2 ChromaB = vec2(global.chromab_x, global.chromab_y); +vec2 ChromaC = vec2(global.chromac_x, global.chromac_y); const mat3 XYZ_TO_sRGB = mat3( 3.2406, -1.5372, -0.4986, @@ -50,15 +47,23 @@ const mat3 XYZ_TO_sRGB = mat3( void main() { - vec4 cin = texture(DiffuseSampler, vTexCoord); - vec4 cout = vec4(0.0, 0.0, 0.0, cin.a); - mat3x2 xy = { ChromaA, ChromaB, ChromaC }; + if(!Chromaticity) + { + FragColor = texture(Source, vTexCoord); + return; + } + else + { + vec4 cin = texture(DiffuseSampler, vTexCoord); + vec4 cout = vec4(0.0, 0.0, 0.0, cin.a); + mat3x2 xy = { ChromaA, ChromaB, ChromaC }; - for (int i = 0; i < 3; ++i) { - float Y = YGain[i] * cin[i]; - float X = xy[i].x * (Y / xy[i].y); - float Z = (1.0 - xy[i].x - xy[i].y) * (Y / xy[i].y); - cout.rgb += mul(XYZ_TO_sRGB, vec3(X, Y, Z)); - } - FragColor = cout; + for (int i = 0; i < 3; ++i) { + float Y = YGain[i] * cin[i]; + float X = xy[i].x * (Y / xy[i].y); + float Z = (1.0 - xy[i].x - xy[i].y) * (Y / xy[i].y); + cout.rgb += mul(XYZ_TO_sRGB, vec3(X, Y, Z)); + } + FragColor = cout; + } } diff --git a/test/nonfunctional/shaders/mame/mame_color.slang b/test/nonfunctional/shaders/mame/mame_color.slang index 5b08a8b..3a50e9d 100644 --- a/test/nonfunctional/shaders/mame/mame_color.slang +++ b/test/nonfunctional/shaders/mame/mame_color.slang @@ -12,33 +12,9 @@ layout(push_constant) uniform Push vec4 OriginalSize; vec4 OutputSize; uint FrameCount; - float col_red; - float col_grn; - float col_blu; - float col_offset_x; - float col_offset_y; - float col_offset_z; - float col_scale_x; - float col_scale_y; - float col_scale_z; - float col_saturation; } params; -#pragma parameter col_red "Red Shift" 1.0 0.0 1.0 0.01 -#pragma parameter col_grn "Green Shift" 1.0 0.0 1.0 0.01 -#pragma parameter col_blu "Blue Shift" 1.0 0.0 1.0 0.01 -#pragma parameter col_offset_x "Offset X" 0.0 0.0 1.0 0.01 -#pragma parameter col_offset_y "Offset Y" 0.0 0.0 1.0 0.01 -#pragma parameter col_offset_z "Offset Z" 0.0 0.0 1.0 0.01 -#pragma parameter col_scale_x "Scale X" 1.0 0.0 1.0 0.01 -#pragma parameter col_scale_y "Scale Y" 1.0 0.0 1.0 0.01 -#pragma parameter col_scale_z "Scale Z" 1.0 0.0 1.0 0.01 -#pragma parameter col_saturation "Saturation" 1.0 0.0 0.01 - -layout(std140, set = 0, binding = 0) uniform UBO -{ - mat4 MVP; -} global; +#include "mame_parameters.inc" #pragma stage vertex layout(location = 0) in vec4 Position; @@ -58,12 +34,12 @@ layout(set = 0, binding = 2) uniform sampler2D Source; #define DiffuseSampler Source -vec3 RedRatios = vec3(params.col_red, 0.0f, 0.0f); -vec3 GrnRatios = vec3(0.0f, params.col_grn, 0.0f); -vec3 BluRatios = vec3(0.0f, 0.0f, params.col_blu); -vec3 Offset = vec3(params.col_offset_x, params.col_offset_y, params.col_offset_z); -vec3 Scale = vec3(params.col_scale_x, params.col_scale_y, params.col_scale_z); -float Saturation = params.col_saturation; +vec3 RedRatios = vec3(global.col_red, 0.0f, 0.0f); +vec3 GrnRatios = vec3(0.0f, global.col_grn, 0.0f); +vec3 BluRatios = vec3(0.0f, 0.0f, global.col_blu); +vec3 Offset = vec3(global.col_offset_x, global.col_offset_y, global.col_offset_z); +vec3 Scale = vec3(global.col_scale_x, global.col_scale_y, global.col_scale_z); +float Saturation = global.col_saturation; void main() { diff --git a/test/nonfunctional/shaders/mame/mame_deconverge.slang b/test/nonfunctional/shaders/mame/mame_deconverge.slang index b51a080..e3a3905 100644 --- a/test/nonfunctional/shaders/mame/mame_deconverge.slang +++ b/test/nonfunctional/shaders/mame/mame_deconverge.slang @@ -12,42 +12,15 @@ layout(push_constant) uniform Push vec4 OriginalSize; vec4 OutputSize; uint FrameCount; - float converge_x_r; - float converge_x_g; - float converge_x_b; - float converge_y_r; - float converge_y_g; - float converge_y_b; - float radial_conv_x_r; - float radial_conv_x_g; - float radial_conv_x_b; - float radial_conv_y_r; - float radial_conv_y_g; - float radial_conv_y_b; + } params; -#pragma parameter converge_x_r "Convergence X Red" 0.0 -100.0 100.0 0.5 -#pragma parameter converge_x_g "Convergence X Green" 0.0 -100.0 100.0 0.5 -#pragma parameter converge_x_b "Convergence X Blue" 0.0 -100.0 100.0 0.5 -#pragma parameter converge_y_r "Convergence Y Red" 0.0 -100.0 100.0 0.5 -#pragma parameter converge_y_g "Convergence Y Green" 0.0 -100.0 100.0 0.5 -#pragma parameter converge_y_b "Convergence Y Blue" 0.0 -100.0 100.0 0.5 -#pragma parameter radial_conv_x_r "Radial Conv X Red" 0.0 -100.0 100.0 0.5 -#pragma parameter radial_conv_x_g "Radial Conv X Green" 0.0 -100.0 100.0 0.5 -#pragma parameter radial_conv_x_b "Radial Conv X Blue" 0.0 -100.0 100.0 0.5 -#pragma parameter radial_conv_y_r "Radial Conv Y Red" 0.0 -100.0 100.0 0.5 -#pragma parameter radial_conv_y_g "Radial Conv Y Green" 0.0 -100.0 100.0 0.5 -#pragma parameter radial_conv_y_b "Radial Conv Y Blue" 0.0 -100.0 100.0 0.5 +#include "mame_parameters.inc" -layout(std140, set = 0, binding = 0) uniform UBO -{ - mat4 MVP; -} global; - -vec3 ConvergeX = vec3(params.converge_x_r, params.converge_x_g, params.converge_x_b); -vec3 ConvergeY = vec3(params.converge_y_r, params.converge_y_g, params.converge_y_b); -vec3 RadialConvergeX = vec3(params.radial_conv_x_r, params.radial_conv_x_g, params.radial_conv_x_b); -vec3 RadialConvergeY = vec3(params.radial_conv_y_r, params.radial_conv_y_g, params.radial_conv_y_b); +vec3 ConvergeX = vec3(global.converge_x_r, global.converge_x_g, global.converge_x_b); +vec3 ConvergeY = vec3(global.converge_y_r, global.converge_y_g, global.converge_y_b); +vec3 RadialConvergeX = vec3(global.radial_conv_x_r, global.radial_conv_x_g, global.radial_conv_x_b); +vec3 RadialConvergeY = vec3(global.radial_conv_y_r, global.radial_conv_y_g, global.radial_conv_y_b); #pragma stage vertex layout(location = 0) in vec4 Position; diff --git a/test/nonfunctional/shaders/mame/mame_distortion.slang b/test/nonfunctional/shaders/mame/mame_distortion.slang index 74b1f4b..0345368 100644 --- a/test/nonfunctional/shaders/mame/mame_distortion.slang +++ b/test/nonfunctional/shaders/mame/mame_distortion.slang @@ -12,43 +12,14 @@ layout(push_constant) uniform Push vec4 OriginalSize; vec4 OutputSize; uint FrameCount; - float distortion_amount; - float cubic_distortion_amount; - float distort_corner_amount; - float round_corner_amount; - float smooth_border_amount; - float vignette_amount; - float reflection_amount; - float reflection_col_r; - float reflection_col_g; - float reflection_col_b; - float swapxy; - float target_scale; } params; -#pragma parameter distortion_amount "Distortion Amount" 0.0 0.0 1.0 0.01 -#pragma parameter cubic_distortion_amount "Cubic Dist. Amt" 0.0 0.0 1.0 0.01 -#pragma parameter distort_corner_amount "Corner Dist. Amt" 0.0 0.0 1.0 0.01 -#pragma parameter round_corner_amount "Corner Rounding" 0.0 0.0 1.0 0.01 -#pragma parameter smooth_border_amount "Border Smoothing" 0.0 0.0 1.0 0.01 -#pragma parameter vignette_amount "Vignetting Amount" 0.0 0.0 1.0 0.01 -#pragma parameter reflection_amount "Reflection Amount" 0.0 0.0 1.0 0.01 -#pragma parameter reflection_col_r "Reflection Color R" 1.0 0.0 1.0 0.01 -#pragma parameter reflection_col_g "Reflection Color G" 0.9 0.0 1.0 0.01 -#pragma parameter reflection_col_b "Reflection Color B" 0.8 0.0 1.0 0.01 - -#pragma parameter swapxy "Swap X and Y" 0.0 0.0 1.0 1.0 -#pragma parameter target_scale "Target Scale" 1.0 1.0 10.0 1.0 +#include "mame_parameters.inc" #define saturate(c) clamp(c, 0.0, 1.0) #define mul(a,b) (b*a) const int ScreenCount = 1; -layout(std140, set = 0, binding = 0) uniform UBO -{ - mat4 MVP; -} global; - //----------------------------------------------------------------------------- // Constants //----------------------------------------------------------------------------- @@ -103,19 +74,18 @@ layout(set = 0, binding = 2) uniform sampler2D Source; #define DiffuseSampler Source -float DistortionAmount = params.distortion_amount; // k - quartic distortion coefficient -float CubicDistortionAmount = params.cubic_distortion_amount; // kcube - cubic distortion modifier -float DistortCornerAmount = params.distort_corner_amount; -float RoundCornerAmount = params.round_corner_amount; -float SmoothBorderAmount = params.smooth_border_amount; -float VignettingAmount = params.vignette_amount; -float ReflectionAmount = params.reflection_amount; -vec3 LightReflectionColor = vec3(params.reflection_col_r, params.reflection_col_g, params.reflection_col_b); // color temperature 5.000 Kelvin +float DistortionAmount = global.distortion_amount; // k - quartic distortion coefficient +float CubicDistortionAmount = global.cubic_distortion_amount; // kcube - cubic distortion modifier +float DistortCornerAmount = global.distort_corner_amount; +float RoundCornerAmount = global.round_corner_amount; +float SmoothBorderAmount = global.smooth_border_amount; +float VignettingAmount = global.vignette_amount; +float ReflectionAmount = global.reflection_amount; +vec3 LightReflectionColor = vec3(global.reflection_col_r, global.reflection_col_g, global.reflection_col_b); // color temperature 5.000 Kelvin -bool SwapXY = bool(params.swapxy); vec2 QuadDims = params.SourceSize.xy; -vec2 TargetDims = params.SourceSize.xy; -float TargetScale = params.target_scale; +vec2 TargetDims = params.OutputSize.xy; +float TargetScale = 1.0; float GetNoiseFactor(vec3 n, float random) { @@ -242,73 +212,81 @@ vec2 GetQuadCoords(vec2 coord, vec2 scale, float distortionAmount, float cubicDi void main() { - // image distortion - float distortionAmount = DistortionAmount; - float cubicDistortionAmount = CubicDistortionAmount > 0.0f - ? CubicDistortionAmount * 1.1f // cubic distortion need to be a little higher to compensate the quartic distortion - : CubicDistortionAmount * 1.2f; // negativ values even more + if(!Distortion) + { + FragColor = texture(Source, vTexCoord); + return; + } + else + { + // image distortion + float distortionAmount = DistortionAmount; + float cubicDistortionAmount = CubicDistortionAmount > 0.0f + ? CubicDistortionAmount * 1.1f // cubic distortion need to be a little higher to compensate the quartic distortion + : CubicDistortionAmount * 1.2f; // negativ values even more - // corner distortion at least by the amount of the image distorition - float distortCornerAmount = max(DistortCornerAmount, DistortionAmount + CubicDistortionAmount); + // corner distortion at least by the amount of the image distorition + float distortCornerAmount = max(DistortCornerAmount, DistortionAmount + CubicDistortionAmount); - float roundCornerAmount = RoundCornerAmount * 0.5f; - float smoothBorderAmount = SmoothBorderAmount * 0.5f; + float roundCornerAmount = RoundCornerAmount * 0.5f; + float smoothBorderAmount = SmoothBorderAmount * 0.5f; - vec2 TexelDims = 1.0f / TargetDims; + vec2 TexelDims = 1.0f / TargetDims; - // base-target dimensions (without oversampling) - vec2 BaseTargetDims = TargetDims / TargetScale; - BaseTargetDims = SwapXY - ? BaseTargetDims.yx - : BaseTargetDims.xy; + // base-target dimensions (without oversampling) + vec2 BaseTargetDims = TargetDims / TargetScale; + BaseTargetDims = SwapXY + ? BaseTargetDims.yx + : BaseTargetDims.xy; - // base-target/quad difference scale - vec2 BaseTargetQuadScale = (ScreenCount == 1) - ? BaseTargetDims / QuadDims // keeps the coords inside of the quad bounds of a single screen - : vec2(1.0); + // base-target/quad difference scale + vec2 BaseTargetQuadScale = (ScreenCount == 1) + ? BaseTargetDims / QuadDims // keeps the coords inside of the quad bounds of a single screen + : vec2(1.0); - // Screen Texture Curvature - vec2 BaseCoord = GetTextureCoords(vTexCoord, distortionAmount, cubicDistortionAmount); + // Screen Texture Curvature + vec2 BaseCoord = GetTextureCoords(vTexCoord, distortionAmount, cubicDistortionAmount); - // Screen Quad Curvature - vec2 QuadCoord = GetQuadCoords(vTexCoord, BaseTargetQuadScale, distortCornerAmount, 0.0f); -/* - // clip border - if (BaseCoord.x < 0.0f - TexelDims.x || BaseCoord.y < 0.0f - TexelDims.y || - BaseCoord.x > 1.0f + TexelDims.x || BaseCoord.y > 1.0f + TexelDims.y) - { - // we don't use the clip function, because we don't clear the render target before - return vec4(0.0f, 0.0f, 0.0f, 1.0f); - } -*/ + // Screen Quad Curvature + vec2 QuadCoord = GetQuadCoords(vTexCoord, BaseTargetQuadScale, distortCornerAmount, 0.0f); + /* + // clip border + if (BaseCoord.x < 0.0f - TexelDims.x || BaseCoord.y < 0.0f - TexelDims.y || + BaseCoord.x > 1.0f + TexelDims.x || BaseCoord.y > 1.0f + TexelDims.y) + { + // we don't use the clip function, because we don't clear the render target before + return vec4(0.0f, 0.0f, 0.0f, 1.0f); + } + */ - // Color - vec4 BaseColor = texture(DiffuseSampler, BaseCoord); - BaseColor.a = 1.0f; + // Color + vec4 BaseColor = texture(DiffuseSampler, BaseCoord); + BaseColor.a = 1.0f; - // Vignetting Simulation - vec2 VignetteCoord = QuadCoord; + // Vignetting Simulation + vec2 VignetteCoord = QuadCoord; - float VignetteFactor = GetVignetteFactor(VignetteCoord, VignettingAmount); - BaseColor.rgb *= VignetteFactor; + float VignetteFactor = GetVignetteFactor(VignetteCoord, VignettingAmount); + BaseColor.rgb *= VignetteFactor; - // Light Reflection Simulation - vec2 SpotCoord = QuadCoord; + // Light Reflection Simulation + vec2 SpotCoord = QuadCoord; - vec3 SpotAddend = GetSpotAddend(SpotCoord, ReflectionAmount) * LightReflectionColor; - BaseColor.rgb += SpotAddend * GetNoiseFactor(SpotAddend, random(SpotCoord)); + vec3 SpotAddend = GetSpotAddend(SpotCoord, ReflectionAmount) * LightReflectionColor; + BaseColor.rgb += SpotAddend * GetNoiseFactor(SpotAddend, random(SpotCoord)); - // Round Corners Simulation - vec2 RoundCornerCoord = QuadCoord; - vec2 RoundCornerBounds = (ScreenCount == 1) - ? QuadDims // align corners to quad bounds of a single screen - : BaseTargetDims; // align corners to target bounds of multiple screens - RoundCornerBounds = SwapXY - ? RoundCornerBounds.yx - : RoundCornerBounds.xy; + // Round Corners Simulation + vec2 RoundCornerCoord = QuadCoord; + vec2 RoundCornerBounds = (ScreenCount == 1) + ? QuadDims // align corners to quad bounds of a single screen + : BaseTargetDims; // align corners to target bounds of multiple screens + RoundCornerBounds = SwapXY + ? RoundCornerBounds.yx + : RoundCornerBounds.xy; - float roundCornerFactor = GetBoundsFactor(RoundCornerCoord, RoundCornerBounds, roundCornerAmount, smoothBorderAmount); - BaseColor.rgb *= roundCornerFactor; + float roundCornerFactor = GetBoundsFactor(RoundCornerCoord, RoundCornerBounds, roundCornerAmount, smoothBorderAmount); + BaseColor.rgb *= roundCornerFactor; - FragColor = BaseColor; + FragColor = BaseColor; + } } diff --git a/test/nonfunctional/shaders/mame/mame_focus.slang b/test/nonfunctional/shaders/mame/mame_focus.slang index 4ad9350..d1ac42a 100644 --- a/test/nonfunctional/shaders/mame/mame_focus.slang +++ b/test/nonfunctional/shaders/mame/mame_focus.slang @@ -12,17 +12,9 @@ layout(push_constant) uniform Push vec4 OriginalSize; vec4 OutputSize; uint FrameCount; - float defocus_x; - float defocus_y; } params; -#pragma parameter defocus_x "Defocus X Axis" 0.0 0.0 10.0 0.1 -#pragma parameter defocus_y "Defocus Y Axis" 0.0 0.0 10.0 0.1 - -layout(std140, set = 0, binding = 0) uniform UBO -{ - mat4 MVP; -} global; +#include "mame_parameters.inc" #pragma stage vertex layout(location = 0) in vec4 Position; @@ -42,7 +34,7 @@ layout(set = 0, binding = 2) uniform sampler2D Source; #define DiffuseSampler Source -vec2 Defocus = vec2(params.defocus_x, params.defocus_y); +vec2 Defocus = vec2(global.defocus_x, global.defocus_y); // previously this pass was applied two times with offsets of 0.25, 0.5, 0.75, 1.0 // now this pass is applied only once with offsets of 0.25, 0.55, 1.0, 1.6 to achieve the same appearance as before till a maximum defocus of 2.0 diff --git a/test/nonfunctional/shaders/mame/mame_hlsl.slangp b/test/nonfunctional/shaders/mame/mame_hlsl.slangp new file mode 100644 index 0000000..3b44814 --- /dev/null +++ b/test/nonfunctional/shaders/mame/mame_hlsl.slangp @@ -0,0 +1,66 @@ +# info on how the passes come together can be found in mame/src/osd/modules/render/d3d/d3dhlsl.cpp +shaders = 12 + +shader0 = mame_ntsc.slang +filter_linear0 = true +alias0 = NTSCPass +scale_type0 = source +scale0 = 1.0 + +shader1 = mame_color.slang +alias1 = ColorPass +scale_type1 = source +scale1 = 1.0 +filter_linear1 = true + +shader2 = ../../../../retro/shaders/sharp-bilinear.slang +alias2 = PrescalePass +scale_type2 = source +filter_linear2 = true + +shader3 = mame_deconverge.slang +alias3 = DeconvergePass +filter_linear3 = true + +shader4 = mame_scanline.slang +alias4 = ScanlinePass +filter_linear4 = true +scale_type4 = source +scale4 = 4.0 + +shader5 = mame_focus.slang +alias5 = FocusPass +filter_linear5 = true + +shader6 = mame_phosphor.slang +alias6 = PhosphorPass +filter_linear6 = true + +shader7 = mame_post.slang +alias7 = PostPass +filter_linear7 = true + +shader8 = mame_chroma.slang +alias8 = ChromaPass +filter_linear8 = true + +shader9 = mame_downsample.slang +alias9 = DownsamplePass +filter_linear9 = true +mipmap_input9 = true + +shader10 = mame_bloom.slang +alias10 = BloomPass +filter_linear10 = true + +shader11 = mame_distortion.slang +alias11 = DistortionPass +filter_linear11 = true + +shader12 = mame_vector.slang +alias12 = VectorPass +filter_linear12 = true + +# mame's textures are available here: https://github.com/mamedev/mame/tree/master/artwork +textures = "MaskTexture" +MaskTexture = slot-mask.png \ No newline at end of file diff --git a/test/nonfunctional/shaders/mame/mame_ntsc.slang b/test/nonfunctional/shaders/mame/mame_ntsc.slang new file mode 100644 index 0000000..0748037 --- /dev/null +++ b/test/nonfunctional/shaders/mame/mame_ntsc.slang @@ -0,0 +1,221 @@ +#version 450 + +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz,ImJezze +//----------------------------------------------------------------------------- +// NTSC Effect +//----------------------------------------------------------------------------- + +layout(push_constant) uniform Push +{ + vec4 SourceSize; + vec4 OriginalSize; + vec4 OutputSize; + uint FrameCount; +} params; + +#include "mame_parameters.inc" + +//----------------------------------------------------------------------------- +// Constants +//----------------------------------------------------------------------------- + +const float PI = 3.1415927f; +const float PI2 = PI * 2.0f; + +const vec4 YDot = vec4(0.299f, 0.587f, 0.114f, 0.0f); +const vec4 IDot = vec4(0.595716f, -0.274453f, -0.321263f, 0.0f); +const vec4 QDot = vec4(0.211456f, -0.522591f, 0.311135f, 0.0f); + +const vec3 RDot = vec3(1.0f, 0.956f, 0.621f); +const vec3 GDot = vec3(1.0f, -0.272f, -0.647f); +const vec3 BDot = vec3(1.0f, -1.106f, 1.703f); + +const vec4 OffsetX = vec4(0.0f, 0.25f, 0.50f, 0.75f); +const vec4 NotchOffset = vec4(0.0f, 1.0f, 2.0f, 3.0f); + +const int SampleCount = 64; +const int HalfSampleCount = SampleCount / 2; + +#pragma stage vertex +layout(location = 0) in vec4 Position; +layout(location = 1) in vec2 TexCoord; +layout(location = 0) out vec2 vTexCoord; + +void main() +{ + gl_Position = global.MVP * Position; + vTexCoord = TexCoord; +} + +#pragma stage fragment +layout(location = 0) in vec2 vTexCoord; +layout(location = 0) out vec4 FragColor; +layout(set = 0, binding = 2) uniform sampler2D Source; + +#define DiffuseSampler Source +#define SourceDims params.SourceSize.xy + +float AValue = global.avalue; +float BValue = global.bvalue; +float CCValue = global.ccvalue; +float OValue = global.ovalue; +float PValue = global.pvalue; +float ScanTime = global.scantime; + +float NotchHalfWidth = global.notchhalfwidth; +float YFreqResponse = global.yfreqresponse; +float IFreqResponse = global.ifreqresponse; +float QFreqResponse = global.qfreqresponse; + +float SignalOffset = global.signaloffset; + +vec4 GetCompositeYIQ(vec2 coord) +{ + vec2 PValueSourceTexel = vec2(PValue / SourceDims.x, 0.0f); + + vec2 C0 = coord + PValueSourceTexel * OffsetX.x; + vec2 C1 = coord + PValueSourceTexel * OffsetX.y; + vec2 C2 = coord + PValueSourceTexel * OffsetX.z; + vec2 C3 = coord + PValueSourceTexel * OffsetX.w; + vec4 Cx = vec4(C0.x, C1.x, C2.x, C3.x); + vec4 Cy = vec4(C0.y, C1.y, C2.y, C3.y); + vec4 Texel0 = texture(DiffuseSampler, C0); + vec4 Texel1 = texture(DiffuseSampler, C1); + vec4 Texel2 = texture(DiffuseSampler, C2); + vec4 Texel3 = texture(DiffuseSampler, C3); + + vec4 HPosition = Cx; + vec4 VPosition = Cy; + + vec4 Y = vec4(dot(Texel0, YDot), dot(Texel1, YDot), dot(Texel2, YDot), dot(Texel3, YDot)); + vec4 I = vec4(dot(Texel0, IDot), dot(Texel1, IDot), dot(Texel2, IDot), dot(Texel3, IDot)); + vec4 Q = vec4(dot(Texel0, QDot), dot(Texel1, QDot), dot(Texel2, QDot), dot(Texel3, QDot)); + + float W = PI2 * CCValue * ScanTime; + float WoPI = W / PI; + + float HOffset = (BValue + SignalOffset) / WoPI; + float VScale = (AValue * SourceDims.y) / WoPI; + + vec4 T = HPosition + HOffset + VPosition * VScale; + vec4 TW = T * W; + + vec4 CompositeYIQ = Y + I * cos(TW) + Q * sin(TW); + + return CompositeYIQ; +} + +void main() +{ + if(!NTSCSignal) + { + FragColor = texture(DiffuseSampler, vTexCoord); + return; + } + else + { + vec4 BaseTexel = texture(DiffuseSampler, vTexCoord); + + float TimePerSample = ScanTime / (SourceDims.x * 4.0f); + + float Fc_y1 = (CCValue - NotchHalfWidth) * TimePerSample; + float Fc_y2 = (CCValue + NotchHalfWidth) * TimePerSample; + float Fc_y3 = YFreqResponse * TimePerSample; + float Fc_i = IFreqResponse * TimePerSample; + float Fc_q = QFreqResponse * TimePerSample; + float Fc_i_2 = Fc_i * 2.0f; + float Fc_q_2 = Fc_q * 2.0f; + float Fc_y1_2 = Fc_y1 * 2.0f; + float Fc_y2_2 = Fc_y2 * 2.0f; + float Fc_y3_2 = Fc_y3 * 2.0f; + float Fc_i_pi2 = Fc_i * PI2; + float Fc_q_pi2 = Fc_q * PI2; + float Fc_y1_pi2 = Fc_y1 * PI2; + float Fc_y2_pi2 = Fc_y2 * PI2; + float Fc_y3_pi2 = Fc_y3 * PI2; + float PI2Length = PI2 / SampleCount; + + float W = PI2 * CCValue * ScanTime; + float WoPI = W / PI; + + float HOffset = (BValue + SignalOffset) / WoPI; + float VScale = (AValue * SourceDims.y) / WoPI; + + vec4 YAccum = vec4(0.0); + vec4 IAccum = vec4(0.0); + vec4 QAccum = vec4(0.0); + + vec4 Cy = vTexCoord.yyyy; + vec4 VPosition = Cy; + + for (float i = 0; i < SampleCount; i += 4.0f) + { + float n = i - HalfSampleCount; + vec4 n4 = n + NotchOffset; + + vec4 Cx = vTexCoord.x + (n4 * 0.25f) / SourceDims.x; + vec4 HPosition = Cx; + + vec4 C = GetCompositeYIQ(vec2(Cx.r, Cy.r)); + + vec4 T = HPosition + HOffset + VPosition * VScale; + vec4 WT = W * T + OValue; + + vec4 SincKernel = 0.54f + 0.46f * cos(PI2Length * n4); + + vec4 SincYIn1 = Fc_y1_pi2 * n4; + vec4 SincYIn2 = Fc_y2_pi2 * n4; + vec4 SincYIn3 = Fc_y3_pi2 * n4; + vec4 SincIIn = Fc_i_pi2 * n4; + vec4 SincQIn = Fc_q_pi2 * n4; + + vec4 SincY1, SincY2, SincY3; + + SincY1.x = (SincYIn1.x != 0.0f) ? sin(SincYIn1.x) / SincYIn1.x : 1.0f; + SincY1.y = (SincYIn1.y != 0.0f) ? sin(SincYIn1.y) / SincYIn1.y : 1.0f; + SincY1.z = (SincYIn1.z != 0.0f) ? sin(SincYIn1.z) / SincYIn1.z : 1.0f; + SincY1.w = (SincYIn1.w != 0.0f) ? sin(SincYIn1.w) / SincYIn1.w : 1.0f; + SincY2.x = (SincYIn2.x != 0.0f) ? sin(SincYIn2.x) / SincYIn2.x : 1.0f; + SincY2.y = (SincYIn2.y != 0.0f) ? sin(SincYIn2.y) / SincYIn2.y : 1.0f; + SincY2.z = (SincYIn2.z != 0.0f) ? sin(SincYIn2.z) / SincYIn2.z : 1.0f; + SincY2.w = (SincYIn2.w != 0.0f) ? sin(SincYIn2.w) / SincYIn2.w : 1.0f; + SincY3.x = (SincYIn3.x != 0.0f) ? sin(SincYIn3.x) / SincYIn3.x : 1.0f; + SincY3.y = (SincYIn3.y != 0.0f) ? sin(SincYIn3.y) / SincYIn3.y : 1.0f; + SincY3.z = (SincYIn3.z != 0.0f) ? sin(SincYIn3.z) / SincYIn3.z : 1.0f; + SincY3.w = (SincYIn3.w != 0.0f) ? sin(SincYIn3.w) / SincYIn3.w : 1.0f; + + vec4 IdealY, IdealI, IdealQ; + + IdealY = (Fc_y1_2 * SincY1 - Fc_y2_2 * SincY2) + Fc_y3_2 * SincY3; + IdealI.x = Fc_i_2 * (SincIIn.x != 0.0f ? sin(SincIIn.x) / SincIIn.x : 1.0f); + IdealI.y = Fc_i_2 * (SincIIn.y != 0.0f ? sin(SincIIn.y) / SincIIn.y : 1.0f); + IdealI.z = Fc_i_2 * (SincIIn.z != 0.0f ? sin(SincIIn.z) / SincIIn.z : 1.0f); + IdealI.w = Fc_i_2 * (SincIIn.w != 0.0f ? sin(SincIIn.w) / SincIIn.w : 1.0f); + IdealQ.x = Fc_q_2 * (SincQIn.x != 0.0f ? sin(SincQIn.x) / SincQIn.x : 1.0f); + IdealQ.y = Fc_q_2 * (SincQIn.y != 0.0f ? sin(SincQIn.y) / SincQIn.y : 1.0f); + IdealQ.z = Fc_q_2 * (SincQIn.z != 0.0f ? sin(SincQIn.z) / SincQIn.z : 1.0f); + IdealQ.w = Fc_q_2 * (SincQIn.w != 0.0f ? sin(SincQIn.w) / SincQIn.w : 1.0f); + + vec4 FilterY = SincKernel * IdealY; + vec4 FilterI = SincKernel * IdealI; + vec4 FilterQ = SincKernel * IdealQ; + + YAccum = YAccum + C * FilterY; + IAccum = IAccum + C * cos(WT) * FilterI; + QAccum = QAccum + C * sin(WT) * FilterQ; + } + + vec3 YIQ = vec3( + (YAccum.r + YAccum.g + YAccum.b + YAccum.a), + (IAccum.r + IAccum.g + IAccum.b + IAccum.a) * 2.0f, + (QAccum.r + QAccum.g + QAccum.b + QAccum.a) * 2.0f); + + vec3 RGB = vec3( + dot(YIQ, RDot), + dot(YIQ, GDot), + dot(YIQ, BDot)); + + FragColor = vec4(RGB, BaseTexel.a); + } +} \ No newline at end of file diff --git a/test/nonfunctional/shaders/mame/mame_ntsc.slang.ps.hlsl b/test/nonfunctional/shaders/mame/mame_ntsc.slang.ps.hlsl new file mode 100644 index 0000000..933096f --- /dev/null +++ b/test/nonfunctional/shaders/mame/mame_ntsc.slang.ps.hlsl @@ -0,0 +1,379 @@ +cbuffer global : register(b0) +{ + row_major float4x4 global_MVP : packoffset(c0); +}; +cbuffer params : register(b1) +{ + float4 params_SourceSize : packoffset(c0); + float4 params_OriginalSize : packoffset(c1); + float4 params_OutputSize : packoffset(c2); + uint params_FrameCount : packoffset(c3); + float params_avalue : packoffset(c3.y); + float params_bvalue : packoffset(c3.z); + float params_ccvalue : packoffset(c3.w); + float params_ovalue : packoffset(c4); + float params_pvalue : packoffset(c4.y); + float params_scantime : packoffset(c4.z); + float params_notchhalfwidth : packoffset(c4.w); + float params_yfreqresponse : packoffset(c5); + float params_ifreqresponse : packoffset(c5.y); + float params_qfreqresponse : packoffset(c5.z); + float params_signaloffset : packoffset(c5.w); + float params_ntscsignal : packoffset(c6); +}; +Texture2D Source : register(t2); +SamplerState _Source_sampler : register(s2); + +static float4 FragColor; +static float2 vTexCoord; + +struct SPIRV_Cross_Input +{ + float2 vTexCoord : TEXCOORD0; +}; + +struct SPIRV_Cross_Output +{ + float4 FragColor : SV_Target0; +}; + +static bool NTSCSignal; +static float AValue; +static float BValue; +static float CCValue; +static float OValue; +static float PValue; +static float ScanTime; +static float NotchHalfWidth; +static float YFreqResponse; +static float IFreqResponse; +static float QFreqResponse; +static float SignalOffset; + +float4 GetCompositeYIQ(float2 coord) +{ + float2 PValueSourceTexel = float2(PValue / params_SourceSize.x, 0.0f); + float2 C0 = coord + (PValueSourceTexel * 0.0f); + float2 C1 = coord + (PValueSourceTexel * 0.25f); + float2 C2 = coord + (PValueSourceTexel * 0.5f); + float2 C3 = coord + (PValueSourceTexel * 0.75f); + float4 Cx = float4(C0.x, C1.x, C2.x, C3.x); + float4 Cy = float4(C0.y, C1.y, C2.y, C3.y); + float4 Texel0 = Source.Sample(_Source_sampler, C0); + float4 Texel1 = Source.Sample(_Source_sampler, C1); + float4 Texel2 = Source.Sample(_Source_sampler, C2); + float4 Texel3 = Source.Sample(_Source_sampler, C3); + float4 HPosition = Cx; + float4 VPosition = Cy; + float4 Y = float4(dot(Texel0, float4(0.2989999949932098388671875f, 0.58700001239776611328125f, 0.114000000059604644775390625f, 0.0f)), dot(Texel1, float4(0.2989999949932098388671875f, 0.58700001239776611328125f, 0.114000000059604644775390625f, 0.0f)), dot(Texel2, float4(0.2989999949932098388671875f, 0.58700001239776611328125f, 0.114000000059604644775390625f, 0.0f)), dot(Texel3, float4(0.2989999949932098388671875f, 0.58700001239776611328125f, 0.114000000059604644775390625f, 0.0f))); + float4 I = float4(dot(Texel0, float4(0.595715999603271484375f, -0.2744530141353607177734375f, -0.3212629854679107666015625f, 0.0f)), dot(Texel1, float4(0.595715999603271484375f, -0.2744530141353607177734375f, -0.3212629854679107666015625f, 0.0f)), dot(Texel2, float4(0.595715999603271484375f, -0.2744530141353607177734375f, -0.3212629854679107666015625f, 0.0f)), dot(Texel3, float4(0.595715999603271484375f, -0.2744530141353607177734375f, -0.3212629854679107666015625f, 0.0f))); + float4 Q = float4(dot(Texel0, float4(0.211456000804901123046875f, -0.52259099483489990234375f, 0.311134994029998779296875f, 0.0f)), dot(Texel1, float4(0.211456000804901123046875f, -0.52259099483489990234375f, 0.311134994029998779296875f, 0.0f)), dot(Texel2, float4(0.211456000804901123046875f, -0.52259099483489990234375f, 0.311134994029998779296875f, 0.0f)), dot(Texel3, float4(0.211456000804901123046875f, -0.52259099483489990234375f, 0.311134994029998779296875f, 0.0f))); + float W = (6.283185482025146484375f * CCValue) * ScanTime; + float WoPI = W / 3.1415927410125732421875f; + float HOffset = (BValue + SignalOffset) / WoPI; + float VScale = (AValue * params_SourceSize.y) / WoPI; + float4 T = (HPosition + HOffset.xxxx) + (VPosition * VScale); + float4 TW = T * W; + float4 CompositeYIQ = (Y + (I * cos(TW))) + (Q * sin(TW)); + return CompositeYIQ; +} + +void frag_main() +{ + NTSCSignal = params_ntscsignal != 0.0f; + AValue = params_avalue; + BValue = params_bvalue; + CCValue = params_ccvalue; + OValue = params_ovalue; + PValue = params_pvalue; + ScanTime = params_scantime; + NotchHalfWidth = params_notchhalfwidth; + YFreqResponse = params_yfreqresponse; + IFreqResponse = params_ifreqresponse; + QFreqResponse = params_qfreqresponse; + SignalOffset = params_signaloffset; + if (!NTSCSignal) + { + FragColor = Source.Sample(_Source_sampler, vTexCoord); + return; + } + else + { + float4 BaseTexel = Source.Sample(_Source_sampler, vTexCoord); + float TimePerSample = ScanTime / (params_SourceSize.x * 4.0f); + float Fc_y1 = (CCValue - NotchHalfWidth) * TimePerSample; + float Fc_y2 = (CCValue + NotchHalfWidth) * TimePerSample; + float Fc_y3 = YFreqResponse * TimePerSample; + float Fc_i = IFreqResponse * TimePerSample; + float Fc_q = QFreqResponse * TimePerSample; + float Fc_i_2 = Fc_i * 2.0f; + float Fc_q_2 = Fc_q * 2.0f; + float Fc_y1_2 = Fc_y1 * 2.0f; + float Fc_y2_2 = Fc_y2 * 2.0f; + float Fc_y3_2 = Fc_y3 * 2.0f; + float Fc_i_pi2 = Fc_i * 6.283185482025146484375f; + float Fc_q_pi2 = Fc_q * 6.283185482025146484375f; + float Fc_y1_pi2 = Fc_y1 * 6.283185482025146484375f; + float Fc_y2_pi2 = Fc_y2 * 6.283185482025146484375f; + float Fc_y3_pi2 = Fc_y3 * 6.283185482025146484375f; + float PI2Length = 0.098174773156642913818359375f; + float W = (6.283185482025146484375f * CCValue) * ScanTime; + float WoPI = W / 3.1415927410125732421875f; + float HOffset = (BValue + SignalOffset) / WoPI; + float VScale = (AValue * params_SourceSize.y) / WoPI; + float4 YAccum = 0.0f.xxxx; + float4 IAccum = 0.0f.xxxx; + float4 QAccum = 0.0f.xxxx; + float4 Cy = vTexCoord.yyyy; + float4 VPosition = Cy; + for (float i = 0.0f; i < 64.0f; i += 4.0f) + { + float n = i - 32.0f; + float4 n4 = n.xxxx + float4(0.0f, 1.0f, 2.0f, 3.0f); + float4 Cx = vTexCoord.x.xxxx + ((n4 * 0.25f) / params_SourceSize.x.xxxx); + float4 HPosition = Cx; + float2 param = float2(Cx.x, Cy.x); + float4 C = GetCompositeYIQ(param); + float4 T = (HPosition + HOffset.xxxx) + (VPosition * VScale); + float4 WT = (T * W) + OValue.xxxx; + float4 SincKernel = 0.540000021457672119140625f.xxxx + (cos(n4 * PI2Length) * 0.4600000083446502685546875f); + float4 SincYIn1 = n4 * Fc_y1_pi2; + float4 SincYIn2 = n4 * Fc_y2_pi2; + float4 SincYIn3 = n4 * Fc_y3_pi2; + float4 SincIIn = n4 * Fc_i_pi2; + float4 SincQIn = n4 * Fc_q_pi2; + float _447; + if (SincYIn1.x != 0.0f) + { + _447 = sin(SincYIn1.x) / SincYIn1.x; + } + else + { + _447 = 1.0f; + } + float4 SincY1; + SincY1.x = _447; + float _462; + if (SincYIn1.y != 0.0f) + { + _462 = sin(SincYIn1.y) / SincYIn1.y; + } + else + { + _462 = 1.0f; + } + SincY1.y = _462; + float _478; + if (SincYIn1.z != 0.0f) + { + _478 = sin(SincYIn1.z) / SincYIn1.z; + } + else + { + _478 = 1.0f; + } + SincY1.z = _478; + float _494; + if (SincYIn1.w != 0.0f) + { + _494 = sin(SincYIn1.w) / SincYIn1.w; + } + else + { + _494 = 1.0f; + } + SincY1.w = _494; + float _510; + if (SincYIn2.x != 0.0f) + { + _510 = sin(SincYIn2.x) / SincYIn2.x; + } + else + { + _510 = 1.0f; + } + float4 SincY2; + SincY2.x = _510; + float _525; + if (SincYIn2.y != 0.0f) + { + _525 = sin(SincYIn2.y) / SincYIn2.y; + } + else + { + _525 = 1.0f; + } + SincY2.y = _525; + float _540; + if (SincYIn2.z != 0.0f) + { + _540 = sin(SincYIn2.z) / SincYIn2.z; + } + else + { + _540 = 1.0f; + } + SincY2.z = _540; + float _555; + if (SincYIn2.w != 0.0f) + { + _555 = sin(SincYIn2.w) / SincYIn2.w; + } + else + { + _555 = 1.0f; + } + SincY2.w = _555; + float _571; + if (SincYIn3.x != 0.0f) + { + _571 = sin(SincYIn3.x) / SincYIn3.x; + } + else + { + _571 = 1.0f; + } + float4 SincY3; + SincY3.x = _571; + float _586; + if (SincYIn3.y != 0.0f) + { + _586 = sin(SincYIn3.y) / SincYIn3.y; + } + else + { + _586 = 1.0f; + } + SincY3.y = _586; + float _601; + if (SincYIn3.z != 0.0f) + { + _601 = sin(SincYIn3.z) / SincYIn3.z; + } + else + { + _601 = 1.0f; + } + SincY3.z = _601; + float _616; + if (SincYIn3.w != 0.0f) + { + _616 = sin(SincYIn3.w) / SincYIn3.w; + } + else + { + _616 = 1.0f; + } + SincY3.w = _616; + float4 IdealY = ((SincY1 * Fc_y1_2) - (SincY2 * Fc_y2_2)) + (SincY3 * Fc_y3_2); + float _641 = Fc_i_2; + float _645; + if (SincIIn.x != 0.0f) + { + _645 = sin(SincIIn.x) / SincIIn.x; + } + else + { + _645 = 1.0f; + } + float4 IdealI; + IdealI.x = _641 * _645; + float _658 = Fc_i_2; + float _662; + if (SincIIn.y != 0.0f) + { + _662 = sin(SincIIn.y) / SincIIn.y; + } + else + { + _662 = 1.0f; + } + IdealI.y = _658 * _662; + float _675 = Fc_i_2; + float _679; + if (SincIIn.z != 0.0f) + { + _679 = sin(SincIIn.z) / SincIIn.z; + } + else + { + _679 = 1.0f; + } + IdealI.z = _675 * _679; + float _692 = Fc_i_2; + float _696; + if (SincIIn.w != 0.0f) + { + _696 = sin(SincIIn.w) / SincIIn.w; + } + else + { + _696 = 1.0f; + } + IdealI.w = _692 * _696; + float _710 = Fc_q_2; + float _714; + if (SincQIn.x != 0.0f) + { + _714 = sin(SincQIn.x) / SincQIn.x; + } + else + { + _714 = 1.0f; + } + float4 IdealQ; + IdealQ.x = _710 * _714; + float _727 = Fc_q_2; + float _731; + if (SincQIn.y != 0.0f) + { + _731 = sin(SincQIn.y) / SincQIn.y; + } + else + { + _731 = 1.0f; + } + IdealQ.y = _727 * _731; + float _744 = Fc_q_2; + float _748; + if (SincQIn.z != 0.0f) + { + _748 = sin(SincQIn.z) / SincQIn.z; + } + else + { + _748 = 1.0f; + } + IdealQ.z = _744 * _748; + float _761 = Fc_q_2; + float _765; + if (SincQIn.w != 0.0f) + { + _765 = sin(SincQIn.w) / SincQIn.w; + } + else + { + _765 = 1.0f; + } + IdealQ.w = _761 * _765; + float4 FilterY = SincKernel * IdealY; + float4 FilterI = SincKernel * IdealI; + float4 FilterQ = SincKernel * IdealQ; + YAccum += (C * FilterY); + IAccum += ((C * cos(WT)) * FilterI); + QAccum += ((C * sin(WT)) * FilterQ); + } + float3 YIQ = float3(((YAccum.x + YAccum.y) + YAccum.z) + YAccum.w, (((IAccum.x + IAccum.y) + IAccum.z) + IAccum.w) * 2.0f, (((QAccum.x + QAccum.y) + QAccum.z) + QAccum.w) * 2.0f); + float3 RGB = float3(dot(YIQ, float3(1.0f, 0.95599997043609619140625f, 0.620999991893768310546875f)), dot(YIQ, float3(1.0f, -0.272000014781951904296875f, -0.647000014781951904296875f)), dot(YIQ, float3(1.0f, -1.10599994659423828125f, 1.70299994945526123046875f))); + FragColor = float4(RGB, BaseTexel.w); + } +} + +SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input) +{ + vTexCoord = stage_input.vTexCoord; + frag_main(); + SPIRV_Cross_Output stage_output; + stage_output.FragColor = FragColor; + return stage_output; +} diff --git a/test/nonfunctional/shaders/mame/mame_ntsc.slang.vs.hlsl b/test/nonfunctional/shaders/mame/mame_ntsc.slang.vs.hlsl new file mode 100644 index 0000000..e796987 --- /dev/null +++ b/test/nonfunctional/shaders/mame/mame_ntsc.slang.vs.hlsl @@ -0,0 +1,60 @@ +cbuffer global : register(b0) +{ + row_major float4x4 global_MVP : packoffset(c0); +}; +cbuffer params : register(b1) +{ + float4 params_SourceSize : packoffset(c0); + float4 params_OriginalSize : packoffset(c1); + float4 params_OutputSize : packoffset(c2); + uint params_FrameCount : packoffset(c3); + float params_avalue : packoffset(c3.y); + float params_bvalue : packoffset(c3.z); + float params_ccvalue : packoffset(c3.w); + float params_ovalue : packoffset(c4); + float params_pvalue : packoffset(c4.y); + float params_scantime : packoffset(c4.z); + float params_notchhalfwidth : packoffset(c4.w); + float params_yfreqresponse : packoffset(c5); + float params_ifreqresponse : packoffset(c5.y); + float params_qfreqresponse : packoffset(c5.z); + float params_signaloffset : packoffset(c5.w); + float params_ntscsignal : packoffset(c6); +}; + +static float4 gl_Position; +static float4 Position; +static float2 vTexCoord; +static float2 TexCoord; + +struct SPIRV_Cross_Input +{ + float4 Position : TEXCOORD0; + float2 TexCoord : TEXCOORD1; +}; + +struct SPIRV_Cross_Output +{ + float2 vTexCoord : TEXCOORD0; + float4 gl_Position : SV_Position; +}; + +static bool NTSCSignal; + +void vert_main() +{ + NTSCSignal = params_ntscsignal != 0.0f; + gl_Position = mul(Position, global_MVP); + vTexCoord = TexCoord; +} + +SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input) +{ + Position = stage_input.Position; + TexCoord = stage_input.TexCoord; + vert_main(); + SPIRV_Cross_Output stage_output; + stage_output.gl_Position = gl_Position; + stage_output.vTexCoord = vTexCoord; + return stage_output; +} diff --git a/test/nonfunctional/shaders/mame/mame_parameters.inc b/test/nonfunctional/shaders/mame/mame_parameters.inc new file mode 100644 index 0000000..e75cbba --- /dev/null +++ b/test/nonfunctional/shaders/mame/mame_parameters.inc @@ -0,0 +1,295 @@ +layout(std140, set = 0, binding = 0) uniform UBO +{ + mat4 MVP; +// effect toggles and multi + float bloomtoggle; + float ntscsignal; + float scanlinetoggle; + float chromatoggle; + float distortiontoggle; + float screenscale_x; + float screenscale_y; + float screenoffset_x; + float screenoffset_y; + float swapxy; +// bloom params + float bloomblendmode; +// float vectorscreen; + float bloomscale; + float bloomoverdrive_r; + float bloomoverdrive_g; + float bloomoverdrive_b; + float level0weight; + float level1weight; + float level2weight; + float level3weight; + float level4weight; + float level5weight; + float level6weight; + float level7weight; + float level8weight; +// post params + float mask_width; + float mask_height; + float mask_offset_x; + float mask_offset_y; + float preparebloom; + float shadowtilemode; + float power_r; + float power_g; + float power_b; + float floor_r; + float floor_g; + float floor_b; + float chromamode; + float conversiongain_x; + float conversiongain_y; + float conversiongain_z; + float humbaralpha; + float backcolor_r; + float backcolor_g; + float backcolor_b; + float shadowalpha; + float shadowcount_x; + float shadowcount_y; + float shadowuv_x; + float shadowuv_y; +// ntsc params + float avalue; + float bvalue; + float ccvalue; + float ovalue; + float pvalue; + float scantime; + float notchhalfwidth; + float yfreqresponse; + float ifreqresponse; + float qfreqresponse; + float signaloffset; +// color params + float col_red; + float col_grn; + float col_blu; + float col_offset_x; + float col_offset_y; + float col_offset_z; + float col_scale_x; + float col_scale_y; + float col_scale_z; + float col_saturation; +// deconverge params + float converge_x_r; + float converge_x_g; + float converge_x_b; + float converge_y_r; + float converge_y_g; + float converge_y_b; + float radial_conv_x_r; + float radial_conv_x_g; + float radial_conv_x_b; + float radial_conv_y_r; + float radial_conv_y_g; + float radial_conv_y_b; +// scanline params + float scanlinealpha; + float scanlinescale; + float scanlineheight; + float scanlinevariation; + float scanlineoffset; + float scanlinebrightscale; + float scanlinebrightoffset; +// defocus params + float defocus_x; + float defocus_y; +// phosphor params + float deltatime; + float phosphor_r; + float phosphor_g; + float phosphor_b; + float phosphortoggle; +// chroma params + float ygain_r; + float ygain_g; + float ygain_b; + float chromaa_x; + float chromaa_y; + float chromab_x; + float chromab_y; + float chromac_x; + float chromac_y; +// distortion params + float distortion_amount; + float cubic_distortion_amount; + float distort_corner_amount; + float round_corner_amount; + float smooth_border_amount; + float vignette_amount; + float reflection_amount; + float reflection_col_r; + float reflection_col_g; + float reflection_col_b; +// vector params +// float timeratio; +// float timescale; +// float lengthratio; +// float lengthscale; +// float beamsmooth; +} global; + +// Effect Toggles and Settings Used In Multiple Passes +#pragma parameter ntscsignal "NTSC Signal Mode" 0.0 0.0 1.0 1.01.0 +bool NTSCSignal = bool(global.ntscsignal); +#pragma parameter scanlinetoggle "Scanline Toggle" 1.0 0.0 1.0 1.0 +bool ScanlineToggle = bool(global.scanlinetoggle); +#pragma parameter bloomtoggle "Bloom Enable" 0.0 0.0 1.0 1.0 +bool BloomToggle = bool(global.bloomtoggle); +#pragma parameter chromatoggle "Chromaticity Toggle" 0.0 0.0 1.0 1.0 +bool Chromaticity = bool(global.chromatoggle); +#pragma parameter distortiontoggle "Distortion Toggle" 0.0 0.0 1.0 1.0 +bool Distortion = bool(global.distortiontoggle); +#pragma parameter phosphortoggle "Phosphor Toggle" 0.0 0.0 1.0 1.0 +bool Passthrough = bool(global.phosphortoggle); +#pragma parameter screenscale_x "Screen Scale X" 1.0 0.5 3.0 0.01 +#pragma parameter screenscale_y "Screen Scale Y" 1.0 0.5 3.0 0.01 +vec2 ScreenScale = vec2(global.screenscale_x, global.screenscale_y); +//#pragma parameter vectorscreen "Vector Screen Mode" 0.0 0.0 1.0 1.0 // TODO/FIXME +const float vectorscreen = 0.0; +bool VectorScreen = bool(vectorscreen); + +#pragma parameter screenoffset_x "Screen Offset X" 0.0 -1.0 1.0 0.005 +#pragma parameter screenoffset_y "Screen Offset Y" 0.0 -1.0 1.0 0.005 +vec2 ScreenOffset = vec2(global.screenoffset_x, global.screenoffset_y); +#pragma parameter swapxy "Swap X and Y" 0.0 0.0 1.0 1.0 +bool SwapXY = bool(global.swapxy); + +// Bloom Pass +#pragma parameter bloomtoggle "Bloom Enable" 0.0 0.0 1.0 1.0 +#pragma parameter bloomblendmode "Bloom Blend Mode" 0.0 0.0 1.0 1.0 +#pragma parameter bloomscale "Bloom Scale" 0.06 0.0 1.0 0.01 +#pragma parameter bloomoverdrive_r "Bloom Overdrive R" 1.0 0.0 1.0 0.01 +#pragma parameter bloomoverdrive_g "Bloom Overdrive G" 1.0 0.0 1.0 0.01 +#pragma parameter bloomoverdrive_b "Bloom Overdrive B" 1.0 0.0 1.0 0.01 +#pragma parameter level0weight "Bloom Level 0 Weight" 1.0 0.0 1.0 0.01 +#pragma parameter level1weight "Bloom Level 1 Weight" 0.64 0.0 1.0 0.01 +#pragma parameter level2weight "Bloom Level 2 Weight" 0.32 0.0 1.0 0.01 +#pragma parameter level3weight "Bloom Level 3 Weight" 0.16 0.0 1.0 0.01 +#pragma parameter level4weight "Bloom Level 4 Weight" 0.08 0.0 1.0 0.01 +#pragma parameter level5weight "Bloom Level 5 Weight" 0.06 0.0 1.0 0.01 +#pragma parameter level6weight "Bloom Level 6 Weight" 0.04 0.0 1.0 0.01 +#pragma parameter level7weight "Bloom Level 7 Weight" 0.02 0.0 1.0 0.01 +#pragma parameter level8weight "Bloom Level 8 Weight" 0.01 0.0 1.0 0.01 + +// Post Pass +#pragma parameter humbaralpha "Hum Bar Alpha" 0.0 0.0 1.0 0.01 +#pragma parameter backcolor_r "Back Color R" 0.0 0.0 1.0 0.01 +#pragma parameter backcolor_g "Back Color G" 0.0 0.0 1.0 0.01 +#pragma parameter backcolor_b "Back Color B" 0.0 0.0 1.0 0.01 +#pragma parameter shadowtilemode "Mask Tiling Mode" 0.0 0.0 1.0 1.0 +#pragma parameter shadowalpha "Mask Alpha" 0.3 0.0 1.0 0.01 +#pragma parameter shadowcount_x "Mask Tile Size X" 6.0 1.0 32.0 1.0 +#pragma parameter shadowcount_y "Mask Tile Size Y" 6.0 1.0 32.0 1.0 +#pragma parameter shadowuv_x "Mask UV X" 0.25 0.0 1.0 0.01 +#pragma parameter shadowuv_y "Mask UV Y" 0.25 0.0 1.0 0.01 +#pragma parameter mask_width "Mask Texture Width" 32.0 0.0 256.0 16.0 +#pragma parameter mask_height "Mask Texture Height" 32.0 0.0 256.0 16.0 +#pragma parameter mask_offset_x "Mask Offset X" 0.0 -10.0 10.0 0.1 +#pragma parameter mask_offset_y "Mask Offset Y" 0.0 -10.0 10.0 0.1 +#pragma parameter chromamode "Chroma Mode" 3.0 1.0 3.0 1.0 +#pragma parameter conversiongain_x "Conversion Gain X" 0.0 -5.0 5.0 0.5 +#pragma parameter conversiongain_y "Conversion Gain Y" 0.0 -5.0 5.0 0.5 +#pragma parameter conversiongain_z "Conversion Gain Z" 0.0 -5.0 5.0 0.5 +#pragma parameter power_r "Color Power R" 1.0 1.0 10.0 1.0 +#pragma parameter power_g "Color Power G" 1.0 1.0 10.0 1.0 +#pragma parameter power_b "Color Power B" 1.0 1.0 10.0 1.0 +#pragma parameter floor_r "Color Floor R" 0.0 0.0 1.0 0.01 +#pragma parameter floor_g "Color Floor G" 0.0 0.0 1.0 0.01 +#pragma parameter floor_b "Color Floor B" 0.0 0.0 1.0 0.01 +#pragma parameter preparebloom "Prepare Bloom" 0.0 0.0 1.0 1.0 + +// NTSC Pass +#pragma parameter avalue "A Value" 0.5 0.0 1.0 0.01 +#pragma parameter bvalue "B Value" 0.5 0.0 1.0 0.01 +#pragma parameter ccvalue "CC Value" 3.5795454 0.0 5.0 0.1 +#pragma parameter ovalue "O Value" 0.0 -2.0 2.0 0.1 +#pragma parameter pvalue "P Value" 1.0 -2.0 3.0 0.1 +#pragma parameter scantime "Scan Time" 52.6 0.0 100.0 1.0 +#pragma parameter notchhalfwidth "Notch Half Width" 1.0 0.0 5.0 0.5 +#pragma parameter yfreqresponse "Y Freq Response" 6.0 0.0 10.0 0.1 +#pragma parameter ifreqresponse "I Freq Response" 1.2 0.0 10.0 0.1 +#pragma parameter qfreqresponse "Q Freq Response" 0.6 0.0 10.0 0.1 +#pragma parameter signaloffset "Signal Offset" 0.0 -5.0 5.0 0.01 + +// Color Pass +#pragma parameter col_red "Red Shift" 1.0 0.0 1.0 0.01 +#pragma parameter col_grn "Green Shift" 1.0 0.0 1.0 0.01 +#pragma parameter col_blu "Blue Shift" 1.0 0.0 1.0 0.01 +#pragma parameter col_offset_x "Offset X" 0.0 0.0 1.0 0.01 +#pragma parameter col_offset_y "Offset Y" 0.0 0.0 1.0 0.01 +#pragma parameter col_offset_z "Offset Z" 0.0 0.0 1.0 0.01 +#pragma parameter col_scale_x "Scale X" 1.0 0.0 1.0 0.01 +#pragma parameter col_scale_y "Scale Y" 1.0 0.0 1.0 0.01 +#pragma parameter col_scale_z "Scale Z" 1.0 0.0 1.0 0.01 +#pragma parameter col_saturation "Saturation" 1.0 0.0 0.01 + +// Deconverge Pass +#pragma parameter converge_x_r "Convergence X Red" 0.0 -100.0 100.0 0.5 +#pragma parameter converge_x_g "Convergence X Green" 0.0 -100.0 100.0 0.5 +#pragma parameter converge_x_b "Convergence X Blue" 0.0 -100.0 100.0 0.5 +#pragma parameter converge_y_r "Convergence Y Red" 0.0 -100.0 100.0 0.5 +#pragma parameter converge_y_g "Convergence Y Green" 0.0 -100.0 100.0 0.5 +#pragma parameter converge_y_b "Convergence Y Blue" 0.0 -100.0 100.0 0.5 +#pragma parameter radial_conv_x_r "Radial Conv X Red" 0.0 -100.0 100.0 0.5 +#pragma parameter radial_conv_x_g "Radial Conv X Green" 0.0 -100.0 100.0 0.5 +#pragma parameter radial_conv_x_b "Radial Conv X Blue" 0.0 -100.0 100.0 0.5 +#pragma parameter radial_conv_y_r "Radial Conv Y Red" 0.0 -100.0 100.0 0.5 +#pragma parameter radial_conv_y_g "Radial Conv Y Green" 0.0 -100.0 100.0 0.5 +#pragma parameter radial_conv_y_b "Radial Conv Y Blue" 0.0 -100.0 100.0 0.5 + +// Scanline Pass +#pragma parameter scanlinealpha "Scanline Alpha" 0.5 0.0 1.0 0.01 +#pragma parameter scanlinescale "Scanline Scale" 1.0 1.0 5.0 1.0 +#pragma parameter scanlineheight "Scanline Height" 1.0 0.0 2.0 0.1 +#pragma parameter scanlinevariation "Scanline Variation" 1.0 0.0 5.0 0.5 +#pragma parameter scanlineoffset "Scanline Offset" 1.0 -1.5 3.0 0.1 +#pragma parameter scanlinebrightscale "Scanline Bright Scale" 1.0 0.0 2.0 0.1 +#pragma parameter scanlinebrightoffset "Scanline Bright Offset" 1.0 -1.5 3.0 0.1 + +// Defocus Pass +#pragma parameter defocus_x "Defocus X Axis" 0.0 0.0 10.0 0.1 +#pragma parameter defocus_y "Defocus Y Axis" 0.0 0.0 10.0 0.1 + +// Phosphor Pass +#pragma parameter deltatime "Delta Time" 1.0 0.0 2.0 0.1 +#pragma parameter phosphor_r "Phosphor Red" 0.8 0.0 0.99 0.1 +#pragma parameter phosphor_g "Phosphor Green" 0.0 0.0 0.99 0.1 +#pragma parameter phosphor_b "Phosphor Blue" 0.0 0.0 0.99 0.1 + +// Chroma Pass +#pragma parameter ygain_r "Y Gain R Channel" 0.2126 0.0 1.0 0.01 +#pragma parameter ygain_g "Y Gain G Channel" 0.7152 0.0 1.0 0.01 +#pragma parameter ygain_b "Y Gain B Channel" 0.0722 0.0 1.0 0.01 +#pragma parameter chromaa_x "Chroma A X" 0.630 0.0 1.0 0.01 +#pragma parameter chromaa_y "Chroma A Y" 0.340 0.0 1.0 0.01 +#pragma parameter chromab_x "Chroma B X" 0.310 0.0 1.0 0.01 +#pragma parameter chromab_y "Chroma B Y" 0.595 0.0 1.0 0.01 +#pragma parameter chromac_x "Chroma C X" 0.155 0.0 1.0 0.01 +#pragma parameter chromac_y "Chroma C Y" 0.070 0.0 1.0 0.01 + +// Distortion Pass +#pragma parameter distortion_amount "Distortion Amount" 0.0 0.0 1.0 0.01 +#pragma parameter cubic_distortion_amount "Cubic Dist. Amt" 0.0 0.0 1.0 0.01 +#pragma parameter distort_corner_amount "Corner Dist. Amt" 0.0 0.0 1.0 0.01 +#pragma parameter round_corner_amount "Corner Rounding" 0.0 0.0 1.0 0.01 +#pragma parameter smooth_border_amount "Border Smoothing" 0.0 0.0 1.0 0.01 +#pragma parameter vignette_amount "Vignetting Amount" 0.0 0.0 1.0 0.01 +#pragma parameter reflection_amount "Reflection Amount" 0.0 0.0 1.0 0.01 +#pragma parameter reflection_col_r "Reflection Color R" 1.0 0.0 1.0 0.01 +#pragma parameter reflection_col_g "Reflection Color G" 0.9 0.0 1.0 0.01 +#pragma parameter reflection_col_b "Reflection Color B" 0.8 0.0 1.0 0.01 + +// Vector Pass +//#pragma parameter timeratio "Time Ratio" 1.0 0.0 2.0 0.01 +//#pragma parameter timescale "Time Scale" 1.0 1.0 10.0 1.0 +//#pragma parameter lengthratio "Length Ratio" 1.0 1.0 10.0 1.0 +//#pragma parameter lengthscale "Length Scale" 1.0 1.0 10.0 1.0 +//#pragma parameter beamsmooth "Beam Smooth Amt" 0.5 0.1 1.0 0.1 diff --git a/test/nonfunctional/shaders/mame/mame_phosphor.slang b/test/nonfunctional/shaders/mame/mame_phosphor.slang new file mode 100644 index 0000000..98e88b4 --- /dev/null +++ b/test/nonfunctional/shaders/mame/mame_phosphor.slang @@ -0,0 +1,56 @@ +#version 450 + +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +//----------------------------------------------------------------------------- +// Phosphor Effect +//----------------------------------------------------------------------------- + +layout(push_constant) uniform Push +{ + vec4 SourceSize; + vec4 OriginalSize; + vec4 OutputSize; + uint FrameCount; +} params; + +#include "mame_parameters.inc" + +float DeltaTime = global.deltatime; +vec3 Phosphor = vec3(global.phosphor_r, global.phosphor_g, global.phosphor_b); + +const float F = 1.0; + +#pragma stage vertex +layout(location = 0) in vec4 Position; +layout(location = 1) in vec2 TexCoord; +layout(location = 0) out vec2 vTexCoord; + +void main() +{ + gl_Position = global.MVP * Position; + vTexCoord = TexCoord; +} + +#pragma stage fragment +layout(location = 0) in vec2 vTexCoord; +layout(location = 0) out vec4 FragColor; +layout(set = 0, binding = 2) uniform sampler2D Source; +layout(set = 0, binding = 3) uniform sampler2D PassFeedback6; + +#define DiffuseSampler Source +#define PreviousSampler PassFeedback6 + +void main() +{ + vec4 CurrY = texture(DiffuseSampler, vTexCoord); + vec3 PrevY = texture(PreviousSampler, vTexCoord).rgb; + + PrevY[0] *= (Phosphor[0] == 0.0) ? 0.0 : pow(Phosphor[0], F * DeltaTime); + PrevY[1] *= (Phosphor[1] == 0.0) ? 0.0 : pow(Phosphor[1], F * DeltaTime); + PrevY[2] *= (Phosphor[2] == 0.0) ? 0.0 : pow(Phosphor[2], F * DeltaTime); + float a = max(PrevY[0], CurrY[0]); + float b = max(PrevY[1], CurrY[1]); + float c = max(PrevY[2], CurrY[2]); + FragColor = Passthrough ? CurrY : vec4(a, b, c, CurrY.a); +} \ No newline at end of file diff --git a/test/nonfunctional/shaders/mame/mame_post.slang b/test/nonfunctional/shaders/mame/mame_post.slang new file mode 100644 index 0000000..b1799f0 --- /dev/null +++ b/test/nonfunctional/shaders/mame/mame_post.slang @@ -0,0 +1,197 @@ +#version 450 + +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz,ImJezze +//----------------------------------------------------------------------------- +// Shadowmask Effect +//----------------------------------------------------------------------------- + +layout(push_constant) uniform Push +{ + vec4 SourceSize; + vec4 OriginalSize; + vec4 OutputSize; + uint FrameCount; +} params; + +#include "mame_parameters.inc" + +#define TargetDims params.OutputSize.xy +#define SourceDims params.OriginalSize.xy +float TargetScale = 1.0;//max(TargetDims.x / SourceDims.x, TargetDims.y / SourceDims.y); + +float HumBarAlpha = global.humbaralpha; +float TimeMilliseconds = float(mod(params.FrameCount, 1000)); +vec3 BackColor = vec3(global.backcolor_r, global.backcolor_g, global.backcolor_b); +int ShadowTileMode = int(global.shadowtilemode); // 0 based on screen (quad) dimension, 1 based on source dimension +float ShadowAlpha = global.shadowalpha; +vec2 ShadowCount = vec2(global.shadowcount_x, global.shadowcount_y); +vec2 ShadowUV = vec2(global.shadowuv_x, global.shadowuv_y); +vec2 ShadowDims = vec2(global.mask_width, global.mask_height); +vec2 ShadowUVOffset = vec2(global.mask_offset_x, global.mask_offset_y); +int ChromaMode = int(global.chromamode); +vec3 ConversionGain = vec3(global.conversiongain_x, global.conversiongain_y, global.conversiongain_z); +vec3 Power = vec3(global.power_r, global.power_g, global.power_b); +vec3 Floor = vec3(global.floor_r, global.floor_g, global.floor_b); +bool PrepareBloom = bool(global.preparebloom); + +#define MONOCHROME 1 +#define DICHROME 2 +#define TRICHROME 3 + +//----------------------------------------------------------------------------- +// Constants +//----------------------------------------------------------------------------- + +const float PI = 3.1415927; +const float HalfPI = PI * 0.5; + +float HumBarDesync = 60.0 / 59.94 - 1.0; // difference between the 59.94 Hz field rate and 60 Hz line frequency (NTSC) + +vec2 GetAdjustedCoords(vec2 coord) +{ + // center coordinates + coord -= 0.5; + + // apply screen scale + coord *= ScreenScale; + + // un-center coordinates + coord += 0.5; + + // apply screen offset + coord += ScreenOffset; + + return coord; +} + +vec2 GetShadowCoord(vec2 TargetCoord, vec2 SourceCoord) +{ + // base-target dimensions (without oversampling) + vec2 BaseTargetDims = TargetDims / TargetScale; + BaseTargetDims = SwapXY + ? BaseTargetDims.yx + : BaseTargetDims.xy; + + vec2 canvasCoord = ShadowTileMode == 0 + ? TargetCoord + ShadowUVOffset / BaseTargetDims + : SourceCoord + ShadowUVOffset / SourceDims; + vec2 canvasTexelDims = ShadowTileMode == 0 + ? 1.0 / BaseTargetDims + : 1.0 / SourceDims; + + vec2 shadowDims = ShadowDims; + vec2 shadowUV = ShadowUV; + vec2 shadowCount = ShadowCount; + + // swap x/y in screen mode (not source mode) + canvasCoord = ShadowTileMode == 0 && SwapXY + ? canvasCoord.yx + : canvasCoord.xy; + + // swap x/y in screen mode (not source mode) + shadowCount = ShadowTileMode == 0 && SwapXY + ? shadowCount.yx + : shadowCount.xy; + + vec2 shadowTile = canvasTexelDims * shadowCount; + + vec2 shadowFrac = fract(canvasCoord / shadowTile); + + // swap x/y in screen mode (not source mode) + shadowFrac = ShadowTileMode == 0 && SwapXY + ? shadowFrac.yx + : shadowFrac.xy; + + vec2 shadowCoord = (shadowFrac * shadowUV); + shadowCoord += ShadowTileMode == 0 + ? vec2(0.5) * (vec2(1.0) / shadowDims) // fix half texel offset (DX9) + : vec2(0.0); + + return shadowCoord; +} + +#pragma stage vertex +layout(location = 0) in vec4 Position; +layout(location = 1) in vec2 TexCoord; +layout(location = 0) out vec2 vTexCoord; + +void main() +{ + gl_Position = global.MVP * Position; + vTexCoord = TexCoord; +} + +#pragma stage fragment +layout(location = 0) in vec2 vTexCoord; +layout(location = 0) out vec4 FragColor; +layout(set = 0, binding = 2) uniform sampler2D Source; +layout(set = 0, binding = 3) uniform sampler2D MaskTexture; + +#define DiffuseSampler Source +#define ShadowSampler MaskTexture +//#define ScreenCoord vTexCoord + +void main() +{ + vec2 ScreenCoord = vTexCoord; + vec2 BaseCoord = GetAdjustedCoords(ScreenCoord); + + // Color + vec4 BaseColor = texture(DiffuseSampler, BaseCoord); + BaseColor.a = 1.0; +/* + // clip border + if (BaseCoord.x < 0.0 || BaseCoord.y < 0.0 || + BaseCoord.x > 1.0 || BaseCoord.y > 1.0) + { + // we don't use the clip function, because we don't clear the render target before + return vec4(0.0, 0.0, 0.0, 1.0); + } +*/ + // Color Compression (may not affect bloom) + if (!PrepareBloom) + { + // increasing the floor of the signal without affecting the ceiling + BaseColor.rgb = Floor + (1.0f - Floor) * BaseColor.rgb; + } + + // Color Power (may affect bloom) + BaseColor.r = pow(BaseColor.r, Power.r); + BaseColor.g = pow(BaseColor.g, Power.g); + BaseColor.b = pow(BaseColor.b, Power.b); + + // Hum Bar Simulation (may not affect vector screen) + if (!PrepareBloom && !VectorScreen && HumBarAlpha > 0.0) + { + float HumBarStep = fract(TimeMilliseconds * HumBarDesync); + float HumBarBrightness = 1.0 - fract(BaseCoord.y + HumBarStep) * HumBarAlpha; + BaseColor.rgb *= HumBarBrightness; + } + + // Mask Simulation (may not affect bloom) + if (!PrepareBloom && ShadowAlpha > 0.0) + { + vec2 ShadowCoord = GetShadowCoord(ScreenCoord, BaseCoord); + + vec4 ShadowColor = texture(ShadowSampler, ShadowCoord); + vec3 ShadowMaskColor = mix(vec3(1.0), ShadowColor.rgb, ShadowAlpha); + float ShadowMaskClear = (1.0 - ShadowColor.a) * ShadowAlpha; + + // apply shadow mask color + BaseColor.rgb *= ShadowMaskColor; + // clear shadow mask by background color + BaseColor.rgb = mix(BaseColor.rgb, BackColor, ShadowMaskClear); + } + + // Preparation for phosphor color conversion + if (ChromaMode == MONOCHROME) { + BaseColor.r = dot(ConversionGain, BaseColor.rgb); + BaseColor.gb = vec2(BaseColor.r, BaseColor.r); + } else if (ChromaMode == DICHROME) { + BaseColor.r = dot(ConversionGain.rg, BaseColor.rg); + BaseColor.g = BaseColor.r; + } + + FragColor = BaseColor; +} \ No newline at end of file diff --git a/test/nonfunctional/shaders/mame/mame_scanline.slang b/test/nonfunctional/shaders/mame/mame_scanline.slang new file mode 100644 index 0000000..60593ee --- /dev/null +++ b/test/nonfunctional/shaders/mame/mame_scanline.slang @@ -0,0 +1,124 @@ +#version 450 + +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz,ImJezze +//----------------------------------------------------------------------------- +// Scanline Effect +//----------------------------------------------------------------------------- + +layout(push_constant) uniform Push +{ + vec4 SourceSize; + vec4 OriginalSize; + vec4 OutputSize; + uint FrameCount; +} params; + +#include "mame_parameters.inc" + +//----------------------------------------------------------------------------- +// Constants +//----------------------------------------------------------------------------- + +const float PI = 3.1415927f; +const float HalfPI = PI * 0.5f; + +//----------------------------------------------------------------------------- +// Scanline Pixel Shader +//----------------------------------------------------------------------------- + +float ScanlineAlpha = global.scanlinealpha; +float ScanlineScale = global.scanlinescale; +float ScanlineHeight = global.scanlineheight; +float ScanlineVariation = global.scanlinevariation; +float ScanlineOffset = global.scanlineoffset; +float ScanlineBrightScale = global.scanlinebrightscale; +float ScanlineBrightOffset = global.scanlinebrightoffset; + +vec2 QuadDims = params.SourceSize.xy; +vec2 SourceDims = params.SourceSize.xy; + +vec2 GetAdjustedCoords(vec2 coord) +{ + // center coordinates + coord -= 0.5f; + + // apply screen scale + coord *= ScreenScale; + + // un-center coordinates + coord += 0.5f; + + // apply screen offset + coord += ScreenOffset; + + return coord; +} + +#pragma stage vertex +layout(location = 0) in vec4 Position; +layout(location = 1) in vec2 TexCoord; +layout(location = 0) out vec2 vTexCoord; + +void main() +{ + gl_Position = global.MVP * Position; + vTexCoord = TexCoord; +} + +#pragma stage fragment +layout(location = 0) in vec2 vTexCoord; +layout(location = 0) out vec4 FragColor; +layout(set = 0, binding = 2) uniform sampler2D Source; + +#define DiffuseSampler Source + +void main() +{ + if(!ScanlineToggle) + { + FragColor = texture(Source, vTexCoord); + return; + } + else + { + vec2 BaseCoord = GetAdjustedCoords(vTexCoord); + + // Color + vec4 BaseColor = texture(DiffuseSampler, BaseCoord); + BaseColor.a = 1.0f; +/* + // clip border + if (BaseCoord.x < 0.0f || BaseCoord.y < 0.0f || + BaseCoord.x > 1.0f || BaseCoord.y > 1.0f) + { + // we don't use the clip function, because we don't clear the render target before + return vec4(0.0f, 0.0f, 0.0f, 1.0f); + } +*/ + float BrightnessOffset = (ScanlineBrightOffset * ScanlineAlpha); + float BrightnessScale = (ScanlineBrightScale * ScanlineAlpha) + (1.0f - ScanlineAlpha); + + float ColorBrightness = 0.299f * BaseColor.r + 0.587f * BaseColor.g + 0.114 * BaseColor.b; + + float ScanlineCoord = BaseCoord.y; + ScanlineCoord += SwapXY + ? QuadDims.x <= SourceDims.x * 2.0f + ? 0.5f / QuadDims.x // uncenter scanlines if the quad is less than twice the size of the source + : 0.0f + : QuadDims.y <= SourceDims.y * 2.0f + ? 0.5f / QuadDims.y // uncenter scanlines if the quad is less than twice the size of the source + : 0.0f; + ScanlineCoord *= SourceDims.y * ScanlineScale * PI; + + float ScanlineCoordJitter = ScanlineOffset * HalfPI; + float ScanlineSine = sin(ScanlineCoord + ScanlineCoordJitter); + float ScanlineWide = ScanlineHeight + ScanlineVariation * max(1.0f, ScanlineHeight) * (1.0f - ColorBrightness); + float ScanlineAmount = pow(ScanlineSine * ScanlineSine, ScanlineWide); + float ScanlineBrightness = ScanlineAmount * BrightnessScale + BrightnessOffset * BrightnessScale; + + BaseColor.rgb *= mix(1.0f, ScanlineBrightness, ScanlineAlpha); + + FragColor = BaseColor; + } +} \ No newline at end of file diff --git a/test/nonfunctional/shaders/mame/mame_vector.slang b/test/nonfunctional/shaders/mame/mame_vector.slang new file mode 100644 index 0000000..5ec4099 --- /dev/null +++ b/test/nonfunctional/shaders/mame/mame_vector.slang @@ -0,0 +1,102 @@ +#version 450 + +layout(push_constant) uniform Push +{ + vec4 SourceSize; + vec4 OriginalSize; + vec4 OutputSize; + uint FrameCount; +} params; + +#include "mame_parameters.inc" + +#define saturate(c) clamp(c, 0.0, 1.0) +#define TargetDims params.OutputSize.xy +#define DiffuseSampler Source + +float TimeRatio = global.timeratio; // Frame time of the vector (not set) +float TimeScale = global.timescale; // How much frame time affects the vector's fade (not set) +float LengthRatio = global.lengthratio; // Size at which fade is maximum +float LengthScale = global.lengthscale; // How much length affects the vector's fade +float BeamSmooth = global.beamsmooth; +// vec2 SizeInfo; +// vec4 Color; + +const vec2 SizeInfo = vec2(1.0); +const vec4 Color = vec4(1.0); + +//----------------------------------------------------------------------------- +// Functions +//----------------------------------------------------------------------------- + +// www.iquilezles.org/www/articles/distfunctions/distfunctions.htm +float roundBox(vec2 p, vec2 b, float r) +{ + return length(max(abs(p) - b + r, 0.0f)) - r; +} + +float GetBoundsFactor(vec2 coord, vec2 bounds, float radiusAmount, float smoothAmount) +{ + // reduce smooth amount down to radius amount + smoothAmount = min(smoothAmount, radiusAmount); + + float range = min(bounds.x, bounds.y); + float amountMinimum = 1.0f / range; + float radius = range * max(radiusAmount, amountMinimum); + float smooth_ = 1.0f / (range * max(smoothAmount, amountMinimum * 2.0f)); + + // compute box + float box = roundBox(bounds * (coord * 2.0f), bounds, radius); + + // apply smooth_ + box *= smooth_; + box += 1.0f - pow(smooth_ * 0.5f, 0.5f); + + float border = smoothstep(1.0f, 0.0f, box); + + return saturate(border); +} + +#pragma stage vertex +layout(location = 0) in vec4 Position; +layout(location = 1) in vec2 TexCoord; +layout(location = 0) out vec2 vTexCoord; + +void main() +{ + gl_Position = global.MVP * Position; + vTexCoord = TexCoord; +} + +#pragma stage fragment +layout(location = 0) in vec2 vTexCoord; +layout(location = 0) out vec4 FragColor; +layout(set = 0, binding = 2) uniform sampler2D Source; + +void main() +{ + if(!VectorScreen) + { + FragColor = texture(Source, vTexCoord); + return; + } + else + { + vec2 lineSize = SizeInfo / max(TargetDims.x, TargetDims.y); // normalize + + float lineLength = lineSize.x; + float lineLengthRatio = params.LengthRatio; + float lineLengthScale = params.LengthScale; + + float timeModulate = mix(1.0f, params.TimeRatio, params.TimeScale); + float lengthModulate = 1.0f - clamp(lineLength / lineLengthRatio, 0.0f, 1.0f); + float timeLengthModulate = mix(1.0f, timeModulate * lengthModulate, params.LengthScale); + + vec4 outColor = vec4(timeLengthModulate, timeLengthModulate, timeLengthModulate, 1.0f); + outColor *= Color; + + float RoundCornerFactor = GetBoundsFactor(vTexCoord - 0.5f, SizeInfo, 1.0f, params.BeamSmooth); + outColor.rgb *= RoundCornerFactor; + FragColor = outColor; + } +} \ No newline at end of file diff --git a/test/nonfunctional/shaders/mame/primary.slang b/test/nonfunctional/shaders/mame/primary.slang new file mode 100644 index 0000000..31f1df3 --- /dev/null +++ b/test/nonfunctional/shaders/mame/primary.slang @@ -0,0 +1,71 @@ +#version 450 + +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz, W. M. Martinez +//----------------------------------------------------------------------------- +// Primary Effect +//----------------------------------------------------------------------------- + +layout(push_constant) uniform Push +{ + vec4 SourceSize; + vec4 OriginalSize; + vec4 OutputSize; + uint FrameCount; +} params; + +layout(std140, set = 0, binding = 0) uniform UBO +{ + mat4 MVP; +} global; + +//----------------------------------------------------------------------------- +// Macros +//----------------------------------------------------------------------------- + +#define LUT_TEXTURE_WIDTH 4096.0f +#define LUT_SIZE 64.0f +#define LUT_SCALE vec2(1.0f / LUT_TEXTURE_WIDTH, 1.0f / LUT_SIZE) + +#pragma stage vertex +layout(location = 0) in vec4 Position; +layout(location = 1) in vec2 TexCoord; +layout(location = 0) out vec2 vTexCoord; + +void main() +{ + gl_Position = global.MVP * Position; + vTexCoord = TexCoord; +} + +#pragma stage fragment +layout(location = 0) in vec2 vTexCoord; +layout(location = 0) out vec4 FragColor; +layout(set = 0, binding = 2) uniform sampler2D Source; +layout(set = 0, binding = 3) uniform sampler2D MaskTexture; + +#define DiffuseSampler Source +#define LutSampler MaskTexture + +//----------------------------------------------------------------------------- +// Utilities +//----------------------------------------------------------------------------- + +vec3 apply_lut(vec3 color) +{ + // NOTE: Do not change the order of parameters here. + vec3 lutcoord = vec3((color.rg * (LUT_SIZE - 1.0f) + 0.5f) * + LUT_SCALE, color.b * (LUT_SIZE - 1.0f)); + float shift = floor(lutcoord.z); + + lutcoord.x += shift * LUT_SCALE.y; + color.rgb = mix(texture(LutSampler, lutcoord.xy).rgb, texture(LutSampler, + float2(lutcoord.x + LUT_SCALE.y, lutcoord.y)).rgb, + lutcoord.z - shift); + return color; +} + +void main() +{ + FragColor = vec4(texture(Source, vTexCoord).rgb, 1.0); +} \ No newline at end of file diff --git a/test/nonfunctional/shaders/mame/shadow-mask.png b/test/nonfunctional/shaders/mame/shadow-mask.png new file mode 100644 index 0000000000000000000000000000000000000000..0c04c5f92fa785a3d73f98033230e8f6f809ab97 GIT binary patch literal 20397 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 literal 0 HcmV?d00001