scanlines-horizontal-apply-mask.fs 566 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845
  1. #version 150
  2. ///////////////////////////// GPL LICENSE NOTICE /////////////////////////////
  3. // crt-royale: A full-featured CRT shader, with cheese.
  4. // Copyright (C) 2014 TroggleMonkey <trogglemonkey@gmx.com>
  5. //
  6. // This program is free software; you can redistribute it and/or modify it
  7. // under the terms of the GNU General Public License as published by the Free
  8. // Software Foundation; either version 2 of the License, or any later version.
  9. //
  10. // This program is distributed in the hope that it will be useful, but WITHOUT
  11. // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12. // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  13. // more details.
  14. //
  15. // You should have received a copy of the GNU General Public License along with
  16. // this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  17. // Place, Suite 330, Boston, MA 02111-1307 USA
  18. uniform sampler2D source[];
  19. uniform vec4 sourceSize[];
  20. uniform vec4 targetSize;
  21. uniform int phase;
  22. uniform sampler2D pixmap[];
  23. in Vertex {
  24. vec2 vTexCoord;
  25. vec2 video_uv;
  26. vec2 scanline_tex_uv;
  27. vec2 blur3x3_tex_uv;
  28. vec2 halation_tex_uv;
  29. vec2 scanline_texture_size_inv;
  30. vec4 mask_tile_start_uv_and_size;
  31. vec2 mask_tiles_per_screen;
  32. };
  33. out vec4 FragColor;
  34. // USER SETTINGS BLOCK //
  35. #define crt_gamma 2.500000
  36. #define lcd_gamma 2.200000
  37. #define levels_contrast 1.0
  38. #define halation_weight 0.0
  39. #define diffusion_weight 0.075
  40. #define bloom_underestimate_levels 0.8
  41. #define bloom_excess 0.000000
  42. #define beam_min_sigma 0.020000
  43. #define beam_max_sigma 0.300000
  44. #define beam_spot_power 0.330000
  45. #define beam_min_shape 2.000000
  46. #define beam_max_shape 4.000000
  47. #define beam_shape_power 0.250000
  48. #define beam_horiz_filter 0.000000
  49. #define beam_horiz_sigma 0.35
  50. #define beam_horiz_linear_rgb_weight 1.000000
  51. #define convergence_offset_x_r -0.000000
  52. #define convergence_offset_x_g 0.000000
  53. #define convergence_offset_x_b 0.000000
  54. #define convergence_offset_y_r 0.000000
  55. #define convergence_offset_y_g -0.000000
  56. #define convergence_offset_y_b 0.000000
  57. #define mask_type 1.000000
  58. #define mask_sample_mode_desired 0.000000
  59. #define mask_specify_num_triads 0.000000
  60. #define mask_triad_size_desired 3.000000
  61. #define mask_num_triads_desired 480.000000
  62. #define aa_subpixel_r_offset_x_runtime -0.0
  63. #define aa_subpixel_r_offset_y_runtime 0.000000
  64. #define aa_cubic_c 0.500000
  65. #define aa_gauss_sigma 0.500000
  66. #define geom_mode_runtime 0.000000
  67. #define geom_radius 2.000000
  68. #define geom_view_dist 2.000000
  69. #define geom_tilt_angle_x 0.000000
  70. #define geom_tilt_angle_y 0.000000
  71. #define geom_aspect_ratio_x 432.000000
  72. #define geom_aspect_ratio_y 329.000000
  73. #define geom_overscan_x 1.000000
  74. #define geom_overscan_y 1.000000
  75. #define border_size 0.015
  76. #define border_darkness 2.0
  77. #define border_compress 2.500000
  78. #define interlace_bff 0.000000
  79. #define interlace_1080i 0.000000
  80. // END USER SETTINGS BLOCK //
  81. #define VERTICAL_SCANLINEStexture source[5]
  82. #define VERTICAL_SCANLINEStexture_size sourceSize[5].xy
  83. #define VERTICAL_SCANLINESvideo_size sourceSize[5].xy
  84. #define BLOOM_APPROXtexture source[4]
  85. #define BLOOM_APPROXtexture_size sourceSize[4].xy
  86. #define BLOOM_APPROXvideo_size sourceSize[4].xy
  87. #define HALATION_BLURtexture source[2]
  88. #define HALATION_BLURtexture_size sourceSize[2].xy
  89. #define HALATION_BLURvideo_size sourceSize[2].xy
  90. #ifdef INTEGRATED_GRAPHICS_COMPATIBILITY_MODE
  91. #define MASK_RESIZEtexture source[0]
  92. #else
  93. #define MASK_RESIZEtexture source[0]
  94. #endif
  95. #define MASK_RESIZEtexture_size sourceSize[0]
  96. #define MASK_RESIZEvideo_size sourceSize[0]
  97. #define input_texture source[0]
  98. #define mask_grille_texture_large pixmap[1]
  99. #define mask_slot_texture_large pixmap[3]
  100. #define mask_shadow_texture_large pixmap[5]
  101. float bloom_approx_scale_x = targetSize.x / sourceSize[0].y;
  102. const float max_viewport_size_x = 1080.0*1024.0*(4.0/3.0);
  103. // compatibility macros for transparently converting HLSLisms into GLSLisms
  104. #define mul(a,b) (b*a)
  105. #define lerp(a,b,c) mix(a,b,c)
  106. #define saturate(c) clamp(c, 0.0, 1.0)
  107. #define frac(x) (fract(x))
  108. #define float2 vec2
  109. #define float3 vec3
  110. #define float4 vec4
  111. #define bool2 bvec2
  112. #define bool3 bvec3
  113. #define bool4 bvec4
  114. #define float2x2 mat2x2
  115. #define float3x3 mat3x3
  116. #define float4x4 mat4x4
  117. #define float4x3 mat4x3
  118. #define float2x4 mat2x4
  119. #define IN params
  120. #define texture_size sourceSize[0].xy
  121. #define video_size sourceSize[0].xy
  122. #define output_size targetSize.xy
  123. #define frame_count phase
  124. #define static
  125. #define inline
  126. #define const
  127. #define fmod(x,y) mod(x,y)
  128. #define ddx(c) dFdx(c)
  129. #define ddy(c) dFdy(c)
  130. #define atan2(x,y) atan(y,x)
  131. #define rsqrt(c) inversesqrt(c)
  132. #define input_texture source[0]
  133. #if defined(GL_ES)
  134. #define COMPAT_PRECISION mediump
  135. #else
  136. #define COMPAT_PRECISION
  137. #endif
  138. #if __VERSION__ >= 130
  139. #define COMPAT_TEXTURE texture
  140. #else
  141. #define COMPAT_TEXTURE texture2D
  142. #endif
  143. // VERTEX INCLUDES //
  144. ///////////////////////////// SETTINGS MANAGEMENT ////////////////////////////
  145. //#include "../user-settings.h"
  146. ///////////////////////////// BEGIN USER-SETTINGS ////////////////////////////
  147. #ifndef USER_SETTINGS_H
  148. #define USER_SETTINGS_H
  149. ///////////////////////////// DRIVER CAPABILITIES ////////////////////////////
  150. // The Cg compiler uses different "profiles" with different capabilities.
  151. // This shader requires a Cg compilation profile >= arbfp1, but a few options
  152. // require higher profiles like fp30 or fp40. The shader can't detect profile
  153. // or driver capabilities, so instead you must comment or uncomment the lines
  154. // below with "//" before "#define." Disable an option if you get compilation
  155. // errors resembling those listed. Generally speaking, all of these options
  156. // will run on nVidia cards, but only DRIVERS_ALLOW_TEX2DBIAS (if that) is
  157. // likely to run on ATI/AMD, due to the Cg compiler's profile limitations.
  158. // Derivatives: Unsupported on fp20, ps_1_1, ps_1_2, ps_1_3, and arbfp1.
  159. // Among other things, derivatives help us fix anisotropic filtering artifacts
  160. // with curved manually tiled phosphor mask coords. Related errors:
  161. // error C3004: function "float2 ddx(float2);" not supported in this profile
  162. // error C3004: function "float2 ddy(float2);" not supported in this profile
  163. //#define DRIVERS_ALLOW_DERIVATIVES
  164. // Fine derivatives: Unsupported on older ATI cards.
  165. // Fine derivatives enable 2x2 fragment block communication, letting us perform
  166. // fast single-pass blur operations. If your card uses coarse derivatives and
  167. // these are enabled, blurs could look broken. Derivatives are a prerequisite.
  168. #ifdef DRIVERS_ALLOW_DERIVATIVES
  169. #define DRIVERS_ALLOW_FINE_DERIVATIVES
  170. #endif
  171. // Dynamic looping: Requires an fp30 or newer profile.
  172. // This makes phosphor mask resampling faster in some cases. Related errors:
  173. // error C5013: profile does not support "for" statements and "for" could not
  174. // be unrolled
  175. //#define DRIVERS_ALLOW_DYNAMIC_BRANCHES
  176. // Without DRIVERS_ALLOW_DYNAMIC_BRANCHES, we need to use unrollable loops.
  177. // Using one static loop avoids overhead if the user is right, but if the user
  178. // is wrong (loops are allowed), breaking a loop into if-blocked pieces with a
  179. // binary search can potentially save some iterations. However, it may fail:
  180. // error C6001: Temporary register limit of 32 exceeded; 35 registers
  181. // needed to compile program
  182. //#define ACCOMODATE_POSSIBLE_DYNAMIC_LOOPS
  183. // tex2Dlod: Requires an fp40 or newer profile. This can be used to disable
  184. // anisotropic filtering, thereby fixing related artifacts. Related errors:
  185. // error C3004: function "float4 tex2Dlod(sampler2D, float4);" not supported in
  186. // this profile
  187. //#define DRIVERS_ALLOW_TEX2DLOD
  188. // tex2Dbias: Requires an fp30 or newer profile. This can be used to alleviate
  189. // artifacts from anisotropic filtering and mipmapping. Related errors:
  190. // error C3004: function "float4 tex2Dbias(sampler2D, float4);" not supported
  191. // in this profile
  192. //#define DRIVERS_ALLOW_TEX2DBIAS
  193. // Integrated graphics compatibility: Integrated graphics like Intel HD 4000
  194. // impose stricter limitations on register counts and instructions. Enable
  195. // INTEGRATED_GRAPHICS_COMPATIBILITY_MODE if you still see error C6001 or:
  196. // error C6002: Instruction limit of 1024 exceeded: 1523 instructions needed
  197. // to compile program.
  198. // Enabling integrated graphics compatibility mode will automatically disable:
  199. // 1.) PHOSPHOR_MASK_MANUALLY_RESIZE: The phosphor mask will be softer.
  200. // (This may be reenabled in a later release.)
  201. // 2.) RUNTIME_GEOMETRY_MODE
  202. // 3.) The high-quality 4x4 Gaussian resize for the bloom approximation
  203. //#define INTEGRATED_GRAPHICS_COMPATIBILITY_MODE
  204. //////////////////////////// USER CODEPATH OPTIONS ///////////////////////////
  205. // To disable a #define option, turn its line into a comment with "//."
  206. // RUNTIME VS. COMPILE-TIME OPTIONS (Major Performance Implications):
  207. // Enable runtime shader parameters in the Retroarch (etc.) GUI? They override
  208. // many of the options in this file and allow real-time tuning, but many of
  209. // them are slower. Disabling them and using this text file will boost FPS.
  210. #define RUNTIME_SHADER_PARAMS_ENABLE
  211. // Specify the phosphor bloom sigma at runtime? This option is 10% slower, but
  212. // it's the only way to do a wide-enough full bloom with a runtime dot pitch.
  213. #define RUNTIME_PHOSPHOR_BLOOM_SIGMA
  214. // Specify antialiasing weight parameters at runtime? (Costs ~20% with cubics)
  215. #define RUNTIME_ANTIALIAS_WEIGHTS
  216. // Specify subpixel offsets at runtime? (WARNING: EXTREMELY EXPENSIVE!)
  217. //#define RUNTIME_ANTIALIAS_SUBPIXEL_OFFSETS
  218. // Make beam_horiz_filter and beam_horiz_linear_rgb_weight into runtime shader
  219. // parameters? This will require more math or dynamic branching.
  220. #define RUNTIME_SCANLINES_HORIZ_FILTER_COLORSPACE
  221. // Specify the tilt at runtime? This makes things about 3% slower.
  222. #define RUNTIME_GEOMETRY_TILT
  223. // Specify the geometry mode at runtime?
  224. #define RUNTIME_GEOMETRY_MODE
  225. // Specify the phosphor mask type (aperture grille, slot mask, shadow mask) and
  226. // mode (Lanczos-resize, hardware resize, or tile 1:1) at runtime, even without
  227. // dynamic branches? This is cheap if mask_resize_viewport_scale is small.
  228. #define FORCE_RUNTIME_PHOSPHOR_MASK_MODE_TYPE_SELECT
  229. // PHOSPHOR MASK:
  230. // Manually resize the phosphor mask for best results (slower)? Disabling this
  231. // removes the option to do so, but it may be faster without dynamic branches.
  232. #define PHOSPHOR_MASK_MANUALLY_RESIZE
  233. // If we sinc-resize the mask, should we Lanczos-window it (slower but better)?
  234. #define PHOSPHOR_MASK_RESIZE_LANCZOS_WINDOW
  235. // Larger blurs are expensive, but we need them to blur larger triads. We can
  236. // detect the right blur if the triad size is static or our profile allows
  237. // dynamic branches, but otherwise we use the largest blur the user indicates
  238. // they might need:
  239. #define PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_3_PIXELS
  240. //#define PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_6_PIXELS
  241. //#define PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_9_PIXELS
  242. //#define PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_12_PIXELS
  243. // Here's a helpful chart:
  244. // MaxTriadSize BlurSize MinTriadCountsByResolution
  245. // 3.0 9.0 480/640/960/1920 triads at 1080p/1440p/2160p/4320p, 4:3 aspect
  246. // 6.0 17.0 240/320/480/960 triads at 1080p/1440p/2160p/4320p, 4:3 aspect
  247. // 9.0 25.0 160/213/320/640 triads at 1080p/1440p/2160p/4320p, 4:3 aspect
  248. // 12.0 31.0 120/160/240/480 triads at 1080p/1440p/2160p/4320p, 4:3 aspect
  249. // 18.0 43.0 80/107/160/320 triads at 1080p/1440p/2160p/4320p, 4:3 aspect
  250. /////////////////////////////// USER PARAMETERS //////////////////////////////
  251. // Note: Many of these static parameters are overridden by runtime shader
  252. // parameters when those are enabled. However, many others are static codepath
  253. // options that were cleaner or more convert to code as static constants.
  254. // GAMMA:
  255. static const float crt_gamma_static = 2.5; // range [1, 5]
  256. static const float lcd_gamma_static = 2.2; // range [1, 5]
  257. // LEVELS MANAGEMENT:
  258. // Control the final multiplicative image contrast:
  259. static const float levels_contrast_static = 1.0; // range [0, 4)
  260. // We auto-dim to avoid clipping between passes and restore brightness
  261. // later. Control the dim factor here: Lower values clip less but crush
  262. // blacks more (static only for now).
  263. static const float levels_autodim_temp = 0.5; // range (0, 1] default is 0.5 but that was unnecessarily dark for me, so I set it to 1.0
  264. // HALATION/DIFFUSION/BLOOM:
  265. // Halation weight: How much energy should be lost to electrons bounding
  266. // around under the CRT glass and exciting random phosphors?
  267. static const float halation_weight_static = 0.0; // range [0, 1]
  268. // Refractive diffusion weight: How much light should spread/diffuse from
  269. // refracting through the CRT glass?
  270. static const float diffusion_weight_static = 0.075; // range [0, 1]
  271. // Underestimate brightness: Bright areas bloom more, but we can base the
  272. // bloom brightpass on a lower brightness to sharpen phosphors, or a higher
  273. // brightness to soften them. Low values clip, but >= 0.8 looks okay.
  274. static const float bloom_underestimate_levels_static = 0.8; // range [0, 5]
  275. // Blur all colors more than necessary for a softer phosphor bloom?
  276. static const float bloom_excess_static = 0.0; // range [0, 1]
  277. // The BLOOM_APPROX pass approximates a phosphor blur early on with a small
  278. // blurred resize of the input (convergence offsets are applied as well).
  279. // There are three filter options (static option only for now):
  280. // 0.) Bilinear resize: A fast, close approximation to a 4x4 resize
  281. // if min_allowed_viewport_triads and the BLOOM_APPROX resolution are sane
  282. // and beam_max_sigma is low.
  283. // 1.) 3x3 resize blur: Medium speed, soft/smeared from bilinear blurring,
  284. // always uses a static sigma regardless of beam_max_sigma or
  285. // mask_num_triads_desired.
  286. // 2.) True 4x4 Gaussian resize: Slowest, technically correct.
  287. // These options are more pronounced for the fast, unbloomed shader version.
  288. #ifndef RADEON_FIX
  289. static const float bloom_approx_filter_static = 2.0;
  290. #else
  291. static const float bloom_approx_filter_static = 1.0;
  292. #endif
  293. // ELECTRON BEAM SCANLINE DISTRIBUTION:
  294. // How many scanlines should contribute light to each pixel? Using more
  295. // scanlines is slower (especially for a generalized Gaussian) but less
  296. // distorted with larger beam sigmas (especially for a pure Gaussian). The
  297. // max_beam_sigma at which the closest unused weight is guaranteed <
  298. // 1.0/255.0 (for a 3x antialiased pure Gaussian) is:
  299. // 2 scanlines: max_beam_sigma = 0.2089; distortions begin ~0.34; 141.7 FPS pure, 131.9 FPS generalized
  300. // 3 scanlines, max_beam_sigma = 0.3879; distortions begin ~0.52; 137.5 FPS pure; 123.8 FPS generalized
  301. // 4 scanlines, max_beam_sigma = 0.5723; distortions begin ~0.70; 134.7 FPS pure; 117.2 FPS generalized
  302. // 5 scanlines, max_beam_sigma = 0.7591; distortions begin ~0.89; 131.6 FPS pure; 112.1 FPS generalized
  303. // 6 scanlines, max_beam_sigma = 0.9483; distortions begin ~1.08; 127.9 FPS pure; 105.6 FPS generalized
  304. static const float beam_num_scanlines = 3.0; // range [2, 6]
  305. // A generalized Gaussian beam varies shape with color too, now just width.
  306. // It's slower but more flexible (static option only for now).
  307. static const bool beam_generalized_gaussian = true;
  308. // What kind of scanline antialiasing do you want?
  309. // 0: Sample weights at 1x; 1: Sample weights at 3x; 2: Compute an integral
  310. // Integrals are slow (especially for generalized Gaussians) and rarely any
  311. // better than 3x antialiasing (static option only for now).
  312. static const float beam_antialias_level = 1.0; // range [0, 2]
  313. // Min/max standard deviations for scanline beams: Higher values widen and
  314. // soften scanlines. Depending on other options, low min sigmas can alias.
  315. static const float beam_min_sigma_static = 0.02; // range (0, 1]
  316. static const float beam_max_sigma_static = 0.3; // range (0, 1]
  317. // Beam width varies as a function of color: A power function (0) is more
  318. // configurable, but a spherical function (1) gives the widest beam
  319. // variability without aliasing (static option only for now).
  320. static const float beam_spot_shape_function = 0.0;
  321. // Spot shape power: Powers <= 1 give smoother spot shapes but lower
  322. // sharpness. Powers >= 1.0 are awful unless mix/max sigmas are close.
  323. static const float beam_spot_power_static = 1.0/3.0; // range (0, 16]
  324. // Generalized Gaussian max shape parameters: Higher values give flatter
  325. // scanline plateaus and steeper dropoffs, simultaneously widening and
  326. // sharpening scanlines at the cost of aliasing. 2.0 is pure Gaussian, and
  327. // values > ~40.0 cause artifacts with integrals.
  328. static const float beam_min_shape_static = 2.0; // range [2, 32]
  329. static const float beam_max_shape_static = 4.0; // range [2, 32]
  330. // Generalized Gaussian shape power: Affects how quickly the distribution
  331. // changes shape from Gaussian to steep/plateaued as color increases from 0
  332. // to 1.0. Higher powers appear softer for most colors, and lower powers
  333. // appear sharper for most colors.
  334. static const float beam_shape_power_static = 1.0/4.0; // range (0, 16]
  335. // What filter should be used to sample scanlines horizontally?
  336. // 0: Quilez (fast), 1: Gaussian (configurable), 2: Lanczos2 (sharp)
  337. static const float beam_horiz_filter_static = 0.0;
  338. // Standard deviation for horizontal Gaussian resampling:
  339. static const float beam_horiz_sigma_static = 0.35; // range (0, 2/3]
  340. // Do horizontal scanline sampling in linear RGB (correct light mixing),
  341. // gamma-encoded RGB (darker, hard spot shape, may better match bandwidth-
  342. // limiting circuitry in some CRT's), or a weighted avg.?
  343. static const float beam_horiz_linear_rgb_weight_static = 1.0; // range [0, 1]
  344. // Simulate scanline misconvergence? This needs 3x horizontal texture
  345. // samples and 3x texture samples of BLOOM_APPROX and HALATION_BLUR in
  346. // later passes (static option only for now).
  347. static const bool beam_misconvergence = true;
  348. // Convergence offsets in x/y directions for R/G/B scanline beams in units
  349. // of scanlines. Positive offsets go right/down; ranges [-2, 2]
  350. static const float2 convergence_offsets_r_static = float2(0.1, 0.2);
  351. static const float2 convergence_offsets_g_static = float2(0.3, 0.4);
  352. static const float2 convergence_offsets_b_static = float2(0.5, 0.6);
  353. // Detect interlacing (static option only for now)?
  354. static const bool interlace_detect = true;
  355. // Assume 1080-line sources are interlaced?
  356. static const bool interlace_1080i_static = false;
  357. // For interlaced sources, assume TFF (top-field first) or BFF order?
  358. // (Whether this matters depends on the nature of the interlaced input.)
  359. static const bool interlace_bff_static = false;
  360. // ANTIALIASING:
  361. // What AA level do you want for curvature/overscan/subpixels? Options:
  362. // 0x (none), 1x (sample subpixels), 4x, 5x, 6x, 7x, 8x, 12x, 16x, 20x, 24x
  363. // (Static option only for now)
  364. static const float aa_level = 12.0; // range [0, 24]
  365. // What antialiasing filter do you want (static option only)? Options:
  366. // 0: Box (separable), 1: Box (cylindrical),
  367. // 2: Tent (separable), 3: Tent (cylindrical),
  368. // 4: Gaussian (separable), 5: Gaussian (cylindrical),
  369. // 6: Cubic* (separable), 7: Cubic* (cylindrical, poor)
  370. // 8: Lanczos Sinc (separable), 9: Lanczos Jinc (cylindrical, poor)
  371. // * = Especially slow with RUNTIME_ANTIALIAS_WEIGHTS
  372. static const float aa_filter = 6.0; // range [0, 9]
  373. // Flip the sample grid on odd/even frames (static option only for now)?
  374. static const bool aa_temporal = false;
  375. // Use RGB subpixel offsets for antialiasing? The pixel is at green, and
  376. // the blue offset is the negative r offset; range [0, 0.5]
  377. static const float2 aa_subpixel_r_offset_static = float2(-1.0/3.0, 0.0);//float2(0.0);
  378. // Cubics: See http://www.imagemagick.org/Usage/filter/#mitchell
  379. // 1.) "Keys cubics" with B = 1 - 2C are considered the highest quality.
  380. // 2.) C = 0.5 (default) is Catmull-Rom; higher C's apply sharpening.
  381. // 3.) C = 1.0/3.0 is the Mitchell-Netravali filter.
  382. // 4.) C = 0.0 is a soft spline filter.
  383. static const float aa_cubic_c_static = 0.5; // range [0, 4]
  384. // Standard deviation for Gaussian antialiasing: Try 0.5/aa_pixel_diameter.
  385. static const float aa_gauss_sigma_static = 0.5; // range [0.0625, 1.0]
  386. // PHOSPHOR MASK:
  387. // Mask type: 0 = aperture grille, 1 = slot mask, 2 = EDP shadow mask
  388. static const float mask_type_static = 1.0; // range [0, 2]
  389. // We can sample the mask three ways. Pick 2/3 from: Pretty/Fast/Flexible.
  390. // 0.) Sinc-resize to the desired dot pitch manually (pretty/slow/flexible).
  391. // This requires PHOSPHOR_MASK_MANUALLY_RESIZE to be #defined.
  392. // 1.) Hardware-resize to the desired dot pitch (ugly/fast/flexible). This
  393. // is halfway decent with LUT mipmapping but atrocious without it.
  394. // 2.) Tile it without resizing at a 1:1 texel:pixel ratio for flat coords
  395. // (pretty/fast/inflexible). Each input LUT has a fixed dot pitch.
  396. // This mode reuses the same masks, so triads will be enormous unless
  397. // you change the mask LUT filenames in your .cgp file.
  398. static const float mask_sample_mode_static = 0.0; // range [0, 2]
  399. // Prefer setting the triad size (0.0) or number on the screen (1.0)?
  400. // If RUNTIME_PHOSPHOR_BLOOM_SIGMA isn't #defined, the specified triad size
  401. // will always be used to calculate the full bloom sigma statically.
  402. static const float mask_specify_num_triads_static = 0.0; // range [0, 1]
  403. // Specify the phosphor triad size, in pixels. Each tile (usually with 8
  404. // triads) will be rounded to the nearest integer tile size and clamped to
  405. // obey minimum size constraints (imposed to reduce downsize taps) and
  406. // maximum size constraints (imposed to have a sane MASK_RESIZE FBO size).
  407. // To increase the size limit, double the viewport-relative scales for the
  408. // two MASK_RESIZE passes in crt-royale.cgp and user-cgp-contants.h.
  409. // range [1, mask_texture_small_size/mask_triads_per_tile]
  410. static const float mask_triad_size_desired_static = 24.0 / 8.0;
  411. // If mask_specify_num_triads is 1.0/true, we'll go by this instead (the
  412. // final size will be rounded and constrained as above); default 480.0
  413. static const float mask_num_triads_desired_static = 480.0;
  414. // How many lobes should the sinc/Lanczos resizer use? More lobes require
  415. // more samples and avoid moire a bit better, but some is unavoidable
  416. // depending on the destination size (static option for now).
  417. static const float mask_sinc_lobes = 3.0; // range [2, 4]
  418. // The mask is resized using a variable number of taps in each dimension,
  419. // but some Cg profiles always fetch a constant number of taps no matter
  420. // what (no dynamic branching). We can limit the maximum number of taps if
  421. // we statically limit the minimum phosphor triad size. Larger values are
  422. // faster, but the limit IS enforced (static option only, forever);
  423. // range [1, mask_texture_small_size/mask_triads_per_tile]
  424. // TODO: Make this 1.0 and compensate with smarter sampling!
  425. static const float mask_min_allowed_triad_size = 2.0;
  426. // GEOMETRY:
  427. // Geometry mode:
  428. // 0: Off (default), 1: Spherical mapping (like cgwg's),
  429. // 2: Alt. spherical mapping (more bulbous), 3: Cylindrical/Trinitron
  430. static const float geom_mode_static = 0.0; // range [0, 3]
  431. // Radius of curvature: Measured in units of your viewport's diagonal size.
  432. static const float geom_radius_static = 2.0; // range [1/(2*pi), 1024]
  433. // View dist is the distance from the player to their physical screen, in
  434. // units of the viewport's diagonal size. It controls the field of view.
  435. static const float geom_view_dist_static = 2.0; // range [0.5, 1024]
  436. // Tilt angle in radians (clockwise around up and right vectors):
  437. static const float2 geom_tilt_angle_static = float2(0.0, 0.0); // range [-pi, pi]
  438. // Aspect ratio: When the true viewport size is unknown, this value is used
  439. // to help convert between the phosphor triad size and count, along with
  440. // the mask_resize_viewport_scale constant from user-cgp-constants.h. Set
  441. // this equal to Retroarch's display aspect ratio (DAR) for best results;
  442. // range [1, geom_max_aspect_ratio from user-cgp-constants.h];
  443. // default (256/224)*(54/47) = 1.313069909 (see below)
  444. static const float geom_aspect_ratio_static = 1.313069909;
  445. // Before getting into overscan, here's some general aspect ratio info:
  446. // - DAR = display aspect ratio = SAR * PAR; as in your Retroarch setting
  447. // - SAR = storage aspect ratio = DAR / PAR; square pixel emulator frame AR
  448. // - PAR = pixel aspect ratio = DAR / SAR; holds regardless of cropping
  449. // Geometry processing has to "undo" the screen-space 2D DAR to calculate
  450. // 3D view vectors, then reapplies the aspect ratio to the simulated CRT in
  451. // uv-space. To ensure the source SAR is intended for a ~4:3 DAR, either:
  452. // a.) Enable Retroarch's "Crop Overscan"
  453. // b.) Readd horizontal padding: Set overscan to e.g. N*(1.0, 240.0/224.0)
  454. // Real consoles use horizontal black padding in the signal, but emulators
  455. // often crop this without cropping the vertical padding; a 256x224 [S]NES
  456. // frame (8:7 SAR) is intended for a ~4:3 DAR, but a 256x240 frame is not.
  457. // The correct [S]NES PAR is 54:47, found by blargg and NewRisingSun:
  458. // http://board.zsnes.com/phpBB3/viewtopic.php?f=22&t=11928&start=50
  459. // http://forums.nesdev.com/viewtopic.php?p=24815#p24815
  460. // For flat output, it's okay to set DAR = [existing] SAR * [correct] PAR
  461. // without doing a. or b., but horizontal image borders will be tighter
  462. // than vertical ones, messing up curvature and overscan. Fixing the
  463. // padding first corrects this.
  464. // Overscan: Amount to "zoom in" before cropping. You can zoom uniformly
  465. // or adjust x/y independently to e.g. readd horizontal padding, as noted
  466. // above: Values < 1.0 zoom out; range (0, inf)
  467. static const float2 geom_overscan_static = float2(1.0, 1.0);// * 1.005 * (1.0, 240/224.0)
  468. // Compute a proper pixel-space to texture-space matrix even without ddx()/
  469. // ddy()? This is ~8.5% slower but improves antialiasing/subpixel filtering
  470. // with strong curvature (static option only for now).
  471. static const bool geom_force_correct_tangent_matrix = true;
  472. // BORDERS:
  473. // Rounded border size in texture uv coords:
  474. static const float border_size_static = 0.015; // range [0, 0.5]
  475. // Border darkness: Moderate values darken the border smoothly, and high
  476. // values make the image very dark just inside the border:
  477. static const float border_darkness_static = 2.0; // range [0, inf)
  478. // Border compression: High numbers compress border transitions, narrowing
  479. // the dark border area.
  480. static const float border_compress_static = 2.5; // range [1, inf)
  481. #endif // USER_SETTINGS_H
  482. //////////////////////////// END USER-SETTINGS //////////////////////////
  483. //#include "derived-settings-and-constants.h"
  484. //////////////////// BEGIN DERIVED-SETTINGS-AND-CONSTANTS ////////////////////
  485. #ifndef DERIVED_SETTINGS_AND_CONSTANTS_H
  486. #define DERIVED_SETTINGS_AND_CONSTANTS_H
  487. ///////////////////////////// GPL LICENSE NOTICE /////////////////////////////
  488. // crt-royale: A full-featured CRT shader, with cheese.
  489. // Copyright (C) 2014 TroggleMonkey <trogglemonkey@gmx.com>
  490. //
  491. // This program is free software; you can redistribute it and/or modify it
  492. // under the terms of the GNU General Public License as published by the Free
  493. // Software Foundation; either version 2 of the License, or any later version.
  494. //
  495. // This program is distributed in the hope that it will be useful, but WITHOUT
  496. // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  497. // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  498. // more details.
  499. //
  500. // You should have received a copy of the GNU General Public License along with
  501. // this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  502. // Place, Suite 330, Boston, MA 02111-1307 USA
  503. ///////////////////////////////// DESCRIPTION ////////////////////////////////
  504. // These macros and constants can be used across the whole codebase.
  505. // Unlike the values in user-settings.cgh, end users shouldn't modify these.
  506. /////////////////////////////// BEGIN INCLUDES ///////////////////////////////
  507. //#include "../user-settings.h"
  508. ///////////////////////////// BEGIN USER-SETTINGS ////////////////////////////
  509. #ifndef USER_SETTINGS_H
  510. #define USER_SETTINGS_H
  511. ///////////////////////////// DRIVER CAPABILITIES ////////////////////////////
  512. // The Cg compiler uses different "profiles" with different capabilities.
  513. // This shader requires a Cg compilation profile >= arbfp1, but a few options
  514. // require higher profiles like fp30 or fp40. The shader can't detect profile
  515. // or driver capabilities, so instead you must comment or uncomment the lines
  516. // below with "//" before "#define." Disable an option if you get compilation
  517. // errors resembling those listed. Generally speaking, all of these options
  518. // will run on nVidia cards, but only DRIVERS_ALLOW_TEX2DBIAS (if that) is
  519. // likely to run on ATI/AMD, due to the Cg compiler's profile limitations.
  520. // Derivatives: Unsupported on fp20, ps_1_1, ps_1_2, ps_1_3, and arbfp1.
  521. // Among other things, derivatives help us fix anisotropic filtering artifacts
  522. // with curved manually tiled phosphor mask coords. Related errors:
  523. // error C3004: function "float2 ddx(float2);" not supported in this profile
  524. // error C3004: function "float2 ddy(float2);" not supported in this profile
  525. //#define DRIVERS_ALLOW_DERIVATIVES
  526. // Fine derivatives: Unsupported on older ATI cards.
  527. // Fine derivatives enable 2x2 fragment block communication, letting us perform
  528. // fast single-pass blur operations. If your card uses coarse derivatives and
  529. // these are enabled, blurs could look broken. Derivatives are a prerequisite.
  530. #ifdef DRIVERS_ALLOW_DERIVATIVES
  531. #define DRIVERS_ALLOW_FINE_DERIVATIVES
  532. #endif
  533. // Dynamic looping: Requires an fp30 or newer profile.
  534. // This makes phosphor mask resampling faster in some cases. Related errors:
  535. // error C5013: profile does not support "for" statements and "for" could not
  536. // be unrolled
  537. //#define DRIVERS_ALLOW_DYNAMIC_BRANCHES
  538. // Without DRIVERS_ALLOW_DYNAMIC_BRANCHES, we need to use unrollable loops.
  539. // Using one static loop avoids overhead if the user is right, but if the user
  540. // is wrong (loops are allowed), breaking a loop into if-blocked pieces with a
  541. // binary search can potentially save some iterations. However, it may fail:
  542. // error C6001: Temporary register limit of 32 exceeded; 35 registers
  543. // needed to compile program
  544. //#define ACCOMODATE_POSSIBLE_DYNAMIC_LOOPS
  545. // tex2Dlod: Requires an fp40 or newer profile. This can be used to disable
  546. // anisotropic filtering, thereby fixing related artifacts. Related errors:
  547. // error C3004: function "float4 tex2Dlod(sampler2D, float4);" not supported in
  548. // this profile
  549. //#define DRIVERS_ALLOW_TEX2DLOD
  550. // tex2Dbias: Requires an fp30 or newer profile. This can be used to alleviate
  551. // artifacts from anisotropic filtering and mipmapping. Related errors:
  552. // error C3004: function "float4 tex2Dbias(sampler2D, float4);" not supported
  553. // in this profile
  554. //#define DRIVERS_ALLOW_TEX2DBIAS
  555. // Integrated graphics compatibility: Integrated graphics like Intel HD 4000
  556. // impose stricter limitations on register counts and instructions. Enable
  557. // INTEGRATED_GRAPHICS_COMPATIBILITY_MODE if you still see error C6001 or:
  558. // error C6002: Instruction limit of 1024 exceeded: 1523 instructions needed
  559. // to compile program.
  560. // Enabling integrated graphics compatibility mode will automatically disable:
  561. // 1.) PHOSPHOR_MASK_MANUALLY_RESIZE: The phosphor mask will be softer.
  562. // (This may be reenabled in a later release.)
  563. // 2.) RUNTIME_GEOMETRY_MODE
  564. // 3.) The high-quality 4x4 Gaussian resize for the bloom approximation
  565. //#define INTEGRATED_GRAPHICS_COMPATIBILITY_MODE
  566. //////////////////////////// USER CODEPATH OPTIONS ///////////////////////////
  567. // To disable a #define option, turn its line into a comment with "//."
  568. // RUNTIME VS. COMPILE-TIME OPTIONS (Major Performance Implications):
  569. // Enable runtime shader parameters in the Retroarch (etc.) GUI? They override
  570. // many of the options in this file and allow real-time tuning, but many of
  571. // them are slower. Disabling them and using this text file will boost FPS.
  572. #define RUNTIME_SHADER_PARAMS_ENABLE
  573. // Specify the phosphor bloom sigma at runtime? This option is 10% slower, but
  574. // it's the only way to do a wide-enough full bloom with a runtime dot pitch.
  575. #define RUNTIME_PHOSPHOR_BLOOM_SIGMA
  576. // Specify antialiasing weight parameters at runtime? (Costs ~20% with cubics)
  577. #define RUNTIME_ANTIALIAS_WEIGHTS
  578. // Specify subpixel offsets at runtime? (WARNING: EXTREMELY EXPENSIVE!)
  579. //#define RUNTIME_ANTIALIAS_SUBPIXEL_OFFSETS
  580. // Make beam_horiz_filter and beam_horiz_linear_rgb_weight into runtime shader
  581. // parameters? This will require more math or dynamic branching.
  582. #define RUNTIME_SCANLINES_HORIZ_FILTER_COLORSPACE
  583. // Specify the tilt at runtime? This makes things about 3% slower.
  584. #define RUNTIME_GEOMETRY_TILT
  585. // Specify the geometry mode at runtime?
  586. #define RUNTIME_GEOMETRY_MODE
  587. // Specify the phosphor mask type (aperture grille, slot mask, shadow mask) and
  588. // mode (Lanczos-resize, hardware resize, or tile 1:1) at runtime, even without
  589. // dynamic branches? This is cheap if mask_resize_viewport_scale is small.
  590. #define FORCE_RUNTIME_PHOSPHOR_MASK_MODE_TYPE_SELECT
  591. // PHOSPHOR MASK:
  592. // Manually resize the phosphor mask for best results (slower)? Disabling this
  593. // removes the option to do so, but it may be faster without dynamic branches.
  594. #define PHOSPHOR_MASK_MANUALLY_RESIZE
  595. // If we sinc-resize the mask, should we Lanczos-window it (slower but better)?
  596. #define PHOSPHOR_MASK_RESIZE_LANCZOS_WINDOW
  597. // Larger blurs are expensive, but we need them to blur larger triads. We can
  598. // detect the right blur if the triad size is static or our profile allows
  599. // dynamic branches, but otherwise we use the largest blur the user indicates
  600. // they might need:
  601. #define PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_3_PIXELS
  602. //#define PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_6_PIXELS
  603. //#define PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_9_PIXELS
  604. //#define PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_12_PIXELS
  605. // Here's a helpful chart:
  606. // MaxTriadSize BlurSize MinTriadCountsByResolution
  607. // 3.0 9.0 480/640/960/1920 triads at 1080p/1440p/2160p/4320p, 4:3 aspect
  608. // 6.0 17.0 240/320/480/960 triads at 1080p/1440p/2160p/4320p, 4:3 aspect
  609. // 9.0 25.0 160/213/320/640 triads at 1080p/1440p/2160p/4320p, 4:3 aspect
  610. // 12.0 31.0 120/160/240/480 triads at 1080p/1440p/2160p/4320p, 4:3 aspect
  611. // 18.0 43.0 80/107/160/320 triads at 1080p/1440p/2160p/4320p, 4:3 aspect
  612. /////////////////////////////// USER PARAMETERS //////////////////////////////
  613. // Note: Many of these static parameters are overridden by runtime shader
  614. // parameters when those are enabled. However, many others are static codepath
  615. // options that were cleaner or more convert to code as static constants.
  616. // GAMMA:
  617. static const float crt_gamma_static = 2.5; // range [1, 5]
  618. static const float lcd_gamma_static = 2.2; // range [1, 5]
  619. // LEVELS MANAGEMENT:
  620. // Control the final multiplicative image contrast:
  621. static const float levels_contrast_static = 1.0; // range [0, 4)
  622. // We auto-dim to avoid clipping between passes and restore brightness
  623. // later. Control the dim factor here: Lower values clip less but crush
  624. // blacks more (static only for now).
  625. static const float levels_autodim_temp = 0.5; // range (0, 1] default is 0.5 but that was unnecessarily dark for me, so I set it to 1.0
  626. // HALATION/DIFFUSION/BLOOM:
  627. // Halation weight: How much energy should be lost to electrons bounding
  628. // around under the CRT glass and exciting random phosphors?
  629. static const float halation_weight_static = 0.0; // range [0, 1]
  630. // Refractive diffusion weight: How much light should spread/diffuse from
  631. // refracting through the CRT glass?
  632. static const float diffusion_weight_static = 0.075; // range [0, 1]
  633. // Underestimate brightness: Bright areas bloom more, but we can base the
  634. // bloom brightpass on a lower brightness to sharpen phosphors, or a higher
  635. // brightness to soften them. Low values clip, but >= 0.8 looks okay.
  636. static const float bloom_underestimate_levels_static = 0.8; // range [0, 5]
  637. // Blur all colors more than necessary for a softer phosphor bloom?
  638. static const float bloom_excess_static = 0.0; // range [0, 1]
  639. // The BLOOM_APPROX pass approximates a phosphor blur early on with a small
  640. // blurred resize of the input (convergence offsets are applied as well).
  641. // There are three filter options (static option only for now):
  642. // 0.) Bilinear resize: A fast, close approximation to a 4x4 resize
  643. // if min_allowed_viewport_triads and the BLOOM_APPROX resolution are sane
  644. // and beam_max_sigma is low.
  645. // 1.) 3x3 resize blur: Medium speed, soft/smeared from bilinear blurring,
  646. // always uses a static sigma regardless of beam_max_sigma or
  647. // mask_num_triads_desired.
  648. // 2.) True 4x4 Gaussian resize: Slowest, technically correct.
  649. // These options are more pronounced for the fast, unbloomed shader version.
  650. #ifndef RADEON_FIX
  651. static const float bloom_approx_filter_static = 2.0;
  652. #else
  653. static const float bloom_approx_filter_static = 1.0;
  654. #endif
  655. // ELECTRON BEAM SCANLINE DISTRIBUTION:
  656. // How many scanlines should contribute light to each pixel? Using more
  657. // scanlines is slower (especially for a generalized Gaussian) but less
  658. // distorted with larger beam sigmas (especially for a pure Gaussian). The
  659. // max_beam_sigma at which the closest unused weight is guaranteed <
  660. // 1.0/255.0 (for a 3x antialiased pure Gaussian) is:
  661. // 2 scanlines: max_beam_sigma = 0.2089; distortions begin ~0.34; 141.7 FPS pure, 131.9 FPS generalized
  662. // 3 scanlines, max_beam_sigma = 0.3879; distortions begin ~0.52; 137.5 FPS pure; 123.8 FPS generalized
  663. // 4 scanlines, max_beam_sigma = 0.5723; distortions begin ~0.70; 134.7 FPS pure; 117.2 FPS generalized
  664. // 5 scanlines, max_beam_sigma = 0.7591; distortions begin ~0.89; 131.6 FPS pure; 112.1 FPS generalized
  665. // 6 scanlines, max_beam_sigma = 0.9483; distortions begin ~1.08; 127.9 FPS pure; 105.6 FPS generalized
  666. static const float beam_num_scanlines = 3.0; // range [2, 6]
  667. // A generalized Gaussian beam varies shape with color too, now just width.
  668. // It's slower but more flexible (static option only for now).
  669. static const bool beam_generalized_gaussian = true;
  670. // What kind of scanline antialiasing do you want?
  671. // 0: Sample weights at 1x; 1: Sample weights at 3x; 2: Compute an integral
  672. // Integrals are slow (especially for generalized Gaussians) and rarely any
  673. // better than 3x antialiasing (static option only for now).
  674. static const float beam_antialias_level = 1.0; // range [0, 2]
  675. // Min/max standard deviations for scanline beams: Higher values widen and
  676. // soften scanlines. Depending on other options, low min sigmas can alias.
  677. static const float beam_min_sigma_static = 0.02; // range (0, 1]
  678. static const float beam_max_sigma_static = 0.3; // range (0, 1]
  679. // Beam width varies as a function of color: A power function (0) is more
  680. // configurable, but a spherical function (1) gives the widest beam
  681. // variability without aliasing (static option only for now).
  682. static const float beam_spot_shape_function = 0.0;
  683. // Spot shape power: Powers <= 1 give smoother spot shapes but lower
  684. // sharpness. Powers >= 1.0 are awful unless mix/max sigmas are close.
  685. static const float beam_spot_power_static = 1.0/3.0; // range (0, 16]
  686. // Generalized Gaussian max shape parameters: Higher values give flatter
  687. // scanline plateaus and steeper dropoffs, simultaneously widening and
  688. // sharpening scanlines at the cost of aliasing. 2.0 is pure Gaussian, and
  689. // values > ~40.0 cause artifacts with integrals.
  690. static const float beam_min_shape_static = 2.0; // range [2, 32]
  691. static const float beam_max_shape_static = 4.0; // range [2, 32]
  692. // Generalized Gaussian shape power: Affects how quickly the distribution
  693. // changes shape from Gaussian to steep/plateaued as color increases from 0
  694. // to 1.0. Higher powers appear softer for most colors, and lower powers
  695. // appear sharper for most colors.
  696. static const float beam_shape_power_static = 1.0/4.0; // range (0, 16]
  697. // What filter should be used to sample scanlines horizontally?
  698. // 0: Quilez (fast), 1: Gaussian (configurable), 2: Lanczos2 (sharp)
  699. static const float beam_horiz_filter_static = 0.0;
  700. // Standard deviation for horizontal Gaussian resampling:
  701. static const float beam_horiz_sigma_static = 0.35; // range (0, 2/3]
  702. // Do horizontal scanline sampling in linear RGB (correct light mixing),
  703. // gamma-encoded RGB (darker, hard spot shape, may better match bandwidth-
  704. // limiting circuitry in some CRT's), or a weighted avg.?
  705. static const float beam_horiz_linear_rgb_weight_static = 1.0; // range [0, 1]
  706. // Simulate scanline misconvergence? This needs 3x horizontal texture
  707. // samples and 3x texture samples of BLOOM_APPROX and HALATION_BLUR in
  708. // later passes (static option only for now).
  709. static const bool beam_misconvergence = true;
  710. // Convergence offsets in x/y directions for R/G/B scanline beams in units
  711. // of scanlines. Positive offsets go right/down; ranges [-2, 2]
  712. static const float2 convergence_offsets_r_static = float2(0.1, 0.2);
  713. static const float2 convergence_offsets_g_static = float2(0.3, 0.4);
  714. static const float2 convergence_offsets_b_static = float2(0.5, 0.6);
  715. // Detect interlacing (static option only for now)?
  716. static const bool interlace_detect = true;
  717. // Assume 1080-line sources are interlaced?
  718. static const bool interlace_1080i_static = false;
  719. // For interlaced sources, assume TFF (top-field first) or BFF order?
  720. // (Whether this matters depends on the nature of the interlaced input.)
  721. static const bool interlace_bff_static = false;
  722. // ANTIALIASING:
  723. // What AA level do you want for curvature/overscan/subpixels? Options:
  724. // 0x (none), 1x (sample subpixels), 4x, 5x, 6x, 7x, 8x, 12x, 16x, 20x, 24x
  725. // (Static option only for now)
  726. static const float aa_level = 12.0; // range [0, 24]
  727. // What antialiasing filter do you want (static option only)? Options:
  728. // 0: Box (separable), 1: Box (cylindrical),
  729. // 2: Tent (separable), 3: Tent (cylindrical),
  730. // 4: Gaussian (separable), 5: Gaussian (cylindrical),
  731. // 6: Cubic* (separable), 7: Cubic* (cylindrical, poor)
  732. // 8: Lanczos Sinc (separable), 9: Lanczos Jinc (cylindrical, poor)
  733. // * = Especially slow with RUNTIME_ANTIALIAS_WEIGHTS
  734. static const float aa_filter = 6.0; // range [0, 9]
  735. // Flip the sample grid on odd/even frames (static option only for now)?
  736. static const bool aa_temporal = false;
  737. // Use RGB subpixel offsets for antialiasing? The pixel is at green, and
  738. // the blue offset is the negative r offset; range [0, 0.5]
  739. static const float2 aa_subpixel_r_offset_static = float2(-1.0/3.0, 0.0);//float2(0.0);
  740. // Cubics: See http://www.imagemagick.org/Usage/filter/#mitchell
  741. // 1.) "Keys cubics" with B = 1 - 2C are considered the highest quality.
  742. // 2.) C = 0.5 (default) is Catmull-Rom; higher C's apply sharpening.
  743. // 3.) C = 1.0/3.0 is the Mitchell-Netravali filter.
  744. // 4.) C = 0.0 is a soft spline filter.
  745. static const float aa_cubic_c_static = 0.5; // range [0, 4]
  746. // Standard deviation for Gaussian antialiasing: Try 0.5/aa_pixel_diameter.
  747. static const float aa_gauss_sigma_static = 0.5; // range [0.0625, 1.0]
  748. // PHOSPHOR MASK:
  749. // Mask type: 0 = aperture grille, 1 = slot mask, 2 = EDP shadow mask
  750. static const float mask_type_static = 1.0; // range [0, 2]
  751. // We can sample the mask three ways. Pick 2/3 from: Pretty/Fast/Flexible.
  752. // 0.) Sinc-resize to the desired dot pitch manually (pretty/slow/flexible).
  753. // This requires PHOSPHOR_MASK_MANUALLY_RESIZE to be #defined.
  754. // 1.) Hardware-resize to the desired dot pitch (ugly/fast/flexible). This
  755. // is halfway decent with LUT mipmapping but atrocious without it.
  756. // 2.) Tile it without resizing at a 1:1 texel:pixel ratio for flat coords
  757. // (pretty/fast/inflexible). Each input LUT has a fixed dot pitch.
  758. // This mode reuses the same masks, so triads will be enormous unless
  759. // you change the mask LUT filenames in your .cgp file.
  760. static const float mask_sample_mode_static = 0.0; // range [0, 2]
  761. // Prefer setting the triad size (0.0) or number on the screen (1.0)?
  762. // If RUNTIME_PHOSPHOR_BLOOM_SIGMA isn't #defined, the specified triad size
  763. // will always be used to calculate the full bloom sigma statically.
  764. static const float mask_specify_num_triads_static = 0.0; // range [0, 1]
  765. // Specify the phosphor triad size, in pixels. Each tile (usually with 8
  766. // triads) will be rounded to the nearest integer tile size and clamped to
  767. // obey minimum size constraints (imposed to reduce downsize taps) and
  768. // maximum size constraints (imposed to have a sane MASK_RESIZE FBO size).
  769. // To increase the size limit, double the viewport-relative scales for the
  770. // two MASK_RESIZE passes in crt-royale.cgp and user-cgp-contants.h.
  771. // range [1, mask_texture_small_size/mask_triads_per_tile]
  772. static const float mask_triad_size_desired_static = 24.0 / 8.0;
  773. // If mask_specify_num_triads is 1.0/true, we'll go by this instead (the
  774. // final size will be rounded and constrained as above); default 480.0
  775. static const float mask_num_triads_desired_static = 480.0;
  776. // How many lobes should the sinc/Lanczos resizer use? More lobes require
  777. // more samples and avoid moire a bit better, but some is unavoidable
  778. // depending on the destination size (static option for now).
  779. static const float mask_sinc_lobes = 3.0; // range [2, 4]
  780. // The mask is resized using a variable number of taps in each dimension,
  781. // but some Cg profiles always fetch a constant number of taps no matter
  782. // what (no dynamic branching). We can limit the maximum number of taps if
  783. // we statically limit the minimum phosphor triad size. Larger values are
  784. // faster, but the limit IS enforced (static option only, forever);
  785. // range [1, mask_texture_small_size/mask_triads_per_tile]
  786. // TODO: Make this 1.0 and compensate with smarter sampling!
  787. static const float mask_min_allowed_triad_size = 2.0;
  788. // GEOMETRY:
  789. // Geometry mode:
  790. // 0: Off (default), 1: Spherical mapping (like cgwg's),
  791. // 2: Alt. spherical mapping (more bulbous), 3: Cylindrical/Trinitron
  792. static const float geom_mode_static = 0.0; // range [0, 3]
  793. // Radius of curvature: Measured in units of your viewport's diagonal size.
  794. static const float geom_radius_static = 2.0; // range [1/(2*pi), 1024]
  795. // View dist is the distance from the player to their physical screen, in
  796. // units of the viewport's diagonal size. It controls the field of view.
  797. static const float geom_view_dist_static = 2.0; // range [0.5, 1024]
  798. // Tilt angle in radians (clockwise around up and right vectors):
  799. static const float2 geom_tilt_angle_static = float2(0.0, 0.0); // range [-pi, pi]
  800. // Aspect ratio: When the true viewport size is unknown, this value is used
  801. // to help convert between the phosphor triad size and count, along with
  802. // the mask_resize_viewport_scale constant from user-cgp-constants.h. Set
  803. // this equal to Retroarch's display aspect ratio (DAR) for best results;
  804. // range [1, geom_max_aspect_ratio from user-cgp-constants.h];
  805. // default (256/224)*(54/47) = 1.313069909 (see below)
  806. static const float geom_aspect_ratio_static = 1.313069909;
  807. // Before getting into overscan, here's some general aspect ratio info:
  808. // - DAR = display aspect ratio = SAR * PAR; as in your Retroarch setting
  809. // - SAR = storage aspect ratio = DAR / PAR; square pixel emulator frame AR
  810. // - PAR = pixel aspect ratio = DAR / SAR; holds regardless of cropping
  811. // Geometry processing has to "undo" the screen-space 2D DAR to calculate
  812. // 3D view vectors, then reapplies the aspect ratio to the simulated CRT in
  813. // uv-space. To ensure the source SAR is intended for a ~4:3 DAR, either:
  814. // a.) Enable Retroarch's "Crop Overscan"
  815. // b.) Readd horizontal padding: Set overscan to e.g. N*(1.0, 240.0/224.0)
  816. // Real consoles use horizontal black padding in the signal, but emulators
  817. // often crop this without cropping the vertical padding; a 256x224 [S]NES
  818. // frame (8:7 SAR) is intended for a ~4:3 DAR, but a 256x240 frame is not.
  819. // The correct [S]NES PAR is 54:47, found by blargg and NewRisingSun:
  820. // http://board.zsnes.com/phpBB3/viewtopic.php?f=22&t=11928&start=50
  821. // http://forums.nesdev.com/viewtopic.php?p=24815#p24815
  822. // For flat output, it's okay to set DAR = [existing] SAR * [correct] PAR
  823. // without doing a. or b., but horizontal image borders will be tighter
  824. // than vertical ones, messing up curvature and overscan. Fixing the
  825. // padding first corrects this.
  826. // Overscan: Amount to "zoom in" before cropping. You can zoom uniformly
  827. // or adjust x/y independently to e.g. readd horizontal padding, as noted
  828. // above: Values < 1.0 zoom out; range (0, inf)
  829. static const float2 geom_overscan_static = float2(1.0, 1.0);// * 1.005 * (1.0, 240/224.0)
  830. // Compute a proper pixel-space to texture-space matrix even without ddx()/
  831. // ddy()? This is ~8.5% slower but improves antialiasing/subpixel filtering
  832. // with strong curvature (static option only for now).
  833. static const bool geom_force_correct_tangent_matrix = true;
  834. // BORDERS:
  835. // Rounded border size in texture uv coords:
  836. static const float border_size_static = 0.015; // range [0, 0.5]
  837. // Border darkness: Moderate values darken the border smoothly, and high
  838. // values make the image very dark just inside the border:
  839. static const float border_darkness_static = 2.0; // range [0, inf)
  840. // Border compression: High numbers compress border transitions, narrowing
  841. // the dark border area.
  842. static const float border_compress_static = 2.5; // range [1, inf)
  843. #endif // USER_SETTINGS_H
  844. ///////////////////////////// END USER-SETTINGS ////////////////////////////
  845. //#include "user-cgp-constants.h"
  846. ///////////////////////// BEGIN USER-CGP-CONSTANTS /////////////////////////
  847. #ifndef USER_CGP_CONSTANTS_H
  848. #define USER_CGP_CONSTANTS_H
  849. // IMPORTANT:
  850. // These constants MUST be set appropriately for the settings in crt-royale.cgp
  851. // (or whatever related .cgp file you're using). If they aren't, you're likely
  852. // to get artifacts, the wrong phosphor mask size, etc. I wish these could be
  853. // set directly in the .cgp file to make things easier, but...they can't.
  854. // PASS SCALES AND RELATED CONSTANTS:
  855. // Copy the absolute scale_x for BLOOM_APPROX. There are two major versions of
  856. // this shader: One does a viewport-scale bloom, and the other skips it. The
  857. // latter benefits from a higher bloom_approx_scale_x, so save both separately:
  858. static const float bloom_approx_size_x = 320.0;
  859. static const float bloom_approx_size_x_for_fake = 400.0;
  860. // Copy the viewport-relative scales of the phosphor mask resize passes
  861. // (MASK_RESIZE and the pass immediately preceding it):
  862. static const float2 mask_resize_viewport_scale = float2(0.0625, 0.0625);
  863. // Copy the geom_max_aspect_ratio used to calculate the MASK_RESIZE scales, etc.:
  864. static const float geom_max_aspect_ratio = 4.0/3.0;
  865. // PHOSPHOR MASK TEXTURE CONSTANTS:
  866. // Set the following constants to reflect the properties of the phosphor mask
  867. // texture named in crt-royale.cgp. The shader optionally resizes a mask tile
  868. // based on user settings, then repeats a single tile until filling the screen.
  869. // The shader must know the input texture size (default 64x64), and to manually
  870. // resize, it must also know the horizontal triads per tile (default 8).
  871. static const float2 mask_texture_small_size = float2(64.0, 64.0);
  872. static const float2 mask_texture_large_size = float2(512.0, 512.0);
  873. static const float mask_triads_per_tile = 8.0;
  874. // We need the average brightness of the phosphor mask to compensate for the
  875. // dimming it causes. The following four values are roughly correct for the
  876. // masks included with the shader. Update the value for any LUT texture you
  877. // change. [Un]comment "#define PHOSPHOR_MASK_GRILLE14" depending on whether
  878. // the loaded aperture grille uses 14-pixel or 15-pixel stripes (default 15).
  879. //#define PHOSPHOR_MASK_GRILLE14
  880. static const float mask_grille14_avg_color = 50.6666666/255.0;
  881. // TileableLinearApertureGrille14Wide7d33Spacing*.png
  882. // TileableLinearApertureGrille14Wide10And6Spacing*.png
  883. static const float mask_grille15_avg_color = 53.0/255.0;
  884. // TileableLinearApertureGrille15Wide6d33Spacing*.png
  885. // TileableLinearApertureGrille15Wide8And5d5Spacing*.png
  886. static const float mask_slot_avg_color = 46.0/255.0;
  887. // TileableLinearSlotMask15Wide9And4d5Horizontal8VerticalSpacing*.png
  888. // TileableLinearSlotMaskTall15Wide9And4d5Horizontal9d14VerticalSpacing*.png
  889. static const float mask_shadow_avg_color = 41.0/255.0;
  890. // TileableLinearShadowMask*.png
  891. // TileableLinearShadowMaskEDP*.png
  892. #ifdef PHOSPHOR_MASK_GRILLE14
  893. static const float mask_grille_avg_color = mask_grille14_avg_color;
  894. #else
  895. static const float mask_grille_avg_color = mask_grille15_avg_color;
  896. #endif
  897. #endif // USER_CGP_CONSTANTS_H
  898. ////////////////////////// END USER-CGP-CONSTANTS //////////////////////////
  899. //////////////////////////////// END INCLUDES ////////////////////////////////
  900. /////////////////////////////// FIXED SETTINGS ///////////////////////////////
  901. // Avoid dividing by zero; using a macro overloads for float, float2, etc.:
  902. #define FIX_ZERO(c) (max(abs(c), 0.0000152587890625)) // 2^-16
  903. // Ensure the first pass decodes CRT gamma and the last encodes LCD gamma.
  904. #ifndef SIMULATE_CRT_ON_LCD
  905. #define SIMULATE_CRT_ON_LCD
  906. #endif
  907. // Manually tiling a manually resized texture creates texture coord derivative
  908. // discontinuities and confuses anisotropic filtering, causing discolored tile
  909. // seams in the phosphor mask. Workarounds:
  910. // a.) Using tex2Dlod disables anisotropic filtering for tiled masks. It's
  911. // downgraded to tex2Dbias without DRIVERS_ALLOW_TEX2DLOD #defined and
  912. // disabled without DRIVERS_ALLOW_TEX2DBIAS #defined either.
  913. // b.) "Tile flat twice" requires drawing two full tiles without border padding
  914. // to the resized mask FBO, and it's incompatible with same-pass curvature.
  915. // (Same-pass curvature isn't used but could be in the future...maybe.)
  916. // c.) "Fix discontinuities" requires derivatives and drawing one tile with
  917. // border padding to the resized mask FBO, but it works with same-pass
  918. // curvature. It's disabled without DRIVERS_ALLOW_DERIVATIVES #defined.
  919. // Precedence: a, then, b, then c (if multiple strategies are #defined).
  920. #define ANISOTROPIC_TILING_COMPAT_TEX2DLOD // 129.7 FPS, 4x, flat; 101.8 at fullscreen
  921. #define ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE // 128.1 FPS, 4x, flat; 101.5 at fullscreen
  922. #define ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES // 124.4 FPS, 4x, flat; 97.4 at fullscreen
  923. // Also, manually resampling the phosphor mask is slightly blurrier with
  924. // anisotropic filtering. (Resampling with mipmapping is even worse: It
  925. // creates artifacts, but only with the fully bloomed shader.) The difference
  926. // is subtle with small triads, but you can fix it for a small cost.
  927. //#define ANISOTROPIC_RESAMPLING_COMPAT_TEX2DLOD
  928. ////////////////////////////// DERIVED SETTINGS //////////////////////////////
  929. // Intel HD 4000 GPU's can't handle manual mask resizing (for now), setting the
  930. // geometry mode at runtime, or a 4x4 true Gaussian resize. Disable
  931. // incompatible settings ASAP. (INTEGRATED_GRAPHICS_COMPATIBILITY_MODE may be
  932. // #defined by either user-settings.h or a wrapper .cg that #includes the
  933. // current .cg pass.)
  934. #ifdef INTEGRATED_GRAPHICS_COMPATIBILITY_MODE
  935. #ifdef PHOSPHOR_MASK_MANUALLY_RESIZE
  936. #undef PHOSPHOR_MASK_MANUALLY_RESIZE
  937. #endif
  938. #ifdef RUNTIME_GEOMETRY_MODE
  939. #undef RUNTIME_GEOMETRY_MODE
  940. #endif
  941. // Mode 2 (4x4 Gaussian resize) won't work, and mode 1 (3x3 blur) is
  942. // inferior in most cases, so replace 2.0 with 0.0:
  943. static const float bloom_approx_filter =
  944. bloom_approx_filter_static > 1.5 ? 0.0 : bloom_approx_filter_static;
  945. #else
  946. static const float bloom_approx_filter = bloom_approx_filter_static;
  947. #endif
  948. // Disable slow runtime paths if static parameters are used. Most of these
  949. // won't be a problem anyway once the params are disabled, but some will.
  950. #ifndef RUNTIME_SHADER_PARAMS_ENABLE
  951. #ifdef RUNTIME_PHOSPHOR_BLOOM_SIGMA
  952. #undef RUNTIME_PHOSPHOR_BLOOM_SIGMA
  953. #endif
  954. #ifdef RUNTIME_ANTIALIAS_WEIGHTS
  955. #undef RUNTIME_ANTIALIAS_WEIGHTS
  956. #endif
  957. #ifdef RUNTIME_ANTIALIAS_SUBPIXEL_OFFSETS
  958. #undef RUNTIME_ANTIALIAS_SUBPIXEL_OFFSETS
  959. #endif
  960. #ifdef RUNTIME_SCANLINES_HORIZ_FILTER_COLORSPACE
  961. #undef RUNTIME_SCANLINES_HORIZ_FILTER_COLORSPACE
  962. #endif
  963. #ifdef RUNTIME_GEOMETRY_TILT
  964. #undef RUNTIME_GEOMETRY_TILT
  965. #endif
  966. #ifdef RUNTIME_GEOMETRY_MODE
  967. #undef RUNTIME_GEOMETRY_MODE
  968. #endif
  969. #ifdef FORCE_RUNTIME_PHOSPHOR_MASK_MODE_TYPE_SELECT
  970. #undef FORCE_RUNTIME_PHOSPHOR_MASK_MODE_TYPE_SELECT
  971. #endif
  972. #endif
  973. // Make tex2Dbias a backup for tex2Dlod for wider compatibility.
  974. #ifdef ANISOTROPIC_TILING_COMPAT_TEX2DLOD
  975. #define ANISOTROPIC_TILING_COMPAT_TEX2DBIAS
  976. #endif
  977. #ifdef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DLOD
  978. #define ANISOTROPIC_RESAMPLING_COMPAT_TEX2DBIAS
  979. #endif
  980. // Rule out unavailable anisotropic compatibility strategies:
  981. #ifndef DRIVERS_ALLOW_DERIVATIVES
  982. #ifdef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
  983. #undef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
  984. #endif
  985. #endif
  986. #ifndef DRIVERS_ALLOW_TEX2DLOD
  987. #ifdef ANISOTROPIC_TILING_COMPAT_TEX2DLOD
  988. #undef ANISOTROPIC_TILING_COMPAT_TEX2DLOD
  989. #endif
  990. #ifdef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DLOD
  991. #undef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DLOD
  992. #endif
  993. #ifdef ANTIALIAS_DISABLE_ANISOTROPIC
  994. #undef ANTIALIAS_DISABLE_ANISOTROPIC
  995. #endif
  996. #endif
  997. #ifndef DRIVERS_ALLOW_TEX2DBIAS
  998. #ifdef ANISOTROPIC_TILING_COMPAT_TEX2DBIAS
  999. #undef ANISOTROPIC_TILING_COMPAT_TEX2DBIAS
  1000. #endif
  1001. #ifdef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DBIAS
  1002. #undef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DBIAS
  1003. #endif
  1004. #endif
  1005. // Prioritize anisotropic tiling compatibility strategies by performance and
  1006. // disable unused strategies. This concentrates all the nesting in one place.
  1007. #ifdef ANISOTROPIC_TILING_COMPAT_TEX2DLOD
  1008. #ifdef ANISOTROPIC_TILING_COMPAT_TEX2DBIAS
  1009. #undef ANISOTROPIC_TILING_COMPAT_TEX2DBIAS
  1010. #endif
  1011. #ifdef ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE
  1012. #undef ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE
  1013. #endif
  1014. #ifdef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
  1015. #undef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
  1016. #endif
  1017. #else
  1018. #ifdef ANISOTROPIC_TILING_COMPAT_TEX2DBIAS
  1019. #ifdef ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE
  1020. #undef ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE
  1021. #endif
  1022. #ifdef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
  1023. #undef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
  1024. #endif
  1025. #else
  1026. // ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE is only compatible with
  1027. // flat texture coords in the same pass, but that's all we use.
  1028. #ifdef ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE
  1029. #ifdef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
  1030. #undef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
  1031. #endif
  1032. #endif
  1033. #endif
  1034. #endif
  1035. // The tex2Dlod and tex2Dbias strategies share a lot in common, and we can
  1036. // reduce some #ifdef nesting in the next section by essentially OR'ing them:
  1037. #ifdef ANISOTROPIC_TILING_COMPAT_TEX2DLOD
  1038. #define ANISOTROPIC_TILING_COMPAT_TEX2DLOD_FAMILY
  1039. #endif
  1040. #ifdef ANISOTROPIC_TILING_COMPAT_TEX2DBIAS
  1041. #define ANISOTROPIC_TILING_COMPAT_TEX2DLOD_FAMILY
  1042. #endif
  1043. // Prioritize anisotropic resampling compatibility strategies the same way:
  1044. #ifdef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DLOD
  1045. #ifdef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DBIAS
  1046. #undef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DBIAS
  1047. #endif
  1048. #endif
  1049. /////////////////////// DERIVED PHOSPHOR MASK CONSTANTS //////////////////////
  1050. // If we can use the large mipmapped LUT without mipmapping artifacts, we
  1051. // should: It gives us more options for using fewer samples.
  1052. #ifdef DRIVERS_ALLOW_TEX2DLOD
  1053. #ifdef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DLOD
  1054. // TODO: Take advantage of this!
  1055. #define PHOSPHOR_MASK_RESIZE_MIPMAPPED_LUT
  1056. static const float2 mask_resize_src_lut_size = mask_texture_large_size;
  1057. #else
  1058. static const float2 mask_resize_src_lut_size = mask_texture_small_size;
  1059. #endif
  1060. #else
  1061. static const float2 mask_resize_src_lut_size = mask_texture_small_size;
  1062. #endif
  1063. // tex2D's sampler2D parameter MUST be a uniform global, a uniform input to
  1064. // main_fragment, or a static alias of one of the above. This makes it hard
  1065. // to select the phosphor mask at runtime: We can't even assign to a uniform
  1066. // global in the vertex shader or select a sampler2D in the vertex shader and
  1067. // pass it to the fragment shader (even with explicit TEXUNIT# bindings),
  1068. // because it just gives us the input texture or a black screen. However, we
  1069. // can get around these limitations by calling tex2D three times with different
  1070. // uniform samplers (or resizing the phosphor mask three times altogether).
  1071. // With dynamic branches, we can process only one of these branches on top of
  1072. // quickly discarding fragments we don't need (cgc seems able to overcome
  1073. // limigations around dependent texture fetches inside of branches). Without
  1074. // dynamic branches, we have to process every branch for every fragment...which
  1075. // is slower. Runtime sampling mode selection is slower without dynamic
  1076. // branches as well. Let the user's static #defines decide if it's worth it.
  1077. #ifdef DRIVERS_ALLOW_DYNAMIC_BRANCHES
  1078. #define RUNTIME_PHOSPHOR_MASK_MODE_TYPE_SELECT
  1079. #else
  1080. #ifdef FORCE_RUNTIME_PHOSPHOR_MASK_MODE_TYPE_SELECT
  1081. #define RUNTIME_PHOSPHOR_MASK_MODE_TYPE_SELECT
  1082. #endif
  1083. #endif
  1084. // We need to render some minimum number of tiles in the resize passes.
  1085. // We need at least 1.0 just to repeat a single tile, and we need extra
  1086. // padding beyond that for anisotropic filtering, discontinuitity fixing,
  1087. // antialiasing, same-pass curvature (not currently used), etc. First
  1088. // determine how many border texels and tiles we need, based on how the result
  1089. // will be sampled:
  1090. #ifdef GEOMETRY_EARLY
  1091. static const float max_subpixel_offset = aa_subpixel_r_offset_static.x;
  1092. // Most antialiasing filters have a base radius of 4.0 pixels:
  1093. static const float max_aa_base_pixel_border = 4.0 +
  1094. max_subpixel_offset;
  1095. #else
  1096. static const float max_aa_base_pixel_border = 0.0;
  1097. #endif
  1098. // Anisotropic filtering adds about 0.5 to the pixel border:
  1099. #ifndef ANISOTROPIC_TILING_COMPAT_TEX2DLOD_FAMILY
  1100. static const float max_aniso_pixel_border = max_aa_base_pixel_border + 0.5;
  1101. #else
  1102. static const float max_aniso_pixel_border = max_aa_base_pixel_border;
  1103. #endif
  1104. // Fixing discontinuities adds 1.0 more to the pixel border:
  1105. #ifdef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
  1106. static const float max_tiled_pixel_border = max_aniso_pixel_border + 1.0;
  1107. #else
  1108. static const float max_tiled_pixel_border = max_aniso_pixel_border;
  1109. #endif
  1110. // Convert the pixel border to an integer texel border. Assume same-pass
  1111. // curvature about triples the texel frequency:
  1112. #ifdef GEOMETRY_EARLY
  1113. static const float max_mask_texel_border =
  1114. ceil(max_tiled_pixel_border * 3.0);
  1115. #else
  1116. static const float max_mask_texel_border = ceil(max_tiled_pixel_border);
  1117. #endif
  1118. // Convert the texel border to a tile border using worst-case assumptions:
  1119. static const float max_mask_tile_border = max_mask_texel_border/
  1120. (mask_min_allowed_triad_size * mask_triads_per_tile);
  1121. // Finally, set the number of resized tiles to render to MASK_RESIZE, and set
  1122. // the starting texel (inside borders) for sampling it.
  1123. #ifndef GEOMETRY_EARLY
  1124. #ifdef ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE
  1125. // Special case: Render two tiles without borders. Anisotropic
  1126. // filtering doesn't seem to be a problem here.
  1127. static const float mask_resize_num_tiles = 1.0 + 1.0;
  1128. static const float mask_start_texels = 0.0;
  1129. #else
  1130. static const float mask_resize_num_tiles = 1.0 +
  1131. 2.0 * max_mask_tile_border;
  1132. static const float mask_start_texels = max_mask_texel_border;
  1133. #endif
  1134. #else
  1135. static const float mask_resize_num_tiles = 1.0 + 2.0*max_mask_tile_border;
  1136. static const float mask_start_texels = max_mask_texel_border;
  1137. #endif
  1138. // We have to fit mask_resize_num_tiles into an FBO with a viewport scale of
  1139. // mask_resize_viewport_scale. This limits the maximum final triad size.
  1140. // Estimate the minimum number of triads we can split the screen into in each
  1141. // dimension (we'll be as correct as mask_resize_viewport_scale is):
  1142. static const float mask_resize_num_triads =
  1143. mask_resize_num_tiles * mask_triads_per_tile;
  1144. static const float2 min_allowed_viewport_triads =
  1145. float2(mask_resize_num_triads) / mask_resize_viewport_scale;
  1146. //////////////////////// COMMON MATHEMATICAL CONSTANTS ///////////////////////
  1147. static const float pi = 3.141592653589;
  1148. // We often want to find the location of the previous texel, e.g.:
  1149. // const float2 curr_texel = uv * texture_size;
  1150. // const float2 prev_texel = floor(curr_texel - float2(0.5)) + float2(0.5);
  1151. // const float2 prev_texel_uv = prev_texel / texture_size;
  1152. // However, many GPU drivers round incorrectly around exact texel locations.
  1153. // We need to subtract a little less than 0.5 before flooring, and some GPU's
  1154. // require this value to be farther from 0.5 than others; define it here.
  1155. // const float2 prev_texel =
  1156. // floor(curr_texel - float2(under_half)) + float2(0.5);
  1157. static const float under_half = 0.4995;
  1158. #endif // DERIVED_SETTINGS_AND_CONSTANTS_H
  1159. ///////////////////////////// END DERIVED-SETTINGS-AND-CONSTANTS ////////////////////////////
  1160. //#include "bind-shader-h"
  1161. ///////////////////////////// BEGIN BIND-SHADER-PARAMS ////////////////////////////
  1162. #ifndef BIND_SHADER_PARAMS_H
  1163. #define BIND_SHADER_PARAMS_H
  1164. ///////////////////////////// GPL LICENSE NOTICE /////////////////////////////
  1165. // crt-royale: A full-featured CRT shader, with cheese.
  1166. // Copyright (C) 2014 TroggleMonkey <trogglemonkey@gmx.com>
  1167. //
  1168. // This program is free software; you can redistribute it and/or modify it
  1169. // under the terms of the GNU General Public License as published by the Free
  1170. // Software Foundation; either version 2 of the License, or any later version.
  1171. //
  1172. // This program is distributed in the hope that it will be useful, but WITHOUT
  1173. // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  1174. // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  1175. // more details.
  1176. //
  1177. // You should have received a copy of the GNU General Public License along with
  1178. // this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  1179. // Place, Suite 330, Boston, MA 02111-1307 USA
  1180. ///////////////////////////// SETTINGS MANAGEMENT ////////////////////////////
  1181. /////////////////////////////// BEGIN INCLUDES ///////////////////////////////
  1182. //#include "../user-settings.h"
  1183. ///////////////////////////// BEGIN USER-SETTINGS ////////////////////////////
  1184. #ifndef USER_SETTINGS_H
  1185. #define USER_SETTINGS_H
  1186. ///////////////////////////// DRIVER CAPABILITIES ////////////////////////////
  1187. // The Cg compiler uses different "profiles" with different capabilities.
  1188. // This shader requires a Cg compilation profile >= arbfp1, but a few options
  1189. // require higher profiles like fp30 or fp40. The shader can't detect profile
  1190. // or driver capabilities, so instead you must comment or uncomment the lines
  1191. // below with "//" before "#define." Disable an option if you get compilation
  1192. // errors resembling those listed. Generally speaking, all of these options
  1193. // will run on nVidia cards, but only DRIVERS_ALLOW_TEX2DBIAS (if that) is
  1194. // likely to run on ATI/AMD, due to the Cg compiler's profile limitations.
  1195. // Derivatives: Unsupported on fp20, ps_1_1, ps_1_2, ps_1_3, and arbfp1.
  1196. // Among other things, derivatives help us fix anisotropic filtering artifacts
  1197. // with curved manually tiled phosphor mask coords. Related errors:
  1198. // error C3004: function "float2 ddx(float2);" not supported in this profile
  1199. // error C3004: function "float2 ddy(float2);" not supported in this profile
  1200. //#define DRIVERS_ALLOW_DERIVATIVES
  1201. // Fine derivatives: Unsupported on older ATI cards.
  1202. // Fine derivatives enable 2x2 fragment block communication, letting us perform
  1203. // fast single-pass blur operations. If your card uses coarse derivatives and
  1204. // these are enabled, blurs could look broken. Derivatives are a prerequisite.
  1205. #ifdef DRIVERS_ALLOW_DERIVATIVES
  1206. #define DRIVERS_ALLOW_FINE_DERIVATIVES
  1207. #endif
  1208. // Dynamic looping: Requires an fp30 or newer profile.
  1209. // This makes phosphor mask resampling faster in some cases. Related errors:
  1210. // error C5013: profile does not support "for" statements and "for" could not
  1211. // be unrolled
  1212. //#define DRIVERS_ALLOW_DYNAMIC_BRANCHES
  1213. // Without DRIVERS_ALLOW_DYNAMIC_BRANCHES, we need to use unrollable loops.
  1214. // Using one static loop avoids overhead if the user is right, but if the user
  1215. // is wrong (loops are allowed), breaking a loop into if-blocked pieces with a
  1216. // binary search can potentially save some iterations. However, it may fail:
  1217. // error C6001: Temporary register limit of 32 exceeded; 35 registers
  1218. // needed to compile program
  1219. //#define ACCOMODATE_POSSIBLE_DYNAMIC_LOOPS
  1220. // tex2Dlod: Requires an fp40 or newer profile. This can be used to disable
  1221. // anisotropic filtering, thereby fixing related artifacts. Related errors:
  1222. // error C3004: function "float4 tex2Dlod(sampler2D, float4);" not supported in
  1223. // this profile
  1224. //#define DRIVERS_ALLOW_TEX2DLOD
  1225. // tex2Dbias: Requires an fp30 or newer profile. This can be used to alleviate
  1226. // artifacts from anisotropic filtering and mipmapping. Related errors:
  1227. // error C3004: function "float4 tex2Dbias(sampler2D, float4);" not supported
  1228. // in this profile
  1229. //#define DRIVERS_ALLOW_TEX2DBIAS
  1230. // Integrated graphics compatibility: Integrated graphics like Intel HD 4000
  1231. // impose stricter limitations on register counts and instructions. Enable
  1232. // INTEGRATED_GRAPHICS_COMPATIBILITY_MODE if you still see error C6001 or:
  1233. // error C6002: Instruction limit of 1024 exceeded: 1523 instructions needed
  1234. // to compile program.
  1235. // Enabling integrated graphics compatibility mode will automatically disable:
  1236. // 1.) PHOSPHOR_MASK_MANUALLY_RESIZE: The phosphor mask will be softer.
  1237. // (This may be reenabled in a later release.)
  1238. // 2.) RUNTIME_GEOMETRY_MODE
  1239. // 3.) The high-quality 4x4 Gaussian resize for the bloom approximation
  1240. //#define INTEGRATED_GRAPHICS_COMPATIBILITY_MODE
  1241. //////////////////////////// USER CODEPATH OPTIONS ///////////////////////////
  1242. // To disable a #define option, turn its line into a comment with "//."
  1243. // RUNTIME VS. COMPILE-TIME OPTIONS (Major Performance Implications):
  1244. // Enable runtime shader parameters in the Retroarch (etc.) GUI? They override
  1245. // many of the options in this file and allow real-time tuning, but many of
  1246. // them are slower. Disabling them and using this text file will boost FPS.
  1247. #define RUNTIME_SHADER_PARAMS_ENABLE
  1248. // Specify the phosphor bloom sigma at runtime? This option is 10% slower, but
  1249. // it's the only way to do a wide-enough full bloom with a runtime dot pitch.
  1250. #define RUNTIME_PHOSPHOR_BLOOM_SIGMA
  1251. // Specify antialiasing weight parameters at runtime? (Costs ~20% with cubics)
  1252. #define RUNTIME_ANTIALIAS_WEIGHTS
  1253. // Specify subpixel offsets at runtime? (WARNING: EXTREMELY EXPENSIVE!)
  1254. //#define RUNTIME_ANTIALIAS_SUBPIXEL_OFFSETS
  1255. // Make beam_horiz_filter and beam_horiz_linear_rgb_weight into runtime shader
  1256. // parameters? This will require more math or dynamic branching.
  1257. #define RUNTIME_SCANLINES_HORIZ_FILTER_COLORSPACE
  1258. // Specify the tilt at runtime? This makes things about 3% slower.
  1259. #define RUNTIME_GEOMETRY_TILT
  1260. // Specify the geometry mode at runtime?
  1261. #define RUNTIME_GEOMETRY_MODE
  1262. // Specify the phosphor mask type (aperture grille, slot mask, shadow mask) and
  1263. // mode (Lanczos-resize, hardware resize, or tile 1:1) at runtime, even without
  1264. // dynamic branches? This is cheap if mask_resize_viewport_scale is small.
  1265. #define FORCE_RUNTIME_PHOSPHOR_MASK_MODE_TYPE_SELECT
  1266. // PHOSPHOR MASK:
  1267. // Manually resize the phosphor mask for best results (slower)? Disabling this
  1268. // removes the option to do so, but it may be faster without dynamic branches.
  1269. #define PHOSPHOR_MASK_MANUALLY_RESIZE
  1270. // If we sinc-resize the mask, should we Lanczos-window it (slower but better)?
  1271. #define PHOSPHOR_MASK_RESIZE_LANCZOS_WINDOW
  1272. // Larger blurs are expensive, but we need them to blur larger triads. We can
  1273. // detect the right blur if the triad size is static or our profile allows
  1274. // dynamic branches, but otherwise we use the largest blur the user indicates
  1275. // they might need:
  1276. #define PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_3_PIXELS
  1277. //#define PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_6_PIXELS
  1278. //#define PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_9_PIXELS
  1279. //#define PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_12_PIXELS
  1280. // Here's a helpful chart:
  1281. // MaxTriadSize BlurSize MinTriadCountsByResolution
  1282. // 3.0 9.0 480/640/960/1920 triads at 1080p/1440p/2160p/4320p, 4:3 aspect
  1283. // 6.0 17.0 240/320/480/960 triads at 1080p/1440p/2160p/4320p, 4:3 aspect
  1284. // 9.0 25.0 160/213/320/640 triads at 1080p/1440p/2160p/4320p, 4:3 aspect
  1285. // 12.0 31.0 120/160/240/480 triads at 1080p/1440p/2160p/4320p, 4:3 aspect
  1286. // 18.0 43.0 80/107/160/320 triads at 1080p/1440p/2160p/4320p, 4:3 aspect
  1287. /////////////////////////////// USER PARAMETERS //////////////////////////////
  1288. // Note: Many of these static parameters are overridden by runtime shader
  1289. // parameters when those are enabled. However, many others are static codepath
  1290. // options that were cleaner or more convert to code as static constants.
  1291. // GAMMA:
  1292. static const float crt_gamma_static = 2.5; // range [1, 5]
  1293. static const float lcd_gamma_static = 2.2; // range [1, 5]
  1294. // LEVELS MANAGEMENT:
  1295. // Control the final multiplicative image contrast:
  1296. static const float levels_contrast_static = 1.0; // range [0, 4)
  1297. // We auto-dim to avoid clipping between passes and restore brightness
  1298. // later. Control the dim factor here: Lower values clip less but crush
  1299. // blacks more (static only for now).
  1300. static const float levels_autodim_temp = 0.5; // range (0, 1] default is 0.5 but that was unnecessarily dark for me, so I set it to 1.0
  1301. // HALATION/DIFFUSION/BLOOM:
  1302. // Halation weight: How much energy should be lost to electrons bounding
  1303. // around under the CRT glass and exciting random phosphors?
  1304. static const float halation_weight_static = 0.0; // range [0, 1]
  1305. // Refractive diffusion weight: How much light should spread/diffuse from
  1306. // refracting through the CRT glass?
  1307. static const float diffusion_weight_static = 0.075; // range [0, 1]
  1308. // Underestimate brightness: Bright areas bloom more, but we can base the
  1309. // bloom brightpass on a lower brightness to sharpen phosphors, or a higher
  1310. // brightness to soften them. Low values clip, but >= 0.8 looks okay.
  1311. static const float bloom_underestimate_levels_static = 0.8; // range [0, 5]
  1312. // Blur all colors more than necessary for a softer phosphor bloom?
  1313. static const float bloom_excess_static = 0.0; // range [0, 1]
  1314. // The BLOOM_APPROX pass approximates a phosphor blur early on with a small
  1315. // blurred resize of the input (convergence offsets are applied as well).
  1316. // There are three filter options (static option only for now):
  1317. // 0.) Bilinear resize: A fast, close approximation to a 4x4 resize
  1318. // if min_allowed_viewport_triads and the BLOOM_APPROX resolution are sane
  1319. // and beam_max_sigma is low.
  1320. // 1.) 3x3 resize blur: Medium speed, soft/smeared from bilinear blurring,
  1321. // always uses a static sigma regardless of beam_max_sigma or
  1322. // mask_num_triads_desired.
  1323. // 2.) True 4x4 Gaussian resize: Slowest, technically correct.
  1324. // These options are more pronounced for the fast, unbloomed shader version.
  1325. #ifndef RADEON_FIX
  1326. static const float bloom_approx_filter_static = 2.0;
  1327. #else
  1328. static const float bloom_approx_filter_static = 1.0;
  1329. #endif
  1330. // ELECTRON BEAM SCANLINE DISTRIBUTION:
  1331. // How many scanlines should contribute light to each pixel? Using more
  1332. // scanlines is slower (especially for a generalized Gaussian) but less
  1333. // distorted with larger beam sigmas (especially for a pure Gaussian). The
  1334. // max_beam_sigma at which the closest unused weight is guaranteed <
  1335. // 1.0/255.0 (for a 3x antialiased pure Gaussian) is:
  1336. // 2 scanlines: max_beam_sigma = 0.2089; distortions begin ~0.34; 141.7 FPS pure, 131.9 FPS generalized
  1337. // 3 scanlines, max_beam_sigma = 0.3879; distortions begin ~0.52; 137.5 FPS pure; 123.8 FPS generalized
  1338. // 4 scanlines, max_beam_sigma = 0.5723; distortions begin ~0.70; 134.7 FPS pure; 117.2 FPS generalized
  1339. // 5 scanlines, max_beam_sigma = 0.7591; distortions begin ~0.89; 131.6 FPS pure; 112.1 FPS generalized
  1340. // 6 scanlines, max_beam_sigma = 0.9483; distortions begin ~1.08; 127.9 FPS pure; 105.6 FPS generalized
  1341. static const float beam_num_scanlines = 3.0; // range [2, 6]
  1342. // A generalized Gaussian beam varies shape with color too, now just width.
  1343. // It's slower but more flexible (static option only for now).
  1344. static const bool beam_generalized_gaussian = true;
  1345. // What kind of scanline antialiasing do you want?
  1346. // 0: Sample weights at 1x; 1: Sample weights at 3x; 2: Compute an integral
  1347. // Integrals are slow (especially for generalized Gaussians) and rarely any
  1348. // better than 3x antialiasing (static option only for now).
  1349. static const float beam_antialias_level = 1.0; // range [0, 2]
  1350. // Min/max standard deviations for scanline beams: Higher values widen and
  1351. // soften scanlines. Depending on other options, low min sigmas can alias.
  1352. static const float beam_min_sigma_static = 0.02; // range (0, 1]
  1353. static const float beam_max_sigma_static = 0.3; // range (0, 1]
  1354. // Beam width varies as a function of color: A power function (0) is more
  1355. // configurable, but a spherical function (1) gives the widest beam
  1356. // variability without aliasing (static option only for now).
  1357. static const float beam_spot_shape_function = 0.0;
  1358. // Spot shape power: Powers <= 1 give smoother spot shapes but lower
  1359. // sharpness. Powers >= 1.0 are awful unless mix/max sigmas are close.
  1360. static const float beam_spot_power_static = 1.0/3.0; // range (0, 16]
  1361. // Generalized Gaussian max shape parameters: Higher values give flatter
  1362. // scanline plateaus and steeper dropoffs, simultaneously widening and
  1363. // sharpening scanlines at the cost of aliasing. 2.0 is pure Gaussian, and
  1364. // values > ~40.0 cause artifacts with integrals.
  1365. static const float beam_min_shape_static = 2.0; // range [2, 32]
  1366. static const float beam_max_shape_static = 4.0; // range [2, 32]
  1367. // Generalized Gaussian shape power: Affects how quickly the distribution
  1368. // changes shape from Gaussian to steep/plateaued as color increases from 0
  1369. // to 1.0. Higher powers appear softer for most colors, and lower powers
  1370. // appear sharper for most colors.
  1371. static const float beam_shape_power_static = 1.0/4.0; // range (0, 16]
  1372. // What filter should be used to sample scanlines horizontally?
  1373. // 0: Quilez (fast), 1: Gaussian (configurable), 2: Lanczos2 (sharp)
  1374. static const float beam_horiz_filter_static = 0.0;
  1375. // Standard deviation for horizontal Gaussian resampling:
  1376. static const float beam_horiz_sigma_static = 0.35; // range (0, 2/3]
  1377. // Do horizontal scanline sampling in linear RGB (correct light mixing),
  1378. // gamma-encoded RGB (darker, hard spot shape, may better match bandwidth-
  1379. // limiting circuitry in some CRT's), or a weighted avg.?
  1380. static const float beam_horiz_linear_rgb_weight_static = 1.0; // range [0, 1]
  1381. // Simulate scanline misconvergence? This needs 3x horizontal texture
  1382. // samples and 3x texture samples of BLOOM_APPROX and HALATION_BLUR in
  1383. // later passes (static option only for now).
  1384. static const bool beam_misconvergence = true;
  1385. // Convergence offsets in x/y directions for R/G/B scanline beams in units
  1386. // of scanlines. Positive offsets go right/down; ranges [-2, 2]
  1387. static const float2 convergence_offsets_r_static = float2(0.1, 0.2);
  1388. static const float2 convergence_offsets_g_static = float2(0.3, 0.4);
  1389. static const float2 convergence_offsets_b_static = float2(0.5, 0.6);
  1390. // Detect interlacing (static option only for now)?
  1391. static const bool interlace_detect = true;
  1392. // Assume 1080-line sources are interlaced?
  1393. static const bool interlace_1080i_static = false;
  1394. // For interlaced sources, assume TFF (top-field first) or BFF order?
  1395. // (Whether this matters depends on the nature of the interlaced input.)
  1396. static const bool interlace_bff_static = false;
  1397. // ANTIALIASING:
  1398. // What AA level do you want for curvature/overscan/subpixels? Options:
  1399. // 0x (none), 1x (sample subpixels), 4x, 5x, 6x, 7x, 8x, 12x, 16x, 20x, 24x
  1400. // (Static option only for now)
  1401. static const float aa_level = 12.0; // range [0, 24]
  1402. // What antialiasing filter do you want (static option only)? Options:
  1403. // 0: Box (separable), 1: Box (cylindrical),
  1404. // 2: Tent (separable), 3: Tent (cylindrical),
  1405. // 4: Gaussian (separable), 5: Gaussian (cylindrical),
  1406. // 6: Cubic* (separable), 7: Cubic* (cylindrical, poor)
  1407. // 8: Lanczos Sinc (separable), 9: Lanczos Jinc (cylindrical, poor)
  1408. // * = Especially slow with RUNTIME_ANTIALIAS_WEIGHTS
  1409. static const float aa_filter = 6.0; // range [0, 9]
  1410. // Flip the sample grid on odd/even frames (static option only for now)?
  1411. static const bool aa_temporal = false;
  1412. // Use RGB subpixel offsets for antialiasing? The pixel is at green, and
  1413. // the blue offset is the negative r offset; range [0, 0.5]
  1414. static const float2 aa_subpixel_r_offset_static = float2(-1.0/3.0, 0.0);//float2(0.0);
  1415. // Cubics: See http://www.imagemagick.org/Usage/filter/#mitchell
  1416. // 1.) "Keys cubics" with B = 1 - 2C are considered the highest quality.
  1417. // 2.) C = 0.5 (default) is Catmull-Rom; higher C's apply sharpening.
  1418. // 3.) C = 1.0/3.0 is the Mitchell-Netravali filter.
  1419. // 4.) C = 0.0 is a soft spline filter.
  1420. static const float aa_cubic_c_static = 0.5; // range [0, 4]
  1421. // Standard deviation for Gaussian antialiasing: Try 0.5/aa_pixel_diameter.
  1422. static const float aa_gauss_sigma_static = 0.5; // range [0.0625, 1.0]
  1423. // PHOSPHOR MASK:
  1424. // Mask type: 0 = aperture grille, 1 = slot mask, 2 = EDP shadow mask
  1425. static const float mask_type_static = 1.0; // range [0, 2]
  1426. // We can sample the mask three ways. Pick 2/3 from: Pretty/Fast/Flexible.
  1427. // 0.) Sinc-resize to the desired dot pitch manually (pretty/slow/flexible).
  1428. // This requires PHOSPHOR_MASK_MANUALLY_RESIZE to be #defined.
  1429. // 1.) Hardware-resize to the desired dot pitch (ugly/fast/flexible). This
  1430. // is halfway decent with LUT mipmapping but atrocious without it.
  1431. // 2.) Tile it without resizing at a 1:1 texel:pixel ratio for flat coords
  1432. // (pretty/fast/inflexible). Each input LUT has a fixed dot pitch.
  1433. // This mode reuses the same masks, so triads will be enormous unless
  1434. // you change the mask LUT filenames in your .cgp file.
  1435. static const float mask_sample_mode_static = 0.0; // range [0, 2]
  1436. // Prefer setting the triad size (0.0) or number on the screen (1.0)?
  1437. // If RUNTIME_PHOSPHOR_BLOOM_SIGMA isn't #defined, the specified triad size
  1438. // will always be used to calculate the full bloom sigma statically.
  1439. static const float mask_specify_num_triads_static = 0.0; // range [0, 1]
  1440. // Specify the phosphor triad size, in pixels. Each tile (usually with 8
  1441. // triads) will be rounded to the nearest integer tile size and clamped to
  1442. // obey minimum size constraints (imposed to reduce downsize taps) and
  1443. // maximum size constraints (imposed to have a sane MASK_RESIZE FBO size).
  1444. // To increase the size limit, double the viewport-relative scales for the
  1445. // two MASK_RESIZE passes in crt-royale.cgp and user-cgp-contants.h.
  1446. // range [1, mask_texture_small_size/mask_triads_per_tile]
  1447. static const float mask_triad_size_desired_static = 24.0 / 8.0;
  1448. // If mask_specify_num_triads is 1.0/true, we'll go by this instead (the
  1449. // final size will be rounded and constrained as above); default 480.0
  1450. static const float mask_num_triads_desired_static = 480.0;
  1451. // How many lobes should the sinc/Lanczos resizer use? More lobes require
  1452. // more samples and avoid moire a bit better, but some is unavoidable
  1453. // depending on the destination size (static option for now).
  1454. static const float mask_sinc_lobes = 3.0; // range [2, 4]
  1455. // The mask is resized using a variable number of taps in each dimension,
  1456. // but some Cg profiles always fetch a constant number of taps no matter
  1457. // what (no dynamic branching). We can limit the maximum number of taps if
  1458. // we statically limit the minimum phosphor triad size. Larger values are
  1459. // faster, but the limit IS enforced (static option only, forever);
  1460. // range [1, mask_texture_small_size/mask_triads_per_tile]
  1461. // TODO: Make this 1.0 and compensate with smarter sampling!
  1462. static const float mask_min_allowed_triad_size = 2.0;
  1463. // GEOMETRY:
  1464. // Geometry mode:
  1465. // 0: Off (default), 1: Spherical mapping (like cgwg's),
  1466. // 2: Alt. spherical mapping (more bulbous), 3: Cylindrical/Trinitron
  1467. static const float geom_mode_static = 0.0; // range [0, 3]
  1468. // Radius of curvature: Measured in units of your viewport's diagonal size.
  1469. static const float geom_radius_static = 2.0; // range [1/(2*pi), 1024]
  1470. // View dist is the distance from the player to their physical screen, in
  1471. // units of the viewport's diagonal size. It controls the field of view.
  1472. static const float geom_view_dist_static = 2.0; // range [0.5, 1024]
  1473. // Tilt angle in radians (clockwise around up and right vectors):
  1474. static const float2 geom_tilt_angle_static = float2(0.0, 0.0); // range [-pi, pi]
  1475. // Aspect ratio: When the true viewport size is unknown, this value is used
  1476. // to help convert between the phosphor triad size and count, along with
  1477. // the mask_resize_viewport_scale constant from user-cgp-constants.h. Set
  1478. // this equal to Retroarch's display aspect ratio (DAR) for best results;
  1479. // range [1, geom_max_aspect_ratio from user-cgp-constants.h];
  1480. // default (256/224)*(54/47) = 1.313069909 (see below)
  1481. static const float geom_aspect_ratio_static = 1.313069909;
  1482. // Before getting into overscan, here's some general aspect ratio info:
  1483. // - DAR = display aspect ratio = SAR * PAR; as in your Retroarch setting
  1484. // - SAR = storage aspect ratio = DAR / PAR; square pixel emulator frame AR
  1485. // - PAR = pixel aspect ratio = DAR / SAR; holds regardless of cropping
  1486. // Geometry processing has to "undo" the screen-space 2D DAR to calculate
  1487. // 3D view vectors, then reapplies the aspect ratio to the simulated CRT in
  1488. // uv-space. To ensure the source SAR is intended for a ~4:3 DAR, either:
  1489. // a.) Enable Retroarch's "Crop Overscan"
  1490. // b.) Readd horizontal padding: Set overscan to e.g. N*(1.0, 240.0/224.0)
  1491. // Real consoles use horizontal black padding in the signal, but emulators
  1492. // often crop this without cropping the vertical padding; a 256x224 [S]NES
  1493. // frame (8:7 SAR) is intended for a ~4:3 DAR, but a 256x240 frame is not.
  1494. // The correct [S]NES PAR is 54:47, found by blargg and NewRisingSun:
  1495. // http://board.zsnes.com/phpBB3/viewtopic.php?f=22&t=11928&start=50
  1496. // http://forums.nesdev.com/viewtopic.php?p=24815#p24815
  1497. // For flat output, it's okay to set DAR = [existing] SAR * [correct] PAR
  1498. // without doing a. or b., but horizontal image borders will be tighter
  1499. // than vertical ones, messing up curvature and overscan. Fixing the
  1500. // padding first corrects this.
  1501. // Overscan: Amount to "zoom in" before cropping. You can zoom uniformly
  1502. // or adjust x/y independently to e.g. readd horizontal padding, as noted
  1503. // above: Values < 1.0 zoom out; range (0, inf)
  1504. static const float2 geom_overscan_static = float2(1.0, 1.0);// * 1.005 * (1.0, 240/224.0)
  1505. // Compute a proper pixel-space to texture-space matrix even without ddx()/
  1506. // ddy()? This is ~8.5% slower but improves antialiasing/subpixel filtering
  1507. // with strong curvature (static option only for now).
  1508. static const bool geom_force_correct_tangent_matrix = true;
  1509. // BORDERS:
  1510. // Rounded border size in texture uv coords:
  1511. static const float border_size_static = 0.015; // range [0, 0.5]
  1512. // Border darkness: Moderate values darken the border smoothly, and high
  1513. // values make the image very dark just inside the border:
  1514. static const float border_darkness_static = 2.0; // range [0, inf)
  1515. // Border compression: High numbers compress border transitions, narrowing
  1516. // the dark border area.
  1517. static const float border_compress_static = 2.5; // range [1, inf)
  1518. #endif // USER_SETTINGS_H
  1519. ///////////////////////////// END USER-SETTINGS ////////////////////////////
  1520. //#include "derived-settings-and-constants.h"
  1521. ///////////////////// BEGIN DERIVED-SETTINGS-AND-CONSTANTS ////////////////////
  1522. #ifndef DERIVED_SETTINGS_AND_CONSTANTS_H
  1523. #define DERIVED_SETTINGS_AND_CONSTANTS_H
  1524. ///////////////////////////// GPL LICENSE NOTICE /////////////////////////////
  1525. // crt-royale: A full-featured CRT shader, with cheese.
  1526. // Copyright (C) 2014 TroggleMonkey <trogglemonkey@gmx.com>
  1527. //
  1528. // This program is free software; you can redistribute it and/or modify it
  1529. // under the terms of the GNU General Public License as published by the Free
  1530. // Software Foundation; either version 2 of the License, or any later version.
  1531. //
  1532. // This program is distributed in the hope that it will be useful, but WITHOUT
  1533. // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  1534. // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  1535. // more details.
  1536. //
  1537. // You should have received a copy of the GNU General Public License along with
  1538. // this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  1539. // Place, Suite 330, Boston, MA 02111-1307 USA
  1540. ///////////////////////////////// DESCRIPTION ////////////////////////////////
  1541. // These macros and constants can be used across the whole codebase.
  1542. // Unlike the values in user-settings.cgh, end users shouldn't modify these.
  1543. /////////////////////////////// BEGIN INCLUDES ///////////////////////////////
  1544. //#include "../user-settings.h"
  1545. ///////////////////////////// BEGIN USER-SETTINGS ////////////////////////////
  1546. #ifndef USER_SETTINGS_H
  1547. #define USER_SETTINGS_H
  1548. ///////////////////////////// DRIVER CAPABILITIES ////////////////////////////
  1549. // The Cg compiler uses different "profiles" with different capabilities.
  1550. // This shader requires a Cg compilation profile >= arbfp1, but a few options
  1551. // require higher profiles like fp30 or fp40. The shader can't detect profile
  1552. // or driver capabilities, so instead you must comment or uncomment the lines
  1553. // below with "//" before "#define." Disable an option if you get compilation
  1554. // errors resembling those listed. Generally speaking, all of these options
  1555. // will run on nVidia cards, but only DRIVERS_ALLOW_TEX2DBIAS (if that) is
  1556. // likely to run on ATI/AMD, due to the Cg compiler's profile limitations.
  1557. // Derivatives: Unsupported on fp20, ps_1_1, ps_1_2, ps_1_3, and arbfp1.
  1558. // Among other things, derivatives help us fix anisotropic filtering artifacts
  1559. // with curved manually tiled phosphor mask coords. Related errors:
  1560. // error C3004: function "float2 ddx(float2);" not supported in this profile
  1561. // error C3004: function "float2 ddy(float2);" not supported in this profile
  1562. //#define DRIVERS_ALLOW_DERIVATIVES
  1563. // Fine derivatives: Unsupported on older ATI cards.
  1564. // Fine derivatives enable 2x2 fragment block communication, letting us perform
  1565. // fast single-pass blur operations. If your card uses coarse derivatives and
  1566. // these are enabled, blurs could look broken. Derivatives are a prerequisite.
  1567. #ifdef DRIVERS_ALLOW_DERIVATIVES
  1568. #define DRIVERS_ALLOW_FINE_DERIVATIVES
  1569. #endif
  1570. // Dynamic looping: Requires an fp30 or newer profile.
  1571. // This makes phosphor mask resampling faster in some cases. Related errors:
  1572. // error C5013: profile does not support "for" statements and "for" could not
  1573. // be unrolled
  1574. //#define DRIVERS_ALLOW_DYNAMIC_BRANCHES
  1575. // Without DRIVERS_ALLOW_DYNAMIC_BRANCHES, we need to use unrollable loops.
  1576. // Using one static loop avoids overhead if the user is right, but if the user
  1577. // is wrong (loops are allowed), breaking a loop into if-blocked pieces with a
  1578. // binary search can potentially save some iterations. However, it may fail:
  1579. // error C6001: Temporary register limit of 32 exceeded; 35 registers
  1580. // needed to compile program
  1581. //#define ACCOMODATE_POSSIBLE_DYNAMIC_LOOPS
  1582. // tex2Dlod: Requires an fp40 or newer profile. This can be used to disable
  1583. // anisotropic filtering, thereby fixing related artifacts. Related errors:
  1584. // error C3004: function "float4 tex2Dlod(sampler2D, float4);" not supported in
  1585. // this profile
  1586. //#define DRIVERS_ALLOW_TEX2DLOD
  1587. // tex2Dbias: Requires an fp30 or newer profile. This can be used to alleviate
  1588. // artifacts from anisotropic filtering and mipmapping. Related errors:
  1589. // error C3004: function "float4 tex2Dbias(sampler2D, float4);" not supported
  1590. // in this profile
  1591. //#define DRIVERS_ALLOW_TEX2DBIAS
  1592. // Integrated graphics compatibility: Integrated graphics like Intel HD 4000
  1593. // impose stricter limitations on register counts and instructions. Enable
  1594. // INTEGRATED_GRAPHICS_COMPATIBILITY_MODE if you still see error C6001 or:
  1595. // error C6002: Instruction limit of 1024 exceeded: 1523 instructions needed
  1596. // to compile program.
  1597. // Enabling integrated graphics compatibility mode will automatically disable:
  1598. // 1.) PHOSPHOR_MASK_MANUALLY_RESIZE: The phosphor mask will be softer.
  1599. // (This may be reenabled in a later release.)
  1600. // 2.) RUNTIME_GEOMETRY_MODE
  1601. // 3.) The high-quality 4x4 Gaussian resize for the bloom approximation
  1602. //#define INTEGRATED_GRAPHICS_COMPATIBILITY_MODE
  1603. //////////////////////////// USER CODEPATH OPTIONS ///////////////////////////
  1604. // To disable a #define option, turn its line into a comment with "//."
  1605. // RUNTIME VS. COMPILE-TIME OPTIONS (Major Performance Implications):
  1606. // Enable runtime shader parameters in the Retroarch (etc.) GUI? They override
  1607. // many of the options in this file and allow real-time tuning, but many of
  1608. // them are slower. Disabling them and using this text file will boost FPS.
  1609. #define RUNTIME_SHADER_PARAMS_ENABLE
  1610. // Specify the phosphor bloom sigma at runtime? This option is 10% slower, but
  1611. // it's the only way to do a wide-enough full bloom with a runtime dot pitch.
  1612. #define RUNTIME_PHOSPHOR_BLOOM_SIGMA
  1613. // Specify antialiasing weight parameters at runtime? (Costs ~20% with cubics)
  1614. #define RUNTIME_ANTIALIAS_WEIGHTS
  1615. // Specify subpixel offsets at runtime? (WARNING: EXTREMELY EXPENSIVE!)
  1616. //#define RUNTIME_ANTIALIAS_SUBPIXEL_OFFSETS
  1617. // Make beam_horiz_filter and beam_horiz_linear_rgb_weight into runtime shader
  1618. // parameters? This will require more math or dynamic branching.
  1619. #define RUNTIME_SCANLINES_HORIZ_FILTER_COLORSPACE
  1620. // Specify the tilt at runtime? This makes things about 3% slower.
  1621. #define RUNTIME_GEOMETRY_TILT
  1622. // Specify the geometry mode at runtime?
  1623. #define RUNTIME_GEOMETRY_MODE
  1624. // Specify the phosphor mask type (aperture grille, slot mask, shadow mask) and
  1625. // mode (Lanczos-resize, hardware resize, or tile 1:1) at runtime, even without
  1626. // dynamic branches? This is cheap if mask_resize_viewport_scale is small.
  1627. #define FORCE_RUNTIME_PHOSPHOR_MASK_MODE_TYPE_SELECT
  1628. // PHOSPHOR MASK:
  1629. // Manually resize the phosphor mask for best results (slower)? Disabling this
  1630. // removes the option to do so, but it may be faster without dynamic branches.
  1631. #define PHOSPHOR_MASK_MANUALLY_RESIZE
  1632. // If we sinc-resize the mask, should we Lanczos-window it (slower but better)?
  1633. #define PHOSPHOR_MASK_RESIZE_LANCZOS_WINDOW
  1634. // Larger blurs are expensive, but we need them to blur larger triads. We can
  1635. // detect the right blur if the triad size is static or our profile allows
  1636. // dynamic branches, but otherwise we use the largest blur the user indicates
  1637. // they might need:
  1638. #define PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_3_PIXELS
  1639. //#define PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_6_PIXELS
  1640. //#define PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_9_PIXELS
  1641. //#define PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_12_PIXELS
  1642. // Here's a helpful chart:
  1643. // MaxTriadSize BlurSize MinTriadCountsByResolution
  1644. // 3.0 9.0 480/640/960/1920 triads at 1080p/1440p/2160p/4320p, 4:3 aspect
  1645. // 6.0 17.0 240/320/480/960 triads at 1080p/1440p/2160p/4320p, 4:3 aspect
  1646. // 9.0 25.0 160/213/320/640 triads at 1080p/1440p/2160p/4320p, 4:3 aspect
  1647. // 12.0 31.0 120/160/240/480 triads at 1080p/1440p/2160p/4320p, 4:3 aspect
  1648. // 18.0 43.0 80/107/160/320 triads at 1080p/1440p/2160p/4320p, 4:3 aspect
  1649. /////////////////////////////// USER PARAMETERS //////////////////////////////
  1650. // Note: Many of these static parameters are overridden by runtime shader
  1651. // parameters when those are enabled. However, many others are static codepath
  1652. // options that were cleaner or more convert to code as static constants.
  1653. // GAMMA:
  1654. static const float crt_gamma_static = 2.5; // range [1, 5]
  1655. static const float lcd_gamma_static = 2.2; // range [1, 5]
  1656. // LEVELS MANAGEMENT:
  1657. // Control the final multiplicative image contrast:
  1658. static const float levels_contrast_static = 1.0; // range [0, 4)
  1659. // We auto-dim to avoid clipping between passes and restore brightness
  1660. // later. Control the dim factor here: Lower values clip less but crush
  1661. // blacks more (static only for now).
  1662. static const float levels_autodim_temp = 0.5; // range (0, 1] default is 0.5 but that was unnecessarily dark for me, so I set it to 1.0
  1663. // HALATION/DIFFUSION/BLOOM:
  1664. // Halation weight: How much energy should be lost to electrons bounding
  1665. // around under the CRT glass and exciting random phosphors?
  1666. static const float halation_weight_static = 0.0; // range [0, 1]
  1667. // Refractive diffusion weight: How much light should spread/diffuse from
  1668. // refracting through the CRT glass?
  1669. static const float diffusion_weight_static = 0.075; // range [0, 1]
  1670. // Underestimate brightness: Bright areas bloom more, but we can base the
  1671. // bloom brightpass on a lower brightness to sharpen phosphors, or a higher
  1672. // brightness to soften them. Low values clip, but >= 0.8 looks okay.
  1673. static const float bloom_underestimate_levels_static = 0.8; // range [0, 5]
  1674. // Blur all colors more than necessary for a softer phosphor bloom?
  1675. static const float bloom_excess_static = 0.0; // range [0, 1]
  1676. // The BLOOM_APPROX pass approximates a phosphor blur early on with a small
  1677. // blurred resize of the input (convergence offsets are applied as well).
  1678. // There are three filter options (static option only for now):
  1679. // 0.) Bilinear resize: A fast, close approximation to a 4x4 resize
  1680. // if min_allowed_viewport_triads and the BLOOM_APPROX resolution are sane
  1681. // and beam_max_sigma is low.
  1682. // 1.) 3x3 resize blur: Medium speed, soft/smeared from bilinear blurring,
  1683. // always uses a static sigma regardless of beam_max_sigma or
  1684. // mask_num_triads_desired.
  1685. // 2.) True 4x4 Gaussian resize: Slowest, technically correct.
  1686. // These options are more pronounced for the fast, unbloomed shader version.
  1687. #ifndef RADEON_FIX
  1688. static const float bloom_approx_filter_static = 2.0;
  1689. #else
  1690. static const float bloom_approx_filter_static = 1.0;
  1691. #endif
  1692. // ELECTRON BEAM SCANLINE DISTRIBUTION:
  1693. // How many scanlines should contribute light to each pixel? Using more
  1694. // scanlines is slower (especially for a generalized Gaussian) but less
  1695. // distorted with larger beam sigmas (especially for a pure Gaussian). The
  1696. // max_beam_sigma at which the closest unused weight is guaranteed <
  1697. // 1.0/255.0 (for a 3x antialiased pure Gaussian) is:
  1698. // 2 scanlines: max_beam_sigma = 0.2089; distortions begin ~0.34; 141.7 FPS pure, 131.9 FPS generalized
  1699. // 3 scanlines, max_beam_sigma = 0.3879; distortions begin ~0.52; 137.5 FPS pure; 123.8 FPS generalized
  1700. // 4 scanlines, max_beam_sigma = 0.5723; distortions begin ~0.70; 134.7 FPS pure; 117.2 FPS generalized
  1701. // 5 scanlines, max_beam_sigma = 0.7591; distortions begin ~0.89; 131.6 FPS pure; 112.1 FPS generalized
  1702. // 6 scanlines, max_beam_sigma = 0.9483; distortions begin ~1.08; 127.9 FPS pure; 105.6 FPS generalized
  1703. static const float beam_num_scanlines = 3.0; // range [2, 6]
  1704. // A generalized Gaussian beam varies shape with color too, now just width.
  1705. // It's slower but more flexible (static option only for now).
  1706. static const bool beam_generalized_gaussian = true;
  1707. // What kind of scanline antialiasing do you want?
  1708. // 0: Sample weights at 1x; 1: Sample weights at 3x; 2: Compute an integral
  1709. // Integrals are slow (especially for generalized Gaussians) and rarely any
  1710. // better than 3x antialiasing (static option only for now).
  1711. static const float beam_antialias_level = 1.0; // range [0, 2]
  1712. // Min/max standard deviations for scanline beams: Higher values widen and
  1713. // soften scanlines. Depending on other options, low min sigmas can alias.
  1714. static const float beam_min_sigma_static = 0.02; // range (0, 1]
  1715. static const float beam_max_sigma_static = 0.3; // range (0, 1]
  1716. // Beam width varies as a function of color: A power function (0) is more
  1717. // configurable, but a spherical function (1) gives the widest beam
  1718. // variability without aliasing (static option only for now).
  1719. static const float beam_spot_shape_function = 0.0;
  1720. // Spot shape power: Powers <= 1 give smoother spot shapes but lower
  1721. // sharpness. Powers >= 1.0 are awful unless mix/max sigmas are close.
  1722. static const float beam_spot_power_static = 1.0/3.0; // range (0, 16]
  1723. // Generalized Gaussian max shape parameters: Higher values give flatter
  1724. // scanline plateaus and steeper dropoffs, simultaneously widening and
  1725. // sharpening scanlines at the cost of aliasing. 2.0 is pure Gaussian, and
  1726. // values > ~40.0 cause artifacts with integrals.
  1727. static const float beam_min_shape_static = 2.0; // range [2, 32]
  1728. static const float beam_max_shape_static = 4.0; // range [2, 32]
  1729. // Generalized Gaussian shape power: Affects how quickly the distribution
  1730. // changes shape from Gaussian to steep/plateaued as color increases from 0
  1731. // to 1.0. Higher powers appear softer for most colors, and lower powers
  1732. // appear sharper for most colors.
  1733. static const float beam_shape_power_static = 1.0/4.0; // range (0, 16]
  1734. // What filter should be used to sample scanlines horizontally?
  1735. // 0: Quilez (fast), 1: Gaussian (configurable), 2: Lanczos2 (sharp)
  1736. static const float beam_horiz_filter_static = 0.0;
  1737. // Standard deviation for horizontal Gaussian resampling:
  1738. static const float beam_horiz_sigma_static = 0.35; // range (0, 2/3]
  1739. // Do horizontal scanline sampling in linear RGB (correct light mixing),
  1740. // gamma-encoded RGB (darker, hard spot shape, may better match bandwidth-
  1741. // limiting circuitry in some CRT's), or a weighted avg.?
  1742. static const float beam_horiz_linear_rgb_weight_static = 1.0; // range [0, 1]
  1743. // Simulate scanline misconvergence? This needs 3x horizontal texture
  1744. // samples and 3x texture samples of BLOOM_APPROX and HALATION_BLUR in
  1745. // later passes (static option only for now).
  1746. static const bool beam_misconvergence = true;
  1747. // Convergence offsets in x/y directions for R/G/B scanline beams in units
  1748. // of scanlines. Positive offsets go right/down; ranges [-2, 2]
  1749. static const float2 convergence_offsets_r_static = float2(0.1, 0.2);
  1750. static const float2 convergence_offsets_g_static = float2(0.3, 0.4);
  1751. static const float2 convergence_offsets_b_static = float2(0.5, 0.6);
  1752. // Detect interlacing (static option only for now)?
  1753. static const bool interlace_detect = true;
  1754. // Assume 1080-line sources are interlaced?
  1755. static const bool interlace_1080i_static = false;
  1756. // For interlaced sources, assume TFF (top-field first) or BFF order?
  1757. // (Whether this matters depends on the nature of the interlaced input.)
  1758. static const bool interlace_bff_static = false;
  1759. // ANTIALIASING:
  1760. // What AA level do you want for curvature/overscan/subpixels? Options:
  1761. // 0x (none), 1x (sample subpixels), 4x, 5x, 6x, 7x, 8x, 12x, 16x, 20x, 24x
  1762. // (Static option only for now)
  1763. static const float aa_level = 12.0; // range [0, 24]
  1764. // What antialiasing filter do you want (static option only)? Options:
  1765. // 0: Box (separable), 1: Box (cylindrical),
  1766. // 2: Tent (separable), 3: Tent (cylindrical),
  1767. // 4: Gaussian (separable), 5: Gaussian (cylindrical),
  1768. // 6: Cubic* (separable), 7: Cubic* (cylindrical, poor)
  1769. // 8: Lanczos Sinc (separable), 9: Lanczos Jinc (cylindrical, poor)
  1770. // * = Especially slow with RUNTIME_ANTIALIAS_WEIGHTS
  1771. static const float aa_filter = 6.0; // range [0, 9]
  1772. // Flip the sample grid on odd/even frames (static option only for now)?
  1773. static const bool aa_temporal = false;
  1774. // Use RGB subpixel offsets for antialiasing? The pixel is at green, and
  1775. // the blue offset is the negative r offset; range [0, 0.5]
  1776. static const float2 aa_subpixel_r_offset_static = float2(-1.0/3.0, 0.0);//float2(0.0);
  1777. // Cubics: See http://www.imagemagick.org/Usage/filter/#mitchell
  1778. // 1.) "Keys cubics" with B = 1 - 2C are considered the highest quality.
  1779. // 2.) C = 0.5 (default) is Catmull-Rom; higher C's apply sharpening.
  1780. // 3.) C = 1.0/3.0 is the Mitchell-Netravali filter.
  1781. // 4.) C = 0.0 is a soft spline filter.
  1782. static const float aa_cubic_c_static = 0.5; // range [0, 4]
  1783. // Standard deviation for Gaussian antialiasing: Try 0.5/aa_pixel_diameter.
  1784. static const float aa_gauss_sigma_static = 0.5; // range [0.0625, 1.0]
  1785. // PHOSPHOR MASK:
  1786. // Mask type: 0 = aperture grille, 1 = slot mask, 2 = EDP shadow mask
  1787. static const float mask_type_static = 1.0; // range [0, 2]
  1788. // We can sample the mask three ways. Pick 2/3 from: Pretty/Fast/Flexible.
  1789. // 0.) Sinc-resize to the desired dot pitch manually (pretty/slow/flexible).
  1790. // This requires PHOSPHOR_MASK_MANUALLY_RESIZE to be #defined.
  1791. // 1.) Hardware-resize to the desired dot pitch (ugly/fast/flexible). This
  1792. // is halfway decent with LUT mipmapping but atrocious without it.
  1793. // 2.) Tile it without resizing at a 1:1 texel:pixel ratio for flat coords
  1794. // (pretty/fast/inflexible). Each input LUT has a fixed dot pitch.
  1795. // This mode reuses the same masks, so triads will be enormous unless
  1796. // you change the mask LUT filenames in your .cgp file.
  1797. static const float mask_sample_mode_static = 0.0; // range [0, 2]
  1798. // Prefer setting the triad size (0.0) or number on the screen (1.0)?
  1799. // If RUNTIME_PHOSPHOR_BLOOM_SIGMA isn't #defined, the specified triad size
  1800. // will always be used to calculate the full bloom sigma statically.
  1801. static const float mask_specify_num_triads_static = 0.0; // range [0, 1]
  1802. // Specify the phosphor triad size, in pixels. Each tile (usually with 8
  1803. // triads) will be rounded to the nearest integer tile size and clamped to
  1804. // obey minimum size constraints (imposed to reduce downsize taps) and
  1805. // maximum size constraints (imposed to have a sane MASK_RESIZE FBO size).
  1806. // To increase the size limit, double the viewport-relative scales for the
  1807. // two MASK_RESIZE passes in crt-royale.cgp and user-cgp-contants.h.
  1808. // range [1, mask_texture_small_size/mask_triads_per_tile]
  1809. static const float mask_triad_size_desired_static = 24.0 / 8.0;
  1810. // If mask_specify_num_triads is 1.0/true, we'll go by this instead (the
  1811. // final size will be rounded and constrained as above); default 480.0
  1812. static const float mask_num_triads_desired_static = 480.0;
  1813. // How many lobes should the sinc/Lanczos resizer use? More lobes require
  1814. // more samples and avoid moire a bit better, but some is unavoidable
  1815. // depending on the destination size (static option for now).
  1816. static const float mask_sinc_lobes = 3.0; // range [2, 4]
  1817. // The mask is resized using a variable number of taps in each dimension,
  1818. // but some Cg profiles always fetch a constant number of taps no matter
  1819. // what (no dynamic branching). We can limit the maximum number of taps if
  1820. // we statically limit the minimum phosphor triad size. Larger values are
  1821. // faster, but the limit IS enforced (static option only, forever);
  1822. // range [1, mask_texture_small_size/mask_triads_per_tile]
  1823. // TODO: Make this 1.0 and compensate with smarter sampling!
  1824. static const float mask_min_allowed_triad_size = 2.0;
  1825. // GEOMETRY:
  1826. // Geometry mode:
  1827. // 0: Off (default), 1: Spherical mapping (like cgwg's),
  1828. // 2: Alt. spherical mapping (more bulbous), 3: Cylindrical/Trinitron
  1829. static const float geom_mode_static = 0.0; // range [0, 3]
  1830. // Radius of curvature: Measured in units of your viewport's diagonal size.
  1831. static const float geom_radius_static = 2.0; // range [1/(2*pi), 1024]
  1832. // View dist is the distance from the player to their physical screen, in
  1833. // units of the viewport's diagonal size. It controls the field of view.
  1834. static const float geom_view_dist_static = 2.0; // range [0.5, 1024]
  1835. // Tilt angle in radians (clockwise around up and right vectors):
  1836. static const float2 geom_tilt_angle_static = float2(0.0, 0.0); // range [-pi, pi]
  1837. // Aspect ratio: When the true viewport size is unknown, this value is used
  1838. // to help convert between the phosphor triad size and count, along with
  1839. // the mask_resize_viewport_scale constant from user-cgp-constants.h. Set
  1840. // this equal to Retroarch's display aspect ratio (DAR) for best results;
  1841. // range [1, geom_max_aspect_ratio from user-cgp-constants.h];
  1842. // default (256/224)*(54/47) = 1.313069909 (see below)
  1843. static const float geom_aspect_ratio_static = 1.313069909;
  1844. // Before getting into overscan, here's some general aspect ratio info:
  1845. // - DAR = display aspect ratio = SAR * PAR; as in your Retroarch setting
  1846. // - SAR = storage aspect ratio = DAR / PAR; square pixel emulator frame AR
  1847. // - PAR = pixel aspect ratio = DAR / SAR; holds regardless of cropping
  1848. // Geometry processing has to "undo" the screen-space 2D DAR to calculate
  1849. // 3D view vectors, then reapplies the aspect ratio to the simulated CRT in
  1850. // uv-space. To ensure the source SAR is intended for a ~4:3 DAR, either:
  1851. // a.) Enable Retroarch's "Crop Overscan"
  1852. // b.) Readd horizontal padding: Set overscan to e.g. N*(1.0, 240.0/224.0)
  1853. // Real consoles use horizontal black padding in the signal, but emulators
  1854. // often crop this without cropping the vertical padding; a 256x224 [S]NES
  1855. // frame (8:7 SAR) is intended for a ~4:3 DAR, but a 256x240 frame is not.
  1856. // The correct [S]NES PAR is 54:47, found by blargg and NewRisingSun:
  1857. // http://board.zsnes.com/phpBB3/viewtopic.php?f=22&t=11928&start=50
  1858. // http://forums.nesdev.com/viewtopic.php?p=24815#p24815
  1859. // For flat output, it's okay to set DAR = [existing] SAR * [correct] PAR
  1860. // without doing a. or b., but horizontal image borders will be tighter
  1861. // than vertical ones, messing up curvature and overscan. Fixing the
  1862. // padding first corrects this.
  1863. // Overscan: Amount to "zoom in" before cropping. You can zoom uniformly
  1864. // or adjust x/y independently to e.g. readd horizontal padding, as noted
  1865. // above: Values < 1.0 zoom out; range (0, inf)
  1866. static const float2 geom_overscan_static = float2(1.0, 1.0);// * 1.005 * (1.0, 240/224.0)
  1867. // Compute a proper pixel-space to texture-space matrix even without ddx()/
  1868. // ddy()? This is ~8.5% slower but improves antialiasing/subpixel filtering
  1869. // with strong curvature (static option only for now).
  1870. static const bool geom_force_correct_tangent_matrix = true;
  1871. // BORDERS:
  1872. // Rounded border size in texture uv coords:
  1873. static const float border_size_static = 0.015; // range [0, 0.5]
  1874. // Border darkness: Moderate values darken the border smoothly, and high
  1875. // values make the image very dark just inside the border:
  1876. static const float border_darkness_static = 2.0; // range [0, inf)
  1877. // Border compression: High numbers compress border transitions, narrowing
  1878. // the dark border area.
  1879. static const float border_compress_static = 2.5; // range [1, inf)
  1880. #endif // USER_SETTINGS_H
  1881. ///////////////////////////// END USER-SETTINGS ////////////////////////////
  1882. //#include "user-cgp-constants.h"
  1883. ///////////////////////// BEGIN USER-CGP-CONSTANTS /////////////////////////
  1884. #ifndef USER_CGP_CONSTANTS_H
  1885. #define USER_CGP_CONSTANTS_H
  1886. // IMPORTANT:
  1887. // These constants MUST be set appropriately for the settings in crt-royale.cgp
  1888. // (or whatever related .cgp file you're using). If they aren't, you're likely
  1889. // to get artifacts, the wrong phosphor mask size, etc. I wish these could be
  1890. // set directly in the .cgp file to make things easier, but...they can't.
  1891. // PASS SCALES AND RELATED CONSTANTS:
  1892. // Copy the absolute scale_x for BLOOM_APPROX. There are two major versions of
  1893. // this shader: One does a viewport-scale bloom, and the other skips it. The
  1894. // latter benefits from a higher bloom_approx_scale_x, so save both separately:
  1895. static const float bloom_approx_size_x = 320.0;
  1896. static const float bloom_approx_size_x_for_fake = 400.0;
  1897. // Copy the viewport-relative scales of the phosphor mask resize passes
  1898. // (MASK_RESIZE and the pass immediately preceding it):
  1899. static const float2 mask_resize_viewport_scale = float2(0.0625, 0.0625);
  1900. // Copy the geom_max_aspect_ratio used to calculate the MASK_RESIZE scales, etc.:
  1901. static const float geom_max_aspect_ratio = 4.0/3.0;
  1902. // PHOSPHOR MASK TEXTURE CONSTANTS:
  1903. // Set the following constants to reflect the properties of the phosphor mask
  1904. // texture named in crt-royale.cgp. The shader optionally resizes a mask tile
  1905. // based on user settings, then repeats a single tile until filling the screen.
  1906. // The shader must know the input texture size (default 64x64), and to manually
  1907. // resize, it must also know the horizontal triads per tile (default 8).
  1908. static const float2 mask_texture_small_size = float2(64.0, 64.0);
  1909. static const float2 mask_texture_large_size = float2(512.0, 512.0);
  1910. static const float mask_triads_per_tile = 8.0;
  1911. // We need the average brightness of the phosphor mask to compensate for the
  1912. // dimming it causes. The following four values are roughly correct for the
  1913. // masks included with the shader. Update the value for any LUT texture you
  1914. // change. [Un]comment "#define PHOSPHOR_MASK_GRILLE14" depending on whether
  1915. // the loaded aperture grille uses 14-pixel or 15-pixel stripes (default 15).
  1916. //#define PHOSPHOR_MASK_GRILLE14
  1917. static const float mask_grille14_avg_color = 50.6666666/255.0;
  1918. // TileableLinearApertureGrille14Wide7d33Spacing*.png
  1919. // TileableLinearApertureGrille14Wide10And6Spacing*.png
  1920. static const float mask_grille15_avg_color = 53.0/255.0;
  1921. // TileableLinearApertureGrille15Wide6d33Spacing*.png
  1922. // TileableLinearApertureGrille15Wide8And5d5Spacing*.png
  1923. static const float mask_slot_avg_color = 46.0/255.0;
  1924. // TileableLinearSlotMask15Wide9And4d5Horizontal8VerticalSpacing*.png
  1925. // TileableLinearSlotMaskTall15Wide9And4d5Horizontal9d14VerticalSpacing*.png
  1926. static const float mask_shadow_avg_color = 41.0/255.0;
  1927. // TileableLinearShadowMask*.png
  1928. // TileableLinearShadowMaskEDP*.png
  1929. #ifdef PHOSPHOR_MASK_GRILLE14
  1930. static const float mask_grille_avg_color = mask_grille14_avg_color;
  1931. #else
  1932. static const float mask_grille_avg_color = mask_grille15_avg_color;
  1933. #endif
  1934. #endif // USER_CGP_CONSTANTS_H
  1935. ////////////////////////// END USER-CGP-CONSTANTS //////////////////////////
  1936. //////////////////////////////// END INCLUDES ////////////////////////////////
  1937. /////////////////////////////// FIXED SETTINGS ///////////////////////////////
  1938. // Avoid dividing by zero; using a macro overloads for float, float2, etc.:
  1939. #define FIX_ZERO(c) (max(abs(c), 0.0000152587890625)) // 2^-16
  1940. // Ensure the first pass decodes CRT gamma and the last encodes LCD gamma.
  1941. #ifndef SIMULATE_CRT_ON_LCD
  1942. #define SIMULATE_CRT_ON_LCD
  1943. #endif
  1944. // Manually tiling a manually resized texture creates texture coord derivative
  1945. // discontinuities and confuses anisotropic filtering, causing discolored tile
  1946. // seams in the phosphor mask. Workarounds:
  1947. // a.) Using tex2Dlod disables anisotropic filtering for tiled masks. It's
  1948. // downgraded to tex2Dbias without DRIVERS_ALLOW_TEX2DLOD #defined and
  1949. // disabled without DRIVERS_ALLOW_TEX2DBIAS #defined either.
  1950. // b.) "Tile flat twice" requires drawing two full tiles without border padding
  1951. // to the resized mask FBO, and it's incompatible with same-pass curvature.
  1952. // (Same-pass curvature isn't used but could be in the future...maybe.)
  1953. // c.) "Fix discontinuities" requires derivatives and drawing one tile with
  1954. // border padding to the resized mask FBO, but it works with same-pass
  1955. // curvature. It's disabled without DRIVERS_ALLOW_DERIVATIVES #defined.
  1956. // Precedence: a, then, b, then c (if multiple strategies are #defined).
  1957. #define ANISOTROPIC_TILING_COMPAT_TEX2DLOD // 129.7 FPS, 4x, flat; 101.8 at fullscreen
  1958. #define ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE // 128.1 FPS, 4x, flat; 101.5 at fullscreen
  1959. #define ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES // 124.4 FPS, 4x, flat; 97.4 at fullscreen
  1960. // Also, manually resampling the phosphor mask is slightly blurrier with
  1961. // anisotropic filtering. (Resampling with mipmapping is even worse: It
  1962. // creates artifacts, but only with the fully bloomed shader.) The difference
  1963. // is subtle with small triads, but you can fix it for a small cost.
  1964. //#define ANISOTROPIC_RESAMPLING_COMPAT_TEX2DLOD
  1965. ////////////////////////////// DERIVED SETTINGS //////////////////////////////
  1966. // Intel HD 4000 GPU's can't handle manual mask resizing (for now), setting the
  1967. // geometry mode at runtime, or a 4x4 true Gaussian resize. Disable
  1968. // incompatible settings ASAP. (INTEGRATED_GRAPHICS_COMPATIBILITY_MODE may be
  1969. // #defined by either user-settings.h or a wrapper .cg that #includes the
  1970. // current .cg pass.)
  1971. #ifdef INTEGRATED_GRAPHICS_COMPATIBILITY_MODE
  1972. #ifdef PHOSPHOR_MASK_MANUALLY_RESIZE
  1973. #undef PHOSPHOR_MASK_MANUALLY_RESIZE
  1974. #endif
  1975. #ifdef RUNTIME_GEOMETRY_MODE
  1976. #undef RUNTIME_GEOMETRY_MODE
  1977. #endif
  1978. // Mode 2 (4x4 Gaussian resize) won't work, and mode 1 (3x3 blur) is
  1979. // inferior in most cases, so replace 2.0 with 0.0:
  1980. static const float bloom_approx_filter =
  1981. bloom_approx_filter_static > 1.5 ? 0.0 : bloom_approx_filter_static;
  1982. #else
  1983. static const float bloom_approx_filter = bloom_approx_filter_static;
  1984. #endif
  1985. // Disable slow runtime paths if static parameters are used. Most of these
  1986. // won't be a problem anyway once the params are disabled, but some will.
  1987. #ifndef RUNTIME_SHADER_PARAMS_ENABLE
  1988. #ifdef RUNTIME_PHOSPHOR_BLOOM_SIGMA
  1989. #undef RUNTIME_PHOSPHOR_BLOOM_SIGMA
  1990. #endif
  1991. #ifdef RUNTIME_ANTIALIAS_WEIGHTS
  1992. #undef RUNTIME_ANTIALIAS_WEIGHTS
  1993. #endif
  1994. #ifdef RUNTIME_ANTIALIAS_SUBPIXEL_OFFSETS
  1995. #undef RUNTIME_ANTIALIAS_SUBPIXEL_OFFSETS
  1996. #endif
  1997. #ifdef RUNTIME_SCANLINES_HORIZ_FILTER_COLORSPACE
  1998. #undef RUNTIME_SCANLINES_HORIZ_FILTER_COLORSPACE
  1999. #endif
  2000. #ifdef RUNTIME_GEOMETRY_TILT
  2001. #undef RUNTIME_GEOMETRY_TILT
  2002. #endif
  2003. #ifdef RUNTIME_GEOMETRY_MODE
  2004. #undef RUNTIME_GEOMETRY_MODE
  2005. #endif
  2006. #ifdef FORCE_RUNTIME_PHOSPHOR_MASK_MODE_TYPE_SELECT
  2007. #undef FORCE_RUNTIME_PHOSPHOR_MASK_MODE_TYPE_SELECT
  2008. #endif
  2009. #endif
  2010. // Make tex2Dbias a backup for tex2Dlod for wider compatibility.
  2011. #ifdef ANISOTROPIC_TILING_COMPAT_TEX2DLOD
  2012. #define ANISOTROPIC_TILING_COMPAT_TEX2DBIAS
  2013. #endif
  2014. #ifdef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DLOD
  2015. #define ANISOTROPIC_RESAMPLING_COMPAT_TEX2DBIAS
  2016. #endif
  2017. // Rule out unavailable anisotropic compatibility strategies:
  2018. #ifndef DRIVERS_ALLOW_DERIVATIVES
  2019. #ifdef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
  2020. #undef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
  2021. #endif
  2022. #endif
  2023. #ifndef DRIVERS_ALLOW_TEX2DLOD
  2024. #ifdef ANISOTROPIC_TILING_COMPAT_TEX2DLOD
  2025. #undef ANISOTROPIC_TILING_COMPAT_TEX2DLOD
  2026. #endif
  2027. #ifdef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DLOD
  2028. #undef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DLOD
  2029. #endif
  2030. #ifdef ANTIALIAS_DISABLE_ANISOTROPIC
  2031. #undef ANTIALIAS_DISABLE_ANISOTROPIC
  2032. #endif
  2033. #endif
  2034. #ifndef DRIVERS_ALLOW_TEX2DBIAS
  2035. #ifdef ANISOTROPIC_TILING_COMPAT_TEX2DBIAS
  2036. #undef ANISOTROPIC_TILING_COMPAT_TEX2DBIAS
  2037. #endif
  2038. #ifdef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DBIAS
  2039. #undef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DBIAS
  2040. #endif
  2041. #endif
  2042. // Prioritize anisotropic tiling compatibility strategies by performance and
  2043. // disable unused strategies. This concentrates all the nesting in one place.
  2044. #ifdef ANISOTROPIC_TILING_COMPAT_TEX2DLOD
  2045. #ifdef ANISOTROPIC_TILING_COMPAT_TEX2DBIAS
  2046. #undef ANISOTROPIC_TILING_COMPAT_TEX2DBIAS
  2047. #endif
  2048. #ifdef ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE
  2049. #undef ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE
  2050. #endif
  2051. #ifdef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
  2052. #undef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
  2053. #endif
  2054. #else
  2055. #ifdef ANISOTROPIC_TILING_COMPAT_TEX2DBIAS
  2056. #ifdef ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE
  2057. #undef ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE
  2058. #endif
  2059. #ifdef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
  2060. #undef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
  2061. #endif
  2062. #else
  2063. // ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE is only compatible with
  2064. // flat texture coords in the same pass, but that's all we use.
  2065. #ifdef ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE
  2066. #ifdef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
  2067. #undef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
  2068. #endif
  2069. #endif
  2070. #endif
  2071. #endif
  2072. // The tex2Dlod and tex2Dbias strategies share a lot in common, and we can
  2073. // reduce some #ifdef nesting in the next section by essentially OR'ing them:
  2074. #ifdef ANISOTROPIC_TILING_COMPAT_TEX2DLOD
  2075. #define ANISOTROPIC_TILING_COMPAT_TEX2DLOD_FAMILY
  2076. #endif
  2077. #ifdef ANISOTROPIC_TILING_COMPAT_TEX2DBIAS
  2078. #define ANISOTROPIC_TILING_COMPAT_TEX2DLOD_FAMILY
  2079. #endif
  2080. // Prioritize anisotropic resampling compatibility strategies the same way:
  2081. #ifdef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DLOD
  2082. #ifdef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DBIAS
  2083. #undef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DBIAS
  2084. #endif
  2085. #endif
  2086. /////////////////////// DERIVED PHOSPHOR MASK CONSTANTS //////////////////////
  2087. // If we can use the large mipmapped LUT without mipmapping artifacts, we
  2088. // should: It gives us more options for using fewer samples.
  2089. #ifdef DRIVERS_ALLOW_TEX2DLOD
  2090. #ifdef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DLOD
  2091. // TODO: Take advantage of this!
  2092. #define PHOSPHOR_MASK_RESIZE_MIPMAPPED_LUT
  2093. static const float2 mask_resize_src_lut_size = mask_texture_large_size;
  2094. #else
  2095. static const float2 mask_resize_src_lut_size = mask_texture_small_size;
  2096. #endif
  2097. #else
  2098. static const float2 mask_resize_src_lut_size = mask_texture_small_size;
  2099. #endif
  2100. // tex2D's sampler2D parameter MUST be a uniform global, a uniform input to
  2101. // main_fragment, or a static alias of one of the above. This makes it hard
  2102. // to select the phosphor mask at runtime: We can't even assign to a uniform
  2103. // global in the vertex shader or select a sampler2D in the vertex shader and
  2104. // pass it to the fragment shader (even with explicit TEXUNIT# bindings),
  2105. // because it just gives us the input texture or a black screen. However, we
  2106. // can get around these limitations by calling tex2D three times with different
  2107. // uniform samplers (or resizing the phosphor mask three times altogether).
  2108. // With dynamic branches, we can process only one of these branches on top of
  2109. // quickly discarding fragments we don't need (cgc seems able to overcome
  2110. // limigations around dependent texture fetches inside of branches). Without
  2111. // dynamic branches, we have to process every branch for every fragment...which
  2112. // is slower. Runtime sampling mode selection is slower without dynamic
  2113. // branches as well. Let the user's static #defines decide if it's worth it.
  2114. #ifdef DRIVERS_ALLOW_DYNAMIC_BRANCHES
  2115. #define RUNTIME_PHOSPHOR_MASK_MODE_TYPE_SELECT
  2116. #else
  2117. #ifdef FORCE_RUNTIME_PHOSPHOR_MASK_MODE_TYPE_SELECT
  2118. #define RUNTIME_PHOSPHOR_MASK_MODE_TYPE_SELECT
  2119. #endif
  2120. #endif
  2121. // We need to render some minimum number of tiles in the resize passes.
  2122. // We need at least 1.0 just to repeat a single tile, and we need extra
  2123. // padding beyond that for anisotropic filtering, discontinuitity fixing,
  2124. // antialiasing, same-pass curvature (not currently used), etc. First
  2125. // determine how many border texels and tiles we need, based on how the result
  2126. // will be sampled:
  2127. #ifdef GEOMETRY_EARLY
  2128. static const float max_subpixel_offset = aa_subpixel_r_offset_static.x;
  2129. // Most antialiasing filters have a base radius of 4.0 pixels:
  2130. static const float max_aa_base_pixel_border = 4.0 +
  2131. max_subpixel_offset;
  2132. #else
  2133. static const float max_aa_base_pixel_border = 0.0;
  2134. #endif
  2135. // Anisotropic filtering adds about 0.5 to the pixel border:
  2136. #ifndef ANISOTROPIC_TILING_COMPAT_TEX2DLOD_FAMILY
  2137. static const float max_aniso_pixel_border = max_aa_base_pixel_border + 0.5;
  2138. #else
  2139. static const float max_aniso_pixel_border = max_aa_base_pixel_border;
  2140. #endif
  2141. // Fixing discontinuities adds 1.0 more to the pixel border:
  2142. #ifdef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
  2143. static const float max_tiled_pixel_border = max_aniso_pixel_border + 1.0;
  2144. #else
  2145. static const float max_tiled_pixel_border = max_aniso_pixel_border;
  2146. #endif
  2147. // Convert the pixel border to an integer texel border. Assume same-pass
  2148. // curvature about triples the texel frequency:
  2149. #ifdef GEOMETRY_EARLY
  2150. static const float max_mask_texel_border =
  2151. ceil(max_tiled_pixel_border * 3.0);
  2152. #else
  2153. static const float max_mask_texel_border = ceil(max_tiled_pixel_border);
  2154. #endif
  2155. // Convert the texel border to a tile border using worst-case assumptions:
  2156. static const float max_mask_tile_border = max_mask_texel_border/
  2157. (mask_min_allowed_triad_size * mask_triads_per_tile);
  2158. // Finally, set the number of resized tiles to render to MASK_RESIZE, and set
  2159. // the starting texel (inside borders) for sampling it.
  2160. #ifndef GEOMETRY_EARLY
  2161. #ifdef ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE
  2162. // Special case: Render two tiles without borders. Anisotropic
  2163. // filtering doesn't seem to be a problem here.
  2164. static const float mask_resize_num_tiles = 1.0 + 1.0;
  2165. static const float mask_start_texels = 0.0;
  2166. #else
  2167. static const float mask_resize_num_tiles = 1.0 +
  2168. 2.0 * max_mask_tile_border;
  2169. static const float mask_start_texels = max_mask_texel_border;
  2170. #endif
  2171. #else
  2172. static const float mask_resize_num_tiles = 1.0 + 2.0*max_mask_tile_border;
  2173. static const float mask_start_texels = max_mask_texel_border;
  2174. #endif
  2175. // We have to fit mask_resize_num_tiles into an FBO with a viewport scale of
  2176. // mask_resize_viewport_scale. This limits the maximum final triad size.
  2177. // Estimate the minimum number of triads we can split the screen into in each
  2178. // dimension (we'll be as correct as mask_resize_viewport_scale is):
  2179. static const float mask_resize_num_triads =
  2180. mask_resize_num_tiles * mask_triads_per_tile;
  2181. static const float2 min_allowed_viewport_triads =
  2182. float2(mask_resize_num_triads) / mask_resize_viewport_scale;
  2183. //////////////////////// COMMON MATHEMATICAL CONSTANTS ///////////////////////
  2184. static const float pi = 3.141592653589;
  2185. // We often want to find the location of the previous texel, e.g.:
  2186. // const float2 curr_texel = uv * texture_size;
  2187. // const float2 prev_texel = floor(curr_texel - float2(0.5)) + float2(0.5);
  2188. // const float2 prev_texel_uv = prev_texel / texture_size;
  2189. // However, many GPU drivers round incorrectly around exact texel locations.
  2190. // We need to subtract a little less than 0.5 before flooring, and some GPU's
  2191. // require this value to be farther from 0.5 than others; define it here.
  2192. // const float2 prev_texel =
  2193. // floor(curr_texel - float2(under_half)) + float2(0.5);
  2194. static const float under_half = 0.4995;
  2195. #endif // DERIVED_SETTINGS_AND_CONSTANTS_H
  2196. //////////////////// END DERIVED-SETTINGS-AND-CONSTANTS /////////////////////
  2197. //////////////////////////////// END INCLUDES ////////////////////////////////
  2198. // Override some parameters for gamma-management.h and tex2Dantialias.h:
  2199. #define OVERRIDE_DEVICE_GAMMA
  2200. static const float gba_gamma = 3.5; // Irrelevant but necessary to define.
  2201. #define ANTIALIAS_OVERRIDE_BASICS
  2202. #define ANTIALIAS_OVERRIDE_PARAMETERS
  2203. // Provide accessors for vector constants that pack scalar uniforms:
  2204. inline float2 get_aspect_vector(const float geom_aspect_ratio)
  2205. {
  2206. // Get an aspect ratio vector. Enforce geom_max_aspect_ratio, and prevent
  2207. // the absolute scale from affecting the uv-mapping for curvature:
  2208. const float geom_clamped_aspect_ratio =
  2209. min(geom_aspect_ratio, geom_max_aspect_ratio);
  2210. const float2 geom_aspect =
  2211. normalize(float2(geom_clamped_aspect_ratio, 1.0));
  2212. return geom_aspect;
  2213. }
  2214. inline float2 get_geom_overscan_vector()
  2215. {
  2216. return float2(geom_overscan_x, geom_overscan_y);
  2217. }
  2218. inline float2 get_geom_tilt_angle_vector()
  2219. {
  2220. return float2(geom_tilt_angle_x, geom_tilt_angle_y);
  2221. }
  2222. inline float3 get_convergence_offsets_x_vector()
  2223. {
  2224. return float3(convergence_offset_x_r, convergence_offset_x_g,
  2225. convergence_offset_x_b);
  2226. }
  2227. inline float3 get_convergence_offsets_y_vector()
  2228. {
  2229. return float3(convergence_offset_y_r, convergence_offset_y_g,
  2230. convergence_offset_y_b);
  2231. }
  2232. inline float2 get_convergence_offsets_r_vector()
  2233. {
  2234. return float2(convergence_offset_x_r, convergence_offset_y_r);
  2235. }
  2236. inline float2 get_convergence_offsets_g_vector()
  2237. {
  2238. return float2(convergence_offset_x_g, convergence_offset_y_g);
  2239. }
  2240. inline float2 get_convergence_offsets_b_vector()
  2241. {
  2242. return float2(convergence_offset_x_b, convergence_offset_y_b);
  2243. }
  2244. inline float2 get_aa_subpixel_r_offset()
  2245. {
  2246. #ifdef RUNTIME_ANTIALIAS_WEIGHTS
  2247. #ifdef RUNTIME_ANTIALIAS_SUBPIXEL_OFFSETS
  2248. // WARNING: THIS IS EXTREMELY EXPENSIVE.
  2249. return float2(aa_subpixel_r_offset_x_runtime,
  2250. aa_subpixel_r_offset_y_runtime);
  2251. #else
  2252. return aa_subpixel_r_offset_static;
  2253. #endif
  2254. #else
  2255. return aa_subpixel_r_offset_static;
  2256. #endif
  2257. }
  2258. // Provide accessors settings which still need "cooking:"
  2259. inline float get_mask_amplify()
  2260. {
  2261. static const float mask_grille_amplify = 1.0/mask_grille_avg_color;
  2262. static const float mask_slot_amplify = 1.0/mask_slot_avg_color;
  2263. static const float mask_shadow_amplify = 1.0/mask_shadow_avg_color;
  2264. return mask_type < 0.5 ? mask_grille_amplify :
  2265. mask_type < 1.5 ? mask_slot_amplify :
  2266. mask_shadow_amplify;
  2267. }
  2268. inline float get_mask_sample_mode()
  2269. {
  2270. #ifdef RUNTIME_PHOSPHOR_MASK_MODE_TYPE_SELECT
  2271. #ifdef PHOSPHOR_MASK_MANUALLY_RESIZE
  2272. return mask_sample_mode_desired;
  2273. #else
  2274. return clamp(mask_sample_mode_desired, 1.0, 2.0);
  2275. #endif
  2276. #else
  2277. #ifdef PHOSPHOR_MASK_MANUALLY_RESIZE
  2278. return mask_sample_mode_static;
  2279. #else
  2280. return clamp(mask_sample_mode_static, 1.0, 2.0);
  2281. #endif
  2282. #endif
  2283. }
  2284. #endif // BIND_SHADER_PARAMS_H
  2285. //////////////////////////// END BIND-SHADER-PARAMS ///////////////////////////
  2286. /////////////////////////////// VERTEX INCLUDES ///////////////////////////////
  2287. //#include "scanline-functions.h"
  2288. ///////////////////////////// BEGIN SCANLINE-FUNCTIONS ////////////////////////////
  2289. #ifndef SCANLINE_FUNCTIONS_H
  2290. #define SCANLINE_FUNCTIONS_H
  2291. ///////////////////////////// GPL LICENSE NOTICE /////////////////////////////
  2292. // crt-royale: A full-featured CRT shader, with cheese.
  2293. // Copyright (C) 2014 TroggleMonkey <trogglemonkey@gmx.com>
  2294. //
  2295. // This program is free software; you can redistribute it and/or modify it
  2296. // under the terms of the GNU General Public License as published by the Free
  2297. // Software Foundation; either version 2 of the License, or any later version.
  2298. //
  2299. // This program is distributed in the hope that it will be useful, but WITHOUT
  2300. // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  2301. // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  2302. // more details.
  2303. //
  2304. // You should have received a copy of the GNU General Public License along with
  2305. // this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  2306. // Place, Suite 330, Boston, MA 02111-1307 USA
  2307. /////////////////////////////// BEGIN INCLUDES ///////////////////////////////
  2308. //#include "../user-settings.h"
  2309. ///////////////////////////// BEGIN USER-SETTINGS ////////////////////////////
  2310. #ifndef USER_SETTINGS_H
  2311. #define USER_SETTINGS_H
  2312. ///////////////////////////// DRIVER CAPABILITIES ////////////////////////////
  2313. // The Cg compiler uses different "profiles" with different capabilities.
  2314. // This shader requires a Cg compilation profile >= arbfp1, but a few options
  2315. // require higher profiles like fp30 or fp40. The shader can't detect profile
  2316. // or driver capabilities, so instead you must comment or uncomment the lines
  2317. // below with "//" before "#define." Disable an option if you get compilation
  2318. // errors resembling those listed. Generally speaking, all of these options
  2319. // will run on nVidia cards, but only DRIVERS_ALLOW_TEX2DBIAS (if that) is
  2320. // likely to run on ATI/AMD, due to the Cg compiler's profile limitations.
  2321. // Derivatives: Unsupported on fp20, ps_1_1, ps_1_2, ps_1_3, and arbfp1.
  2322. // Among other things, derivatives help us fix anisotropic filtering artifacts
  2323. // with curved manually tiled phosphor mask coords. Related errors:
  2324. // error C3004: function "float2 ddx(float2);" not supported in this profile
  2325. // error C3004: function "float2 ddy(float2);" not supported in this profile
  2326. //#define DRIVERS_ALLOW_DERIVATIVES
  2327. // Fine derivatives: Unsupported on older ATI cards.
  2328. // Fine derivatives enable 2x2 fragment block communication, letting us perform
  2329. // fast single-pass blur operations. If your card uses coarse derivatives and
  2330. // these are enabled, blurs could look broken. Derivatives are a prerequisite.
  2331. #ifdef DRIVERS_ALLOW_DERIVATIVES
  2332. #define DRIVERS_ALLOW_FINE_DERIVATIVES
  2333. #endif
  2334. // Dynamic looping: Requires an fp30 or newer profile.
  2335. // This makes phosphor mask resampling faster in some cases. Related errors:
  2336. // error C5013: profile does not support "for" statements and "for" could not
  2337. // be unrolled
  2338. //#define DRIVERS_ALLOW_DYNAMIC_BRANCHES
  2339. // Without DRIVERS_ALLOW_DYNAMIC_BRANCHES, we need to use unrollable loops.
  2340. // Using one static loop avoids overhead if the user is right, but if the user
  2341. // is wrong (loops are allowed), breaking a loop into if-blocked pieces with a
  2342. // binary search can potentially save some iterations. However, it may fail:
  2343. // error C6001: Temporary register limit of 32 exceeded; 35 registers
  2344. // needed to compile program
  2345. //#define ACCOMODATE_POSSIBLE_DYNAMIC_LOOPS
  2346. // tex2Dlod: Requires an fp40 or newer profile. This can be used to disable
  2347. // anisotropic filtering, thereby fixing related artifacts. Related errors:
  2348. // error C3004: function "float4 tex2Dlod(sampler2D, float4);" not supported in
  2349. // this profile
  2350. //#define DRIVERS_ALLOW_TEX2DLOD
  2351. // tex2Dbias: Requires an fp30 or newer profile. This can be used to alleviate
  2352. // artifacts from anisotropic filtering and mipmapping. Related errors:
  2353. // error C3004: function "float4 tex2Dbias(sampler2D, float4);" not supported
  2354. // in this profile
  2355. //#define DRIVERS_ALLOW_TEX2DBIAS
  2356. // Integrated graphics compatibility: Integrated graphics like Intel HD 4000
  2357. // impose stricter limitations on register counts and instructions. Enable
  2358. // INTEGRATED_GRAPHICS_COMPATIBILITY_MODE if you still see error C6001 or:
  2359. // error C6002: Instruction limit of 1024 exceeded: 1523 instructions needed
  2360. // to compile program.
  2361. // Enabling integrated graphics compatibility mode will automatically disable:
  2362. // 1.) PHOSPHOR_MASK_MANUALLY_RESIZE: The phosphor mask will be softer.
  2363. // (This may be reenabled in a later release.)
  2364. // 2.) RUNTIME_GEOMETRY_MODE
  2365. // 3.) The high-quality 4x4 Gaussian resize for the bloom approximation
  2366. //#define INTEGRATED_GRAPHICS_COMPATIBILITY_MODE
  2367. //////////////////////////// USER CODEPATH OPTIONS ///////////////////////////
  2368. // To disable a #define option, turn its line into a comment with "//."
  2369. // RUNTIME VS. COMPILE-TIME OPTIONS (Major Performance Implications):
  2370. // Enable runtime shader parameters in the Retroarch (etc.) GUI? They override
  2371. // many of the options in this file and allow real-time tuning, but many of
  2372. // them are slower. Disabling them and using this text file will boost FPS.
  2373. #define RUNTIME_SHADER_PARAMS_ENABLE
  2374. // Specify the phosphor bloom sigma at runtime? This option is 10% slower, but
  2375. // it's the only way to do a wide-enough full bloom with a runtime dot pitch.
  2376. #define RUNTIME_PHOSPHOR_BLOOM_SIGMA
  2377. // Specify antialiasing weight parameters at runtime? (Costs ~20% with cubics)
  2378. #define RUNTIME_ANTIALIAS_WEIGHTS
  2379. // Specify subpixel offsets at runtime? (WARNING: EXTREMELY EXPENSIVE!)
  2380. //#define RUNTIME_ANTIALIAS_SUBPIXEL_OFFSETS
  2381. // Make beam_horiz_filter and beam_horiz_linear_rgb_weight into runtime shader
  2382. // parameters? This will require more math or dynamic branching.
  2383. #define RUNTIME_SCANLINES_HORIZ_FILTER_COLORSPACE
  2384. // Specify the tilt at runtime? This makes things about 3% slower.
  2385. #define RUNTIME_GEOMETRY_TILT
  2386. // Specify the geometry mode at runtime?
  2387. #define RUNTIME_GEOMETRY_MODE
  2388. // Specify the phosphor mask type (aperture grille, slot mask, shadow mask) and
  2389. // mode (Lanczos-resize, hardware resize, or tile 1:1) at runtime, even without
  2390. // dynamic branches? This is cheap if mask_resize_viewport_scale is small.
  2391. #define FORCE_RUNTIME_PHOSPHOR_MASK_MODE_TYPE_SELECT
  2392. // PHOSPHOR MASK:
  2393. // Manually resize the phosphor mask for best results (slower)? Disabling this
  2394. // removes the option to do so, but it may be faster without dynamic branches.
  2395. #define PHOSPHOR_MASK_MANUALLY_RESIZE
  2396. // If we sinc-resize the mask, should we Lanczos-window it (slower but better)?
  2397. #define PHOSPHOR_MASK_RESIZE_LANCZOS_WINDOW
  2398. // Larger blurs are expensive, but we need them to blur larger triads. We can
  2399. // detect the right blur if the triad size is static or our profile allows
  2400. // dynamic branches, but otherwise we use the largest blur the user indicates
  2401. // they might need:
  2402. #define PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_3_PIXELS
  2403. //#define PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_6_PIXELS
  2404. //#define PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_9_PIXELS
  2405. //#define PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_12_PIXELS
  2406. // Here's a helpful chart:
  2407. // MaxTriadSize BlurSize MinTriadCountsByResolution
  2408. // 3.0 9.0 480/640/960/1920 triads at 1080p/1440p/2160p/4320p, 4:3 aspect
  2409. // 6.0 17.0 240/320/480/960 triads at 1080p/1440p/2160p/4320p, 4:3 aspect
  2410. // 9.0 25.0 160/213/320/640 triads at 1080p/1440p/2160p/4320p, 4:3 aspect
  2411. // 12.0 31.0 120/160/240/480 triads at 1080p/1440p/2160p/4320p, 4:3 aspect
  2412. // 18.0 43.0 80/107/160/320 triads at 1080p/1440p/2160p/4320p, 4:3 aspect
  2413. /////////////////////////////// USER PARAMETERS //////////////////////////////
  2414. // Note: Many of these static parameters are overridden by runtime shader
  2415. // parameters when those are enabled. However, many others are static codepath
  2416. // options that were cleaner or more convert to code as static constants.
  2417. // GAMMA:
  2418. static const float crt_gamma_static = 2.5; // range [1, 5]
  2419. static const float lcd_gamma_static = 2.2; // range [1, 5]
  2420. // LEVELS MANAGEMENT:
  2421. // Control the final multiplicative image contrast:
  2422. static const float levels_contrast_static = 1.0; // range [0, 4)
  2423. // We auto-dim to avoid clipping between passes and restore brightness
  2424. // later. Control the dim factor here: Lower values clip less but crush
  2425. // blacks more (static only for now).
  2426. static const float levels_autodim_temp = 0.5; // range (0, 1] default is 0.5 but that was unnecessarily dark for me, so I set it to 1.0
  2427. // HALATION/DIFFUSION/BLOOM:
  2428. // Halation weight: How much energy should be lost to electrons bounding
  2429. // around under the CRT glass and exciting random phosphors?
  2430. static const float halation_weight_static = 0.0; // range [0, 1]
  2431. // Refractive diffusion weight: How much light should spread/diffuse from
  2432. // refracting through the CRT glass?
  2433. static const float diffusion_weight_static = 0.075; // range [0, 1]
  2434. // Underestimate brightness: Bright areas bloom more, but we can base the
  2435. // bloom brightpass on a lower brightness to sharpen phosphors, or a higher
  2436. // brightness to soften them. Low values clip, but >= 0.8 looks okay.
  2437. static const float bloom_underestimate_levels_static = 0.8; // range [0, 5]
  2438. // Blur all colors more than necessary for a softer phosphor bloom?
  2439. static const float bloom_excess_static = 0.0; // range [0, 1]
  2440. // The BLOOM_APPROX pass approximates a phosphor blur early on with a small
  2441. // blurred resize of the input (convergence offsets are applied as well).
  2442. // There are three filter options (static option only for now):
  2443. // 0.) Bilinear resize: A fast, close approximation to a 4x4 resize
  2444. // if min_allowed_viewport_triads and the BLOOM_APPROX resolution are sane
  2445. // and beam_max_sigma is low.
  2446. // 1.) 3x3 resize blur: Medium speed, soft/smeared from bilinear blurring,
  2447. // always uses a static sigma regardless of beam_max_sigma or
  2448. // mask_num_triads_desired.
  2449. // 2.) True 4x4 Gaussian resize: Slowest, technically correct.
  2450. // These options are more pronounced for the fast, unbloomed shader version.
  2451. #ifndef RADEON_FIX
  2452. static const float bloom_approx_filter_static = 2.0;
  2453. #else
  2454. static const float bloom_approx_filter_static = 1.0;
  2455. #endif
  2456. // ELECTRON BEAM SCANLINE DISTRIBUTION:
  2457. // How many scanlines should contribute light to each pixel? Using more
  2458. // scanlines is slower (especially for a generalized Gaussian) but less
  2459. // distorted with larger beam sigmas (especially for a pure Gaussian). The
  2460. // max_beam_sigma at which the closest unused weight is guaranteed <
  2461. // 1.0/255.0 (for a 3x antialiased pure Gaussian) is:
  2462. // 2 scanlines: max_beam_sigma = 0.2089; distortions begin ~0.34; 141.7 FPS pure, 131.9 FPS generalized
  2463. // 3 scanlines, max_beam_sigma = 0.3879; distortions begin ~0.52; 137.5 FPS pure; 123.8 FPS generalized
  2464. // 4 scanlines, max_beam_sigma = 0.5723; distortions begin ~0.70; 134.7 FPS pure; 117.2 FPS generalized
  2465. // 5 scanlines, max_beam_sigma = 0.7591; distortions begin ~0.89; 131.6 FPS pure; 112.1 FPS generalized
  2466. // 6 scanlines, max_beam_sigma = 0.9483; distortions begin ~1.08; 127.9 FPS pure; 105.6 FPS generalized
  2467. static const float beam_num_scanlines = 3.0; // range [2, 6]
  2468. // A generalized Gaussian beam varies shape with color too, now just width.
  2469. // It's slower but more flexible (static option only for now).
  2470. static const bool beam_generalized_gaussian = true;
  2471. // What kind of scanline antialiasing do you want?
  2472. // 0: Sample weights at 1x; 1: Sample weights at 3x; 2: Compute an integral
  2473. // Integrals are slow (especially for generalized Gaussians) and rarely any
  2474. // better than 3x antialiasing (static option only for now).
  2475. static const float beam_antialias_level = 1.0; // range [0, 2]
  2476. // Min/max standard deviations for scanline beams: Higher values widen and
  2477. // soften scanlines. Depending on other options, low min sigmas can alias.
  2478. static const float beam_min_sigma_static = 0.02; // range (0, 1]
  2479. static const float beam_max_sigma_static = 0.3; // range (0, 1]
  2480. // Beam width varies as a function of color: A power function (0) is more
  2481. // configurable, but a spherical function (1) gives the widest beam
  2482. // variability without aliasing (static option only for now).
  2483. static const float beam_spot_shape_function = 0.0;
  2484. // Spot shape power: Powers <= 1 give smoother spot shapes but lower
  2485. // sharpness. Powers >= 1.0 are awful unless mix/max sigmas are close.
  2486. static const float beam_spot_power_static = 1.0/3.0; // range (0, 16]
  2487. // Generalized Gaussian max shape parameters: Higher values give flatter
  2488. // scanline plateaus and steeper dropoffs, simultaneously widening and
  2489. // sharpening scanlines at the cost of aliasing. 2.0 is pure Gaussian, and
  2490. // values > ~40.0 cause artifacts with integrals.
  2491. static const float beam_min_shape_static = 2.0; // range [2, 32]
  2492. static const float beam_max_shape_static = 4.0; // range [2, 32]
  2493. // Generalized Gaussian shape power: Affects how quickly the distribution
  2494. // changes shape from Gaussian to steep/plateaued as color increases from 0
  2495. // to 1.0. Higher powers appear softer for most colors, and lower powers
  2496. // appear sharper for most colors.
  2497. static const float beam_shape_power_static = 1.0/4.0; // range (0, 16]
  2498. // What filter should be used to sample scanlines horizontally?
  2499. // 0: Quilez (fast), 1: Gaussian (configurable), 2: Lanczos2 (sharp)
  2500. static const float beam_horiz_filter_static = 0.0;
  2501. // Standard deviation for horizontal Gaussian resampling:
  2502. static const float beam_horiz_sigma_static = 0.35; // range (0, 2/3]
  2503. // Do horizontal scanline sampling in linear RGB (correct light mixing),
  2504. // gamma-encoded RGB (darker, hard spot shape, may better match bandwidth-
  2505. // limiting circuitry in some CRT's), or a weighted avg.?
  2506. static const float beam_horiz_linear_rgb_weight_static = 1.0; // range [0, 1]
  2507. // Simulate scanline misconvergence? This needs 3x horizontal texture
  2508. // samples and 3x texture samples of BLOOM_APPROX and HALATION_BLUR in
  2509. // later passes (static option only for now).
  2510. static const bool beam_misconvergence = true;
  2511. // Convergence offsets in x/y directions for R/G/B scanline beams in units
  2512. // of scanlines. Positive offsets go right/down; ranges [-2, 2]
  2513. static const float2 convergence_offsets_r_static = float2(0.1, 0.2);
  2514. static const float2 convergence_offsets_g_static = float2(0.3, 0.4);
  2515. static const float2 convergence_offsets_b_static = float2(0.5, 0.6);
  2516. // Detect interlacing (static option only for now)?
  2517. static const bool interlace_detect = true;
  2518. // Assume 1080-line sources are interlaced?
  2519. static const bool interlace_1080i_static = false;
  2520. // For interlaced sources, assume TFF (top-field first) or BFF order?
  2521. // (Whether this matters depends on the nature of the interlaced input.)
  2522. static const bool interlace_bff_static = false;
  2523. // ANTIALIASING:
  2524. // What AA level do you want for curvature/overscan/subpixels? Options:
  2525. // 0x (none), 1x (sample subpixels), 4x, 5x, 6x, 7x, 8x, 12x, 16x, 20x, 24x
  2526. // (Static option only for now)
  2527. static const float aa_level = 12.0; // range [0, 24]
  2528. // What antialiasing filter do you want (static option only)? Options:
  2529. // 0: Box (separable), 1: Box (cylindrical),
  2530. // 2: Tent (separable), 3: Tent (cylindrical),
  2531. // 4: Gaussian (separable), 5: Gaussian (cylindrical),
  2532. // 6: Cubic* (separable), 7: Cubic* (cylindrical, poor)
  2533. // 8: Lanczos Sinc (separable), 9: Lanczos Jinc (cylindrical, poor)
  2534. // * = Especially slow with RUNTIME_ANTIALIAS_WEIGHTS
  2535. static const float aa_filter = 6.0; // range [0, 9]
  2536. // Flip the sample grid on odd/even frames (static option only for now)?
  2537. static const bool aa_temporal = false;
  2538. // Use RGB subpixel offsets for antialiasing? The pixel is at green, and
  2539. // the blue offset is the negative r offset; range [0, 0.5]
  2540. static const float2 aa_subpixel_r_offset_static = float2(-1.0/3.0, 0.0);//float2(0.0);
  2541. // Cubics: See http://www.imagemagick.org/Usage/filter/#mitchell
  2542. // 1.) "Keys cubics" with B = 1 - 2C are considered the highest quality.
  2543. // 2.) C = 0.5 (default) is Catmull-Rom; higher C's apply sharpening.
  2544. // 3.) C = 1.0/3.0 is the Mitchell-Netravali filter.
  2545. // 4.) C = 0.0 is a soft spline filter.
  2546. static const float aa_cubic_c_static = 0.5; // range [0, 4]
  2547. // Standard deviation for Gaussian antialiasing: Try 0.5/aa_pixel_diameter.
  2548. static const float aa_gauss_sigma_static = 0.5; // range [0.0625, 1.0]
  2549. // PHOSPHOR MASK:
  2550. // Mask type: 0 = aperture grille, 1 = slot mask, 2 = EDP shadow mask
  2551. static const float mask_type_static = 1.0; // range [0, 2]
  2552. // We can sample the mask three ways. Pick 2/3 from: Pretty/Fast/Flexible.
  2553. // 0.) Sinc-resize to the desired dot pitch manually (pretty/slow/flexible).
  2554. // This requires PHOSPHOR_MASK_MANUALLY_RESIZE to be #defined.
  2555. // 1.) Hardware-resize to the desired dot pitch (ugly/fast/flexible). This
  2556. // is halfway decent with LUT mipmapping but atrocious without it.
  2557. // 2.) Tile it without resizing at a 1:1 texel:pixel ratio for flat coords
  2558. // (pretty/fast/inflexible). Each input LUT has a fixed dot pitch.
  2559. // This mode reuses the same masks, so triads will be enormous unless
  2560. // you change the mask LUT filenames in your .cgp file.
  2561. static const float mask_sample_mode_static = 0.0; // range [0, 2]
  2562. // Prefer setting the triad size (0.0) or number on the screen (1.0)?
  2563. // If RUNTIME_PHOSPHOR_BLOOM_SIGMA isn't #defined, the specified triad size
  2564. // will always be used to calculate the full bloom sigma statically.
  2565. static const float mask_specify_num_triads_static = 0.0; // range [0, 1]
  2566. // Specify the phosphor triad size, in pixels. Each tile (usually with 8
  2567. // triads) will be rounded to the nearest integer tile size and clamped to
  2568. // obey minimum size constraints (imposed to reduce downsize taps) and
  2569. // maximum size constraints (imposed to have a sane MASK_RESIZE FBO size).
  2570. // To increase the size limit, double the viewport-relative scales for the
  2571. // two MASK_RESIZE passes in crt-royale.cgp and user-cgp-contants.h.
  2572. // range [1, mask_texture_small_size/mask_triads_per_tile]
  2573. static const float mask_triad_size_desired_static = 24.0 / 8.0;
  2574. // If mask_specify_num_triads is 1.0/true, we'll go by this instead (the
  2575. // final size will be rounded and constrained as above); default 480.0
  2576. static const float mask_num_triads_desired_static = 480.0;
  2577. // How many lobes should the sinc/Lanczos resizer use? More lobes require
  2578. // more samples and avoid moire a bit better, but some is unavoidable
  2579. // depending on the destination size (static option for now).
  2580. static const float mask_sinc_lobes = 3.0; // range [2, 4]
  2581. // The mask is resized using a variable number of taps in each dimension,
  2582. // but some Cg profiles always fetch a constant number of taps no matter
  2583. // what (no dynamic branching). We can limit the maximum number of taps if
  2584. // we statically limit the minimum phosphor triad size. Larger values are
  2585. // faster, but the limit IS enforced (static option only, forever);
  2586. // range [1, mask_texture_small_size/mask_triads_per_tile]
  2587. // TODO: Make this 1.0 and compensate with smarter sampling!
  2588. static const float mask_min_allowed_triad_size = 2.0;
  2589. // GEOMETRY:
  2590. // Geometry mode:
  2591. // 0: Off (default), 1: Spherical mapping (like cgwg's),
  2592. // 2: Alt. spherical mapping (more bulbous), 3: Cylindrical/Trinitron
  2593. static const float geom_mode_static = 0.0; // range [0, 3]
  2594. // Radius of curvature: Measured in units of your viewport's diagonal size.
  2595. static const float geom_radius_static = 2.0; // range [1/(2*pi), 1024]
  2596. // View dist is the distance from the player to their physical screen, in
  2597. // units of the viewport's diagonal size. It controls the field of view.
  2598. static const float geom_view_dist_static = 2.0; // range [0.5, 1024]
  2599. // Tilt angle in radians (clockwise around up and right vectors):
  2600. static const float2 geom_tilt_angle_static = float2(0.0, 0.0); // range [-pi, pi]
  2601. // Aspect ratio: When the true viewport size is unknown, this value is used
  2602. // to help convert between the phosphor triad size and count, along with
  2603. // the mask_resize_viewport_scale constant from user-cgp-constants.h. Set
  2604. // this equal to Retroarch's display aspect ratio (DAR) for best results;
  2605. // range [1, geom_max_aspect_ratio from user-cgp-constants.h];
  2606. // default (256/224)*(54/47) = 1.313069909 (see below)
  2607. static const float geom_aspect_ratio_static = 1.313069909;
  2608. // Before getting into overscan, here's some general aspect ratio info:
  2609. // - DAR = display aspect ratio = SAR * PAR; as in your Retroarch setting
  2610. // - SAR = storage aspect ratio = DAR / PAR; square pixel emulator frame AR
  2611. // - PAR = pixel aspect ratio = DAR / SAR; holds regardless of cropping
  2612. // Geometry processing has to "undo" the screen-space 2D DAR to calculate
  2613. // 3D view vectors, then reapplies the aspect ratio to the simulated CRT in
  2614. // uv-space. To ensure the source SAR is intended for a ~4:3 DAR, either:
  2615. // a.) Enable Retroarch's "Crop Overscan"
  2616. // b.) Readd horizontal padding: Set overscan to e.g. N*(1.0, 240.0/224.0)
  2617. // Real consoles use horizontal black padding in the signal, but emulators
  2618. // often crop this without cropping the vertical padding; a 256x224 [S]NES
  2619. // frame (8:7 SAR) is intended for a ~4:3 DAR, but a 256x240 frame is not.
  2620. // The correct [S]NES PAR is 54:47, found by blargg and NewRisingSun:
  2621. // http://board.zsnes.com/phpBB3/viewtopic.php?f=22&t=11928&start=50
  2622. // http://forums.nesdev.com/viewtopic.php?p=24815#p24815
  2623. // For flat output, it's okay to set DAR = [existing] SAR * [correct] PAR
  2624. // without doing a. or b., but horizontal image borders will be tighter
  2625. // than vertical ones, messing up curvature and overscan. Fixing the
  2626. // padding first corrects this.
  2627. // Overscan: Amount to "zoom in" before cropping. You can zoom uniformly
  2628. // or adjust x/y independently to e.g. readd horizontal padding, as noted
  2629. // above: Values < 1.0 zoom out; range (0, inf)
  2630. static const float2 geom_overscan_static = float2(1.0, 1.0);// * 1.005 * (1.0, 240/224.0)
  2631. // Compute a proper pixel-space to texture-space matrix even without ddx()/
  2632. // ddy()? This is ~8.5% slower but improves antialiasing/subpixel filtering
  2633. // with strong curvature (static option only for now).
  2634. static const bool geom_force_correct_tangent_matrix = true;
  2635. // BORDERS:
  2636. // Rounded border size in texture uv coords:
  2637. static const float border_size_static = 0.015; // range [0, 0.5]
  2638. // Border darkness: Moderate values darken the border smoothly, and high
  2639. // values make the image very dark just inside the border:
  2640. static const float border_darkness_static = 2.0; // range [0, inf)
  2641. // Border compression: High numbers compress border transitions, narrowing
  2642. // the dark border area.
  2643. static const float border_compress_static = 2.5; // range [1, inf)
  2644. #endif // USER_SETTINGS_H
  2645. //////////////////////////// END USER-SETTINGS //////////////////////////
  2646. //#include "derived-settings-and-constants.h"
  2647. //////////////////// BEGIN DERIVED-SETTINGS-AND-CONSTANTS ////////////////////
  2648. #ifndef DERIVED_SETTINGS_AND_CONSTANTS_H
  2649. #define DERIVED_SETTINGS_AND_CONSTANTS_H
  2650. ///////////////////////////// GPL LICENSE NOTICE /////////////////////////////
  2651. // crt-royale: A full-featured CRT shader, with cheese.
  2652. // Copyright (C) 2014 TroggleMonkey <trogglemonkey@gmx.com>
  2653. //
  2654. // This program is free software; you can redistribute it and/or modify it
  2655. // under the terms of the GNU General Public License as published by the Free
  2656. // Software Foundation; either version 2 of the License, or any later version.
  2657. //
  2658. // This program is distributed in the hope that it will be useful, but WITHOUT
  2659. // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  2660. // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  2661. // more details.
  2662. //
  2663. // You should have received a copy of the GNU General Public License along with
  2664. // this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  2665. // Place, Suite 330, Boston, MA 02111-1307 USA
  2666. ///////////////////////////////// DESCRIPTION ////////////////////////////////
  2667. // These macros and constants can be used across the whole codebase.
  2668. // Unlike the values in user-settings.cgh, end users shouldn't modify these.
  2669. /////////////////////////////// BEGIN INCLUDES ///////////////////////////////
  2670. //#include "../user-settings.h"
  2671. ///////////////////////////// BEGIN USER-SETTINGS ////////////////////////////
  2672. #ifndef USER_SETTINGS_H
  2673. #define USER_SETTINGS_H
  2674. ///////////////////////////// DRIVER CAPABILITIES ////////////////////////////
  2675. // The Cg compiler uses different "profiles" with different capabilities.
  2676. // This shader requires a Cg compilation profile >= arbfp1, but a few options
  2677. // require higher profiles like fp30 or fp40. The shader can't detect profile
  2678. // or driver capabilities, so instead you must comment or uncomment the lines
  2679. // below with "//" before "#define." Disable an option if you get compilation
  2680. // errors resembling those listed. Generally speaking, all of these options
  2681. // will run on nVidia cards, but only DRIVERS_ALLOW_TEX2DBIAS (if that) is
  2682. // likely to run on ATI/AMD, due to the Cg compiler's profile limitations.
  2683. // Derivatives: Unsupported on fp20, ps_1_1, ps_1_2, ps_1_3, and arbfp1.
  2684. // Among other things, derivatives help us fix anisotropic filtering artifacts
  2685. // with curved manually tiled phosphor mask coords. Related errors:
  2686. // error C3004: function "float2 ddx(float2);" not supported in this profile
  2687. // error C3004: function "float2 ddy(float2);" not supported in this profile
  2688. //#define DRIVERS_ALLOW_DERIVATIVES
  2689. // Fine derivatives: Unsupported on older ATI cards.
  2690. // Fine derivatives enable 2x2 fragment block communication, letting us perform
  2691. // fast single-pass blur operations. If your card uses coarse derivatives and
  2692. // these are enabled, blurs could look broken. Derivatives are a prerequisite.
  2693. #ifdef DRIVERS_ALLOW_DERIVATIVES
  2694. #define DRIVERS_ALLOW_FINE_DERIVATIVES
  2695. #endif
  2696. // Dynamic looping: Requires an fp30 or newer profile.
  2697. // This makes phosphor mask resampling faster in some cases. Related errors:
  2698. // error C5013: profile does not support "for" statements and "for" could not
  2699. // be unrolled
  2700. //#define DRIVERS_ALLOW_DYNAMIC_BRANCHES
  2701. // Without DRIVERS_ALLOW_DYNAMIC_BRANCHES, we need to use unrollable loops.
  2702. // Using one static loop avoids overhead if the user is right, but if the user
  2703. // is wrong (loops are allowed), breaking a loop into if-blocked pieces with a
  2704. // binary search can potentially save some iterations. However, it may fail:
  2705. // error C6001: Temporary register limit of 32 exceeded; 35 registers
  2706. // needed to compile program
  2707. //#define ACCOMODATE_POSSIBLE_DYNAMIC_LOOPS
  2708. // tex2Dlod: Requires an fp40 or newer profile. This can be used to disable
  2709. // anisotropic filtering, thereby fixing related artifacts. Related errors:
  2710. // error C3004: function "float4 tex2Dlod(sampler2D, float4);" not supported in
  2711. // this profile
  2712. //#define DRIVERS_ALLOW_TEX2DLOD
  2713. // tex2Dbias: Requires an fp30 or newer profile. This can be used to alleviate
  2714. // artifacts from anisotropic filtering and mipmapping. Related errors:
  2715. // error C3004: function "float4 tex2Dbias(sampler2D, float4);" not supported
  2716. // in this profile
  2717. //#define DRIVERS_ALLOW_TEX2DBIAS
  2718. // Integrated graphics compatibility: Integrated graphics like Intel HD 4000
  2719. // impose stricter limitations on register counts and instructions. Enable
  2720. // INTEGRATED_GRAPHICS_COMPATIBILITY_MODE if you still see error C6001 or:
  2721. // error C6002: Instruction limit of 1024 exceeded: 1523 instructions needed
  2722. // to compile program.
  2723. // Enabling integrated graphics compatibility mode will automatically disable:
  2724. // 1.) PHOSPHOR_MASK_MANUALLY_RESIZE: The phosphor mask will be softer.
  2725. // (This may be reenabled in a later release.)
  2726. // 2.) RUNTIME_GEOMETRY_MODE
  2727. // 3.) The high-quality 4x4 Gaussian resize for the bloom approximation
  2728. //#define INTEGRATED_GRAPHICS_COMPATIBILITY_MODE
  2729. //////////////////////////// USER CODEPATH OPTIONS ///////////////////////////
  2730. // To disable a #define option, turn its line into a comment with "//."
  2731. // RUNTIME VS. COMPILE-TIME OPTIONS (Major Performance Implications):
  2732. // Enable runtime shader parameters in the Retroarch (etc.) GUI? They override
  2733. // many of the options in this file and allow real-time tuning, but many of
  2734. // them are slower. Disabling them and using this text file will boost FPS.
  2735. #define RUNTIME_SHADER_PARAMS_ENABLE
  2736. // Specify the phosphor bloom sigma at runtime? This option is 10% slower, but
  2737. // it's the only way to do a wide-enough full bloom with a runtime dot pitch.
  2738. #define RUNTIME_PHOSPHOR_BLOOM_SIGMA
  2739. // Specify antialiasing weight parameters at runtime? (Costs ~20% with cubics)
  2740. #define RUNTIME_ANTIALIAS_WEIGHTS
  2741. // Specify subpixel offsets at runtime? (WARNING: EXTREMELY EXPENSIVE!)
  2742. //#define RUNTIME_ANTIALIAS_SUBPIXEL_OFFSETS
  2743. // Make beam_horiz_filter and beam_horiz_linear_rgb_weight into runtime shader
  2744. // parameters? This will require more math or dynamic branching.
  2745. #define RUNTIME_SCANLINES_HORIZ_FILTER_COLORSPACE
  2746. // Specify the tilt at runtime? This makes things about 3% slower.
  2747. #define RUNTIME_GEOMETRY_TILT
  2748. // Specify the geometry mode at runtime?
  2749. #define RUNTIME_GEOMETRY_MODE
  2750. // Specify the phosphor mask type (aperture grille, slot mask, shadow mask) and
  2751. // mode (Lanczos-resize, hardware resize, or tile 1:1) at runtime, even without
  2752. // dynamic branches? This is cheap if mask_resize_viewport_scale is small.
  2753. #define FORCE_RUNTIME_PHOSPHOR_MASK_MODE_TYPE_SELECT
  2754. // PHOSPHOR MASK:
  2755. // Manually resize the phosphor mask for best results (slower)? Disabling this
  2756. // removes the option to do so, but it may be faster without dynamic branches.
  2757. #define PHOSPHOR_MASK_MANUALLY_RESIZE
  2758. // If we sinc-resize the mask, should we Lanczos-window it (slower but better)?
  2759. #define PHOSPHOR_MASK_RESIZE_LANCZOS_WINDOW
  2760. // Larger blurs are expensive, but we need them to blur larger triads. We can
  2761. // detect the right blur if the triad size is static or our profile allows
  2762. // dynamic branches, but otherwise we use the largest blur the user indicates
  2763. // they might need:
  2764. #define PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_3_PIXELS
  2765. //#define PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_6_PIXELS
  2766. //#define PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_9_PIXELS
  2767. //#define PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_12_PIXELS
  2768. // Here's a helpful chart:
  2769. // MaxTriadSize BlurSize MinTriadCountsByResolution
  2770. // 3.0 9.0 480/640/960/1920 triads at 1080p/1440p/2160p/4320p, 4:3 aspect
  2771. // 6.0 17.0 240/320/480/960 triads at 1080p/1440p/2160p/4320p, 4:3 aspect
  2772. // 9.0 25.0 160/213/320/640 triads at 1080p/1440p/2160p/4320p, 4:3 aspect
  2773. // 12.0 31.0 120/160/240/480 triads at 1080p/1440p/2160p/4320p, 4:3 aspect
  2774. // 18.0 43.0 80/107/160/320 triads at 1080p/1440p/2160p/4320p, 4:3 aspect
  2775. /////////////////////////////// USER PARAMETERS //////////////////////////////
  2776. // Note: Many of these static parameters are overridden by runtime shader
  2777. // parameters when those are enabled. However, many others are static codepath
  2778. // options that were cleaner or more convert to code as static constants.
  2779. // GAMMA:
  2780. static const float crt_gamma_static = 2.5; // range [1, 5]
  2781. static const float lcd_gamma_static = 2.2; // range [1, 5]
  2782. // LEVELS MANAGEMENT:
  2783. // Control the final multiplicative image contrast:
  2784. static const float levels_contrast_static = 1.0; // range [0, 4)
  2785. // We auto-dim to avoid clipping between passes and restore brightness
  2786. // later. Control the dim factor here: Lower values clip less but crush
  2787. // blacks more (static only for now).
  2788. static const float levels_autodim_temp = 0.5; // range (0, 1] default is 0.5 but that was unnecessarily dark for me, so I set it to 1.0
  2789. // HALATION/DIFFUSION/BLOOM:
  2790. // Halation weight: How much energy should be lost to electrons bounding
  2791. // around under the CRT glass and exciting random phosphors?
  2792. static const float halation_weight_static = 0.0; // range [0, 1]
  2793. // Refractive diffusion weight: How much light should spread/diffuse from
  2794. // refracting through the CRT glass?
  2795. static const float diffusion_weight_static = 0.075; // range [0, 1]
  2796. // Underestimate brightness: Bright areas bloom more, but we can base the
  2797. // bloom brightpass on a lower brightness to sharpen phosphors, or a higher
  2798. // brightness to soften them. Low values clip, but >= 0.8 looks okay.
  2799. static const float bloom_underestimate_levels_static = 0.8; // range [0, 5]
  2800. // Blur all colors more than necessary for a softer phosphor bloom?
  2801. static const float bloom_excess_static = 0.0; // range [0, 1]
  2802. // The BLOOM_APPROX pass approximates a phosphor blur early on with a small
  2803. // blurred resize of the input (convergence offsets are applied as well).
  2804. // There are three filter options (static option only for now):
  2805. // 0.) Bilinear resize: A fast, close approximation to a 4x4 resize
  2806. // if min_allowed_viewport_triads and the BLOOM_APPROX resolution are sane
  2807. // and beam_max_sigma is low.
  2808. // 1.) 3x3 resize blur: Medium speed, soft/smeared from bilinear blurring,
  2809. // always uses a static sigma regardless of beam_max_sigma or
  2810. // mask_num_triads_desired.
  2811. // 2.) True 4x4 Gaussian resize: Slowest, technically correct.
  2812. // These options are more pronounced for the fast, unbloomed shader version.
  2813. #ifndef RADEON_FIX
  2814. static const float bloom_approx_filter_static = 2.0;
  2815. #else
  2816. static const float bloom_approx_filter_static = 1.0;
  2817. #endif
  2818. // ELECTRON BEAM SCANLINE DISTRIBUTION:
  2819. // How many scanlines should contribute light to each pixel? Using more
  2820. // scanlines is slower (especially for a generalized Gaussian) but less
  2821. // distorted with larger beam sigmas (especially for a pure Gaussian). The
  2822. // max_beam_sigma at which the closest unused weight is guaranteed <
  2823. // 1.0/255.0 (for a 3x antialiased pure Gaussian) is:
  2824. // 2 scanlines: max_beam_sigma = 0.2089; distortions begin ~0.34; 141.7 FPS pure, 131.9 FPS generalized
  2825. // 3 scanlines, max_beam_sigma = 0.3879; distortions begin ~0.52; 137.5 FPS pure; 123.8 FPS generalized
  2826. // 4 scanlines, max_beam_sigma = 0.5723; distortions begin ~0.70; 134.7 FPS pure; 117.2 FPS generalized
  2827. // 5 scanlines, max_beam_sigma = 0.7591; distortions begin ~0.89; 131.6 FPS pure; 112.1 FPS generalized
  2828. // 6 scanlines, max_beam_sigma = 0.9483; distortions begin ~1.08; 127.9 FPS pure; 105.6 FPS generalized
  2829. static const float beam_num_scanlines = 3.0; // range [2, 6]
  2830. // A generalized Gaussian beam varies shape with color too, now just width.
  2831. // It's slower but more flexible (static option only for now).
  2832. static const bool beam_generalized_gaussian = true;
  2833. // What kind of scanline antialiasing do you want?
  2834. // 0: Sample weights at 1x; 1: Sample weights at 3x; 2: Compute an integral
  2835. // Integrals are slow (especially for generalized Gaussians) and rarely any
  2836. // better than 3x antialiasing (static option only for now).
  2837. static const float beam_antialias_level = 1.0; // range [0, 2]
  2838. // Min/max standard deviations for scanline beams: Higher values widen and
  2839. // soften scanlines. Depending on other options, low min sigmas can alias.
  2840. static const float beam_min_sigma_static = 0.02; // range (0, 1]
  2841. static const float beam_max_sigma_static = 0.3; // range (0, 1]
  2842. // Beam width varies as a function of color: A power function (0) is more
  2843. // configurable, but a spherical function (1) gives the widest beam
  2844. // variability without aliasing (static option only for now).
  2845. static const float beam_spot_shape_function = 0.0;
  2846. // Spot shape power: Powers <= 1 give smoother spot shapes but lower
  2847. // sharpness. Powers >= 1.0 are awful unless mix/max sigmas are close.
  2848. static const float beam_spot_power_static = 1.0/3.0; // range (0, 16]
  2849. // Generalized Gaussian max shape parameters: Higher values give flatter
  2850. // scanline plateaus and steeper dropoffs, simultaneously widening and
  2851. // sharpening scanlines at the cost of aliasing. 2.0 is pure Gaussian, and
  2852. // values > ~40.0 cause artifacts with integrals.
  2853. static const float beam_min_shape_static = 2.0; // range [2, 32]
  2854. static const float beam_max_shape_static = 4.0; // range [2, 32]
  2855. // Generalized Gaussian shape power: Affects how quickly the distribution
  2856. // changes shape from Gaussian to steep/plateaued as color increases from 0
  2857. // to 1.0. Higher powers appear softer for most colors, and lower powers
  2858. // appear sharper for most colors.
  2859. static const float beam_shape_power_static = 1.0/4.0; // range (0, 16]
  2860. // What filter should be used to sample scanlines horizontally?
  2861. // 0: Quilez (fast), 1: Gaussian (configurable), 2: Lanczos2 (sharp)
  2862. static const float beam_horiz_filter_static = 0.0;
  2863. // Standard deviation for horizontal Gaussian resampling:
  2864. static const float beam_horiz_sigma_static = 0.35; // range (0, 2/3]
  2865. // Do horizontal scanline sampling in linear RGB (correct light mixing),
  2866. // gamma-encoded RGB (darker, hard spot shape, may better match bandwidth-
  2867. // limiting circuitry in some CRT's), or a weighted avg.?
  2868. static const float beam_horiz_linear_rgb_weight_static = 1.0; // range [0, 1]
  2869. // Simulate scanline misconvergence? This needs 3x horizontal texture
  2870. // samples and 3x texture samples of BLOOM_APPROX and HALATION_BLUR in
  2871. // later passes (static option only for now).
  2872. static const bool beam_misconvergence = true;
  2873. // Convergence offsets in x/y directions for R/G/B scanline beams in units
  2874. // of scanlines. Positive offsets go right/down; ranges [-2, 2]
  2875. static const float2 convergence_offsets_r_static = float2(0.1, 0.2);
  2876. static const float2 convergence_offsets_g_static = float2(0.3, 0.4);
  2877. static const float2 convergence_offsets_b_static = float2(0.5, 0.6);
  2878. // Detect interlacing (static option only for now)?
  2879. static const bool interlace_detect = true;
  2880. // Assume 1080-line sources are interlaced?
  2881. static const bool interlace_1080i_static = false;
  2882. // For interlaced sources, assume TFF (top-field first) or BFF order?
  2883. // (Whether this matters depends on the nature of the interlaced input.)
  2884. static const bool interlace_bff_static = false;
  2885. // ANTIALIASING:
  2886. // What AA level do you want for curvature/overscan/subpixels? Options:
  2887. // 0x (none), 1x (sample subpixels), 4x, 5x, 6x, 7x, 8x, 12x, 16x, 20x, 24x
  2888. // (Static option only for now)
  2889. static const float aa_level = 12.0; // range [0, 24]
  2890. // What antialiasing filter do you want (static option only)? Options:
  2891. // 0: Box (separable), 1: Box (cylindrical),
  2892. // 2: Tent (separable), 3: Tent (cylindrical),
  2893. // 4: Gaussian (separable), 5: Gaussian (cylindrical),
  2894. // 6: Cubic* (separable), 7: Cubic* (cylindrical, poor)
  2895. // 8: Lanczos Sinc (separable), 9: Lanczos Jinc (cylindrical, poor)
  2896. // * = Especially slow with RUNTIME_ANTIALIAS_WEIGHTS
  2897. static const float aa_filter = 6.0; // range [0, 9]
  2898. // Flip the sample grid on odd/even frames (static option only for now)?
  2899. static const bool aa_temporal = false;
  2900. // Use RGB subpixel offsets for antialiasing? The pixel is at green, and
  2901. // the blue offset is the negative r offset; range [0, 0.5]
  2902. static const float2 aa_subpixel_r_offset_static = float2(-1.0/3.0, 0.0);//float2(0.0);
  2903. // Cubics: See http://www.imagemagick.org/Usage/filter/#mitchell
  2904. // 1.) "Keys cubics" with B = 1 - 2C are considered the highest quality.
  2905. // 2.) C = 0.5 (default) is Catmull-Rom; higher C's apply sharpening.
  2906. // 3.) C = 1.0/3.0 is the Mitchell-Netravali filter.
  2907. // 4.) C = 0.0 is a soft spline filter.
  2908. static const float aa_cubic_c_static = 0.5; // range [0, 4]
  2909. // Standard deviation for Gaussian antialiasing: Try 0.5/aa_pixel_diameter.
  2910. static const float aa_gauss_sigma_static = 0.5; // range [0.0625, 1.0]
  2911. // PHOSPHOR MASK:
  2912. // Mask type: 0 = aperture grille, 1 = slot mask, 2 = EDP shadow mask
  2913. static const float mask_type_static = 1.0; // range [0, 2]
  2914. // We can sample the mask three ways. Pick 2/3 from: Pretty/Fast/Flexible.
  2915. // 0.) Sinc-resize to the desired dot pitch manually (pretty/slow/flexible).
  2916. // This requires PHOSPHOR_MASK_MANUALLY_RESIZE to be #defined.
  2917. // 1.) Hardware-resize to the desired dot pitch (ugly/fast/flexible). This
  2918. // is halfway decent with LUT mipmapping but atrocious without it.
  2919. // 2.) Tile it without resizing at a 1:1 texel:pixel ratio for flat coords
  2920. // (pretty/fast/inflexible). Each input LUT has a fixed dot pitch.
  2921. // This mode reuses the same masks, so triads will be enormous unless
  2922. // you change the mask LUT filenames in your .cgp file.
  2923. static const float mask_sample_mode_static = 0.0; // range [0, 2]
  2924. // Prefer setting the triad size (0.0) or number on the screen (1.0)?
  2925. // If RUNTIME_PHOSPHOR_BLOOM_SIGMA isn't #defined, the specified triad size
  2926. // will always be used to calculate the full bloom sigma statically.
  2927. static const float mask_specify_num_triads_static = 0.0; // range [0, 1]
  2928. // Specify the phosphor triad size, in pixels. Each tile (usually with 8
  2929. // triads) will be rounded to the nearest integer tile size and clamped to
  2930. // obey minimum size constraints (imposed to reduce downsize taps) and
  2931. // maximum size constraints (imposed to have a sane MASK_RESIZE FBO size).
  2932. // To increase the size limit, double the viewport-relative scales for the
  2933. // two MASK_RESIZE passes in crt-royale.cgp and user-cgp-contants.h.
  2934. // range [1, mask_texture_small_size/mask_triads_per_tile]
  2935. static const float mask_triad_size_desired_static = 24.0 / 8.0;
  2936. // If mask_specify_num_triads is 1.0/true, we'll go by this instead (the
  2937. // final size will be rounded and constrained as above); default 480.0
  2938. static const float mask_num_triads_desired_static = 480.0;
  2939. // How many lobes should the sinc/Lanczos resizer use? More lobes require
  2940. // more samples and avoid moire a bit better, but some is unavoidable
  2941. // depending on the destination size (static option for now).
  2942. static const float mask_sinc_lobes = 3.0; // range [2, 4]
  2943. // The mask is resized using a variable number of taps in each dimension,
  2944. // but some Cg profiles always fetch a constant number of taps no matter
  2945. // what (no dynamic branching). We can limit the maximum number of taps if
  2946. // we statically limit the minimum phosphor triad size. Larger values are
  2947. // faster, but the limit IS enforced (static option only, forever);
  2948. // range [1, mask_texture_small_size/mask_triads_per_tile]
  2949. // TODO: Make this 1.0 and compensate with smarter sampling!
  2950. static const float mask_min_allowed_triad_size = 2.0;
  2951. // GEOMETRY:
  2952. // Geometry mode:
  2953. // 0: Off (default), 1: Spherical mapping (like cgwg's),
  2954. // 2: Alt. spherical mapping (more bulbous), 3: Cylindrical/Trinitron
  2955. static const float geom_mode_static = 0.0; // range [0, 3]
  2956. // Radius of curvature: Measured in units of your viewport's diagonal size.
  2957. static const float geom_radius_static = 2.0; // range [1/(2*pi), 1024]
  2958. // View dist is the distance from the player to their physical screen, in
  2959. // units of the viewport's diagonal size. It controls the field of view.
  2960. static const float geom_view_dist_static = 2.0; // range [0.5, 1024]
  2961. // Tilt angle in radians (clockwise around up and right vectors):
  2962. static const float2 geom_tilt_angle_static = float2(0.0, 0.0); // range [-pi, pi]
  2963. // Aspect ratio: When the true viewport size is unknown, this value is used
  2964. // to help convert between the phosphor triad size and count, along with
  2965. // the mask_resize_viewport_scale constant from user-cgp-constants.h. Set
  2966. // this equal to Retroarch's display aspect ratio (DAR) for best results;
  2967. // range [1, geom_max_aspect_ratio from user-cgp-constants.h];
  2968. // default (256/224)*(54/47) = 1.313069909 (see below)
  2969. static const float geom_aspect_ratio_static = 1.313069909;
  2970. // Before getting into overscan, here's some general aspect ratio info:
  2971. // - DAR = display aspect ratio = SAR * PAR; as in your Retroarch setting
  2972. // - SAR = storage aspect ratio = DAR / PAR; square pixel emulator frame AR
  2973. // - PAR = pixel aspect ratio = DAR / SAR; holds regardless of cropping
  2974. // Geometry processing has to "undo" the screen-space 2D DAR to calculate
  2975. // 3D view vectors, then reapplies the aspect ratio to the simulated CRT in
  2976. // uv-space. To ensure the source SAR is intended for a ~4:3 DAR, either:
  2977. // a.) Enable Retroarch's "Crop Overscan"
  2978. // b.) Readd horizontal padding: Set overscan to e.g. N*(1.0, 240.0/224.0)
  2979. // Real consoles use horizontal black padding in the signal, but emulators
  2980. // often crop this without cropping the vertical padding; a 256x224 [S]NES
  2981. // frame (8:7 SAR) is intended for a ~4:3 DAR, but a 256x240 frame is not.
  2982. // The correct [S]NES PAR is 54:47, found by blargg and NewRisingSun:
  2983. // http://board.zsnes.com/phpBB3/viewtopic.php?f=22&t=11928&start=50
  2984. // http://forums.nesdev.com/viewtopic.php?p=24815#p24815
  2985. // For flat output, it's okay to set DAR = [existing] SAR * [correct] PAR
  2986. // without doing a. or b., but horizontal image borders will be tighter
  2987. // than vertical ones, messing up curvature and overscan. Fixing the
  2988. // padding first corrects this.
  2989. // Overscan: Amount to "zoom in" before cropping. You can zoom uniformly
  2990. // or adjust x/y independently to e.g. readd horizontal padding, as noted
  2991. // above: Values < 1.0 zoom out; range (0, inf)
  2992. static const float2 geom_overscan_static = float2(1.0, 1.0);// * 1.005 * (1.0, 240/224.0)
  2993. // Compute a proper pixel-space to texture-space matrix even without ddx()/
  2994. // ddy()? This is ~8.5% slower but improves antialiasing/subpixel filtering
  2995. // with strong curvature (static option only for now).
  2996. static const bool geom_force_correct_tangent_matrix = true;
  2997. // BORDERS:
  2998. // Rounded border size in texture uv coords:
  2999. static const float border_size_static = 0.015; // range [0, 0.5]
  3000. // Border darkness: Moderate values darken the border smoothly, and high
  3001. // values make the image very dark just inside the border:
  3002. static const float border_darkness_static = 2.0; // range [0, inf)
  3003. // Border compression: High numbers compress border transitions, narrowing
  3004. // the dark border area.
  3005. static const float border_compress_static = 2.5; // range [1, inf)
  3006. #endif // USER_SETTINGS_H
  3007. ///////////////////////////// END USER-SETTINGS ////////////////////////////
  3008. //#include "user-cgp-constants.h"
  3009. ///////////////////////// BEGIN USER-CGP-CONSTANTS /////////////////////////
  3010. #ifndef USER_CGP_CONSTANTS_H
  3011. #define USER_CGP_CONSTANTS_H
  3012. // IMPORTANT:
  3013. // These constants MUST be set appropriately for the settings in crt-royale.cgp
  3014. // (or whatever related .cgp file you're using). If they aren't, you're likely
  3015. // to get artifacts, the wrong phosphor mask size, etc. I wish these could be
  3016. // set directly in the .cgp file to make things easier, but...they can't.
  3017. // PASS SCALES AND RELATED CONSTANTS:
  3018. // Copy the absolute scale_x for BLOOM_APPROX. There are two major versions of
  3019. // this shader: One does a viewport-scale bloom, and the other skips it. The
  3020. // latter benefits from a higher bloom_approx_scale_x, so save both separately:
  3021. static const float bloom_approx_size_x = 320.0;
  3022. static const float bloom_approx_size_x_for_fake = 400.0;
  3023. // Copy the viewport-relative scales of the phosphor mask resize passes
  3024. // (MASK_RESIZE and the pass immediately preceding it):
  3025. static const float2 mask_resize_viewport_scale = float2(0.0625, 0.0625);
  3026. // Copy the geom_max_aspect_ratio used to calculate the MASK_RESIZE scales, etc.:
  3027. static const float geom_max_aspect_ratio = 4.0/3.0;
  3028. // PHOSPHOR MASK TEXTURE CONSTANTS:
  3029. // Set the following constants to reflect the properties of the phosphor mask
  3030. // texture named in crt-royale.cgp. The shader optionally resizes a mask tile
  3031. // based on user settings, then repeats a single tile until filling the screen.
  3032. // The shader must know the input texture size (default 64x64), and to manually
  3033. // resize, it must also know the horizontal triads per tile (default 8).
  3034. static const float2 mask_texture_small_size = float2(64.0, 64.0);
  3035. static const float2 mask_texture_large_size = float2(512.0, 512.0);
  3036. static const float mask_triads_per_tile = 8.0;
  3037. // We need the average brightness of the phosphor mask to compensate for the
  3038. // dimming it causes. The following four values are roughly correct for the
  3039. // masks included with the shader. Update the value for any LUT texture you
  3040. // change. [Un]comment "#define PHOSPHOR_MASK_GRILLE14" depending on whether
  3041. // the loaded aperture grille uses 14-pixel or 15-pixel stripes (default 15).
  3042. //#define PHOSPHOR_MASK_GRILLE14
  3043. static const float mask_grille14_avg_color = 50.6666666/255.0;
  3044. // TileableLinearApertureGrille14Wide7d33Spacing*.png
  3045. // TileableLinearApertureGrille14Wide10And6Spacing*.png
  3046. static const float mask_grille15_avg_color = 53.0/255.0;
  3047. // TileableLinearApertureGrille15Wide6d33Spacing*.png
  3048. // TileableLinearApertureGrille15Wide8And5d5Spacing*.png
  3049. static const float mask_slot_avg_color = 46.0/255.0;
  3050. // TileableLinearSlotMask15Wide9And4d5Horizontal8VerticalSpacing*.png
  3051. // TileableLinearSlotMaskTall15Wide9And4d5Horizontal9d14VerticalSpacing*.png
  3052. static const float mask_shadow_avg_color = 41.0/255.0;
  3053. // TileableLinearShadowMask*.png
  3054. // TileableLinearShadowMaskEDP*.png
  3055. #ifdef PHOSPHOR_MASK_GRILLE14
  3056. static const float mask_grille_avg_color = mask_grille14_avg_color;
  3057. #else
  3058. static const float mask_grille_avg_color = mask_grille15_avg_color;
  3059. #endif
  3060. #endif // USER_CGP_CONSTANTS_H
  3061. ////////////////////////// END USER-CGP-CONSTANTS //////////////////////////
  3062. //////////////////////////////// END INCLUDES ////////////////////////////////
  3063. /////////////////////////////// FIXED SETTINGS ///////////////////////////////
  3064. // Avoid dividing by zero; using a macro overloads for float, float2, etc.:
  3065. #define FIX_ZERO(c) (max(abs(c), 0.0000152587890625)) // 2^-16
  3066. // Ensure the first pass decodes CRT gamma and the last encodes LCD gamma.
  3067. #ifndef SIMULATE_CRT_ON_LCD
  3068. #define SIMULATE_CRT_ON_LCD
  3069. #endif
  3070. // Manually tiling a manually resized texture creates texture coord derivative
  3071. // discontinuities and confuses anisotropic filtering, causing discolored tile
  3072. // seams in the phosphor mask. Workarounds:
  3073. // a.) Using tex2Dlod disables anisotropic filtering for tiled masks. It's
  3074. // downgraded to tex2Dbias without DRIVERS_ALLOW_TEX2DLOD #defined and
  3075. // disabled without DRIVERS_ALLOW_TEX2DBIAS #defined either.
  3076. // b.) "Tile flat twice" requires drawing two full tiles without border padding
  3077. // to the resized mask FBO, and it's incompatible with same-pass curvature.
  3078. // (Same-pass curvature isn't used but could be in the future...maybe.)
  3079. // c.) "Fix discontinuities" requires derivatives and drawing one tile with
  3080. // border padding to the resized mask FBO, but it works with same-pass
  3081. // curvature. It's disabled without DRIVERS_ALLOW_DERIVATIVES #defined.
  3082. // Precedence: a, then, b, then c (if multiple strategies are #defined).
  3083. #define ANISOTROPIC_TILING_COMPAT_TEX2DLOD // 129.7 FPS, 4x, flat; 101.8 at fullscreen
  3084. #define ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE // 128.1 FPS, 4x, flat; 101.5 at fullscreen
  3085. #define ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES // 124.4 FPS, 4x, flat; 97.4 at fullscreen
  3086. // Also, manually resampling the phosphor mask is slightly blurrier with
  3087. // anisotropic filtering. (Resampling with mipmapping is even worse: It
  3088. // creates artifacts, but only with the fully bloomed shader.) The difference
  3089. // is subtle with small triads, but you can fix it for a small cost.
  3090. //#define ANISOTROPIC_RESAMPLING_COMPAT_TEX2DLOD
  3091. ////////////////////////////// DERIVED SETTINGS //////////////////////////////
  3092. // Intel HD 4000 GPU's can't handle manual mask resizing (for now), setting the
  3093. // geometry mode at runtime, or a 4x4 true Gaussian resize. Disable
  3094. // incompatible settings ASAP. (INTEGRATED_GRAPHICS_COMPATIBILITY_MODE may be
  3095. // #defined by either user-settings.h or a wrapper .cg that #includes the
  3096. // current .cg pass.)
  3097. #ifdef INTEGRATED_GRAPHICS_COMPATIBILITY_MODE
  3098. #ifdef PHOSPHOR_MASK_MANUALLY_RESIZE
  3099. #undef PHOSPHOR_MASK_MANUALLY_RESIZE
  3100. #endif
  3101. #ifdef RUNTIME_GEOMETRY_MODE
  3102. #undef RUNTIME_GEOMETRY_MODE
  3103. #endif
  3104. // Mode 2 (4x4 Gaussian resize) won't work, and mode 1 (3x3 blur) is
  3105. // inferior in most cases, so replace 2.0 with 0.0:
  3106. static const float bloom_approx_filter =
  3107. bloom_approx_filter_static > 1.5 ? 0.0 : bloom_approx_filter_static;
  3108. #else
  3109. static const float bloom_approx_filter = bloom_approx_filter_static;
  3110. #endif
  3111. // Disable slow runtime paths if static parameters are used. Most of these
  3112. // won't be a problem anyway once the params are disabled, but some will.
  3113. #ifndef RUNTIME_SHADER_PARAMS_ENABLE
  3114. #ifdef RUNTIME_PHOSPHOR_BLOOM_SIGMA
  3115. #undef RUNTIME_PHOSPHOR_BLOOM_SIGMA
  3116. #endif
  3117. #ifdef RUNTIME_ANTIALIAS_WEIGHTS
  3118. #undef RUNTIME_ANTIALIAS_WEIGHTS
  3119. #endif
  3120. #ifdef RUNTIME_ANTIALIAS_SUBPIXEL_OFFSETS
  3121. #undef RUNTIME_ANTIALIAS_SUBPIXEL_OFFSETS
  3122. #endif
  3123. #ifdef RUNTIME_SCANLINES_HORIZ_FILTER_COLORSPACE
  3124. #undef RUNTIME_SCANLINES_HORIZ_FILTER_COLORSPACE
  3125. #endif
  3126. #ifdef RUNTIME_GEOMETRY_TILT
  3127. #undef RUNTIME_GEOMETRY_TILT
  3128. #endif
  3129. #ifdef RUNTIME_GEOMETRY_MODE
  3130. #undef RUNTIME_GEOMETRY_MODE
  3131. #endif
  3132. #ifdef FORCE_RUNTIME_PHOSPHOR_MASK_MODE_TYPE_SELECT
  3133. #undef FORCE_RUNTIME_PHOSPHOR_MASK_MODE_TYPE_SELECT
  3134. #endif
  3135. #endif
  3136. // Make tex2Dbias a backup for tex2Dlod for wider compatibility.
  3137. #ifdef ANISOTROPIC_TILING_COMPAT_TEX2DLOD
  3138. #define ANISOTROPIC_TILING_COMPAT_TEX2DBIAS
  3139. #endif
  3140. #ifdef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DLOD
  3141. #define ANISOTROPIC_RESAMPLING_COMPAT_TEX2DBIAS
  3142. #endif
  3143. // Rule out unavailable anisotropic compatibility strategies:
  3144. #ifndef DRIVERS_ALLOW_DERIVATIVES
  3145. #ifdef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
  3146. #undef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
  3147. #endif
  3148. #endif
  3149. #ifndef DRIVERS_ALLOW_TEX2DLOD
  3150. #ifdef ANISOTROPIC_TILING_COMPAT_TEX2DLOD
  3151. #undef ANISOTROPIC_TILING_COMPAT_TEX2DLOD
  3152. #endif
  3153. #ifdef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DLOD
  3154. #undef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DLOD
  3155. #endif
  3156. #ifdef ANTIALIAS_DISABLE_ANISOTROPIC
  3157. #undef ANTIALIAS_DISABLE_ANISOTROPIC
  3158. #endif
  3159. #endif
  3160. #ifndef DRIVERS_ALLOW_TEX2DBIAS
  3161. #ifdef ANISOTROPIC_TILING_COMPAT_TEX2DBIAS
  3162. #undef ANISOTROPIC_TILING_COMPAT_TEX2DBIAS
  3163. #endif
  3164. #ifdef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DBIAS
  3165. #undef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DBIAS
  3166. #endif
  3167. #endif
  3168. // Prioritize anisotropic tiling compatibility strategies by performance and
  3169. // disable unused strategies. This concentrates all the nesting in one place.
  3170. #ifdef ANISOTROPIC_TILING_COMPAT_TEX2DLOD
  3171. #ifdef ANISOTROPIC_TILING_COMPAT_TEX2DBIAS
  3172. #undef ANISOTROPIC_TILING_COMPAT_TEX2DBIAS
  3173. #endif
  3174. #ifdef ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE
  3175. #undef ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE
  3176. #endif
  3177. #ifdef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
  3178. #undef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
  3179. #endif
  3180. #else
  3181. #ifdef ANISOTROPIC_TILING_COMPAT_TEX2DBIAS
  3182. #ifdef ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE
  3183. #undef ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE
  3184. #endif
  3185. #ifdef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
  3186. #undef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
  3187. #endif
  3188. #else
  3189. // ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE is only compatible with
  3190. // flat texture coords in the same pass, but that's all we use.
  3191. #ifdef ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE
  3192. #ifdef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
  3193. #undef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
  3194. #endif
  3195. #endif
  3196. #endif
  3197. #endif
  3198. // The tex2Dlod and tex2Dbias strategies share a lot in common, and we can
  3199. // reduce some #ifdef nesting in the next section by essentially OR'ing them:
  3200. #ifdef ANISOTROPIC_TILING_COMPAT_TEX2DLOD
  3201. #define ANISOTROPIC_TILING_COMPAT_TEX2DLOD_FAMILY
  3202. #endif
  3203. #ifdef ANISOTROPIC_TILING_COMPAT_TEX2DBIAS
  3204. #define ANISOTROPIC_TILING_COMPAT_TEX2DLOD_FAMILY
  3205. #endif
  3206. // Prioritize anisotropic resampling compatibility strategies the same way:
  3207. #ifdef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DLOD
  3208. #ifdef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DBIAS
  3209. #undef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DBIAS
  3210. #endif
  3211. #endif
  3212. /////////////////////// DERIVED PHOSPHOR MASK CONSTANTS //////////////////////
  3213. // If we can use the large mipmapped LUT without mipmapping artifacts, we
  3214. // should: It gives us more options for using fewer samples.
  3215. #ifdef DRIVERS_ALLOW_TEX2DLOD
  3216. #ifdef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DLOD
  3217. // TODO: Take advantage of this!
  3218. #define PHOSPHOR_MASK_RESIZE_MIPMAPPED_LUT
  3219. static const float2 mask_resize_src_lut_size = mask_texture_large_size;
  3220. #else
  3221. static const float2 mask_resize_src_lut_size = mask_texture_small_size;
  3222. #endif
  3223. #else
  3224. static const float2 mask_resize_src_lut_size = mask_texture_small_size;
  3225. #endif
  3226. // tex2D's sampler2D parameter MUST be a uniform global, a uniform input to
  3227. // main_fragment, or a static alias of one of the above. This makes it hard
  3228. // to select the phosphor mask at runtime: We can't even assign to a uniform
  3229. // global in the vertex shader or select a sampler2D in the vertex shader and
  3230. // pass it to the fragment shader (even with explicit TEXUNIT# bindings),
  3231. // because it just gives us the input texture or a black screen. However, we
  3232. // can get around these limitations by calling tex2D three times with different
  3233. // uniform samplers (or resizing the phosphor mask three times altogether).
  3234. // With dynamic branches, we can process only one of these branches on top of
  3235. // quickly discarding fragments we don't need (cgc seems able to overcome
  3236. // limigations around dependent texture fetches inside of branches). Without
  3237. // dynamic branches, we have to process every branch for every fragment...which
  3238. // is slower. Runtime sampling mode selection is slower without dynamic
  3239. // branches as well. Let the user's static #defines decide if it's worth it.
  3240. #ifdef DRIVERS_ALLOW_DYNAMIC_BRANCHES
  3241. #define RUNTIME_PHOSPHOR_MASK_MODE_TYPE_SELECT
  3242. #else
  3243. #ifdef FORCE_RUNTIME_PHOSPHOR_MASK_MODE_TYPE_SELECT
  3244. #define RUNTIME_PHOSPHOR_MASK_MODE_TYPE_SELECT
  3245. #endif
  3246. #endif
  3247. // We need to render some minimum number of tiles in the resize passes.
  3248. // We need at least 1.0 just to repeat a single tile, and we need extra
  3249. // padding beyond that for anisotropic filtering, discontinuitity fixing,
  3250. // antialiasing, same-pass curvature (not currently used), etc. First
  3251. // determine how many border texels and tiles we need, based on how the result
  3252. // will be sampled:
  3253. #ifdef GEOMETRY_EARLY
  3254. static const float max_subpixel_offset = aa_subpixel_r_offset_static.x;
  3255. // Most antialiasing filters have a base radius of 4.0 pixels:
  3256. static const float max_aa_base_pixel_border = 4.0 +
  3257. max_subpixel_offset;
  3258. #else
  3259. static const float max_aa_base_pixel_border = 0.0;
  3260. #endif
  3261. // Anisotropic filtering adds about 0.5 to the pixel border:
  3262. #ifndef ANISOTROPIC_TILING_COMPAT_TEX2DLOD_FAMILY
  3263. static const float max_aniso_pixel_border = max_aa_base_pixel_border + 0.5;
  3264. #else
  3265. static const float max_aniso_pixel_border = max_aa_base_pixel_border;
  3266. #endif
  3267. // Fixing discontinuities adds 1.0 more to the pixel border:
  3268. #ifdef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
  3269. static const float max_tiled_pixel_border = max_aniso_pixel_border + 1.0;
  3270. #else
  3271. static const float max_tiled_pixel_border = max_aniso_pixel_border;
  3272. #endif
  3273. // Convert the pixel border to an integer texel border. Assume same-pass
  3274. // curvature about triples the texel frequency:
  3275. #ifdef GEOMETRY_EARLY
  3276. static const float max_mask_texel_border =
  3277. ceil(max_tiled_pixel_border * 3.0);
  3278. #else
  3279. static const float max_mask_texel_border = ceil(max_tiled_pixel_border);
  3280. #endif
  3281. // Convert the texel border to a tile border using worst-case assumptions:
  3282. static const float max_mask_tile_border = max_mask_texel_border/
  3283. (mask_min_allowed_triad_size * mask_triads_per_tile);
  3284. // Finally, set the number of resized tiles to render to MASK_RESIZE, and set
  3285. // the starting texel (inside borders) for sampling it.
  3286. #ifndef GEOMETRY_EARLY
  3287. #ifdef ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE
  3288. // Special case: Render two tiles without borders. Anisotropic
  3289. // filtering doesn't seem to be a problem here.
  3290. static const float mask_resize_num_tiles = 1.0 + 1.0;
  3291. static const float mask_start_texels = 0.0;
  3292. #else
  3293. static const float mask_resize_num_tiles = 1.0 +
  3294. 2.0 * max_mask_tile_border;
  3295. static const float mask_start_texels = max_mask_texel_border;
  3296. #endif
  3297. #else
  3298. static const float mask_resize_num_tiles = 1.0 + 2.0*max_mask_tile_border;
  3299. static const float mask_start_texels = max_mask_texel_border;
  3300. #endif
  3301. // We have to fit mask_resize_num_tiles into an FBO with a viewport scale of
  3302. // mask_resize_viewport_scale. This limits the maximum final triad size.
  3303. // Estimate the minimum number of triads we can split the screen into in each
  3304. // dimension (we'll be as correct as mask_resize_viewport_scale is):
  3305. static const float mask_resize_num_triads =
  3306. mask_resize_num_tiles * mask_triads_per_tile;
  3307. static const float2 min_allowed_viewport_triads =
  3308. float2(mask_resize_num_triads) / mask_resize_viewport_scale;
  3309. //////////////////////// COMMON MATHEMATICAL CONSTANTS ///////////////////////
  3310. static const float pi = 3.141592653589;
  3311. // We often want to find the location of the previous texel, e.g.:
  3312. // const float2 curr_texel = uv * texture_size;
  3313. // const float2 prev_texel = floor(curr_texel - float2(0.5)) + float2(0.5);
  3314. // const float2 prev_texel_uv = prev_texel / texture_size;
  3315. // However, many GPU drivers round incorrectly around exact texel locations.
  3316. // We need to subtract a little less than 0.5 before flooring, and some GPU's
  3317. // require this value to be farther from 0.5 than others; define it here.
  3318. // const float2 prev_texel =
  3319. // floor(curr_texel - float2(under_half)) + float2(0.5);
  3320. static const float under_half = 0.4995;
  3321. #endif // DERIVED_SETTINGS_AND_CONSTANTS_H
  3322. ///////////////////////////// END DERIVED-SETTINGS-AND-CONSTANTS ////////////////////////////
  3323. //#include "../../../../include/special-functions.h"
  3324. /////////////////////////// BEGIN SPECIAL-FUNCTIONS //////////////////////////
  3325. #ifndef SPECIAL_FUNCTIONS_H
  3326. #define SPECIAL_FUNCTIONS_H
  3327. ///////////////////////////////// MIT LICENSE ////////////////////////////////
  3328. // Copyright (C) 2014 TroggleMonkey
  3329. //
  3330. // Permission is hereby granted, free of charge, to any person obtaining a copy
  3331. // of this software and associated documentation files (the "Software"), to
  3332. // deal in the Software without restriction, including without limitation the
  3333. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  3334. // sell copies of the Software, and to permit persons to whom the Software is
  3335. // furnished to do so, subject to the following conditions:
  3336. //
  3337. // The above copyright notice and this permission notice shall be included in
  3338. // all copies or substantial portions of the Software.
  3339. //
  3340. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  3341. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  3342. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  3343. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  3344. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  3345. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  3346. // IN THE SOFTWARE.
  3347. ///////////////////////////////// DESCRIPTION ////////////////////////////////
  3348. // This file implements the following mathematical special functions:
  3349. // 1.) erf() = 2/sqrt(pi) * indefinite_integral(e**(-x**2))
  3350. // 2.) gamma(s), a real-numbered extension of the integer factorial function
  3351. // It also implements normalized_ligamma(s, z), a normalized lower incomplete
  3352. // gamma function for s < 0.5 only. Both gamma() and normalized_ligamma() can
  3353. // be called with an _impl suffix to use an implementation version with a few
  3354. // extra precomputed parameters (which may be useful for the caller to reuse).
  3355. // See below for details.
  3356. //
  3357. // Design Rationale:
  3358. // Pretty much every line of code in this file is duplicated four times for
  3359. // different input types (float4/float3/float2/float). This is unfortunate,
  3360. // but Cg doesn't allow function templates. Macros would be far less verbose,
  3361. // but they would make the code harder to document and read. I don't expect
  3362. // these functions will require a whole lot of maintenance changes unless
  3363. // someone ever has need for more robust incomplete gamma functions, so code
  3364. // duplication seems to be the lesser evil in this case.
  3365. /////////////////////////// GAUSSIAN ERROR FUNCTION //////////////////////////
  3366. float4 erf6(float4 x)
  3367. {
  3368. // Requires: x is the standard parameter to erf().
  3369. // Returns: Return an Abramowitz/Stegun approximation of erf(), where:
  3370. // erf(x) = 2/sqrt(pi) * integral(e**(-x**2))
  3371. // This approximation has a max absolute error of 2.5*10**-5
  3372. // with solid numerical robustness and efficiency. See:
  3373. // https://en.wikipedia.org/wiki/Error_function#Approximation_with_elementary_functions
  3374. static const float4 one = float4(1.0);
  3375. const float4 sign_x = sign(x);
  3376. const float4 t = one/(one + 0.47047*abs(x));
  3377. const float4 result = one - t*(0.3480242 + t*(-0.0958798 + t*0.7478556))*
  3378. exp(-(x*x));
  3379. return result * sign_x;
  3380. }
  3381. float3 erf6(const float3 x)
  3382. {
  3383. // Float3 version:
  3384. static const float3 one = float3(1.0);
  3385. const float3 sign_x = sign(x);
  3386. const float3 t = one/(one + 0.47047*abs(x));
  3387. const float3 result = one - t*(0.3480242 + t*(-0.0958798 + t*0.7478556))*
  3388. exp(-(x*x));
  3389. return result * sign_x;
  3390. }
  3391. float2 erf6(const float2 x)
  3392. {
  3393. // Float2 version:
  3394. static const float2 one = float2(1.0);
  3395. const float2 sign_x = sign(x);
  3396. const float2 t = one/(one + 0.47047*abs(x));
  3397. const float2 result = one - t*(0.3480242 + t*(-0.0958798 + t*0.7478556))*
  3398. exp(-(x*x));
  3399. return result * sign_x;
  3400. }
  3401. float erf6(const float x)
  3402. {
  3403. // Float version:
  3404. const float sign_x = sign(x);
  3405. const float t = 1.0/(1.0 + 0.47047*abs(x));
  3406. const float result = 1.0 - t*(0.3480242 + t*(-0.0958798 + t*0.7478556))*
  3407. exp(-(x*x));
  3408. return result * sign_x;
  3409. }
  3410. float4 erft(const float4 x)
  3411. {
  3412. // Requires: x is the standard parameter to erf().
  3413. // Returns: Approximate erf() with the hyperbolic tangent. The error is
  3414. // visually noticeable, but it's blazing fast and perceptually
  3415. // close...at least on ATI hardware. See:
  3416. // http://www.maplesoft.com/applications/view.aspx?SID=5525&view=html
  3417. // Warning: Only use this if your hardware drivers correctly implement
  3418. // tanh(): My nVidia 8800GTS returns garbage output.
  3419. return tanh(1.202760580 * x);
  3420. }
  3421. float3 erft(const float3 x)
  3422. {
  3423. // Float3 version:
  3424. return tanh(1.202760580 * x);
  3425. }
  3426. float2 erft(const float2 x)
  3427. {
  3428. // Float2 version:
  3429. return tanh(1.202760580 * x);
  3430. }
  3431. float erft(const float x)
  3432. {
  3433. // Float version:
  3434. return tanh(1.202760580 * x);
  3435. }
  3436. inline float4 erf(const float4 x)
  3437. {
  3438. // Requires: x is the standard parameter to erf().
  3439. // Returns: Some approximation of erf(x), depending on user settings.
  3440. #ifdef ERF_FAST_APPROXIMATION
  3441. return erft(x);
  3442. #else
  3443. return erf6(x);
  3444. #endif
  3445. }
  3446. inline float3 erf(const float3 x)
  3447. {
  3448. // Float3 version:
  3449. #ifdef ERF_FAST_APPROXIMATION
  3450. return erft(x);
  3451. #else
  3452. return erf6(x);
  3453. #endif
  3454. }
  3455. inline float2 erf(const float2 x)
  3456. {
  3457. // Float2 version:
  3458. #ifdef ERF_FAST_APPROXIMATION
  3459. return erft(x);
  3460. #else
  3461. return erf6(x);
  3462. #endif
  3463. }
  3464. inline float erf(const float x)
  3465. {
  3466. // Float version:
  3467. #ifdef ERF_FAST_APPROXIMATION
  3468. return erft(x);
  3469. #else
  3470. return erf6(x);
  3471. #endif
  3472. }
  3473. /////////////////////////// COMPLETE GAMMA FUNCTION //////////////////////////
  3474. float4 gamma_impl(const float4 s, const float4 s_inv)
  3475. {
  3476. // Requires: 1.) s is the standard parameter to the gamma function, and
  3477. // it should lie in the [0, 36] range.
  3478. // 2.) s_inv = 1.0/s. This implementation function requires
  3479. // the caller to precompute this value, giving users the
  3480. // opportunity to reuse it.
  3481. // Returns: Return approximate gamma function (real-numbered factorial)
  3482. // output using the Lanczos approximation with two coefficients
  3483. // calculated using Paul Godfrey's method here:
  3484. // http://my.fit.edu/~gabdo/gamma.txt
  3485. // An optimal g value for s in [0, 36] is ~1.12906830989, with
  3486. // a maximum relative error of 0.000463 for 2**16 equally
  3487. // evals. We could use three coeffs (0.0000346 error) without
  3488. // hurting latency, but this allows more parallelism with
  3489. // outside instructions.
  3490. static const float4 g = float4(1.12906830989);
  3491. static const float4 c0 = float4(0.8109119309638332633713423362694399653724431);
  3492. static const float4 c1 = float4(0.4808354605142681877121661197951496120000040);
  3493. static const float4 e = float4(2.71828182845904523536028747135266249775724709);
  3494. const float4 sph = s + float4(0.5);
  3495. const float4 lanczos_sum = c0 + c1/(s + float4(1.0));
  3496. const float4 base = (sph + g)/e; // or (s + g + float4(0.5))/e
  3497. // gamma(s + 1) = base**sph * lanczos_sum; divide by s for gamma(s).
  3498. // This has less error for small s's than (s -= 1.0) at the beginning.
  3499. return (pow(base, sph) * lanczos_sum) * s_inv;
  3500. }
  3501. float3 gamma_impl(const float3 s, const float3 s_inv)
  3502. {
  3503. // Float3 version:
  3504. static const float3 g = float3(1.12906830989);
  3505. static const float3 c0 = float3(0.8109119309638332633713423362694399653724431);
  3506. static const float3 c1 = float3(0.4808354605142681877121661197951496120000040);
  3507. static const float3 e = float3(2.71828182845904523536028747135266249775724709);
  3508. const float3 sph = s + float3(0.5);
  3509. const float3 lanczos_sum = c0 + c1/(s + float3(1.0));
  3510. const float3 base = (sph + g)/e;
  3511. return (pow(base, sph) * lanczos_sum) * s_inv;
  3512. }
  3513. float2 gamma_impl(const float2 s, const float2 s_inv)
  3514. {
  3515. // Float2 version:
  3516. static const float2 g = float2(1.12906830989);
  3517. static const float2 c0 = float2(0.8109119309638332633713423362694399653724431);
  3518. static const float2 c1 = float2(0.4808354605142681877121661197951496120000040);
  3519. static const float2 e = float2(2.71828182845904523536028747135266249775724709);
  3520. const float2 sph = s + float2(0.5);
  3521. const float2 lanczos_sum = c0 + c1/(s + float2(1.0));
  3522. const float2 base = (sph + g)/e;
  3523. return (pow(base, sph) * lanczos_sum) * s_inv;
  3524. }
  3525. float gamma_impl(const float s, const float s_inv)
  3526. {
  3527. // Float version:
  3528. static const float g = 1.12906830989;
  3529. static const float c0 = 0.8109119309638332633713423362694399653724431;
  3530. static const float c1 = 0.4808354605142681877121661197951496120000040;
  3531. static const float e = 2.71828182845904523536028747135266249775724709;
  3532. const float sph = s + 0.5;
  3533. const float lanczos_sum = c0 + c1/(s + 1.0);
  3534. const float base = (sph + g)/e;
  3535. return (pow(base, sph) * lanczos_sum) * s_inv;
  3536. }
  3537. float4 gamma(const float4 s)
  3538. {
  3539. // Requires: s is the standard parameter to the gamma function, and it
  3540. // should lie in the [0, 36] range.
  3541. // Returns: Return approximate gamma function output with a maximum
  3542. // relative error of 0.000463. See gamma_impl for details.
  3543. return gamma_impl(s, float4(1.0)/s);
  3544. }
  3545. float3 gamma(const float3 s)
  3546. {
  3547. // Float3 version:
  3548. return gamma_impl(s, float3(1.0)/s);
  3549. }
  3550. float2 gamma(const float2 s)
  3551. {
  3552. // Float2 version:
  3553. return gamma_impl(s, float2(1.0)/s);
  3554. }
  3555. float gamma(const float s)
  3556. {
  3557. // Float version:
  3558. return gamma_impl(s, 1.0/s);
  3559. }
  3560. //////////////// INCOMPLETE GAMMA FUNCTIONS (RESTRICTED INPUT) ///////////////
  3561. // Lower incomplete gamma function for small s and z (implementation):
  3562. float4 ligamma_small_z_impl(const float4 s, const float4 z, const float4 s_inv)
  3563. {
  3564. // Requires: 1.) s < ~0.5
  3565. // 2.) z <= ~0.775075
  3566. // 3.) s_inv = 1.0/s (precomputed for outside reuse)
  3567. // Returns: A series representation for the lower incomplete gamma
  3568. // function for small s and small z (4 terms).
  3569. // The actual "rolled up" summation looks like:
  3570. // last_sign = 1.0; last_pow = 1.0; last_factorial = 1.0;
  3571. // sum = last_sign * last_pow / ((s + k) * last_factorial)
  3572. // for(int i = 0; i < 4; ++i)
  3573. // {
  3574. // last_sign *= -1.0; last_pow *= z; last_factorial *= i;
  3575. // sum += last_sign * last_pow / ((s + k) * last_factorial);
  3576. // }
  3577. // Unrolled, constant-unfolded and arranged for madds and parallelism:
  3578. const float4 scale = pow(z, s);
  3579. float4 sum = s_inv; // Summation iteration 0 result
  3580. // Summation iterations 1, 2, and 3:
  3581. const float4 z_sq = z*z;
  3582. const float4 denom1 = s + float4(1.0);
  3583. const float4 denom2 = 2.0*s + float4(4.0);
  3584. const float4 denom3 = 6.0*s + float4(18.0);
  3585. //float4 denom4 = 24.0*s + float4(96.0);
  3586. sum -= z/denom1;
  3587. sum += z_sq/denom2;
  3588. sum -= z * z_sq/denom3;
  3589. //sum += z_sq * z_sq / denom4;
  3590. // Scale and return:
  3591. return scale * sum;
  3592. }
  3593. float3 ligamma_small_z_impl(const float3 s, const float3 z, const float3 s_inv)
  3594. {
  3595. // Float3 version:
  3596. const float3 scale = pow(z, s);
  3597. float3 sum = s_inv;
  3598. const float3 z_sq = z*z;
  3599. const float3 denom1 = s + float3(1.0);
  3600. const float3 denom2 = 2.0*s + float3(4.0);
  3601. const float3 denom3 = 6.0*s + float3(18.0);
  3602. sum -= z/denom1;
  3603. sum += z_sq/denom2;
  3604. sum -= z * z_sq/denom3;
  3605. return scale * sum;
  3606. }
  3607. float2 ligamma_small_z_impl(const float2 s, const float2 z, const float2 s_inv)
  3608. {
  3609. // Float2 version:
  3610. const float2 scale = pow(z, s);
  3611. float2 sum = s_inv;
  3612. const float2 z_sq = z*z;
  3613. const float2 denom1 = s + float2(1.0);
  3614. const float2 denom2 = 2.0*s + float2(4.0);
  3615. const float2 denom3 = 6.0*s + float2(18.0);
  3616. sum -= z/denom1;
  3617. sum += z_sq/denom2;
  3618. sum -= z * z_sq/denom3;
  3619. return scale * sum;
  3620. }
  3621. float ligamma_small_z_impl(const float s, const float z, const float s_inv)
  3622. {
  3623. // Float version:
  3624. const float scale = pow(z, s);
  3625. float sum = s_inv;
  3626. const float z_sq = z*z;
  3627. const float denom1 = s + 1.0;
  3628. const float denom2 = 2.0*s + 4.0;
  3629. const float denom3 = 6.0*s + 18.0;
  3630. sum -= z/denom1;
  3631. sum += z_sq/denom2;
  3632. sum -= z * z_sq/denom3;
  3633. return scale * sum;
  3634. }
  3635. // Upper incomplete gamma function for small s and large z (implementation):
  3636. float4 uigamma_large_z_impl(const float4 s, const float4 z)
  3637. {
  3638. // Requires: 1.) s < ~0.5
  3639. // 2.) z > ~0.775075
  3640. // Returns: Gauss's continued fraction representation for the upper
  3641. // incomplete gamma function (4 terms).
  3642. // The "rolled up" continued fraction looks like this. The denominator
  3643. // is truncated, and it's calculated "from the bottom up:"
  3644. // denom = float4('inf');
  3645. // float4 one = float4(1.0);
  3646. // for(int i = 4; i > 0; --i)
  3647. // {
  3648. // denom = ((i * 2.0) - one) + z - s + (i * (s - i))/denom;
  3649. // }
  3650. // Unrolled and constant-unfolded for madds and parallelism:
  3651. const float4 numerator = pow(z, s) * exp(-z);
  3652. float4 denom = float4(7.0) + z - s;
  3653. denom = float4(5.0) + z - s + (3.0*s - float4(9.0))/denom;
  3654. denom = float4(3.0) + z - s + (2.0*s - float4(4.0))/denom;
  3655. denom = float4(1.0) + z - s + (s - float4(1.0))/denom;
  3656. return numerator / denom;
  3657. }
  3658. float3 uigamma_large_z_impl(const float3 s, const float3 z)
  3659. {
  3660. // Float3 version:
  3661. const float3 numerator = pow(z, s) * exp(-z);
  3662. float3 denom = float3(7.0) + z - s;
  3663. denom = float3(5.0) + z - s + (3.0*s - float3(9.0))/denom;
  3664. denom = float3(3.0) + z - s + (2.0*s - float3(4.0))/denom;
  3665. denom = float3(1.0) + z - s + (s - float3(1.0))/denom;
  3666. return numerator / denom;
  3667. }
  3668. float2 uigamma_large_z_impl(const float2 s, const float2 z)
  3669. {
  3670. // Float2 version:
  3671. const float2 numerator = pow(z, s) * exp(-z);
  3672. float2 denom = float2(7.0) + z - s;
  3673. denom = float2(5.0) + z - s + (3.0*s - float2(9.0))/denom;
  3674. denom = float2(3.0) + z - s + (2.0*s - float2(4.0))/denom;
  3675. denom = float2(1.0) + z - s + (s - float2(1.0))/denom;
  3676. return numerator / denom;
  3677. }
  3678. float uigamma_large_z_impl(const float s, const float z)
  3679. {
  3680. // Float version:
  3681. const float numerator = pow(z, s) * exp(-z);
  3682. float denom = 7.0 + z - s;
  3683. denom = 5.0 + z - s + (3.0*s - 9.0)/denom;
  3684. denom = 3.0 + z - s + (2.0*s - 4.0)/denom;
  3685. denom = 1.0 + z - s + (s - 1.0)/denom;
  3686. return numerator / denom;
  3687. }
  3688. // Normalized lower incomplete gamma function for small s (implementation):
  3689. float4 normalized_ligamma_impl(const float4 s, const float4 z,
  3690. const float4 s_inv, const float4 gamma_s_inv)
  3691. {
  3692. // Requires: 1.) s < ~0.5
  3693. // 2.) s_inv = 1/s (precomputed for outside reuse)
  3694. // 3.) gamma_s_inv = 1/gamma(s) (precomputed for outside reuse)
  3695. // Returns: Approximate the normalized lower incomplete gamma function
  3696. // for s < 0.5. Since we only care about s < 0.5, we only need
  3697. // to evaluate two branches (not four) based on z. Each branch
  3698. // uses four terms, with a max relative error of ~0.00182. The
  3699. // branch threshold and specifics were adapted for fewer terms
  3700. // from Gil/Segura/Temme's paper here:
  3701. // http://oai.cwi.nl/oai/asset/20433/20433B.pdf
  3702. // Evaluate both branches: Real branches test slower even when available.
  3703. static const float4 thresh = float4(0.775075);
  3704. bool4 z_is_large;
  3705. z_is_large.x = z.x > thresh.x;
  3706. z_is_large.y = z.y > thresh.y;
  3707. z_is_large.z = z.z > thresh.z;
  3708. z_is_large.w = z.w > thresh.w;
  3709. const float4 large_z = float4(1.0) - uigamma_large_z_impl(s, z) * gamma_s_inv;
  3710. const float4 small_z = ligamma_small_z_impl(s, z, s_inv) * gamma_s_inv;
  3711. // Combine the results from both branches:
  3712. bool4 inverse_z_is_large = not(z_is_large);
  3713. return large_z * float4(z_is_large) + small_z * float4(inverse_z_is_large);
  3714. }
  3715. float3 normalized_ligamma_impl(const float3 s, const float3 z,
  3716. const float3 s_inv, const float3 gamma_s_inv)
  3717. {
  3718. // Float3 version:
  3719. static const float3 thresh = float3(0.775075);
  3720. bool3 z_is_large;
  3721. z_is_large.x = z.x > thresh.x;
  3722. z_is_large.y = z.y > thresh.y;
  3723. z_is_large.z = z.z > thresh.z;
  3724. const float3 large_z = float3(1.0) - uigamma_large_z_impl(s, z) * gamma_s_inv;
  3725. const float3 small_z = ligamma_small_z_impl(s, z, s_inv) * gamma_s_inv;
  3726. bool3 inverse_z_is_large = not(z_is_large);
  3727. return large_z * float3(z_is_large) + small_z * float3(inverse_z_is_large);
  3728. }
  3729. float2 normalized_ligamma_impl(const float2 s, const float2 z,
  3730. const float2 s_inv, const float2 gamma_s_inv)
  3731. {
  3732. // Float2 version:
  3733. static const float2 thresh = float2(0.775075);
  3734. bool2 z_is_large;
  3735. z_is_large.x = z.x > thresh.x;
  3736. z_is_large.y = z.y > thresh.y;
  3737. const float2 large_z = float2(1.0) - uigamma_large_z_impl(s, z) * gamma_s_inv;
  3738. const float2 small_z = ligamma_small_z_impl(s, z, s_inv) * gamma_s_inv;
  3739. bool2 inverse_z_is_large = not(z_is_large);
  3740. return large_z * float2(z_is_large) + small_z * float2(inverse_z_is_large);
  3741. }
  3742. float normalized_ligamma_impl(const float s, const float z,
  3743. const float s_inv, const float gamma_s_inv)
  3744. {
  3745. // Float version:
  3746. static const float thresh = 0.775075;
  3747. const bool z_is_large = z > thresh;
  3748. const float large_z = 1.0 - uigamma_large_z_impl(s, z) * gamma_s_inv;
  3749. const float small_z = ligamma_small_z_impl(s, z, s_inv) * gamma_s_inv;
  3750. return large_z * float(z_is_large) + small_z * float(!z_is_large);
  3751. }
  3752. // Normalized lower incomplete gamma function for small s:
  3753. float4 normalized_ligamma(const float4 s, const float4 z)
  3754. {
  3755. // Requires: s < ~0.5
  3756. // Returns: Approximate the normalized lower incomplete gamma function
  3757. // for s < 0.5. See normalized_ligamma_impl() for details.
  3758. const float4 s_inv = float4(1.0)/s;
  3759. const float4 gamma_s_inv = float4(1.0)/gamma_impl(s, s_inv);
  3760. return normalized_ligamma_impl(s, z, s_inv, gamma_s_inv);
  3761. }
  3762. float3 normalized_ligamma(const float3 s, const float3 z)
  3763. {
  3764. // Float3 version:
  3765. const float3 s_inv = float3(1.0)/s;
  3766. const float3 gamma_s_inv = float3(1.0)/gamma_impl(s, s_inv);
  3767. return normalized_ligamma_impl(s, z, s_inv, gamma_s_inv);
  3768. }
  3769. float2 normalized_ligamma(const float2 s, const float2 z)
  3770. {
  3771. // Float2 version:
  3772. const float2 s_inv = float2(1.0)/s;
  3773. const float2 gamma_s_inv = float2(1.0)/gamma_impl(s, s_inv);
  3774. return normalized_ligamma_impl(s, z, s_inv, gamma_s_inv);
  3775. }
  3776. float normalized_ligamma(const float s, const float z)
  3777. {
  3778. // Float version:
  3779. const float s_inv = 1.0/s;
  3780. const float gamma_s_inv = 1.0/gamma_impl(s, s_inv);
  3781. return normalized_ligamma_impl(s, z, s_inv, gamma_s_inv);
  3782. }
  3783. #endif // SPECIAL_FUNCTIONS_H
  3784. //////////////////////////// END SPECIAL-FUNCTIONS ///////////////////////////
  3785. //#include "../../../../include/gamma-management.h"
  3786. //////////////////////////// BEGIN GAMMA-MANAGEMENT //////////////////////////
  3787. #ifndef GAMMA_MANAGEMENT_H
  3788. #define GAMMA_MANAGEMENT_H
  3789. ///////////////////////////////// MIT LICENSE ////////////////////////////////
  3790. // Copyright (C) 2014 TroggleMonkey
  3791. //
  3792. // Permission is hereby granted, free of charge, to any person obtaining a copy
  3793. // of this software and associated documentation files (the "Software"), to
  3794. // deal in the Software without restriction, including without limitation the
  3795. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  3796. // sell copies of the Software, and to permit persons to whom the Software is
  3797. // furnished to do so, subject to the following conditions:
  3798. //
  3799. // The above copyright notice and this permission notice shall be included in
  3800. // all copies or substantial portions of the Software.
  3801. //
  3802. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  3803. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  3804. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  3805. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  3806. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  3807. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  3808. // IN THE SOFTWARE.
  3809. ///////////////////////////////// DESCRIPTION ////////////////////////////////
  3810. // This file provides gamma-aware tex*D*() and encode_output() functions.
  3811. // Requires: Before #include-ing this file, the including file must #define
  3812. // the following macros when applicable and follow their rules:
  3813. // 1.) #define FIRST_PASS if this is the first pass.
  3814. // 2.) #define LAST_PASS if this is the last pass.
  3815. // 3.) If sRGB is available, set srgb_framebufferN = "true" for
  3816. // every pass except the last in your .cgp preset.
  3817. // 4.) If sRGB isn't available but you want gamma-correctness with
  3818. // no banding, #define GAMMA_ENCODE_EVERY_FBO each pass.
  3819. // 5.) #define SIMULATE_CRT_ON_LCD if desired (precedence over 5-7)
  3820. // 6.) #define SIMULATE_GBA_ON_LCD if desired (precedence over 6-7)
  3821. // 7.) #define SIMULATE_LCD_ON_CRT if desired (precedence over 7)
  3822. // 8.) #define SIMULATE_GBA_ON_CRT if desired (precedence over -)
  3823. // If an option in [5, 8] is #defined in the first or last pass, it
  3824. // should be #defined for both. It shouldn't make a difference
  3825. // whether it's #defined for intermediate passes or not.
  3826. // Optional: The including file (or an earlier included file) may optionally
  3827. // #define a number of macros indicating it will override certain
  3828. // macros and associated constants are as follows:
  3829. // static constants with either static or uniform constants. The
  3830. // 1.) OVERRIDE_STANDARD_GAMMA: The user must first define:
  3831. // static const float ntsc_gamma
  3832. // static const float pal_gamma
  3833. // static const float crt_reference_gamma_high
  3834. // static const float crt_reference_gamma_low
  3835. // static const float lcd_reference_gamma
  3836. // static const float crt_office_gamma
  3837. // static const float lcd_office_gamma
  3838. // 2.) OVERRIDE_DEVICE_GAMMA: The user must first define:
  3839. // static const float crt_gamma
  3840. // static const float gba_gamma
  3841. // static const float lcd_gamma
  3842. // 3.) OVERRIDE_FINAL_GAMMA: The user must first define:
  3843. // static const float input_gamma
  3844. // static const float intermediate_gamma
  3845. // static const float output_gamma
  3846. // (intermediate_gamma is for GAMMA_ENCODE_EVERY_FBO.)
  3847. // 4.) OVERRIDE_ALPHA_ASSUMPTIONS: The user must first define:
  3848. // static const bool assume_opaque_alpha
  3849. // The gamma constant overrides must be used in every pass or none,
  3850. // and OVERRIDE_FINAL_GAMMA bypasses all of the SIMULATE* macros.
  3851. // OVERRIDE_ALPHA_ASSUMPTIONS may be set on a per-pass basis.
  3852. // Usage: After setting macros appropriately, ignore gamma correction and
  3853. // replace all tex*D*() calls with equivalent gamma-aware
  3854. // tex*D*_linearize calls, except:
  3855. // 1.) When you read an LUT, use regular tex*D or a gamma-specified
  3856. // function, depending on its gamma encoding:
  3857. // tex*D*_linearize_gamma (takes a runtime gamma parameter)
  3858. // 2.) If you must read pass0's original input in a later pass, use
  3859. // tex2D_linearize_ntsc_gamma. If you want to read pass0's
  3860. // input with gamma-corrected bilinear filtering, consider
  3861. // creating a first linearizing pass and reading from the input
  3862. // of pass1 later.
  3863. // Then, return encode_output(color) from every fragment shader.
  3864. // Finally, use the global gamma_aware_bilinear boolean if you want
  3865. // to statically branch based on whether bilinear filtering is
  3866. // gamma-correct or not (e.g. for placing Gaussian blur samples).
  3867. //
  3868. // Detailed Policy:
  3869. // tex*D*_linearize() functions enforce a consistent gamma-management policy
  3870. // based on the FIRST_PASS and GAMMA_ENCODE_EVERY_FBO settings. They assume
  3871. // their input texture has the same encoding characteristics as the input for
  3872. // the current pass (which doesn't apply to the exceptions listed above).
  3873. // Similarly, encode_output() enforces a policy based on the LAST_PASS and
  3874. // GAMMA_ENCODE_EVERY_FBO settings. Together, they result in one of the
  3875. // following two pipelines.
  3876. // Typical pipeline with intermediate sRGB framebuffers:
  3877. // linear_color = pow(pass0_encoded_color, input_gamma);
  3878. // intermediate_output = linear_color; // Automatic sRGB encoding
  3879. // linear_color = intermediate_output; // Automatic sRGB decoding
  3880. // final_output = pow(intermediate_output, 1.0/output_gamma);
  3881. // Typical pipeline without intermediate sRGB framebuffers:
  3882. // linear_color = pow(pass0_encoded_color, input_gamma);
  3883. // intermediate_output = pow(linear_color, 1.0/intermediate_gamma);
  3884. // linear_color = pow(intermediate_output, intermediate_gamma);
  3885. // final_output = pow(intermediate_output, 1.0/output_gamma);
  3886. // Using GAMMA_ENCODE_EVERY_FBO is much slower, but it's provided as a way to
  3887. // easily get gamma-correctness without banding on devices where sRGB isn't
  3888. // supported.
  3889. //
  3890. // Use This Header to Maximize Code Reuse:
  3891. // The purpose of this header is to provide a consistent interface for texture
  3892. // reads and output gamma-encoding that localizes and abstracts away all the
  3893. // annoying details. This greatly reduces the amount of code in each shader
  3894. // pass that depends on the pass number in the .cgp preset or whether sRGB
  3895. // FBO's are being used: You can trivially change the gamma behavior of your
  3896. // whole pass by commenting or uncommenting 1-3 #defines. To reuse the same
  3897. // code in your first, Nth, and last passes, you can even put it all in another
  3898. // header file and #include it from skeleton .cg files that #define the
  3899. // appropriate pass-specific settings.
  3900. //
  3901. // Rationale for Using Three Macros:
  3902. // This file uses GAMMA_ENCODE_EVERY_FBO instead of an opposite macro like
  3903. // SRGB_PIPELINE to ensure sRGB is assumed by default, which hopefully imposes
  3904. // a lower maintenance burden on each pass. At first glance it seems we could
  3905. // accomplish everything with two macros: GAMMA_CORRECT_IN / GAMMA_CORRECT_OUT.
  3906. // This works for simple use cases where input_gamma == output_gamma, but it
  3907. // breaks down for more complex scenarios like CRT simulation, where the pass
  3908. // number determines the gamma encoding of the input and output.
  3909. /////////////////////////////// BASE CONSTANTS ///////////////////////////////
  3910. // Set standard gamma constants, but allow users to override them:
  3911. #ifndef OVERRIDE_STANDARD_GAMMA
  3912. // Standard encoding gammas:
  3913. static const float ntsc_gamma = 2.2; // Best to use NTSC for PAL too?
  3914. static const float pal_gamma = 2.8; // Never actually 2.8 in practice
  3915. // Typical device decoding gammas (only use for emulating devices):
  3916. // CRT/LCD reference gammas are higher than NTSC and Rec.709 video standard
  3917. // gammas: The standards purposely undercorrected for an analog CRT's
  3918. // assumed 2.5 reference display gamma to maintain contrast in assumed
  3919. // [dark] viewing conditions: http://www.poynton.com/PDFs/GammaFAQ.pdf
  3920. // These unstated assumptions about display gamma and perceptual rendering
  3921. // intent caused a lot of confusion, and more modern CRT's seemed to target
  3922. // NTSC 2.2 gamma with circuitry. LCD displays seem to have followed suit
  3923. // (they struggle near black with 2.5 gamma anyway), especially PC/laptop
  3924. // displays designed to view sRGB in bright environments. (Standards are
  3925. // also in flux again with BT.1886, but it's underspecified for displays.)
  3926. static const float crt_reference_gamma_high = 2.5; // In (2.35, 2.55)
  3927. static const float crt_reference_gamma_low = 2.35; // In (2.35, 2.55)
  3928. static const float lcd_reference_gamma = 2.5; // To match CRT
  3929. static const float crt_office_gamma = 2.2; // Circuitry-adjusted for NTSC
  3930. static const float lcd_office_gamma = 2.2; // Approximates sRGB
  3931. #endif // OVERRIDE_STANDARD_GAMMA
  3932. // Assuming alpha == 1.0 might make it easier for users to avoid some bugs,
  3933. // but only if they're aware of it.
  3934. #ifndef OVERRIDE_ALPHA_ASSUMPTIONS
  3935. static const bool assume_opaque_alpha = false;
  3936. #endif
  3937. /////////////////////// DERIVED CONSTANTS AS FUNCTIONS ///////////////////////
  3938. // gamma-management.h should be compatible with overriding gamma values with
  3939. // runtime user parameters, but we can only define other global constants in
  3940. // terms of static constants, not uniform user parameters. To get around this
  3941. // limitation, we need to define derived constants using functions.
  3942. // Set device gamma constants, but allow users to override them:
  3943. #ifdef OVERRIDE_DEVICE_GAMMA
  3944. // The user promises to globally define the appropriate constants:
  3945. inline float get_crt_gamma() { return crt_gamma; }
  3946. inline float get_gba_gamma() { return gba_gamma; }
  3947. inline float get_lcd_gamma() { return lcd_gamma; }
  3948. #else
  3949. inline float get_crt_gamma() { return crt_reference_gamma_high; }
  3950. inline float get_gba_gamma() { return 3.5; } // Game Boy Advance; in (3.0, 4.0)
  3951. inline float get_lcd_gamma() { return lcd_office_gamma; }
  3952. #endif // OVERRIDE_DEVICE_GAMMA
  3953. // Set decoding/encoding gammas for the first/lass passes, but allow overrides:
  3954. #ifdef OVERRIDE_FINAL_GAMMA
  3955. // The user promises to globally define the appropriate constants:
  3956. inline float get_intermediate_gamma() { return intermediate_gamma; }
  3957. inline float get_input_gamma() { return input_gamma; }
  3958. inline float get_output_gamma() { return output_gamma; }
  3959. #else
  3960. // If we gamma-correct every pass, always use ntsc_gamma between passes to
  3961. // ensure middle passes don't need to care if anything is being simulated:
  3962. inline float get_intermediate_gamma() { return ntsc_gamma; }
  3963. #ifdef SIMULATE_CRT_ON_LCD
  3964. inline float get_input_gamma() { return get_crt_gamma(); }
  3965. inline float get_output_gamma() { return get_lcd_gamma(); }
  3966. #else
  3967. #ifdef SIMULATE_GBA_ON_LCD
  3968. inline float get_input_gamma() { return get_gba_gamma(); }
  3969. inline float get_output_gamma() { return get_lcd_gamma(); }
  3970. #else
  3971. #ifdef SIMULATE_LCD_ON_CRT
  3972. inline float get_input_gamma() { return get_lcd_gamma(); }
  3973. inline float get_output_gamma() { return get_crt_gamma(); }
  3974. #else
  3975. #ifdef SIMULATE_GBA_ON_CRT
  3976. inline float get_input_gamma() { return get_gba_gamma(); }
  3977. inline float get_output_gamma() { return get_crt_gamma(); }
  3978. #else // Don't simulate anything:
  3979. inline float get_input_gamma() { return ntsc_gamma; }
  3980. inline float get_output_gamma() { return ntsc_gamma; }
  3981. #endif // SIMULATE_GBA_ON_CRT
  3982. #endif // SIMULATE_LCD_ON_CRT
  3983. #endif // SIMULATE_GBA_ON_LCD
  3984. #endif // SIMULATE_CRT_ON_LCD
  3985. #endif // OVERRIDE_FINAL_GAMMA
  3986. // Set decoding/encoding gammas for the current pass. Use static constants for
  3987. // linearize_input and gamma_encode_output, because they aren't derived, and
  3988. // they let the compiler do dead-code elimination.
  3989. #ifndef GAMMA_ENCODE_EVERY_FBO
  3990. #ifdef FIRST_PASS
  3991. static const bool linearize_input = true;
  3992. inline float get_pass_input_gamma() { return get_input_gamma(); }
  3993. #else
  3994. static const bool linearize_input = false;
  3995. inline float get_pass_input_gamma() { return 1.0; }
  3996. #endif
  3997. #ifdef LAST_PASS
  3998. static const bool gamma_encode_output = true;
  3999. inline float get_pass_output_gamma() { return get_output_gamma(); }
  4000. #else
  4001. static const bool gamma_encode_output = false;
  4002. inline float get_pass_output_gamma() { return 1.0; }
  4003. #endif
  4004. #else
  4005. static const bool linearize_input = true;
  4006. static const bool gamma_encode_output = true;
  4007. #ifdef FIRST_PASS
  4008. inline float get_pass_input_gamma() { return get_input_gamma(); }
  4009. #else
  4010. inline float get_pass_input_gamma() { return get_intermediate_gamma(); }
  4011. #endif
  4012. #ifdef LAST_PASS
  4013. inline float get_pass_output_gamma() { return get_output_gamma(); }
  4014. #else
  4015. inline float get_pass_output_gamma() { return get_intermediate_gamma(); }
  4016. #endif
  4017. #endif
  4018. // Users might want to know if bilinear filtering will be gamma-correct:
  4019. static const bool gamma_aware_bilinear = !linearize_input;
  4020. ////////////////////// COLOR ENCODING/DECODING FUNCTIONS /////////////////////
  4021. inline float4 encode_output(const float4 color)
  4022. {
  4023. if(gamma_encode_output)
  4024. {
  4025. if(assume_opaque_alpha)
  4026. {
  4027. return float4(pow(color.rgb, float3(1.0/get_pass_output_gamma())), 1.0);
  4028. }
  4029. else
  4030. {
  4031. return float4(pow(color.rgb, float3(1.0/get_pass_output_gamma())), color.a);
  4032. }
  4033. }
  4034. else
  4035. {
  4036. return color;
  4037. }
  4038. }
  4039. inline float4 decode_input(const float4 color)
  4040. {
  4041. if(linearize_input)
  4042. {
  4043. if(assume_opaque_alpha)
  4044. {
  4045. return float4(pow(color.rgb, float3(get_pass_input_gamma())), 1.0);
  4046. }
  4047. else
  4048. {
  4049. return float4(pow(color.rgb, float3(get_pass_input_gamma())), color.a);
  4050. }
  4051. }
  4052. else
  4053. {
  4054. return color;
  4055. }
  4056. }
  4057. inline float4 decode_gamma_input(const float4 color, const float3 gamma)
  4058. {
  4059. if(assume_opaque_alpha)
  4060. {
  4061. return float4(pow(color.rgb, gamma), 1.0);
  4062. }
  4063. else
  4064. {
  4065. return float4(pow(color.rgb, gamma), color.a);
  4066. }
  4067. }
  4068. //TODO/FIXME: I have no idea why replacing the lookup wrappers with this macro fixes the blurs being offset ¯\_(ツ)_/¯
  4069. //#define tex2D_linearize(C, D) decode_input(vec4(texture(C, D)))
  4070. // EDIT: it's the 'const' in front of the coords that's doing it
  4071. /////////////////////////// TEXTURE LOOKUP WRAPPERS //////////////////////////
  4072. // "SMART" LINEARIZING TEXTURE LOOKUP FUNCTIONS:
  4073. // Provide a wide array of linearizing texture lookup wrapper functions. The
  4074. // Cg shader spec Retroarch uses only allows for 2D textures, but 1D and 3D
  4075. // lookups are provided for completeness in case that changes someday. Nobody
  4076. // is likely to use the *fetch and *proj functions, but they're included just
  4077. // in case. The only tex*D texture sampling functions omitted are:
  4078. // - tex*Dcmpbias
  4079. // - tex*Dcmplod
  4080. // - tex*DARRAY*
  4081. // - tex*DMS*
  4082. // - Variants returning integers
  4083. // Standard line length restrictions are ignored below for vertical brevity.
  4084. /*
  4085. // tex1D:
  4086. inline float4 tex1D_linearize(const sampler1D tex, const float tex_coords)
  4087. { return decode_input(tex1D(tex, tex_coords)); }
  4088. inline float4 tex1D_linearize(const sampler1D tex, const float2 tex_coords)
  4089. { return decode_input(tex1D(tex, tex_coords)); }
  4090. inline float4 tex1D_linearize(const sampler1D tex, const float tex_coords, const int texel_off)
  4091. { return decode_input(tex1D(tex, tex_coords, texel_off)); }
  4092. inline float4 tex1D_linearize(const sampler1D tex, const float2 tex_coords, const int texel_off)
  4093. { return decode_input(tex1D(tex, tex_coords, texel_off)); }
  4094. inline float4 tex1D_linearize(const sampler1D tex, const float tex_coords, const float dx, const float dy)
  4095. { return decode_input(tex1D(tex, tex_coords, dx, dy)); }
  4096. inline float4 tex1D_linearize(const sampler1D tex, const float2 tex_coords, const float dx, const float dy)
  4097. { return decode_input(tex1D(tex, tex_coords, dx, dy)); }
  4098. inline float4 tex1D_linearize(const sampler1D tex, const float tex_coords, const float dx, const float dy, const int texel_off)
  4099. { return decode_input(tex1D(tex, tex_coords, dx, dy, texel_off)); }
  4100. inline float4 tex1D_linearize(const sampler1D tex, const float2 tex_coords, const float dx, const float dy, const int texel_off)
  4101. { return decode_input(tex1D(tex, tex_coords, dx, dy, texel_off)); }
  4102. // tex1Dbias:
  4103. inline float4 tex1Dbias_linearize(const sampler1D tex, const float4 tex_coords)
  4104. { return decode_input(tex1Dbias(tex, tex_coords)); }
  4105. inline float4 tex1Dbias_linearize(const sampler1D tex, const float4 tex_coords, const int texel_off)
  4106. { return decode_input(tex1Dbias(tex, tex_coords, texel_off)); }
  4107. // tex1Dfetch:
  4108. inline float4 tex1Dfetch_linearize(const sampler1D tex, const int4 tex_coords)
  4109. { return decode_input(tex1Dfetch(tex, tex_coords)); }
  4110. inline float4 tex1Dfetch_linearize(const sampler1D tex, const int4 tex_coords, const int texel_off)
  4111. { return decode_input(tex1Dfetch(tex, tex_coords, texel_off)); }
  4112. // tex1Dlod:
  4113. inline float4 tex1Dlod_linearize(const sampler1D tex, const float4 tex_coords)
  4114. { return decode_input(tex1Dlod(tex, tex_coords)); }
  4115. inline float4 tex1Dlod_linearize(const sampler1D tex, const float4 tex_coords, const int texel_off)
  4116. { return decode_input(tex1Dlod(tex, tex_coords, texel_off)); }
  4117. // tex1Dproj:
  4118. inline float4 tex1Dproj_linearize(const sampler1D tex, const float2 tex_coords)
  4119. { return decode_input(tex1Dproj(tex, tex_coords)); }
  4120. inline float4 tex1Dproj_linearize(const sampler1D tex, const float3 tex_coords)
  4121. { return decode_input(tex1Dproj(tex, tex_coords)); }
  4122. inline float4 tex1Dproj_linearize(const sampler1D tex, const float2 tex_coords, const int texel_off)
  4123. { return decode_input(tex1Dproj(tex, tex_coords, texel_off)); }
  4124. inline float4 tex1Dproj_linearize(const sampler1D tex, const float3 tex_coords, const int texel_off)
  4125. { return decode_input(tex1Dproj(tex, tex_coords, texel_off)); }
  4126. */
  4127. // tex2D:
  4128. inline float4 tex2D_linearize(const sampler2D tex, float2 tex_coords)
  4129. { return decode_input(COMPAT_TEXTURE(tex, tex_coords)); }
  4130. inline float4 tex2D_linearize(const sampler2D tex, float3 tex_coords)
  4131. { return decode_input(COMPAT_TEXTURE(tex, tex_coords.xy)); }
  4132. inline float4 tex2D_linearize(const sampler2D tex, float2 tex_coords, int texel_off)
  4133. { return decode_input(textureLod(tex, tex_coords, texel_off)); }
  4134. inline float4 tex2D_linearize(const sampler2D tex, float3 tex_coords, int texel_off)
  4135. { return decode_input(textureLod(tex, tex_coords.xy, texel_off)); }
  4136. //inline float4 tex2D_linearize(const sampler2D tex, const float2 tex_coords, const float2 dx, const float2 dy)
  4137. //{ return decode_input(COMPAT_TEXTURE(tex, tex_coords, dx, dy)); }
  4138. //inline float4 tex2D_linearize(const sampler2D tex, const float3 tex_coords, const float2 dx, const float2 dy)
  4139. //{ return decode_input(COMPAT_TEXTURE(tex, tex_coords, dx, dy)); }
  4140. //inline float4 tex2D_linearize(const sampler2D tex, const float2 tex_coords, const float2 dx, const float2 dy, const int texel_off)
  4141. //{ return decode_input(COMPAT_TEXTURE(tex, tex_coords, dx, dy, texel_off)); }
  4142. //inline float4 tex2D_linearize(const sampler2D tex, const float3 tex_coords, const float2 dx, const float2 dy, const int texel_off)
  4143. //{ return decode_input(COMPAT_TEXTURE(tex, tex_coords, dx, dy, texel_off)); }
  4144. // tex2Dbias:
  4145. //inline float4 tex2Dbias_linearize(const sampler2D tex, const float4 tex_coords)
  4146. //{ return decode_input(tex2Dbias(tex, tex_coords)); }
  4147. //inline float4 tex2Dbias_linearize(const sampler2D tex, const float4 tex_coords, const int texel_off)
  4148. //{ return decode_input(tex2Dbias(tex, tex_coords, texel_off)); }
  4149. // tex2Dfetch:
  4150. //inline float4 tex2Dfetch_linearize(const sampler2D tex, const int4 tex_coords)
  4151. //{ return decode_input(tex2Dfetch(tex, tex_coords)); }
  4152. //inline float4 tex2Dfetch_linearize(const sampler2D tex, const int4 tex_coords, const int texel_off)
  4153. //{ return decode_input(tex2Dfetch(tex, tex_coords, texel_off)); }
  4154. // tex2Dlod:
  4155. inline float4 tex2Dlod_linearize(const sampler2D tex, float4 tex_coords)
  4156. { return decode_input(textureLod(tex, tex_coords.xy, 0.0)); }
  4157. inline float4 tex2Dlod_linearize(const sampler2D tex, float4 tex_coords, int texel_off)
  4158. { return decode_input(textureLod(tex, tex_coords.xy, texel_off)); }
  4159. /*
  4160. // tex2Dproj:
  4161. inline float4 tex2Dproj_linearize(const sampler2D tex, const float3 tex_coords)
  4162. { return decode_input(tex2Dproj(tex, tex_coords)); }
  4163. inline float4 tex2Dproj_linearize(const sampler2D tex, const float4 tex_coords)
  4164. { return decode_input(tex2Dproj(tex, tex_coords)); }
  4165. inline float4 tex2Dproj_linearize(const sampler2D tex, const float3 tex_coords, const int texel_off)
  4166. { return decode_input(tex2Dproj(tex, tex_coords, texel_off)); }
  4167. inline float4 tex2Dproj_linearize(const sampler2D tex, const float4 tex_coords, const int texel_off)
  4168. { return decode_input(tex2Dproj(tex, tex_coords, texel_off)); }
  4169. */
  4170. /*
  4171. // tex3D:
  4172. inline float4 tex3D_linearize(const sampler3D tex, const float3 tex_coords)
  4173. { return decode_input(tex3D(tex, tex_coords)); }
  4174. inline float4 tex3D_linearize(const sampler3D tex, const float3 tex_coords, const int texel_off)
  4175. { return decode_input(tex3D(tex, tex_coords, texel_off)); }
  4176. inline float4 tex3D_linearize(const sampler3D tex, const float3 tex_coords, const float3 dx, const float3 dy)
  4177. { return decode_input(tex3D(tex, tex_coords, dx, dy)); }
  4178. inline float4 tex3D_linearize(const sampler3D tex, const float3 tex_coords, const float3 dx, const float3 dy, const int texel_off)
  4179. { return decode_input(tex3D(tex, tex_coords, dx, dy, texel_off)); }
  4180. // tex3Dbias:
  4181. inline float4 tex3Dbias_linearize(const sampler3D tex, const float4 tex_coords)
  4182. { return decode_input(tex3Dbias(tex, tex_coords)); }
  4183. inline float4 tex3Dbias_linearize(const sampler3D tex, const float4 tex_coords, const int texel_off)
  4184. { return decode_input(tex3Dbias(tex, tex_coords, texel_off)); }
  4185. // tex3Dfetch:
  4186. inline float4 tex3Dfetch_linearize(const sampler3D tex, const int4 tex_coords)
  4187. { return decode_input(tex3Dfetch(tex, tex_coords)); }
  4188. inline float4 tex3Dfetch_linearize(const sampler3D tex, const int4 tex_coords, const int texel_off)
  4189. { return decode_input(tex3Dfetch(tex, tex_coords, texel_off)); }
  4190. // tex3Dlod:
  4191. inline float4 tex3Dlod_linearize(const sampler3D tex, const float4 tex_coords)
  4192. { return decode_input(tex3Dlod(tex, tex_coords)); }
  4193. inline float4 tex3Dlod_linearize(const sampler3D tex, const float4 tex_coords, const int texel_off)
  4194. { return decode_input(tex3Dlod(tex, tex_coords, texel_off)); }
  4195. // tex3Dproj:
  4196. inline float4 tex3Dproj_linearize(const sampler3D tex, const float4 tex_coords)
  4197. { return decode_input(tex3Dproj(tex, tex_coords)); }
  4198. inline float4 tex3Dproj_linearize(const sampler3D tex, const float4 tex_coords, const int texel_off)
  4199. { return decode_input(tex3Dproj(tex, tex_coords, texel_off)); }
  4200. /////////*
  4201. // NONSTANDARD "SMART" LINEARIZING TEXTURE LOOKUP FUNCTIONS:
  4202. // This narrow selection of nonstandard tex2D* functions can be useful:
  4203. // tex2Dlod0: Automatically fill in the tex2D LOD parameter for mip level 0.
  4204. //inline float4 tex2Dlod0_linearize(const sampler2D tex, const float2 tex_coords)
  4205. //{ return decode_input(tex2Dlod(tex, float4(tex_coords, 0.0, 0.0))); }
  4206. //inline float4 tex2Dlod0_linearize(const sampler2D tex, const float2 tex_coords, const int texel_off)
  4207. //{ return decode_input(tex2Dlod(tex, float4(tex_coords, 0.0, 0.0), texel_off)); }
  4208. // MANUALLY LINEARIZING TEXTURE LOOKUP FUNCTIONS:
  4209. // Provide a narrower selection of tex2D* wrapper functions that decode an
  4210. // input sample with a specified gamma value. These are useful for reading
  4211. // LUT's and for reading the input of pass0 in a later pass.
  4212. // tex2D:
  4213. inline float4 tex2D_linearize_gamma(const sampler2D tex, const float2 tex_coords, const float3 gamma)
  4214. { return decode_gamma_input(COMPAT_TEXTURE(tex, tex_coords), gamma); }
  4215. inline float4 tex2D_linearize_gamma(const sampler2D tex, const float3 tex_coords, const float3 gamma)
  4216. { return decode_gamma_input(COMPAT_TEXTURE(tex, tex_coords.xy), gamma); }
  4217. //inline float4 tex2D_linearize_gamma(const sampler2D tex, const float2 tex_coords, const int texel_off, const float3 gamma)
  4218. //{ return decode_gamma_input(COMPAT_TEXTURE(tex, tex_coords, texel_off), gamma); }
  4219. //inline float4 tex2D_linearize_gamma(const sampler2D tex, const float3 tex_coords, const int texel_off, const float3 gamma)
  4220. //{ return decode_gamma_input(COMPAT_TEXTURE(tex, tex_coords, texel_off), gamma); }
  4221. //inline float4 tex2D_linearize_gamma(const sampler2D tex, const float2 tex_coords, const float2 dx, const float2 dy, const float3 gamma)
  4222. //{ return decode_gamma_input(COMPAT_TEXTURE(tex, tex_coords, dx, dy), gamma); }
  4223. //inline float4 tex2D_linearize_gamma(const sampler2D tex, const float3 tex_coords, const float2 dx, const float2 dy, const float3 gamma)
  4224. //{ return decode_gamma_input(COMPAT_TEXTURE(tex, tex_coords, dx, dy), gamma); }
  4225. //inline float4 tex2D_linearize_gamma(const sampler2D tex, const float2 tex_coords, const float2 dx, const float2 dy, const int texel_off, const float3 gamma)
  4226. //{ return decode_gamma_input(COMPAT_TEXTURE(tex, tex_coords, dx, dy, texel_off), gamma); }
  4227. //inline float4 tex2D_linearize_gamma(const sampler2D tex, const float3 tex_coords, const float2 dx, const float2 dy, const int texel_off, const float3 gamma)
  4228. //{ return decode_gamma_input(COMPAT_TEXTURE(tex, tex_coords, dx, dy, texel_off), gamma); }
  4229. /*
  4230. // tex2Dbias:
  4231. inline float4 tex2Dbias_linearize_gamma(const sampler2D tex, const float4 tex_coords, const float3 gamma)
  4232. { return decode_gamma_input(tex2Dbias(tex, tex_coords), gamma); }
  4233. inline float4 tex2Dbias_linearize_gamma(const sampler2D tex, const float4 tex_coords, const int texel_off, const float3 gamma)
  4234. { return decode_gamma_input(tex2Dbias(tex, tex_coords, texel_off), gamma); }
  4235. // tex2Dfetch:
  4236. inline float4 tex2Dfetch_linearize_gamma(const sampler2D tex, const int4 tex_coords, const float3 gamma)
  4237. { return decode_gamma_input(tex2Dfetch(tex, tex_coords), gamma); }
  4238. inline float4 tex2Dfetch_linearize_gamma(const sampler2D tex, const int4 tex_coords, const int texel_off, const float3 gamma)
  4239. { return decode_gamma_input(tex2Dfetch(tex, tex_coords, texel_off), gamma); }
  4240. */
  4241. // tex2Dlod:
  4242. inline float4 tex2Dlod_linearize_gamma(const sampler2D tex, float4 tex_coords, float3 gamma)
  4243. { return decode_gamma_input(textureLod(tex, tex_coords.xy, 0.0), gamma); }
  4244. inline float4 tex2Dlod_linearize_gamma(const sampler2D tex, float4 tex_coords, int texel_off, float3 gamma)
  4245. { return decode_gamma_input(textureLod(tex, tex_coords.xy, texel_off), gamma); }
  4246. #endif // GAMMA_MANAGEMENT_H
  4247. //////////////////////////// END GAMMA-MANAGEMENT //////////////////////////
  4248. //////////////////////////////// END INCLUDES ////////////////////////////////
  4249. ///////////////////////////// SCANLINE FUNCTIONS /////////////////////////////
  4250. inline float3 get_gaussian_sigma(const float3 color, const float sigma_range)
  4251. {
  4252. // Requires: Globals:
  4253. // 1.) beam_min_sigma and beam_max_sigma are global floats
  4254. // containing the desired minimum and maximum beam standard
  4255. // deviations, for dim and bright colors respectively.
  4256. // 2.) beam_max_sigma must be > 0.0
  4257. // 3.) beam_min_sigma must be in (0.0, beam_max_sigma]
  4258. // 4.) beam_spot_power must be defined as a global float.
  4259. // Parameters:
  4260. // 1.) color is the underlying source color along a scanline
  4261. // 2.) sigma_range = beam_max_sigma - beam_min_sigma; we take
  4262. // sigma_range as a parameter to avoid repeated computation
  4263. // when beam_{min, max}_sigma are runtime shader parameters
  4264. // Optional: Users may set beam_spot_shape_function to 1 to define the
  4265. // inner f(color) subfunction (see below) as:
  4266. // f(color) = sqrt(1.0 - (color - 1.0)*(color - 1.0))
  4267. // Otherwise (technically, if beam_spot_shape_function < 0.5):
  4268. // f(color) = pow(color, beam_spot_power)
  4269. // Returns: The standard deviation of the Gaussian beam for "color:"
  4270. // sigma = beam_min_sigma + sigma_range * f(color)
  4271. // Details/Discussion:
  4272. // The beam's spot shape vaguely resembles an aspect-corrected f() in the
  4273. // range [0, 1] (not quite, but it's related). f(color) = color makes
  4274. // spots look like diamonds, and a spherical function or cube balances
  4275. // between variable width and a soft/realistic shape. A beam_spot_power
  4276. // > 1.0 can produce an ugly spot shape and more initial clipping, but the
  4277. // final shape also differs based on the horizontal resampling filter and
  4278. // the phosphor bloom. For instance, resampling horizontally in nonlinear
  4279. // light and/or with a sharp (e.g. Lanczos) filter will sharpen the spot
  4280. // shape, but a sixth root is still quite soft. A power function (default
  4281. // 1.0/3.0 beam_spot_power) is most flexible, but a fixed spherical curve
  4282. // has the highest variability without an awful spot shape.
  4283. //
  4284. // beam_min_sigma affects scanline sharpness/aliasing in dim areas, and its
  4285. // difference from beam_max_sigma affects beam width variability. It only
  4286. // affects clipping [for pure Gaussians] if beam_spot_power > 1.0 (which is
  4287. // a conservative estimate for a more complex constraint).
  4288. //
  4289. // beam_max_sigma affects clipping and increasing scanline width/softness
  4290. // as color increases. The wider this is, the more scanlines need to be
  4291. // evaluated to avoid distortion. For a pure Gaussian, the max_beam_sigma
  4292. // at which the first unused scanline always has a weight < 1.0/255.0 is:
  4293. // num scanlines = 2, max_beam_sigma = 0.2089; distortions begin ~0.34
  4294. // num scanlines = 3, max_beam_sigma = 0.3879; distortions begin ~0.52
  4295. // num scanlines = 4, max_beam_sigma = 0.5723; distortions begin ~0.70
  4296. // num scanlines = 5, max_beam_sigma = 0.7591; distortions begin ~0.89
  4297. // num scanlines = 6, max_beam_sigma = 0.9483; distortions begin ~1.08
  4298. // Generalized Gaussians permit more leeway here as steepness increases.
  4299. if(beam_spot_shape_function < 0.5)
  4300. {
  4301. // Use a power function:
  4302. return float3(beam_min_sigma) + sigma_range *
  4303. pow(color, float3(beam_spot_power));
  4304. }
  4305. else
  4306. {
  4307. // Use a spherical function:
  4308. const float3 color_minus_1 = color - float3(1.0);
  4309. return float3(beam_min_sigma) + sigma_range *
  4310. sqrt(float3(1.0) - color_minus_1*color_minus_1);
  4311. }
  4312. }
  4313. inline float3 get_generalized_gaussian_beta(const float3 color,
  4314. const float shape_range)
  4315. {
  4316. // Requires: Globals:
  4317. // 1.) beam_min_shape and beam_max_shape are global floats
  4318. // containing the desired min/max generalized Gaussian
  4319. // beta parameters, for dim and bright colors respectively.
  4320. // 2.) beam_max_shape must be >= 2.0
  4321. // 3.) beam_min_shape must be in [2.0, beam_max_shape]
  4322. // 4.) beam_shape_power must be defined as a global float.
  4323. // Parameters:
  4324. // 1.) color is the underlying source color along a scanline
  4325. // 2.) shape_range = beam_max_shape - beam_min_shape; we take
  4326. // shape_range as a parameter to avoid repeated computation
  4327. // when beam_{min, max}_shape are runtime shader parameters
  4328. // Returns: The type-I generalized Gaussian "shape" parameter beta for
  4329. // the given color.
  4330. // Details/Discussion:
  4331. // Beta affects the scanline distribution as follows:
  4332. // a.) beta < 2.0 narrows the peak to a spike with a discontinuous slope
  4333. // b.) beta == 2.0 just degenerates to a Gaussian
  4334. // c.) beta > 2.0 flattens and widens the peak, then drops off more steeply
  4335. // than a Gaussian. Whereas high sigmas widen and soften peaks, high
  4336. // beta widen and sharpen peaks at the risk of aliasing.
  4337. // Unlike high beam_spot_powers, high beam_shape_powers actually soften shape
  4338. // transitions, whereas lower ones sharpen them (at the risk of aliasing).
  4339. return beam_min_shape + shape_range * pow(color, float3(beam_shape_power));
  4340. }
  4341. float3 scanline_gaussian_integral_contrib(const float3 dist,
  4342. const float3 color, const float pixel_height, const float sigma_range)
  4343. {
  4344. // Requires: 1.) dist is the distance of the [potentially separate R/G/B]
  4345. // point(s) from a scanline in units of scanlines, where
  4346. // 1.0 means the sample point straddles the next scanline.
  4347. // 2.) color is the underlying source color along a scanline.
  4348. // 3.) pixel_height is the output pixel height in scanlines.
  4349. // 4.) Requirements of get_gaussian_sigma() must be met.
  4350. // Returns: Return a scanline's light output over a given pixel.
  4351. // Details:
  4352. // The CRT beam profile follows a roughly Gaussian distribution which is
  4353. // wider for bright colors than dark ones. The integral over the full
  4354. // range of a Gaussian function is always 1.0, so we can vary the beam
  4355. // with a standard deviation without affecting brightness. 'x' = distance:
  4356. // gaussian sample = 1/(sigma*sqrt(2*pi)) * e**(-(x**2)/(2*sigma**2))
  4357. // gaussian integral = 0.5 (1.0 + erf(x/(sigma * sqrt(2))))
  4358. // Use a numerical approximation of the "error function" (the Gaussian
  4359. // indefinite integral) to find the definite integral of the scanline's
  4360. // average brightness over a given pixel area. Even if curved coords were
  4361. // used in this pass, a flat scalar pixel height works almost as well as a
  4362. // pixel height computed from a full pixel-space to scanline-space matrix.
  4363. const float3 sigma = get_gaussian_sigma(color, sigma_range);
  4364. const float3 ph_offset = float3(pixel_height * 0.5);
  4365. const float3 denom_inv = 1.0/(sigma*sqrt(2.0));
  4366. const float3 integral_high = erf((dist + ph_offset)*denom_inv);
  4367. const float3 integral_low = erf((dist - ph_offset)*denom_inv);
  4368. return color * 0.5*(integral_high - integral_low)/pixel_height;
  4369. }
  4370. float3 scanline_generalized_gaussian_integral_contrib(float3 dist,
  4371. float3 color, float pixel_height, float sigma_range,
  4372. float shape_range)
  4373. {
  4374. // Requires: 1.) Requirements of scanline_gaussian_integral_contrib()
  4375. // must be met.
  4376. // 2.) Requirements of get_gaussian_sigma() must be met.
  4377. // 3.) Requirements of get_generalized_gaussian_beta() must be
  4378. // met.
  4379. // Returns: Return a scanline's light output over a given pixel.
  4380. // A generalized Gaussian distribution allows the shape (beta) to vary
  4381. // as well as the width (alpha). "gamma" refers to the gamma function:
  4382. // generalized sample =
  4383. // beta/(2*alpha*gamma(1/beta)) * e**(-(|x|/alpha)**beta)
  4384. // ligamma(s, z) is the lower incomplete gamma function, for which we only
  4385. // implement two of four branches (because we keep 1/beta <= 0.5):
  4386. // generalized integral = 0.5 + 0.5* sign(x) *
  4387. // ligamma(1/beta, (|x|/alpha)**beta)/gamma(1/beta)
  4388. // See get_generalized_gaussian_beta() for a discussion of beta.
  4389. // We base alpha on the intended Gaussian sigma, but it only strictly
  4390. // models models standard deviation at beta == 2, because the standard
  4391. // deviation depends on both alpha and beta (keeping alpha independent is
  4392. // faster and preserves intuitive behavior and a full spectrum of results).
  4393. const float3 alpha = sqrt(2.0) * get_gaussian_sigma(color, sigma_range);
  4394. const float3 beta = get_generalized_gaussian_beta(color, shape_range);
  4395. const float3 alpha_inv = float3(1.0)/alpha;
  4396. const float3 s = float3(1.0)/beta;
  4397. const float3 ph_offset = float3(pixel_height * 0.5);
  4398. // Pass beta to gamma_impl to avoid repeated divides. Similarly pass
  4399. // beta (i.e. 1/s) and 1/gamma(s) to normalized_ligamma_impl.
  4400. const float3 gamma_s_inv = float3(1.0)/gamma_impl(s, beta);
  4401. const float3 dist1 = dist + ph_offset;
  4402. const float3 dist0 = dist - ph_offset;
  4403. const float3 integral_high = sign(dist1) * normalized_ligamma_impl(
  4404. s, pow(abs(dist1)*alpha_inv, beta), beta, gamma_s_inv);
  4405. const float3 integral_low = sign(dist0) * normalized_ligamma_impl(
  4406. s, pow(abs(dist0)*alpha_inv, beta), beta, gamma_s_inv);
  4407. return color * 0.5*(integral_high - integral_low)/pixel_height;
  4408. }
  4409. float3 scanline_gaussian_sampled_contrib(const float3 dist, const float3 color,
  4410. const float pixel_height, const float sigma_range)
  4411. {
  4412. // See scanline_gaussian integral_contrib() for detailed comments!
  4413. // gaussian sample = 1/(sigma*sqrt(2*pi)) * e**(-(x**2)/(2*sigma**2))
  4414. const float3 sigma = get_gaussian_sigma(color, sigma_range);
  4415. // Avoid repeated divides:
  4416. const float3 sigma_inv = float3(1.0)/sigma;
  4417. const float3 inner_denom_inv = 0.5 * sigma_inv * sigma_inv;
  4418. const float3 outer_denom_inv = sigma_inv/sqrt(2.0*pi);
  4419. if(beam_antialias_level > 0.5)
  4420. {
  4421. // Sample 1/3 pixel away in each direction as well:
  4422. const float3 sample_offset = float3(pixel_height/3.0);
  4423. const float3 dist2 = dist + sample_offset;
  4424. const float3 dist3 = abs(dist - sample_offset);
  4425. // Average three pure Gaussian samples:
  4426. const float3 scale = color/3.0 * outer_denom_inv;
  4427. const float3 weight1 = exp(-(dist*dist)*inner_denom_inv);
  4428. const float3 weight2 = exp(-(dist2*dist2)*inner_denom_inv);
  4429. const float3 weight3 = exp(-(dist3*dist3)*inner_denom_inv);
  4430. return scale * (weight1 + weight2 + weight3);
  4431. }
  4432. else
  4433. {
  4434. return color*exp(-(dist*dist)*inner_denom_inv)*outer_denom_inv;
  4435. }
  4436. }
  4437. float3 scanline_generalized_gaussian_sampled_contrib(float3 dist,
  4438. float3 color, float pixel_height, float sigma_range,
  4439. float shape_range)
  4440. {
  4441. // See scanline_generalized_gaussian_integral_contrib() for details!
  4442. // generalized sample =
  4443. // beta/(2*alpha*gamma(1/beta)) * e**(-(|x|/alpha)**beta)
  4444. const float3 alpha = sqrt(2.0) * get_gaussian_sigma(color, sigma_range);
  4445. const float3 beta = get_generalized_gaussian_beta(color, shape_range);
  4446. // Avoid repeated divides:
  4447. const float3 alpha_inv = float3(1.0)/alpha;
  4448. const float3 beta_inv = float3(1.0)/beta;
  4449. const float3 scale = color * beta * 0.5 * alpha_inv /
  4450. gamma_impl(beta_inv, beta);
  4451. if(beam_antialias_level > 0.5)
  4452. {
  4453. // Sample 1/3 pixel closer to and farther from the scanline too.
  4454. const float3 sample_offset = float3(pixel_height/3.0);
  4455. const float3 dist2 = dist + sample_offset;
  4456. const float3 dist3 = abs(dist - sample_offset);
  4457. // Average three generalized Gaussian samples:
  4458. const float3 weight1 = exp(-pow(abs(dist*alpha_inv), beta));
  4459. const float3 weight2 = exp(-pow(abs(dist2*alpha_inv), beta));
  4460. const float3 weight3 = exp(-pow(abs(dist3*alpha_inv), beta));
  4461. return scale/3.0 * (weight1 + weight2 + weight3);
  4462. }
  4463. else
  4464. {
  4465. return scale * exp(-pow(abs(dist*alpha_inv), beta));
  4466. }
  4467. }
  4468. inline float3 scanline_contrib(float3 dist, float3 color,
  4469. float pixel_height, const float sigma_range, const float shape_range)
  4470. {
  4471. // Requires: 1.) Requirements of scanline_gaussian_integral_contrib()
  4472. // must be met.
  4473. // 2.) Requirements of get_gaussian_sigma() must be met.
  4474. // 3.) Requirements of get_generalized_gaussian_beta() must be
  4475. // met.
  4476. // Returns: Return a scanline's light output over a given pixel, using
  4477. // a generalized or pure Gaussian distribution and sampling or
  4478. // integrals as desired by user codepath choices.
  4479. if(beam_generalized_gaussian)
  4480. {
  4481. if(beam_antialias_level > 1.5)
  4482. {
  4483. return scanline_generalized_gaussian_integral_contrib(
  4484. dist, color, pixel_height, sigma_range, shape_range);
  4485. }
  4486. else
  4487. {
  4488. return scanline_generalized_gaussian_sampled_contrib(
  4489. dist, color, pixel_height, sigma_range, shape_range);
  4490. }
  4491. }
  4492. else
  4493. {
  4494. if(beam_antialias_level > 1.5)
  4495. {
  4496. return scanline_gaussian_integral_contrib(
  4497. dist, color, pixel_height, sigma_range);
  4498. }
  4499. else
  4500. {
  4501. return scanline_gaussian_sampled_contrib(
  4502. dist, color, pixel_height, sigma_range);
  4503. }
  4504. }
  4505. }
  4506. inline float3 get_raw_interpolated_color(const float3 color0,
  4507. const float3 color1, const float3 color2, const float3 color3,
  4508. const float4 weights)
  4509. {
  4510. // Use max to avoid bizarre artifacts from negative colors:
  4511. return max(mul(weights, float4x3(color0, color1, color2, color3)), 0.0);
  4512. }
  4513. float3 get_interpolated_linear_color(const float3 color0, const float3 color1,
  4514. const float3 color2, const float3 color3, const float4 weights)
  4515. {
  4516. // Requires: 1.) Requirements of include/gamma-management.h must be met:
  4517. // intermediate_gamma must be globally defined, and input
  4518. // colors are interpreted as linear RGB unless you #define
  4519. // GAMMA_ENCODE_EVERY_FBO (in which case they are
  4520. // interpreted as gamma-encoded with intermediate_gamma).
  4521. // 2.) color0-3 are colors sampled from a texture with tex2D().
  4522. // They are interpreted as defined in requirement 1.
  4523. // 3.) weights contains weights for each color, summing to 1.0.
  4524. // 4.) beam_horiz_linear_rgb_weight must be defined as a global
  4525. // float in [0.0, 1.0] describing how much blending should
  4526. // be done in linear RGB (rest is gamma-corrected RGB).
  4527. // 5.) RUNTIME_SCANLINES_HORIZ_FILTER_COLORSPACE must be #defined
  4528. // if beam_horiz_linear_rgb_weight is anything other than a
  4529. // static constant, or we may try branching at runtime
  4530. // without dynamic branches allowed (slow).
  4531. // Returns: Return an interpolated color lookup between the four input
  4532. // colors based on the weights in weights. The final color will
  4533. // be a linear RGB value, but the blending will be done as
  4534. // indicated above.
  4535. const float intermediate_gamma = get_intermediate_gamma();
  4536. // Branch if beam_horiz_linear_rgb_weight is static (for free) or if the
  4537. // profile allows dynamic branches (faster than computing extra pows):
  4538. #ifndef RUNTIME_SCANLINES_HORIZ_FILTER_COLORSPACE
  4539. #define SCANLINES_BRANCH_FOR_LINEAR_RGB_WEIGHT
  4540. #else
  4541. #ifdef DRIVERS_ALLOW_DYNAMIC_BRANCHES
  4542. #define SCANLINES_BRANCH_FOR_LINEAR_RGB_WEIGHT
  4543. #endif
  4544. #endif
  4545. #ifdef SCANLINES_BRANCH_FOR_LINEAR_RGB_WEIGHT
  4546. // beam_horiz_linear_rgb_weight is static, so we can branch:
  4547. #ifdef GAMMA_ENCODE_EVERY_FBO
  4548. const float3 gamma_mixed_color = pow(get_raw_interpolated_color(
  4549. color0, color1, color2, color3, weights), float3(intermediate_gamma));
  4550. if(beam_horiz_linear_rgb_weight > 0.0)
  4551. {
  4552. const float3 linear_mixed_color = get_raw_interpolated_color(
  4553. pow(color0, float3(intermediate_gamma)),
  4554. pow(color1, float3(intermediate_gamma)),
  4555. pow(color2, float3(intermediate_gamma)),
  4556. pow(color3, float3(intermediate_gamma)),
  4557. weights);
  4558. return lerp(gamma_mixed_color, linear_mixed_color,
  4559. beam_horiz_linear_rgb_weight);
  4560. }
  4561. else
  4562. {
  4563. return gamma_mixed_color;
  4564. }
  4565. #else
  4566. const float3 linear_mixed_color = get_raw_interpolated_color(
  4567. color0, color1, color2, color3, weights);
  4568. if(beam_horiz_linear_rgb_weight < 1.0)
  4569. {
  4570. const float3 gamma_mixed_color = get_raw_interpolated_color(
  4571. pow(color0, float3(1.0/intermediate_gamma)),
  4572. pow(color1, float3(1.0/intermediate_gamma)),
  4573. pow(color2, float3(1.0/intermediate_gamma)),
  4574. pow(color3, float3(1.0/intermediate_gamma)),
  4575. weights);
  4576. return lerp(gamma_mixed_color, linear_mixed_color,
  4577. beam_horiz_linear_rgb_weight);
  4578. }
  4579. else
  4580. {
  4581. return linear_mixed_color;
  4582. }
  4583. #endif // GAMMA_ENCODE_EVERY_FBO
  4584. #else
  4585. #ifdef GAMMA_ENCODE_EVERY_FBO
  4586. // Inputs: color0-3 are colors in gamma-encoded RGB.
  4587. const float3 gamma_mixed_color = pow(get_raw_interpolated_color(
  4588. color0, color1, color2, color3, weights), intermediate_gamma);
  4589. const float3 linear_mixed_color = get_raw_interpolated_color(
  4590. pow(color0, float3(intermediate_gamma)),
  4591. pow(color1, float3(intermediate_gamma)),
  4592. pow(color2, float3(intermediate_gamma)),
  4593. pow(color3, float3(intermediate_gamma)),
  4594. weights);
  4595. return lerp(gamma_mixed_color, linear_mixed_color,
  4596. beam_horiz_linear_rgb_weight);
  4597. #else
  4598. // Inputs: color0-3 are colors in linear RGB.
  4599. const float3 linear_mixed_color = get_raw_interpolated_color(
  4600. color0, color1, color2, color3, weights);
  4601. const float3 gamma_mixed_color = get_raw_interpolated_color(
  4602. pow(color0, float3(1.0/intermediate_gamma)),
  4603. pow(color1, float3(1.0/intermediate_gamma)),
  4604. pow(color2, float3(1.0/intermediate_gamma)),
  4605. pow(color3, float3(1.0/intermediate_gamma)),
  4606. weights);
  4607. // wtf fixme
  4608. // const float beam_horiz_linear_rgb_weight1 = 1.0;
  4609. return lerp(gamma_mixed_color, linear_mixed_color,
  4610. beam_horiz_linear_rgb_weight);
  4611. #endif // GAMMA_ENCODE_EVERY_FBO
  4612. #endif // SCANLINES_BRANCH_FOR_LINEAR_RGB_WEIGHT
  4613. }
  4614. float3 get_scanline_color(const sampler2D tex, const float2 scanline_uv,
  4615. const float2 uv_step_x, const float4 weights)
  4616. {
  4617. // Requires: 1.) scanline_uv must be vertically snapped to the caller's
  4618. // desired line or scanline and horizontally snapped to the
  4619. // texel just left of the output pixel (color1)
  4620. // 2.) uv_step_x must contain the horizontal uv distance
  4621. // between texels.
  4622. // 3.) weights must contain interpolation filter weights for
  4623. // color0, color1, color2, and color3, where color1 is just
  4624. // left of the output pixel.
  4625. // Returns: Return a horizontally interpolated texture lookup using 2-4
  4626. // nearby texels, according to weights and the conventions of
  4627. // get_interpolated_linear_color().
  4628. // We can ignore the outside texture lookups for Quilez resampling.
  4629. const float3 color1 = COMPAT_TEXTURE(tex, scanline_uv).rgb;
  4630. const float3 color2 = COMPAT_TEXTURE(tex, scanline_uv + uv_step_x).rgb;
  4631. float3 color0 = float3(0.0);
  4632. float3 color3 = float3(0.0);
  4633. if(beam_horiz_filter > 0.5)
  4634. {
  4635. color0 = COMPAT_TEXTURE(tex, scanline_uv - uv_step_x).rgb;
  4636. color3 = COMPAT_TEXTURE(tex, scanline_uv + 2.0 * uv_step_x).rgb;
  4637. }
  4638. // Sample the texture as-is, whether it's linear or gamma-encoded:
  4639. // get_interpolated_linear_color() will handle the difference.
  4640. return get_interpolated_linear_color(color0, color1, color2, color3, weights);
  4641. }
  4642. float3 sample_single_scanline_horizontal(const sampler2D tex,
  4643. const float2 tex_uv, const float2 tex_size,
  4644. const float2 texture_size_inv)
  4645. {
  4646. // TODO: Add function requirements.
  4647. // Snap to the previous texel and get sample dists from 2/4 nearby texels:
  4648. const float2 curr_texel = tex_uv * tex_size;
  4649. // Use under_half to fix a rounding bug right around exact texel locations.
  4650. const float2 prev_texel =
  4651. floor(curr_texel - float2(under_half)) + float2(0.5);
  4652. const float2 prev_texel_hor = float2(prev_texel.x, curr_texel.y);
  4653. const float2 prev_texel_hor_uv = prev_texel_hor * texture_size_inv;
  4654. const float prev_dist = curr_texel.x - prev_texel_hor.x;
  4655. const float4 sample_dists = float4(1.0 + prev_dist, prev_dist,
  4656. 1.0 - prev_dist, 2.0 - prev_dist);
  4657. // Get Quilez, Lanczos2, or Gaussian resize weights for 2/4 nearby texels:
  4658. float4 weights;
  4659. if(beam_horiz_filter < 0.5)
  4660. {
  4661. // Quilez:
  4662. const float x = sample_dists.y;
  4663. const float w2 = x*x*x*(x*(x*6.0 - 15.0) + 10.0);
  4664. weights = float4(0.0, 1.0 - w2, w2, 0.0);
  4665. }
  4666. else if(beam_horiz_filter < 1.5)
  4667. {
  4668. // Gaussian:
  4669. float inner_denom_inv = 1.0/(2.0*beam_horiz_sigma*beam_horiz_sigma);
  4670. weights = exp(-(sample_dists*sample_dists)*inner_denom_inv);
  4671. }
  4672. else
  4673. {
  4674. // Lanczos2:
  4675. const float4 pi_dists = FIX_ZERO(sample_dists * pi);
  4676. weights = 2.0 * sin(pi_dists) * sin(pi_dists * 0.5) /
  4677. (pi_dists * pi_dists);
  4678. }
  4679. // Ensure the weight sum == 1.0:
  4680. const float4 final_weights = weights/dot(weights, float4(1.0));
  4681. // Get the interpolated horizontal scanline color:
  4682. const float2 uv_step_x = float2(texture_size_inv.x, 0.0);
  4683. return get_scanline_color(
  4684. tex, prev_texel_hor_uv, uv_step_x, final_weights);
  4685. }
  4686. float3 sample_rgb_scanline_horizontal(const sampler2D tex,
  4687. const float2 tex_uv, const float2 tex_size,
  4688. const float2 texture_size_inv)
  4689. {
  4690. // TODO: Add function requirements.
  4691. // Rely on a helper to make convergence easier.
  4692. if(beam_misconvergence)
  4693. {
  4694. const float3 convergence_offsets_rgb =
  4695. get_convergence_offsets_x_vector();
  4696. const float3 offset_u_rgb =
  4697. convergence_offsets_rgb * texture_size_inv.xxx;
  4698. const float2 scanline_uv_r = tex_uv - float2(offset_u_rgb.r, 0.0);
  4699. const float2 scanline_uv_g = tex_uv - float2(offset_u_rgb.g, 0.0);
  4700. const float2 scanline_uv_b = tex_uv - float2(offset_u_rgb.b, 0.0);
  4701. const float3 sample_r = sample_single_scanline_horizontal(
  4702. tex, scanline_uv_r, tex_size, texture_size_inv);
  4703. const float3 sample_g = sample_single_scanline_horizontal(
  4704. tex, scanline_uv_g, tex_size, texture_size_inv);
  4705. const float3 sample_b = sample_single_scanline_horizontal(
  4706. tex, scanline_uv_b, tex_size, texture_size_inv);
  4707. return float3(sample_r.r, sample_g.g, sample_b.b);
  4708. }
  4709. else
  4710. {
  4711. return sample_single_scanline_horizontal(tex, tex_uv, tex_size,
  4712. texture_size_inv);
  4713. }
  4714. }
  4715. float2 get_last_scanline_uv(const float2 tex_uv, const float2 tex_size,
  4716. const float2 texture_size_inv, const float2 il_step_multiple,
  4717. const float frame_count, out float dist)
  4718. {
  4719. // Compute texture coords for the last/upper scanline, accounting for
  4720. // interlacing: With interlacing, only consider even/odd scanlines every
  4721. // other frame. Top-field first (TFF) order puts even scanlines on even
  4722. // frames, and BFF order puts them on odd frames. Texels are centered at:
  4723. // frac(tex_uv * tex_size) == x.5
  4724. // Caution: If these coordinates ever seem incorrect, first make sure it's
  4725. // not because anisotropic filtering is blurring across field boundaries.
  4726. // Note: TFF/BFF won't matter for sources that double-weave or similar.
  4727. // wtf fixme
  4728. // const float interlace_bff1 = 1.0;
  4729. const float field_offset = floor(il_step_multiple.y * 0.75) *
  4730. fmod(frame_count + float(interlace_bff), 2.0);
  4731. const float2 curr_texel = tex_uv * tex_size;
  4732. // Use under_half to fix a rounding bug right around exact texel locations.
  4733. const float2 prev_texel_num = floor(curr_texel - float2(under_half));
  4734. const float wrong_field = fmod(
  4735. prev_texel_num.y + field_offset, il_step_multiple.y);
  4736. const float2 scanline_texel_num = prev_texel_num - float2(0.0, wrong_field);
  4737. // Snap to the center of the previous scanline in the current field:
  4738. const float2 scanline_texel = scanline_texel_num + float2(0.5);
  4739. const float2 scanline_uv = scanline_texel * texture_size_inv;
  4740. // Save the sample's distance from the scanline, in units of scanlines:
  4741. dist = (curr_texel.y - scanline_texel.y)/il_step_multiple.y;
  4742. return scanline_uv;
  4743. }
  4744. inline bool is_interlaced(float num_lines)
  4745. {
  4746. // Detect interlacing based on the number of lines in the source.
  4747. if(interlace_detect)
  4748. {
  4749. // NTSC: 525 lines, 262.5/field; 486 active (2 half-lines), 243/field
  4750. // NTSC Emulators: Typically 224 or 240 lines
  4751. // PAL: 625 lines, 312.5/field; 576 active (typical), 288/field
  4752. // PAL Emulators: ?
  4753. // ATSC: 720p, 1080i, 1080p
  4754. // Where do we place our cutoffs? Assumptions:
  4755. // 1.) We only need to care about active lines.
  4756. // 2.) Anything > 288 and <= 576 lines is probably interlaced.
  4757. // 3.) Anything > 576 lines is probably not interlaced...
  4758. // 4.) ...except 1080 lines, which is a crapshoot (user decision).
  4759. // 5.) Just in case the main program uses calculated video sizes,
  4760. // we should nudge the float thresholds a bit.
  4761. const bool sd_interlace = ((num_lines > 288.5) && (num_lines < 576.5));
  4762. const bool hd_interlace = bool(interlace_1080i) ?
  4763. ((num_lines > 1079.5) && (num_lines < 1080.5)) :
  4764. false;
  4765. return (sd_interlace || hd_interlace);
  4766. }
  4767. else
  4768. {
  4769. return false;
  4770. }
  4771. }
  4772. #endif // SCANLINE_FUNCTIONS_H
  4773. ///////////////////////////// END SCANLINE-FUNCTIONS ////////////////////////////
  4774. //#include "phosphor-mask-resizing.h"
  4775. //////////////////////// BEGIN PHOSPHOR-MASK-RESIZING ////////////////////////
  4776. #ifndef PHOSPHOR_MASK_RESIZING_H
  4777. #define PHOSPHOR_MASK_RESIZING_H
  4778. ///////////////////////////// GPL LICENSE NOTICE /////////////////////////////
  4779. // crt-royale: A full-featured CRT shader, with cheese.
  4780. // Copyright (C) 2014 TroggleMonkey <trogglemonkey@gmx.com>
  4781. //
  4782. // This program is free software; you can redistribute it and/or modify it
  4783. // under the terms of the GNU General Public License as published by the Free
  4784. // Software Foundation; either version 2 of the License, or any later version.
  4785. //
  4786. // This program is distributed in the hope that it will be useful, but WITHOUT
  4787. // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  4788. // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  4789. // more details.
  4790. //
  4791. // You should have received a copy of the GNU General Public License along with
  4792. // this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  4793. // Place, Suite 330, Boston, MA 02111-1307 USA
  4794. ////////////////////////////////// INCLUDES //////////////////////////////////
  4795. //#include "../user-settings.h"
  4796. //#include "derived-settings-and-constants.h"
  4797. ///////////////////////////// CODEPATH SELECTION /////////////////////////////
  4798. // Choose a looping strategy based on what's allowed:
  4799. // Dynamic loops not allowed: Use a flat static loop.
  4800. // Dynamic loops accomodated: Coarsely branch around static loops.
  4801. // Dynamic loops assumed allowed: Use a flat dynamic loop.
  4802. #ifndef DRIVERS_ALLOW_DYNAMIC_BRANCHES
  4803. #ifdef ACCOMODATE_POSSIBLE_DYNAMIC_LOOPS
  4804. #define BREAK_LOOPS_INTO_PIECES
  4805. #else
  4806. #define USE_SINGLE_STATIC_LOOP
  4807. #endif
  4808. #endif // No else needed: Dynamic loops assumed.
  4809. ////////////////////////////////// CONSTANTS /////////////////////////////////
  4810. // The larger the resized tile, the fewer samples we'll need for downsizing.
  4811. // See if we can get a static min tile size > mask_min_allowed_tile_size:
  4812. static const float mask_min_allowed_tile_size = ceil(
  4813. mask_min_allowed_triad_size * mask_triads_per_tile);
  4814. static const float mask_min_expected_tile_size =
  4815. mask_min_allowed_tile_size;
  4816. // Limit the number of sinc resize taps by the maximum minification factor:
  4817. static const float pi_over_lobes = pi/mask_sinc_lobes;
  4818. static const float max_sinc_resize_samples_float = 2.0 * mask_sinc_lobes *
  4819. mask_resize_src_lut_size.x/mask_min_expected_tile_size;
  4820. // Vectorized loops sample in multiples of 4. Round up to be safe:
  4821. static const float max_sinc_resize_samples_m4 = ceil(
  4822. max_sinc_resize_samples_float * 0.25) * 4.0;
  4823. ///////////////////////// RESAMPLING FUNCTION HELPERS ////////////////////////
  4824. inline float get_dynamic_loop_size(const float magnification_scale)
  4825. {
  4826. // Requires: The following global constants must be defined:
  4827. // 1.) mask_sinc_lobes
  4828. // 2.) max_sinc_resize_samples_m4
  4829. // Returns: The minimum number of texture samples for a correct downsize
  4830. // at magnification_scale.
  4831. // We're downsizing, so the filter is sized across 2*lobes output pixels
  4832. // (not 2*lobes input texels). This impacts distance measurements and the
  4833. // minimum number of input samples needed.
  4834. const float min_samples_float = 2.0 * mask_sinc_lobes / magnification_scale;
  4835. const float min_samples_m4 = ceil(min_samples_float * 0.25) * 4.0;
  4836. #ifdef DRIVERS_ALLOW_DYNAMIC_BRANCHES
  4837. const float max_samples_m4 = max_sinc_resize_samples_m4;
  4838. #else // ifdef BREAK_LOOPS_INTO_PIECES
  4839. // Simulating loops with branches imposes a 128-sample limit.
  4840. const float max_samples_m4 = min(128.0, max_sinc_resize_samples_m4);
  4841. #endif
  4842. return min(min_samples_m4, max_samples_m4);
  4843. }
  4844. float2 get_first_texel_tile_uv_and_dist(const float2 tex_uv,
  4845. const float2 tex_size, const float dr,
  4846. const float input_tiles_per_texture_r, const float samples,
  4847. static const bool vertical)
  4848. {
  4849. // Requires: 1.) dr == du == 1.0/texture_size.x or
  4850. // dr == dv == 1.0/texture_size.y
  4851. // (whichever direction we're resampling in).
  4852. // It's a scalar to save register space.
  4853. // 2.) input_tiles_per_texture_r is the number of input tiles
  4854. // that can fit in the input texture in the direction we're
  4855. // resampling this pass.
  4856. // 3.) vertical indicates whether we're resampling vertically
  4857. // this pass (or horizontally).
  4858. // Returns: Pack and return the first sample's tile_uv coord in [0, 1]
  4859. // and its texel distance from the destination pixel, in the
  4860. // resized dimension only.
  4861. // We'll start with the topmost or leftmost sample and work down or right,
  4862. // so get the first sample location and distance. Modify both dimensions
  4863. // as if we're doing a one-pass 2D resize; we'll throw away the unneeded
  4864. // (and incorrect) dimension at the end.
  4865. const float2 curr_texel = tex_uv * tex_size;
  4866. const float2 prev_texel =
  4867. floor(curr_texel - float2(under_half)) + float2(0.5);
  4868. const float2 first_texel = prev_texel - float2(samples/2.0 - 1.0);
  4869. const float2 first_texel_uv_wrap_2D = first_texel * dr;
  4870. const float2 first_texel_dist_2D = curr_texel - first_texel;
  4871. // Convert from tex_uv to tile_uv coords so we can sub fracs for fmods.
  4872. const float2 first_texel_tile_uv_wrap_2D =
  4873. first_texel_uv_wrap_2D * input_tiles_per_texture_r;
  4874. // Project wrapped coordinates to the [0, 1] range. We'll do this with all
  4875. // samples,but the first texel is special, since it might be negative.
  4876. const float2 coord_negative =
  4877. float2((first_texel_tile_uv_wrap_2D.x < 0.),(first_texel_tile_uv_wrap_2D.y < 0.));
  4878. const float2 first_texel_tile_uv_2D =
  4879. frac(first_texel_tile_uv_wrap_2D) + coord_negative;
  4880. // Pack the first texel's tile_uv coord and texel distance in 1D:
  4881. const float2 tile_u_and_dist =
  4882. float2(first_texel_tile_uv_2D.x, first_texel_dist_2D.x);
  4883. const float2 tile_v_and_dist =
  4884. float2(first_texel_tile_uv_2D.y, first_texel_dist_2D.y);
  4885. return vertical ? tile_v_and_dist : tile_u_and_dist;
  4886. //return lerp(tile_u_and_dist, tile_v_and_dist, float(vertical));
  4887. }
  4888. inline float4 tex2Dlod0try(const sampler2D tex, const float2 tex_uv)
  4889. {
  4890. // Mipmapping and anisotropic filtering get confused by sinc-resampling.
  4891. // One [slow] workaround is to select the lowest mip level:
  4892. #ifdef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DLOD
  4893. return textureLod(tex, float4(tex_uv, 0.0, 0.0).xy);
  4894. #else
  4895. #ifdef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DBIAS
  4896. return tex2Dbias(tex, float4(tex_uv, 0.0, -16.0));
  4897. #else
  4898. return texture(tex, tex_uv);
  4899. #endif
  4900. #endif
  4901. }
  4902. ////////////////////////////// LOOP BODY MACROS //////////////////////////////
  4903. // Using inline functions can exceed the temporary register limit, so we're
  4904. // stuck with #define macros (I'm TRULY sorry). They're declared here instead
  4905. // of above to be closer to the actual invocation sites. Steps:
  4906. // 1.) Get the exact texel location.
  4907. // 2.) Sample the phosphor mask (already assumed encoded in linear RGB).
  4908. // 3.) Get the distance from the current pixel and sinc weight:
  4909. // sinc(dist) = sin(pi * dist)/(pi * dist)
  4910. // We can also use the slower/smoother Lanczos instead:
  4911. // L(x) = sinc(dist) * sinc(dist / lobes)
  4912. // 4.) Accumulate the weight sum in weights, and accumulate the weighted texels
  4913. // in pixel_color (we'll normalize outside the loop at the end).
  4914. // We vectorize the loop to help reduce the Lanczos window's cost.
  4915. // The r coord is the coord in the dimension we're resizing along (u or v),
  4916. // and first_texel_tile_uv_rrrr is a float4 of the first texel's u or v
  4917. // tile_uv coord in [0, 1]. tex_uv_r will contain the tile_uv u or v coord
  4918. // for four new texel samples.
  4919. #define CALCULATE_R_COORD_FOR_4_SAMPLES \
  4920. const float4 true_i = float4(i_base + i) + float4(0.0, 1.0, 2.0, 3.0); \
  4921. const float4 tile_uv_r = frac( \
  4922. first_texel_tile_uv_rrrr + true_i * tile_dr); \
  4923. const float4 tex_uv_r = tile_uv_r * tile_size_uv_r;
  4924. #ifdef PHOSPHOR_MASK_RESIZE_LANCZOS_WINDOW
  4925. #define CALCULATE_SINC_RESAMPLE_WEIGHTS \
  4926. const float4 pi_dist_over_lobes = pi_over_lobes * dist; \
  4927. const float4 weights = min(sin(pi_dist) * sin(pi_dist_over_lobes) /\
  4928. (pi_dist*pi_dist_over_lobes), float4(1.0));
  4929. #else
  4930. #define CALCULATE_SINC_RESAMPLE_WEIGHTS \
  4931. const float4 weights = min(sin(pi_dist)/pi_dist, float4(1.0));
  4932. #endif
  4933. #define UPDATE_COLOR_AND_WEIGHT_SUMS \
  4934. const float4 dist = magnification_scale * \
  4935. abs(first_dist_unscaled - true_i); \
  4936. const float4 pi_dist = pi * dist; \
  4937. CALCULATE_SINC_RESAMPLE_WEIGHTS; \
  4938. pixel_color += new_sample0 * weights.xxx; \
  4939. pixel_color += new_sample1 * weights.yyy; \
  4940. pixel_color += new_sample2 * weights.zzz; \
  4941. pixel_color += new_sample3 * weights.www; \
  4942. weight_sum += weights;
  4943. #define VERTICAL_SINC_RESAMPLE_LOOP_BODY \
  4944. CALCULATE_R_COORD_FOR_4_SAMPLES; \
  4945. const float3 new_sample0 = tex2Dlod0try(tex, \
  4946. float2(tex_uv.x, tex_uv_r.x)).rgb; \
  4947. const float3 new_sample1 = tex2Dlod0try(tex, \
  4948. float2(tex_uv.x, tex_uv_r.y)).rgb; \
  4949. const float3 new_sample2 = tex2Dlod0try(tex, \
  4950. float2(tex_uv.x, tex_uv_r.z)).rgb; \
  4951. const float3 new_sample3 = tex2Dlod0try(tex, \
  4952. float2(tex_uv.x, tex_uv_r.w)).rgb; \
  4953. UPDATE_COLOR_AND_WEIGHT_SUMS;
  4954. #define HORIZONTAL_SINC_RESAMPLE_LOOP_BODY \
  4955. CALCULATE_R_COORD_FOR_4_SAMPLES; \
  4956. const float3 new_sample0 = tex2Dlod0try(tex, \
  4957. float2(tex_uv_r.x, tex_uv.y)).rgb; \
  4958. const float3 new_sample1 = tex2Dlod0try(tex, \
  4959. float2(tex_uv_r.y, tex_uv.y)).rgb; \
  4960. const float3 new_sample2 = tex2Dlod0try(tex, \
  4961. float2(tex_uv_r.z, tex_uv.y)).rgb; \
  4962. const float3 new_sample3 = tex2Dlod0try(tex, \
  4963. float2(tex_uv_r.w, tex_uv.y)).rgb; \
  4964. UPDATE_COLOR_AND_WEIGHT_SUMS;
  4965. //////////////////////////// RESAMPLING FUNCTIONS ////////////////////////////
  4966. float3 downsample_vertical_sinc_tiled(const sampler2D tex,
  4967. const float2 tex_uv, const float2 tex_size, static const float dr,
  4968. const float magnification_scale, static const float tile_size_uv_r)
  4969. {
  4970. // Requires: 1.) dr == du == 1.0/texture_size.x or
  4971. // dr == dv == 1.0/texture_size.y
  4972. // (whichever direction we're resampling in).
  4973. // It's a scalar to save register space.
  4974. // 2.) tile_size_uv_r is the number of texels an input tile
  4975. // takes up in the input texture, in the direction we're
  4976. // resampling this pass.
  4977. // 3.) magnification_scale must be <= 1.0.
  4978. // Returns: Return a [Lanczos] sinc-resampled pixel of a vertically
  4979. // downsized input tile embedded in an input texture. (The
  4980. // vertical version is special-cased though: It assumes the
  4981. // tile size equals the [static] texture size, since it's used
  4982. // on an LUT texture input containing one tile. For more
  4983. // generic use, eliminate the "static" in the parameters.)
  4984. // The "r" in "dr," "tile_size_uv_r," etc. refers to the dimension
  4985. // we're resizing along, e.g. "dy" in this case.
  4986. #ifdef USE_SINGLE_STATIC_LOOP
  4987. // A static loop can be faster, but it might blur too much from using
  4988. // more samples than it should.
  4989. static const int samples = int(max_sinc_resize_samples_m4);
  4990. #else
  4991. const int samples = int(get_dynamic_loop_size(magnification_scale));
  4992. #endif
  4993. // Get the first sample location (scalar tile uv coord along the resized
  4994. // dimension) and distance from the output location (in texels):
  4995. static const float input_tiles_per_texture_r = 1.0/tile_size_uv_r;
  4996. // true = vertical resize:
  4997. const float2 first_texel_tile_r_and_dist = get_first_texel_tile_uv_and_dist(
  4998. tex_uv, tex_size, dr, input_tiles_per_texture_r, samples, true);
  4999. const float4 first_texel_tile_uv_rrrr = first_texel_tile_r_and_dist.xxxx;
  5000. const float4 first_dist_unscaled = first_texel_tile_r_and_dist.yyyy;
  5001. // Get the tile sample offset:
  5002. static const float tile_dr = dr * input_tiles_per_texture_r;
  5003. // Sum up each weight and weighted sample color, varying the looping
  5004. // strategy based on our expected dynamic loop capabilities. See the
  5005. // loop body macros above.
  5006. int i_base = 0;
  5007. float4 weight_sum = float4(0.0);
  5008. float3 pixel_color = float3(0.0);
  5009. static const int i_step = 4;
  5010. #ifdef BREAK_LOOPS_INTO_PIECES
  5011. if(samples - i_base >= 64)
  5012. {
  5013. for(int i = 0; i < 64; i += i_step)
  5014. {
  5015. VERTICAL_SINC_RESAMPLE_LOOP_BODY;
  5016. }
  5017. i_base += 64;
  5018. }
  5019. if(samples - i_base >= 32)
  5020. {
  5021. for(int i = 0; i < 32; i += i_step)
  5022. {
  5023. VERTICAL_SINC_RESAMPLE_LOOP_BODY;
  5024. }
  5025. i_base += 32;
  5026. }
  5027. if(samples - i_base >= 16)
  5028. {
  5029. for(int i = 0; i < 16; i += i_step)
  5030. {
  5031. VERTICAL_SINC_RESAMPLE_LOOP_BODY;
  5032. }
  5033. i_base += 16;
  5034. }
  5035. if(samples - i_base >= 8)
  5036. {
  5037. for(int i = 0; i < 8; i += i_step)
  5038. {
  5039. VERTICAL_SINC_RESAMPLE_LOOP_BODY;
  5040. }
  5041. i_base += 8;
  5042. }
  5043. if(samples - i_base >= 4)
  5044. {
  5045. for(int i = 0; i < 4; i += i_step)
  5046. {
  5047. VERTICAL_SINC_RESAMPLE_LOOP_BODY;
  5048. }
  5049. i_base += 4;
  5050. }
  5051. // Do another 4-sample block for a total of 128 max samples.
  5052. if(samples - i_base > 0)
  5053. {
  5054. for(int i = 0; i < 4; i += i_step)
  5055. {
  5056. VERTICAL_SINC_RESAMPLE_LOOP_BODY;
  5057. }
  5058. }
  5059. #else
  5060. for(int i = 0; i < samples; i += i_step)
  5061. {
  5062. VERTICAL_SINC_RESAMPLE_LOOP_BODY;
  5063. }
  5064. #endif
  5065. // Normalize so the weight_sum == 1.0, and return:
  5066. const float2 weight_sum_reduce = weight_sum.xy + weight_sum.zw;
  5067. const float3 scalar_weight_sum = float3(weight_sum_reduce.x +
  5068. weight_sum_reduce.y);
  5069. return (pixel_color/scalar_weight_sum);
  5070. }
  5071. float3 downsample_horizontal_sinc_tiled(const sampler2D tex,
  5072. const float2 tex_uv, const float2 tex_size, const float dr,
  5073. const float magnification_scale, const float tile_size_uv_r)
  5074. {
  5075. // Differences from downsample_horizontal_sinc_tiled:
  5076. // 1.) The dr and tile_size_uv_r parameters are not static consts.
  5077. // 2.) The "vertical" parameter to get_first_texel_tile_uv_and_dist is
  5078. // set to false instead of true.
  5079. // 3.) The horizontal version of the loop body is used.
  5080. // TODO: If we can get guaranteed compile-time dead code elimination,
  5081. // we can combine the vertical/horizontal downsampling functions by:
  5082. // 1.) Add an extra static const bool parameter called "vertical."
  5083. // 2.) Supply it with the result of get_first_texel_tile_uv_and_dist().
  5084. // 3.) Use a conditional assignment in the loop body macro. This is the
  5085. // tricky part: We DO NOT want to incur the extra conditional
  5086. // assignment in the inner loop at runtime!
  5087. // The "r" in "dr," "tile_size_uv_r," etc. refers to the dimension
  5088. // we're resizing along, e.g. "dx" in this case.
  5089. #ifdef USE_SINGLE_STATIC_LOOP
  5090. // If we have to load all samples, we might as well use them.
  5091. static const int samples = int(max_sinc_resize_samples_m4);
  5092. #else
  5093. const int samples = int(get_dynamic_loop_size(magnification_scale));
  5094. #endif
  5095. // Get the first sample location (scalar tile uv coord along resized
  5096. // dimension) and distance from the output location (in texels):
  5097. const float input_tiles_per_texture_r = 1.0/tile_size_uv_r;
  5098. // false = horizontal resize:
  5099. const float2 first_texel_tile_r_and_dist = get_first_texel_tile_uv_and_dist(
  5100. tex_uv, tex_size, dr, input_tiles_per_texture_r, samples, false);
  5101. const float4 first_texel_tile_uv_rrrr = first_texel_tile_r_and_dist.xxxx;
  5102. const float4 first_dist_unscaled = first_texel_tile_r_and_dist.yyyy;
  5103. // Get the tile sample offset:
  5104. const float tile_dr = dr * input_tiles_per_texture_r;
  5105. // Sum up each weight and weighted sample color, varying the looping
  5106. // strategy based on our expected dynamic loop capabilities. See the
  5107. // loop body macros above.
  5108. int i_base = 0;
  5109. float4 weight_sum = float4(0.0);
  5110. float3 pixel_color = float3(0.0);
  5111. static const int i_step = 4;
  5112. #ifdef BREAK_LOOPS_INTO_PIECES
  5113. if(samples - i_base >= 64)
  5114. {
  5115. for(int i = 0; i < 64; i += i_step)
  5116. {
  5117. HORIZONTAL_SINC_RESAMPLE_LOOP_BODY;
  5118. }
  5119. i_base += 64;
  5120. }
  5121. if(samples - i_base >= 32)
  5122. {
  5123. for(int i = 0; i < 32; i += i_step)
  5124. {
  5125. HORIZONTAL_SINC_RESAMPLE_LOOP_BODY;
  5126. }
  5127. i_base += 32;
  5128. }
  5129. if(samples - i_base >= 16)
  5130. {
  5131. for(int i = 0; i < 16; i += i_step)
  5132. {
  5133. HORIZONTAL_SINC_RESAMPLE_LOOP_BODY;
  5134. }
  5135. i_base += 16;
  5136. }
  5137. if(samples - i_base >= 8)
  5138. {
  5139. for(int i = 0; i < 8; i += i_step)
  5140. {
  5141. HORIZONTAL_SINC_RESAMPLE_LOOP_BODY;
  5142. }
  5143. i_base += 8;
  5144. }
  5145. if(samples - i_base >= 4)
  5146. {
  5147. for(int i = 0; i < 4; i += i_step)
  5148. {
  5149. HORIZONTAL_SINC_RESAMPLE_LOOP_BODY;
  5150. }
  5151. i_base += 4;
  5152. }
  5153. // Do another 4-sample block for a total of 128 max samples.
  5154. if(samples - i_base > 0)
  5155. {
  5156. for(int i = 0; i < 4; i += i_step)
  5157. {
  5158. HORIZONTAL_SINC_RESAMPLE_LOOP_BODY;
  5159. }
  5160. }
  5161. #else
  5162. for(int i = 0; i < samples; i += i_step)
  5163. {
  5164. HORIZONTAL_SINC_RESAMPLE_LOOP_BODY;
  5165. }
  5166. #endif
  5167. // Normalize so the weight_sum == 1.0, and return:
  5168. const float2 weight_sum_reduce = weight_sum.xy + weight_sum.zw;
  5169. const float3 scalar_weight_sum = float3(weight_sum_reduce.x +
  5170. weight_sum_reduce.y);
  5171. return (pixel_color/scalar_weight_sum);
  5172. }
  5173. //////////////////////////// TILE SIZE CALCULATION ///////////////////////////
  5174. float2 get_resized_mask_tile_size(const float2 estimated_viewport_size,
  5175. const float2 estimated_mask_resize_output_size,
  5176. const bool solemnly_swear_same_inputs_for_every_pass)
  5177. {
  5178. // Requires: The following global constants must be defined according to
  5179. // certain constraints:
  5180. // 1.) mask_resize_num_triads: Must be high enough that our
  5181. // mask sampling method won't have artifacts later
  5182. // (long story; see derived-settings-and-constants.h)
  5183. // 2.) mask_resize_src_lut_size: Texel size of our mask LUT
  5184. // 3.) mask_triads_per_tile: Num horizontal triads in our LUT
  5185. // 4.) mask_min_allowed_triad_size: User setting (the more
  5186. // restrictive it is, the faster the resize will go)
  5187. // 5.) mask_min_allowed_tile_size_x < mask_resize_src_lut_size.x
  5188. // 6.) mask_triad_size_desired_{runtime, static}
  5189. // 7.) mask_num_triads_desired_{runtime, static}
  5190. // 8.) mask_specify_num_triads must be 0.0/1.0 (false/true)
  5191. // The function parameters must be defined as follows:
  5192. // 1.) estimated_viewport_size == (final viewport size);
  5193. // If mask_specify_num_triads is 1.0/true and the viewport
  5194. // estimate is wrong, the number of triads will differ from
  5195. // the user's preference by about the same factor.
  5196. // 2.) estimated_mask_resize_output_size: Must equal the
  5197. // output size of the MASK_RESIZE pass.
  5198. // Exception: The x component may be estimated garbage if
  5199. // and only if the caller throws away the x result.
  5200. // 3.) solemnly_swear_same_inputs_for_every_pass: Set to false,
  5201. // unless you can guarantee that every call across every
  5202. // pass will use the same sizes for the other parameters.
  5203. // When calling this across multiple passes, always use the
  5204. // same y viewport size/scale, and always use the same x
  5205. // viewport size/scale when using the x result.
  5206. // Returns: Return the final size of a manually resized mask tile, after
  5207. // constraining the desired size to avoid artifacts. Under
  5208. // unusual circumstances, tiles may become stretched vertically
  5209. // (see wall of text below).
  5210. // Stated tile properties must be correct:
  5211. static const float tile_aspect_ratio_inv =
  5212. mask_resize_src_lut_size.y/mask_resize_src_lut_size.x;
  5213. static const float tile_aspect_ratio = 1.0/tile_aspect_ratio_inv;
  5214. static const float2 tile_aspect = float2(1.0, tile_aspect_ratio_inv);
  5215. // If mask_specify_num_triads is 1.0/true and estimated_viewport_size.x is
  5216. // wrong, the user preference will be misinterpreted:
  5217. const float desired_tile_size_x = mask_triads_per_tile * lerp(
  5218. mask_triad_size_desired,
  5219. estimated_viewport_size.x / mask_num_triads_desired,
  5220. mask_specify_num_triads);
  5221. if(get_mask_sample_mode() > 0.5)
  5222. {
  5223. // We don't need constraints unless we're sampling MASK_RESIZE.
  5224. return desired_tile_size_x * tile_aspect;
  5225. }
  5226. // Make sure we're not upsizing:
  5227. const float temp_tile_size_x =
  5228. min(desired_tile_size_x, mask_resize_src_lut_size.x);
  5229. // Enforce min_tile_size and max_tile_size in both dimensions:
  5230. const float2 temp_tile_size = temp_tile_size_x * tile_aspect;
  5231. static const float2 min_tile_size =
  5232. mask_min_allowed_tile_size * tile_aspect;
  5233. const float2 max_tile_size =
  5234. estimated_mask_resize_output_size / mask_resize_num_tiles;
  5235. const float2 clamped_tile_size =
  5236. clamp(temp_tile_size, min_tile_size, max_tile_size);
  5237. // Try to maintain tile_aspect_ratio. This is the tricky part:
  5238. // If we're currently resizing in the y dimension, the x components
  5239. // could be MEANINGLESS. (If estimated_mask_resize_output_size.x is
  5240. // bogus, then so is max_tile_size.x and clamped_tile_size.x.)
  5241. // We can't adjust the y size based on clamped_tile_size.x. If it
  5242. // clamps when it shouldn't, it won't clamp again when later passes
  5243. // call this function with the correct sizes, and the discrepancy will
  5244. // break the sampling coords in MASKED_SCANLINES. Instead, we'll limit
  5245. // the x size based on the y size, but not vice versa, unless the
  5246. // caller swears the parameters were the same (correct) in every pass.
  5247. // As a result, triads could appear vertically stretched if:
  5248. // a.) mask_resize_src_lut_size.x > mask_resize_src_lut_size.y: Wide
  5249. // LUT's might clamp x more than y (all provided LUT's are square)
  5250. // b.) true_viewport_size.x < true_viewport_size.y: The user is playing
  5251. // with a vertically oriented screen (not accounted for anyway)
  5252. // c.) mask_resize_viewport_scale.x < masked_resize_viewport_scale.y:
  5253. // Viewport scales are equal by default.
  5254. // If any of these are the case, you can fix the stretching by setting:
  5255. // mask_resize_viewport_scale.x = mask_resize_viewport_scale.y *
  5256. // (1.0 / min_expected_aspect_ratio) *
  5257. // (mask_resize_src_lut_size.x / mask_resize_src_lut_size.y)
  5258. const float x_tile_size_from_y =
  5259. clamped_tile_size.y * tile_aspect_ratio;
  5260. const float y_tile_size_from_x = lerp(clamped_tile_size.y,
  5261. clamped_tile_size.x * tile_aspect_ratio_inv,
  5262. float(solemnly_swear_same_inputs_for_every_pass));
  5263. const float2 reclamped_tile_size = float2(
  5264. min(clamped_tile_size.x, x_tile_size_from_y),
  5265. min(clamped_tile_size.y, y_tile_size_from_x));
  5266. // We need integer tile sizes in both directions for tiled sampling to
  5267. // work correctly. Use floor (to make sure we don't round up), but be
  5268. // careful to avoid a rounding bug where floor decreases whole numbers:
  5269. const float2 final_resized_tile_size =
  5270. floor(reclamped_tile_size + float2(FIX_ZERO(0.0)));
  5271. return final_resized_tile_size;
  5272. }
  5273. ///////////////////////// FINAL MASK SAMPLING HELPERS ////////////////////////
  5274. float4 get_mask_sampling_parameters(const float2 mask_resize_texture_size,
  5275. const float2 mask_resize_video_size, const float2 true_viewport_size,
  5276. out float2 mask_tiles_per_screen)
  5277. {
  5278. // Requires: 1.) Requirements of get_resized_mask_tile_size() must be
  5279. // met, particularly regarding global constants.
  5280. // The function parameters must be defined as follows:
  5281. // 1.) mask_resize_texture_size == MASK_RESIZE.texture_size
  5282. // if get_mask_sample_mode() is 0 (otherwise anything)
  5283. // 2.) mask_resize_video_size == MASK_RESIZE.video_size
  5284. // if get_mask_sample_mode() is 0 (otherwise anything)
  5285. // 3.) true_viewport_size == output_size for a pass set to
  5286. // 1.0 viewport scale (i.e. it must be correct)
  5287. // Returns: Return a float4 containing:
  5288. // xy: tex_uv coords for the start of the mask tile
  5289. // zw: tex_uv size of the mask tile from start to end
  5290. // mask_tiles_per_screen is an out parameter containing the
  5291. // number of mask tiles that will fit on the screen.
  5292. // First get the final resized tile size. The viewport size and mask
  5293. // resize viewport scale must be correct, but don't solemnly swear they
  5294. // were correct in both mask resize passes unless you know it's true.
  5295. // (We can better ensure a correct tile aspect ratio if the parameters are
  5296. // guaranteed correct in all passes...but if we lie, we'll get inconsistent
  5297. // sizes across passes, resulting in broken texture coordinates.)
  5298. const float mask_sample_mode = get_mask_sample_mode();
  5299. const float2 mask_resize_tile_size = get_resized_mask_tile_size(
  5300. true_viewport_size, mask_resize_video_size, false);
  5301. if(mask_sample_mode < 0.5)
  5302. {
  5303. // Sample MASK_RESIZE: The resized tile is a fraction of the texture
  5304. // size and starts at a nonzero offset to allow for border texels:
  5305. const float2 mask_tile_uv_size = mask_resize_tile_size /
  5306. mask_resize_texture_size;
  5307. const float2 skipped_tiles = mask_start_texels/mask_resize_tile_size;
  5308. const float2 mask_tile_start_uv = skipped_tiles * mask_tile_uv_size;
  5309. // mask_tiles_per_screen must be based on the *true* viewport size:
  5310. mask_tiles_per_screen = true_viewport_size / mask_resize_tile_size;
  5311. return float4(mask_tile_start_uv, mask_tile_uv_size);
  5312. }
  5313. else
  5314. {
  5315. // If we're tiling at the original size (1:1 pixel:texel), redefine a
  5316. // "tile" to be the full texture containing many triads. Otherwise,
  5317. // we're hardware-resampling an LUT, and the texture truly contains a
  5318. // single unresized phosphor mask tile anyway.
  5319. static const float2 mask_tile_uv_size = float2(1.0);
  5320. static const float2 mask_tile_start_uv = float2(0.0);
  5321. if(mask_sample_mode > 1.5)
  5322. {
  5323. // Repeat the full LUT at a 1:1 pixel:texel ratio without resizing:
  5324. mask_tiles_per_screen = true_viewport_size/mask_texture_large_size;
  5325. }
  5326. else
  5327. {
  5328. // Hardware-resize the original LUT:
  5329. mask_tiles_per_screen = true_viewport_size / mask_resize_tile_size;
  5330. }
  5331. return float4(mask_tile_start_uv, mask_tile_uv_size);
  5332. }
  5333. }
  5334. /*
  5335. float2 fix_tiling_discontinuities_normalized(const float2 tile_uv,
  5336. float2 duv_dx, float2 duv_dy)
  5337. {
  5338. // Requires: 1.) duv_dx == ddx(tile_uv)
  5339. // 2.) duv_dy == ddy(tile_uv)
  5340. // 3.) tile_uv contains tile-relative uv coords in [0, 1],
  5341. // such that (0.5, 0.5) is the center of a tile, etc.
  5342. // ("Tile" can mean texture, the video embedded in the
  5343. // texture, or some other "tile" embedded in a texture.)
  5344. // Returns: Return new tile_uv coords that contain no discontinuities
  5345. // across a 2x2 pixel quad.
  5346. // Description:
  5347. // When uv coords wrap from 1.0 to 0.0, they create a discontinuity in the
  5348. // derivatives, which we assume happened if the absolute difference between
  5349. // any fragment in a 2x2 block is > ~half a tile. If the current block has
  5350. // a u or v discontinuity and the current fragment is in the first half of
  5351. // the tile along that axis (i.e. it wrapped from 1.0 to 0.0), add a tile
  5352. // to that coord to make the 2x2 block continuous. (It will now have a
  5353. // coord > 1.0 in the padding area beyond the tile.) This function takes
  5354. // derivatives as parameters so the caller can reuse them.
  5355. // In case we're using high-quality (nVidia-style) derivatives, ensure
  5356. // diagonically opposite fragments see each other for correctness:
  5357. duv_dx = abs(duv_dx) + abs(ddy(duv_dx));
  5358. duv_dy = abs(duv_dy) + abs(ddx(duv_dy));
  5359. const float2 pixel_in_first_half_tile = float2((tile_uv.x < 0.5),(tile_uv.y < 0.5));
  5360. const float2 jump_exists = float2(((duv_dx + duv_dy).x > 0.5),((duv_dx + duv_dy).y > 0.5));
  5361. return tile_uv + jump_exists * pixel_in_first_half_tile;
  5362. }
  5363. */
  5364. float2 convert_phosphor_tile_uv_wrap_to_tex_uv(const float2 tile_uv_wrap,
  5365. const float4 mask_tile_start_uv_and_size)
  5366. {
  5367. // Requires: 1.) tile_uv_wrap contains tile-relative uv coords, where the
  5368. // tile spans from [0, 1], such that (0.5, 0.5) is at the
  5369. // tile center. The input coords can range from [0, inf],
  5370. // and their fractional parts map to a repeated tile.
  5371. // ("Tile" can mean texture, the video embedded in the
  5372. // texture, or some other "tile" embedded in a texture.)
  5373. // 2.) mask_tile_start_uv_and_size.xy contains tex_uv coords
  5374. // for the start of the embedded tile in the full texture.
  5375. // 3.) mask_tile_start_uv_and_size.zw contains the [fractional]
  5376. // tex_uv size of the embedded tile in the full texture.
  5377. // Returns: Return tex_uv coords (used for texture sampling)
  5378. // corresponding to tile_uv_wrap.
  5379. if(get_mask_sample_mode() < 0.5)
  5380. {
  5381. // Manually repeat the resized mask tile to fill the screen:
  5382. // First get fractional tile_uv coords. Using frac/fmod on coords
  5383. // confuses anisotropic filtering; fix it as user options dictate.
  5384. // derived-settings-and-constants.h disables incompatible options.
  5385. #ifdef ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE
  5386. float2 tile_uv = frac(tile_uv_wrap * 0.5) * 2.0;
  5387. #else
  5388. float2 tile_uv = frac(tile_uv_wrap);
  5389. #endif
  5390. #ifdef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
  5391. const float2 tile_uv_dx = ddx(tile_uv);
  5392. const float2 tile_uv_dy = ddy(tile_uv);
  5393. tile_uv = fix_tiling_discontinuities_normalized(tile_uv,
  5394. tile_uv_dx, tile_uv_dy);
  5395. #endif
  5396. // The tile is embedded in a padded FBO, and it may start at a
  5397. // nonzero offset if border texels are used to avoid artifacts:
  5398. const float2 mask_tex_uv = mask_tile_start_uv_and_size.xy +
  5399. tile_uv * mask_tile_start_uv_and_size.zw;
  5400. return mask_tex_uv;
  5401. }
  5402. else
  5403. {
  5404. // Sample from the input phosphor mask texture with hardware tiling.
  5405. // If we're tiling at the original size (mode 2), the "tile" is the
  5406. // whole texture, and it contains a large number of triads mapped with
  5407. // a 1:1 pixel:texel ratio. OTHERWISE, the texture contains a single
  5408. // unresized tile. tile_uv_wrap already has correct coords for both!
  5409. return tile_uv_wrap;
  5410. }
  5411. }
  5412. #endif // PHOSPHOR_MASK_RESIZING_H
  5413. ///////////////////////// END PHOSPHOR-MASK-RESIZING /////////////////////////
  5414. //#include "../../../../include/gamma-management.h"
  5415. // already got it
  5416. //////////////////////////////// END INCLUDES ////////////////////////////////
  5417. /////////////////////////////////// HELPERS //////////////////////////////////
  5418. inline float4 tex2Dtiled_mask_linearize(const sampler2D tex,
  5419. const float2 tex_uv)
  5420. {
  5421. // If we're manually tiling a texture, anisotropic filtering can get
  5422. // confused. One workaround is to just select the lowest mip level:
  5423. #ifdef PHOSPHOR_MASK_MANUALLY_RESIZE
  5424. #ifdef ANISOTROPIC_TILING_COMPAT_TEX2DLOD
  5425. // TODO: Use tex2Dlod_linearize with a calculated mip level.
  5426. return tex2Dlod_linearize(tex, float4(tex_uv, 0.0, 0.0));
  5427. #else
  5428. #ifdef ANISOTROPIC_TILING_COMPAT_TEX2DBIAS
  5429. return tex2Dbias_linearize(tex, float4(tex_uv, 0.0, -16.0));
  5430. #else
  5431. return tex2D_linearize(tex, tex_uv);
  5432. #endif
  5433. #endif
  5434. #else
  5435. return tex2D_linearize(tex, tex_uv);
  5436. #endif
  5437. }
  5438. #undef COMPAT_PRECISION
  5439. #undef COMPAT_TEXTURE
  5440. // END VERTEX INCLUDES //
  5441. ////////////////////////////// FRAGMENT INCLUDES //////////////////////////////
  5442. //#include "bloom-functions.h"
  5443. //////////////////////////// BEGIN BLOOM-FUNCTIONS ///////////////////////////
  5444. #ifndef BLOOM_FUNCTIONS_H
  5445. #define BLOOM_FUNCTIONS_H
  5446. ///////////////////////////// GPL LICENSE NOTICE /////////////////////////////
  5447. // crt-royale: A full-featured CRT shader, with cheese.
  5448. // Copyright (C) 2014 TroggleMonkey <trogglemonkey@gmx.com>
  5449. //
  5450. // This program is free software; you can redistribute it and/or modify it
  5451. // under the terms of the GNU General Public License as published by the Free
  5452. // Software Foundation; either version 2 of the License, or any later version.
  5453. //
  5454. // This program is distributed in the hope that it will be useful, but WITHOUT
  5455. // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  5456. // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  5457. // more details.
  5458. //
  5459. // You should have received a copy of the GNU General Public License along with
  5460. // this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  5461. // Place, Suite 330, Boston, MA 02111-1307 USA
  5462. ///////////////////////////////// DESCRIPTION ////////////////////////////////
  5463. // These utility functions and constants help several passes determine the
  5464. // size and center texel weight of the phosphor bloom in a uniform manner.
  5465. ////////////////////////////////// INCLUDES //////////////////////////////////
  5466. // We need to calculate the correct blur sigma using some .cgp constants:
  5467. //#include "../user-settings.h"
  5468. ///////////////////////////// BEGIN USER-SETTINGS ////////////////////////////
  5469. #ifndef USER_SETTINGS_H
  5470. #define USER_SETTINGS_H
  5471. ///////////////////////////// DRIVER CAPABILITIES ////////////////////////////
  5472. // The Cg compiler uses different "profiles" with different capabilities.
  5473. // This shader requires a Cg compilation profile >= arbfp1, but a few options
  5474. // require higher profiles like fp30 or fp40. The shader can't detect profile
  5475. // or driver capabilities, so instead you must comment or uncomment the lines
  5476. // below with "//" before "#define." Disable an option if you get compilation
  5477. // errors resembling those listed. Generally speaking, all of these options
  5478. // will run on nVidia cards, but only DRIVERS_ALLOW_TEX2DBIAS (if that) is
  5479. // likely to run on ATI/AMD, due to the Cg compiler's profile limitations.
  5480. // Derivatives: Unsupported on fp20, ps_1_1, ps_1_2, ps_1_3, and arbfp1.
  5481. // Among other things, derivatives help us fix anisotropic filtering artifacts
  5482. // with curved manually tiled phosphor mask coords. Related errors:
  5483. // error C3004: function "float2 ddx(float2);" not supported in this profile
  5484. // error C3004: function "float2 ddy(float2);" not supported in this profile
  5485. //#define DRIVERS_ALLOW_DERIVATIVES
  5486. // Fine derivatives: Unsupported on older ATI cards.
  5487. // Fine derivatives enable 2x2 fragment block communication, letting us perform
  5488. // fast single-pass blur operations. If your card uses coarse derivatives and
  5489. // these are enabled, blurs could look broken. Derivatives are a prerequisite.
  5490. #ifdef DRIVERS_ALLOW_DERIVATIVES
  5491. #define DRIVERS_ALLOW_FINE_DERIVATIVES
  5492. #endif
  5493. // Dynamic looping: Requires an fp30 or newer profile.
  5494. // This makes phosphor mask resampling faster in some cases. Related errors:
  5495. // error C5013: profile does not support "for" statements and "for" could not
  5496. // be unrolled
  5497. //#define DRIVERS_ALLOW_DYNAMIC_BRANCHES
  5498. // Without DRIVERS_ALLOW_DYNAMIC_BRANCHES, we need to use unrollable loops.
  5499. // Using one static loop avoids overhead if the user is right, but if the user
  5500. // is wrong (loops are allowed), breaking a loop into if-blocked pieces with a
  5501. // binary search can potentially save some iterations. However, it may fail:
  5502. // error C6001: Temporary register limit of 32 exceeded; 35 registers
  5503. // needed to compile program
  5504. //#define ACCOMODATE_POSSIBLE_DYNAMIC_LOOPS
  5505. // tex2Dlod: Requires an fp40 or newer profile. This can be used to disable
  5506. // anisotropic filtering, thereby fixing related artifacts. Related errors:
  5507. // error C3004: function "float4 tex2Dlod(sampler2D, float4);" not supported in
  5508. // this profile
  5509. //#define DRIVERS_ALLOW_TEX2DLOD
  5510. // tex2Dbias: Requires an fp30 or newer profile. This can be used to alleviate
  5511. // artifacts from anisotropic filtering and mipmapping. Related errors:
  5512. // error C3004: function "float4 tex2Dbias(sampler2D, float4);" not supported
  5513. // in this profile
  5514. //#define DRIVERS_ALLOW_TEX2DBIAS
  5515. // Integrated graphics compatibility: Integrated graphics like Intel HD 4000
  5516. // impose stricter limitations on register counts and instructions. Enable
  5517. // INTEGRATED_GRAPHICS_COMPATIBILITY_MODE if you still see error C6001 or:
  5518. // error C6002: Instruction limit of 1024 exceeded: 1523 instructions needed
  5519. // to compile program.
  5520. // Enabling integrated graphics compatibility mode will automatically disable:
  5521. // 1.) PHOSPHOR_MASK_MANUALLY_RESIZE: The phosphor mask will be softer.
  5522. // (This may be reenabled in a later release.)
  5523. // 2.) RUNTIME_GEOMETRY_MODE
  5524. // 3.) The high-quality 4x4 Gaussian resize for the bloom approximation
  5525. //#define INTEGRATED_GRAPHICS_COMPATIBILITY_MODE
  5526. //////////////////////////// USER CODEPATH OPTIONS ///////////////////////////
  5527. // To disable a #define option, turn its line into a comment with "//."
  5528. // RUNTIME VS. COMPILE-TIME OPTIONS (Major Performance Implications):
  5529. // Enable runtime shader parameters in the Retroarch (etc.) GUI? They override
  5530. // many of the options in this file and allow real-time tuning, but many of
  5531. // them are slower. Disabling them and using this text file will boost FPS.
  5532. #define RUNTIME_SHADER_PARAMS_ENABLE
  5533. // Specify the phosphor bloom sigma at runtime? This option is 10% slower, but
  5534. // it's the only way to do a wide-enough full bloom with a runtime dot pitch.
  5535. #define RUNTIME_PHOSPHOR_BLOOM_SIGMA
  5536. // Specify antialiasing weight parameters at runtime? (Costs ~20% with cubics)
  5537. #define RUNTIME_ANTIALIAS_WEIGHTS
  5538. // Specify subpixel offsets at runtime? (WARNING: EXTREMELY EXPENSIVE!)
  5539. //#define RUNTIME_ANTIALIAS_SUBPIXEL_OFFSETS
  5540. // Make beam_horiz_filter and beam_horiz_linear_rgb_weight into runtime shader
  5541. // parameters? This will require more math or dynamic branching.
  5542. #define RUNTIME_SCANLINES_HORIZ_FILTER_COLORSPACE
  5543. // Specify the tilt at runtime? This makes things about 3% slower.
  5544. #define RUNTIME_GEOMETRY_TILT
  5545. // Specify the geometry mode at runtime?
  5546. #define RUNTIME_GEOMETRY_MODE
  5547. // Specify the phosphor mask type (aperture grille, slot mask, shadow mask) and
  5548. // mode (Lanczos-resize, hardware resize, or tile 1:1) at runtime, even without
  5549. // dynamic branches? This is cheap if mask_resize_viewport_scale is small.
  5550. #define FORCE_RUNTIME_PHOSPHOR_MASK_MODE_TYPE_SELECT
  5551. // PHOSPHOR MASK:
  5552. // Manually resize the phosphor mask for best results (slower)? Disabling this
  5553. // removes the option to do so, but it may be faster without dynamic branches.
  5554. #define PHOSPHOR_MASK_MANUALLY_RESIZE
  5555. // If we sinc-resize the mask, should we Lanczos-window it (slower but better)?
  5556. #define PHOSPHOR_MASK_RESIZE_LANCZOS_WINDOW
  5557. // Larger blurs are expensive, but we need them to blur larger triads. We can
  5558. // detect the right blur if the triad size is static or our profile allows
  5559. // dynamic branches, but otherwise we use the largest blur the user indicates
  5560. // they might need:
  5561. #define PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_3_PIXELS
  5562. //#define PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_6_PIXELS
  5563. //#define PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_9_PIXELS
  5564. //#define PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_12_PIXELS
  5565. // Here's a helpful chart:
  5566. // MaxTriadSize BlurSize MinTriadCountsByResolution
  5567. // 3.0 9.0 480/640/960/1920 triads at 1080p/1440p/2160p/4320p, 4:3 aspect
  5568. // 6.0 17.0 240/320/480/960 triads at 1080p/1440p/2160p/4320p, 4:3 aspect
  5569. // 9.0 25.0 160/213/320/640 triads at 1080p/1440p/2160p/4320p, 4:3 aspect
  5570. // 12.0 31.0 120/160/240/480 triads at 1080p/1440p/2160p/4320p, 4:3 aspect
  5571. // 18.0 43.0 80/107/160/320 triads at 1080p/1440p/2160p/4320p, 4:3 aspect
  5572. /////////////////////////////// USER PARAMETERS //////////////////////////////
  5573. // Note: Many of these static parameters are overridden by runtime shader
  5574. // parameters when those are enabled. However, many others are static codepath
  5575. // options that were cleaner or more convert to code as static constants.
  5576. // GAMMA:
  5577. static const float crt_gamma_static = 2.5; // range [1, 5]
  5578. static const float lcd_gamma_static = 2.2; // range [1, 5]
  5579. // LEVELS MANAGEMENT:
  5580. // Control the final multiplicative image contrast:
  5581. static const float levels_contrast_static = 1.0; // range [0, 4)
  5582. // We auto-dim to avoid clipping between passes and restore brightness
  5583. // later. Control the dim factor here: Lower values clip less but crush
  5584. // blacks more (static only for now).
  5585. static const float levels_autodim_temp = 0.5; // range (0, 1] default is 0.5 but that was unnecessarily dark for me, so I set it to 1.0
  5586. // HALATION/DIFFUSION/BLOOM:
  5587. // Halation weight: How much energy should be lost to electrons bounding
  5588. // around under the CRT glass and exciting random phosphors?
  5589. static const float halation_weight_static = 0.0; // range [0, 1]
  5590. // Refractive diffusion weight: How much light should spread/diffuse from
  5591. // refracting through the CRT glass?
  5592. static const float diffusion_weight_static = 0.075; // range [0, 1]
  5593. // Underestimate brightness: Bright areas bloom more, but we can base the
  5594. // bloom brightpass on a lower brightness to sharpen phosphors, or a higher
  5595. // brightness to soften them. Low values clip, but >= 0.8 looks okay.
  5596. static const float bloom_underestimate_levels_static = 0.8; // range [0, 5]
  5597. // Blur all colors more than necessary for a softer phosphor bloom?
  5598. static const float bloom_excess_static = 0.0; // range [0, 1]
  5599. // The BLOOM_APPROX pass approximates a phosphor blur early on with a small
  5600. // blurred resize of the input (convergence offsets are applied as well).
  5601. // There are three filter options (static option only for now):
  5602. // 0.) Bilinear resize: A fast, close approximation to a 4x4 resize
  5603. // if min_allowed_viewport_triads and the BLOOM_APPROX resolution are sane
  5604. // and beam_max_sigma is low.
  5605. // 1.) 3x3 resize blur: Medium speed, soft/smeared from bilinear blurring,
  5606. // always uses a static sigma regardless of beam_max_sigma or
  5607. // mask_num_triads_desired.
  5608. // 2.) True 4x4 Gaussian resize: Slowest, technically correct.
  5609. // These options are more pronounced for the fast, unbloomed shader version.
  5610. #ifndef RADEON_FIX
  5611. static const float bloom_approx_filter_static = 2.0;
  5612. #else
  5613. static const float bloom_approx_filter_static = 1.0;
  5614. #endif
  5615. // ELECTRON BEAM SCANLINE DISTRIBUTION:
  5616. // How many scanlines should contribute light to each pixel? Using more
  5617. // scanlines is slower (especially for a generalized Gaussian) but less
  5618. // distorted with larger beam sigmas (especially for a pure Gaussian). The
  5619. // max_beam_sigma at which the closest unused weight is guaranteed <
  5620. // 1.0/255.0 (for a 3x antialiased pure Gaussian) is:
  5621. // 2 scanlines: max_beam_sigma = 0.2089; distortions begin ~0.34; 141.7 FPS pure, 131.9 FPS generalized
  5622. // 3 scanlines, max_beam_sigma = 0.3879; distortions begin ~0.52; 137.5 FPS pure; 123.8 FPS generalized
  5623. // 4 scanlines, max_beam_sigma = 0.5723; distortions begin ~0.70; 134.7 FPS pure; 117.2 FPS generalized
  5624. // 5 scanlines, max_beam_sigma = 0.7591; distortions begin ~0.89; 131.6 FPS pure; 112.1 FPS generalized
  5625. // 6 scanlines, max_beam_sigma = 0.9483; distortions begin ~1.08; 127.9 FPS pure; 105.6 FPS generalized
  5626. static const float beam_num_scanlines = 3.0; // range [2, 6]
  5627. // A generalized Gaussian beam varies shape with color too, now just width.
  5628. // It's slower but more flexible (static option only for now).
  5629. static const bool beam_generalized_gaussian = true;
  5630. // What kind of scanline antialiasing do you want?
  5631. // 0: Sample weights at 1x; 1: Sample weights at 3x; 2: Compute an integral
  5632. // Integrals are slow (especially for generalized Gaussians) and rarely any
  5633. // better than 3x antialiasing (static option only for now).
  5634. static const float beam_antialias_level = 1.0; // range [0, 2]
  5635. // Min/max standard deviations for scanline beams: Higher values widen and
  5636. // soften scanlines. Depending on other options, low min sigmas can alias.
  5637. static const float beam_min_sigma_static = 0.02; // range (0, 1]
  5638. static const float beam_max_sigma_static = 0.3; // range (0, 1]
  5639. // Beam width varies as a function of color: A power function (0) is more
  5640. // configurable, but a spherical function (1) gives the widest beam
  5641. // variability without aliasing (static option only for now).
  5642. static const float beam_spot_shape_function = 0.0;
  5643. // Spot shape power: Powers <= 1 give smoother spot shapes but lower
  5644. // sharpness. Powers >= 1.0 are awful unless mix/max sigmas are close.
  5645. static const float beam_spot_power_static = 1.0/3.0; // range (0, 16]
  5646. // Generalized Gaussian max shape parameters: Higher values give flatter
  5647. // scanline plateaus and steeper dropoffs, simultaneously widening and
  5648. // sharpening scanlines at the cost of aliasing. 2.0 is pure Gaussian, and
  5649. // values > ~40.0 cause artifacts with integrals.
  5650. static const float beam_min_shape_static = 2.0; // range [2, 32]
  5651. static const float beam_max_shape_static = 4.0; // range [2, 32]
  5652. // Generalized Gaussian shape power: Affects how quickly the distribution
  5653. // changes shape from Gaussian to steep/plateaued as color increases from 0
  5654. // to 1.0. Higher powers appear softer for most colors, and lower powers
  5655. // appear sharper for most colors.
  5656. static const float beam_shape_power_static = 1.0/4.0; // range (0, 16]
  5657. // What filter should be used to sample scanlines horizontally?
  5658. // 0: Quilez (fast), 1: Gaussian (configurable), 2: Lanczos2 (sharp)
  5659. static const float beam_horiz_filter_static = 0.0;
  5660. // Standard deviation for horizontal Gaussian resampling:
  5661. static const float beam_horiz_sigma_static = 0.35; // range (0, 2/3]
  5662. // Do horizontal scanline sampling in linear RGB (correct light mixing),
  5663. // gamma-encoded RGB (darker, hard spot shape, may better match bandwidth-
  5664. // limiting circuitry in some CRT's), or a weighted avg.?
  5665. static const float beam_horiz_linear_rgb_weight_static = 1.0; // range [0, 1]
  5666. // Simulate scanline misconvergence? This needs 3x horizontal texture
  5667. // samples and 3x texture samples of BLOOM_APPROX and HALATION_BLUR in
  5668. // later passes (static option only for now).
  5669. static const bool beam_misconvergence = true;
  5670. // Convergence offsets in x/y directions for R/G/B scanline beams in units
  5671. // of scanlines. Positive offsets go right/down; ranges [-2, 2]
  5672. static const float2 convergence_offsets_r_static = float2(0.1, 0.2);
  5673. static const float2 convergence_offsets_g_static = float2(0.3, 0.4);
  5674. static const float2 convergence_offsets_b_static = float2(0.5, 0.6);
  5675. // Detect interlacing (static option only for now)?
  5676. static const bool interlace_detect = true;
  5677. // Assume 1080-line sources are interlaced?
  5678. static const bool interlace_1080i_static = false;
  5679. // For interlaced sources, assume TFF (top-field first) or BFF order?
  5680. // (Whether this matters depends on the nature of the interlaced input.)
  5681. static const bool interlace_bff_static = false;
  5682. // ANTIALIASING:
  5683. // What AA level do you want for curvature/overscan/subpixels? Options:
  5684. // 0x (none), 1x (sample subpixels), 4x, 5x, 6x, 7x, 8x, 12x, 16x, 20x, 24x
  5685. // (Static option only for now)
  5686. static const float aa_level = 12.0; // range [0, 24]
  5687. // What antialiasing filter do you want (static option only)? Options:
  5688. // 0: Box (separable), 1: Box (cylindrical),
  5689. // 2: Tent (separable), 3: Tent (cylindrical),
  5690. // 4: Gaussian (separable), 5: Gaussian (cylindrical),
  5691. // 6: Cubic* (separable), 7: Cubic* (cylindrical, poor)
  5692. // 8: Lanczos Sinc (separable), 9: Lanczos Jinc (cylindrical, poor)
  5693. // * = Especially slow with RUNTIME_ANTIALIAS_WEIGHTS
  5694. static const float aa_filter = 6.0; // range [0, 9]
  5695. // Flip the sample grid on odd/even frames (static option only for now)?
  5696. static const bool aa_temporal = false;
  5697. // Use RGB subpixel offsets for antialiasing? The pixel is at green, and
  5698. // the blue offset is the negative r offset; range [0, 0.5]
  5699. static const float2 aa_subpixel_r_offset_static = float2(-1.0/3.0, 0.0);//float2(0.0);
  5700. // Cubics: See http://www.imagemagick.org/Usage/filter/#mitchell
  5701. // 1.) "Keys cubics" with B = 1 - 2C are considered the highest quality.
  5702. // 2.) C = 0.5 (default) is Catmull-Rom; higher C's apply sharpening.
  5703. // 3.) C = 1.0/3.0 is the Mitchell-Netravali filter.
  5704. // 4.) C = 0.0 is a soft spline filter.
  5705. static const float aa_cubic_c_static = 0.5; // range [0, 4]
  5706. // Standard deviation for Gaussian antialiasing: Try 0.5/aa_pixel_diameter.
  5707. static const float aa_gauss_sigma_static = 0.5; // range [0.0625, 1.0]
  5708. // PHOSPHOR MASK:
  5709. // Mask type: 0 = aperture grille, 1 = slot mask, 2 = EDP shadow mask
  5710. static const float mask_type_static = 1.0; // range [0, 2]
  5711. // We can sample the mask three ways. Pick 2/3 from: Pretty/Fast/Flexible.
  5712. // 0.) Sinc-resize to the desired dot pitch manually (pretty/slow/flexible).
  5713. // This requires PHOSPHOR_MASK_MANUALLY_RESIZE to be #defined.
  5714. // 1.) Hardware-resize to the desired dot pitch (ugly/fast/flexible). This
  5715. // is halfway decent with LUT mipmapping but atrocious without it.
  5716. // 2.) Tile it without resizing at a 1:1 texel:pixel ratio for flat coords
  5717. // (pretty/fast/inflexible). Each input LUT has a fixed dot pitch.
  5718. // This mode reuses the same masks, so triads will be enormous unless
  5719. // you change the mask LUT filenames in your .cgp file.
  5720. static const float mask_sample_mode_static = 0.0; // range [0, 2]
  5721. // Prefer setting the triad size (0.0) or number on the screen (1.0)?
  5722. // If RUNTIME_PHOSPHOR_BLOOM_SIGMA isn't #defined, the specified triad size
  5723. // will always be used to calculate the full bloom sigma statically.
  5724. static const float mask_specify_num_triads_static = 0.0; // range [0, 1]
  5725. // Specify the phosphor triad size, in pixels. Each tile (usually with 8
  5726. // triads) will be rounded to the nearest integer tile size and clamped to
  5727. // obey minimum size constraints (imposed to reduce downsize taps) and
  5728. // maximum size constraints (imposed to have a sane MASK_RESIZE FBO size).
  5729. // To increase the size limit, double the viewport-relative scales for the
  5730. // two MASK_RESIZE passes in crt-royale.cgp and user-cgp-contants.h.
  5731. // range [1, mask_texture_small_size/mask_triads_per_tile]
  5732. static const float mask_triad_size_desired_static = 24.0 / 8.0;
  5733. // If mask_specify_num_triads is 1.0/true, we'll go by this instead (the
  5734. // final size will be rounded and constrained as above); default 480.0
  5735. static const float mask_num_triads_desired_static = 480.0;
  5736. // How many lobes should the sinc/Lanczos resizer use? More lobes require
  5737. // more samples and avoid moire a bit better, but some is unavoidable
  5738. // depending on the destination size (static option for now).
  5739. static const float mask_sinc_lobes = 3.0; // range [2, 4]
  5740. // The mask is resized using a variable number of taps in each dimension,
  5741. // but some Cg profiles always fetch a constant number of taps no matter
  5742. // what (no dynamic branching). We can limit the maximum number of taps if
  5743. // we statically limit the minimum phosphor triad size. Larger values are
  5744. // faster, but the limit IS enforced (static option only, forever);
  5745. // range [1, mask_texture_small_size/mask_triads_per_tile]
  5746. // TODO: Make this 1.0 and compensate with smarter sampling!
  5747. static const float mask_min_allowed_triad_size = 2.0;
  5748. // GEOMETRY:
  5749. // Geometry mode:
  5750. // 0: Off (default), 1: Spherical mapping (like cgwg's),
  5751. // 2: Alt. spherical mapping (more bulbous), 3: Cylindrical/Trinitron
  5752. static const float geom_mode_static = 0.0; // range [0, 3]
  5753. // Radius of curvature: Measured in units of your viewport's diagonal size.
  5754. static const float geom_radius_static = 2.0; // range [1/(2*pi), 1024]
  5755. // View dist is the distance from the player to their physical screen, in
  5756. // units of the viewport's diagonal size. It controls the field of view.
  5757. static const float geom_view_dist_static = 2.0; // range [0.5, 1024]
  5758. // Tilt angle in radians (clockwise around up and right vectors):
  5759. static const float2 geom_tilt_angle_static = float2(0.0, 0.0); // range [-pi, pi]
  5760. // Aspect ratio: When the true viewport size is unknown, this value is used
  5761. // to help convert between the phosphor triad size and count, along with
  5762. // the mask_resize_viewport_scale constant from user-cgp-constants.h. Set
  5763. // this equal to Retroarch's display aspect ratio (DAR) for best results;
  5764. // range [1, geom_max_aspect_ratio from user-cgp-constants.h];
  5765. // default (256/224)*(54/47) = 1.313069909 (see below)
  5766. static const float geom_aspect_ratio_static = 1.313069909;
  5767. // Before getting into overscan, here's some general aspect ratio info:
  5768. // - DAR = display aspect ratio = SAR * PAR; as in your Retroarch setting
  5769. // - SAR = storage aspect ratio = DAR / PAR; square pixel emulator frame AR
  5770. // - PAR = pixel aspect ratio = DAR / SAR; holds regardless of cropping
  5771. // Geometry processing has to "undo" the screen-space 2D DAR to calculate
  5772. // 3D view vectors, then reapplies the aspect ratio to the simulated CRT in
  5773. // uv-space. To ensure the source SAR is intended for a ~4:3 DAR, either:
  5774. // a.) Enable Retroarch's "Crop Overscan"
  5775. // b.) Readd horizontal padding: Set overscan to e.g. N*(1.0, 240.0/224.0)
  5776. // Real consoles use horizontal black padding in the signal, but emulators
  5777. // often crop this without cropping the vertical padding; a 256x224 [S]NES
  5778. // frame (8:7 SAR) is intended for a ~4:3 DAR, but a 256x240 frame is not.
  5779. // The correct [S]NES PAR is 54:47, found by blargg and NewRisingSun:
  5780. // http://board.zsnes.com/phpBB3/viewtopic.php?f=22&t=11928&start=50
  5781. // http://forums.nesdev.com/viewtopic.php?p=24815#p24815
  5782. // For flat output, it's okay to set DAR = [existing] SAR * [correct] PAR
  5783. // without doing a. or b., but horizontal image borders will be tighter
  5784. // than vertical ones, messing up curvature and overscan. Fixing the
  5785. // padding first corrects this.
  5786. // Overscan: Amount to "zoom in" before cropping. You can zoom uniformly
  5787. // or adjust x/y independently to e.g. readd horizontal padding, as noted
  5788. // above: Values < 1.0 zoom out; range (0, inf)
  5789. static const float2 geom_overscan_static = float2(1.0, 1.0);// * 1.005 * (1.0, 240/224.0)
  5790. // Compute a proper pixel-space to texture-space matrix even without ddx()/
  5791. // ddy()? This is ~8.5% slower but improves antialiasing/subpixel filtering
  5792. // with strong curvature (static option only for now).
  5793. static const bool geom_force_correct_tangent_matrix = true;
  5794. // BORDERS:
  5795. // Rounded border size in texture uv coords:
  5796. static const float border_size_static = 0.015; // range [0, 0.5]
  5797. // Border darkness: Moderate values darken the border smoothly, and high
  5798. // values make the image very dark just inside the border:
  5799. static const float border_darkness_static = 2.0; // range [0, inf)
  5800. // Border compression: High numbers compress border transitions, narrowing
  5801. // the dark border area.
  5802. static const float border_compress_static = 2.5; // range [1, inf)
  5803. #endif // USER_SETTINGS_H
  5804. //////////////////////////// END USER-SETTINGS //////////////////////////
  5805. //#include "derived-settings-and-constants.h"
  5806. //////////////////// BEGIN DERIVED-SETTINGS-AND-CONSTANTS ////////////////////
  5807. #ifndef DERIVED_SETTINGS_AND_CONSTANTS_H
  5808. #define DERIVED_SETTINGS_AND_CONSTANTS_H
  5809. ///////////////////////////// GPL LICENSE NOTICE /////////////////////////////
  5810. // crt-royale: A full-featured CRT shader, with cheese.
  5811. // Copyright (C) 2014 TroggleMonkey <trogglemonkey@gmx.com>
  5812. //
  5813. // This program is free software; you can redistribute it and/or modify it
  5814. // under the terms of the GNU General Public License as published by the Free
  5815. // Software Foundation; either version 2 of the License, or any later version.
  5816. //
  5817. // This program is distributed in the hope that it will be useful, but WITHOUT
  5818. // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  5819. // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  5820. // more details.
  5821. //
  5822. // You should have received a copy of the GNU General Public License along with
  5823. // this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  5824. // Place, Suite 330, Boston, MA 02111-1307 USA
  5825. ///////////////////////////////// DESCRIPTION ////////////////////////////////
  5826. // These macros and constants can be used across the whole codebase.
  5827. // Unlike the values in user-settings.cgh, end users shouldn't modify these.
  5828. /////////////////////////////// BEGIN INCLUDES ///////////////////////////////
  5829. //#include "../user-settings.h"
  5830. ///////////////////////////// BEGIN USER-SETTINGS ////////////////////////////
  5831. #ifndef USER_SETTINGS_H
  5832. #define USER_SETTINGS_H
  5833. ///////////////////////////// DRIVER CAPABILITIES ////////////////////////////
  5834. // The Cg compiler uses different "profiles" with different capabilities.
  5835. // This shader requires a Cg compilation profile >= arbfp1, but a few options
  5836. // require higher profiles like fp30 or fp40. The shader can't detect profile
  5837. // or driver capabilities, so instead you must comment or uncomment the lines
  5838. // below with "//" before "#define." Disable an option if you get compilation
  5839. // errors resembling those listed. Generally speaking, all of these options
  5840. // will run on nVidia cards, but only DRIVERS_ALLOW_TEX2DBIAS (if that) is
  5841. // likely to run on ATI/AMD, due to the Cg compiler's profile limitations.
  5842. // Derivatives: Unsupported on fp20, ps_1_1, ps_1_2, ps_1_3, and arbfp1.
  5843. // Among other things, derivatives help us fix anisotropic filtering artifacts
  5844. // with curved manually tiled phosphor mask coords. Related errors:
  5845. // error C3004: function "float2 ddx(float2);" not supported in this profile
  5846. // error C3004: function "float2 ddy(float2);" not supported in this profile
  5847. //#define DRIVERS_ALLOW_DERIVATIVES
  5848. // Fine derivatives: Unsupported on older ATI cards.
  5849. // Fine derivatives enable 2x2 fragment block communication, letting us perform
  5850. // fast single-pass blur operations. If your card uses coarse derivatives and
  5851. // these are enabled, blurs could look broken. Derivatives are a prerequisite.
  5852. #ifdef DRIVERS_ALLOW_DERIVATIVES
  5853. #define DRIVERS_ALLOW_FINE_DERIVATIVES
  5854. #endif
  5855. // Dynamic looping: Requires an fp30 or newer profile.
  5856. // This makes phosphor mask resampling faster in some cases. Related errors:
  5857. // error C5013: profile does not support "for" statements and "for" could not
  5858. // be unrolled
  5859. //#define DRIVERS_ALLOW_DYNAMIC_BRANCHES
  5860. // Without DRIVERS_ALLOW_DYNAMIC_BRANCHES, we need to use unrollable loops.
  5861. // Using one static loop avoids overhead if the user is right, but if the user
  5862. // is wrong (loops are allowed), breaking a loop into if-blocked pieces with a
  5863. // binary search can potentially save some iterations. However, it may fail:
  5864. // error C6001: Temporary register limit of 32 exceeded; 35 registers
  5865. // needed to compile program
  5866. //#define ACCOMODATE_POSSIBLE_DYNAMIC_LOOPS
  5867. // tex2Dlod: Requires an fp40 or newer profile. This can be used to disable
  5868. // anisotropic filtering, thereby fixing related artifacts. Related errors:
  5869. // error C3004: function "float4 tex2Dlod(sampler2D, float4);" not supported in
  5870. // this profile
  5871. //#define DRIVERS_ALLOW_TEX2DLOD
  5872. // tex2Dbias: Requires an fp30 or newer profile. This can be used to alleviate
  5873. // artifacts from anisotropic filtering and mipmapping. Related errors:
  5874. // error C3004: function "float4 tex2Dbias(sampler2D, float4);" not supported
  5875. // in this profile
  5876. //#define DRIVERS_ALLOW_TEX2DBIAS
  5877. // Integrated graphics compatibility: Integrated graphics like Intel HD 4000
  5878. // impose stricter limitations on register counts and instructions. Enable
  5879. // INTEGRATED_GRAPHICS_COMPATIBILITY_MODE if you still see error C6001 or:
  5880. // error C6002: Instruction limit of 1024 exceeded: 1523 instructions needed
  5881. // to compile program.
  5882. // Enabling integrated graphics compatibility mode will automatically disable:
  5883. // 1.) PHOSPHOR_MASK_MANUALLY_RESIZE: The phosphor mask will be softer.
  5884. // (This may be reenabled in a later release.)
  5885. // 2.) RUNTIME_GEOMETRY_MODE
  5886. // 3.) The high-quality 4x4 Gaussian resize for the bloom approximation
  5887. //#define INTEGRATED_GRAPHICS_COMPATIBILITY_MODE
  5888. //////////////////////////// USER CODEPATH OPTIONS ///////////////////////////
  5889. // To disable a #define option, turn its line into a comment with "//."
  5890. // RUNTIME VS. COMPILE-TIME OPTIONS (Major Performance Implications):
  5891. // Enable runtime shader parameters in the Retroarch (etc.) GUI? They override
  5892. // many of the options in this file and allow real-time tuning, but many of
  5893. // them are slower. Disabling them and using this text file will boost FPS.
  5894. #define RUNTIME_SHADER_PARAMS_ENABLE
  5895. // Specify the phosphor bloom sigma at runtime? This option is 10% slower, but
  5896. // it's the only way to do a wide-enough full bloom with a runtime dot pitch.
  5897. #define RUNTIME_PHOSPHOR_BLOOM_SIGMA
  5898. // Specify antialiasing weight parameters at runtime? (Costs ~20% with cubics)
  5899. #define RUNTIME_ANTIALIAS_WEIGHTS
  5900. // Specify subpixel offsets at runtime? (WARNING: EXTREMELY EXPENSIVE!)
  5901. //#define RUNTIME_ANTIALIAS_SUBPIXEL_OFFSETS
  5902. // Make beam_horiz_filter and beam_horiz_linear_rgb_weight into runtime shader
  5903. // parameters? This will require more math or dynamic branching.
  5904. #define RUNTIME_SCANLINES_HORIZ_FILTER_COLORSPACE
  5905. // Specify the tilt at runtime? This makes things about 3% slower.
  5906. #define RUNTIME_GEOMETRY_TILT
  5907. // Specify the geometry mode at runtime?
  5908. #define RUNTIME_GEOMETRY_MODE
  5909. // Specify the phosphor mask type (aperture grille, slot mask, shadow mask) and
  5910. // mode (Lanczos-resize, hardware resize, or tile 1:1) at runtime, even without
  5911. // dynamic branches? This is cheap if mask_resize_viewport_scale is small.
  5912. #define FORCE_RUNTIME_PHOSPHOR_MASK_MODE_TYPE_SELECT
  5913. // PHOSPHOR MASK:
  5914. // Manually resize the phosphor mask for best results (slower)? Disabling this
  5915. // removes the option to do so, but it may be faster without dynamic branches.
  5916. #define PHOSPHOR_MASK_MANUALLY_RESIZE
  5917. // If we sinc-resize the mask, should we Lanczos-window it (slower but better)?
  5918. #define PHOSPHOR_MASK_RESIZE_LANCZOS_WINDOW
  5919. // Larger blurs are expensive, but we need them to blur larger triads. We can
  5920. // detect the right blur if the triad size is static or our profile allows
  5921. // dynamic branches, but otherwise we use the largest blur the user indicates
  5922. // they might need:
  5923. #define PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_3_PIXELS
  5924. //#define PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_6_PIXELS
  5925. //#define PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_9_PIXELS
  5926. //#define PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_12_PIXELS
  5927. // Here's a helpful chart:
  5928. // MaxTriadSize BlurSize MinTriadCountsByResolution
  5929. // 3.0 9.0 480/640/960/1920 triads at 1080p/1440p/2160p/4320p, 4:3 aspect
  5930. // 6.0 17.0 240/320/480/960 triads at 1080p/1440p/2160p/4320p, 4:3 aspect
  5931. // 9.0 25.0 160/213/320/640 triads at 1080p/1440p/2160p/4320p, 4:3 aspect
  5932. // 12.0 31.0 120/160/240/480 triads at 1080p/1440p/2160p/4320p, 4:3 aspect
  5933. // 18.0 43.0 80/107/160/320 triads at 1080p/1440p/2160p/4320p, 4:3 aspect
  5934. /////////////////////////////// USER PARAMETERS //////////////////////////////
  5935. // Note: Many of these static parameters are overridden by runtime shader
  5936. // parameters when those are enabled. However, many others are static codepath
  5937. // options that were cleaner or more convert to code as static constants.
  5938. // GAMMA:
  5939. static const float crt_gamma_static = 2.5; // range [1, 5]
  5940. static const float lcd_gamma_static = 2.2; // range [1, 5]
  5941. // LEVELS MANAGEMENT:
  5942. // Control the final multiplicative image contrast:
  5943. static const float levels_contrast_static = 1.0; // range [0, 4)
  5944. // We auto-dim to avoid clipping between passes and restore brightness
  5945. // later. Control the dim factor here: Lower values clip less but crush
  5946. // blacks more (static only for now).
  5947. static const float levels_autodim_temp = 0.5; // range (0, 1] default is 0.5 but that was unnecessarily dark for me, so I set it to 1.0
  5948. // HALATION/DIFFUSION/BLOOM:
  5949. // Halation weight: How much energy should be lost to electrons bounding
  5950. // around under the CRT glass and exciting random phosphors?
  5951. static const float halation_weight_static = 0.0; // range [0, 1]
  5952. // Refractive diffusion weight: How much light should spread/diffuse from
  5953. // refracting through the CRT glass?
  5954. static const float diffusion_weight_static = 0.075; // range [0, 1]
  5955. // Underestimate brightness: Bright areas bloom more, but we can base the
  5956. // bloom brightpass on a lower brightness to sharpen phosphors, or a higher
  5957. // brightness to soften them. Low values clip, but >= 0.8 looks okay.
  5958. static const float bloom_underestimate_levels_static = 0.8; // range [0, 5]
  5959. // Blur all colors more than necessary for a softer phosphor bloom?
  5960. static const float bloom_excess_static = 0.0; // range [0, 1]
  5961. // The BLOOM_APPROX pass approximates a phosphor blur early on with a small
  5962. // blurred resize of the input (convergence offsets are applied as well).
  5963. // There are three filter options (static option only for now):
  5964. // 0.) Bilinear resize: A fast, close approximation to a 4x4 resize
  5965. // if min_allowed_viewport_triads and the BLOOM_APPROX resolution are sane
  5966. // and beam_max_sigma is low.
  5967. // 1.) 3x3 resize blur: Medium speed, soft/smeared from bilinear blurring,
  5968. // always uses a static sigma regardless of beam_max_sigma or
  5969. // mask_num_triads_desired.
  5970. // 2.) True 4x4 Gaussian resize: Slowest, technically correct.
  5971. // These options are more pronounced for the fast, unbloomed shader version.
  5972. #ifndef RADEON_FIX
  5973. static const float bloom_approx_filter_static = 2.0;
  5974. #else
  5975. static const float bloom_approx_filter_static = 1.0;
  5976. #endif
  5977. // ELECTRON BEAM SCANLINE DISTRIBUTION:
  5978. // How many scanlines should contribute light to each pixel? Using more
  5979. // scanlines is slower (especially for a generalized Gaussian) but less
  5980. // distorted with larger beam sigmas (especially for a pure Gaussian). The
  5981. // max_beam_sigma at which the closest unused weight is guaranteed <
  5982. // 1.0/255.0 (for a 3x antialiased pure Gaussian) is:
  5983. // 2 scanlines: max_beam_sigma = 0.2089; distortions begin ~0.34; 141.7 FPS pure, 131.9 FPS generalized
  5984. // 3 scanlines, max_beam_sigma = 0.3879; distortions begin ~0.52; 137.5 FPS pure; 123.8 FPS generalized
  5985. // 4 scanlines, max_beam_sigma = 0.5723; distortions begin ~0.70; 134.7 FPS pure; 117.2 FPS generalized
  5986. // 5 scanlines, max_beam_sigma = 0.7591; distortions begin ~0.89; 131.6 FPS pure; 112.1 FPS generalized
  5987. // 6 scanlines, max_beam_sigma = 0.9483; distortions begin ~1.08; 127.9 FPS pure; 105.6 FPS generalized
  5988. static const float beam_num_scanlines = 3.0; // range [2, 6]
  5989. // A generalized Gaussian beam varies shape with color too, now just width.
  5990. // It's slower but more flexible (static option only for now).
  5991. static const bool beam_generalized_gaussian = true;
  5992. // What kind of scanline antialiasing do you want?
  5993. // 0: Sample weights at 1x; 1: Sample weights at 3x; 2: Compute an integral
  5994. // Integrals are slow (especially for generalized Gaussians) and rarely any
  5995. // better than 3x antialiasing (static option only for now).
  5996. static const float beam_antialias_level = 1.0; // range [0, 2]
  5997. // Min/max standard deviations for scanline beams: Higher values widen and
  5998. // soften scanlines. Depending on other options, low min sigmas can alias.
  5999. static const float beam_min_sigma_static = 0.02; // range (0, 1]
  6000. static const float beam_max_sigma_static = 0.3; // range (0, 1]
  6001. // Beam width varies as a function of color: A power function (0) is more
  6002. // configurable, but a spherical function (1) gives the widest beam
  6003. // variability without aliasing (static option only for now).
  6004. static const float beam_spot_shape_function = 0.0;
  6005. // Spot shape power: Powers <= 1 give smoother spot shapes but lower
  6006. // sharpness. Powers >= 1.0 are awful unless mix/max sigmas are close.
  6007. static const float beam_spot_power_static = 1.0/3.0; // range (0, 16]
  6008. // Generalized Gaussian max shape parameters: Higher values give flatter
  6009. // scanline plateaus and steeper dropoffs, simultaneously widening and
  6010. // sharpening scanlines at the cost of aliasing. 2.0 is pure Gaussian, and
  6011. // values > ~40.0 cause artifacts with integrals.
  6012. static const float beam_min_shape_static = 2.0; // range [2, 32]
  6013. static const float beam_max_shape_static = 4.0; // range [2, 32]
  6014. // Generalized Gaussian shape power: Affects how quickly the distribution
  6015. // changes shape from Gaussian to steep/plateaued as color increases from 0
  6016. // to 1.0. Higher powers appear softer for most colors, and lower powers
  6017. // appear sharper for most colors.
  6018. static const float beam_shape_power_static = 1.0/4.0; // range (0, 16]
  6019. // What filter should be used to sample scanlines horizontally?
  6020. // 0: Quilez (fast), 1: Gaussian (configurable), 2: Lanczos2 (sharp)
  6021. static const float beam_horiz_filter_static = 0.0;
  6022. // Standard deviation for horizontal Gaussian resampling:
  6023. static const float beam_horiz_sigma_static = 0.35; // range (0, 2/3]
  6024. // Do horizontal scanline sampling in linear RGB (correct light mixing),
  6025. // gamma-encoded RGB (darker, hard spot shape, may better match bandwidth-
  6026. // limiting circuitry in some CRT's), or a weighted avg.?
  6027. static const float beam_horiz_linear_rgb_weight_static = 1.0; // range [0, 1]
  6028. // Simulate scanline misconvergence? This needs 3x horizontal texture
  6029. // samples and 3x texture samples of BLOOM_APPROX and HALATION_BLUR in
  6030. // later passes (static option only for now).
  6031. static const bool beam_misconvergence = true;
  6032. // Convergence offsets in x/y directions for R/G/B scanline beams in units
  6033. // of scanlines. Positive offsets go right/down; ranges [-2, 2]
  6034. static const float2 convergence_offsets_r_static = float2(0.1, 0.2);
  6035. static const float2 convergence_offsets_g_static = float2(0.3, 0.4);
  6036. static const float2 convergence_offsets_b_static = float2(0.5, 0.6);
  6037. // Detect interlacing (static option only for now)?
  6038. static const bool interlace_detect = true;
  6039. // Assume 1080-line sources are interlaced?
  6040. static const bool interlace_1080i_static = false;
  6041. // For interlaced sources, assume TFF (top-field first) or BFF order?
  6042. // (Whether this matters depends on the nature of the interlaced input.)
  6043. static const bool interlace_bff_static = false;
  6044. // ANTIALIASING:
  6045. // What AA level do you want for curvature/overscan/subpixels? Options:
  6046. // 0x (none), 1x (sample subpixels), 4x, 5x, 6x, 7x, 8x, 12x, 16x, 20x, 24x
  6047. // (Static option only for now)
  6048. static const float aa_level = 12.0; // range [0, 24]
  6049. // What antialiasing filter do you want (static option only)? Options:
  6050. // 0: Box (separable), 1: Box (cylindrical),
  6051. // 2: Tent (separable), 3: Tent (cylindrical),
  6052. // 4: Gaussian (separable), 5: Gaussian (cylindrical),
  6053. // 6: Cubic* (separable), 7: Cubic* (cylindrical, poor)
  6054. // 8: Lanczos Sinc (separable), 9: Lanczos Jinc (cylindrical, poor)
  6055. // * = Especially slow with RUNTIME_ANTIALIAS_WEIGHTS
  6056. static const float aa_filter = 6.0; // range [0, 9]
  6057. // Flip the sample grid on odd/even frames (static option only for now)?
  6058. static const bool aa_temporal = false;
  6059. // Use RGB subpixel offsets for antialiasing? The pixel is at green, and
  6060. // the blue offset is the negative r offset; range [0, 0.5]
  6061. static const float2 aa_subpixel_r_offset_static = float2(-1.0/3.0, 0.0);//float2(0.0);
  6062. // Cubics: See http://www.imagemagick.org/Usage/filter/#mitchell
  6063. // 1.) "Keys cubics" with B = 1 - 2C are considered the highest quality.
  6064. // 2.) C = 0.5 (default) is Catmull-Rom; higher C's apply sharpening.
  6065. // 3.) C = 1.0/3.0 is the Mitchell-Netravali filter.
  6066. // 4.) C = 0.0 is a soft spline filter.
  6067. static const float aa_cubic_c_static = 0.5; // range [0, 4]
  6068. // Standard deviation for Gaussian antialiasing: Try 0.5/aa_pixel_diameter.
  6069. static const float aa_gauss_sigma_static = 0.5; // range [0.0625, 1.0]
  6070. // PHOSPHOR MASK:
  6071. // Mask type: 0 = aperture grille, 1 = slot mask, 2 = EDP shadow mask
  6072. static const float mask_type_static = 1.0; // range [0, 2]
  6073. // We can sample the mask three ways. Pick 2/3 from: Pretty/Fast/Flexible.
  6074. // 0.) Sinc-resize to the desired dot pitch manually (pretty/slow/flexible).
  6075. // This requires PHOSPHOR_MASK_MANUALLY_RESIZE to be #defined.
  6076. // 1.) Hardware-resize to the desired dot pitch (ugly/fast/flexible). This
  6077. // is halfway decent with LUT mipmapping but atrocious without it.
  6078. // 2.) Tile it without resizing at a 1:1 texel:pixel ratio for flat coords
  6079. // (pretty/fast/inflexible). Each input LUT has a fixed dot pitch.
  6080. // This mode reuses the same masks, so triads will be enormous unless
  6081. // you change the mask LUT filenames in your .cgp file.
  6082. static const float mask_sample_mode_static = 0.0; // range [0, 2]
  6083. // Prefer setting the triad size (0.0) or number on the screen (1.0)?
  6084. // If RUNTIME_PHOSPHOR_BLOOM_SIGMA isn't #defined, the specified triad size
  6085. // will always be used to calculate the full bloom sigma statically.
  6086. static const float mask_specify_num_triads_static = 0.0; // range [0, 1]
  6087. // Specify the phosphor triad size, in pixels. Each tile (usually with 8
  6088. // triads) will be rounded to the nearest integer tile size and clamped to
  6089. // obey minimum size constraints (imposed to reduce downsize taps) and
  6090. // maximum size constraints (imposed to have a sane MASK_RESIZE FBO size).
  6091. // To increase the size limit, double the viewport-relative scales for the
  6092. // two MASK_RESIZE passes in crt-royale.cgp and user-cgp-contants.h.
  6093. // range [1, mask_texture_small_size/mask_triads_per_tile]
  6094. static const float mask_triad_size_desired_static = 24.0 / 8.0;
  6095. // If mask_specify_num_triads is 1.0/true, we'll go by this instead (the
  6096. // final size will be rounded and constrained as above); default 480.0
  6097. static const float mask_num_triads_desired_static = 480.0;
  6098. // How many lobes should the sinc/Lanczos resizer use? More lobes require
  6099. // more samples and avoid moire a bit better, but some is unavoidable
  6100. // depending on the destination size (static option for now).
  6101. static const float mask_sinc_lobes = 3.0; // range [2, 4]
  6102. // The mask is resized using a variable number of taps in each dimension,
  6103. // but some Cg profiles always fetch a constant number of taps no matter
  6104. // what (no dynamic branching). We can limit the maximum number of taps if
  6105. // we statically limit the minimum phosphor triad size. Larger values are
  6106. // faster, but the limit IS enforced (static option only, forever);
  6107. // range [1, mask_texture_small_size/mask_triads_per_tile]
  6108. // TODO: Make this 1.0 and compensate with smarter sampling!
  6109. static const float mask_min_allowed_triad_size = 2.0;
  6110. // GEOMETRY:
  6111. // Geometry mode:
  6112. // 0: Off (default), 1: Spherical mapping (like cgwg's),
  6113. // 2: Alt. spherical mapping (more bulbous), 3: Cylindrical/Trinitron
  6114. static const float geom_mode_static = 0.0; // range [0, 3]
  6115. // Radius of curvature: Measured in units of your viewport's diagonal size.
  6116. static const float geom_radius_static = 2.0; // range [1/(2*pi), 1024]
  6117. // View dist is the distance from the player to their physical screen, in
  6118. // units of the viewport's diagonal size. It controls the field of view.
  6119. static const float geom_view_dist_static = 2.0; // range [0.5, 1024]
  6120. // Tilt angle in radians (clockwise around up and right vectors):
  6121. static const float2 geom_tilt_angle_static = float2(0.0, 0.0); // range [-pi, pi]
  6122. // Aspect ratio: When the true viewport size is unknown, this value is used
  6123. // to help convert between the phosphor triad size and count, along with
  6124. // the mask_resize_viewport_scale constant from user-cgp-constants.h. Set
  6125. // this equal to Retroarch's display aspect ratio (DAR) for best results;
  6126. // range [1, geom_max_aspect_ratio from user-cgp-constants.h];
  6127. // default (256/224)*(54/47) = 1.313069909 (see below)
  6128. static const float geom_aspect_ratio_static = 1.313069909;
  6129. // Before getting into overscan, here's some general aspect ratio info:
  6130. // - DAR = display aspect ratio = SAR * PAR; as in your Retroarch setting
  6131. // - SAR = storage aspect ratio = DAR / PAR; square pixel emulator frame AR
  6132. // - PAR = pixel aspect ratio = DAR / SAR; holds regardless of cropping
  6133. // Geometry processing has to "undo" the screen-space 2D DAR to calculate
  6134. // 3D view vectors, then reapplies the aspect ratio to the simulated CRT in
  6135. // uv-space. To ensure the source SAR is intended for a ~4:3 DAR, either:
  6136. // a.) Enable Retroarch's "Crop Overscan"
  6137. // b.) Readd horizontal padding: Set overscan to e.g. N*(1.0, 240.0/224.0)
  6138. // Real consoles use horizontal black padding in the signal, but emulators
  6139. // often crop this without cropping the vertical padding; a 256x224 [S]NES
  6140. // frame (8:7 SAR) is intended for a ~4:3 DAR, but a 256x240 frame is not.
  6141. // The correct [S]NES PAR is 54:47, found by blargg and NewRisingSun:
  6142. // http://board.zsnes.com/phpBB3/viewtopic.php?f=22&t=11928&start=50
  6143. // http://forums.nesdev.com/viewtopic.php?p=24815#p24815
  6144. // For flat output, it's okay to set DAR = [existing] SAR * [correct] PAR
  6145. // without doing a. or b., but horizontal image borders will be tighter
  6146. // than vertical ones, messing up curvature and overscan. Fixing the
  6147. // padding first corrects this.
  6148. // Overscan: Amount to "zoom in" before cropping. You can zoom uniformly
  6149. // or adjust x/y independently to e.g. readd horizontal padding, as noted
  6150. // above: Values < 1.0 zoom out; range (0, inf)
  6151. static const float2 geom_overscan_static = float2(1.0, 1.0);// * 1.005 * (1.0, 240/224.0)
  6152. // Compute a proper pixel-space to texture-space matrix even without ddx()/
  6153. // ddy()? This is ~8.5% slower but improves antialiasing/subpixel filtering
  6154. // with strong curvature (static option only for now).
  6155. static const bool geom_force_correct_tangent_matrix = true;
  6156. // BORDERS:
  6157. // Rounded border size in texture uv coords:
  6158. static const float border_size_static = 0.015; // range [0, 0.5]
  6159. // Border darkness: Moderate values darken the border smoothly, and high
  6160. // values make the image very dark just inside the border:
  6161. static const float border_darkness_static = 2.0; // range [0, inf)
  6162. // Border compression: High numbers compress border transitions, narrowing
  6163. // the dark border area.
  6164. static const float border_compress_static = 2.5; // range [1, inf)
  6165. #endif // USER_SETTINGS_H
  6166. ///////////////////////////// END USER-SETTINGS ////////////////////////////
  6167. //#include "user-cgp-constants.h"
  6168. ///////////////////////// BEGIN USER-CGP-CONSTANTS /////////////////////////
  6169. #ifndef USER_CGP_CONSTANTS_H
  6170. #define USER_CGP_CONSTANTS_H
  6171. // IMPORTANT:
  6172. // These constants MUST be set appropriately for the settings in crt-royale.cgp
  6173. // (or whatever related .cgp file you're using). If they aren't, you're likely
  6174. // to get artifacts, the wrong phosphor mask size, etc. I wish these could be
  6175. // set directly in the .cgp file to make things easier, but...they can't.
  6176. // PASS SCALES AND RELATED CONSTANTS:
  6177. // Copy the absolute scale_x for BLOOM_APPROX. There are two major versions of
  6178. // this shader: One does a viewport-scale bloom, and the other skips it. The
  6179. // latter benefits from a higher bloom_approx_scale_x, so save both separately:
  6180. static const float bloom_approx_size_x = 320.0;
  6181. static const float bloom_approx_size_x_for_fake = 400.0;
  6182. // Copy the viewport-relative scales of the phosphor mask resize passes
  6183. // (MASK_RESIZE and the pass immediately preceding it):
  6184. static const float2 mask_resize_viewport_scale = float2(0.0625, 0.0625);
  6185. // Copy the geom_max_aspect_ratio used to calculate the MASK_RESIZE scales, etc.:
  6186. static const float geom_max_aspect_ratio = 4.0/3.0;
  6187. // PHOSPHOR MASK TEXTURE CONSTANTS:
  6188. // Set the following constants to reflect the properties of the phosphor mask
  6189. // texture named in crt-royale.cgp. The shader optionally resizes a mask tile
  6190. // based on user settings, then repeats a single tile until filling the screen.
  6191. // The shader must know the input texture size (default 64x64), and to manually
  6192. // resize, it must also know the horizontal triads per tile (default 8).
  6193. static const float2 mask_texture_small_size = float2(64.0, 64.0);
  6194. static const float2 mask_texture_large_size = float2(512.0, 512.0);
  6195. static const float mask_triads_per_tile = 8.0;
  6196. // We need the average brightness of the phosphor mask to compensate for the
  6197. // dimming it causes. The following four values are roughly correct for the
  6198. // masks included with the shader. Update the value for any LUT texture you
  6199. // change. [Un]comment "#define PHOSPHOR_MASK_GRILLE14" depending on whether
  6200. // the loaded aperture grille uses 14-pixel or 15-pixel stripes (default 15).
  6201. //#define PHOSPHOR_MASK_GRILLE14
  6202. static const float mask_grille14_avg_color = 50.6666666/255.0;
  6203. // TileableLinearApertureGrille14Wide7d33Spacing*.png
  6204. // TileableLinearApertureGrille14Wide10And6Spacing*.png
  6205. static const float mask_grille15_avg_color = 53.0/255.0;
  6206. // TileableLinearApertureGrille15Wide6d33Spacing*.png
  6207. // TileableLinearApertureGrille15Wide8And5d5Spacing*.png
  6208. static const float mask_slot_avg_color = 46.0/255.0;
  6209. // TileableLinearSlotMask15Wide9And4d5Horizontal8VerticalSpacing*.png
  6210. // TileableLinearSlotMaskTall15Wide9And4d5Horizontal9d14VerticalSpacing*.png
  6211. static const float mask_shadow_avg_color = 41.0/255.0;
  6212. // TileableLinearShadowMask*.png
  6213. // TileableLinearShadowMaskEDP*.png
  6214. #ifdef PHOSPHOR_MASK_GRILLE14
  6215. static const float mask_grille_avg_color = mask_grille14_avg_color;
  6216. #else
  6217. static const float mask_grille_avg_color = mask_grille15_avg_color;
  6218. #endif
  6219. #endif // USER_CGP_CONSTANTS_H
  6220. ////////////////////////// END USER-CGP-CONSTANTS //////////////////////////
  6221. //////////////////////////////// END INCLUDES ////////////////////////////////
  6222. /////////////////////////////// FIXED SETTINGS ///////////////////////////////
  6223. // Avoid dividing by zero; using a macro overloads for float, float2, etc.:
  6224. #define FIX_ZERO(c) (max(abs(c), 0.0000152587890625)) // 2^-16
  6225. // Ensure the first pass decodes CRT gamma and the last encodes LCD gamma.
  6226. #ifndef SIMULATE_CRT_ON_LCD
  6227. #define SIMULATE_CRT_ON_LCD
  6228. #endif
  6229. // Manually tiling a manually resized texture creates texture coord derivative
  6230. // discontinuities and confuses anisotropic filtering, causing discolored tile
  6231. // seams in the phosphor mask. Workarounds:
  6232. // a.) Using tex2Dlod disables anisotropic filtering for tiled masks. It's
  6233. // downgraded to tex2Dbias without DRIVERS_ALLOW_TEX2DLOD #defined and
  6234. // disabled without DRIVERS_ALLOW_TEX2DBIAS #defined either.
  6235. // b.) "Tile flat twice" requires drawing two full tiles without border padding
  6236. // to the resized mask FBO, and it's incompatible with same-pass curvature.
  6237. // (Same-pass curvature isn't used but could be in the future...maybe.)
  6238. // c.) "Fix discontinuities" requires derivatives and drawing one tile with
  6239. // border padding to the resized mask FBO, but it works with same-pass
  6240. // curvature. It's disabled without DRIVERS_ALLOW_DERIVATIVES #defined.
  6241. // Precedence: a, then, b, then c (if multiple strategies are #defined).
  6242. #define ANISOTROPIC_TILING_COMPAT_TEX2DLOD // 129.7 FPS, 4x, flat; 101.8 at fullscreen
  6243. #define ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE // 128.1 FPS, 4x, flat; 101.5 at fullscreen
  6244. #define ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES // 124.4 FPS, 4x, flat; 97.4 at fullscreen
  6245. // Also, manually resampling the phosphor mask is slightly blurrier with
  6246. // anisotropic filtering. (Resampling with mipmapping is even worse: It
  6247. // creates artifacts, but only with the fully bloomed shader.) The difference
  6248. // is subtle with small triads, but you can fix it for a small cost.
  6249. //#define ANISOTROPIC_RESAMPLING_COMPAT_TEX2DLOD
  6250. ////////////////////////////// DERIVED SETTINGS //////////////////////////////
  6251. // Intel HD 4000 GPU's can't handle manual mask resizing (for now), setting the
  6252. // geometry mode at runtime, or a 4x4 true Gaussian resize. Disable
  6253. // incompatible settings ASAP. (INTEGRATED_GRAPHICS_COMPATIBILITY_MODE may be
  6254. // #defined by either user-settings.h or a wrapper .cg that #includes the
  6255. // current .cg pass.)
  6256. #ifdef INTEGRATED_GRAPHICS_COMPATIBILITY_MODE
  6257. #ifdef PHOSPHOR_MASK_MANUALLY_RESIZE
  6258. #undef PHOSPHOR_MASK_MANUALLY_RESIZE
  6259. #endif
  6260. #ifdef RUNTIME_GEOMETRY_MODE
  6261. #undef RUNTIME_GEOMETRY_MODE
  6262. #endif
  6263. // Mode 2 (4x4 Gaussian resize) won't work, and mode 1 (3x3 blur) is
  6264. // inferior in most cases, so replace 2.0 with 0.0:
  6265. static const float bloom_approx_filter =
  6266. bloom_approx_filter_static > 1.5 ? 0.0 : bloom_approx_filter_static;
  6267. #else
  6268. static const float bloom_approx_filter = bloom_approx_filter_static;
  6269. #endif
  6270. // Disable slow runtime paths if static parameters are used. Most of these
  6271. // won't be a problem anyway once the params are disabled, but some will.
  6272. #ifndef RUNTIME_SHADER_PARAMS_ENABLE
  6273. #ifdef RUNTIME_PHOSPHOR_BLOOM_SIGMA
  6274. #undef RUNTIME_PHOSPHOR_BLOOM_SIGMA
  6275. #endif
  6276. #ifdef RUNTIME_ANTIALIAS_WEIGHTS
  6277. #undef RUNTIME_ANTIALIAS_WEIGHTS
  6278. #endif
  6279. #ifdef RUNTIME_ANTIALIAS_SUBPIXEL_OFFSETS
  6280. #undef RUNTIME_ANTIALIAS_SUBPIXEL_OFFSETS
  6281. #endif
  6282. #ifdef RUNTIME_SCANLINES_HORIZ_FILTER_COLORSPACE
  6283. #undef RUNTIME_SCANLINES_HORIZ_FILTER_COLORSPACE
  6284. #endif
  6285. #ifdef RUNTIME_GEOMETRY_TILT
  6286. #undef RUNTIME_GEOMETRY_TILT
  6287. #endif
  6288. #ifdef RUNTIME_GEOMETRY_MODE
  6289. #undef RUNTIME_GEOMETRY_MODE
  6290. #endif
  6291. #ifdef FORCE_RUNTIME_PHOSPHOR_MASK_MODE_TYPE_SELECT
  6292. #undef FORCE_RUNTIME_PHOSPHOR_MASK_MODE_TYPE_SELECT
  6293. #endif
  6294. #endif
  6295. // Make tex2Dbias a backup for tex2Dlod for wider compatibility.
  6296. #ifdef ANISOTROPIC_TILING_COMPAT_TEX2DLOD
  6297. #define ANISOTROPIC_TILING_COMPAT_TEX2DBIAS
  6298. #endif
  6299. #ifdef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DLOD
  6300. #define ANISOTROPIC_RESAMPLING_COMPAT_TEX2DBIAS
  6301. #endif
  6302. // Rule out unavailable anisotropic compatibility strategies:
  6303. #ifndef DRIVERS_ALLOW_DERIVATIVES
  6304. #ifdef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
  6305. #undef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
  6306. #endif
  6307. #endif
  6308. #ifndef DRIVERS_ALLOW_TEX2DLOD
  6309. #ifdef ANISOTROPIC_TILING_COMPAT_TEX2DLOD
  6310. #undef ANISOTROPIC_TILING_COMPAT_TEX2DLOD
  6311. #endif
  6312. #ifdef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DLOD
  6313. #undef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DLOD
  6314. #endif
  6315. #ifdef ANTIALIAS_DISABLE_ANISOTROPIC
  6316. #undef ANTIALIAS_DISABLE_ANISOTROPIC
  6317. #endif
  6318. #endif
  6319. #ifndef DRIVERS_ALLOW_TEX2DBIAS
  6320. #ifdef ANISOTROPIC_TILING_COMPAT_TEX2DBIAS
  6321. #undef ANISOTROPIC_TILING_COMPAT_TEX2DBIAS
  6322. #endif
  6323. #ifdef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DBIAS
  6324. #undef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DBIAS
  6325. #endif
  6326. #endif
  6327. // Prioritize anisotropic tiling compatibility strategies by performance and
  6328. // disable unused strategies. This concentrates all the nesting in one place.
  6329. #ifdef ANISOTROPIC_TILING_COMPAT_TEX2DLOD
  6330. #ifdef ANISOTROPIC_TILING_COMPAT_TEX2DBIAS
  6331. #undef ANISOTROPIC_TILING_COMPAT_TEX2DBIAS
  6332. #endif
  6333. #ifdef ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE
  6334. #undef ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE
  6335. #endif
  6336. #ifdef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
  6337. #undef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
  6338. #endif
  6339. #else
  6340. #ifdef ANISOTROPIC_TILING_COMPAT_TEX2DBIAS
  6341. #ifdef ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE
  6342. #undef ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE
  6343. #endif
  6344. #ifdef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
  6345. #undef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
  6346. #endif
  6347. #else
  6348. // ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE is only compatible with
  6349. // flat texture coords in the same pass, but that's all we use.
  6350. #ifdef ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE
  6351. #ifdef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
  6352. #undef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
  6353. #endif
  6354. #endif
  6355. #endif
  6356. #endif
  6357. // The tex2Dlod and tex2Dbias strategies share a lot in common, and we can
  6358. // reduce some #ifdef nesting in the next section by essentially OR'ing them:
  6359. #ifdef ANISOTROPIC_TILING_COMPAT_TEX2DLOD
  6360. #define ANISOTROPIC_TILING_COMPAT_TEX2DLOD_FAMILY
  6361. #endif
  6362. #ifdef ANISOTROPIC_TILING_COMPAT_TEX2DBIAS
  6363. #define ANISOTROPIC_TILING_COMPAT_TEX2DLOD_FAMILY
  6364. #endif
  6365. // Prioritize anisotropic resampling compatibility strategies the same way:
  6366. #ifdef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DLOD
  6367. #ifdef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DBIAS
  6368. #undef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DBIAS
  6369. #endif
  6370. #endif
  6371. /////////////////////// DERIVED PHOSPHOR MASK CONSTANTS //////////////////////
  6372. // If we can use the large mipmapped LUT without mipmapping artifacts, we
  6373. // should: It gives us more options for using fewer samples.
  6374. #ifdef DRIVERS_ALLOW_TEX2DLOD
  6375. #ifdef ANISOTROPIC_RESAMPLING_COMPAT_TEX2DLOD
  6376. // TODO: Take advantage of this!
  6377. #define PHOSPHOR_MASK_RESIZE_MIPMAPPED_LUT
  6378. static const float2 mask_resize_src_lut_size = mask_texture_large_size;
  6379. #else
  6380. static const float2 mask_resize_src_lut_size = mask_texture_small_size;
  6381. #endif
  6382. #else
  6383. static const float2 mask_resize_src_lut_size = mask_texture_small_size;
  6384. #endif
  6385. // tex2D's sampler2D parameter MUST be a uniform global, a uniform input to
  6386. // main_fragment, or a static alias of one of the above. This makes it hard
  6387. // to select the phosphor mask at runtime: We can't even assign to a uniform
  6388. // global in the vertex shader or select a sampler2D in the vertex shader and
  6389. // pass it to the fragment shader (even with explicit TEXUNIT# bindings),
  6390. // because it just gives us the input texture or a black screen. However, we
  6391. // can get around these limitations by calling tex2D three times with different
  6392. // uniform samplers (or resizing the phosphor mask three times altogether).
  6393. // With dynamic branches, we can process only one of these branches on top of
  6394. // quickly discarding fragments we don't need (cgc seems able to overcome
  6395. // limigations around dependent texture fetches inside of branches). Without
  6396. // dynamic branches, we have to process every branch for every fragment...which
  6397. // is slower. Runtime sampling mode selection is slower without dynamic
  6398. // branches as well. Let the user's static #defines decide if it's worth it.
  6399. #ifdef DRIVERS_ALLOW_DYNAMIC_BRANCHES
  6400. #define RUNTIME_PHOSPHOR_MASK_MODE_TYPE_SELECT
  6401. #else
  6402. #ifdef FORCE_RUNTIME_PHOSPHOR_MASK_MODE_TYPE_SELECT
  6403. #define RUNTIME_PHOSPHOR_MASK_MODE_TYPE_SELECT
  6404. #endif
  6405. #endif
  6406. // We need to render some minimum number of tiles in the resize passes.
  6407. // We need at least 1.0 just to repeat a single tile, and we need extra
  6408. // padding beyond that for anisotropic filtering, discontinuitity fixing,
  6409. // antialiasing, same-pass curvature (not currently used), etc. First
  6410. // determine how many border texels and tiles we need, based on how the result
  6411. // will be sampled:
  6412. #ifdef GEOMETRY_EARLY
  6413. static const float max_subpixel_offset = aa_subpixel_r_offset_static.x;
  6414. // Most antialiasing filters have a base radius of 4.0 pixels:
  6415. static const float max_aa_base_pixel_border = 4.0 +
  6416. max_subpixel_offset;
  6417. #else
  6418. static const float max_aa_base_pixel_border = 0.0;
  6419. #endif
  6420. // Anisotropic filtering adds about 0.5 to the pixel border:
  6421. #ifndef ANISOTROPIC_TILING_COMPAT_TEX2DLOD_FAMILY
  6422. static const float max_aniso_pixel_border = max_aa_base_pixel_border + 0.5;
  6423. #else
  6424. static const float max_aniso_pixel_border = max_aa_base_pixel_border;
  6425. #endif
  6426. // Fixing discontinuities adds 1.0 more to the pixel border:
  6427. #ifdef ANISOTROPIC_TILING_COMPAT_FIX_DISCONTINUITIES
  6428. static const float max_tiled_pixel_border = max_aniso_pixel_border + 1.0;
  6429. #else
  6430. static const float max_tiled_pixel_border = max_aniso_pixel_border;
  6431. #endif
  6432. // Convert the pixel border to an integer texel border. Assume same-pass
  6433. // curvature about triples the texel frequency:
  6434. #ifdef GEOMETRY_EARLY
  6435. static const float max_mask_texel_border =
  6436. ceil(max_tiled_pixel_border * 3.0);
  6437. #else
  6438. static const float max_mask_texel_border = ceil(max_tiled_pixel_border);
  6439. #endif
  6440. // Convert the texel border to a tile border using worst-case assumptions:
  6441. static const float max_mask_tile_border = max_mask_texel_border/
  6442. (mask_min_allowed_triad_size * mask_triads_per_tile);
  6443. // Finally, set the number of resized tiles to render to MASK_RESIZE, and set
  6444. // the starting texel (inside borders) for sampling it.
  6445. #ifndef GEOMETRY_EARLY
  6446. #ifdef ANISOTROPIC_TILING_COMPAT_TILE_FLAT_TWICE
  6447. // Special case: Render two tiles without borders. Anisotropic
  6448. // filtering doesn't seem to be a problem here.
  6449. static const float mask_resize_num_tiles = 1.0 + 1.0;
  6450. static const float mask_start_texels = 0.0;
  6451. #else
  6452. static const float mask_resize_num_tiles = 1.0 +
  6453. 2.0 * max_mask_tile_border;
  6454. static const float mask_start_texels = max_mask_texel_border;
  6455. #endif
  6456. #else
  6457. static const float mask_resize_num_tiles = 1.0 + 2.0*max_mask_tile_border;
  6458. static const float mask_start_texels = max_mask_texel_border;
  6459. #endif
  6460. // We have to fit mask_resize_num_tiles into an FBO with a viewport scale of
  6461. // mask_resize_viewport_scale. This limits the maximum final triad size.
  6462. // Estimate the minimum number of triads we can split the screen into in each
  6463. // dimension (we'll be as correct as mask_resize_viewport_scale is):
  6464. static const float mask_resize_num_triads =
  6465. mask_resize_num_tiles * mask_triads_per_tile;
  6466. static const float2 min_allowed_viewport_triads =
  6467. float2(mask_resize_num_triads) / mask_resize_viewport_scale;
  6468. //////////////////////// COMMON MATHEMATICAL CONSTANTS ///////////////////////
  6469. static const float pi = 3.141592653589;
  6470. // We often want to find the location of the previous texel, e.g.:
  6471. // const float2 curr_texel = uv * texture_size;
  6472. // const float2 prev_texel = floor(curr_texel - float2(0.5)) + float2(0.5);
  6473. // const float2 prev_texel_uv = prev_texel / texture_size;
  6474. // However, many GPU drivers round incorrectly around exact texel locations.
  6475. // We need to subtract a little less than 0.5 before flooring, and some GPU's
  6476. // require this value to be farther from 0.5 than others; define it here.
  6477. // const float2 prev_texel =
  6478. // floor(curr_texel - float2(under_half)) + float2(0.5);
  6479. static const float under_half = 0.4995;
  6480. #endif // DERIVED_SETTINGS_AND_CONSTANTS_H
  6481. ///////////////////////////// END DERIVED-SETTINGS-AND-CONSTANTS ////////////////////////////
  6482. //#include "../../../../include/blur-functions.h"
  6483. //////////////////////////// BEGIN BLUR-FUNCTIONS ///////////////////////////
  6484. #ifndef BLUR_FUNCTIONS_H
  6485. #define BLUR_FUNCTIONS_H
  6486. ///////////////////////////////// MIT LICENSE ////////////////////////////////
  6487. // Copyright (C) 2014 TroggleMonkey
  6488. //
  6489. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6490. // of this software and associated documentation files (the "Software"), to
  6491. // deal in the Software without restriction, including without limitation the
  6492. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  6493. // sell copies of the Software, and to permit persons to whom the Software is
  6494. // furnished to do so, subject to the following conditions:
  6495. //
  6496. // The above copyright notice and this permission notice shall be included in
  6497. // all copies or substantial portions of the Software.
  6498. //
  6499. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  6500. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  6501. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  6502. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  6503. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  6504. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  6505. // IN THE SOFTWARE.
  6506. ///////////////////////////////// DESCRIPTION ////////////////////////////////
  6507. // This file provides reusable one-pass and separable (two-pass) blurs.
  6508. // Requires: All blurs share these requirements (dxdy requirement is split):
  6509. // 1.) All requirements of gamma-management.h must be satisfied!
  6510. // 2.) filter_linearN must == "true" in your .cgp preset unless
  6511. // you're using tex2DblurNresize at 1x scale.
  6512. // 3.) mipmap_inputN must == "true" in your .cgp preset if
  6513. // output_size < video_size.
  6514. // 4.) output_size == video_size / pow(2, M), where M is some
  6515. // positive integer. tex2Dblur*resize can resize arbitrarily
  6516. // (and the blur will be done after resizing), but arbitrary
  6517. // resizes "fail" with other blurs due to the way they mix
  6518. // static weights with bilinear sample exploitation.
  6519. // 5.) In general, dxdy should contain the uv pixel spacing:
  6520. // dxdy = (video_size/output_size)/texture_size
  6521. // 6.) For separable blurs (tex2DblurNresize and tex2DblurNfast),
  6522. // zero out the dxdy component in the unblurred dimension:
  6523. // dxdy = float2(dxdy.x, 0.0) or float2(0.0, dxdy.y)
  6524. // Many blurs share these requirements:
  6525. // 1.) One-pass blurs require scale_xN == scale_yN or scales > 1.0,
  6526. // or they will blur more in the lower-scaled dimension.
  6527. // 2.) One-pass shared sample blurs require ddx(), ddy(), and
  6528. // tex2Dlod() to be supported by the current Cg profile, and
  6529. // the drivers must support high-quality derivatives.
  6530. // 3.) One-pass shared sample blurs require:
  6531. // tex_uv.w == log2(video_size/output_size).y;
  6532. // Non-wrapper blurs share this requirement:
  6533. // 1.) sigma is the intended standard deviation of the blur
  6534. // Wrapper blurs share this requirement, which is automatically
  6535. // met (unless OVERRIDE_BLUR_STD_DEVS is #defined; see below):
  6536. // 1.) blurN_std_dev must be global static const float values
  6537. // specifying standard deviations for Nx blurs in units
  6538. // of destination pixels
  6539. // Optional: 1.) The including file (or an earlier included file) may
  6540. // optionally #define USE_BINOMIAL_BLUR_STD_DEVS to replace
  6541. // default standard deviations with those matching a binomial
  6542. // distribution. (See below for details/properties.)
  6543. // 2.) The including file (or an earlier included file) may
  6544. // optionally #define OVERRIDE_BLUR_STD_DEVS and override:
  6545. // static const float blur3_std_dev
  6546. // static const float blur4_std_dev
  6547. // static const float blur5_std_dev
  6548. // static const float blur6_std_dev
  6549. // static const float blur7_std_dev
  6550. // static const float blur8_std_dev
  6551. // static const float blur9_std_dev
  6552. // static const float blur10_std_dev
  6553. // static const float blur11_std_dev
  6554. // static const float blur12_std_dev
  6555. // static const float blur17_std_dev
  6556. // static const float blur25_std_dev
  6557. // static const float blur31_std_dev
  6558. // static const float blur43_std_dev
  6559. // 3.) The including file (or an earlier included file) may
  6560. // optionally #define OVERRIDE_ERROR_BLURRING and override:
  6561. // static const float error_blurring
  6562. // This tuning value helps mitigate weighting errors from one-
  6563. // pass shared-sample blurs sharing bilinear samples between
  6564. // fragments. Values closer to 0.0 have "correct" blurriness
  6565. // but allow more artifacts, and values closer to 1.0 blur away
  6566. // artifacts by sampling closer to halfway between texels.
  6567. // UPDATE 6/21/14: The above static constants may now be overridden
  6568. // by non-static uniform constants. This permits exposing blur
  6569. // standard deviations as runtime GUI shader parameters. However,
  6570. // using them keeps weights from being statically computed, and the
  6571. // speed hit depends on the blur: On my machine, uniforms kill over
  6572. // 53% of the framerate with tex2Dblur12x12shared, but they only
  6573. // drop the framerate by about 18% with tex2Dblur11fast.
  6574. // Quality and Performance Comparisons:
  6575. // For the purposes of the following discussion, "no sRGB" means
  6576. // GAMMA_ENCODE_EVERY_FBO is #defined, and "sRGB" means it isn't.
  6577. // 1.) tex2DblurNfast is always faster than tex2DblurNresize.
  6578. // 2.) tex2DblurNresize functions are the only ones that can arbitrarily resize
  6579. // well, because they're the only ones that don't exploit bilinear samples.
  6580. // This also means they're the only functions which can be truly gamma-
  6581. // correct without linear (or sRGB FBO) input, but only at 1x scale.
  6582. // 3.) One-pass shared sample blurs only have a speed advantage without sRGB.
  6583. // They also have some inaccuracies due to their shared-[bilinear-]sample
  6584. // design, which grow increasingly bothersome for smaller blurs and higher-
  6585. // frequency source images (relative to their resolution). I had high
  6586. // hopes for them, but their most realistic use case is limited to quickly
  6587. // reblurring an already blurred input at full resolution. Otherwise:
  6588. // a.) If you're blurring a low-resolution source, you want a better blur.
  6589. // b.) If you're blurring a lower mipmap, you want a better blur.
  6590. // c.) If you're blurring a high-resolution, high-frequency source, you
  6591. // want a better blur.
  6592. // 4.) The one-pass blurs without shared samples grow slower for larger blurs,
  6593. // but they're competitive with separable blurs at 5x5 and smaller, and
  6594. // even tex2Dblur7x7 isn't bad if you're wanting to conserve passes.
  6595. // Here are some framerates from a GeForce 8800GTS. The first pass resizes to
  6596. // viewport size (4x in this test) and linearizes for sRGB codepaths, and the
  6597. // remaining passes perform 6 full blurs. Mipmapped tests are performed at the
  6598. // same scale, so they just measure the cost of mipmapping each FBO (only every
  6599. // other FBO is mipmapped for separable blurs, to mimic realistic usage).
  6600. // Mipmap Neither sRGB+Mipmap sRGB Function
  6601. // 76.0 92.3 131.3 193.7 tex2Dblur3fast
  6602. // 63.2 74.4 122.4 175.5 tex2Dblur3resize
  6603. // 93.7 121.2 159.3 263.2 tex2Dblur3x3
  6604. // 59.7 68.7 115.4 162.1 tex2Dblur3x3resize
  6605. // 63.2 74.4 122.4 175.5 tex2Dblur5fast
  6606. // 49.3 54.8 100.0 132.7 tex2Dblur5resize
  6607. // 59.7 68.7 115.4 162.1 tex2Dblur5x5
  6608. // 64.9 77.2 99.1 137.2 tex2Dblur6x6shared
  6609. // 55.8 63.7 110.4 151.8 tex2Dblur7fast
  6610. // 39.8 43.9 83.9 105.8 tex2Dblur7resize
  6611. // 40.0 44.2 83.2 104.9 tex2Dblur7x7
  6612. // 56.4 65.5 71.9 87.9 tex2Dblur8x8shared
  6613. // 49.3 55.1 99.9 132.5 tex2Dblur9fast
  6614. // 33.3 36.2 72.4 88.0 tex2Dblur9resize
  6615. // 27.8 29.7 61.3 72.2 tex2Dblur9x9
  6616. // 37.2 41.1 52.6 60.2 tex2Dblur10x10shared
  6617. // 44.4 49.5 91.3 117.8 tex2Dblur11fast
  6618. // 28.8 30.8 63.6 75.4 tex2Dblur11resize
  6619. // 33.6 36.5 40.9 45.5 tex2Dblur12x12shared
  6620. // TODO: Fill in benchmarks for new untested blurs.
  6621. // tex2Dblur17fast
  6622. // tex2Dblur25fast
  6623. // tex2Dblur31fast
  6624. // tex2Dblur43fast
  6625. // tex2Dblur3x3resize
  6626. ///////////////////////////// SETTINGS MANAGEMENT ////////////////////////////
  6627. // Set static standard deviations, but allow users to override them with their
  6628. // own constants (even non-static uniforms if they're okay with the speed hit):
  6629. #ifndef OVERRIDE_BLUR_STD_DEVS
  6630. // blurN_std_dev values are specified in terms of dxdy strides.
  6631. #ifdef USE_BINOMIAL_BLUR_STD_DEVS
  6632. // By request, we can define standard deviations corresponding to a
  6633. // binomial distribution with p = 0.5 (related to Pascal's triangle).
  6634. // This distribution works such that blurring multiple times should
  6635. // have the same result as a single larger blur. These values are
  6636. // larger than default for blurs up to 6x and smaller thereafter.
  6637. static const float blur3_std_dev = 0.84931640625;
  6638. static const float blur4_std_dev = 0.84931640625;
  6639. static const float blur5_std_dev = 1.0595703125;
  6640. static const float blur6_std_dev = 1.06591796875;
  6641. static const float blur7_std_dev = 1.17041015625;
  6642. static const float blur8_std_dev = 1.1720703125;
  6643. static const float blur9_std_dev = 1.2259765625;
  6644. static const float blur10_std_dev = 1.21982421875;
  6645. static const float blur11_std_dev = 1.25361328125;
  6646. static const float blur12_std_dev = 1.2423828125;
  6647. static const float blur17_std_dev = 1.27783203125;
  6648. static const float blur25_std_dev = 1.2810546875;
  6649. static const float blur31_std_dev = 1.28125;
  6650. static const float blur43_std_dev = 1.28125;
  6651. #else
  6652. // The defaults are the largest values that keep the largest unused
  6653. // blur term on each side <= 1.0/256.0. (We could get away with more
  6654. // or be more conservative, but this compromise is pretty reasonable.)
  6655. static const float blur3_std_dev = 0.62666015625;
  6656. static const float blur4_std_dev = 0.66171875;
  6657. static const float blur5_std_dev = 0.9845703125;
  6658. static const float blur6_std_dev = 1.02626953125;
  6659. static const float blur7_std_dev = 1.36103515625;
  6660. static const float blur8_std_dev = 1.4080078125;
  6661. static const float blur9_std_dev = 1.7533203125;
  6662. static const float blur10_std_dev = 1.80478515625;
  6663. static const float blur11_std_dev = 2.15986328125;
  6664. static const float blur12_std_dev = 2.215234375;
  6665. static const float blur17_std_dev = 3.45535583496;
  6666. static const float blur25_std_dev = 5.3409576416;
  6667. static const float blur31_std_dev = 6.86488037109;
  6668. static const float blur43_std_dev = 10.1852050781;
  6669. #endif // USE_BINOMIAL_BLUR_STD_DEVS
  6670. #endif // OVERRIDE_BLUR_STD_DEVS
  6671. #ifndef OVERRIDE_ERROR_BLURRING
  6672. // error_blurring should be in [0.0, 1.0]. Higher values reduce ringing
  6673. // in shared-sample blurs but increase blurring and feature shifting.
  6674. static const float error_blurring = 0.5;
  6675. #endif
  6676. ////////////////////////////////// INCLUDES //////////////////////////////////
  6677. // gamma-management.h relies on pass-specific settings to guide its behavior:
  6678. // FIRST_PASS, LAST_PASS, GAMMA_ENCODE_EVERY_FBO, etc. See it for details.
  6679. //#include "gamma-management.h"
  6680. //////////////////////////// BEGIN GAMMA-MANAGEMENT //////////////////////////
  6681. #ifndef GAMMA_MANAGEMENT_H
  6682. #define GAMMA_MANAGEMENT_H
  6683. ///////////////////////////////// MIT LICENSE ////////////////////////////////
  6684. // Copyright (C) 2014 TroggleMonkey
  6685. //
  6686. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6687. // of this software and associated documentation files (the "Software"), to
  6688. // deal in the Software without restriction, including without limitation the
  6689. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  6690. // sell copies of the Software, and to permit persons to whom the Software is
  6691. // furnished to do so, subject to the following conditions:
  6692. //
  6693. // The above copyright notice and this permission notice shall be included in
  6694. // all copies or substantial portions of the Software.
  6695. //
  6696. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  6697. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  6698. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  6699. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  6700. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  6701. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  6702. // IN THE SOFTWARE.
  6703. ///////////////////////////////// DESCRIPTION ////////////////////////////////
  6704. // This file provides gamma-aware tex*D*() and encode_output() functions.
  6705. // Requires: Before #include-ing this file, the including file must #define
  6706. // the following macros when applicable and follow their rules:
  6707. // 1.) #define FIRST_PASS if this is the first pass.
  6708. // 2.) #define LAST_PASS if this is the last pass.
  6709. // 3.) If sRGB is available, set srgb_framebufferN = "true" for
  6710. // every pass except the last in your .cgp preset.
  6711. // 4.) If sRGB isn't available but you want gamma-correctness with
  6712. // no banding, #define GAMMA_ENCODE_EVERY_FBO each pass.
  6713. // 5.) #define SIMULATE_CRT_ON_LCD if desired (precedence over 5-7)
  6714. // 6.) #define SIMULATE_GBA_ON_LCD if desired (precedence over 6-7)
  6715. // 7.) #define SIMULATE_LCD_ON_CRT if desired (precedence over 7)
  6716. // 8.) #define SIMULATE_GBA_ON_CRT if desired (precedence over -)
  6717. // If an option in [5, 8] is #defined in the first or last pass, it
  6718. // should be #defined for both. It shouldn't make a difference
  6719. // whether it's #defined for intermediate passes or not.
  6720. // Optional: The including file (or an earlier included file) may optionally
  6721. // #define a number of macros indicating it will override certain
  6722. // macros and associated constants are as follows:
  6723. // static constants with either static or uniform constants. The
  6724. // 1.) OVERRIDE_STANDARD_GAMMA: The user must first define:
  6725. // static const float ntsc_gamma
  6726. // static const float pal_gamma
  6727. // static const float crt_reference_gamma_high
  6728. // static const float crt_reference_gamma_low
  6729. // static const float lcd_reference_gamma
  6730. // static const float crt_office_gamma
  6731. // static const float lcd_office_gamma
  6732. // 2.) OVERRIDE_DEVICE_GAMMA: The user must first define:
  6733. // static const float crt_gamma
  6734. // static const float gba_gamma
  6735. // static const float lcd_gamma
  6736. // 3.) OVERRIDE_FINAL_GAMMA: The user must first define:
  6737. // static const float input_gamma
  6738. // static const float intermediate_gamma
  6739. // static const float output_gamma
  6740. // (intermediate_gamma is for GAMMA_ENCODE_EVERY_FBO.)
  6741. // 4.) OVERRIDE_ALPHA_ASSUMPTIONS: The user must first define:
  6742. // static const bool assume_opaque_alpha
  6743. // The gamma constant overrides must be used in every pass or none,
  6744. // and OVERRIDE_FINAL_GAMMA bypasses all of the SIMULATE* macros.
  6745. // OVERRIDE_ALPHA_ASSUMPTIONS may be set on a per-pass basis.
  6746. // Usage: After setting macros appropriately, ignore gamma correction and
  6747. // replace all tex*D*() calls with equivalent gamma-aware
  6748. // tex*D*_linearize calls, except:
  6749. // 1.) When you read an LUT, use regular tex*D or a gamma-specified
  6750. // function, depending on its gamma encoding:
  6751. // tex*D*_linearize_gamma (takes a runtime gamma parameter)
  6752. // 2.) If you must read pass0's original input in a later pass, use
  6753. // tex2D_linearize_ntsc_gamma. If you want to read pass0's
  6754. // input with gamma-corrected bilinear filtering, consider
  6755. // creating a first linearizing pass and reading from the input
  6756. // of pass1 later.
  6757. // Then, return encode_output(color) from every fragment shader.
  6758. // Finally, use the global gamma_aware_bilinear boolean if you want
  6759. // to statically branch based on whether bilinear filtering is
  6760. // gamma-correct or not (e.g. for placing Gaussian blur samples).
  6761. //
  6762. // Detailed Policy:
  6763. // tex*D*_linearize() functions enforce a consistent gamma-management policy
  6764. // based on the FIRST_PASS and GAMMA_ENCODE_EVERY_FBO settings. They assume
  6765. // their input texture has the same encoding characteristics as the input for
  6766. // the current pass (which doesn't apply to the exceptions listed above).
  6767. // Similarly, encode_output() enforces a policy based on the LAST_PASS and
  6768. // GAMMA_ENCODE_EVERY_FBO settings. Together, they result in one of the
  6769. // following two pipelines.
  6770. // Typical pipeline with intermediate sRGB framebuffers:
  6771. // linear_color = pow(pass0_encoded_color, input_gamma);
  6772. // intermediate_output = linear_color; // Automatic sRGB encoding
  6773. // linear_color = intermediate_output; // Automatic sRGB decoding
  6774. // final_output = pow(intermediate_output, 1.0/output_gamma);
  6775. // Typical pipeline without intermediate sRGB framebuffers:
  6776. // linear_color = pow(pass0_encoded_color, input_gamma);
  6777. // intermediate_output = pow(linear_color, 1.0/intermediate_gamma);
  6778. // linear_color = pow(intermediate_output, intermediate_gamma);
  6779. // final_output = pow(intermediate_output, 1.0/output_gamma);
  6780. // Using GAMMA_ENCODE_EVERY_FBO is much slower, but it's provided as a way to
  6781. // easily get gamma-correctness without banding on devices where sRGB isn't
  6782. // supported.
  6783. //
  6784. // Use This Header to Maximize Code Reuse:
  6785. // The purpose of this header is to provide a consistent interface for texture
  6786. // reads and output gamma-encoding that localizes and abstracts away all the
  6787. // annoying details. This greatly reduces the amount of code in each shader
  6788. // pass that depends on the pass number in the .cgp preset or whether sRGB
  6789. // FBO's are being used: You can trivially change the gamma behavior of your
  6790. // whole pass by commenting or uncommenting 1-3 #defines. To reuse the same
  6791. // code in your first, Nth, and last passes, you can even put it all in another
  6792. // header file and #include it from skeleton .cg files that #define the
  6793. // appropriate pass-specific settings.
  6794. //
  6795. // Rationale for Using Three Macros:
  6796. // This file uses GAMMA_ENCODE_EVERY_FBO instead of an opposite macro like
  6797. // SRGB_PIPELINE to ensure sRGB is assumed by default, which hopefully imposes
  6798. // a lower maintenance burden on each pass. At first glance it seems we could
  6799. // accomplish everything with two macros: GAMMA_CORRECT_IN / GAMMA_CORRECT_OUT.
  6800. // This works for simple use cases where input_gamma == output_gamma, but it
  6801. // breaks down for more complex scenarios like CRT simulation, where the pass
  6802. // number determines the gamma encoding of the input and output.
  6803. /////////////////////////////// BASE CONSTANTS ///////////////////////////////
  6804. // Set standard gamma constants, but allow users to override them:
  6805. #ifndef OVERRIDE_STANDARD_GAMMA
  6806. // Standard encoding gammas:
  6807. static const float ntsc_gamma = 2.2; // Best to use NTSC for PAL too?
  6808. static const float pal_gamma = 2.8; // Never actually 2.8 in practice
  6809. // Typical device decoding gammas (only use for emulating devices):
  6810. // CRT/LCD reference gammas are higher than NTSC and Rec.709 video standard
  6811. // gammas: The standards purposely undercorrected for an analog CRT's
  6812. // assumed 2.5 reference display gamma to maintain contrast in assumed
  6813. // [dark] viewing conditions: http://www.poynton.com/PDFs/GammaFAQ.pdf
  6814. // These unstated assumptions about display gamma and perceptual rendering
  6815. // intent caused a lot of confusion, and more modern CRT's seemed to target
  6816. // NTSC 2.2 gamma with circuitry. LCD displays seem to have followed suit
  6817. // (they struggle near black with 2.5 gamma anyway), especially PC/laptop
  6818. // displays designed to view sRGB in bright environments. (Standards are
  6819. // also in flux again with BT.1886, but it's underspecified for displays.)
  6820. static const float crt_reference_gamma_high = 2.5; // In (2.35, 2.55)
  6821. static const float crt_reference_gamma_low = 2.35; // In (2.35, 2.55)
  6822. static const float lcd_reference_gamma = 2.5; // To match CRT
  6823. static const float crt_office_gamma = 2.2; // Circuitry-adjusted for NTSC
  6824. static const float lcd_office_gamma = 2.2; // Approximates sRGB
  6825. #endif // OVERRIDE_STANDARD_GAMMA
  6826. // Assuming alpha == 1.0 might make it easier for users to avoid some bugs,
  6827. // but only if they're aware of it.
  6828. #ifndef OVERRIDE_ALPHA_ASSUMPTIONS
  6829. static const bool assume_opaque_alpha = false;
  6830. #endif
  6831. /////////////////////// DERIVED CONSTANTS AS FUNCTIONS ///////////////////////
  6832. // gamma-management.h should be compatible with overriding gamma values with
  6833. // runtime user parameters, but we can only define other global constants in
  6834. // terms of static constants, not uniform user parameters. To get around this
  6835. // limitation, we need to define derived constants using functions.
  6836. // Set device gamma constants, but allow users to override them:
  6837. #ifdef OVERRIDE_DEVICE_GAMMA
  6838. // The user promises to globally define the appropriate constants:
  6839. inline float get_crt_gamma() { return crt_gamma; }
  6840. inline float get_gba_gamma() { return gba_gamma; }
  6841. inline float get_lcd_gamma() { return lcd_gamma; }
  6842. #else
  6843. inline float get_crt_gamma() { return crt_reference_gamma_high; }
  6844. inline float get_gba_gamma() { return 3.5; } // Game Boy Advance; in (3.0, 4.0)
  6845. inline float get_lcd_gamma() { return lcd_office_gamma; }
  6846. #endif // OVERRIDE_DEVICE_GAMMA
  6847. // Set decoding/encoding gammas for the first/lass passes, but allow overrides:
  6848. #ifdef OVERRIDE_FINAL_GAMMA
  6849. // The user promises to globally define the appropriate constants:
  6850. inline float get_intermediate_gamma() { return intermediate_gamma; }
  6851. inline float get_input_gamma() { return input_gamma; }
  6852. inline float get_output_gamma() { return output_gamma; }
  6853. #else
  6854. // If we gamma-correct every pass, always use ntsc_gamma between passes to
  6855. // ensure middle passes don't need to care if anything is being simulated:
  6856. inline float get_intermediate_gamma() { return ntsc_gamma; }
  6857. #ifdef SIMULATE_CRT_ON_LCD
  6858. inline float get_input_gamma() { return get_crt_gamma(); }
  6859. inline float get_output_gamma() { return get_lcd_gamma(); }
  6860. #else
  6861. #ifdef SIMULATE_GBA_ON_LCD
  6862. inline float get_input_gamma() { return get_gba_gamma(); }
  6863. inline float get_output_gamma() { return get_lcd_gamma(); }
  6864. #else
  6865. #ifdef SIMULATE_LCD_ON_CRT
  6866. inline float get_input_gamma() { return get_lcd_gamma(); }
  6867. inline float get_output_gamma() { return get_crt_gamma(); }
  6868. #else
  6869. #ifdef SIMULATE_GBA_ON_CRT
  6870. inline float get_input_gamma() { return get_gba_gamma(); }
  6871. inline float get_output_gamma() { return get_crt_gamma(); }
  6872. #else // Don't simulate anything:
  6873. inline float get_input_gamma() { return ntsc_gamma; }
  6874. inline float get_output_gamma() { return ntsc_gamma; }
  6875. #endif // SIMULATE_GBA_ON_CRT
  6876. #endif // SIMULATE_LCD_ON_CRT
  6877. #endif // SIMULATE_GBA_ON_LCD
  6878. #endif // SIMULATE_CRT_ON_LCD
  6879. #endif // OVERRIDE_FINAL_GAMMA
  6880. // Set decoding/encoding gammas for the current pass. Use static constants for
  6881. // linearize_input and gamma_encode_output, because they aren't derived, and
  6882. // they let the compiler do dead-code elimination.
  6883. #ifndef GAMMA_ENCODE_EVERY_FBO
  6884. #ifdef FIRST_PASS
  6885. static const bool linearize_input = true;
  6886. inline float get_pass_input_gamma() { return get_input_gamma(); }
  6887. #else
  6888. static const bool linearize_input = false;
  6889. inline float get_pass_input_gamma() { return 1.0; }
  6890. #endif
  6891. #ifdef LAST_PASS
  6892. static const bool gamma_encode_output = true;
  6893. inline float get_pass_output_gamma() { return get_output_gamma(); }
  6894. #else
  6895. static const bool gamma_encode_output = false;
  6896. inline float get_pass_output_gamma() { return 1.0; }
  6897. #endif
  6898. #else
  6899. static const bool linearize_input = true;
  6900. static const bool gamma_encode_output = true;
  6901. #ifdef FIRST_PASS
  6902. inline float get_pass_input_gamma() { return get_input_gamma(); }
  6903. #else
  6904. inline float get_pass_input_gamma() { return get_intermediate_gamma(); }
  6905. #endif
  6906. #ifdef LAST_PASS
  6907. inline float get_pass_output_gamma() { return get_output_gamma(); }
  6908. #else
  6909. inline float get_pass_output_gamma() { return get_intermediate_gamma(); }
  6910. #endif
  6911. #endif
  6912. // Users might want to know if bilinear filtering will be gamma-correct:
  6913. static const bool gamma_aware_bilinear = !linearize_input;
  6914. ////////////////////// COLOR ENCODING/DECODING FUNCTIONS /////////////////////
  6915. inline float4 encode_output(const float4 color)
  6916. {
  6917. if(gamma_encode_output)
  6918. {
  6919. if(assume_opaque_alpha)
  6920. {
  6921. return float4(pow(color.rgb, float3(1.0/get_pass_output_gamma())), 1.0);
  6922. }
  6923. else
  6924. {
  6925. return float4(pow(color.rgb, float3(1.0/get_pass_output_gamma())), color.a);
  6926. }
  6927. }
  6928. else
  6929. {
  6930. return color;
  6931. }
  6932. }
  6933. inline float4 decode_input(const float4 color)
  6934. {
  6935. if(linearize_input)
  6936. {
  6937. if(assume_opaque_alpha)
  6938. {
  6939. return float4(pow(color.rgb, float3(get_pass_input_gamma())), 1.0);
  6940. }
  6941. else
  6942. {
  6943. return float4(pow(color.rgb, float3(get_pass_input_gamma())), color.a);
  6944. }
  6945. }
  6946. else
  6947. {
  6948. return color;
  6949. }
  6950. }
  6951. inline float4 decode_gamma_input(const float4 color, const float3 gamma)
  6952. {
  6953. if(assume_opaque_alpha)
  6954. {
  6955. return float4(pow(color.rgb, gamma), 1.0);
  6956. }
  6957. else
  6958. {
  6959. return float4(pow(color.rgb, gamma), color.a);
  6960. }
  6961. }
  6962. //TODO/FIXME: I have no idea why replacing the lookup wrappers with this macro fixes the blurs being offset ¯\_(ツ)_/¯
  6963. //#define tex2D_linearize(C, D) decode_input(vec4(COMPAT_TEXTURE(C, D)))
  6964. // EDIT: it's the 'const' in front of the coords that's doing it
  6965. /////////////////////////// TEXTURE LOOKUP WRAPPERS //////////////////////////
  6966. // "SMART" LINEARIZING TEXTURE LOOKUP FUNCTIONS:
  6967. // Provide a wide array of linearizing texture lookup wrapper functions. The
  6968. // Cg shader spec Retroarch uses only allows for 2D textures, but 1D and 3D
  6969. // lookups are provided for completeness in case that changes someday. Nobody
  6970. // is likely to use the *fetch and *proj functions, but they're included just
  6971. // in case. The only tex*D texture sampling functions omitted are:
  6972. // - tex*Dcmpbias
  6973. // - tex*Dcmplod
  6974. // - tex*DARRAY*
  6975. // - tex*DMS*
  6976. // - Variants returning integers
  6977. // Standard line length restrictions are ignored below for vertical brevity.
  6978. /*
  6979. // tex1D:
  6980. inline float4 tex1D_linearize(const sampler1D tex, const float tex_coords)
  6981. { return decode_input(tex1D(tex, tex_coords)); }
  6982. inline float4 tex1D_linearize(const sampler1D tex, const float2 tex_coords)
  6983. { return decode_input(tex1D(tex, tex_coords)); }
  6984. inline float4 tex1D_linearize(const sampler1D tex, const float tex_coords, const int texel_off)
  6985. { return decode_input(tex1D(tex, tex_coords, texel_off)); }
  6986. inline float4 tex1D_linearize(const sampler1D tex, const float2 tex_coords, const int texel_off)
  6987. { return decode_input(tex1D(tex, tex_coords, texel_off)); }
  6988. inline float4 tex1D_linearize(const sampler1D tex, const float tex_coords, const float dx, const float dy)
  6989. { return decode_input(tex1D(tex, tex_coords, dx, dy)); }
  6990. inline float4 tex1D_linearize(const sampler1D tex, const float2 tex_coords, const float dx, const float dy)
  6991. { return decode_input(tex1D(tex, tex_coords, dx, dy)); }
  6992. inline float4 tex1D_linearize(const sampler1D tex, const float tex_coords, const float dx, const float dy, const int texel_off)
  6993. { return decode_input(tex1D(tex, tex_coords, dx, dy, texel_off)); }
  6994. inline float4 tex1D_linearize(const sampler1D tex, const float2 tex_coords, const float dx, const float dy, const int texel_off)
  6995. { return decode_input(tex1D(tex, tex_coords, dx, dy, texel_off)); }
  6996. // tex1Dbias:
  6997. inline float4 tex1Dbias_linearize(const sampler1D tex, const float4 tex_coords)
  6998. { return decode_input(tex1Dbias(tex, tex_coords)); }
  6999. inline float4 tex1Dbias_linearize(const sampler1D tex, const float4 tex_coords, const int texel_off)
  7000. { return decode_input(tex1Dbias(tex, tex_coords, texel_off)); }
  7001. // tex1Dfetch:
  7002. inline float4 tex1Dfetch_linearize(const sampler1D tex, const int4 tex_coords)
  7003. { return decode_input(tex1Dfetch(tex, tex_coords)); }
  7004. inline float4 tex1Dfetch_linearize(const sampler1D tex, const int4 tex_coords, const int texel_off)
  7005. { return decode_input(tex1Dfetch(tex, tex_coords, texel_off)); }
  7006. // tex1Dlod:
  7007. inline float4 tex1Dlod_linearize(const sampler1D tex, const float4 tex_coords)
  7008. { return decode_input(tex1Dlod(tex, tex_coords)); }
  7009. inline float4 tex1Dlod_linearize(const sampler1D tex, const float4 tex_coords, const int texel_off)
  7010. { return decode_input(tex1Dlod(tex, tex_coords, texel_off)); }
  7011. // tex1Dproj:
  7012. inline float4 tex1Dproj_linearize(const sampler1D tex, const float2 tex_coords)
  7013. { return decode_input(tex1Dproj(tex, tex_coords)); }
  7014. inline float4 tex1Dproj_linearize(const sampler1D tex, const float3 tex_coords)
  7015. { return decode_input(tex1Dproj(tex, tex_coords)); }
  7016. inline float4 tex1Dproj_linearize(const sampler1D tex, const float2 tex_coords, const int texel_off)
  7017. { return decode_input(tex1Dproj(tex, tex_coords, texel_off)); }
  7018. inline float4 tex1Dproj_linearize(const sampler1D tex, const float3 tex_coords, const int texel_off)
  7019. { return decode_input(tex1Dproj(tex, tex_coords, texel_off)); }
  7020. */
  7021. // tex2D:
  7022. inline float4 tex2D_linearize(const sampler2D tex, float2 tex_coords)
  7023. { return decode_input(COMPAT_TEXTURE(tex, tex_coords)); }
  7024. inline float4 tex2D_linearize(const sampler2D tex, float3 tex_coords)
  7025. { return decode_input(COMPAT_TEXTURE(tex, tex_coords.xy)); }
  7026. inline float4 tex2D_linearize(const sampler2D tex, float2 tex_coords, int texel_off)
  7027. { return decode_input(textureLod(tex, tex_coords, texel_off)); }
  7028. inline float4 tex2D_linearize(const sampler2D tex, float3 tex_coords, int texel_off)
  7029. { return decode_input(textureLod(tex, tex_coords.xy, texel_off)); }
  7030. //inline float4 tex2D_linearize(const sampler2D tex, const float2 tex_coords, const float2 dx, const float2 dy)
  7031. //{ return decode_input(COMPAT_TEXTURE(tex, tex_coords, dx, dy)); }
  7032. //inline float4 tex2D_linearize(const sampler2D tex, const float3 tex_coords, const float2 dx, const float2 dy)
  7033. //{ return decode_input(COMPAT_TEXTURE(tex, tex_coords, dx, dy)); }
  7034. //inline float4 tex2D_linearize(const sampler2D tex, const float2 tex_coords, const float2 dx, const float2 dy, const int texel_off)
  7035. //{ return decode_input(COMPAT_TEXTURE(tex, tex_coords, dx, dy, texel_off)); }
  7036. //inline float4 tex2D_linearize(const sampler2D tex, const float3 tex_coords, const float2 dx, const float2 dy, const int texel_off)
  7037. //{ return decode_input(COMPAT_TEXTURE(tex, tex_coords, dx, dy, texel_off)); }
  7038. // tex2Dbias:
  7039. //inline float4 tex2Dbias_linearize(const sampler2D tex, const float4 tex_coords)
  7040. //{ return decode_input(tex2Dbias(tex, tex_coords)); }
  7041. //inline float4 tex2Dbias_linearize(const sampler2D tex, const float4 tex_coords, const int texel_off)
  7042. //{ return decode_input(tex2Dbias(tex, tex_coords, texel_off)); }
  7043. // tex2Dfetch:
  7044. //inline float4 tex2Dfetch_linearize(const sampler2D tex, const int4 tex_coords)
  7045. //{ return decode_input(tex2Dfetch(tex, tex_coords)); }
  7046. //inline float4 tex2Dfetch_linearize(const sampler2D tex, const int4 tex_coords, const int texel_off)
  7047. //{ return decode_input(tex2Dfetch(tex, tex_coords, texel_off)); }
  7048. // tex2Dlod:
  7049. inline float4 tex2Dlod_linearize(const sampler2D tex, float4 tex_coords)
  7050. { return decode_input(textureLod(tex, tex_coords.xy, 0.0)); }
  7051. inline float4 tex2Dlod_linearize(const sampler2D tex, float4 tex_coords, int texel_off)
  7052. { return decode_input(textureLod(tex, tex_coords.xy, texel_off)); }
  7053. /*
  7054. // tex2Dproj:
  7055. inline float4 tex2Dproj_linearize(const sampler2D tex, const float3 tex_coords)
  7056. { return decode_input(tex2Dproj(tex, tex_coords)); }
  7057. inline float4 tex2Dproj_linearize(const sampler2D tex, const float4 tex_coords)
  7058. { return decode_input(tex2Dproj(tex, tex_coords)); }
  7059. inline float4 tex2Dproj_linearize(const sampler2D tex, const float3 tex_coords, const int texel_off)
  7060. { return decode_input(tex2Dproj(tex, tex_coords, texel_off)); }
  7061. inline float4 tex2Dproj_linearize(const sampler2D tex, const float4 tex_coords, const int texel_off)
  7062. { return decode_input(tex2Dproj(tex, tex_coords, texel_off)); }
  7063. */
  7064. /*
  7065. // tex3D:
  7066. inline float4 tex3D_linearize(const sampler3D tex, const float3 tex_coords)
  7067. { return decode_input(tex3D(tex, tex_coords)); }
  7068. inline float4 tex3D_linearize(const sampler3D tex, const float3 tex_coords, const int texel_off)
  7069. { return decode_input(tex3D(tex, tex_coords, texel_off)); }
  7070. inline float4 tex3D_linearize(const sampler3D tex, const float3 tex_coords, const float3 dx, const float3 dy)
  7071. { return decode_input(tex3D(tex, tex_coords, dx, dy)); }
  7072. inline float4 tex3D_linearize(const sampler3D tex, const float3 tex_coords, const float3 dx, const float3 dy, const int texel_off)
  7073. { return decode_input(tex3D(tex, tex_coords, dx, dy, texel_off)); }
  7074. // tex3Dbias:
  7075. inline float4 tex3Dbias_linearize(const sampler3D tex, const float4 tex_coords)
  7076. { return decode_input(tex3Dbias(tex, tex_coords)); }
  7077. inline float4 tex3Dbias_linearize(const sampler3D tex, const float4 tex_coords, const int texel_off)
  7078. { return decode_input(tex3Dbias(tex, tex_coords, texel_off)); }
  7079. // tex3Dfetch:
  7080. inline float4 tex3Dfetch_linearize(const sampler3D tex, const int4 tex_coords)
  7081. { return decode_input(tex3Dfetch(tex, tex_coords)); }
  7082. inline float4 tex3Dfetch_linearize(const sampler3D tex, const int4 tex_coords, const int texel_off)
  7083. { return decode_input(tex3Dfetch(tex, tex_coords, texel_off)); }
  7084. // tex3Dlod:
  7085. inline float4 tex3Dlod_linearize(const sampler3D tex, const float4 tex_coords)
  7086. { return decode_input(tex3Dlod(tex, tex_coords)); }
  7087. inline float4 tex3Dlod_linearize(const sampler3D tex, const float4 tex_coords, const int texel_off)
  7088. { return decode_input(tex3Dlod(tex, tex_coords, texel_off)); }
  7089. // tex3Dproj:
  7090. inline float4 tex3Dproj_linearize(const sampler3D tex, const float4 tex_coords)
  7091. { return decode_input(tex3Dproj(tex, tex_coords)); }
  7092. inline float4 tex3Dproj_linearize(const sampler3D tex, const float4 tex_coords, const int texel_off)
  7093. { return decode_input(tex3Dproj(tex, tex_coords, texel_off)); }
  7094. /////////*
  7095. // NONSTANDARD "SMART" LINEARIZING TEXTURE LOOKUP FUNCTIONS:
  7096. // This narrow selection of nonstandard tex2D* functions can be useful:
  7097. // tex2Dlod0: Automatically fill in the tex2D LOD parameter for mip level 0.
  7098. //inline float4 tex2Dlod0_linearize(const sampler2D tex, const float2 tex_coords)
  7099. //{ return decode_input(tex2Dlod(tex, float4(tex_coords, 0.0, 0.0))); }
  7100. //inline float4 tex2Dlod0_linearize(const sampler2D tex, const float2 tex_coords, const int texel_off)
  7101. //{ return decode_input(tex2Dlod(tex, float4(tex_coords, 0.0, 0.0), texel_off)); }
  7102. // MANUALLY LINEARIZING TEXTURE LOOKUP FUNCTIONS:
  7103. // Provide a narrower selection of tex2D* wrapper functions that decode an
  7104. // input sample with a specified gamma value. These are useful for reading
  7105. // LUT's and for reading the input of pass0 in a later pass.
  7106. // tex2D:
  7107. inline float4 tex2D_linearize_gamma(const sampler2D tex, const float2 tex_coords, const float3 gamma)
  7108. { return decode_gamma_input(COMPAT_TEXTURE(tex, tex_coords), gamma); }
  7109. inline float4 tex2D_linearize_gamma(const sampler2D tex, const float3 tex_coords, const float3 gamma)
  7110. { return decode_gamma_input(COMPAT_TEXTURE(tex, tex_coords.xy), gamma); }
  7111. //inline float4 tex2D_linearize_gamma(const sampler2D tex, const float2 tex_coords, const int texel_off, const float3 gamma)
  7112. //{ return decode_gamma_input(COMPAT_TEXTURE(tex, tex_coords, texel_off), gamma); }
  7113. //inline float4 tex2D_linearize_gamma(const sampler2D tex, const float3 tex_coords, const int texel_off, const float3 gamma)
  7114. //{ return decode_gamma_input(COMPAT_TEXTURE(tex, tex_coords, texel_off), gamma); }
  7115. //inline float4 tex2D_linearize_gamma(const sampler2D tex, const float2 tex_coords, const float2 dx, const float2 dy, const float3 gamma)
  7116. //{ return decode_gamma_input(COMPAT_TEXTURE(tex, tex_coords, dx, dy), gamma); }
  7117. //inline float4 tex2D_linearize_gamma(const sampler2D tex, const float3 tex_coords, const float2 dx, const float2 dy, const float3 gamma)
  7118. //{ return decode_gamma_input(COMPAT_TEXTURE(tex, tex_coords, dx, dy), gamma); }
  7119. //inline float4 tex2D_linearize_gamma(const sampler2D tex, const float2 tex_coords, const float2 dx, const float2 dy, const int texel_off, const float3 gamma)
  7120. //{ return decode_gamma_input(COMPAT_TEXTURE(tex, tex_coords, dx, dy, texel_off), gamma); }
  7121. //inline float4 tex2D_linearize_gamma(const sampler2D tex, const float3 tex_coords, const float2 dx, const float2 dy, const int texel_off, const float3 gamma)
  7122. //{ return decode_gamma_input(COMPAT_TEXTURE(tex, tex_coords, dx, dy, texel_off), gamma); }
  7123. /*
  7124. // tex2Dbias:
  7125. inline float4 tex2Dbias_linearize_gamma(const sampler2D tex, const float4 tex_coords, const float3 gamma)
  7126. { return decode_gamma_input(tex2Dbias(tex, tex_coords), gamma); }
  7127. inline float4 tex2Dbias_linearize_gamma(const sampler2D tex, const float4 tex_coords, const int texel_off, const float3 gamma)
  7128. { return decode_gamma_input(tex2Dbias(tex, tex_coords, texel_off), gamma); }
  7129. // tex2Dfetch:
  7130. inline float4 tex2Dfetch_linearize_gamma(const sampler2D tex, const int4 tex_coords, const float3 gamma)
  7131. { return decode_gamma_input(tex2Dfetch(tex, tex_coords), gamma); }
  7132. inline float4 tex2Dfetch_linearize_gamma(const sampler2D tex, const int4 tex_coords, const int texel_off, const float3 gamma)
  7133. { return decode_gamma_input(tex2Dfetch(tex, tex_coords, texel_off), gamma); }
  7134. */
  7135. // tex2Dlod:
  7136. inline float4 tex2Dlod_linearize_gamma(const sampler2D tex, float4 tex_coords, float3 gamma)
  7137. { return decode_gamma_input(textureLod(tex, tex_coords.xy, 0.0), gamma); }
  7138. inline float4 tex2Dlod_linearize_gamma(const sampler2D tex, float4 tex_coords, int texel_off, float3 gamma)
  7139. { return decode_gamma_input(textureLod(tex, tex_coords.xy, texel_off), gamma); }
  7140. #endif // GAMMA_MANAGEMENT_H
  7141. //////////////////////////// END GAMMA-MANAGEMENT //////////////////////////
  7142. //#include "quad-pixel-communication.h"
  7143. /////////////////////// BEGIN QUAD-PIXEL-COMMUNICATION //////////////////////
  7144. #ifndef QUAD_PIXEL_COMMUNICATION_H
  7145. #define QUAD_PIXEL_COMMUNICATION_H
  7146. ///////////////////////////////// MIT LICENSE ////////////////////////////////
  7147. // Copyright (C) 2014 TroggleMonkey*
  7148. //
  7149. // Permission is hereby granted, free of charge, to any person obtaining a copy
  7150. // of this software and associated documentation files (the "Software"), to
  7151. // deal in the Software without restriction, including without limitation the
  7152. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  7153. // sell copies of the Software, and to permit persons to whom the Software is
  7154. // furnished to do so, subject to the following conditions:
  7155. //
  7156. // The above copyright notice and this permission notice shall be included in
  7157. // all copies or substantial portions of the Software.
  7158. //
  7159. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  7160. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  7161. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  7162. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  7163. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  7164. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  7165. // IN THE SOFTWARE.
  7166. ///////////////////////////////// DISCLAIMER /////////////////////////////////
  7167. // *This code was inspired by "Shader Amortization using Pixel Quad Message
  7168. // Passing" by Eric Penner, published in GPU Pro 2, Chapter VI.2. My intent
  7169. // is not to plagiarize his fundamentally similar code and assert my own
  7170. // copyright, but the algorithmic helper functions require so little code that
  7171. // implementations can't vary by much except bugfixes and conventions. I just
  7172. // wanted to license my own particular code here to avoid ambiguity and make it
  7173. // clear that as far as I'm concerned, people can do as they please with it.
  7174. ///////////////////////////////// DESCRIPTION ////////////////////////////////
  7175. // Given screen pixel numbers, derive a "quad vector" describing a fragment's
  7176. // position in its 2x2 pixel quad. Given that vector, obtain the values of any
  7177. // variable at neighboring fragments.
  7178. // Requires: Using this file in general requires:
  7179. // 1.) ddx() and ddy() are present in the current Cg profile.
  7180. // 2.) The GPU driver is using fine/high-quality derivatives.
  7181. // Functions will give incorrect results if this is not true,
  7182. // so a test function is included.
  7183. ///////////////////// QUAD-PIXEL COMMUNICATION PRIMITIVES ////////////////////
  7184. float4 get_quad_vector_naive(float4 output_pixel_num_wrt_uvxy)
  7185. {
  7186. // Requires: Two measures of the current fragment's output pixel number
  7187. // in the range ([0, output_size.x), [0, output_size.y)):
  7188. // 1.) output_pixel_num_wrt_uvxy.xy increase with uv coords.
  7189. // 2.) output_pixel_num_wrt_uvxy.zw increase with screen xy.
  7190. // Returns: Two measures of the fragment's position in its 2x2 quad:
  7191. // 1.) The .xy components are its 2x2 placement with respect to
  7192. // uv direction (the origin (0, 0) is at the top-left):
  7193. // top-left = (-1.0, -1.0) top-right = ( 1.0, -1.0)
  7194. // bottom-left = (-1.0, 1.0) bottom-right = ( 1.0, 1.0)
  7195. // You need this to arrange/weight shared texture samples.
  7196. // 2.) The .zw components are its 2x2 placement with respect to
  7197. // screen xy direction (position); the origin varies.
  7198. // quad_gather needs this measure to work correctly.
  7199. // Note: quad_vector.zw = quad_vector.xy * float2(
  7200. // ddx(output_pixel_num_wrt_uvxy.x),
  7201. // ddy(output_pixel_num_wrt_uvxy.y));
  7202. // Caveats: This function assumes the GPU driver always starts 2x2 pixel
  7203. // quads at even pixel numbers. This assumption can be wrong
  7204. // for odd output resolutions (nondeterministically so).
  7205. float4 pixel_odd = frac(output_pixel_num_wrt_uvxy * 0.5) * 2.0;
  7206. float4 quad_vector = pixel_odd * 2.0 - float4(1.0);
  7207. return quad_vector;
  7208. }
  7209. float4 get_quad_vector(float4 output_pixel_num_wrt_uvxy)
  7210. {
  7211. // Requires: Same as get_quad_vector_naive() (see that first).
  7212. // Returns: Same as get_quad_vector_naive() (see that first), but it's
  7213. // correct even if the 2x2 pixel quad starts at an odd pixel,
  7214. // which can occur at odd resolutions.
  7215. float4 quad_vector_guess =
  7216. get_quad_vector_naive(output_pixel_num_wrt_uvxy);
  7217. // If quad_vector_guess.zw doesn't increase with screen xy, we know
  7218. // the 2x2 pixel quad starts at an odd pixel:
  7219. float2 odd_start_mirror = 0.5 * float2(ddx(quad_vector_guess.z),
  7220. ddy(quad_vector_guess.w));
  7221. return quad_vector_guess * odd_start_mirror.xyxy;
  7222. }
  7223. float4 get_quad_vector(float2 output_pixel_num_wrt_uv)
  7224. {
  7225. // Requires: 1.) ddx() and ddy() are present in the current Cg profile.
  7226. // 2.) output_pixel_num_wrt_uv must increase with uv coords and
  7227. // measure the current fragment's output pixel number in:
  7228. // ([0, output_size.x), [0, output_size.y))
  7229. // Returns: Same as get_quad_vector_naive() (see that first), but it's
  7230. // correct even if the 2x2 pixel quad starts at an odd pixel,
  7231. // which can occur at odd resolutions.
  7232. // Caveats: This function requires less information than the version
  7233. // taking a float4, but it's potentially slower.
  7234. // Do screen coords increase with or against uv? Get the direction
  7235. // with respect to (uv.x, uv.y) for (screen.x, screen.y) in {-1, 1}.
  7236. float2 screen_uv_mirror = float2(ddx(output_pixel_num_wrt_uv.x),
  7237. ddy(output_pixel_num_wrt_uv.y));
  7238. float2 pixel_odd_wrt_uv = frac(output_pixel_num_wrt_uv * 0.5) * 2.0;
  7239. float2 quad_vector_uv_guess = (pixel_odd_wrt_uv - float2(0.5)) * 2.0;
  7240. float2 quad_vector_screen_guess = quad_vector_uv_guess * screen_uv_mirror;
  7241. // If quad_vector_screen_guess doesn't increase with screen xy, we know
  7242. // the 2x2 pixel quad starts at an odd pixel:
  7243. float2 odd_start_mirror = 0.5 * float2(ddx(quad_vector_screen_guess.x),
  7244. ddy(quad_vector_screen_guess.y));
  7245. float4 quad_vector_guess = float4(
  7246. quad_vector_uv_guess, quad_vector_screen_guess);
  7247. return quad_vector_guess * odd_start_mirror.xyxy;
  7248. }
  7249. void quad_gather(float4 quad_vector, float4 curr,
  7250. out float4 adjx, out float4 adjy, out float4 diag)
  7251. {
  7252. // Requires: 1.) ddx() and ddy() are present in the current Cg profile.
  7253. // 2.) The GPU driver is using fine/high-quality derivatives.
  7254. // 3.) quad_vector describes the current fragment's location in
  7255. // its 2x2 pixel quad using get_quad_vector()'s conventions.
  7256. // 4.) curr is any vector you wish to get neighboring values of.
  7257. // Returns: Values of an input vector (curr) at neighboring fragments
  7258. // adjacent x, adjacent y, and diagonal (via out parameters).
  7259. adjx = curr - ddx(curr) * quad_vector.z;
  7260. adjy = curr - ddy(curr) * quad_vector.w;
  7261. diag = adjx - ddy(adjx) * quad_vector.w;
  7262. }
  7263. void quad_gather(float4 quad_vector, float3 curr,
  7264. out float3 adjx, out float3 adjy, out float3 diag)
  7265. {
  7266. // Float3 version
  7267. adjx = curr - ddx(curr) * quad_vector.z;
  7268. adjy = curr - ddy(curr) * quad_vector.w;
  7269. diag = adjx - ddy(adjx) * quad_vector.w;
  7270. }
  7271. void quad_gather(float4 quad_vector, float2 curr,
  7272. out float2 adjx, out float2 adjy, out float2 diag)
  7273. {
  7274. // Float2 version
  7275. adjx = curr - ddx(curr) * quad_vector.z;
  7276. adjy = curr - ddy(curr) * quad_vector.w;
  7277. diag = adjx - ddy(adjx) * quad_vector.w;
  7278. }
  7279. float4 quad_gather(float4 quad_vector, float curr)
  7280. {
  7281. // Float version:
  7282. // Returns: return.x == current
  7283. // return.y == adjacent x
  7284. // return.z == adjacent y
  7285. // return.w == diagonal
  7286. float4 all = float4(curr);
  7287. all.y = all.x - ddx(all.x) * quad_vector.z;
  7288. all.zw = all.xy - ddy(all.xy) * quad_vector.w;
  7289. return all;
  7290. }
  7291. float4 quad_gather_sum(float4 quad_vector, float4 curr)
  7292. {
  7293. // Requires: Same as quad_gather()
  7294. // Returns: Sum of an input vector (curr) at all fragments in a quad.
  7295. float4 adjx, adjy, diag;
  7296. quad_gather(quad_vector, curr, adjx, adjy, diag);
  7297. return (curr + adjx + adjy + diag);
  7298. }
  7299. float3 quad_gather_sum(float4 quad_vector, float3 curr)
  7300. {
  7301. // Float3 version:
  7302. float3 adjx, adjy, diag;
  7303. quad_gather(quad_vector, curr, adjx, adjy, diag);
  7304. return (curr + adjx + adjy + diag);
  7305. }
  7306. float2 quad_gather_sum(float4 quad_vector, float2 curr)
  7307. {
  7308. // Float2 version:
  7309. float2 adjx, adjy, diag;
  7310. quad_gather(quad_vector, curr, adjx, adjy, diag);
  7311. return (curr + adjx + adjy + diag);
  7312. }
  7313. float quad_gather_sum(float4 quad_vector, float curr)
  7314. {
  7315. // Float version:
  7316. float4 all_values = quad_gather(quad_vector, curr);
  7317. return (all_values.x + all_values.y + all_values.z + all_values.w);
  7318. }
  7319. bool fine_derivatives_working(float4 quad_vector, float4 curr)
  7320. {
  7321. // Requires: 1.) ddx() and ddy() are present in the current Cg profile.
  7322. // 2.) quad_vector describes the current fragment's location in
  7323. // its 2x2 pixel quad using get_quad_vector()'s conventions.
  7324. // 3.) curr must be a test vector with non-constant derivatives
  7325. // (its value should change nonlinearly across fragments).
  7326. // Returns: true if fine/hybrid/high-quality derivatives are used, or
  7327. // false if coarse derivatives are used or inconclusive
  7328. // Usage: Test whether quad-pixel communication is working!
  7329. // Method: We can confirm fine derivatives are used if the following
  7330. // holds (ever, for any value at any fragment):
  7331. // (ddy(curr) != ddy(adjx)) or (ddx(curr) != ddx(adjy))
  7332. // The more values we test (e.g. test a float4 two ways), the
  7333. // easier it is to demonstrate fine derivatives are working.
  7334. // TODO: Check for floating point exact comparison issues!
  7335. float4 ddx_curr = ddx(curr);
  7336. float4 ddy_curr = ddy(curr);
  7337. float4 adjx = curr - ddx_curr * quad_vector.z;
  7338. float4 adjy = curr - ddy_curr * quad_vector.w;
  7339. bool ddy_different = any(bool4(ddy_curr.x != ddy(adjx).x, ddy_curr.y != ddy(adjx).y, ddy_curr.z != ddy(adjx).z, ddy_curr.w != ddy(adjx).w));
  7340. bool ddx_different = any(bool4(ddx_curr.x != ddx(adjy).x, ddx_curr.y != ddx(adjy).y, ddx_curr.z != ddx(adjy).z, ddx_curr.w != ddx(adjy).w));
  7341. return any(bool2(ddy_different, ddx_different));
  7342. }
  7343. bool fine_derivatives_working_fast(float4 quad_vector, float curr)
  7344. {
  7345. // Requires: Same as fine_derivatives_working()
  7346. // Returns: Same as fine_derivatives_working()
  7347. // Usage: This is faster than fine_derivatives_working() but more
  7348. // likely to return false negatives, so it's less useful for
  7349. // offline testing/debugging. It's also useless as the basis
  7350. // for dynamic runtime branching as of May 2014: Derivatives
  7351. // (and quad-pixel communication) are currently disallowed in
  7352. // branches. However, future GPU's may allow you to use them
  7353. // in dynamic branches if you promise the branch condition
  7354. // evaluates the same for every fragment in the quad (and/or if
  7355. // the driver enforces that promise by making a single fragment
  7356. // control branch decisions). If that ever happens, this
  7357. // version may become a more economical choice.
  7358. float ddx_curr = ddx(curr);
  7359. float ddy_curr = ddy(curr);
  7360. float adjx = curr - ddx_curr * quad_vector.z;
  7361. return (ddy_curr != ddy(adjx));
  7362. }
  7363. #endif // QUAD_PIXEL_COMMUNICATION_H
  7364. //////////////////////// END QUAD-PIXEL-COMMUNICATION ///////////////////////
  7365. //#include "special-functions.h"
  7366. /////////////////////////// BEGIN SPECIAL-FUNCTIONS //////////////////////////
  7367. #ifndef SPECIAL_FUNCTIONS_H
  7368. #define SPECIAL_FUNCTIONS_H
  7369. ///////////////////////////////// MIT LICENSE ////////////////////////////////
  7370. // Copyright (C) 2014 TroggleMonkey
  7371. //
  7372. // Permission is hereby granted, free of charge, to any person obtaining a copy
  7373. // of this software and associated documentation files (the "Software"), to
  7374. // deal in the Software without restriction, including without limitation the
  7375. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  7376. // sell copies of the Software, and to permit persons to whom the Software is
  7377. // furnished to do so, subject to the following conditions:
  7378. //
  7379. // The above copyright notice and this permission notice shall be included in
  7380. // all copies or substantial portions of the Software.
  7381. //
  7382. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  7383. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  7384. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  7385. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  7386. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  7387. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  7388. // IN THE SOFTWARE.
  7389. ///////////////////////////////// DESCRIPTION ////////////////////////////////
  7390. // This file implements the following mathematical special functions:
  7391. // 1.) erf() = 2/sqrt(pi) * indefinite_integral(e**(-x**2))
  7392. // 2.) gamma(s), a real-numbered extension of the integer factorial function
  7393. // It also implements normalized_ligamma(s, z), a normalized lower incomplete
  7394. // gamma function for s < 0.5 only. Both gamma() and normalized_ligamma() can
  7395. // be called with an _impl suffix to use an implementation version with a few
  7396. // extra precomputed parameters (which may be useful for the caller to reuse).
  7397. // See below for details.
  7398. //
  7399. // Design Rationale:
  7400. // Pretty much every line of code in this file is duplicated four times for
  7401. // different input types (float4/float3/float2/float). This is unfortunate,
  7402. // but Cg doesn't allow function templates. Macros would be far less verbose,
  7403. // but they would make the code harder to document and read. I don't expect
  7404. // these functions will require a whole lot of maintenance changes unless
  7405. // someone ever has need for more robust incomplete gamma functions, so code
  7406. // duplication seems to be the lesser evil in this case.
  7407. /////////////////////////// GAUSSIAN ERROR FUNCTION //////////////////////////
  7408. float4 erf6(float4 x)
  7409. {
  7410. // Requires: x is the standard parameter to erf().
  7411. // Returns: Return an Abramowitz/Stegun approximation of erf(), where:
  7412. // erf(x) = 2/sqrt(pi) * integral(e**(-x**2))
  7413. // This approximation has a max absolute error of 2.5*10**-5
  7414. // with solid numerical robustness and efficiency. See:
  7415. // https://en.wikipedia.org/wiki/Error_function#Approximation_with_elementary_functions
  7416. static const float4 one = float4(1.0);
  7417. const float4 sign_x = sign(x);
  7418. const float4 t = one/(one + 0.47047*abs(x));
  7419. const float4 result = one - t*(0.3480242 + t*(-0.0958798 + t*0.7478556))*
  7420. exp(-(x*x));
  7421. return result * sign_x;
  7422. }
  7423. float3 erf6(const float3 x)
  7424. {
  7425. // Float3 version:
  7426. static const float3 one = float3(1.0);
  7427. const float3 sign_x = sign(x);
  7428. const float3 t = one/(one + 0.47047*abs(x));
  7429. const float3 result = one - t*(0.3480242 + t*(-0.0958798 + t*0.7478556))*
  7430. exp(-(x*x));
  7431. return result * sign_x;
  7432. }
  7433. float2 erf6(const float2 x)
  7434. {
  7435. // Float2 version:
  7436. static const float2 one = float2(1.0);
  7437. const float2 sign_x = sign(x);
  7438. const float2 t = one/(one + 0.47047*abs(x));
  7439. const float2 result = one - t*(0.3480242 + t*(-0.0958798 + t*0.7478556))*
  7440. exp(-(x*x));
  7441. return result * sign_x;
  7442. }
  7443. float erf6(const float x)
  7444. {
  7445. // Float version:
  7446. const float sign_x = sign(x);
  7447. const float t = 1.0/(1.0 + 0.47047*abs(x));
  7448. const float result = 1.0 - t*(0.3480242 + t*(-0.0958798 + t*0.7478556))*
  7449. exp(-(x*x));
  7450. return result * sign_x;
  7451. }
  7452. float4 erft(const float4 x)
  7453. {
  7454. // Requires: x is the standard parameter to erf().
  7455. // Returns: Approximate erf() with the hyperbolic tangent. The error is
  7456. // visually noticeable, but it's blazing fast and perceptually
  7457. // close...at least on ATI hardware. See:
  7458. // http://www.maplesoft.com/applications/view.aspx?SID=5525&view=html
  7459. // Warning: Only use this if your hardware drivers correctly implement
  7460. // tanh(): My nVidia 8800GTS returns garbage output.
  7461. return tanh(1.202760580 * x);
  7462. }
  7463. float3 erft(const float3 x)
  7464. {
  7465. // Float3 version:
  7466. return tanh(1.202760580 * x);
  7467. }
  7468. float2 erft(const float2 x)
  7469. {
  7470. // Float2 version:
  7471. return tanh(1.202760580 * x);
  7472. }
  7473. float erft(const float x)
  7474. {
  7475. // Float version:
  7476. return tanh(1.202760580 * x);
  7477. }
  7478. inline float4 erf(const float4 x)
  7479. {
  7480. // Requires: x is the standard parameter to erf().
  7481. // Returns: Some approximation of erf(x), depending on user settings.
  7482. #ifdef ERF_FAST_APPROXIMATION
  7483. return erft(x);
  7484. #else
  7485. return erf6(x);
  7486. #endif
  7487. }
  7488. inline float3 erf(const float3 x)
  7489. {
  7490. // Float3 version:
  7491. #ifdef ERF_FAST_APPROXIMATION
  7492. return erft(x);
  7493. #else
  7494. return erf6(x);
  7495. #endif
  7496. }
  7497. inline float2 erf(const float2 x)
  7498. {
  7499. // Float2 version:
  7500. #ifdef ERF_FAST_APPROXIMATION
  7501. return erft(x);
  7502. #else
  7503. return erf6(x);
  7504. #endif
  7505. }
  7506. inline float erf(const float x)
  7507. {
  7508. // Float version:
  7509. #ifdef ERF_FAST_APPROXIMATION
  7510. return erft(x);
  7511. #else
  7512. return erf6(x);
  7513. #endif
  7514. }
  7515. /////////////////////////// COMPLETE GAMMA FUNCTION //////////////////////////
  7516. float4 gamma_impl(const float4 s, const float4 s_inv)
  7517. {
  7518. // Requires: 1.) s is the standard parameter to the gamma function, and
  7519. // it should lie in the [0, 36] range.
  7520. // 2.) s_inv = 1.0/s. This implementation function requires
  7521. // the caller to precompute this value, giving users the
  7522. // opportunity to reuse it.
  7523. // Returns: Return approximate gamma function (real-numbered factorial)
  7524. // output using the Lanczos approximation with two coefficients
  7525. // calculated using Paul Godfrey's method here:
  7526. // http://my.fit.edu/~gabdo/gamma.txt
  7527. // An optimal g value for s in [0, 36] is ~1.12906830989, with
  7528. // a maximum relative error of 0.000463 for 2**16 equally
  7529. // evals. We could use three coeffs (0.0000346 error) without
  7530. // hurting latency, but this allows more parallelism with
  7531. // outside instructions.
  7532. static const float4 g = float4(1.12906830989);
  7533. static const float4 c0 = float4(0.8109119309638332633713423362694399653724431);
  7534. static const float4 c1 = float4(0.4808354605142681877121661197951496120000040);
  7535. static const float4 e = float4(2.71828182845904523536028747135266249775724709);
  7536. const float4 sph = s + float4(0.5);
  7537. const float4 lanczos_sum = c0 + c1/(s + float4(1.0));
  7538. const float4 base = (sph + g)/e; // or (s + g + float4(0.5))/e
  7539. // gamma(s + 1) = base**sph * lanczos_sum; divide by s for gamma(s).
  7540. // This has less error for small s's than (s -= 1.0) at the beginning.
  7541. return (pow(base, sph) * lanczos_sum) * s_inv;
  7542. }
  7543. float3 gamma_impl(const float3 s, const float3 s_inv)
  7544. {
  7545. // Float3 version:
  7546. static const float3 g = float3(1.12906830989);
  7547. static const float3 c0 = float3(0.8109119309638332633713423362694399653724431);
  7548. static const float3 c1 = float3(0.4808354605142681877121661197951496120000040);
  7549. static const float3 e = float3(2.71828182845904523536028747135266249775724709);
  7550. const float3 sph = s + float3(0.5);
  7551. const float3 lanczos_sum = c0 + c1/(s + float3(1.0));
  7552. const float3 base = (sph + g)/e;
  7553. return (pow(base, sph) * lanczos_sum) * s_inv;
  7554. }
  7555. float2 gamma_impl(const float2 s, const float2 s_inv)
  7556. {
  7557. // Float2 version:
  7558. static const float2 g = float2(1.12906830989);
  7559. static const float2 c0 = float2(0.8109119309638332633713423362694399653724431);
  7560. static const float2 c1 = float2(0.4808354605142681877121661197951496120000040);
  7561. static const float2 e = float2(2.71828182845904523536028747135266249775724709);
  7562. const float2 sph = s + float2(0.5);
  7563. const float2 lanczos_sum = c0 + c1/(s + float2(1.0));
  7564. const float2 base = (sph + g)/e;
  7565. return (pow(base, sph) * lanczos_sum) * s_inv;
  7566. }
  7567. float gamma_impl(const float s, const float s_inv)
  7568. {
  7569. // Float version:
  7570. static const float g = 1.12906830989;
  7571. static const float c0 = 0.8109119309638332633713423362694399653724431;
  7572. static const float c1 = 0.4808354605142681877121661197951496120000040;
  7573. static const float e = 2.71828182845904523536028747135266249775724709;
  7574. const float sph = s + 0.5;
  7575. const float lanczos_sum = c0 + c1/(s + 1.0);
  7576. const float base = (sph + g)/e;
  7577. return (pow(base, sph) * lanczos_sum) * s_inv;
  7578. }
  7579. float4 gamma(const float4 s)
  7580. {
  7581. // Requires: s is the standard parameter to the gamma function, and it
  7582. // should lie in the [0, 36] range.
  7583. // Returns: Return approximate gamma function output with a maximum
  7584. // relative error of 0.000463. See gamma_impl for details.
  7585. return gamma_impl(s, float4(1.0)/s);
  7586. }
  7587. float3 gamma(const float3 s)
  7588. {
  7589. // Float3 version:
  7590. return gamma_impl(s, float3(1.0)/s);
  7591. }
  7592. float2 gamma(const float2 s)
  7593. {
  7594. // Float2 version:
  7595. return gamma_impl(s, float2(1.0)/s);
  7596. }
  7597. float gamma(const float s)
  7598. {
  7599. // Float version:
  7600. return gamma_impl(s, 1.0/s);
  7601. }
  7602. //////////////// INCOMPLETE GAMMA FUNCTIONS (RESTRICTED INPUT) ///////////////
  7603. // Lower incomplete gamma function for small s and z (implementation):
  7604. float4 ligamma_small_z_impl(const float4 s, const float4 z, const float4 s_inv)
  7605. {
  7606. // Requires: 1.) s < ~0.5
  7607. // 2.) z <= ~0.775075
  7608. // 3.) s_inv = 1.0/s (precomputed for outside reuse)
  7609. // Returns: A series representation for the lower incomplete gamma
  7610. // function for small s and small z (4 terms).
  7611. // The actual "rolled up" summation looks like:
  7612. // last_sign = 1.0; last_pow = 1.0; last_factorial = 1.0;
  7613. // sum = last_sign * last_pow / ((s + k) * last_factorial)
  7614. // for(int i = 0; i < 4; ++i)
  7615. // {
  7616. // last_sign *= -1.0; last_pow *= z; last_factorial *= i;
  7617. // sum += last_sign * last_pow / ((s + k) * last_factorial);
  7618. // }
  7619. // Unrolled, constant-unfolded and arranged for madds and parallelism:
  7620. const float4 scale = pow(z, s);
  7621. float4 sum = s_inv; // Summation iteration 0 result
  7622. // Summation iterations 1, 2, and 3:
  7623. const float4 z_sq = z*z;
  7624. const float4 denom1 = s + float4(1.0);
  7625. const float4 denom2 = 2.0*s + float4(4.0);
  7626. const float4 denom3 = 6.0*s + float4(18.0);
  7627. //float4 denom4 = 24.0*s + float4(96.0);
  7628. sum -= z/denom1;
  7629. sum += z_sq/denom2;
  7630. sum -= z * z_sq/denom3;
  7631. //sum += z_sq * z_sq / denom4;
  7632. // Scale and return:
  7633. return scale * sum;
  7634. }
  7635. float3 ligamma_small_z_impl(const float3 s, const float3 z, const float3 s_inv)
  7636. {
  7637. // Float3 version:
  7638. const float3 scale = pow(z, s);
  7639. float3 sum = s_inv;
  7640. const float3 z_sq = z*z;
  7641. const float3 denom1 = s + float3(1.0);
  7642. const float3 denom2 = 2.0*s + float3(4.0);
  7643. const float3 denom3 = 6.0*s + float3(18.0);
  7644. sum -= z/denom1;
  7645. sum += z_sq/denom2;
  7646. sum -= z * z_sq/denom3;
  7647. return scale * sum;
  7648. }
  7649. float2 ligamma_small_z_impl(const float2 s, const float2 z, const float2 s_inv)
  7650. {
  7651. // Float2 version:
  7652. const float2 scale = pow(z, s);
  7653. float2 sum = s_inv;
  7654. const float2 z_sq = z*z;
  7655. const float2 denom1 = s + float2(1.0);
  7656. const float2 denom2 = 2.0*s + float2(4.0);
  7657. const float2 denom3 = 6.0*s + float2(18.0);
  7658. sum -= z/denom1;
  7659. sum += z_sq/denom2;
  7660. sum -= z * z_sq/denom3;
  7661. return scale * sum;
  7662. }
  7663. float ligamma_small_z_impl(const float s, const float z, const float s_inv)
  7664. {
  7665. // Float version:
  7666. const float scale = pow(z, s);
  7667. float sum = s_inv;
  7668. const float z_sq = z*z;
  7669. const float denom1 = s + 1.0;
  7670. const float denom2 = 2.0*s + 4.0;
  7671. const float denom3 = 6.0*s + 18.0;
  7672. sum -= z/denom1;
  7673. sum += z_sq/denom2;
  7674. sum -= z * z_sq/denom3;
  7675. return scale * sum;
  7676. }
  7677. // Upper incomplete gamma function for small s and large z (implementation):
  7678. float4 uigamma_large_z_impl(const float4 s, const float4 z)
  7679. {
  7680. // Requires: 1.) s < ~0.5
  7681. // 2.) z > ~0.775075
  7682. // Returns: Gauss's continued fraction representation for the upper
  7683. // incomplete gamma function (4 terms).
  7684. // The "rolled up" continued fraction looks like this. The denominator
  7685. // is truncated, and it's calculated "from the bottom up:"
  7686. // denom = float4('inf');
  7687. // float4 one = float4(1.0);
  7688. // for(int i = 4; i > 0; --i)
  7689. // {
  7690. // denom = ((i * 2.0) - one) + z - s + (i * (s - i))/denom;
  7691. // }
  7692. // Unrolled and constant-unfolded for madds and parallelism:
  7693. const float4 numerator = pow(z, s) * exp(-z);
  7694. float4 denom = float4(7.0) + z - s;
  7695. denom = float4(5.0) + z - s + (3.0*s - float4(9.0))/denom;
  7696. denom = float4(3.0) + z - s + (2.0*s - float4(4.0))/denom;
  7697. denom = float4(1.0) + z - s + (s - float4(1.0))/denom;
  7698. return numerator / denom;
  7699. }
  7700. float3 uigamma_large_z_impl(const float3 s, const float3 z)
  7701. {
  7702. // Float3 version:
  7703. const float3 numerator = pow(z, s) * exp(-z);
  7704. float3 denom = float3(7.0) + z - s;
  7705. denom = float3(5.0) + z - s + (3.0*s - float3(9.0))/denom;
  7706. denom = float3(3.0) + z - s + (2.0*s - float3(4.0))/denom;
  7707. denom = float3(1.0) + z - s + (s - float3(1.0))/denom;
  7708. return numerator / denom;
  7709. }
  7710. float2 uigamma_large_z_impl(const float2 s, const float2 z)
  7711. {
  7712. // Float2 version:
  7713. const float2 numerator = pow(z, s) * exp(-z);
  7714. float2 denom = float2(7.0) + z - s;
  7715. denom = float2(5.0) + z - s + (3.0*s - float2(9.0))/denom;
  7716. denom = float2(3.0) + z - s + (2.0*s - float2(4.0))/denom;
  7717. denom = float2(1.0) + z - s + (s - float2(1.0))/denom;
  7718. return numerator / denom;
  7719. }
  7720. float uigamma_large_z_impl(const float s, const float z)
  7721. {
  7722. // Float version:
  7723. const float numerator = pow(z, s) * exp(-z);
  7724. float denom = 7.0 + z - s;
  7725. denom = 5.0 + z - s + (3.0*s - 9.0)/denom;
  7726. denom = 3.0 + z - s + (2.0*s - 4.0)/denom;
  7727. denom = 1.0 + z - s + (s - 1.0)/denom;
  7728. return numerator / denom;
  7729. }
  7730. // Normalized lower incomplete gamma function for small s (implementation):
  7731. float4 normalized_ligamma_impl(const float4 s, const float4 z,
  7732. const float4 s_inv, const float4 gamma_s_inv)
  7733. {
  7734. // Requires: 1.) s < ~0.5
  7735. // 2.) s_inv = 1/s (precomputed for outside reuse)
  7736. // 3.) gamma_s_inv = 1/gamma(s) (precomputed for outside reuse)
  7737. // Returns: Approximate the normalized lower incomplete gamma function
  7738. // for s < 0.5. Since we only care about s < 0.5, we only need
  7739. // to evaluate two branches (not four) based on z. Each branch
  7740. // uses four terms, with a max relative error of ~0.00182. The
  7741. // branch threshold and specifics were adapted for fewer terms
  7742. // from Gil/Segura/Temme's paper here:
  7743. // http://oai.cwi.nl/oai/asset/20433/20433B.pdf
  7744. // Evaluate both branches: Real branches test slower even when available.
  7745. static const float4 thresh = float4(0.775075);
  7746. bool4 z_is_large;
  7747. z_is_large.x = z.x > thresh.x;
  7748. z_is_large.y = z.y > thresh.y;
  7749. z_is_large.z = z.z > thresh.z;
  7750. z_is_large.w = z.w > thresh.w;
  7751. const float4 large_z = float4(1.0) - uigamma_large_z_impl(s, z) * gamma_s_inv;
  7752. const float4 small_z = ligamma_small_z_impl(s, z, s_inv) * gamma_s_inv;
  7753. // Combine the results from both branches:
  7754. bool4 inverse_z_is_large = not(z_is_large);
  7755. return large_z * float4(z_is_large) + small_z * float4(inverse_z_is_large);
  7756. }
  7757. float3 normalized_ligamma_impl(const float3 s, const float3 z,
  7758. const float3 s_inv, const float3 gamma_s_inv)
  7759. {
  7760. // Float3 version:
  7761. static const float3 thresh = float3(0.775075);
  7762. bool3 z_is_large;
  7763. z_is_large.x = z.x > thresh.x;
  7764. z_is_large.y = z.y > thresh.y;
  7765. z_is_large.z = z.z > thresh.z;
  7766. const float3 large_z = float3(1.0) - uigamma_large_z_impl(s, z) * gamma_s_inv;
  7767. const float3 small_z = ligamma_small_z_impl(s, z, s_inv) * gamma_s_inv;
  7768. bool3 inverse_z_is_large = not(z_is_large);
  7769. return large_z * float3(z_is_large) + small_z * float3(inverse_z_is_large);
  7770. }
  7771. float2 normalized_ligamma_impl(const float2 s, const float2 z,
  7772. const float2 s_inv, const float2 gamma_s_inv)
  7773. {
  7774. // Float2 version:
  7775. static const float2 thresh = float2(0.775075);
  7776. bool2 z_is_large;
  7777. z_is_large.x = z.x > thresh.x;
  7778. z_is_large.y = z.y > thresh.y;
  7779. const float2 large_z = float2(1.0) - uigamma_large_z_impl(s, z) * gamma_s_inv;
  7780. const float2 small_z = ligamma_small_z_impl(s, z, s_inv) * gamma_s_inv;
  7781. bool2 inverse_z_is_large = not(z_is_large);
  7782. return large_z * float2(z_is_large) + small_z * float2(inverse_z_is_large);
  7783. }
  7784. float normalized_ligamma_impl(const float s, const float z,
  7785. const float s_inv, const float gamma_s_inv)
  7786. {
  7787. // Float version:
  7788. static const float thresh = 0.775075;
  7789. const bool z_is_large = z > thresh;
  7790. const float large_z = 1.0 - uigamma_large_z_impl(s, z) * gamma_s_inv;
  7791. const float small_z = ligamma_small_z_impl(s, z, s_inv) * gamma_s_inv;
  7792. return large_z * float(z_is_large) + small_z * float(!z_is_large);
  7793. }
  7794. // Normalized lower incomplete gamma function for small s:
  7795. float4 normalized_ligamma(const float4 s, const float4 z)
  7796. {
  7797. // Requires: s < ~0.5
  7798. // Returns: Approximate the normalized lower incomplete gamma function
  7799. // for s < 0.5. See normalized_ligamma_impl() for details.
  7800. const float4 s_inv = float4(1.0)/s;
  7801. const float4 gamma_s_inv = float4(1.0)/gamma_impl(s, s_inv);
  7802. return normalized_ligamma_impl(s, z, s_inv, gamma_s_inv);
  7803. }
  7804. float3 normalized_ligamma(const float3 s, const float3 z)
  7805. {
  7806. // Float3 version:
  7807. const float3 s_inv = float3(1.0)/s;
  7808. const float3 gamma_s_inv = float3(1.0)/gamma_impl(s, s_inv);
  7809. return normalized_ligamma_impl(s, z, s_inv, gamma_s_inv);
  7810. }
  7811. float2 normalized_ligamma(const float2 s, const float2 z)
  7812. {
  7813. // Float2 version:
  7814. const float2 s_inv = float2(1.0)/s;
  7815. const float2 gamma_s_inv = float2(1.0)/gamma_impl(s, s_inv);
  7816. return normalized_ligamma_impl(s, z, s_inv, gamma_s_inv);
  7817. }
  7818. float normalized_ligamma(const float s, const float z)
  7819. {
  7820. // Float version:
  7821. const float s_inv = 1.0/s;
  7822. const float gamma_s_inv = 1.0/gamma_impl(s, s_inv);
  7823. return normalized_ligamma_impl(s, z, s_inv, gamma_s_inv);
  7824. }
  7825. #endif // SPECIAL_FUNCTIONS_H
  7826. //////////////////////////// END SPECIAL-FUNCTIONS ///////////////////////////
  7827. //////////////////////////////// END INCLUDES ////////////////////////////////
  7828. /////////////////////////////////// HELPERS //////////////////////////////////
  7829. inline float4 uv2_to_uv4(float2 tex_uv)
  7830. {
  7831. // Make a float2 uv offset safe for adding to float4 tex2Dlod coords:
  7832. return float4(tex_uv, 0.0, 0.0);
  7833. }
  7834. // Make a length squared helper macro (for usage with static constants):
  7835. #define LENGTH_SQ(vec) (dot(vec, vec))
  7836. inline float get_fast_gaussian_weight_sum_inv(const float sigma)
  7837. {
  7838. // We can use the Gaussian integral to calculate the asymptotic weight for
  7839. // the center pixel. Since the unnormalized center pixel weight is 1.0,
  7840. // the normalized weight is the same as the weight sum inverse. Given a
  7841. // large enough blur (9+), the asymptotic weight sum is close and faster:
  7842. // center_weight = 0.5 *
  7843. // (erf(0.5/(sigma*sqrt(2.0))) - erf(-0.5/(sigma*sqrt(2.0))))
  7844. // erf(-x) == -erf(x), so we get 0.5 * (2.0 * erf(blah blah)):
  7845. // However, we can get even faster results with curve-fitting. These are
  7846. // also closer than the asymptotic results, because they were constructed
  7847. // from 64 blurs sizes from [3, 131) and 255 equally-spaced sigmas from
  7848. // (0, blurN_std_dev), so the results for smaller sigmas are biased toward
  7849. // smaller blurs. The max error is 0.0031793913.
  7850. // Relative FPS: 134.3 with erf, 135.8 with curve-fitting.
  7851. //static const float temp = 0.5/sqrt(2.0);
  7852. //return erf(temp/sigma);
  7853. return min(exp(exp(0.348348412457428/
  7854. (sigma - 0.0860587260734721))), 0.399334576340352/sigma);
  7855. }
  7856. //////////////////// ARBITRARILY RESIZABLE SEPARABLE BLURS ///////////////////
  7857. float3 tex2Dblur11resize(const sampler2D tex, const float2 tex_uv,
  7858. const float2 dxdy, const float sigma)
  7859. {
  7860. // Requires: Global requirements must be met (see file description).
  7861. // Returns: A 1D 11x Gaussian blurred texture lookup using a 11-tap blur.
  7862. // It may be mipmapped depending on settings and dxdy.
  7863. // Calculate Gaussian blur kernel weights and a normalization factor for
  7864. // distances of 0-4, ignoring constant factors (since we're normalizing).
  7865. const float denom_inv = 0.5/(sigma*sigma);
  7866. const float w0 = 1.0;
  7867. const float w1 = exp(-1.0 * denom_inv);
  7868. const float w2 = exp(-4.0 * denom_inv);
  7869. const float w3 = exp(-9.0 * denom_inv);
  7870. const float w4 = exp(-16.0 * denom_inv);
  7871. const float w5 = exp(-25.0 * denom_inv);
  7872. const float weight_sum_inv = 1.0 /
  7873. (w0 + 2.0 * (w1 + w2 + w3 + w4 + w5));
  7874. // Statically normalize weights, sum weighted samples, and return. Blurs are
  7875. // currently optimized for dynamic weights.
  7876. float3 sum = float3(0.0,0.0,0.0);
  7877. sum += w5 * tex2D_linearize(tex, tex_uv - 5.0 * dxdy).rgb;
  7878. sum += w4 * tex2D_linearize(tex, tex_uv - 4.0 * dxdy).rgb;
  7879. sum += w3 * tex2D_linearize(tex, tex_uv - 3.0 * dxdy).rgb;
  7880. sum += w2 * tex2D_linearize(tex, tex_uv - 2.0 * dxdy).rgb;
  7881. sum += w1 * tex2D_linearize(tex, tex_uv - 1.0 * dxdy).rgb;
  7882. sum += w0 * tex2D_linearize(tex, tex_uv).rgb;
  7883. sum += w1 * tex2D_linearize(tex, tex_uv + 1.0 * dxdy).rgb;
  7884. sum += w2 * tex2D_linearize(tex, tex_uv + 2.0 * dxdy).rgb;
  7885. sum += w3 * tex2D_linearize(tex, tex_uv + 3.0 * dxdy).rgb;
  7886. sum += w4 * tex2D_linearize(tex, tex_uv + 4.0 * dxdy).rgb;
  7887. sum += w5 * tex2D_linearize(tex, tex_uv + 5.0 * dxdy).rgb;
  7888. return sum * weight_sum_inv;
  7889. }
  7890. float3 tex2Dblur9resize(const sampler2D tex, const float2 tex_uv,
  7891. const float2 dxdy, const float sigma)
  7892. {
  7893. // Requires: Global requirements must be met (see file description).
  7894. // Returns: A 1D 9x Gaussian blurred texture lookup using a 9-tap blur.
  7895. // It may be mipmapped depending on settings and dxdy.
  7896. // First get the texel weights and normalization factor as above.
  7897. const float denom_inv = 0.5/(sigma*sigma);
  7898. const float w0 = 1.0;
  7899. const float w1 = exp(-1.0 * denom_inv);
  7900. const float w2 = exp(-4.0 * denom_inv);
  7901. const float w3 = exp(-9.0 * denom_inv);
  7902. const float w4 = exp(-16.0 * denom_inv);
  7903. const float weight_sum_inv = 1.0 / (w0 + 2.0 * (w1 + w2 + w3 + w4));
  7904. // Statically normalize weights, sum weighted samples, and return:
  7905. float3 sum = float3(0.0,0.0,0.0);
  7906. sum += w4 * tex2D_linearize(tex, tex_uv - 4.0 * dxdy).rgb;
  7907. sum += w3 * tex2D_linearize(tex, tex_uv - 3.0 * dxdy).rgb;
  7908. sum += w2 * tex2D_linearize(tex, tex_uv - 2.0 * dxdy).rgb;
  7909. sum += w1 * tex2D_linearize(tex, tex_uv - 1.0 * dxdy).rgb;
  7910. sum += w0 * tex2D_linearize(tex, tex_uv).rgb;
  7911. sum += w1 * tex2D_linearize(tex, tex_uv + 1.0 * dxdy).rgb;
  7912. sum += w2 * tex2D_linearize(tex, tex_uv + 2.0 * dxdy).rgb;
  7913. sum += w3 * tex2D_linearize(tex, tex_uv + 3.0 * dxdy).rgb;
  7914. sum += w4 * tex2D_linearize(tex, tex_uv + 4.0 * dxdy).rgb;
  7915. return sum * weight_sum_inv;
  7916. }
  7917. float3 tex2Dblur7resize(const sampler2D tex, const float2 tex_uv,
  7918. const float2 dxdy, const float sigma)
  7919. {
  7920. // Requires: Global requirements must be met (see file description).
  7921. // Returns: A 1D 7x Gaussian blurred texture lookup using a 7-tap blur.
  7922. // It may be mipmapped depending on settings and dxdy.
  7923. // First get the texel weights and normalization factor as above.
  7924. const float denom_inv = 0.5/(sigma*sigma);
  7925. const float w0 = 1.0;
  7926. const float w1 = exp(-1.0 * denom_inv);
  7927. const float w2 = exp(-4.0 * denom_inv);
  7928. const float w3 = exp(-9.0 * denom_inv);
  7929. const float weight_sum_inv = 1.0 / (w0 + 2.0 * (w1 + w2 + w3));
  7930. // Statically normalize weights, sum weighted samples, and return:
  7931. float3 sum = float3(0.0,0.0,0.0);
  7932. sum += w3 * tex2D_linearize(tex, tex_uv - 3.0 * dxdy).rgb;
  7933. sum += w2 * tex2D_linearize(tex, tex_uv - 2.0 * dxdy).rgb;
  7934. sum += w1 * tex2D_linearize(tex, tex_uv - 1.0 * dxdy).rgb;
  7935. sum += w0 * tex2D_linearize(tex, tex_uv).rgb;
  7936. sum += w1 * tex2D_linearize(tex, tex_uv + 1.0 * dxdy).rgb;
  7937. sum += w2 * tex2D_linearize(tex, tex_uv + 2.0 * dxdy).rgb;
  7938. sum += w3 * tex2D_linearize(tex, tex_uv + 3.0 * dxdy).rgb;
  7939. return sum * weight_sum_inv;
  7940. }
  7941. float3 tex2Dblur5resize(const sampler2D tex, const float2 tex_uv,
  7942. const float2 dxdy, const float sigma)
  7943. {
  7944. // Requires: Global requirements must be met (see file description).
  7945. // Returns: A 1D 5x Gaussian blurred texture lookup using a 5-tap blur.
  7946. // It may be mipmapped depending on settings and dxdy.
  7947. // First get the texel weights and normalization factor as above.
  7948. const float denom_inv = 0.5/(sigma*sigma);
  7949. const float w0 = 1.0;
  7950. const float w1 = exp(-1.0 * denom_inv);
  7951. const float w2 = exp(-4.0 * denom_inv);
  7952. const float weight_sum_inv = 1.0 / (w0 + 2.0 * (w1 + w2));
  7953. // Statically normalize weights, sum weighted samples, and return:
  7954. float3 sum = float3(0.0,0.0,0.0);
  7955. sum += w2 * tex2D_linearize(tex, tex_uv - 2.0 * dxdy).rgb;
  7956. sum += w1 * tex2D_linearize(tex, tex_uv - 1.0 * dxdy).rgb;
  7957. sum += w0 * tex2D_linearize(tex, tex_uv).rgb;
  7958. sum += w1 * tex2D_linearize(tex, tex_uv + 1.0 * dxdy).rgb;
  7959. sum += w2 * tex2D_linearize(tex, tex_uv + 2.0 * dxdy).rgb;
  7960. return sum * weight_sum_inv;
  7961. }
  7962. float3 tex2Dblur3resize(const sampler2D tex, const float2 tex_uv,
  7963. const float2 dxdy, const float sigma)
  7964. {
  7965. // Requires: Global requirements must be met (see file description).
  7966. // Returns: A 1D 3x Gaussian blurred texture lookup using a 3-tap blur.
  7967. // It may be mipmapped depending on settings and dxdy.
  7968. // First get the texel weights and normalization factor as above.
  7969. const float denom_inv = 0.5/(sigma*sigma);
  7970. const float w0 = 1.0;
  7971. const float w1 = exp(-1.0 * denom_inv);
  7972. const float weight_sum_inv = 1.0 / (w0 + 2.0 * w1);
  7973. // Statically normalize weights, sum weighted samples, and return:
  7974. float3 sum = float3(0.0,0.0,0.0);
  7975. sum += w1 * tex2D_linearize(tex, tex_uv - 1.0 * dxdy).rgb;
  7976. sum += w0 * tex2D_linearize(tex, tex_uv).rgb;
  7977. sum += w1 * tex2D_linearize(tex, tex_uv + 1.0 * dxdy).rgb;
  7978. return sum * weight_sum_inv;
  7979. }
  7980. /////////////////////////// FAST SEPARABLE BLURS ///////////////////////////
  7981. float3 tex2Dblur11fast(const sampler2D tex, const float2 tex_uv,
  7982. const float2 dxdy, const float sigma)
  7983. {
  7984. // Requires: 1.) Global requirements must be met (see file description).
  7985. // 2.) filter_linearN must = "true" in your .cgp file.
  7986. // 3.) For gamma-correct bilinear filtering, global
  7987. // gamma_aware_bilinear == true (from gamma-management.h)
  7988. // Returns: A 1D 11x Gaussian blurred texture lookup using 6 linear
  7989. // taps. It may be mipmapped depending on settings and dxdy.
  7990. // First get the texel weights and normalization factor as above.
  7991. const float denom_inv = 0.5/(sigma*sigma);
  7992. const float w0 = 1.0;
  7993. const float w1 = exp(-1.0 * denom_inv);
  7994. const float w2 = exp(-4.0 * denom_inv);
  7995. const float w3 = exp(-9.0 * denom_inv);
  7996. const float w4 = exp(-16.0 * denom_inv);
  7997. const float w5 = exp(-25.0 * denom_inv);
  7998. const float weight_sum_inv = 1.0 /
  7999. (w0 + 2.0 * (w1 + w2 + w3 + w4 + w5));
  8000. // Calculate combined weights and linear sample ratios between texel pairs.
  8001. // The center texel (with weight w0) is used twice, so halve its weight.
  8002. const float w01 = w0 * 0.5 + w1;
  8003. const float w23 = w2 + w3;
  8004. const float w45 = w4 + w5;
  8005. const float w01_ratio = w1/w01;
  8006. const float w23_ratio = w3/w23;
  8007. const float w45_ratio = w5/w45;
  8008. // Statically normalize weights, sum weighted samples, and return:
  8009. float3 sum = float3(0.0,0.0,0.0);
  8010. sum += w45 * tex2D_linearize(tex, tex_uv - (4.0 + w45_ratio) * dxdy).rgb;
  8011. sum += w23 * tex2D_linearize(tex, tex_uv - (2.0 + w23_ratio) * dxdy).rgb;
  8012. sum += w01 * tex2D_linearize(tex, tex_uv - w01_ratio * dxdy).rgb;
  8013. sum += w01 * tex2D_linearize(tex, tex_uv + w01_ratio * dxdy).rgb;
  8014. sum += w23 * tex2D_linearize(tex, tex_uv + (2.0 + w23_ratio) * dxdy).rgb;
  8015. sum += w45 * tex2D_linearize(tex, tex_uv + (4.0 + w45_ratio) * dxdy).rgb;
  8016. return sum * weight_sum_inv;
  8017. }
  8018. float3 tex2Dblur9fast(const sampler2D tex, const float2 tex_uv,
  8019. const float2 dxdy, const float sigma)
  8020. {
  8021. // Requires: Same as tex2Dblur11()
  8022. // Returns: A 1D 9x Gaussian blurred texture lookup using 1 nearest
  8023. // neighbor and 4 linear taps. It may be mipmapped depending
  8024. // on settings and dxdy.
  8025. // First get the texel weights and normalization factor as above.
  8026. const float denom_inv = 0.5/(sigma*sigma);
  8027. const float w0 = 1.0;
  8028. const float w1 = exp(-1.0 * denom_inv);
  8029. const float w2 = exp(-4.0 * denom_inv);
  8030. const float w3 = exp(-9.0 * denom_inv);
  8031. const float w4 = exp(-16.0 * denom_inv);
  8032. const float weight_sum_inv = 1.0 / (w0 + 2.0 * (w1 + w2 + w3 + w4));
  8033. // Calculate combined weights and linear sample ratios between texel pairs.
  8034. const float w12 = w1 + w2;
  8035. const float w34 = w3 + w4;
  8036. const float w12_ratio = w2/w12;
  8037. const float w34_ratio = w4/w34;
  8038. // Statically normalize weights, sum weighted samples, and return:
  8039. float3 sum = float3(0.0,0.0,0.0);
  8040. sum += w34 * tex2D_linearize(tex, tex_uv - (3.0 + w34_ratio) * dxdy).rgb;
  8041. sum += w12 * tex2D_linearize(tex, tex_uv - (1.0 + w12_ratio) * dxdy).rgb;
  8042. sum += w0 * tex2D_linearize(tex, tex_uv).rgb;
  8043. sum += w12 * tex2D_linearize(tex, tex_uv + (1.0 + w12_ratio) * dxdy).rgb;
  8044. sum += w34 * tex2D_linearize(tex, tex_uv + (3.0 + w34_ratio) * dxdy).rgb;
  8045. return sum * weight_sum_inv;
  8046. }
  8047. float3 tex2Dblur7fast(const sampler2D tex, const float2 tex_uv,
  8048. const float2 dxdy, const float sigma)
  8049. {
  8050. // Requires: Same as tex2Dblur11()
  8051. // Returns: A 1D 7x Gaussian blurred texture lookup using 4 linear
  8052. // taps. It may be mipmapped depending on settings and dxdy.
  8053. // First get the texel weights and normalization factor as above.
  8054. const float denom_inv = 0.5/(sigma*sigma);
  8055. const float w0 = 1.0;
  8056. const float w1 = exp(-1.0 * denom_inv);
  8057. const float w2 = exp(-4.0 * denom_inv);
  8058. const float w3 = exp(-9.0 * denom_inv);
  8059. const float weight_sum_inv = 1.0 / (w0 + 2.0 * (w1 + w2 + w3));
  8060. // Calculate combined weights and linear sample ratios between texel pairs.
  8061. // The center texel (with weight w0) is used twice, so halve its weight.
  8062. const float w01 = w0 * 0.5 + w1;
  8063. const float w23 = w2 + w3;
  8064. const float w01_ratio = w1/w01;
  8065. const float w23_ratio = w3/w23;
  8066. // Statically normalize weights, sum weighted samples, and return:
  8067. float3 sum = float3(0.0,0.0,0.0);
  8068. sum += w23 * tex2D_linearize(tex, tex_uv - (2.0 + w23_ratio) * dxdy).rgb;
  8069. sum += w01 * tex2D_linearize(tex, tex_uv - w01_ratio * dxdy).rgb;
  8070. sum += w01 * tex2D_linearize(tex, tex_uv + w01_ratio * dxdy).rgb;
  8071. sum += w23 * tex2D_linearize(tex, tex_uv + (2.0 + w23_ratio) * dxdy).rgb;
  8072. return sum * weight_sum_inv;
  8073. }
  8074. float3 tex2Dblur5fast(const sampler2D tex, const float2 tex_uv,
  8075. const float2 dxdy, const float sigma)
  8076. {
  8077. // Requires: Same as tex2Dblur11()
  8078. // Returns: A 1D 5x Gaussian blurred texture lookup using 1 nearest
  8079. // neighbor and 2 linear taps. It may be mipmapped depending
  8080. // on settings and dxdy.
  8081. // First get the texel weights and normalization factor as above.
  8082. const float denom_inv = 0.5/(sigma*sigma);
  8083. const float w0 = 1.0;
  8084. const float w1 = exp(-1.0 * denom_inv);
  8085. const float w2 = exp(-4.0 * denom_inv);
  8086. const float weight_sum_inv = 1.0 / (w0 + 2.0 * (w1 + w2));
  8087. // Calculate combined weights and linear sample ratios between texel pairs.
  8088. const float w12 = w1 + w2;
  8089. const float w12_ratio = w2/w12;
  8090. // Statically normalize weights, sum weighted samples, and return:
  8091. float3 sum = float3(0.0,0.0,0.0);
  8092. sum += w12 * tex2D_linearize(tex, tex_uv - (1.0 + w12_ratio) * dxdy).rgb;
  8093. sum += w0 * tex2D_linearize(tex, tex_uv).rgb;
  8094. sum += w12 * tex2D_linearize(tex, tex_uv + (1.0 + w12_ratio) * dxdy).rgb;
  8095. return sum * weight_sum_inv;
  8096. }
  8097. float3 tex2Dblur3fast(const sampler2D tex, const float2 tex_uv,
  8098. const float2 dxdy, const float sigma)
  8099. {
  8100. // Requires: Same as tex2Dblur11()
  8101. // Returns: A 1D 3x Gaussian blurred texture lookup using 2 linear
  8102. // taps. It may be mipmapped depending on settings and dxdy.
  8103. // First get the texel weights and normalization factor as above.
  8104. const float denom_inv = 0.5/(sigma*sigma);
  8105. const float w0 = 1.0;
  8106. const float w1 = exp(-1.0 * denom_inv);
  8107. const float weight_sum_inv = 1.0 / (w0 + 2.0 * w1);
  8108. // Calculate combined weights and linear sample ratios between texel pairs.
  8109. // The center texel (with weight w0) is used twice, so halve its weight.
  8110. const float w01 = w0 * 0.5 + w1;
  8111. const float w01_ratio = w1/w01;
  8112. // Weights for all samples are the same, so just average them:
  8113. return 0.5 * (
  8114. tex2D_linearize(tex, tex_uv - w01_ratio * dxdy).rgb +
  8115. tex2D_linearize(tex, tex_uv + w01_ratio * dxdy).rgb);
  8116. }
  8117. //////////////////////////// HUGE SEPARABLE BLURS ////////////////////////////
  8118. // Huge separable blurs come only in "fast" versions.
  8119. float3 tex2Dblur43fast(const sampler2D tex, const float2 tex_uv,
  8120. const float2 dxdy, const float sigma)
  8121. {
  8122. // Requires: Same as tex2Dblur11()
  8123. // Returns: A 1D 43x Gaussian blurred texture lookup using 22 linear
  8124. // taps. It may be mipmapped depending on settings and dxdy.
  8125. // First get the texel weights and normalization factor as above.
  8126. const float denom_inv = 0.5/(sigma*sigma);
  8127. const float w0 = 1.0;
  8128. const float w1 = exp(-1.0 * denom_inv);
  8129. const float w2 = exp(-4.0 * denom_inv);
  8130. const float w3 = exp(-9.0 * denom_inv);
  8131. const float w4 = exp(-16.0 * denom_inv);
  8132. const float w5 = exp(-25.0 * denom_inv);
  8133. const float w6 = exp(-36.0 * denom_inv);
  8134. const float w7 = exp(-49.0 * denom_inv);
  8135. const float w8 = exp(-64.0 * denom_inv);
  8136. const float w9 = exp(-81.0 * denom_inv);
  8137. const float w10 = exp(-100.0 * denom_inv);
  8138. const float w11 = exp(-121.0 * denom_inv);
  8139. const float w12 = exp(-144.0 * denom_inv);
  8140. const float w13 = exp(-169.0 * denom_inv);
  8141. const float w14 = exp(-196.0 * denom_inv);
  8142. const float w15 = exp(-225.0 * denom_inv);
  8143. const float w16 = exp(-256.0 * denom_inv);
  8144. const float w17 = exp(-289.0 * denom_inv);
  8145. const float w18 = exp(-324.0 * denom_inv);
  8146. const float w19 = exp(-361.0 * denom_inv);
  8147. const float w20 = exp(-400.0 * denom_inv);
  8148. const float w21 = exp(-441.0 * denom_inv);
  8149. //const float weight_sum_inv = 1.0 /
  8150. // (w0 + 2.0 * (w1 + w2 + w3 + w4 + w5 + w6 + w7 + w8 + w9 + w10 + w11 +
  8151. // w12 + w13 + w14 + w15 + w16 + w17 + w18 + w19 + w20 + w21));
  8152. const float weight_sum_inv = get_fast_gaussian_weight_sum_inv(sigma);
  8153. // Calculate combined weights and linear sample ratios between texel pairs.
  8154. // The center texel (with weight w0) is used twice, so halve its weight.
  8155. const float w0_1 = w0 * 0.5 + w1;
  8156. const float w2_3 = w2 + w3;
  8157. const float w4_5 = w4 + w5;
  8158. const float w6_7 = w6 + w7;
  8159. const float w8_9 = w8 + w9;
  8160. const float w10_11 = w10 + w11;
  8161. const float w12_13 = w12 + w13;
  8162. const float w14_15 = w14 + w15;
  8163. const float w16_17 = w16 + w17;
  8164. const float w18_19 = w18 + w19;
  8165. const float w20_21 = w20 + w21;
  8166. const float w0_1_ratio = w1/w0_1;
  8167. const float w2_3_ratio = w3/w2_3;
  8168. const float w4_5_ratio = w5/w4_5;
  8169. const float w6_7_ratio = w7/w6_7;
  8170. const float w8_9_ratio = w9/w8_9;
  8171. const float w10_11_ratio = w11/w10_11;
  8172. const float w12_13_ratio = w13/w12_13;
  8173. const float w14_15_ratio = w15/w14_15;
  8174. const float w16_17_ratio = w17/w16_17;
  8175. const float w18_19_ratio = w19/w18_19;
  8176. const float w20_21_ratio = w21/w20_21;
  8177. // Statically normalize weights, sum weighted samples, and return:
  8178. float3 sum = float3(0.0,0.0,0.0);
  8179. sum += w20_21 * tex2D_linearize(tex, tex_uv - (20.0 + w20_21_ratio) * dxdy).rgb;
  8180. sum += w18_19 * tex2D_linearize(tex, tex_uv - (18.0 + w18_19_ratio) * dxdy).rgb;
  8181. sum += w16_17 * tex2D_linearize(tex, tex_uv - (16.0 + w16_17_ratio) * dxdy).rgb;
  8182. sum += w14_15 * tex2D_linearize(tex, tex_uv - (14.0 + w14_15_ratio) * dxdy).rgb;
  8183. sum += w12_13 * tex2D_linearize(tex, tex_uv - (12.0 + w12_13_ratio) * dxdy).rgb;
  8184. sum += w10_11 * tex2D_linearize(tex, tex_uv - (10.0 + w10_11_ratio) * dxdy).rgb;
  8185. sum += w8_9 * tex2D_linearize(tex, tex_uv - (8.0 + w8_9_ratio) * dxdy).rgb;
  8186. sum += w6_7 * tex2D_linearize(tex, tex_uv - (6.0 + w6_7_ratio) * dxdy).rgb;
  8187. sum += w4_5 * tex2D_linearize(tex, tex_uv - (4.0 + w4_5_ratio) * dxdy).rgb;
  8188. sum += w2_3 * tex2D_linearize(tex, tex_uv - (2.0 + w2_3_ratio) * dxdy).rgb;
  8189. sum += w0_1 * tex2D_linearize(tex, tex_uv - w0_1_ratio * dxdy).rgb;
  8190. sum += w0_1 * tex2D_linearize(tex, tex_uv + w0_1_ratio * dxdy).rgb;
  8191. sum += w2_3 * tex2D_linearize(tex, tex_uv + (2.0 + w2_3_ratio) * dxdy).rgb;
  8192. sum += w4_5 * tex2D_linearize(tex, tex_uv + (4.0 + w4_5_ratio) * dxdy).rgb;
  8193. sum += w6_7 * tex2D_linearize(tex, tex_uv + (6.0 + w6_7_ratio) * dxdy).rgb;
  8194. sum += w8_9 * tex2D_linearize(tex, tex_uv + (8.0 + w8_9_ratio) * dxdy).rgb;
  8195. sum += w10_11 * tex2D_linearize(tex, tex_uv + (10.0 + w10_11_ratio) * dxdy).rgb;
  8196. sum += w12_13 * tex2D_linearize(tex, tex_uv + (12.0 + w12_13_ratio) * dxdy).rgb;
  8197. sum += w14_15 * tex2D_linearize(tex, tex_uv + (14.0 + w14_15_ratio) * dxdy).rgb;
  8198. sum += w16_17 * tex2D_linearize(tex, tex_uv + (16.0 + w16_17_ratio) * dxdy).rgb;
  8199. sum += w18_19 * tex2D_linearize(tex, tex_uv + (18.0 + w18_19_ratio) * dxdy).rgb;
  8200. sum += w20_21 * tex2D_linearize(tex, tex_uv + (20.0 + w20_21_ratio) * dxdy).rgb;
  8201. return sum * weight_sum_inv;
  8202. }
  8203. float3 tex2Dblur31fast(const sampler2D tex, const float2 tex_uv,
  8204. const float2 dxdy, const float sigma)
  8205. {
  8206. // Requires: Same as tex2Dblur11()
  8207. // Returns: A 1D 31x Gaussian blurred texture lookup using 16 linear
  8208. // taps. It may be mipmapped depending on settings and dxdy.
  8209. // First get the texel weights and normalization factor as above.
  8210. const float denom_inv = 0.5/(sigma*sigma);
  8211. const float w0 = 1.0;
  8212. const float w1 = exp(-1.0 * denom_inv);
  8213. const float w2 = exp(-4.0 * denom_inv);
  8214. const float w3 = exp(-9.0 * denom_inv);
  8215. const float w4 = exp(-16.0 * denom_inv);
  8216. const float w5 = exp(-25.0 * denom_inv);
  8217. const float w6 = exp(-36.0 * denom_inv);
  8218. const float w7 = exp(-49.0 * denom_inv);
  8219. const float w8 = exp(-64.0 * denom_inv);
  8220. const float w9 = exp(-81.0 * denom_inv);
  8221. const float w10 = exp(-100.0 * denom_inv);
  8222. const float w11 = exp(-121.0 * denom_inv);
  8223. const float w12 = exp(-144.0 * denom_inv);
  8224. const float w13 = exp(-169.0 * denom_inv);
  8225. const float w14 = exp(-196.0 * denom_inv);
  8226. const float w15 = exp(-225.0 * denom_inv);
  8227. //const float weight_sum_inv = 1.0 /
  8228. // (w0 + 2.0 * (w1 + w2 + w3 + w4 + w5 + w6 + w7 + w8 +
  8229. // w9 + w10 + w11 + w12 + w13 + w14 + w15));
  8230. const float weight_sum_inv = get_fast_gaussian_weight_sum_inv(sigma);
  8231. // Calculate combined weights and linear sample ratios between texel pairs.
  8232. // The center texel (with weight w0) is used twice, so halve its weight.
  8233. const float w0_1 = w0 * 0.5 + w1;
  8234. const float w2_3 = w2 + w3;
  8235. const float w4_5 = w4 + w5;
  8236. const float w6_7 = w6 + w7;
  8237. const float w8_9 = w8 + w9;
  8238. const float w10_11 = w10 + w11;
  8239. const float w12_13 = w12 + w13;
  8240. const float w14_15 = w14 + w15;
  8241. const float w0_1_ratio = w1/w0_1;
  8242. const float w2_3_ratio = w3/w2_3;
  8243. const float w4_5_ratio = w5/w4_5;
  8244. const float w6_7_ratio = w7/w6_7;
  8245. const float w8_9_ratio = w9/w8_9;
  8246. const float w10_11_ratio = w11/w10_11;
  8247. const float w12_13_ratio = w13/w12_13;
  8248. const float w14_15_ratio = w15/w14_15;
  8249. // Statically normalize weights, sum weighted samples, and return:
  8250. float3 sum = float3(0.0,0.0,0.0);
  8251. sum += w14_15 * tex2D_linearize(tex, tex_uv - (14.0 + w14_15_ratio) * dxdy).rgb;
  8252. sum += w12_13 * tex2D_linearize(tex, tex_uv - (12.0 + w12_13_ratio) * dxdy).rgb;
  8253. sum += w10_11 * tex2D_linearize(tex, tex_uv - (10.0 + w10_11_ratio) * dxdy).rgb;
  8254. sum += w8_9 * tex2D_linearize(tex, tex_uv - (8.0 + w8_9_ratio) * dxdy).rgb;
  8255. sum += w6_7 * tex2D_linearize(tex, tex_uv - (6.0 + w6_7_ratio) * dxdy).rgb;
  8256. sum += w4_5 * tex2D_linearize(tex, tex_uv - (4.0 + w4_5_ratio) * dxdy).rgb;
  8257. sum += w2_3 * tex2D_linearize(tex, tex_uv - (2.0 + w2_3_ratio) * dxdy).rgb;
  8258. sum += w0_1 * tex2D_linearize(tex, tex_uv - w0_1_ratio * dxdy).rgb;
  8259. sum += w0_1 * tex2D_linearize(tex, tex_uv + w0_1_ratio * dxdy).rgb;
  8260. sum += w2_3 * tex2D_linearize(tex, tex_uv + (2.0 + w2_3_ratio) * dxdy).rgb;
  8261. sum += w4_5 * tex2D_linearize(tex, tex_uv + (4.0 + w4_5_ratio) * dxdy).rgb;
  8262. sum += w6_7 * tex2D_linearize(tex, tex_uv + (6.0 + w6_7_ratio) * dxdy).rgb;
  8263. sum += w8_9 * tex2D_linearize(tex, tex_uv + (8.0 + w8_9_ratio) * dxdy).rgb;
  8264. sum += w10_11 * tex2D_linearize(tex, tex_uv + (10.0 + w10_11_ratio) * dxdy).rgb;
  8265. sum += w12_13 * tex2D_linearize(tex, tex_uv + (12.0 + w12_13_ratio) * dxdy).rgb;
  8266. sum += w14_15 * tex2D_linearize(tex, tex_uv + (14.0 + w14_15_ratio) * dxdy).rgb;
  8267. return sum * weight_sum_inv;
  8268. }
  8269. float3 tex2Dblur25fast(const sampler2D tex, const float2 tex_uv,
  8270. const float2 dxdy, const float sigma)
  8271. {
  8272. // Requires: Same as tex2Dblur11()
  8273. // Returns: A 1D 25x Gaussian blurred texture lookup using 1 nearest
  8274. // neighbor and 12 linear taps. It may be mipmapped depending
  8275. // on settings and dxdy.
  8276. // First get the texel weights and normalization factor as above.
  8277. const float denom_inv = 0.5/(sigma*sigma);
  8278. const float w0 = 1.0;
  8279. const float w1 = exp(-1.0 * denom_inv);
  8280. const float w2 = exp(-4.0 * denom_inv);
  8281. const float w3 = exp(-9.0 * denom_inv);
  8282. const float w4 = exp(-16.0 * denom_inv);
  8283. const float w5 = exp(-25.0 * denom_inv);
  8284. const float w6 = exp(-36.0 * denom_inv);
  8285. const float w7 = exp(-49.0 * denom_inv);
  8286. const float w8 = exp(-64.0 * denom_inv);
  8287. const float w9 = exp(-81.0 * denom_inv);
  8288. const float w10 = exp(-100.0 * denom_inv);
  8289. const float w11 = exp(-121.0 * denom_inv);
  8290. const float w12 = exp(-144.0 * denom_inv);
  8291. //const float weight_sum_inv = 1.0 / (w0 + 2.0 * (
  8292. // w1 + w2 + w3 + w4 + w5 + w6 + w7 + w8 + w9 + w10 + w11 + w12));
  8293. const float weight_sum_inv = get_fast_gaussian_weight_sum_inv(sigma);
  8294. // Calculate combined weights and linear sample ratios between texel pairs.
  8295. const float w1_2 = w1 + w2;
  8296. const float w3_4 = w3 + w4;
  8297. const float w5_6 = w5 + w6;
  8298. const float w7_8 = w7 + w8;
  8299. const float w9_10 = w9 + w10;
  8300. const float w11_12 = w11 + w12;
  8301. const float w1_2_ratio = w2/w1_2;
  8302. const float w3_4_ratio = w4/w3_4;
  8303. const float w5_6_ratio = w6/w5_6;
  8304. const float w7_8_ratio = w8/w7_8;
  8305. const float w9_10_ratio = w10/w9_10;
  8306. const float w11_12_ratio = w12/w11_12;
  8307. // Statically normalize weights, sum weighted samples, and return:
  8308. float3 sum = float3(0.0,0.0,0.0);
  8309. sum += w11_12 * tex2D_linearize(tex, tex_uv - (11.0 + w11_12_ratio) * dxdy).rgb;
  8310. sum += w9_10 * tex2D_linearize(tex, tex_uv - (9.0 + w9_10_ratio) * dxdy).rgb;
  8311. sum += w7_8 * tex2D_linearize(tex, tex_uv - (7.0 + w7_8_ratio) * dxdy).rgb;
  8312. sum += w5_6 * tex2D_linearize(tex, tex_uv - (5.0 + w5_6_ratio) * dxdy).rgb;
  8313. sum += w3_4 * tex2D_linearize(tex, tex_uv - (3.0 + w3_4_ratio) * dxdy).rgb;
  8314. sum += w1_2 * tex2D_linearize(tex, tex_uv - (1.0 + w1_2_ratio) * dxdy).rgb;
  8315. sum += w0 * tex2D_linearize(tex, tex_uv).rgb;
  8316. sum += w1_2 * tex2D_linearize(tex, tex_uv + (1.0 + w1_2_ratio) * dxdy).rgb;
  8317. sum += w3_4 * tex2D_linearize(tex, tex_uv + (3.0 + w3_4_ratio) * dxdy).rgb;
  8318. sum += w5_6 * tex2D_linearize(tex, tex_uv + (5.0 + w5_6_ratio) * dxdy).rgb;
  8319. sum += w7_8 * tex2D_linearize(tex, tex_uv + (7.0 + w7_8_ratio) * dxdy).rgb;
  8320. sum += w9_10 * tex2D_linearize(tex, tex_uv + (9.0 + w9_10_ratio) * dxdy).rgb;
  8321. sum += w11_12 * tex2D_linearize(tex, tex_uv + (11.0 + w11_12_ratio) * dxdy).rgb;
  8322. return sum * weight_sum_inv;
  8323. }
  8324. float3 tex2Dblur17fast(const sampler2D tex, const float2 tex_uv,
  8325. const float2 dxdy, const float sigma)
  8326. {
  8327. // Requires: Same as tex2Dblur11()
  8328. // Returns: A 1D 17x Gaussian blurred texture lookup using 1 nearest
  8329. // neighbor and 8 linear taps. It may be mipmapped depending
  8330. // on settings and dxdy.
  8331. // First get the texel weights and normalization factor as above.
  8332. const float denom_inv = 0.5/(sigma*sigma);
  8333. const float w0 = 1.0;
  8334. const float w1 = exp(-1.0 * denom_inv);
  8335. const float w2 = exp(-4.0 * denom_inv);
  8336. const float w3 = exp(-9.0 * denom_inv);
  8337. const float w4 = exp(-16.0 * denom_inv);
  8338. const float w5 = exp(-25.0 * denom_inv);
  8339. const float w6 = exp(-36.0 * denom_inv);
  8340. const float w7 = exp(-49.0 * denom_inv);
  8341. const float w8 = exp(-64.0 * denom_inv);
  8342. //const float weight_sum_inv = 1.0 / (w0 + 2.0 * (
  8343. // w1 + w2 + w3 + w4 + w5 + w6 + w7 + w8));
  8344. const float weight_sum_inv = get_fast_gaussian_weight_sum_inv(sigma);
  8345. // Calculate combined weights and linear sample ratios between texel pairs.
  8346. const float w1_2 = w1 + w2;
  8347. const float w3_4 = w3 + w4;
  8348. const float w5_6 = w5 + w6;
  8349. const float w7_8 = w7 + w8;
  8350. const float w1_2_ratio = w2/w1_2;
  8351. const float w3_4_ratio = w4/w3_4;
  8352. const float w5_6_ratio = w6/w5_6;
  8353. const float w7_8_ratio = w8/w7_8;
  8354. // Statically normalize weights, sum weighted samples, and return:
  8355. float3 sum = float3(0.0,0.0,0.0);
  8356. sum += w7_8 * tex2D_linearize(tex, tex_uv - (7.0 + w7_8_ratio) * dxdy).rgb;
  8357. sum += w5_6 * tex2D_linearize(tex, tex_uv - (5.0 + w5_6_ratio) * dxdy).rgb;
  8358. sum += w3_4 * tex2D_linearize(tex, tex_uv - (3.0 + w3_4_ratio) * dxdy).rgb;
  8359. sum += w1_2 * tex2D_linearize(tex, tex_uv - (1.0 + w1_2_ratio) * dxdy).rgb;
  8360. sum += w0 * tex2D_linearize(tex, tex_uv).rgb;
  8361. sum += w1_2 * tex2D_linearize(tex, tex_uv + (1.0 + w1_2_ratio) * dxdy).rgb;
  8362. sum += w3_4 * tex2D_linearize(tex, tex_uv + (3.0 + w3_4_ratio) * dxdy).rgb;
  8363. sum += w5_6 * tex2D_linearize(tex, tex_uv + (5.0 + w5_6_ratio) * dxdy).rgb;
  8364. sum += w7_8 * tex2D_linearize(tex, tex_uv + (7.0 + w7_8_ratio) * dxdy).rgb;
  8365. return sum * weight_sum_inv;
  8366. }
  8367. //////////////////// ARBITRARILY RESIZABLE ONE-PASS BLURS ////////////////////
  8368. float3 tex2Dblur3x3resize(const sampler2D tex, const float2 tex_uv,
  8369. const float2 dxdy, const float sigma)
  8370. {
  8371. // Requires: Global requirements must be met (see file description).
  8372. // Returns: A 3x3 Gaussian blurred mipmapped texture lookup of the
  8373. // resized input.
  8374. // Description:
  8375. // This is the only arbitrarily resizable one-pass blur; tex2Dblur5x5resize
  8376. // would perform like tex2Dblur9x9, MUCH slower than tex2Dblur5resize.
  8377. const float denom_inv = 0.5/(sigma*sigma);
  8378. // Load each sample. We need all 3x3 samples. Quad-pixel communication
  8379. // won't help either: This should perform like tex2Dblur5x5, but sharing a
  8380. // 4x4 sample field would perform more like tex2Dblur8x8shared (worse).
  8381. const float2 sample4_uv = tex_uv;
  8382. const float2 dx = float2(dxdy.x, 0.0);
  8383. const float2 dy = float2(0.0, dxdy.y);
  8384. const float2 sample1_uv = sample4_uv - dy;
  8385. const float2 sample7_uv = sample4_uv + dy;
  8386. const float3 sample0 = tex2D_linearize(tex, sample1_uv - dx).rgb;
  8387. const float3 sample1 = tex2D_linearize(tex, sample1_uv).rgb;
  8388. const float3 sample2 = tex2D_linearize(tex, sample1_uv + dx).rgb;
  8389. const float3 sample3 = tex2D_linearize(tex, sample4_uv - dx).rgb;
  8390. const float3 sample4 = tex2D_linearize(tex, sample4_uv).rgb;
  8391. const float3 sample5 = tex2D_linearize(tex, sample4_uv + dx).rgb;
  8392. const float3 sample6 = tex2D_linearize(tex, sample7_uv - dx).rgb;
  8393. const float3 sample7 = tex2D_linearize(tex, sample7_uv).rgb;
  8394. const float3 sample8 = tex2D_linearize(tex, sample7_uv + dx).rgb;
  8395. // Statically compute Gaussian sample weights:
  8396. const float w4 = 1.0;
  8397. const float w1_3_5_7 = exp(-LENGTH_SQ(float2(1.0, 0.0)) * denom_inv);
  8398. const float w0_2_6_8 = exp(-LENGTH_SQ(float2(1.0, 1.0)) * denom_inv);
  8399. const float weight_sum_inv = 1.0/(w4 + 4.0 * (w1_3_5_7 + w0_2_6_8));
  8400. // Weight and sum the samples:
  8401. const float3 sum = w4 * sample4 +
  8402. w1_3_5_7 * (sample1 + sample3 + sample5 + sample7) +
  8403. w0_2_6_8 * (sample0 + sample2 + sample6 + sample8);
  8404. return sum * weight_sum_inv;
  8405. }
  8406. //////////////////////////// FASTER ONE-PASS BLURS ///////////////////////////
  8407. float3 tex2Dblur9x9(const sampler2D tex, const float2 tex_uv,
  8408. const float2 dxdy, const float sigma)
  8409. {
  8410. // Perform a 1-pass 9x9 blur with 5x5 bilinear samples.
  8411. // Requires: Same as tex2Dblur9()
  8412. // Returns: A 9x9 Gaussian blurred mipmapped texture lookup composed of
  8413. // 5x5 carefully selected bilinear samples.
  8414. // Description:
  8415. // Perform a 1-pass 9x9 blur with 5x5 bilinear samples. Adjust the
  8416. // bilinear sample location to reflect the true Gaussian weights for each
  8417. // underlying texel. The following diagram illustrates the relative
  8418. // locations of bilinear samples. Each sample with the same number has the
  8419. // same weight (notice the symmetry). The letters a, b, c, d distinguish
  8420. // quadrants, and the letters U, D, L, R, C (up, down, left, right, center)
  8421. // distinguish 1D directions along the line containing the pixel center:
  8422. // 6a 5a 2U 5b 6b
  8423. // 4a 3a 1U 3b 4b
  8424. // 2L 1L 0C 1R 2R
  8425. // 4c 3c 1D 3d 4d
  8426. // 6c 5c 2D 5d 6d
  8427. // The following diagram illustrates the underlying equally spaced texels,
  8428. // named after the sample that accesses them and subnamed by their location
  8429. // within their 2x2, 2x1, 1x2, or 1x1 texel block:
  8430. // 6a4 6a3 5a4 5a3 2U2 5b3 5b4 6b3 6b4
  8431. // 6a2 6a1 5a2 5a1 2U1 5b1 5b2 6b1 6b2
  8432. // 4a4 4a3 3a4 3a3 1U2 3b3 3b4 4b3 4b4
  8433. // 4a2 4a1 3a2 3a1 1U1 3b1 3b2 4b1 4b2
  8434. // 2L2 2L1 1L2 1L1 0C1 1R1 1R2 2R1 2R2
  8435. // 4c2 4c1 3c2 3c1 1D1 3d1 3d2 4d1 4d2
  8436. // 4c4 4c3 3c4 3c3 1D2 3d3 3d4 4d3 4d4
  8437. // 6c2 6c1 5c2 5c1 2D1 5d1 5d2 6d1 6d2
  8438. // 6c4 6c3 5c4 5c3 2D2 5d3 5d4 6d3 6d4
  8439. // Note there is only one C texel and only two texels for each U, D, L, or
  8440. // R sample. The center sample is effectively a nearest neighbor sample,
  8441. // and the U/D/L/R samples use 1D linear filtering. All other texels are
  8442. // read with bilinear samples somewhere within their 2x2 texel blocks.
  8443. // COMPUTE TEXTURE COORDS:
  8444. // Statically compute sampling offsets within each 2x2 texel block, based
  8445. // on 1D sampling ratios between texels [1, 2] and [3, 4] texels away from
  8446. // the center, and reuse them independently for both dimensions. Compute
  8447. // these offsets based on the relative 1D Gaussian weights of the texels
  8448. // in question. (w1off means "Gaussian weight for the texel 1.0 texels
  8449. // away from the pixel center," etc.).
  8450. const float denom_inv = 0.5/(sigma*sigma);
  8451. const float w1off = exp(-1.0 * denom_inv);
  8452. const float w2off = exp(-4.0 * denom_inv);
  8453. const float w3off = exp(-9.0 * denom_inv);
  8454. const float w4off = exp(-16.0 * denom_inv);
  8455. const float texel1to2ratio = w2off/(w1off + w2off);
  8456. const float texel3to4ratio = w4off/(w3off + w4off);
  8457. // Statically compute texel offsets from the fragment center to each
  8458. // bilinear sample in the bottom-right quadrant, including x-axis-aligned:
  8459. const float2 sample1R_texel_offset = float2(1.0, 0.0) + float2(texel1to2ratio, 0.0);
  8460. const float2 sample2R_texel_offset = float2(3.0, 0.0) + float2(texel3to4ratio, 0.0);
  8461. const float2 sample3d_texel_offset = float2(1.0, 1.0) + float2(texel1to2ratio, texel1to2ratio);
  8462. const float2 sample4d_texel_offset = float2(3.0, 1.0) + float2(texel3to4ratio, texel1to2ratio);
  8463. const float2 sample5d_texel_offset = float2(1.0, 3.0) + float2(texel1to2ratio, texel3to4ratio);
  8464. const float2 sample6d_texel_offset = float2(3.0, 3.0) + float2(texel3to4ratio, texel3to4ratio);
  8465. // CALCULATE KERNEL WEIGHTS FOR ALL SAMPLES:
  8466. // Statically compute Gaussian texel weights for the bottom-right quadrant.
  8467. // Read underscores as "and."
  8468. const float w1R1 = w1off;
  8469. const float w1R2 = w2off;
  8470. const float w2R1 = w3off;
  8471. const float w2R2 = w4off;
  8472. const float w3d1 = exp(-LENGTH_SQ(float2(1.0, 1.0)) * denom_inv);
  8473. const float w3d2_3d3 = exp(-LENGTH_SQ(float2(2.0, 1.0)) * denom_inv);
  8474. const float w3d4 = exp(-LENGTH_SQ(float2(2.0, 2.0)) * denom_inv);
  8475. const float w4d1_5d1 = exp(-LENGTH_SQ(float2(3.0, 1.0)) * denom_inv);
  8476. const float w4d2_5d3 = exp(-LENGTH_SQ(float2(4.0, 1.0)) * denom_inv);
  8477. const float w4d3_5d2 = exp(-LENGTH_SQ(float2(3.0, 2.0)) * denom_inv);
  8478. const float w4d4_5d4 = exp(-LENGTH_SQ(float2(4.0, 2.0)) * denom_inv);
  8479. const float w6d1 = exp(-LENGTH_SQ(float2(3.0, 3.0)) * denom_inv);
  8480. const float w6d2_6d3 = exp(-LENGTH_SQ(float2(4.0, 3.0)) * denom_inv);
  8481. const float w6d4 = exp(-LENGTH_SQ(float2(4.0, 4.0)) * denom_inv);
  8482. // Statically add texel weights in each sample to get sample weights:
  8483. const float w0 = 1.0;
  8484. const float w1 = w1R1 + w1R2;
  8485. const float w2 = w2R1 + w2R2;
  8486. const float w3 = w3d1 + 2.0 * w3d2_3d3 + w3d4;
  8487. const float w4 = w4d1_5d1 + w4d2_5d3 + w4d3_5d2 + w4d4_5d4;
  8488. const float w5 = w4;
  8489. const float w6 = w6d1 + 2.0 * w6d2_6d3 + w6d4;
  8490. // Get the weight sum inverse (normalization factor):
  8491. const float weight_sum_inv =
  8492. 1.0/(w0 + 4.0 * (w1 + w2 + w3 + w4 + w5 + w6));
  8493. // LOAD TEXTURE SAMPLES:
  8494. // Load all 25 samples (1 nearest, 8 linear, 16 bilinear) using symmetry:
  8495. const float2 mirror_x = float2(-1.0, 1.0);
  8496. const float2 mirror_y = float2(1.0, -1.0);
  8497. const float2 mirror_xy = float2(-1.0, -1.0);
  8498. const float2 dxdy_mirror_x = dxdy * mirror_x;
  8499. const float2 dxdy_mirror_y = dxdy * mirror_y;
  8500. const float2 dxdy_mirror_xy = dxdy * mirror_xy;
  8501. // Sampling order doesn't seem to affect performance, so just be clear:
  8502. const float3 sample0C = tex2D_linearize(tex, tex_uv).rgb;
  8503. const float3 sample1R = tex2D_linearize(tex, tex_uv + dxdy * sample1R_texel_offset).rgb;
  8504. const float3 sample1D = tex2D_linearize(tex, tex_uv + dxdy * sample1R_texel_offset.yx).rgb;
  8505. const float3 sample1L = tex2D_linearize(tex, tex_uv - dxdy * sample1R_texel_offset).rgb;
  8506. const float3 sample1U = tex2D_linearize(tex, tex_uv - dxdy * sample1R_texel_offset.yx).rgb;
  8507. const float3 sample2R = tex2D_linearize(tex, tex_uv + dxdy * sample2R_texel_offset).rgb;
  8508. const float3 sample2D = tex2D_linearize(tex, tex_uv + dxdy * sample2R_texel_offset.yx).rgb;
  8509. const float3 sample2L = tex2D_linearize(tex, tex_uv - dxdy * sample2R_texel_offset).rgb;
  8510. const float3 sample2U = tex2D_linearize(tex, tex_uv - dxdy * sample2R_texel_offset.yx).rgb;
  8511. const float3 sample3d = tex2D_linearize(tex, tex_uv + dxdy * sample3d_texel_offset).rgb;
  8512. const float3 sample3c = tex2D_linearize(tex, tex_uv + dxdy_mirror_x * sample3d_texel_offset).rgb;
  8513. const float3 sample3b = tex2D_linearize(tex, tex_uv + dxdy_mirror_y * sample3d_texel_offset).rgb;
  8514. const float3 sample3a = tex2D_linearize(tex, tex_uv + dxdy_mirror_xy * sample3d_texel_offset).rgb;
  8515. const float3 sample4d = tex2D_linearize(tex, tex_uv + dxdy * sample4d_texel_offset).rgb;
  8516. const float3 sample4c = tex2D_linearize(tex, tex_uv + dxdy_mirror_x * sample4d_texel_offset).rgb;
  8517. const float3 sample4b = tex2D_linearize(tex, tex_uv + dxdy_mirror_y * sample4d_texel_offset).rgb;
  8518. const float3 sample4a = tex2D_linearize(tex, tex_uv + dxdy_mirror_xy * sample4d_texel_offset).rgb;
  8519. const float3 sample5d = tex2D_linearize(tex, tex_uv + dxdy * sample5d_texel_offset).rgb;
  8520. const float3 sample5c = tex2D_linearize(tex, tex_uv + dxdy_mirror_x * sample5d_texel_offset).rgb;
  8521. const float3 sample5b = tex2D_linearize(tex, tex_uv + dxdy_mirror_y * sample5d_texel_offset).rgb;
  8522. const float3 sample5a = tex2D_linearize(tex, tex_uv + dxdy_mirror_xy * sample5d_texel_offset).rgb;
  8523. const float3 sample6d = tex2D_linearize(tex, tex_uv + dxdy * sample6d_texel_offset).rgb;
  8524. const float3 sample6c = tex2D_linearize(tex, tex_uv + dxdy_mirror_x * sample6d_texel_offset).rgb;
  8525. const float3 sample6b = tex2D_linearize(tex, tex_uv + dxdy_mirror_y * sample6d_texel_offset).rgb;
  8526. const float3 sample6a = tex2D_linearize(tex, tex_uv + dxdy_mirror_xy * sample6d_texel_offset).rgb;
  8527. // SUM WEIGHTED SAMPLES:
  8528. // Statically normalize weights (so total = 1.0), and sum weighted samples.
  8529. float3 sum = w0 * sample0C;
  8530. sum += w1 * (sample1R + sample1D + sample1L + sample1U);
  8531. sum += w2 * (sample2R + sample2D + sample2L + sample2U);
  8532. sum += w3 * (sample3d + sample3c + sample3b + sample3a);
  8533. sum += w4 * (sample4d + sample4c + sample4b + sample4a);
  8534. sum += w5 * (sample5d + sample5c + sample5b + sample5a);
  8535. sum += w6 * (sample6d + sample6c + sample6b + sample6a);
  8536. return sum * weight_sum_inv;
  8537. }
  8538. float3 tex2Dblur7x7(const sampler2D tex, const float2 tex_uv,
  8539. const float2 dxdy, const float sigma)
  8540. {
  8541. // Perform a 1-pass 7x7 blur with 5x5 bilinear samples.
  8542. // Requires: Same as tex2Dblur9()
  8543. // Returns: A 7x7 Gaussian blurred mipmapped texture lookup composed of
  8544. // 4x4 carefully selected bilinear samples.
  8545. // Description:
  8546. // First see the descriptions for tex2Dblur9x9() and tex2Dblur7(). This
  8547. // blur mixes concepts from both. The sample layout is as follows:
  8548. // 4a 3a 3b 4b
  8549. // 2a 1a 1b 2b
  8550. // 2c 1c 1d 2d
  8551. // 4c 3c 3d 4d
  8552. // The texel layout is as follows. Note that samples 3a/3b, 1a/1b, 1c/1d,
  8553. // and 3c/3d share a vertical column of texels, and samples 2a/2c, 1a/1c,
  8554. // 1b/1d, and 2b/2d share a horizontal row of texels (all sample1's share
  8555. // the center texel):
  8556. // 4a4 4a3 3a4 3ab3 3b4 4b3 4b4
  8557. // 4a2 4a1 3a2 3ab1 3b2 4b1 4b2
  8558. // 2a4 2a3 1a4 1ab3 1b4 2b3 2b4
  8559. // 2ac2 2ac1 1ac2 1* 1bd2 2bd1 2bd2
  8560. // 2c4 2c3 1c4 1cd3 1d4 2d3 2d4
  8561. // 4c2 4c1 3c2 3cd1 3d2 4d1 4d2
  8562. // 4c4 4c3 3c4 3cd3 3d4 4d3 4d4
  8563. // COMPUTE TEXTURE COORDS:
  8564. // Statically compute bilinear sampling offsets (details in tex2Dblur9x9).
  8565. const float denom_inv = 0.5/(sigma*sigma);
  8566. const float w0off = 1.0;
  8567. const float w1off = exp(-1.0 * denom_inv);
  8568. const float w2off = exp(-4.0 * denom_inv);
  8569. const float w3off = exp(-9.0 * denom_inv);
  8570. const float texel0to1ratio = w1off/(w0off * 0.5 + w1off);
  8571. const float texel2to3ratio = w3off/(w2off + w3off);
  8572. // Statically compute texel offsets from the fragment center to each
  8573. // bilinear sample in the bottom-right quadrant, including axis-aligned:
  8574. const float2 sample1d_texel_offset = float2(texel0to1ratio, texel0to1ratio);
  8575. const float2 sample2d_texel_offset = float2(2.0, 0.0) + float2(texel2to3ratio, texel0to1ratio);
  8576. const float2 sample3d_texel_offset = float2(0.0, 2.0) + float2(texel0to1ratio, texel2to3ratio);
  8577. const float2 sample4d_texel_offset = float2(2.0, 2.0) + float2(texel2to3ratio, texel2to3ratio);
  8578. // CALCULATE KERNEL WEIGHTS FOR ALL SAMPLES:
  8579. // Statically compute Gaussian texel weights for the bottom-right quadrant.
  8580. // Read underscores as "and."
  8581. const float w1abcd = 1.0;
  8582. const float w1bd2_1cd3 = exp(-LENGTH_SQ(float2(1.0, 0.0)) * denom_inv);
  8583. const float w2bd1_3cd1 = exp(-LENGTH_SQ(float2(2.0, 0.0)) * denom_inv);
  8584. const float w2bd2_3cd2 = exp(-LENGTH_SQ(float2(3.0, 0.0)) * denom_inv);
  8585. const float w1d4 = exp(-LENGTH_SQ(float2(1.0, 1.0)) * denom_inv);
  8586. const float w2d3_3d2 = exp(-LENGTH_SQ(float2(2.0, 1.0)) * denom_inv);
  8587. const float w2d4_3d4 = exp(-LENGTH_SQ(float2(3.0, 1.0)) * denom_inv);
  8588. const float w4d1 = exp(-LENGTH_SQ(float2(2.0, 2.0)) * denom_inv);
  8589. const float w4d2_4d3 = exp(-LENGTH_SQ(float2(3.0, 2.0)) * denom_inv);
  8590. const float w4d4 = exp(-LENGTH_SQ(float2(3.0, 3.0)) * denom_inv);
  8591. // Statically add texel weights in each sample to get sample weights.
  8592. // Split weights for shared texels between samples sharing them:
  8593. const float w1 = w1abcd * 0.25 + w1bd2_1cd3 + w1d4;
  8594. const float w2_3 = (w2bd1_3cd1 + w2bd2_3cd2) * 0.5 + w2d3_3d2 + w2d4_3d4;
  8595. const float w4 = w4d1 + 2.0 * w4d2_4d3 + w4d4;
  8596. // Get the weight sum inverse (normalization factor):
  8597. const float weight_sum_inv =
  8598. 1.0/(4.0 * (w1 + 2.0 * w2_3 + w4));
  8599. // LOAD TEXTURE SAMPLES:
  8600. // Load all 16 samples using symmetry:
  8601. const float2 mirror_x = float2(-1.0, 1.0);
  8602. const float2 mirror_y = float2(1.0, -1.0);
  8603. const float2 mirror_xy = float2(-1.0, -1.0);
  8604. const float2 dxdy_mirror_x = dxdy * mirror_x;
  8605. const float2 dxdy_mirror_y = dxdy * mirror_y;
  8606. const float2 dxdy_mirror_xy = dxdy * mirror_xy;
  8607. const float3 sample1a = tex2D_linearize(tex, tex_uv + dxdy_mirror_xy * sample1d_texel_offset).rgb;
  8608. const float3 sample2a = tex2D_linearize(tex, tex_uv + dxdy_mirror_xy * sample2d_texel_offset).rgb;
  8609. const float3 sample3a = tex2D_linearize(tex, tex_uv + dxdy_mirror_xy * sample3d_texel_offset).rgb;
  8610. const float3 sample4a = tex2D_linearize(tex, tex_uv + dxdy_mirror_xy * sample4d_texel_offset).rgb;
  8611. const float3 sample1b = tex2D_linearize(tex, tex_uv + dxdy_mirror_y * sample1d_texel_offset).rgb;
  8612. const float3 sample2b = tex2D_linearize(tex, tex_uv + dxdy_mirror_y * sample2d_texel_offset).rgb;
  8613. const float3 sample3b = tex2D_linearize(tex, tex_uv + dxdy_mirror_y * sample3d_texel_offset).rgb;
  8614. const float3 sample4b = tex2D_linearize(tex, tex_uv + dxdy_mirror_y * sample4d_texel_offset).rgb;
  8615. const float3 sample1c = tex2D_linearize(tex, tex_uv + dxdy_mirror_x * sample1d_texel_offset).rgb;
  8616. const float3 sample2c = tex2D_linearize(tex, tex_uv + dxdy_mirror_x * sample2d_texel_offset).rgb;
  8617. const float3 sample3c = tex2D_linearize(tex, tex_uv + dxdy_mirror_x * sample3d_texel_offset).rgb;
  8618. const float3 sample4c = tex2D_linearize(tex, tex_uv + dxdy_mirror_x * sample4d_texel_offset).rgb;
  8619. const float3 sample1d = tex2D_linearize(tex, tex_uv + dxdy * sample1d_texel_offset).rgb;
  8620. const float3 sample2d = tex2D_linearize(tex, tex_uv + dxdy * sample2d_texel_offset).rgb;
  8621. const float3 sample3d = tex2D_linearize(tex, tex_uv + dxdy * sample3d_texel_offset).rgb;
  8622. const float3 sample4d = tex2D_linearize(tex, tex_uv + dxdy * sample4d_texel_offset).rgb;
  8623. // SUM WEIGHTED SAMPLES:
  8624. // Statically normalize weights (so total = 1.0), and sum weighted samples.
  8625. float3 sum = float3(0.0,0.0,0.0);
  8626. sum += w1 * (sample1a + sample1b + sample1c + sample1d);
  8627. sum += w2_3 * (sample2a + sample2b + sample2c + sample2d);
  8628. sum += w2_3 * (sample3a + sample3b + sample3c + sample3d);
  8629. sum += w4 * (sample4a + sample4b + sample4c + sample4d);
  8630. return sum * weight_sum_inv;
  8631. }
  8632. float3 tex2Dblur5x5(const sampler2D tex, const float2 tex_uv,
  8633. const float2 dxdy, const float sigma)
  8634. {
  8635. // Perform a 1-pass 5x5 blur with 3x3 bilinear samples.
  8636. // Requires: Same as tex2Dblur9()
  8637. // Returns: A 5x5 Gaussian blurred mipmapped texture lookup composed of
  8638. // 3x3 carefully selected bilinear samples.
  8639. // Description:
  8640. // First see the description for tex2Dblur9x9(). This blur uses the same
  8641. // concept and sample/texel locations except on a smaller scale. Samples:
  8642. // 2a 1U 2b
  8643. // 1L 0C 1R
  8644. // 2c 1D 2d
  8645. // Texels:
  8646. // 2a4 2a3 1U2 2b3 2b4
  8647. // 2a2 2a1 1U1 2b1 2b2
  8648. // 1L2 1L1 0C1 1R1 1R2
  8649. // 2c2 2c1 1D1 2d1 2d2
  8650. // 2c4 2c3 1D2 2d3 2d4
  8651. // COMPUTE TEXTURE COORDS:
  8652. // Statically compute bilinear sampling offsets (details in tex2Dblur9x9).
  8653. const float denom_inv = 0.5/(sigma*sigma);
  8654. const float w1off = exp(-1.0 * denom_inv);
  8655. const float w2off = exp(-4.0 * denom_inv);
  8656. const float texel1to2ratio = w2off/(w1off + w2off);
  8657. // Statically compute texel offsets from the fragment center to each
  8658. // bilinear sample in the bottom-right quadrant, including x-axis-aligned:
  8659. const float2 sample1R_texel_offset = float2(1.0, 0.0) + float2(texel1to2ratio, 0.0);
  8660. const float2 sample2d_texel_offset = float2(1.0, 1.0) + float2(texel1to2ratio, texel1to2ratio);
  8661. // CALCULATE KERNEL WEIGHTS FOR ALL SAMPLES:
  8662. // Statically compute Gaussian texel weights for the bottom-right quadrant.
  8663. // Read underscores as "and."
  8664. const float w1R1 = w1off;
  8665. const float w1R2 = w2off;
  8666. const float w2d1 = exp(-LENGTH_SQ(float2(1.0, 1.0)) * denom_inv);
  8667. const float w2d2_3 = exp(-LENGTH_SQ(float2(2.0, 1.0)) * denom_inv);
  8668. const float w2d4 = exp(-LENGTH_SQ(float2(2.0, 2.0)) * denom_inv);
  8669. // Statically add texel weights in each sample to get sample weights:
  8670. const float w0 = 1.0;
  8671. const float w1 = w1R1 + w1R2;
  8672. const float w2 = w2d1 + 2.0 * w2d2_3 + w2d4;
  8673. // Get the weight sum inverse (normalization factor):
  8674. const float weight_sum_inv = 1.0/(w0 + 4.0 * (w1 + w2));
  8675. // LOAD TEXTURE SAMPLES:
  8676. // Load all 9 samples (1 nearest, 4 linear, 4 bilinear) using symmetry:
  8677. const float2 mirror_x = float2(-1.0, 1.0);
  8678. const float2 mirror_y = float2(1.0, -1.0);
  8679. const float2 mirror_xy = float2(-1.0, -1.0);
  8680. const float2 dxdy_mirror_x = dxdy * mirror_x;
  8681. const float2 dxdy_mirror_y = dxdy * mirror_y;
  8682. const float2 dxdy_mirror_xy = dxdy * mirror_xy;
  8683. const float3 sample0C = tex2D_linearize(tex, tex_uv).rgb;
  8684. const float3 sample1R = tex2D_linearize(tex, tex_uv + dxdy * sample1R_texel_offset).rgb;
  8685. const float3 sample1D = tex2D_linearize(tex, tex_uv + dxdy * sample1R_texel_offset.yx).rgb;
  8686. const float3 sample1L = tex2D_linearize(tex, tex_uv - dxdy * sample1R_texel_offset).rgb;
  8687. const float3 sample1U = tex2D_linearize(tex, tex_uv - dxdy * sample1R_texel_offset.yx).rgb;
  8688. const float3 sample2d = tex2D_linearize(tex, tex_uv + dxdy * sample2d_texel_offset).rgb;
  8689. const float3 sample2c = tex2D_linearize(tex, tex_uv + dxdy_mirror_x * sample2d_texel_offset).rgb;
  8690. const float3 sample2b = tex2D_linearize(tex, tex_uv + dxdy_mirror_y * sample2d_texel_offset).rgb;
  8691. const float3 sample2a = tex2D_linearize(tex, tex_uv + dxdy_mirror_xy * sample2d_texel_offset).rgb;
  8692. // SUM WEIGHTED SAMPLES:
  8693. // Statically normalize weights (so total = 1.0), and sum weighted samples.
  8694. float3 sum = w0 * sample0C;
  8695. sum += w1 * (sample1R + sample1D + sample1L + sample1U);
  8696. sum += w2 * (sample2a + sample2b + sample2c + sample2d);
  8697. return sum * weight_sum_inv;
  8698. }
  8699. float3 tex2Dblur3x3(const sampler2D tex, const float2 tex_uv,
  8700. const float2 dxdy, const float sigma)
  8701. {
  8702. // Perform a 1-pass 3x3 blur with 5x5 bilinear samples.
  8703. // Requires: Same as tex2Dblur9()
  8704. // Returns: A 3x3 Gaussian blurred mipmapped texture lookup composed of
  8705. // 2x2 carefully selected bilinear samples.
  8706. // Description:
  8707. // First see the descriptions for tex2Dblur9x9() and tex2Dblur7(). This
  8708. // blur mixes concepts from both. The sample layout is as follows:
  8709. // 0a 0b
  8710. // 0c 0d
  8711. // The texel layout is as follows. Note that samples 0a/0b and 0c/0d share
  8712. // a vertical column of texels, and samples 0a/0c and 0b/0d share a
  8713. // horizontal row of texels (all samples share the center texel):
  8714. // 0a3 0ab2 0b3
  8715. // 0ac1 0*0 0bd1
  8716. // 0c3 0cd2 0d3
  8717. // COMPUTE TEXTURE COORDS:
  8718. // Statically compute bilinear sampling offsets (details in tex2Dblur9x9).
  8719. const float denom_inv = 0.5/(sigma*sigma);
  8720. const float w0off = 1.0;
  8721. const float w1off = exp(-1.0 * denom_inv);
  8722. const float texel0to1ratio = w1off/(w0off * 0.5 + w1off);
  8723. // Statically compute texel offsets from the fragment center to each
  8724. // bilinear sample in the bottom-right quadrant, including axis-aligned:
  8725. const float2 sample0d_texel_offset = float2(texel0to1ratio, texel0to1ratio);
  8726. // LOAD TEXTURE SAMPLES:
  8727. // Load all 4 samples using symmetry:
  8728. const float2 mirror_x = float2(-1.0, 1.0);
  8729. const float2 mirror_y = float2(1.0, -1.0);
  8730. const float2 mirror_xy = float2(-1.0, -1.0);
  8731. const float2 dxdy_mirror_x = dxdy * mirror_x;
  8732. const float2 dxdy_mirror_y = dxdy * mirror_y;
  8733. const float2 dxdy_mirror_xy = dxdy * mirror_xy;
  8734. const float3 sample0a = tex2D_linearize(tex, tex_uv + dxdy_mirror_xy * sample0d_texel_offset).rgb;
  8735. const float3 sample0b = tex2D_linearize(tex, tex_uv + dxdy_mirror_y * sample0d_texel_offset).rgb;
  8736. const float3 sample0c = tex2D_linearize(tex, tex_uv + dxdy_mirror_x * sample0d_texel_offset).rgb;
  8737. const float3 sample0d = tex2D_linearize(tex, tex_uv + dxdy * sample0d_texel_offset).rgb;
  8738. // SUM WEIGHTED SAMPLES:
  8739. // Weights for all samples are the same, so just average them:
  8740. return 0.25 * (sample0a + sample0b + sample0c + sample0d);
  8741. }
  8742. ////////////////// LINEAR ONE-PASS BLURS WITH SHARED SAMPLES /////////////////
  8743. float3 tex2Dblur12x12shared(const sampler2D tex,
  8744. const float4 tex_uv, const float2 dxdy, const float4 quad_vector,
  8745. const float sigma)
  8746. {
  8747. // Perform a 1-pass mipmapped blur with shared samples across a pixel quad.
  8748. // Requires: 1.) Same as tex2Dblur9()
  8749. // 2.) ddx() and ddy() are present in the current Cg profile.
  8750. // 3.) The GPU driver is using fine/high-quality derivatives.
  8751. // 4.) quad_vector *correctly* describes the current fragment's
  8752. // location in its pixel quad, by the conventions noted in
  8753. // get_quad_vector[_naive].
  8754. // 5.) tex_uv.w = log2(video_size/output_size).y
  8755. // 6.) tex2Dlod() is present in the current Cg profile.
  8756. // Optional: Tune artifacts vs. excessive blurriness with the global
  8757. // float error_blurring.
  8758. // Returns: A blurred texture lookup using a "virtual" 12x12 Gaussian
  8759. // blur (a 6x6 blur of carefully selected bilinear samples)
  8760. // of the given mip level. There will be subtle inaccuracies,
  8761. // especially for small or high-frequency detailed sources.
  8762. // Description:
  8763. // Perform a 1-pass blur with shared texture lookups across a pixel quad.
  8764. // We'll get neighboring samples with high-quality ddx/ddy derivatives, as
  8765. // in GPU Pro 2, Chapter VI.2, "Shader Amortization using Pixel Quad
  8766. // Message Passing" by Eric Penner.
  8767. //
  8768. // Our "virtual" 12x12 blur will be comprised of ((6 - 1)^2)/4 + 3 = 12
  8769. // bilinear samples, where bilinear sampling positions are computed from
  8770. // the relative Gaussian weights of the 4 surrounding texels. The catch is
  8771. // that the appropriate texel weights and sample coords differ for each
  8772. // fragment, but we're reusing most of the same samples across a quad of
  8773. // destination fragments. (We do use unique coords for the four nearest
  8774. // samples at each fragment.) Mixing bilinear filtering and sample-sharing
  8775. // therefore introduces some error into the weights, and this can get nasty
  8776. // when the source image is small or high-frequency. Computing bilinear
  8777. // ratios based on weights at the sample field center results in sharpening
  8778. // and ringing artifacts, but we can move samples closer to halfway between
  8779. // texels to try blurring away the error (which can move features around by
  8780. // a texel or so). Tune this with the global float "error_blurring".
  8781. //
  8782. // The pixel quad's sample field covers 12x12 texels, accessed through 6x6
  8783. // bilinear (2x2 texel) taps. Each fragment depends on a window of 10x10
  8784. // texels (5x5 bilinear taps), and each fragment is responsible for loading
  8785. // a 6x6 texel quadrant as a 3x3 block of bilinear taps, plus 3 more taps
  8786. // to use unique bilinear coords for sample0* for each fragment. This
  8787. // diagram illustrates the relative locations of bilinear samples 1-9 for
  8788. // each quadrant a, b, c, d (note samples will not be equally spaced):
  8789. // 8a 7a 6a 6b 7b 8b
  8790. // 5a 4a 3a 3b 4b 5b
  8791. // 2a 1a 0a 0b 1b 2b
  8792. // 2c 1c 0c 0d 1d 2d
  8793. // 5c 4c 3c 3d 4d 5d
  8794. // 8c 7c 6c 6d 7d 8d
  8795. // The following diagram illustrates the underlying equally spaced texels,
  8796. // named after the sample that accesses them and subnamed by their location
  8797. // within their 2x2 texel block:
  8798. // 8a3 8a2 7a3 7a2 6a3 6a2 6b2 6b3 7b2 7b3 8b2 8b3
  8799. // 8a1 8a0 7a1 7a0 6a1 6a0 6b0 6b1 7b0 7b1 8b0 8b1
  8800. // 5a3 5a2 4a3 4a2 3a3 3a2 3b2 3b3 4b2 4b3 5b2 5b3
  8801. // 5a1 5a0 4a1 4a0 3a1 3a0 3b0 3b1 4b0 4b1 5b0 5b1
  8802. // 2a3 2a2 1a3 1a2 0a3 0a2 0b2 0b3 1b2 1b3 2b2 2b3
  8803. // 2a1 2a0 1a1 1a0 0a1 0a0 0b0 0b1 1b0 1b1 2b0 2b1
  8804. // 2c1 2c0 1c1 1c0 0c1 0c0 0d0 0d1 1d0 1d1 2d0 2d1
  8805. // 2c3 2c2 1c3 1c2 0c3 0c2 0d2 0d3 1d2 1d3 2d2 2d3
  8806. // 5c1 5c0 4c1 4c0 3c1 3c0 3d0 3d1 4d0 4d1 5d0 5d1
  8807. // 5c3 5c2 4c3 4c2 3c3 3c2 3d2 3d3 4d2 4d3 5d2 5d3
  8808. // 8c1 8c0 7c1 7c0 6c1 6c0 6d0 6d1 7d0 7d1 8d0 8d1
  8809. // 8c3 8c2 7c3 7c2 6c3 6c2 6d2 6d3 7d2 7d3 8d2 8d3
  8810. // With this symmetric arrangement, we don't have to know which absolute
  8811. // quadrant a sample lies in to assign kernel weights; it's enough to know
  8812. // the sample number and the relative quadrant of the sample (relative to
  8813. // the current quadrant):
  8814. // {current, adjacent x, adjacent y, diagonal}
  8815. // COMPUTE COORDS FOR TEXTURE SAMPLES THIS FRAGMENT IS RESPONSIBLE FOR:
  8816. // Statically compute sampling offsets within each 2x2 texel block, based
  8817. // on appropriate 1D Gaussian sampling ratio between texels [0, 1], [2, 3],
  8818. // and [4, 5] away from the fragment, and reuse them independently for both
  8819. // dimensions. Use the sample field center as the estimated destination,
  8820. // but nudge the result closer to halfway between texels to blur error.
  8821. const float denom_inv = 0.5/(sigma*sigma);
  8822. const float w0off = 1.0;
  8823. const float w0_5off = exp(-(0.5*0.5) * denom_inv);
  8824. const float w1off = exp(-(1.0*1.0) * denom_inv);
  8825. const float w1_5off = exp(-(1.5*1.5) * denom_inv);
  8826. const float w2off = exp(-(2.0*2.0) * denom_inv);
  8827. const float w2_5off = exp(-(2.5*2.5) * denom_inv);
  8828. const float w3_5off = exp(-(3.5*3.5) * denom_inv);
  8829. const float w4_5off = exp(-(4.5*4.5) * denom_inv);
  8830. const float w5_5off = exp(-(5.5*5.5) * denom_inv);
  8831. const float texel0to1ratio = lerp(w1_5off/(w0_5off + w1_5off), 0.5, error_blurring);
  8832. const float texel2to3ratio = lerp(w3_5off/(w2_5off + w3_5off), 0.5, error_blurring);
  8833. const float texel4to5ratio = lerp(w5_5off/(w4_5off + w5_5off), 0.5, error_blurring);
  8834. // We don't share sample0*, so use the nearest destination fragment:
  8835. const float texel0to1ratio_nearest = w1off/(w0off + w1off);
  8836. const float texel1to2ratio_nearest = w2off/(w1off + w2off);
  8837. // Statically compute texel offsets from the bottom-right fragment to each
  8838. // bilinear sample in the bottom-right quadrant:
  8839. const float2 sample0curr_texel_offset = float2(0.0, 0.0) + float2(texel0to1ratio_nearest, texel0to1ratio_nearest);
  8840. const float2 sample0adjx_texel_offset = float2(-1.0, 0.0) + float2(-texel1to2ratio_nearest, texel0to1ratio_nearest);
  8841. const float2 sample0adjy_texel_offset = float2(0.0, -1.0) + float2(texel0to1ratio_nearest, -texel1to2ratio_nearest);
  8842. const float2 sample0diag_texel_offset = float2(-1.0, -1.0) + float2(-texel1to2ratio_nearest, -texel1to2ratio_nearest);
  8843. const float2 sample1_texel_offset = float2(2.0, 0.0) + float2(texel2to3ratio, texel0to1ratio);
  8844. const float2 sample2_texel_offset = float2(4.0, 0.0) + float2(texel4to5ratio, texel0to1ratio);
  8845. const float2 sample3_texel_offset = float2(0.0, 2.0) + float2(texel0to1ratio, texel2to3ratio);
  8846. const float2 sample4_texel_offset = float2(2.0, 2.0) + float2(texel2to3ratio, texel2to3ratio);
  8847. const float2 sample5_texel_offset = float2(4.0, 2.0) + float2(texel4to5ratio, texel2to3ratio);
  8848. const float2 sample6_texel_offset = float2(0.0, 4.0) + float2(texel0to1ratio, texel4to5ratio);
  8849. const float2 sample7_texel_offset = float2(2.0, 4.0) + float2(texel2to3ratio, texel4to5ratio);
  8850. const float2 sample8_texel_offset = float2(4.0, 4.0) + float2(texel4to5ratio, texel4to5ratio);
  8851. // CALCULATE KERNEL WEIGHTS:
  8852. // Statically compute bilinear sample weights at each destination fragment
  8853. // based on the sum of their 4 underlying texel weights. Assume a same-
  8854. // resolution blur, so each symmetrically named sample weight will compute
  8855. // the same at every fragment in the pixel quad: We can therefore compute
  8856. // texel weights based only on the bottom-right quadrant (fragment at 0d0).
  8857. // Too avoid too much boilerplate code, use a macro to get all 4 texel
  8858. // weights for a bilinear sample based on the offset of its top-left texel:
  8859. #define GET_TEXEL_QUAD_WEIGHTS(xoff, yoff) \
  8860. (exp(-LENGTH_SQ(float2(xoff, yoff)) * denom_inv) + \
  8861. exp(-LENGTH_SQ(float2(xoff + 1.0, yoff)) * denom_inv) + \
  8862. exp(-LENGTH_SQ(float2(xoff, yoff + 1.0)) * denom_inv) + \
  8863. exp(-LENGTH_SQ(float2(xoff + 1.0, yoff + 1.0)) * denom_inv))
  8864. const float w8diag = GET_TEXEL_QUAD_WEIGHTS(-6.0, -6.0);
  8865. const float w7diag = GET_TEXEL_QUAD_WEIGHTS(-4.0, -6.0);
  8866. const float w6diag = GET_TEXEL_QUAD_WEIGHTS(-2.0, -6.0);
  8867. const float w6adjy = GET_TEXEL_QUAD_WEIGHTS(0.0, -6.0);
  8868. const float w7adjy = GET_TEXEL_QUAD_WEIGHTS(2.0, -6.0);
  8869. const float w8adjy = GET_TEXEL_QUAD_WEIGHTS(4.0, -6.0);
  8870. const float w5diag = GET_TEXEL_QUAD_WEIGHTS(-6.0, -4.0);
  8871. const float w4diag = GET_TEXEL_QUAD_WEIGHTS(-4.0, -4.0);
  8872. const float w3diag = GET_TEXEL_QUAD_WEIGHTS(-2.0, -4.0);
  8873. const float w3adjy = GET_TEXEL_QUAD_WEIGHTS(0.0, -4.0);
  8874. const float w4adjy = GET_TEXEL_QUAD_WEIGHTS(2.0, -4.0);
  8875. const float w5adjy = GET_TEXEL_QUAD_WEIGHTS(4.0, -4.0);
  8876. const float w2diag = GET_TEXEL_QUAD_WEIGHTS(-6.0, -2.0);
  8877. const float w1diag = GET_TEXEL_QUAD_WEIGHTS(-4.0, -2.0);
  8878. const float w0diag = GET_TEXEL_QUAD_WEIGHTS(-2.0, -2.0);
  8879. const float w0adjy = GET_TEXEL_QUAD_WEIGHTS(0.0, -2.0);
  8880. const float w1adjy = GET_TEXEL_QUAD_WEIGHTS(2.0, -2.0);
  8881. const float w2adjy = GET_TEXEL_QUAD_WEIGHTS(4.0, -2.0);
  8882. const float w2adjx = GET_TEXEL_QUAD_WEIGHTS(-6.0, 0.0);
  8883. const float w1adjx = GET_TEXEL_QUAD_WEIGHTS(-4.0, 0.0);
  8884. const float w0adjx = GET_TEXEL_QUAD_WEIGHTS(-2.0, 0.0);
  8885. const float w0curr = GET_TEXEL_QUAD_WEIGHTS(0.0, 0.0);
  8886. const float w1curr = GET_TEXEL_QUAD_WEIGHTS(2.0, 0.0);
  8887. const float w2curr = GET_TEXEL_QUAD_WEIGHTS(4.0, 0.0);
  8888. const float w5adjx = GET_TEXEL_QUAD_WEIGHTS(-6.0, 2.0);
  8889. const float w4adjx = GET_TEXEL_QUAD_WEIGHTS(-4.0, 2.0);
  8890. const float w3adjx = GET_TEXEL_QUAD_WEIGHTS(-2.0, 2.0);
  8891. const float w3curr = GET_TEXEL_QUAD_WEIGHTS(0.0, 2.0);
  8892. const float w4curr = GET_TEXEL_QUAD_WEIGHTS(2.0, 2.0);
  8893. const float w5curr = GET_TEXEL_QUAD_WEIGHTS(4.0, 2.0);
  8894. const float w8adjx = GET_TEXEL_QUAD_WEIGHTS(-6.0, 4.0);
  8895. const float w7adjx = GET_TEXEL_QUAD_WEIGHTS(-4.0, 4.0);
  8896. const float w6adjx = GET_TEXEL_QUAD_WEIGHTS(-2.0, 4.0);
  8897. const float w6curr = GET_TEXEL_QUAD_WEIGHTS(0.0, 4.0);
  8898. const float w7curr = GET_TEXEL_QUAD_WEIGHTS(2.0, 4.0);
  8899. const float w8curr = GET_TEXEL_QUAD_WEIGHTS(4.0, 4.0);
  8900. #undef GET_TEXEL_QUAD_WEIGHTS
  8901. // Statically pack weights for runtime:
  8902. const float4 w0 = float4(w0curr, w0adjx, w0adjy, w0diag);
  8903. const float4 w1 = float4(w1curr, w1adjx, w1adjy, w1diag);
  8904. const float4 w2 = float4(w2curr, w2adjx, w2adjy, w2diag);
  8905. const float4 w3 = float4(w3curr, w3adjx, w3adjy, w3diag);
  8906. const float4 w4 = float4(w4curr, w4adjx, w4adjy, w4diag);
  8907. const float4 w5 = float4(w5curr, w5adjx, w5adjy, w5diag);
  8908. const float4 w6 = float4(w6curr, w6adjx, w6adjy, w6diag);
  8909. const float4 w7 = float4(w7curr, w7adjx, w7adjy, w7diag);
  8910. const float4 w8 = float4(w8curr, w8adjx, w8adjy, w8diag);
  8911. // Get the weight sum inverse (normalization factor):
  8912. const float4 weight_sum4 = w0 + w1 + w2 + w3 + w4 + w5 + w6 + w7 + w8;
  8913. const float2 weight_sum2 = weight_sum4.xy + weight_sum4.zw;
  8914. const float weight_sum = weight_sum2.x + weight_sum2.y;
  8915. const float weight_sum_inv = 1.0/(weight_sum);
  8916. // LOAD TEXTURE SAMPLES THIS FRAGMENT IS RESPONSIBLE FOR:
  8917. // Get a uv vector from texel 0q0 of this quadrant to texel 0q3:
  8918. const float2 dxdy_curr = dxdy * quad_vector.xy;
  8919. // Load bilinear samples for the current quadrant (for this fragment):
  8920. const float3 sample0curr = tex2D_linearize(tex, tex_uv.xy + dxdy_curr * sample0curr_texel_offset).rgb;
  8921. const float3 sample0adjx = tex2D_linearize(tex, tex_uv.xy + dxdy_curr * sample0adjx_texel_offset).rgb;
  8922. const float3 sample0adjy = tex2D_linearize(tex, tex_uv.xy + dxdy_curr * sample0adjy_texel_offset).rgb;
  8923. const float3 sample0diag = tex2D_linearize(tex, tex_uv.xy + dxdy_curr * sample0diag_texel_offset).rgb;
  8924. const float3 sample1curr = tex2Dlod_linearize(tex, tex_uv + uv2_to_uv4(dxdy_curr * sample1_texel_offset)).rgb;
  8925. const float3 sample2curr = tex2Dlod_linearize(tex, tex_uv + uv2_to_uv4(dxdy_curr * sample2_texel_offset)).rgb;
  8926. const float3 sample3curr = tex2Dlod_linearize(tex, tex_uv + uv2_to_uv4(dxdy_curr * sample3_texel_offset)).rgb;
  8927. const float3 sample4curr = tex2Dlod_linearize(tex, tex_uv + uv2_to_uv4(dxdy_curr * sample4_texel_offset)).rgb;
  8928. const float3 sample5curr = tex2Dlod_linearize(tex, tex_uv + uv2_to_uv4(dxdy_curr * sample5_texel_offset)).rgb;
  8929. const float3 sample6curr = tex2Dlod_linearize(tex, tex_uv + uv2_to_uv4(dxdy_curr * sample6_texel_offset)).rgb;
  8930. const float3 sample7curr = tex2Dlod_linearize(tex, tex_uv + uv2_to_uv4(dxdy_curr * sample7_texel_offset)).rgb;
  8931. const float3 sample8curr = tex2Dlod_linearize(tex, tex_uv + uv2_to_uv4(dxdy_curr * sample8_texel_offset)).rgb;
  8932. // GATHER NEIGHBORING SAMPLES AND SUM WEIGHTED SAMPLES:
  8933. // Fetch the samples from other fragments in the 2x2 quad:
  8934. float3 sample1adjx, sample1adjy, sample1diag;
  8935. float3 sample2adjx, sample2adjy, sample2diag;
  8936. float3 sample3adjx, sample3adjy, sample3diag;
  8937. float3 sample4adjx, sample4adjy, sample4diag;
  8938. float3 sample5adjx, sample5adjy, sample5diag;
  8939. float3 sample6adjx, sample6adjy, sample6diag;
  8940. float3 sample7adjx, sample7adjy, sample7diag;
  8941. float3 sample8adjx, sample8adjy, sample8diag;
  8942. quad_gather(quad_vector, sample1curr, sample1adjx, sample1adjy, sample1diag);
  8943. quad_gather(quad_vector, sample2curr, sample2adjx, sample2adjy, sample2diag);
  8944. quad_gather(quad_vector, sample3curr, sample3adjx, sample3adjy, sample3diag);
  8945. quad_gather(quad_vector, sample4curr, sample4adjx, sample4adjy, sample4diag);
  8946. quad_gather(quad_vector, sample5curr, sample5adjx, sample5adjy, sample5diag);
  8947. quad_gather(quad_vector, sample6curr, sample6adjx, sample6adjy, sample6diag);
  8948. quad_gather(quad_vector, sample7curr, sample7adjx, sample7adjy, sample7diag);
  8949. quad_gather(quad_vector, sample8curr, sample8adjx, sample8adjy, sample8diag);
  8950. // Statically normalize weights (so total = 1.0), and sum weighted samples.
  8951. // Fill each row of a matrix with an rgb sample and pre-multiply by the
  8952. // weights to obtain a weighted result:
  8953. float3 sum = float3(0.0,0.0,0.0);
  8954. sum += mul(w0, float4x3(sample0curr, sample0adjx, sample0adjy, sample0diag));
  8955. sum += mul(w1, float4x3(sample1curr, sample1adjx, sample1adjy, sample1diag));
  8956. sum += mul(w2, float4x3(sample2curr, sample2adjx, sample2adjy, sample2diag));
  8957. sum += mul(w3, float4x3(sample3curr, sample3adjx, sample3adjy, sample3diag));
  8958. sum += mul(w4, float4x3(sample4curr, sample4adjx, sample4adjy, sample4diag));
  8959. sum += mul(w5, float4x3(sample5curr, sample5adjx, sample5adjy, sample5diag));
  8960. sum += mul(w6, float4x3(sample6curr, sample6adjx, sample6adjy, sample6diag));
  8961. sum += mul(w7, float4x3(sample7curr, sample7adjx, sample7adjy, sample7diag));
  8962. sum += mul(w8, float4x3(sample8curr, sample8adjx, sample8adjy, sample8diag));
  8963. return sum * weight_sum_inv;
  8964. }
  8965. float3 tex2Dblur10x10shared(const sampler2D tex,
  8966. const float4 tex_uv, const float2 dxdy, const float4 quad_vector,
  8967. const float sigma)
  8968. {
  8969. // Perform a 1-pass mipmapped blur with shared samples across a pixel quad.
  8970. // Requires: Same as tex2Dblur12x12shared()
  8971. // Returns: A blurred texture lookup using a "virtual" 10x10 Gaussian
  8972. // blur (a 5x5 blur of carefully selected bilinear samples)
  8973. // of the given mip level. There will be subtle inaccuracies,
  8974. // especially for small or high-frequency detailed sources.
  8975. // Description:
  8976. // First see the description for tex2Dblur12x12shared(). This
  8977. // function shares the same concept and sample placement, but each fragment
  8978. // only uses 25 of the 36 samples taken across the pixel quad (to cover a
  8979. // 5x5 sample area, or 10x10 texel area), and it uses a lower standard
  8980. // deviation to compensate. Thanks to symmetry, the 11 omitted samples
  8981. // are always the "same:"
  8982. // 8adjx, 2adjx, 5adjx,
  8983. // 6adjy, 7adjy, 8adjy,
  8984. // 2diag, 5diag, 6diag, 7diag, 8diag
  8985. // COMPUTE COORDS FOR TEXTURE SAMPLES THIS FRAGMENT IS RESPONSIBLE FOR:
  8986. // Statically compute bilinear sampling offsets (details in tex2Dblur12x12shared).
  8987. const float denom_inv = 0.5/(sigma*sigma);
  8988. const float w0off = 1.0;
  8989. const float w0_5off = exp(-(0.5*0.5) * denom_inv);
  8990. const float w1off = exp(-(1.0*1.0) * denom_inv);
  8991. const float w1_5off = exp(-(1.5*1.5) * denom_inv);
  8992. const float w2off = exp(-(2.0*2.0) * denom_inv);
  8993. const float w2_5off = exp(-(2.5*2.5) * denom_inv);
  8994. const float w3_5off = exp(-(3.5*3.5) * denom_inv);
  8995. const float w4_5off = exp(-(4.5*4.5) * denom_inv);
  8996. const float w5_5off = exp(-(5.5*5.5) * denom_inv);
  8997. const float texel0to1ratio = lerp(w1_5off/(w0_5off + w1_5off), 0.5, error_blurring);
  8998. const float texel2to3ratio = lerp(w3_5off/(w2_5off + w3_5off), 0.5, error_blurring);
  8999. const float texel4to5ratio = lerp(w5_5off/(w4_5off + w5_5off), 0.5, error_blurring);
  9000. // We don't share sample0*, so use the nearest destination fragment:
  9001. const float texel0to1ratio_nearest = w1off/(w0off + w1off);
  9002. const float texel1to2ratio_nearest = w2off/(w1off + w2off);
  9003. // Statically compute texel offsets from the bottom-right fragment to each
  9004. // bilinear sample in the bottom-right quadrant:
  9005. const float2 sample0curr_texel_offset = float2(0.0, 0.0) + float2(texel0to1ratio_nearest, texel0to1ratio_nearest);
  9006. const float2 sample0adjx_texel_offset = float2(-1.0, 0.0) + float2(-texel1to2ratio_nearest, texel0to1ratio_nearest);
  9007. const float2 sample0adjy_texel_offset = float2(0.0, -1.0) + float2(texel0to1ratio_nearest, -texel1to2ratio_nearest);
  9008. const float2 sample0diag_texel_offset = float2(-1.0, -1.0) + float2(-texel1to2ratio_nearest, -texel1to2ratio_nearest);
  9009. const float2 sample1_texel_offset = float2(2.0, 0.0) + float2(texel2to3ratio, texel0to1ratio);
  9010. const float2 sample2_texel_offset = float2(4.0, 0.0) + float2(texel4to5ratio, texel0to1ratio);
  9011. const float2 sample3_texel_offset = float2(0.0, 2.0) + float2(texel0to1ratio, texel2to3ratio);
  9012. const float2 sample4_texel_offset = float2(2.0, 2.0) + float2(texel2to3ratio, texel2to3ratio);
  9013. const float2 sample5_texel_offset = float2(4.0, 2.0) + float2(texel4to5ratio, texel2to3ratio);
  9014. const float2 sample6_texel_offset = float2(0.0, 4.0) + float2(texel0to1ratio, texel4to5ratio);
  9015. const float2 sample7_texel_offset = float2(2.0, 4.0) + float2(texel2to3ratio, texel4to5ratio);
  9016. const float2 sample8_texel_offset = float2(4.0, 4.0) + float2(texel4to5ratio, texel4to5ratio);
  9017. // CALCULATE KERNEL WEIGHTS:
  9018. // Statically compute bilinear sample weights at each destination fragment
  9019. // from the sum of their 4 texel weights (details in tex2Dblur12x12shared).
  9020. #define GET_TEXEL_QUAD_WEIGHTS(xoff, yoff) \
  9021. (exp(-LENGTH_SQ(float2(xoff, yoff)) * denom_inv) + \
  9022. exp(-LENGTH_SQ(float2(xoff + 1.0, yoff)) * denom_inv) + \
  9023. exp(-LENGTH_SQ(float2(xoff, yoff + 1.0)) * denom_inv) + \
  9024. exp(-LENGTH_SQ(float2(xoff + 1.0, yoff + 1.0)) * denom_inv))
  9025. // We only need 25 of the 36 sample weights. Skip the following weights:
  9026. // 8adjx, 2adjx, 5adjx,
  9027. // 6adjy, 7adjy, 8adjy,
  9028. // 2diag, 5diag, 6diag, 7diag, 8diag
  9029. const float w4diag = GET_TEXEL_QUAD_WEIGHTS(-4.0, -4.0);
  9030. const float w3diag = GET_TEXEL_QUAD_WEIGHTS(-2.0, -4.0);
  9031. const float w3adjy = GET_TEXEL_QUAD_WEIGHTS(0.0, -4.0);
  9032. const float w4adjy = GET_TEXEL_QUAD_WEIGHTS(2.0, -4.0);
  9033. const float w5adjy = GET_TEXEL_QUAD_WEIGHTS(4.0, -4.0);
  9034. const float w1diag = GET_TEXEL_QUAD_WEIGHTS(-4.0, -2.0);
  9035. const float w0diag = GET_TEXEL_QUAD_WEIGHTS(-2.0, -2.0);
  9036. const float w0adjy = GET_TEXEL_QUAD_WEIGHTS(0.0, -2.0);
  9037. const float w1adjy = GET_TEXEL_QUAD_WEIGHTS(2.0, -2.0);
  9038. const float w2adjy = GET_TEXEL_QUAD_WEIGHTS(4.0, -2.0);
  9039. const float w1adjx = GET_TEXEL_QUAD_WEIGHTS(-4.0, 0.0);
  9040. const float w0adjx = GET_TEXEL_QUAD_WEIGHTS(-2.0, 0.0);
  9041. const float w0curr = GET_TEXEL_QUAD_WEIGHTS(0.0, 0.0);
  9042. const float w1curr = GET_TEXEL_QUAD_WEIGHTS(2.0, 0.0);
  9043. const float w2curr = GET_TEXEL_QUAD_WEIGHTS(4.0, 0.0);
  9044. const float w4adjx = GET_TEXEL_QUAD_WEIGHTS(-4.0, 2.0);
  9045. const float w3adjx = GET_TEXEL_QUAD_WEIGHTS(-2.0, 2.0);
  9046. const float w3curr = GET_TEXEL_QUAD_WEIGHTS(0.0, 2.0);
  9047. const float w4curr = GET_TEXEL_QUAD_WEIGHTS(2.0, 2.0);
  9048. const float w5curr = GET_TEXEL_QUAD_WEIGHTS(4.0, 2.0);
  9049. const float w7adjx = GET_TEXEL_QUAD_WEIGHTS(-4.0, 4.0);
  9050. const float w6adjx = GET_TEXEL_QUAD_WEIGHTS(-2.0, 4.0);
  9051. const float w6curr = GET_TEXEL_QUAD_WEIGHTS(0.0, 4.0);
  9052. const float w7curr = GET_TEXEL_QUAD_WEIGHTS(2.0, 4.0);
  9053. const float w8curr = GET_TEXEL_QUAD_WEIGHTS(4.0, 4.0);
  9054. #undef GET_TEXEL_QUAD_WEIGHTS
  9055. // Get the weight sum inverse (normalization factor):
  9056. const float weight_sum_inv = 1.0/(w0curr + w1curr + w2curr + w3curr +
  9057. w4curr + w5curr + w6curr + w7curr + w8curr +
  9058. w0adjx + w1adjx + w3adjx + w4adjx + w6adjx + w7adjx +
  9059. w0adjy + w1adjy + w2adjy + w3adjy + w4adjy + w5adjy +
  9060. w0diag + w1diag + w3diag + w4diag);
  9061. // Statically pack most weights for runtime. Note the mixed packing:
  9062. const float4 w0 = float4(w0curr, w0adjx, w0adjy, w0diag);
  9063. const float4 w1 = float4(w1curr, w1adjx, w1adjy, w1diag);
  9064. const float4 w3 = float4(w3curr, w3adjx, w3adjy, w3diag);
  9065. const float4 w4 = float4(w4curr, w4adjx, w4adjy, w4diag);
  9066. const float4 w2and5 = float4(w2curr, w2adjy, w5curr, w5adjy);
  9067. const float4 w6and7 = float4(w6curr, w6adjx, w7curr, w7adjx);
  9068. // LOAD TEXTURE SAMPLES THIS FRAGMENT IS RESPONSIBLE FOR:
  9069. // Get a uv vector from texel 0q0 of this quadrant to texel 0q3:
  9070. const float2 dxdy_curr = dxdy * quad_vector.xy;
  9071. // Load bilinear samples for the current quadrant (for this fragment):
  9072. const float3 sample0curr = tex2D_linearize(tex, tex_uv.xy + dxdy_curr * sample0curr_texel_offset).rgb;
  9073. const float3 sample0adjx = tex2D_linearize(tex, tex_uv.xy + dxdy_curr * sample0adjx_texel_offset).rgb;
  9074. const float3 sample0adjy = tex2D_linearize(tex, tex_uv.xy + dxdy_curr * sample0adjy_texel_offset).rgb;
  9075. const float3 sample0diag = tex2D_linearize(tex, tex_uv.xy + dxdy_curr * sample0diag_texel_offset).rgb;
  9076. const float3 sample1curr = tex2Dlod_linearize(tex, tex_uv + uv2_to_uv4(dxdy_curr * sample1_texel_offset)).rgb;
  9077. const float3 sample2curr = tex2Dlod_linearize(tex, tex_uv + uv2_to_uv4(dxdy_curr * sample2_texel_offset)).rgb;
  9078. const float3 sample3curr = tex2Dlod_linearize(tex, tex_uv + uv2_to_uv4(dxdy_curr * sample3_texel_offset)).rgb;
  9079. const float3 sample4curr = tex2Dlod_linearize(tex, tex_uv + uv2_to_uv4(dxdy_curr * sample4_texel_offset)).rgb;
  9080. const float3 sample5curr = tex2Dlod_linearize(tex, tex_uv + uv2_to_uv4(dxdy_curr * sample5_texel_offset)).rgb;
  9081. const float3 sample6curr = tex2Dlod_linearize(tex, tex_uv + uv2_to_uv4(dxdy_curr * sample6_texel_offset)).rgb;
  9082. const float3 sample7curr = tex2Dlod_linearize(tex, tex_uv + uv2_to_uv4(dxdy_curr * sample7_texel_offset)).rgb;
  9083. const float3 sample8curr = tex2Dlod_linearize(tex, tex_uv + uv2_to_uv4(dxdy_curr * sample8_texel_offset)).rgb;
  9084. // GATHER NEIGHBORING SAMPLES AND SUM WEIGHTED SAMPLES:
  9085. // Fetch the samples from other fragments in the 2x2 quad in order of need:
  9086. float3 sample1adjx, sample1adjy, sample1diag;
  9087. float3 sample2adjx, sample2adjy, sample2diag;
  9088. float3 sample3adjx, sample3adjy, sample3diag;
  9089. float3 sample4adjx, sample4adjy, sample4diag;
  9090. float3 sample5adjx, sample5adjy, sample5diag;
  9091. float3 sample6adjx, sample6adjy, sample6diag;
  9092. float3 sample7adjx, sample7adjy, sample7diag;
  9093. quad_gather(quad_vector, sample1curr, sample1adjx, sample1adjy, sample1diag);
  9094. quad_gather(quad_vector, sample2curr, sample2adjx, sample2adjy, sample2diag);
  9095. quad_gather(quad_vector, sample3curr, sample3adjx, sample3adjy, sample3diag);
  9096. quad_gather(quad_vector, sample4curr, sample4adjx, sample4adjy, sample4diag);
  9097. quad_gather(quad_vector, sample5curr, sample5adjx, sample5adjy, sample5diag);
  9098. quad_gather(quad_vector, sample6curr, sample6adjx, sample6adjy, sample6diag);
  9099. quad_gather(quad_vector, sample7curr, sample7adjx, sample7adjy, sample7diag);
  9100. // Statically normalize weights (so total = 1.0), and sum weighted samples.
  9101. // Fill each row of a matrix with an rgb sample and pre-multiply by the
  9102. // weights to obtain a weighted result. First do the simple ones:
  9103. float3 sum = float3(0.0,0.0,0.0);
  9104. sum += mul(w0, float4x3(sample0curr, sample0adjx, sample0adjy, sample0diag));
  9105. sum += mul(w1, float4x3(sample1curr, sample1adjx, sample1adjy, sample1diag));
  9106. sum += mul(w3, float4x3(sample3curr, sample3adjx, sample3adjy, sample3diag));
  9107. sum += mul(w4, float4x3(sample4curr, sample4adjx, sample4adjy, sample4diag));
  9108. // Now do the mixed-sample ones:
  9109. sum += mul(w2and5, float4x3(sample2curr, sample2adjy, sample5curr, sample5adjy));
  9110. sum += mul(w6and7, float4x3(sample6curr, sample6adjx, sample7curr, sample7adjx));
  9111. sum += w8curr * sample8curr;
  9112. // Normalize the sum (so the weights add to 1.0) and return:
  9113. return sum * weight_sum_inv;
  9114. }
  9115. float3 tex2Dblur8x8shared(const sampler2D tex,
  9116. const float4 tex_uv, const float2 dxdy, const float4 quad_vector,
  9117. const float sigma)
  9118. {
  9119. // Perform a 1-pass mipmapped blur with shared samples across a pixel quad.
  9120. // Requires: Same as tex2Dblur12x12shared()
  9121. // Returns: A blurred texture lookup using a "virtual" 8x8 Gaussian
  9122. // blur (a 4x4 blur of carefully selected bilinear samples)
  9123. // of the given mip level. There will be subtle inaccuracies,
  9124. // especially for small or high-frequency detailed sources.
  9125. // Description:
  9126. // First see the description for tex2Dblur12x12shared(). This function
  9127. // shares the same concept and a similar sample placement, except each
  9128. // quadrant contains 4x4 texels and 2x2 samples instead of 6x6 and 3x3
  9129. // respectively. There could be a total of 16 samples, 4 of which each
  9130. // fragment is responsible for, but each fragment loads 0a/0b/0c/0d with
  9131. // its own offset to reduce shared sample artifacts, bringing the sample
  9132. // count for each fragment to 7. Sample placement:
  9133. // 3a 2a 2b 3b
  9134. // 1a 0a 0b 1b
  9135. // 1c 0c 0d 1d
  9136. // 3c 2c 2d 3d
  9137. // Texel placement:
  9138. // 3a3 3a2 2a3 2a2 2b2 2b3 3b2 3b3
  9139. // 3a1 3a0 2a1 2a0 2b0 2b1 3b0 3b1
  9140. // 1a3 1a2 0a3 0a2 0b2 0b3 1b2 1b3
  9141. // 1a1 1a0 0a1 0a0 0b0 0b1 1b0 1b1
  9142. // 1c1 1c0 0c1 0c0 0d0 0d1 1d0 1d1
  9143. // 1c3 1c2 0c3 0c2 0d2 0d3 1d2 1d3
  9144. // 3c1 3c0 2c1 2c0 2d0 2d1 3d0 4d1
  9145. // 3c3 3c2 2c3 2c2 2d2 2d3 3d2 4d3
  9146. // COMPUTE COORDS FOR TEXTURE SAMPLES THIS FRAGMENT IS RESPONSIBLE FOR:
  9147. // Statically compute bilinear sampling offsets (details in tex2Dblur12x12shared).
  9148. const float denom_inv = 0.5/(sigma*sigma);
  9149. const float w0off = 1.0;
  9150. const float w0_5off = exp(-(0.5*0.5) * denom_inv);
  9151. const float w1off = exp(-(1.0*1.0) * denom_inv);
  9152. const float w1_5off = exp(-(1.5*1.5) * denom_inv);
  9153. const float w2off = exp(-(2.0*2.0) * denom_inv);
  9154. const float w2_5off = exp(-(2.5*2.5) * denom_inv);
  9155. const float w3_5off = exp(-(3.5*3.5) * denom_inv);
  9156. const float texel0to1ratio = lerp(w1_5off/(w0_5off + w1_5off), 0.5, error_blurring);
  9157. const float texel2to3ratio = lerp(w3_5off/(w2_5off + w3_5off), 0.5, error_blurring);
  9158. // We don't share sample0*, so use the nearest destination fragment:
  9159. const float texel0to1ratio_nearest = w1off/(w0off + w1off);
  9160. const float texel1to2ratio_nearest = w2off/(w1off + w2off);
  9161. // Statically compute texel offsets from the bottom-right fragment to each
  9162. // bilinear sample in the bottom-right quadrant:
  9163. const float2 sample0curr_texel_offset = float2(0.0, 0.0) + float2(texel0to1ratio_nearest, texel0to1ratio_nearest);
  9164. const float2 sample0adjx_texel_offset = float2(-1.0, 0.0) + float2(-texel1to2ratio_nearest, texel0to1ratio_nearest);
  9165. const float2 sample0adjy_texel_offset = float2(0.0, -1.0) + float2(texel0to1ratio_nearest, -texel1to2ratio_nearest);
  9166. const float2 sample0diag_texel_offset = float2(-1.0, -1.0) + float2(-texel1to2ratio_nearest, -texel1to2ratio_nearest);
  9167. const float2 sample1_texel_offset = float2(2.0, 0.0) + float2(texel2to3ratio, texel0to1ratio);
  9168. const float2 sample2_texel_offset = float2(0.0, 2.0) + float2(texel0to1ratio, texel2to3ratio);
  9169. const float2 sample3_texel_offset = float2(2.0, 2.0) + float2(texel2to3ratio, texel2to3ratio);
  9170. // CALCULATE KERNEL WEIGHTS:
  9171. // Statically compute bilinear sample weights at each destination fragment
  9172. // from the sum of their 4 texel weights (details in tex2Dblur12x12shared).
  9173. #define GET_TEXEL_QUAD_WEIGHTS(xoff, yoff) \
  9174. (exp(-LENGTH_SQ(float2(xoff, yoff)) * denom_inv) + \
  9175. exp(-LENGTH_SQ(float2(xoff + 1.0, yoff)) * denom_inv) + \
  9176. exp(-LENGTH_SQ(float2(xoff, yoff + 1.0)) * denom_inv) + \
  9177. exp(-LENGTH_SQ(float2(xoff + 1.0, yoff + 1.0)) * denom_inv))
  9178. const float w3diag = GET_TEXEL_QUAD_WEIGHTS(-4.0, -4.0);
  9179. const float w2diag = GET_TEXEL_QUAD_WEIGHTS(-2.0, -4.0);
  9180. const float w2adjy = GET_TEXEL_QUAD_WEIGHTS(0.0, -4.0);
  9181. const float w3adjy = GET_TEXEL_QUAD_WEIGHTS(2.0, -4.0);
  9182. const float w1diag = GET_TEXEL_QUAD_WEIGHTS(-4.0, -2.0);
  9183. const float w0diag = GET_TEXEL_QUAD_WEIGHTS(-2.0, -2.0);
  9184. const float w0adjy = GET_TEXEL_QUAD_WEIGHTS(0.0, -2.0);
  9185. const float w1adjy = GET_TEXEL_QUAD_WEIGHTS(2.0, -2.0);
  9186. const float w1adjx = GET_TEXEL_QUAD_WEIGHTS(-4.0, 0.0);
  9187. const float w0adjx = GET_TEXEL_QUAD_WEIGHTS(-2.0, 0.0);
  9188. const float w0curr = GET_TEXEL_QUAD_WEIGHTS(0.0, 0.0);
  9189. const float w1curr = GET_TEXEL_QUAD_WEIGHTS(2.0, 0.0);
  9190. const float w3adjx = GET_TEXEL_QUAD_WEIGHTS(-4.0, 2.0);
  9191. const float w2adjx = GET_TEXEL_QUAD_WEIGHTS(-2.0, 2.0);
  9192. const float w2curr = GET_TEXEL_QUAD_WEIGHTS(0.0, 2.0);
  9193. const float w3curr = GET_TEXEL_QUAD_WEIGHTS(2.0, 2.0);
  9194. #undef GET_TEXEL_QUAD_WEIGHTS
  9195. // Statically pack weights for runtime:
  9196. const float4 w0 = float4(w0curr, w0adjx, w0adjy, w0diag);
  9197. const float4 w1 = float4(w1curr, w1adjx, w1adjy, w1diag);
  9198. const float4 w2 = float4(w2curr, w2adjx, w2adjy, w2diag);
  9199. const float4 w3 = float4(w3curr, w3adjx, w3adjy, w3diag);
  9200. // Get the weight sum inverse (normalization factor):
  9201. const float4 weight_sum4 = w0 + w1 + w2 + w3;
  9202. const float2 weight_sum2 = weight_sum4.xy + weight_sum4.zw;
  9203. const float weight_sum = weight_sum2.x + weight_sum2.y;
  9204. const float weight_sum_inv = 1.0/(weight_sum);
  9205. // LOAD TEXTURE SAMPLES THIS FRAGMENT IS RESPONSIBLE FOR:
  9206. // Get a uv vector from texel 0q0 of this quadrant to texel 0q3:
  9207. const float2 dxdy_curr = dxdy * quad_vector.xy;
  9208. // Load bilinear samples for the current quadrant (for this fragment):
  9209. const float3 sample0curr = tex2D_linearize(tex, tex_uv.xy + dxdy_curr * sample0curr_texel_offset).rgb;
  9210. const float3 sample0adjx = tex2D_linearize(tex, tex_uv.xy + dxdy_curr * sample0adjx_texel_offset).rgb;
  9211. const float3 sample0adjy = tex2D_linearize(tex, tex_uv.xy + dxdy_curr * sample0adjy_texel_offset).rgb;
  9212. const float3 sample0diag = tex2D_linearize(tex, tex_uv.xy + dxdy_curr * sample0diag_texel_offset).rgb;
  9213. const float3 sample1curr = tex2Dlod_linearize(tex, tex_uv + uv2_to_uv4(dxdy_curr * sample1_texel_offset)).rgb;
  9214. const float3 sample2curr = tex2Dlod_linearize(tex, tex_uv + uv2_to_uv4(dxdy_curr * sample2_texel_offset)).rgb;
  9215. const float3 sample3curr = tex2Dlod_linearize(tex, tex_uv + uv2_to_uv4(dxdy_curr * sample3_texel_offset)).rgb;
  9216. // GATHER NEIGHBORING SAMPLES AND SUM WEIGHTED SAMPLES:
  9217. // Fetch the samples from other fragments in the 2x2 quad:
  9218. float3 sample1adjx, sample1adjy, sample1diag;
  9219. float3 sample2adjx, sample2adjy, sample2diag;
  9220. float3 sample3adjx, sample3adjy, sample3diag;
  9221. quad_gather(quad_vector, sample1curr, sample1adjx, sample1adjy, sample1diag);
  9222. quad_gather(quad_vector, sample2curr, sample2adjx, sample2adjy, sample2diag);
  9223. quad_gather(quad_vector, sample3curr, sample3adjx, sample3adjy, sample3diag);
  9224. // Statically normalize weights (so total = 1.0), and sum weighted samples.
  9225. // Fill each row of a matrix with an rgb sample and pre-multiply by the
  9226. // weights to obtain a weighted result:
  9227. float3 sum = float3(0.0,0.0,0.0);
  9228. sum += mul(w0, float4x3(sample0curr, sample0adjx, sample0adjy, sample0diag));
  9229. sum += mul(w1, float4x3(sample1curr, sample1adjx, sample1adjy, sample1diag));
  9230. sum += mul(w2, float4x3(sample2curr, sample2adjx, sample2adjy, sample2diag));
  9231. sum += mul(w3, float4x3(sample3curr, sample3adjx, sample3adjy, sample3diag));
  9232. return sum * weight_sum_inv;
  9233. }
  9234. float3 tex2Dblur6x6shared(const sampler2D tex,
  9235. const float4 tex_uv, const float2 dxdy, const float4 quad_vector,
  9236. const float sigma)
  9237. {
  9238. // Perform a 1-pass mipmapped blur with shared samples across a pixel quad.
  9239. // Requires: Same as tex2Dblur12x12shared()
  9240. // Returns: A blurred texture lookup using a "virtual" 6x6 Gaussian
  9241. // blur (a 3x3 blur of carefully selected bilinear samples)
  9242. // of the given mip level. There will be some inaccuracies,subtle inaccuracies,
  9243. // especially for small or high-frequency detailed sources.
  9244. // Description:
  9245. // First see the description for tex2Dblur8x8shared(). This
  9246. // function shares the same concept and sample placement, but each fragment
  9247. // only uses 9 of the 16 samples taken across the pixel quad (to cover a
  9248. // 3x3 sample area, or 6x6 texel area), and it uses a lower standard
  9249. // deviation to compensate. Thanks to symmetry, the 7 omitted samples
  9250. // are always the "same:"
  9251. // 1adjx, 3adjx
  9252. // 2adjy, 3adjy
  9253. // 1diag, 2diag, 3diag
  9254. // COMPUTE COORDS FOR TEXTURE SAMPLES THIS FRAGMENT IS RESPONSIBLE FOR:
  9255. // Statically compute bilinear sampling offsets (details in tex2Dblur12x12shared).
  9256. const float denom_inv = 0.5/(sigma*sigma);
  9257. const float w0off = 1.0;
  9258. const float w0_5off = exp(-(0.5*0.5) * denom_inv);
  9259. const float w1off = exp(-(1.0*1.0) * denom_inv);
  9260. const float w1_5off = exp(-(1.5*1.5) * denom_inv);
  9261. const float w2off = exp(-(2.0*2.0) * denom_inv);
  9262. const float w2_5off = exp(-(2.5*2.5) * denom_inv);
  9263. const float w3_5off = exp(-(3.5*3.5) * denom_inv);
  9264. const float texel0to1ratio = lerp(w1_5off/(w0_5off + w1_5off), 0.5, error_blurring);
  9265. const float texel2to3ratio = lerp(w3_5off/(w2_5off + w3_5off), 0.5, error_blurring);
  9266. // We don't share sample0*, so use the nearest destination fragment:
  9267. const float texel0to1ratio_nearest = w1off/(w0off + w1off);
  9268. const float texel1to2ratio_nearest = w2off/(w1off + w2off);
  9269. // Statically compute texel offsets from the bottom-right fragment to each
  9270. // bilinear sample in the bottom-right quadrant:
  9271. const float2 sample0curr_texel_offset = float2(0.0, 0.0) + float2(texel0to1ratio_nearest, texel0to1ratio_nearest);
  9272. const float2 sample0adjx_texel_offset = float2(-1.0, 0.0) + float2(-texel1to2ratio_nearest, texel0to1ratio_nearest);
  9273. const float2 sample0adjy_texel_offset = float2(0.0, -1.0) + float2(texel0to1ratio_nearest, -texel1to2ratio_nearest);
  9274. const float2 sample0diag_texel_offset = float2(-1.0, -1.0) + float2(-texel1to2ratio_nearest, -texel1to2ratio_nearest);
  9275. const float2 sample1_texel_offset = float2(2.0, 0.0) + float2(texel2to3ratio, texel0to1ratio);
  9276. const float2 sample2_texel_offset = float2(0.0, 2.0) + float2(texel0to1ratio, texel2to3ratio);
  9277. const float2 sample3_texel_offset = float2(2.0, 2.0) + float2(texel2to3ratio, texel2to3ratio);
  9278. // CALCULATE KERNEL WEIGHTS:
  9279. // Statically compute bilinear sample weights at each destination fragment
  9280. // from the sum of their 4 texel weights (details in tex2Dblur12x12shared).
  9281. #define GET_TEXEL_QUAD_WEIGHTS(xoff, yoff) \
  9282. (exp(-LENGTH_SQ(float2(xoff, yoff)) * denom_inv) + \
  9283. exp(-LENGTH_SQ(float2(xoff + 1.0, yoff)) * denom_inv) + \
  9284. exp(-LENGTH_SQ(float2(xoff, yoff + 1.0)) * denom_inv) + \
  9285. exp(-LENGTH_SQ(float2(xoff + 1.0, yoff + 1.0)) * denom_inv))
  9286. // We only need 9 of the 16 sample weights. Skip the following weights:
  9287. // 1adjx, 3adjx
  9288. // 2adjy, 3adjy
  9289. // 1diag, 2diag, 3diag
  9290. const float w0diag = GET_TEXEL_QUAD_WEIGHTS(-2.0, -2.0);
  9291. const float w0adjy = GET_TEXEL_QUAD_WEIGHTS(0.0, -2.0);
  9292. const float w1adjy = GET_TEXEL_QUAD_WEIGHTS(2.0, -2.0);
  9293. const float w0adjx = GET_TEXEL_QUAD_WEIGHTS(-2.0, 0.0);
  9294. const float w0curr = GET_TEXEL_QUAD_WEIGHTS(0.0, 0.0);
  9295. const float w1curr = GET_TEXEL_QUAD_WEIGHTS(2.0, 0.0);
  9296. const float w2adjx = GET_TEXEL_QUAD_WEIGHTS(-2.0, 2.0);
  9297. const float w2curr = GET_TEXEL_QUAD_WEIGHTS(0.0, 2.0);
  9298. const float w3curr = GET_TEXEL_QUAD_WEIGHTS(2.0, 2.0);
  9299. #undef GET_TEXEL_QUAD_WEIGHTS
  9300. // Get the weight sum inverse (normalization factor):
  9301. const float weight_sum_inv = 1.0/(w0curr + w1curr + w2curr + w3curr +
  9302. w0adjx + w2adjx + w0adjy + w1adjy + w0diag);
  9303. // Statically pack some weights for runtime:
  9304. const float4 w0 = float4(w0curr, w0adjx, w0adjy, w0diag);
  9305. // LOAD TEXTURE SAMPLES THIS FRAGMENT IS RESPONSIBLE FOR:
  9306. // Get a uv vector from texel 0q0 of this quadrant to texel 0q3:
  9307. const float2 dxdy_curr = dxdy * quad_vector.xy;
  9308. // Load bilinear samples for the current quadrant (for this fragment):
  9309. const float3 sample0curr = tex2D_linearize(tex, tex_uv.xy + dxdy_curr * sample0curr_texel_offset).rgb;
  9310. const float3 sample0adjx = tex2D_linearize(tex, tex_uv.xy + dxdy_curr * sample0adjx_texel_offset).rgb;
  9311. const float3 sample0adjy = tex2D_linearize(tex, tex_uv.xy + dxdy_curr * sample0adjy_texel_offset).rgb;
  9312. const float3 sample0diag = tex2D_linearize(tex, tex_uv.xy + dxdy_curr * sample0diag_texel_offset).rgb;
  9313. const float3 sample1curr = tex2Dlod_linearize(tex, tex_uv + uv2_to_uv4(dxdy_curr * sample1_texel_offset)).rgb;
  9314. const float3 sample2curr = tex2Dlod_linearize(tex, tex_uv + uv2_to_uv4(dxdy_curr * sample2_texel_offset)).rgb;
  9315. const float3 sample3curr = tex2Dlod_linearize(tex, tex_uv + uv2_to_uv4(dxdy_curr * sample3_texel_offset)).rgb;
  9316. // GATHER NEIGHBORING SAMPLES AND SUM WEIGHTED SAMPLES:
  9317. // Fetch the samples from other fragments in the 2x2 quad:
  9318. float3 sample1adjx, sample1adjy, sample1diag;
  9319. float3 sample2adjx, sample2adjy, sample2diag;
  9320. quad_gather(quad_vector, sample1curr, sample1adjx, sample1adjy, sample1diag);
  9321. quad_gather(quad_vector, sample2curr, sample2adjx, sample2adjy, sample2diag);
  9322. // Statically normalize weights (so total = 1.0), and sum weighted samples.
  9323. // Fill each row of a matrix with an rgb sample and pre-multiply by the
  9324. // weights to obtain a weighted result for sample1*, and handle the rest
  9325. // of the weights more directly/verbosely:
  9326. float3 sum = float3(0.0,0.0,0.0);
  9327. sum += mul(w0, float4x3(sample0curr, sample0adjx, sample0adjy, sample0diag));
  9328. sum += w1curr * sample1curr + w1adjy * sample1adjy + w2curr * sample2curr +
  9329. w2adjx * sample2adjx + w3curr * sample3curr;
  9330. return sum * weight_sum_inv;
  9331. }
  9332. /////////////////////// MAX OPTIMAL SIGMA BLUR WRAPPERS //////////////////////
  9333. // The following blurs are static wrappers around the dynamic blurs above.
  9334. // HOPEFULLY, the compiler will be smart enough to do constant-folding.
  9335. // Resizable separable blurs:
  9336. inline float3 tex2Dblur11resize(const sampler2D tex, const float2 tex_uv,
  9337. const float2 dxdy)
  9338. {
  9339. return tex2Dblur11resize(tex, tex_uv, dxdy, blur11_std_dev);
  9340. }
  9341. inline float3 tex2Dblur9resize(const sampler2D tex, const float2 tex_uv,
  9342. const float2 dxdy)
  9343. {
  9344. return tex2Dblur9resize(tex, tex_uv, dxdy, blur9_std_dev);
  9345. }
  9346. inline float3 tex2Dblur7resize(const sampler2D tex, const float2 tex_uv,
  9347. const float2 dxdy)
  9348. {
  9349. return tex2Dblur7resize(tex, tex_uv, dxdy, blur7_std_dev);
  9350. }
  9351. inline float3 tex2Dblur5resize(const sampler2D tex, const float2 tex_uv,
  9352. const float2 dxdy)
  9353. {
  9354. return tex2Dblur5resize(tex, tex_uv, dxdy, blur5_std_dev);
  9355. }
  9356. inline float3 tex2Dblur3resize(const sampler2D tex, const float2 tex_uv,
  9357. const float2 dxdy)
  9358. {
  9359. return tex2Dblur3resize(tex, tex_uv, dxdy, blur3_std_dev);
  9360. }
  9361. // Fast separable blurs:
  9362. inline float3 tex2Dblur11fast(const sampler2D tex, const float2 tex_uv,
  9363. const float2 dxdy)
  9364. {
  9365. return tex2Dblur11fast(tex, tex_uv, dxdy, blur11_std_dev);
  9366. }
  9367. inline float3 tex2Dblur9fast(const sampler2D tex, const float2 tex_uv,
  9368. const float2 dxdy)
  9369. {
  9370. return tex2Dblur9fast(tex, tex_uv, dxdy, blur9_std_dev);
  9371. }
  9372. inline float3 tex2Dblur7fast(const sampler2D tex, const float2 tex_uv,
  9373. const float2 dxdy)
  9374. {
  9375. return tex2Dblur7fast(tex, tex_uv, dxdy, blur7_std_dev);
  9376. }
  9377. inline float3 tex2Dblur5fast(const sampler2D tex, const float2 tex_uv,
  9378. const float2 dxdy)
  9379. {
  9380. return tex2Dblur5fast(tex, tex_uv, dxdy, blur5_std_dev);
  9381. }
  9382. inline float3 tex2Dblur3fast(const sampler2D tex, const float2 tex_uv,
  9383. const float2 dxdy)
  9384. {
  9385. return tex2Dblur3fast(tex, tex_uv, dxdy, blur3_std_dev);
  9386. }
  9387. // Huge, "fast" separable blurs:
  9388. inline float3 tex2Dblur43fast(const sampler2D tex, const float2 tex_uv,
  9389. const float2 dxdy)
  9390. {
  9391. return tex2Dblur43fast(tex, tex_uv, dxdy, blur43_std_dev);
  9392. }
  9393. inline float3 tex2Dblur31fast(const sampler2D tex, const float2 tex_uv,
  9394. const float2 dxdy)
  9395. {
  9396. return tex2Dblur31fast(tex, tex_uv, dxdy, blur31_std_dev);
  9397. }
  9398. inline float3 tex2Dblur25fast(const sampler2D tex, const float2 tex_uv,
  9399. const float2 dxdy)
  9400. {
  9401. return tex2Dblur25fast(tex, tex_uv, dxdy, blur25_std_dev);
  9402. }
  9403. inline float3 tex2Dblur17fast(const sampler2D tex, const float2 tex_uv,
  9404. const float2 dxdy)
  9405. {
  9406. return tex2Dblur17fast(tex, tex_uv, dxdy, blur17_std_dev);
  9407. }
  9408. // Resizable one-pass blurs:
  9409. inline float3 tex2Dblur3x3resize(const sampler2D tex, const float2 tex_uv,
  9410. const float2 dxdy)
  9411. {
  9412. return tex2Dblur3x3resize(tex, tex_uv, dxdy, blur3_std_dev);
  9413. }
  9414. // "Fast" one-pass blurs:
  9415. inline float3 tex2Dblur9x9(const sampler2D tex, const float2 tex_uv,
  9416. const float2 dxdy)
  9417. {
  9418. return tex2Dblur9x9(tex, tex_uv, dxdy, blur9_std_dev);
  9419. }
  9420. inline float3 tex2Dblur7x7(const sampler2D tex, const float2 tex_uv,
  9421. const float2 dxdy)
  9422. {
  9423. return tex2Dblur7x7(tex, tex_uv, dxdy, blur7_std_dev);
  9424. }
  9425. inline float3 tex2Dblur5x5(const sampler2D tex, const float2 tex_uv,
  9426. const float2 dxdy)
  9427. {
  9428. return tex2Dblur5x5(tex, tex_uv, dxdy, blur5_std_dev);
  9429. }
  9430. inline float3 tex2Dblur3x3(const sampler2D tex, const float2 tex_uv,
  9431. const float2 dxdy)
  9432. {
  9433. return tex2Dblur3x3(tex, tex_uv, dxdy, blur3_std_dev);
  9434. }
  9435. // "Fast" shared-sample one-pass blurs:
  9436. inline float3 tex2Dblur12x12shared(const sampler2D tex,
  9437. const float4 tex_uv, const float2 dxdy, const float4 quad_vector)
  9438. {
  9439. return tex2Dblur12x12shared(tex, tex_uv, dxdy, quad_vector, blur12_std_dev);
  9440. }
  9441. inline float3 tex2Dblur10x10shared(const sampler2D tex,
  9442. const float4 tex_uv, const float2 dxdy, const float4 quad_vector)
  9443. {
  9444. return tex2Dblur10x10shared(tex, tex_uv, dxdy, quad_vector, blur10_std_dev);
  9445. }
  9446. inline float3 tex2Dblur8x8shared(const sampler2D tex,
  9447. const float4 tex_uv, const float2 dxdy, const float4 quad_vector)
  9448. {
  9449. return tex2Dblur8x8shared(tex, tex_uv, dxdy, quad_vector, blur8_std_dev);
  9450. }
  9451. inline float3 tex2Dblur6x6shared(const sampler2D tex,
  9452. const float4 tex_uv, const float2 dxdy, const float4 quad_vector)
  9453. {
  9454. return tex2Dblur6x6shared(tex, tex_uv, dxdy, quad_vector, blur6_std_dev);
  9455. }
  9456. #endif // BLUR_FUNCTIONS_H
  9457. //////////////////////////// END BLUR-FUNCTIONS ///////////////////////////
  9458. /////////////////////////////// BLOOM CONSTANTS //////////////////////////////
  9459. // Compute constants with manual inlines of the functions below:
  9460. static const float bloom_diff_thresh = 1.0/256.0;
  9461. /////////////////////////////////// HELPERS //////////////////////////////////
  9462. inline float get_min_sigma_to_blur_triad(const float triad_size,
  9463. const float thresh)
  9464. {
  9465. // Requires: 1.) triad_size is the final phosphor triad size in pixels
  9466. // 2.) thresh is the max desired pixel difference in the
  9467. // blurred triad (e.g. 1.0/256.0).
  9468. // Returns: Return the minimum sigma that will fully blur a phosphor
  9469. // triad on the screen to an even color, within thresh.
  9470. // This closed-form function was found by curve-fitting data.
  9471. // Estimate: max error = ~0.086036, mean sq. error = ~0.0013387:
  9472. return -0.05168 + 0.6113*triad_size -
  9473. 1.122*triad_size*sqrt(0.000416 + thresh);
  9474. // Estimate: max error = ~0.16486, mean sq. error = ~0.0041041:
  9475. //return 0.5985*triad_size - triad_size*sqrt(thresh)
  9476. }
  9477. inline float get_absolute_scale_blur_sigma(const float thresh)
  9478. {
  9479. // Requires: 1.) min_expected_triads must be a global float. The number
  9480. // of horizontal phosphor triads in the final image must be
  9481. // >= min_allowed_viewport_triads.x for realistic results.
  9482. // 2.) bloom_approx_scale_x must be a global float equal to the
  9483. // absolute horizontal scale of BLOOM_APPROX.
  9484. // 3.) bloom_approx_scale_x/min_allowed_viewport_triads.x
  9485. // should be <= 1.1658025090 to keep the final result <
  9486. // 0.62666015625 (the largest sigma ensuring the largest
  9487. // unused texel weight stays < 1.0/256.0 for a 3x3 blur).
  9488. // 4.) thresh is the max desired pixel difference in the
  9489. // blurred triad (e.g. 1.0/256.0).
  9490. // Returns: Return the minimum Gaussian sigma that will blur the pass
  9491. // output as much as it would have taken to blur away
  9492. // bloom_approx_scale_x horizontal phosphor triads.
  9493. // Description:
  9494. // BLOOM_APPROX should look like a downscaled phosphor blur. Ideally, we'd
  9495. // use the same blur sigma as the actual phosphor bloom and scale it down
  9496. // to the current resolution with (bloom_approx_scale_x/viewport_size_x), but
  9497. // we don't know the viewport size in this pass. Instead, we'll blur as
  9498. // much as it would take to blur away min_allowed_viewport_triads.x. This
  9499. // will blur "more than necessary" if the user actually uses more triads,
  9500. // but that's not terrible either, because blurring a constant fraction of
  9501. // the viewport may better resemble a true optical bloom anyway (since the
  9502. // viewport will generally be about the same fraction of each player's
  9503. // field of view, regardless of screen size and resolution).
  9504. // Assume an extremely large viewport size for asymptotic results.
  9505. return bloom_approx_scale_x/max_viewport_size_x *
  9506. get_min_sigma_to_blur_triad(
  9507. max_viewport_size_x/min_allowed_viewport_triads.x, thresh);
  9508. }
  9509. inline float get_center_weight(const float sigma)
  9510. {
  9511. // Given a Gaussian blur sigma, get the blur weight for the center texel.
  9512. #ifdef RUNTIME_PHOSPHOR_BLOOM_SIGMA
  9513. return get_fast_gaussian_weight_sum_inv(sigma);
  9514. #else
  9515. const float denom_inv = 0.5/(sigma*sigma);
  9516. const float w0 = 1.0;
  9517. const float w1 = exp(-1.0 * denom_inv);
  9518. const float w2 = exp(-4.0 * denom_inv);
  9519. const float w3 = exp(-9.0 * denom_inv);
  9520. const float w4 = exp(-16.0 * denom_inv);
  9521. const float w5 = exp(-25.0 * denom_inv);
  9522. const float w6 = exp(-36.0 * denom_inv);
  9523. const float w7 = exp(-49.0 * denom_inv);
  9524. const float w8 = exp(-64.0 * denom_inv);
  9525. const float w9 = exp(-81.0 * denom_inv);
  9526. const float w10 = exp(-100.0 * denom_inv);
  9527. const float w11 = exp(-121.0 * denom_inv);
  9528. const float w12 = exp(-144.0 * denom_inv);
  9529. const float w13 = exp(-169.0 * denom_inv);
  9530. const float w14 = exp(-196.0 * denom_inv);
  9531. const float w15 = exp(-225.0 * denom_inv);
  9532. const float w16 = exp(-256.0 * denom_inv);
  9533. const float w17 = exp(-289.0 * denom_inv);
  9534. const float w18 = exp(-324.0 * denom_inv);
  9535. const float w19 = exp(-361.0 * denom_inv);
  9536. const float w20 = exp(-400.0 * denom_inv);
  9537. const float w21 = exp(-441.0 * denom_inv);
  9538. // Note: If the implementation uses a smaller blur than the max allowed,
  9539. // the worst case scenario is that the center weight will be overestimated,
  9540. // so we'll put a bit more energy into the brightpass...no huge deal.
  9541. // Then again, if the implementation uses a larger blur than the max
  9542. // "allowed" because of dynamic branching, the center weight could be
  9543. // underestimated, which is more of a problem...consider always using
  9544. #ifdef PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_12_PIXELS
  9545. // 43x blur:
  9546. const float weight_sum_inv = 1.0 /
  9547. (w0 + 2.0 * (w1 + w2 + w3 + w4 + w5 + w6 + w7 + w8 + w9 + w10 +
  9548. w11 + w12 + w13 + w14 + w15 + w16 + w17 + w18 + w19 + w20 + w21));
  9549. #else
  9550. #ifdef PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_9_PIXELS
  9551. // 31x blur:
  9552. const float weight_sum_inv = 1.0 /
  9553. (w0 + 2.0 * (w1 + w2 + w3 + w4 + w5 + w6 + w7 +
  9554. w8 + w9 + w10 + w11 + w12 + w13 + w14 + w15));
  9555. #else
  9556. #ifdef PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_6_PIXELS
  9557. // 25x blur:
  9558. const float weight_sum_inv = 1.0 / (w0 + 2.0 * (
  9559. w1 + w2 + w3 + w4 + w5 + w6 + w7 + w8 + w9 + w10 + w11 + w12));
  9560. #else
  9561. #ifdef PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_3_PIXELS
  9562. // 17x blur:
  9563. const float weight_sum_inv = 1.0 / (w0 + 2.0 * (
  9564. w1 + w2 + w3 + w4 + w5 + w6 + w7 + w8));
  9565. #else
  9566. // 9x blur:
  9567. const float weight_sum_inv = 1.0 / (w0 + 2.0 * (w1 + w2 + w3 + w4));
  9568. #endif // PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_3_PIXELS
  9569. #endif // PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_6_PIXELS
  9570. #endif // PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_9_PIXELS
  9571. #endif // PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_12_PIXELS
  9572. const float center_weight = weight_sum_inv * weight_sum_inv;
  9573. return center_weight;
  9574. #endif
  9575. }
  9576. inline float3 tex2DblurNfast(const sampler2D texture, const float2 tex_uv,
  9577. const float2 dxdy, const float sigma)
  9578. {
  9579. // If sigma is static, we can safely branch and use the smallest blur
  9580. // that's big enough. Ignore #define hints, because we'll only use a
  9581. // large blur if we actually need it, and the branches cost nothing.
  9582. #ifndef RUNTIME_PHOSPHOR_BLOOM_SIGMA
  9583. #define PHOSPHOR_BLOOM_BRANCH_FOR_BLUR_SIZE
  9584. #else
  9585. // It's still worth branching if the profile supports dynamic branches:
  9586. // It's much faster than using a hugely excessive blur, but each branch
  9587. // eats ~1% FPS.
  9588. #ifdef DRIVERS_ALLOW_DYNAMIC_BRANCHES
  9589. #define PHOSPHOR_BLOOM_BRANCH_FOR_BLUR_SIZE
  9590. #endif
  9591. #endif
  9592. // Failed optimization notes:
  9593. // I originally created a same-size mipmapped 5-tap separable blur10 that
  9594. // could handle any sigma by reaching into lower mip levels. It was
  9595. // as fast as blur25fast for runtime sigmas and a tad faster than
  9596. // blur31fast for static sigmas, but mipmapping two viewport-size passes
  9597. // ate 10% of FPS across all codepaths, so it wasn't worth it.
  9598. #ifdef PHOSPHOR_BLOOM_BRANCH_FOR_BLUR_SIZE
  9599. if(sigma <= blur9_std_dev)
  9600. {
  9601. return tex2Dblur9fast(texture, tex_uv, dxdy, sigma);
  9602. }
  9603. else if(sigma <= blur17_std_dev)
  9604. {
  9605. return tex2Dblur17fast(texture, tex_uv, dxdy, sigma);
  9606. }
  9607. else if(sigma <= blur25_std_dev)
  9608. {
  9609. return tex2Dblur25fast(texture, tex_uv, dxdy, sigma);
  9610. }
  9611. else if(sigma <= blur31_std_dev)
  9612. {
  9613. return tex2Dblur31fast(texture, tex_uv, dxdy, sigma);
  9614. }
  9615. else
  9616. {
  9617. return tex2Dblur43fast(texture, tex_uv, dxdy, sigma);
  9618. }
  9619. #else
  9620. // If we can't afford to branch, we can only guess at what blur
  9621. // size we need. Therefore, use the largest blur allowed.
  9622. #ifdef PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_12_PIXELS
  9623. return tex2Dblur43fast(texture, tex_uv, dxdy, sigma);
  9624. #else
  9625. #ifdef PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_9_PIXELS
  9626. return tex2Dblur31fast(texture, tex_uv, dxdy, sigma);
  9627. #else
  9628. #ifdef PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_6_PIXELS
  9629. return tex2Dblur25fast(texture, tex_uv, dxdy, sigma);
  9630. #else
  9631. #ifdef PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_3_PIXELS
  9632. return tex2Dblur17fast(texture, tex_uv, dxdy, sigma);
  9633. #else
  9634. return tex2Dblur9fast(texture, tex_uv, dxdy, sigma);
  9635. #endif // PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_3_PIXELS
  9636. #endif // PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_6_PIXELS
  9637. #endif // PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_9_PIXELS
  9638. #endif // PHOSPHOR_BLOOM_TRIADS_LARGER_THAN_12_PIXELS
  9639. #endif // PHOSPHOR_BLOOM_BRANCH_FOR_BLUR_SIZE
  9640. }
  9641. inline float get_bloom_approx_sigma(const float output_size_x_runtime,
  9642. const float estimated_viewport_size_x)
  9643. {
  9644. // Requires: 1.) output_size_x_runtime == BLOOM_APPROX.output_size.x.
  9645. // This is included for dynamic codepaths just in case the
  9646. // following two globals are incorrect:
  9647. // 2.) bloom_approx_size_x_for_skip should == the same
  9648. // if PHOSPHOR_BLOOM_FAKE is #defined
  9649. // 3.) bloom_approx_size_x should == the same otherwise
  9650. // Returns: For gaussian4x4, return a dynamic small bloom sigma that's
  9651. // as close to optimal as possible given available information.
  9652. // For blur3x3, return the a static small bloom sigma that
  9653. // works well for typical cases. Otherwise, we're using simple
  9654. // bilinear filtering, so use static calculations.
  9655. // Assume the default static value. This is a compromise that ensures
  9656. // typical triads are blurred, even if unusually large ones aren't.
  9657. static const float mask_num_triads_static =
  9658. max(min_allowed_viewport_triads.x, mask_num_triads_desired_static);
  9659. const float mask_num_triads_from_size =
  9660. estimated_viewport_size_x/mask_triad_size_desired;
  9661. const float mask_num_triads_runtime = max(min_allowed_viewport_triads.x,
  9662. lerp(mask_num_triads_from_size, mask_num_triads_desired,
  9663. mask_specify_num_triads));
  9664. // Assume an extremely large viewport size for asymptotic results:
  9665. static const float max_viewport_size_x = 1080.0*1024.0*(4.0/3.0);
  9666. if(bloom_approx_filter > 1.5) // 4x4 true Gaussian resize
  9667. {
  9668. // Use the runtime num triads and output size:
  9669. const float asymptotic_triad_size =
  9670. max_viewport_size_x/mask_num_triads_runtime;
  9671. const float asymptotic_sigma = get_min_sigma_to_blur_triad(
  9672. asymptotic_triad_size, bloom_diff_thresh);
  9673. const float bloom_approx_sigma =
  9674. asymptotic_sigma * output_size_x_runtime/max_viewport_size_x;
  9675. // The BLOOM_APPROX input has to be ORIG_LINEARIZED to avoid moire, but
  9676. // account for the Gaussian scanline sigma from the last pass too.
  9677. // The bloom will be too wide horizontally but tall enough vertically.
  9678. return length(float2(bloom_approx_sigma, beam_max_sigma));
  9679. }
  9680. else // 3x3 blur resize (the bilinear resize doesn't need a sigma)
  9681. {
  9682. // We're either using blur3x3 or bilinear filtering. The biggest
  9683. // reason to choose blur3x3 is to avoid dynamic weights, so use a
  9684. // static calculation.
  9685. #ifdef PHOSPHOR_BLOOM_FAKE
  9686. static const float output_size_x_static =
  9687. bloom_approx_size_x_for_fake;
  9688. #else
  9689. static const float output_size_x_static = bloom_approx_size_x;
  9690. #endif
  9691. static const float asymptotic_triad_size =
  9692. max_viewport_size_x/mask_num_triads_static;
  9693. const float asymptotic_sigma = get_min_sigma_to_blur_triad(
  9694. asymptotic_triad_size, bloom_diff_thresh);
  9695. const float bloom_approx_sigma =
  9696. asymptotic_sigma * output_size_x_static/max_viewport_size_x;
  9697. // The BLOOM_APPROX input has to be ORIG_LINEARIZED to avoid moire, but
  9698. // try accounting for the Gaussian scanline sigma from the last pass
  9699. // too; use the static default value:
  9700. return length(float2(bloom_approx_sigma, beam_max_sigma_static));
  9701. }
  9702. }
  9703. inline float get_final_bloom_sigma(const float bloom_sigma_runtime)
  9704. {
  9705. // Requires: 1.) bloom_sigma_runtime is a precalculated sigma that's
  9706. // optimal for the [known] triad size.
  9707. // 2.) Call this from a fragment shader (not a vertex shader),
  9708. // or blurring with static sigmas won't be constant-folded.
  9709. // Returns: Return the optimistic static sigma if the triad size is
  9710. // known at compile time. Otherwise return the optimal runtime
  9711. // sigma (10% slower) or an implementation-specific compromise
  9712. // between an optimistic or pessimistic static sigma.
  9713. // Notes: Call this from the fragment shader, NOT the vertex shader,
  9714. // so static sigmas can be constant-folded!
  9715. const float bloom_sigma_optimistic = get_min_sigma_to_blur_triad(
  9716. mask_triad_size_desired_static, bloom_diff_thresh);
  9717. #ifdef RUNTIME_PHOSPHOR_BLOOM_SIGMA
  9718. return bloom_sigma_runtime;
  9719. #else
  9720. // Overblurring looks as bad as underblurring, so assume average-size
  9721. // triads, not worst-case huge triads:
  9722. return bloom_sigma_optimistic;
  9723. #endif
  9724. }
  9725. #endif // BLOOM_FUNCTIONS_H
  9726. //////////////////////////// END BLOOM-FUNCTIONS ///////////////////////////
  9727. void main() {
  9728. // This pass: Sample (misconverged?) scanlines to the final horizontal
  9729. // resolution, apply halation (bouncing electrons), and apply the phosphor
  9730. // mask. Fake a bloom if requested. Unless we fake a bloom, the output
  9731. // will be dim from the scanline auto-dim, mask dimming, and low gamma.
  9732. // Horizontally sample the current row (a vertically interpolated scanline)
  9733. // and account for horizontal convergence offsets, given in units of texels.
  9734. const float3 scanline_color_dim = sample_rgb_scanline_horizontal(
  9735. VERTICAL_SCANLINEStexture, scanline_tex_uv,
  9736. VERTICAL_SCANLINEStexture_size, scanline_texture_size_inv);
  9737. const float auto_dim_factor = levels_autodim_temp;
  9738. // Sample the phosphor mask:
  9739. const float2 tile_uv_wrap = video_uv * mask_tiles_per_screen;
  9740. const float2 mask_tex_uv = convert_phosphor_tile_uv_wrap_to_tex_uv(
  9741. tile_uv_wrap, mask_tile_start_uv_and_size);
  9742. float3 phosphor_mask_sample;
  9743. #ifdef PHOSPHOR_MASK_MANUALLY_RESIZE
  9744. const bool sample_orig_luts = get_mask_sample_mode() > 0.5;
  9745. #else
  9746. static const bool sample_orig_luts = true;
  9747. #endif
  9748. if(sample_orig_luts)
  9749. {
  9750. // If mask_type is static, this branch will be resolved statically.
  9751. if(mask_type < 0.5)
  9752. {
  9753. phosphor_mask_sample = tex2D_linearize(
  9754. mask_grille_texture_large, mask_tex_uv).rgb;
  9755. }
  9756. else if(mask_type < 1.5)
  9757. {
  9758. phosphor_mask_sample = tex2D_linearize(
  9759. mask_slot_texture_large, mask_tex_uv).rgb;
  9760. }
  9761. else
  9762. {
  9763. phosphor_mask_sample = tex2D_linearize(
  9764. mask_shadow_texture_large, mask_tex_uv).rgb;
  9765. }
  9766. }
  9767. else
  9768. {
  9769. // Sample the resized mask, and avoid tiling artifacts:
  9770. phosphor_mask_sample = tex2Dtiled_mask_linearize(
  9771. MASK_RESIZEtexture, mask_tex_uv).rgb;
  9772. }
  9773. // Sample the halation texture (auto-dim to match the scanlines), and
  9774. // account for both horizontal and vertical convergence offsets, given
  9775. // in units of texels horizontally and same-field scanlines vertically:
  9776. const float3 halation_color = tex2D_linearize(
  9777. HALATION_BLURtexture, halation_tex_uv).rgb;
  9778. // Apply halation: Halation models electrons flying around under the glass
  9779. // and hitting the wrong phosphors (of any color). It desaturates, so
  9780. // average the halation electrons to a scalar. Reduce the local scanline
  9781. // intensity accordingly to conserve energy.
  9782. const float3 halation_intensity_dim =
  9783. float3(dot(halation_color, float3(auto_dim_factor/3.0)));
  9784. const float3 electron_intensity_dim = lerp(scanline_color_dim,
  9785. halation_intensity_dim, halation_weight);
  9786. // Apply the phosphor mask:
  9787. const float3 phosphor_emission_dim = electron_intensity_dim *
  9788. phosphor_mask_sample;
  9789. #ifdef PHOSPHOR_BLOOM_FAKE
  9790. // The BLOOM_APPROX pass approximates a blurred version of a masked
  9791. // and scanlined image. It's usually used to compute the brightpass,
  9792. // but we can also use it to fake the bloom stage entirely. Caveats:
  9793. // 1.) A fake bloom is conceptually different, since we're mixing in a
  9794. // fully blurred low-res image, and the biggest implication are:
  9795. // 2.) If mask_amplify is incorrect, results deteriorate more quickly.
  9796. // 3.) The inaccurate blurring hurts quality in high-contrast areas.
  9797. // 4.) The bloom_underestimate_levels parameter seems less sensitive.
  9798. // Reverse the auto-dimming and amplify to compensate for mask dimming:
  9799. #define PHOSPHOR_BLOOM_FAKE_WITH_SIMPLE_BLEND
  9800. #ifdef PHOSPHOR_BLOOM_FAKE_WITH_SIMPLE_BLEND
  9801. static const float blur_contrast = 1.05;
  9802. #else
  9803. static const float blur_contrast = 1.0;
  9804. #endif
  9805. const float mask_amplify = get_mask_amplify();
  9806. const float undim_factor = 1.0/auto_dim_factor;
  9807. const float3 phosphor_emission =
  9808. phosphor_emission_dim * undim_factor * mask_amplify;
  9809. // Get a phosphor blur estimate, accounting for convergence offsets:
  9810. const float3 electron_intensity = electron_intensity_dim * undim_factor;
  9811. const float3 phosphor_blur_approx_soft = tex2D_linearize(
  9812. BLOOM_APPROXtexture, blur3x3_tex_uv).rgb;
  9813. const float3 phosphor_blur_approx = lerp(phosphor_blur_approx_soft,
  9814. electron_intensity, 0.1) * blur_contrast;
  9815. // We could blend between phosphor_emission and phosphor_blur_approx,
  9816. // solving for the minimum blend_ratio that avoids clipping past 1.0:
  9817. // 1.0 >= total_intensity
  9818. // 1.0 >= phosphor_emission * (1.0 - blend_ratio) +
  9819. // phosphor_blur_approx * blend_ratio
  9820. // blend_ratio = (phosphor_emission - 1.0)/
  9821. // (phosphor_emission - phosphor_blur_approx);
  9822. // However, this blurs far more than necessary, because it aims for
  9823. // full brightness, not minimal blurring. To fix it, base blend_ratio
  9824. // on a max area intensity only so it varies more smoothly:
  9825. const float3 phosphor_blur_underestimate =
  9826. phosphor_blur_approx * bloom_underestimate_levels;
  9827. const float3 area_max_underestimate =
  9828. phosphor_blur_underestimate * mask_amplify;
  9829. #ifdef PHOSPHOR_BLOOM_FAKE_WITH_SIMPLE_BLEND
  9830. const float3 blend_ratio_temp =
  9831. (area_max_underestimate - float3(1.0, 1.0, 1.0)) /
  9832. (area_max_underestimate - phosphor_blur_underestimate);
  9833. #else
  9834. // Try doing it like an area-based brightpass. This is nearly
  9835. // identical, but it's worth toying with the code in case I ever
  9836. // find a way to make it look more like a real bloom. (I've had
  9837. // some promising textures from combining an area-based blend ratio
  9838. // for the phosphor blur and a more brightpass-like blend-ratio for
  9839. // the phosphor emission, but I haven't found a way to make the
  9840. // brightness correct across the whole color range, especially with
  9841. // different bloom_underestimate_levels values.)
  9842. const float desired_triad_size = lerp(mask_triad_size_desired,
  9843. output_size.x/mask_num_triads_desired,
  9844. mask_specify_num_triads);
  9845. const float bloom_sigma = get_min_sigma_to_blur_triad(
  9846. desired_triad_size, bloom_diff_thresh);
  9847. const float center_weight = get_center_weight(bloom_sigma);
  9848. const float3 max_area_contribution_approx =
  9849. max(float3(0.0, 0.0, 0.0), phosphor_blur_approx -
  9850. center_weight * phosphor_emission);
  9851. const float3 area_contrib_underestimate =
  9852. bloom_underestimate_levels * max_area_contribution_approx;
  9853. const float3 blend_ratio_temp =
  9854. ((float3(1.0, 1.0, 1.0) - area_contrib_underestimate) /
  9855. area_max_underestimate - float3(1.0, 1.0, 1.0)) / (center_weight - 1.0);
  9856. #endif
  9857. // Clamp blend_ratio in case it's out-of-range, but be SUPER careful:
  9858. // min/max/clamp are BIZARRELY broken with lerp (optimization bug?),
  9859. // and this redundant sequence avoids bugs, at least on nVidia cards:
  9860. const float3 blend_ratio_clamped = max(clamp(blend_ratio_temp, 0.0, 1.0), 0.0);
  9861. const float3 blend_ratio = lerp(blend_ratio_clamped, float3(1.0,1.0,1.0), bloom_excess);
  9862. // Blend the blurred and unblurred images:
  9863. const float3 phosphor_emission_unclipped =
  9864. lerp(phosphor_emission, phosphor_blur_approx, blend_ratio);
  9865. // Simulate refractive diffusion by reusing the halation sample.
  9866. const float3 pixel_color = lerp(phosphor_emission_unclipped,
  9867. halation_color, diffusion_weight);
  9868. #else
  9869. const float3 pixel_color = phosphor_emission_dim;
  9870. #endif
  9871. // Encode if necessary, and output.
  9872. FragColor = encode_output(float4(pixel_color, 1.0));
  9873. }