milkdropfs.cpp 181 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801
  1. /*
  2. LICENSE
  3. -------
  4. Copyright 2005-2013 Nullsoft, Inc.
  5. All rights reserved.
  6. Redistribution and use in source and binary forms, with or without modification,
  7. are permitted provided that the following conditions are met:
  8. * Redistributions of source code must retain the above copyright notice,
  9. this list of conditions and the following disclaimer.
  10. * Redistributions in binary form must reproduce the above copyright notice,
  11. this list of conditions and the following disclaimer in the documentation
  12. and/or other materials provided with the distribution.
  13. * Neither the name of Nullsoft nor the names of its contributors may be used to
  14. endorse or promote products derived from this software without specific prior written permission.
  15. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
  16. IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  17. FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  18. CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  19. DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  20. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
  21. IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  22. OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  23. */
  24. #include "api__vis_milk2.h"
  25. #include "plugin.h"
  26. #include "resource.h"
  27. #include "support.h"
  28. //#include "evallib\eval.h" // for math. expr. eval - thanks Francis! (in SourceOffSite, it's the 'vis_avs\evallib' project.)
  29. //#include "evallib\compiler.h"
  30. #include "ns-eel2/ns-eel.h"
  31. #include "utility.h"
  32. #include <assert.h>
  33. #include <math.h>
  34. #define D3DCOLOR_RGBA_01(r,g,b,a) D3DCOLOR_RGBA(((int)(r*255)),((int)(g*255)),((int)(b*255)),((int)(a*255)))
  35. #define FRAND ((warand() % 7381)/7380.0f)
  36. #define VERT_CLIP 0.75f // warning: top/bottom can get clipped if you go < 0.65!
  37. int g_title_font_sizes[] =
  38. {
  39. // NOTE: DO NOT EXCEED 64 FONTS HERE.
  40. 6, 8, 10, 12, 14, 16,
  41. 20, 26, 32, 38, 44, 50, 56,
  42. 64, 72, 80, 88, 96, 104, 112, 120, 128, 136, 144,
  43. 160, 192, 224, 256, 288, 320, 352, 384, 416, 448,
  44. 480, 512 /**/
  45. };
  46. //#define COMPILE_MULTIMON_STUBS 1
  47. //#include <multimon.h>
  48. // This function evaluates whether the floating-point
  49. // control Word is set to single precision/round to nearest/
  50. // exceptions disabled. If not, the
  51. // function changes the control Word to set them and returns
  52. // TRUE, putting the old control Word value in the passback
  53. // location pointed to by pwOldCW.
  54. static void MungeFPCW( WORD *pwOldCW )
  55. {
  56. #if 0
  57. BOOL ret = FALSE;
  58. WORD wTemp, wSave;
  59. __asm fstcw wSave
  60. if (wSave & 0x300 || // Not single mode
  61. 0x3f != (wSave & 0x3f) || // Exceptions enabled
  62. wSave & 0xC00) // Not round to nearest mode
  63. {
  64. __asm
  65. {
  66. mov ax, wSave
  67. and ax, not 300h ;; single mode
  68. or ax, 3fh ;; disable all exceptions
  69. and ax, not 0xC00 ;; round to nearest mode
  70. mov wTemp, ax
  71. fldcw wTemp
  72. }
  73. ret = TRUE;
  74. }
  75. if (pwOldCW) *pwOldCW = wSave;
  76. // return ret;
  77. #else
  78. _controlfp(_PC_24, _MCW_PC); // single precision
  79. _controlfp(_RC_NEAR, _MCW_RC); // round to nearest mode
  80. _controlfp(_EM_ZERODIVIDE, _EM_ZERODIVIDE); // disable divide-by-zero
  81. #endif
  82. }
  83. void RestoreFPCW(WORD wSave)
  84. {
  85. __asm fldcw wSave
  86. }
  87. int GetNumToSpawn(float fTime, float fDeltaT, float fRate, float fRegularity, int iNumSpawnedSoFar)
  88. {
  89. // PARAMETERS
  90. // ------------
  91. // fTime: sum of all fDeltaT's so far (excluding this one)
  92. // fDeltaT: time window for this frame
  93. // fRate: avg. rate (spawns per second) of generation
  94. // fRegularity: regularity of generation
  95. // 0.0: totally chaotic
  96. // 0.2: getting chaotic / very jittered
  97. // 0.4: nicely jittered
  98. // 0.6: slightly jittered
  99. // 0.8: almost perfectly regular
  100. // 1.0: perfectly regular
  101. // iNumSpawnedSoFar: the total number of spawnings so far
  102. //
  103. // RETURN VALUE
  104. // ------------
  105. // The number to spawn for this frame (add this to your net count!).
  106. //
  107. // COMMENTS
  108. // ------------
  109. // The spawn values returned will, over time, match
  110. // (within 1%) the theoretical totals expected based on the
  111. // amount of time passed and the average generation rate.
  112. //
  113. // UNRESOLVED ISSUES
  114. // -----------------
  115. // actual results of mixed gen. (0 < reg < 1) are about 1% too low
  116. // in the long run (vs. analytical expectations). Decided not
  117. // to bother fixing it since it's only 1% (and VERY consistent).
  118. float fNumToSpawnReg;
  119. float fNumToSpawnIrreg;
  120. float fNumToSpawn;
  121. // compute # spawned based on regular generation
  122. fNumToSpawnReg = ((fTime + fDeltaT) * fRate) - iNumSpawnedSoFar;
  123. // compute # spawned based on irregular (random) generation
  124. if (fDeltaT <= 1.0f / fRate)
  125. {
  126. // case 1: avg. less than 1 spawn per frame
  127. if ((warand() % 16384)/16384.0f < fDeltaT * fRate)
  128. fNumToSpawnIrreg = 1.0f;
  129. else
  130. fNumToSpawnIrreg = 0.0f;
  131. }
  132. else
  133. {
  134. // case 2: avg. more than 1 spawn per frame
  135. fNumToSpawnIrreg = fDeltaT * fRate;
  136. fNumToSpawnIrreg *= 2.0f*(warand() % 16384)/16384.0f;
  137. }
  138. // get linear combo. of regular & irregular
  139. fNumToSpawn = fNumToSpawnReg*fRegularity + fNumToSpawnIrreg*(1.0f - fRegularity);
  140. // round to nearest integer for result
  141. return (int)(fNumToSpawn + 0.49f);
  142. }
  143. bool CPlugin::OnResizeTextWindow()
  144. {
  145. /*
  146. if (!m_hTextWnd)
  147. return false;
  148. RECT rect;
  149. GetClientRect(m_hTextWnd, &rect);
  150. if (rect.right - rect.left != m_nTextWndWidth ||
  151. rect.bottom - rect.top != m_nTextWndHeight)
  152. {
  153. m_nTextWndWidth = rect.right - rect.left;
  154. m_nTextWndHeight = rect.bottom - rect.top;
  155. // first, resize fonts if necessary
  156. //if (!InitFont())
  157. //return false;
  158. // then resize the memory bitmap used for double buffering
  159. if (m_memDC)
  160. {
  161. SelectObject(m_memDC, m_oldBM); // delete our doublebuffer
  162. DeleteObject(m_memDC);
  163. DeleteObject(m_memBM);
  164. m_memDC = NULL;
  165. m_memBM = NULL;
  166. m_oldBM = NULL;
  167. }
  168. HDC hdc = GetDC(m_hTextWnd);
  169. if (!hdc) return false;
  170. m_memDC = CreateCompatibleDC(hdc);
  171. m_memBM = CreateCompatibleBitmap(hdc, rect.right - rect.left, rect.bottom - rect.top);
  172. m_oldBM = (HBITMAP)SelectObject(m_memDC,m_memBM);
  173. ReleaseDC(m_hTextWnd, hdc);
  174. // save new window pos
  175. WriteRealtimeConfig();
  176. }*/
  177. return true;
  178. }
  179. void CPlugin::ClearGraphicsWindow()
  180. {
  181. // clear the window contents, to avoid a 1-pixel-thick border of noise that sometimes sticks around
  182. /*
  183. RECT rect;
  184. GetClientRect(GetPluginWindow(), &rect);
  185. HDC hdc = GetDC(GetPluginWindow());
  186. FillRect(hdc, &rect, m_hBlackBrush);
  187. ReleaseDC(GetPluginWindow(), hdc);
  188. */
  189. }
  190. /*
  191. bool CPlugin::OnResizeGraphicsWindow()
  192. {
  193. // NO LONGER NEEDED, SINCE PLUGIN SHELL CREATES A NEW DIRECTX
  194. // OBJECT WHENEVER WINDOW IS RESIZED.
  195. }
  196. */
  197. bool CPlugin::RenderStringToTitleTexture() // m_szSongMessage
  198. {
  199. if (!m_lpDDSTitle) // this *can* be NULL, if not much video mem!
  200. return false;
  201. if (m_supertext.szTextW[0]==0)
  202. return false;
  203. LPDIRECT3DDEVICE9 lpDevice = GetDevice();
  204. if (!lpDevice)
  205. return false;
  206. wchar_t szTextToDraw[512];
  207. swprintf(szTextToDraw, L" %s ", m_supertext.szTextW); //add a space @ end for italicized fonts; and at start, too, because it's centered!
  208. // Remember the original backbuffer and zbuffer
  209. LPDIRECT3DSURFACE9 pBackBuffer=NULL;//, pZBuffer=NULL;
  210. lpDevice->GetRenderTarget( 0, &pBackBuffer );
  211. //lpDevice->GetDepthStencilSurface( &pZBuffer );
  212. // set render target to m_lpDDSTitle
  213. {
  214. lpDevice->SetTexture(0, NULL);
  215. IDirect3DSurface9* pNewTarget = NULL;
  216. if (m_lpDDSTitle->GetSurfaceLevel(0, &pNewTarget) != D3D_OK)
  217. {
  218. SafeRelease(pBackBuffer);
  219. //SafeRelease(pZBuffer);
  220. return false;
  221. }
  222. lpDevice->SetRenderTarget(0, pNewTarget);
  223. //lpDevice->SetDepthStencilSurface( NULL );
  224. pNewTarget->Release();
  225. lpDevice->SetTexture(0, NULL);
  226. }
  227. // clear the texture to black
  228. {
  229. lpDevice->SetVertexShader( NULL );
  230. lpDevice->SetFVF( WFVERTEX_FORMAT );
  231. lpDevice->SetTexture(0, NULL);
  232. lpDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
  233. // set up a quad
  234. WFVERTEX verts[4];
  235. for (int i=0; i<4; i++)
  236. {
  237. verts[i].x = (i%2==0) ? -1.f : 1.f;
  238. verts[i].y = (i/2==0) ? -1.f : 1.f;
  239. verts[i].z = 0;
  240. verts[i].Diffuse = 0xFF000000;
  241. }
  242. lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, verts, sizeof(WFVERTEX));
  243. }
  244. /*// 1. clip title if too many chars
  245. if (m_supertext.bIsSongTitle)
  246. {
  247. // truncate song title if too long; don't clip custom messages, though!
  248. int clip_chars = 32;
  249. int user_title_size = GetFontHeight(SONGTITLE_FONT);
  250. #define MIN_CHARS 8 // max clip_chars *for BIG FONTS*
  251. #define MAX_CHARS 64 // max clip chars *for tiny fonts*
  252. float t = (user_title_size-10)/(float)(128-10);
  253. t = min(1,max(0,t));
  254. clip_chars = (int)(MAX_CHARS - (MAX_CHARS-MIN_CHARS)*t);
  255. if ((int)strlen(szTextToDraw) > clip_chars+3)
  256. lstrcpy(&szTextToDraw[clip_chars], "...");
  257. }*/
  258. bool ret = true;
  259. // use 2 lines; must leave room for bottom of 'g' characters and such!
  260. RECT rect;
  261. rect.left = 0;
  262. rect.right = m_nTitleTexSizeX;
  263. rect.top = m_nTitleTexSizeY* 1/21; // otherwise, top of '%' could be cut off (1/21 seems safe)
  264. rect.bottom = m_nTitleTexSizeY*17/21; // otherwise, bottom of 'g' could be cut off (18/21 seems safe, but we want some leeway)
  265. if (!m_supertext.bIsSongTitle)
  266. {
  267. // custom msg -> pick font to use that will best fill the texture
  268. HFONT gdi_font = NULL;
  269. LPD3DXFONT d3dx_font = NULL;
  270. int lo = 0;
  271. int hi = sizeof(g_title_font_sizes)/sizeof(int) - 1;
  272. // limit the size of the font used:
  273. //int user_title_size = GetFontHeight(SONGTITLE_FONT);
  274. //while (g_title_font_sizes[hi] > user_title_size*2 && hi>4)
  275. // hi--;
  276. RECT temp;
  277. while (1)//(lo < hi-1)
  278. {
  279. int mid = (lo+hi)/2;
  280. // create new gdi font at 'mid' size:
  281. gdi_font = CreateFontW( g_title_font_sizes[mid], 0, 0, 0, m_supertext.bBold ? 900 : 400, m_supertext.bItal, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  282. m_fontinfo[SONGTITLE_FONT].bAntiAliased ? ANTIALIASED_QUALITY : DEFAULT_QUALITY,
  283. DEFAULT_PITCH, m_supertext.nFontFace );
  284. if (gdi_font)
  285. {
  286. // create new d3dx font at 'mid' size:
  287. if (pCreateFontW(
  288. lpDevice,
  289. g_title_font_sizes[mid],
  290. 0,
  291. m_supertext.bBold ? 900 : 400,
  292. 1,
  293. m_supertext.bItal,
  294. DEFAULT_CHARSET,
  295. OUT_DEFAULT_PRECIS,
  296. ANTIALIASED_QUALITY,//m_fontinfo[SONGTITLE_FONT].bAntiAliased ? ANTIALIASED_QUALITY : DEFAULT_QUALITY,
  297. DEFAULT_PITCH,
  298. m_supertext.nFontFace,
  299. &d3dx_font
  300. ) == D3D_OK)
  301. {
  302. if (lo == hi-1)
  303. break; // DONE; but the 'lo'-size font is ready for use!
  304. // compute size of text if drawn w/font of THIS size:
  305. temp = rect;
  306. int h = d3dx_font->DrawTextW(NULL, szTextToDraw, -1, &temp, DT_SINGLELINE | DT_CALCRECT /*| DT_NOPREFIX*/, 0xFFFFFFFF);
  307. // adjust & prepare to reiterate:
  308. if (temp.right >= rect.right || h > rect.bottom-rect.top)
  309. hi = mid;
  310. else
  311. lo = mid;
  312. SafeRelease(d3dx_font);
  313. }
  314. DeleteObject(gdi_font); gdi_font=NULL;
  315. }
  316. }
  317. if (gdi_font && d3dx_font)
  318. {
  319. // do actual drawing + set m_supertext.nFontSizeUsed; use 'lo' size
  320. int h = d3dx_font->DrawTextW(NULL, szTextToDraw, -1, &temp, DT_SINGLELINE | DT_CALCRECT /*| DT_NOPREFIX*/ | DT_CENTER, 0xFFFFFFFF);
  321. temp.left = 0;
  322. temp.right = m_nTitleTexSizeX; // now allow text to go all the way over, since we're actually drawing!
  323. temp.top = m_nTitleTexSizeY/2 - h/2;
  324. temp.bottom = m_nTitleTexSizeY/2 + h/2;
  325. m_supertext.nFontSizeUsed = d3dx_font->DrawTextW(NULL, szTextToDraw, -1, &temp, DT_SINGLELINE /*| DT_NOPREFIX*/ | DT_CENTER, 0xFFFFFFFF);
  326. ret = true;
  327. }
  328. else
  329. {
  330. ret = false;
  331. }
  332. // clean up font:
  333. SafeRelease(d3dx_font);
  334. if (gdi_font) DeleteObject(gdi_font); gdi_font=NULL;
  335. }
  336. else // song title
  337. {
  338. wchar_t* str = m_supertext.szTextW;
  339. // clip the text manually...
  340. // NOTE: DT_END_ELLIPSIS CAUSES NOTHING TO DRAW, IF YOU USE W/D3DX9!
  341. int h;
  342. int max_its = 6;
  343. int it = 0;
  344. while (it < max_its)
  345. {
  346. it++;
  347. if (!str[0])
  348. break;
  349. RECT temp = rect;
  350. h = m_d3dx_title_font_doublesize->DrawTextW(NULL, str, -1, &temp, DT_SINGLELINE | DT_CALCRECT /*| DT_NOPREFIX | DT_END_ELLIPSIS*/, 0xFFFFFFFF);
  351. if (temp.right-temp.left <= m_nTitleTexSizeX)
  352. break;
  353. // 11/01/2009 DO - disabled as it was causing to users 'random' titles against
  354. // what is expected so we now just work on the ellipse at the end approach which
  355. // manually clip the text... chop segments off the front
  356. /*wchar_t* p = wcsstr(str, L" - ");
  357. if (p)
  358. {
  359. str = p+3;
  360. continue;
  361. }*/
  362. // no more stuff to chop off the front; chop off the end w/ ...
  363. int len = wcslen(str);
  364. float fPercentToKeep = 0.91f * m_nTitleTexSizeX / (float)(temp.right-temp.left);
  365. if (len > 8)
  366. lstrcpyW( &str[ (int)(len*fPercentToKeep) ], L"...");
  367. break;
  368. }
  369. // now actually draw it
  370. RECT temp;
  371. temp.left = 0;
  372. temp.right = m_nTitleTexSizeX; // now allow text to go all the way over, since we're actually drawing!
  373. temp.top = m_nTitleTexSizeY/2 - h/2;
  374. temp.bottom = m_nTitleTexSizeY/2 + h/2;
  375. // NOTE: DT_END_ELLIPSIS CAUSES NOTHING TO DRAW, IF YOU USE W/D3DX9!
  376. m_supertext.nFontSizeUsed = m_d3dx_title_font_doublesize->DrawTextW(NULL, str, -1, &temp, DT_SINGLELINE /*| DT_NOPREFIX | DT_END_ELLIPSIS*/ | DT_CENTER , 0xFFFFFFFF);
  377. }
  378. // Change the rendertarget back to the original setup
  379. lpDevice->SetTexture(0, NULL);
  380. lpDevice->SetRenderTarget( 0, pBackBuffer );
  381. //lpDevice->SetDepthStencilSurface( pZBuffer );
  382. SafeRelease(pBackBuffer);
  383. //SafeRelease(pZBuffer);
  384. return ret;
  385. }
  386. void CPlugin::LoadPerFrameEvallibVars(CState* pState)
  387. {
  388. // load the 'var_pf_*' variables in this CState object with the correct values.
  389. // for vars that affect pixel motion, that means evaluating them at time==-1,
  390. // (i.e. no blending w/blendto value); the blending of the file dx/dy
  391. // will be done *after* execution of the per-vertex code.
  392. // for vars that do NOT affect pixel motion, evaluate them at the current time,
  393. // so that if they're blending, both states see the blended value.
  394. // 1. vars that affect pixel motion: (eval at time==-1)
  395. *pState->var_pf_zoom = (double)pState->m_fZoom.eval(-1);//GetTime());
  396. *pState->var_pf_zoomexp = (double)pState->m_fZoomExponent.eval(-1);//GetTime());
  397. *pState->var_pf_rot = (double)pState->m_fRot.eval(-1);//GetTime());
  398. *pState->var_pf_warp = (double)pState->m_fWarpAmount.eval(-1);//GetTime());
  399. *pState->var_pf_cx = (double)pState->m_fRotCX.eval(-1);//GetTime());
  400. *pState->var_pf_cy = (double)pState->m_fRotCY.eval(-1);//GetTime());
  401. *pState->var_pf_dx = (double)pState->m_fXPush.eval(-1);//GetTime());
  402. *pState->var_pf_dy = (double)pState->m_fYPush.eval(-1);//GetTime());
  403. *pState->var_pf_sx = (double)pState->m_fStretchX.eval(-1);//GetTime());
  404. *pState->var_pf_sy = (double)pState->m_fStretchY.eval(-1);//GetTime());
  405. // read-only:
  406. *pState->var_pf_time = (double)(GetTime() - m_fStartTime);
  407. *pState->var_pf_fps = (double)GetFps();
  408. *pState->var_pf_bass = (double)mysound.imm_rel[0];
  409. *pState->var_pf_mid = (double)mysound.imm_rel[1];
  410. *pState->var_pf_treb = (double)mysound.imm_rel[2];
  411. *pState->var_pf_bass_att = (double)mysound.avg_rel[0];
  412. *pState->var_pf_mid_att = (double)mysound.avg_rel[1];
  413. *pState->var_pf_treb_att = (double)mysound.avg_rel[2];
  414. *pState->var_pf_frame = (double)GetFrame();
  415. //*pState->var_pf_monitor = 0; -leave this as it was set in the per-frame INIT code!
  416. for (int vi=0; vi<NUM_Q_VAR; vi++)
  417. *pState->var_pf_q[vi] = pState->q_values_after_init_code[vi];//0.0f;
  418. *pState->var_pf_monitor = pState->monitor_after_init_code;
  419. *pState->var_pf_progress = (GetTime() - m_fPresetStartTime) / (m_fNextPresetTime - m_fPresetStartTime);
  420. // 2. vars that do NOT affect pixel motion: (eval at time==now)
  421. *pState->var_pf_decay = (double)pState->m_fDecay.eval(GetTime());
  422. *pState->var_pf_wave_a = (double)pState->m_fWaveAlpha.eval(GetTime());
  423. *pState->var_pf_wave_r = (double)pState->m_fWaveR.eval(GetTime());
  424. *pState->var_pf_wave_g = (double)pState->m_fWaveG.eval(GetTime());
  425. *pState->var_pf_wave_b = (double)pState->m_fWaveB.eval(GetTime());
  426. *pState->var_pf_wave_x = (double)pState->m_fWaveX.eval(GetTime());
  427. *pState->var_pf_wave_y = (double)pState->m_fWaveY.eval(GetTime());
  428. *pState->var_pf_wave_mystery= (double)pState->m_fWaveParam.eval(GetTime());
  429. *pState->var_pf_wave_mode = (double)pState->m_nWaveMode; //?!?! -why won't it work if set to pState->m_nWaveMode???
  430. *pState->var_pf_ob_size = (double)pState->m_fOuterBorderSize.eval(GetTime());
  431. *pState->var_pf_ob_r = (double)pState->m_fOuterBorderR.eval(GetTime());
  432. *pState->var_pf_ob_g = (double)pState->m_fOuterBorderG.eval(GetTime());
  433. *pState->var_pf_ob_b = (double)pState->m_fOuterBorderB.eval(GetTime());
  434. *pState->var_pf_ob_a = (double)pState->m_fOuterBorderA.eval(GetTime());
  435. *pState->var_pf_ib_size = (double)pState->m_fInnerBorderSize.eval(GetTime());
  436. *pState->var_pf_ib_r = (double)pState->m_fInnerBorderR.eval(GetTime());
  437. *pState->var_pf_ib_g = (double)pState->m_fInnerBorderG.eval(GetTime());
  438. *pState->var_pf_ib_b = (double)pState->m_fInnerBorderB.eval(GetTime());
  439. *pState->var_pf_ib_a = (double)pState->m_fInnerBorderA.eval(GetTime());
  440. *pState->var_pf_mv_x = (double)pState->m_fMvX.eval(GetTime());
  441. *pState->var_pf_mv_y = (double)pState->m_fMvY.eval(GetTime());
  442. *pState->var_pf_mv_dx = (double)pState->m_fMvDX.eval(GetTime());
  443. *pState->var_pf_mv_dy = (double)pState->m_fMvDY.eval(GetTime());
  444. *pState->var_pf_mv_l = (double)pState->m_fMvL.eval(GetTime());
  445. *pState->var_pf_mv_r = (double)pState->m_fMvR.eval(GetTime());
  446. *pState->var_pf_mv_g = (double)pState->m_fMvG.eval(GetTime());
  447. *pState->var_pf_mv_b = (double)pState->m_fMvB.eval(GetTime());
  448. *pState->var_pf_mv_a = (double)pState->m_fMvA.eval(GetTime());
  449. *pState->var_pf_echo_zoom = (double)pState->m_fVideoEchoZoom.eval(GetTime());
  450. *pState->var_pf_echo_alpha = (double)pState->m_fVideoEchoAlpha.eval(GetTime());
  451. *pState->var_pf_echo_orient = (double)pState->m_nVideoEchoOrientation;
  452. // new in v1.04:
  453. *pState->var_pf_wave_usedots = (double)pState->m_bWaveDots;
  454. *pState->var_pf_wave_thick = (double)pState->m_bWaveThick;
  455. *pState->var_pf_wave_additive = (double)pState->m_bAdditiveWaves;
  456. *pState->var_pf_wave_brighten = (double)pState->m_bMaximizeWaveColor;
  457. *pState->var_pf_darken_center = (double)pState->m_bDarkenCenter;
  458. *pState->var_pf_gamma = (double)pState->m_fGammaAdj.eval(GetTime());
  459. *pState->var_pf_wrap = (double)pState->m_bTexWrap;
  460. *pState->var_pf_invert = (double)pState->m_bInvert;
  461. *pState->var_pf_brighten = (double)pState->m_bBrighten;
  462. *pState->var_pf_darken = (double)pState->m_bDarken;
  463. *pState->var_pf_solarize = (double)pState->m_bSolarize;
  464. *pState->var_pf_meshx = (double)m_nGridX;
  465. *pState->var_pf_meshy = (double)m_nGridY;
  466. *pState->var_pf_pixelsx = (double)GetWidth();
  467. *pState->var_pf_pixelsy = (double)GetHeight();
  468. *pState->var_pf_aspectx = (double)m_fInvAspectX;
  469. *pState->var_pf_aspecty = (double)m_fInvAspectY;
  470. // new in v2.0:
  471. *pState->var_pf_blur1min = (double)pState->m_fBlur1Min.eval(GetTime());
  472. *pState->var_pf_blur2min = (double)pState->m_fBlur2Min.eval(GetTime());
  473. *pState->var_pf_blur3min = (double)pState->m_fBlur3Min.eval(GetTime());
  474. *pState->var_pf_blur1max = (double)pState->m_fBlur1Max.eval(GetTime());
  475. *pState->var_pf_blur2max = (double)pState->m_fBlur2Max.eval(GetTime());
  476. *pState->var_pf_blur3max = (double)pState->m_fBlur3Max.eval(GetTime());
  477. *pState->var_pf_blur1_edge_darken = (double)pState->m_fBlur1EdgeDarken.eval(GetTime());
  478. }
  479. void CPlugin::RunPerFrameEquations(int code)
  480. {
  481. // run per-frame calculations
  482. /*
  483. code is only valid when blending.
  484. OLDcomp ~ blend-from preset has a composite shader;
  485. NEWwarp ~ blend-to preset has a warp shader; etc.
  486. code OLDcomp NEWcomp OLDwarp NEWwarp
  487. 0
  488. 1 1
  489. 2 1
  490. 3 1 1
  491. 4 1
  492. 5 1 1
  493. 6 1 1
  494. 7 1 1 1
  495. 8 1
  496. 9 1 1
  497. 10 1 1
  498. 11 1 1 1
  499. 12 1 1
  500. 13 1 1 1
  501. 14 1 1 1
  502. 15 1 1 1 1
  503. */
  504. // when blending booleans (like darken, invert, etc) for pre-shader presets,
  505. // if blending to/from a pixel-shader preset, we can tune the snap point
  506. // (when it changes during the blend) for a less jumpy transition:
  507. m_fSnapPoint = 0.5f;
  508. if (m_pState->m_bBlending)
  509. {
  510. switch(code)
  511. {
  512. case 4:
  513. case 6:
  514. case 12:
  515. case 14:
  516. // old preset (only) had a comp shader
  517. m_fSnapPoint = -0.01f;
  518. break;
  519. case 1:
  520. case 3:
  521. case 9:
  522. case 11:
  523. // new preset (only) has a comp shader
  524. m_fSnapPoint = 1.01f;
  525. break;
  526. case 0:
  527. case 2:
  528. case 8:
  529. case 10:
  530. // neither old or new preset had a comp shader
  531. m_fSnapPoint = 0.5f;
  532. break;
  533. case 5:
  534. case 7:
  535. case 13:
  536. case 15:
  537. // both old and new presets use a comp shader - so it won't matter
  538. m_fSnapPoint = 0.5f;
  539. break;
  540. }
  541. }
  542. int num_reps = (m_pState->m_bBlending) ? 2 : 1;
  543. for (int rep=0; rep<num_reps; rep++)
  544. {
  545. CState *pState;
  546. if (rep==0)
  547. pState = m_pState;
  548. else
  549. pState = m_pOldState;
  550. // values that will affect the pixel motion (and will be automatically blended
  551. // LATER, when the results of 2 sets of these params creates 2 different U/V
  552. // meshes that get blended together.)
  553. LoadPerFrameEvallibVars(pState);
  554. // also do just a once-per-frame init for the *per-**VERTEX*** *READ-ONLY* variables
  555. // (the non-read-only ones will be reset/restored at the start of each vertex)
  556. *pState->var_pv_time = *pState->var_pf_time;
  557. *pState->var_pv_fps = *pState->var_pf_fps;
  558. *pState->var_pv_frame = *pState->var_pf_frame;
  559. *pState->var_pv_progress = *pState->var_pf_progress;
  560. *pState->var_pv_bass = *pState->var_pf_bass;
  561. *pState->var_pv_mid = *pState->var_pf_mid;
  562. *pState->var_pv_treb = *pState->var_pf_treb;
  563. *pState->var_pv_bass_att = *pState->var_pf_bass_att;
  564. *pState->var_pv_mid_att = *pState->var_pf_mid_att;
  565. *pState->var_pv_treb_att = *pState->var_pf_treb_att;
  566. *pState->var_pv_meshx = (double)m_nGridX;
  567. *pState->var_pv_meshy = (double)m_nGridY;
  568. *pState->var_pv_pixelsx = (double)GetWidth();
  569. *pState->var_pv_pixelsy = (double)GetHeight();
  570. *pState->var_pv_aspectx = (double)m_fInvAspectX;
  571. *pState->var_pv_aspecty = (double)m_fInvAspectY;
  572. //*pState->var_pv_monitor = *pState->var_pf_monitor;
  573. // execute once-per-frame expressions:
  574. #ifndef _NO_EXPR_
  575. if (pState->m_pf_codehandle)
  576. {
  577. if (pState->m_pf_codehandle)
  578. {
  579. NSEEL_code_execute(pState->m_pf_codehandle);
  580. }
  581. }
  582. #endif
  583. // save some things for next frame:
  584. pState->monitor_after_init_code = *pState->var_pf_monitor;
  585. // save some things for per-vertex code:
  586. for (int vi=0; vi<NUM_Q_VAR; vi++)
  587. *pState->var_pv_q[vi] = *pState->var_pf_q[vi];
  588. // (a few range checks:)
  589. *pState->var_pf_gamma = max(0 , min( 8, *pState->var_pf_gamma ));
  590. *pState->var_pf_echo_zoom = max(0.001, min( 1000, *pState->var_pf_echo_zoom));
  591. /*
  592. if (m_pState->m_bRedBlueStereo || m_bAlways3D)
  593. {
  594. // override wave colors
  595. *pState->var_pf_wave_r = 0.35f*(*pState->var_pf_wave_r) + 0.65f;
  596. *pState->var_pf_wave_g = 0.35f*(*pState->var_pf_wave_g) + 0.65f;
  597. *pState->var_pf_wave_b = 0.35f*(*pState->var_pf_wave_b) + 0.65f;
  598. }
  599. */
  600. }
  601. if (m_pState->m_bBlending)
  602. {
  603. // For all variables that do NOT affect pixel motion, blend them NOW,
  604. // so later the user can just access m_pState->m_pf_whatever.
  605. double mix = (double)CosineInterp(m_pState->m_fBlendProgress);
  606. double mix2 = 1.0 - mix;
  607. *m_pState->var_pf_decay = mix*(*m_pState->var_pf_decay ) + mix2*(*m_pOldState->var_pf_decay );
  608. *m_pState->var_pf_wave_a = mix*(*m_pState->var_pf_wave_a ) + mix2*(*m_pOldState->var_pf_wave_a );
  609. *m_pState->var_pf_wave_r = mix*(*m_pState->var_pf_wave_r ) + mix2*(*m_pOldState->var_pf_wave_r );
  610. *m_pState->var_pf_wave_g = mix*(*m_pState->var_pf_wave_g ) + mix2*(*m_pOldState->var_pf_wave_g );
  611. *m_pState->var_pf_wave_b = mix*(*m_pState->var_pf_wave_b ) + mix2*(*m_pOldState->var_pf_wave_b );
  612. *m_pState->var_pf_wave_x = mix*(*m_pState->var_pf_wave_x ) + mix2*(*m_pOldState->var_pf_wave_x );
  613. *m_pState->var_pf_wave_y = mix*(*m_pState->var_pf_wave_y ) + mix2*(*m_pOldState->var_pf_wave_y );
  614. *m_pState->var_pf_wave_mystery = mix*(*m_pState->var_pf_wave_mystery) + mix2*(*m_pOldState->var_pf_wave_mystery);
  615. // wave_mode: exempt (integer)
  616. *m_pState->var_pf_ob_size = mix*(*m_pState->var_pf_ob_size ) + mix2*(*m_pOldState->var_pf_ob_size );
  617. *m_pState->var_pf_ob_r = mix*(*m_pState->var_pf_ob_r ) + mix2*(*m_pOldState->var_pf_ob_r );
  618. *m_pState->var_pf_ob_g = mix*(*m_pState->var_pf_ob_g ) + mix2*(*m_pOldState->var_pf_ob_g );
  619. *m_pState->var_pf_ob_b = mix*(*m_pState->var_pf_ob_b ) + mix2*(*m_pOldState->var_pf_ob_b );
  620. *m_pState->var_pf_ob_a = mix*(*m_pState->var_pf_ob_a ) + mix2*(*m_pOldState->var_pf_ob_a );
  621. *m_pState->var_pf_ib_size = mix*(*m_pState->var_pf_ib_size ) + mix2*(*m_pOldState->var_pf_ib_size );
  622. *m_pState->var_pf_ib_r = mix*(*m_pState->var_pf_ib_r ) + mix2*(*m_pOldState->var_pf_ib_r );
  623. *m_pState->var_pf_ib_g = mix*(*m_pState->var_pf_ib_g ) + mix2*(*m_pOldState->var_pf_ib_g );
  624. *m_pState->var_pf_ib_b = mix*(*m_pState->var_pf_ib_b ) + mix2*(*m_pOldState->var_pf_ib_b );
  625. *m_pState->var_pf_ib_a = mix*(*m_pState->var_pf_ib_a ) + mix2*(*m_pOldState->var_pf_ib_a );
  626. *m_pState->var_pf_mv_x = mix*(*m_pState->var_pf_mv_x ) + mix2*(*m_pOldState->var_pf_mv_x );
  627. *m_pState->var_pf_mv_y = mix*(*m_pState->var_pf_mv_y ) + mix2*(*m_pOldState->var_pf_mv_y );
  628. *m_pState->var_pf_mv_dx = mix*(*m_pState->var_pf_mv_dx ) + mix2*(*m_pOldState->var_pf_mv_dx );
  629. *m_pState->var_pf_mv_dy = mix*(*m_pState->var_pf_mv_dy ) + mix2*(*m_pOldState->var_pf_mv_dy );
  630. *m_pState->var_pf_mv_l = mix*(*m_pState->var_pf_mv_l ) + mix2*(*m_pOldState->var_pf_mv_l );
  631. *m_pState->var_pf_mv_r = mix*(*m_pState->var_pf_mv_r ) + mix2*(*m_pOldState->var_pf_mv_r );
  632. *m_pState->var_pf_mv_g = mix*(*m_pState->var_pf_mv_g ) + mix2*(*m_pOldState->var_pf_mv_g );
  633. *m_pState->var_pf_mv_b = mix*(*m_pState->var_pf_mv_b ) + mix2*(*m_pOldState->var_pf_mv_b );
  634. *m_pState->var_pf_mv_a = mix*(*m_pState->var_pf_mv_a ) + mix2*(*m_pOldState->var_pf_mv_a );
  635. *m_pState->var_pf_echo_zoom = mix*(*m_pState->var_pf_echo_zoom ) + mix2*(*m_pOldState->var_pf_echo_zoom );
  636. *m_pState->var_pf_echo_alpha = mix*(*m_pState->var_pf_echo_alpha ) + mix2*(*m_pOldState->var_pf_echo_alpha );
  637. *m_pState->var_pf_echo_orient = (mix < m_fSnapPoint) ? *m_pOldState->var_pf_echo_orient : *m_pState->var_pf_echo_orient;
  638. // added in v1.04:
  639. *m_pState->var_pf_wave_usedots = (mix < m_fSnapPoint) ? *m_pOldState->var_pf_wave_usedots : *m_pState->var_pf_wave_usedots ;
  640. *m_pState->var_pf_wave_thick = (mix < m_fSnapPoint) ? *m_pOldState->var_pf_wave_thick : *m_pState->var_pf_wave_thick ;
  641. *m_pState->var_pf_wave_additive= (mix < m_fSnapPoint) ? *m_pOldState->var_pf_wave_additive : *m_pState->var_pf_wave_additive;
  642. *m_pState->var_pf_wave_brighten= (mix < m_fSnapPoint) ? *m_pOldState->var_pf_wave_brighten : *m_pState->var_pf_wave_brighten;
  643. *m_pState->var_pf_darken_center= (mix < m_fSnapPoint) ? *m_pOldState->var_pf_darken_center : *m_pState->var_pf_darken_center;
  644. *m_pState->var_pf_gamma = mix*(*m_pState->var_pf_gamma ) + mix2*(*m_pOldState->var_pf_gamma );
  645. *m_pState->var_pf_wrap = (mix < m_fSnapPoint) ? *m_pOldState->var_pf_wrap : *m_pState->var_pf_wrap ;
  646. *m_pState->var_pf_invert = (mix < m_fSnapPoint) ? *m_pOldState->var_pf_invert : *m_pState->var_pf_invert ;
  647. *m_pState->var_pf_brighten = (mix < m_fSnapPoint) ? *m_pOldState->var_pf_brighten : *m_pState->var_pf_brighten ;
  648. *m_pState->var_pf_darken = (mix < m_fSnapPoint) ? *m_pOldState->var_pf_darken : *m_pState->var_pf_darken ;
  649. *m_pState->var_pf_solarize = (mix < m_fSnapPoint) ? *m_pOldState->var_pf_solarize : *m_pState->var_pf_solarize ;
  650. // added in v2.0:
  651. *m_pState->var_pf_blur1min = mix*(*m_pState->var_pf_blur1min ) + mix2*(*m_pOldState->var_pf_blur1min );
  652. *m_pState->var_pf_blur2min = mix*(*m_pState->var_pf_blur2min ) + mix2*(*m_pOldState->var_pf_blur2min );
  653. *m_pState->var_pf_blur3min = mix*(*m_pState->var_pf_blur3min ) + mix2*(*m_pOldState->var_pf_blur3min );
  654. *m_pState->var_pf_blur1max = mix*(*m_pState->var_pf_blur1max ) + mix2*(*m_pOldState->var_pf_blur1max );
  655. *m_pState->var_pf_blur2max = mix*(*m_pState->var_pf_blur2max ) + mix2*(*m_pOldState->var_pf_blur2max );
  656. *m_pState->var_pf_blur3max = mix*(*m_pState->var_pf_blur3max ) + mix2*(*m_pOldState->var_pf_blur3max );
  657. *m_pState->var_pf_blur1_edge_darken = mix*(*m_pState->var_pf_blur1_edge_darken) + mix2*(*m_pOldState->var_pf_blur1_edge_darken);
  658. }
  659. }
  660. void CPlugin::RenderFrame(int bRedraw)
  661. {
  662. int i;
  663. float fDeltaT = 1.0f/GetFps();
  664. if (bRedraw)
  665. {
  666. // pre-un-flip buffers, so we are redoing the same work as we did last frame...
  667. IDirect3DTexture9* pTemp = m_lpVS[0];
  668. m_lpVS[0] = m_lpVS[1];
  669. m_lpVS[1] = pTemp;
  670. }
  671. // update time
  672. /*
  673. float fDeltaT = (GetFrame()==0) ? 1.0f/30.0f : GetTime() - m_prev_time;
  674. DWORD dwTime = GetTickCount();
  675. float fDeltaT = (dwTime - m_dwPrevTickCount)*0.001f;
  676. if (GetFrame() > 64)
  677. {
  678. fDeltaT = (fDeltaT)*0.2f + 0.8f*(1.0f/m_fps);
  679. if (fDeltaT > 2.0f/m_fps)
  680. {
  681. char buf[64];
  682. sprintf(buf, "fixing time gap of %5.3f seconds", fDeltaT);
  683. dumpmsg(buf);
  684. fDeltaT = 1.0f/m_fps;
  685. }
  686. }
  687. m_dwPrevTickCount = dwTime;
  688. GetTime() += fDeltaT;
  689. */
  690. if (GetFrame()==0)
  691. {
  692. m_fStartTime = GetTime();
  693. m_fPresetStartTime = GetTime();
  694. }
  695. if (m_fNextPresetTime < 0)
  696. {
  697. float dt = m_fTimeBetweenPresetsRand * (warand()%1000)*0.001f;
  698. m_fNextPresetTime = GetTime() + m_fBlendTimeAuto + m_fTimeBetweenPresets + dt;
  699. }
  700. /*
  701. if (m_bPresetLockedByUser || m_bPresetLockedByCode)
  702. {
  703. // if the user has the preset LOCKED, or if they're in the middle of
  704. // saving it, then keep extending the time at which the auto-switch will occur
  705. // (by the length of this frame).
  706. m_fPresetStartTime += fDeltaT;
  707. m_fNextPresetTime += fDeltaT;
  708. }*/
  709. // update fps
  710. /*
  711. if (GetFrame() < 4)
  712. {
  713. m_fps = 0.0f;
  714. }
  715. else if (GetFrame() <= 64)
  716. {
  717. m_fps = GetFrame() / (float)(GetTime() - m_fTimeHistory[0]);
  718. }
  719. else
  720. {
  721. m_fps = 64.0f / (float)(GetTime() - m_fTimeHistory[m_nTimeHistoryPos]);
  722. }
  723. m_fTimeHistory[m_nTimeHistoryPos] = GetTime();
  724. m_nTimeHistoryPos = (m_nTimeHistoryPos + 1) % 64;
  725. */
  726. // limit fps, if necessary
  727. /*
  728. if (m_nFpsLimit > 0 && (GetFrame() % 64) == 0 && GetFrame() > 64)
  729. {
  730. float spf_now = 1.0f / m_fps;
  731. float spf_desired = 1.0f / (float)m_nFpsLimit;
  732. float new_sleep = m_fFPSLimitSleep + (spf_desired - spf_now)*1000.0f;
  733. if (GetFrame() <= 128)
  734. m_fFPSLimitSleep = new_sleep;
  735. else
  736. m_fFPSLimitSleep = m_fFPSLimitSleep*0.8f + 0.2f*new_sleep;
  737. if (m_fFPSLimitSleep < 0) m_fFPSLimitSleep = 0;
  738. if (m_fFPSLimitSleep > 100) m_fFPSLimitSleep = 100;
  739. //sprintf(m_szUserMessage, "sleep=%f", m_fFPSLimitSleep);
  740. //m_fShowUserMessageUntilThisTime = GetTime() + 3.0f;
  741. }
  742. static float deficit;
  743. if (GetFrame()==0) deficit = 0;
  744. float ideal_sleep = (m_fFPSLimitSleep + deficit);
  745. int actual_sleep = (int)ideal_sleep;
  746. if (actual_sleep > 0)
  747. Sleep(actual_sleep);
  748. deficit = ideal_sleep - actual_sleep;
  749. if (deficit < 0) deficit = 0; // just in case
  750. if (deficit > 1) deficit = 1; // just in case
  751. */
  752. if (!bRedraw)
  753. {
  754. m_rand_frame = D3DXVECTOR4(FRAND, FRAND, FRAND, FRAND);
  755. // randomly change the preset, if it's time
  756. if (m_fNextPresetTime < GetTime())
  757. {
  758. if (m_nLoadingPreset==0) // don't start a load if one is already underway!
  759. LoadRandomPreset(m_fBlendTimeAuto);
  760. }
  761. // randomly spawn Song Title, if time
  762. if (m_fTimeBetweenRandomSongTitles > 0 &&
  763. !m_supertext.bRedrawSuperText &&
  764. GetTime() >= m_supertext.fStartTime + m_supertext.fDuration + 1.0f/GetFps())
  765. {
  766. int n = GetNumToSpawn(GetTime(), fDeltaT, 1.0f/m_fTimeBetweenRandomSongTitles, 0.5f, m_nSongTitlesSpawned);
  767. if (n > 0)
  768. {
  769. LaunchSongTitleAnim();
  770. m_nSongTitlesSpawned += n;
  771. }
  772. }
  773. // randomly spawn Custom Message, if time
  774. if (m_fTimeBetweenRandomCustomMsgs > 0 &&
  775. !m_supertext.bRedrawSuperText &&
  776. GetTime() >= m_supertext.fStartTime + m_supertext.fDuration + 1.0f/GetFps())
  777. {
  778. int n = GetNumToSpawn(GetTime(), fDeltaT, 1.0f/m_fTimeBetweenRandomCustomMsgs, 0.5f, m_nCustMsgsSpawned);
  779. if (n > 0)
  780. {
  781. LaunchCustomMessage(-1);
  782. m_nCustMsgsSpawned += n;
  783. }
  784. }
  785. // update m_fBlendProgress;
  786. if (m_pState->m_bBlending)
  787. {
  788. m_pState->m_fBlendProgress = (GetTime() - m_pState->m_fBlendStartTime) / m_pState->m_fBlendDuration;
  789. if (m_pState->m_fBlendProgress > 1.0f)
  790. {
  791. m_pState->m_bBlending = false;
  792. }
  793. }
  794. // handle hard cuts here (just after new sound analysis)
  795. static float m_fHardCutThresh;
  796. if (GetFrame() == 0)
  797. m_fHardCutThresh = m_fHardCutLoudnessThresh*2.0f;
  798. if (GetFps() > 1.0f && !m_bHardCutsDisabled && !m_bPresetLockedByUser && !m_bPresetLockedByCode)
  799. {
  800. if (mysound.imm_rel[0] + mysound.imm_rel[1] + mysound.imm_rel[2] > m_fHardCutThresh*3.0f)
  801. {
  802. if (m_nLoadingPreset==0) // don't start a load if one is already underway!
  803. LoadRandomPreset(0.0f);
  804. m_fHardCutThresh *= 2.0f;
  805. }
  806. else
  807. {
  808. /*
  809. float halflife_modified = m_fHardCutHalflife*0.5f;
  810. //thresh = (thresh - 1.5f)*0.99f + 1.5f;
  811. float k = -0.69315f / halflife_modified;*/
  812. float k = -1.3863f / (m_fHardCutHalflife*GetFps());
  813. //float single_frame_multiplier = powf(2.7183f, k / GetFps());
  814. float single_frame_multiplier = expf(k);
  815. m_fHardCutThresh = (m_fHardCutThresh - m_fHardCutLoudnessThresh)*single_frame_multiplier + m_fHardCutLoudnessThresh;
  816. }
  817. }
  818. // smooth & scale the audio data, according to m_state, for display purposes
  819. float scale = m_pState->m_fWaveScale.eval(GetTime()) / 128.0f;
  820. mysound.fWave[0][0] *= scale;
  821. mysound.fWave[1][0] *= scale;
  822. float mix2 = m_pState->m_fWaveSmoothing.eval(GetTime());
  823. float mix1 = scale*(1.0f - mix2);
  824. for (i=1; i<576; i++)
  825. {
  826. mysound.fWave[0][i] = mysound.fWave[0][i]*mix1 + mysound.fWave[0][i-1]*mix2;
  827. mysound.fWave[1][i] = mysound.fWave[1][i]*mix1 + mysound.fWave[1][i-1]*mix2;
  828. }
  829. }
  830. bool bOldPresetUsesWarpShader = (m_pOldState->m_nWarpPSVersion > 0);
  831. bool bNewPresetUsesWarpShader = (m_pState->m_nWarpPSVersion > 0);
  832. bool bOldPresetUsesCompShader = (m_pOldState->m_nCompPSVersion > 0);
  833. bool bNewPresetUsesCompShader = (m_pState->m_nCompPSVersion > 0);
  834. // note: 'code' is only meaningful if we are BLENDING.
  835. int code = (bOldPresetUsesWarpShader ? 8 : 0) |
  836. (bOldPresetUsesCompShader ? 4 : 0) |
  837. (bNewPresetUsesWarpShader ? 2 : 0) |
  838. (bNewPresetUsesCompShader ? 1 : 0);
  839. RunPerFrameEquations(code);
  840. // restore any lost surfaces
  841. //m_lpDD->RestoreAllSurfaces();
  842. LPDIRECT3DDEVICE9 lpDevice = GetDevice();
  843. if (!lpDevice)
  844. return;
  845. // Remember the original backbuffer and zbuffer
  846. LPDIRECT3DSURFACE9 pBackBuffer=NULL;//, pZBuffer=NULL;
  847. lpDevice->GetRenderTarget( 0, &pBackBuffer );
  848. //lpDevice->GetDepthStencilSurface( &pZBuffer );
  849. // set up render state
  850. {
  851. DWORD texaddr = (*m_pState->var_pf_wrap > m_fSnapPoint) ? D3DTADDRESS_WRAP : D3DTADDRESS_CLAMP;
  852. lpDevice->SetRenderState(D3DRS_WRAP0, 0);//D3DWRAPCOORD_0|D3DWRAPCOORD_1|D3DWRAPCOORD_2|D3DWRAPCOORD_3);
  853. //lpDevice->SetRenderState(D3DRS_WRAP0, (*m_pState->var_pf_wrap) ? D3DWRAP_U|D3DWRAP_V|D3DWRAP_W : 0);
  854. //lpDevice->SetRenderState(D3DRS_WRAP1, (*m_pState->var_pf_wrap) ? D3DWRAP_U|D3DWRAP_V|D3DWRAP_W : 0);
  855. lpDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);//texaddr);
  856. lpDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);//texaddr);
  857. lpDevice->SetSamplerState(0, D3DSAMP_ADDRESSW, D3DTADDRESS_WRAP);//texaddr);
  858. lpDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
  859. lpDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
  860. lpDevice->SetSamplerState(1, D3DSAMP_ADDRESSW, D3DTADDRESS_WRAP);
  861. lpDevice->SetRenderState( D3DRS_SHADEMODE, D3DSHADE_GOURAUD );
  862. lpDevice->SetRenderState( D3DRS_SPECULARENABLE, FALSE );
  863. lpDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
  864. lpDevice->SetRenderState( D3DRS_ZENABLE, FALSE );
  865. lpDevice->SetRenderState( D3DRS_ZWRITEENABLE, FALSE );
  866. lpDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
  867. lpDevice->SetRenderState( D3DRS_COLORVERTEX, TRUE );
  868. lpDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
  869. lpDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
  870. lpDevice->SetRenderState( D3DRS_AMBIENT, 0xFFFFFFFF ); //?
  871. lpDevice->SetRenderState( D3DRS_CLIPPING, TRUE );
  872. // stages 0 and 1 always just use bilinear filtering.
  873. lpDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
  874. lpDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
  875. lpDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
  876. lpDevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
  877. lpDevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
  878. lpDevice->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
  879. // note: this texture stage state setup works for 0 or 1 texture.
  880. // if you set a texture, it will be modulated with the current diffuse color.
  881. // if you don't set a texture, it will just use the current diffuse color.
  882. lpDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
  883. lpDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
  884. lpDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE);
  885. lpDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
  886. lpDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
  887. lpDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE );
  888. lpDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
  889. // NOTE: don't forget to call SetTexture and SetVertexShader before drawing!
  890. // Examples:
  891. // SPRITEVERTEX verts[4]; // has texcoords
  892. // lpDevice->SetTexture(0, m_sprite_tex);
  893. // lpDevice->SetVertexShader( SPRITEVERTEX_FORMAT );
  894. //
  895. // WFVERTEX verts[4]; // no texcoords
  896. // lpDevice->SetTexture(0, NULL);
  897. // lpDevice->SetVertexShader( WFVERTEX_FORMAT );
  898. }
  899. // render string to m_lpDDSTitle, if necessary
  900. if (m_supertext.bRedrawSuperText)
  901. {
  902. if (!RenderStringToTitleTexture())
  903. m_supertext.fStartTime = -1.0f;
  904. m_supertext.bRedrawSuperText = false;
  905. }
  906. // set up to render [from NULL] to VS0 (for motion vectors).
  907. {
  908. lpDevice->SetTexture(0, NULL);
  909. IDirect3DSurface9* pNewTarget = NULL;
  910. if (m_lpVS[0]->GetSurfaceLevel(0, &pNewTarget) != D3D_OK)
  911. return;
  912. lpDevice->SetRenderTarget(0, pNewTarget );
  913. //lpDevice->SetDepthStencilSurface( NULL );
  914. pNewTarget->Release();
  915. lpDevice->SetTexture(0, NULL);
  916. }
  917. // draw motion vectors to VS0
  918. DrawMotionVectors();
  919. lpDevice->SetTexture(0, NULL);
  920. lpDevice->SetTexture(1, NULL);
  921. // on first frame, clear OLD VS.
  922. if (m_nFramesSinceResize == 0)
  923. {
  924. IDirect3DSurface9* pNewTarget = NULL;
  925. if (m_lpVS[0]->GetSurfaceLevel(0, &pNewTarget) != D3D_OK)
  926. return;
  927. lpDevice->SetRenderTarget(0, pNewTarget );
  928. //lpDevice->SetDepthStencilSurface( NULL );
  929. pNewTarget->Release();
  930. lpDevice->Clear(0, NULL, D3DCLEAR_TARGET, 0x00000000, 1.0f, 0);
  931. }
  932. // set up to render [from VS0] to VS1.
  933. {
  934. IDirect3DSurface9* pNewTarget = NULL;
  935. if (m_lpVS[1]->GetSurfaceLevel(0, &pNewTarget) != D3D_OK)
  936. return;
  937. lpDevice->SetRenderTarget(0, pNewTarget );
  938. //lpDevice->SetDepthStencilSurface( NULL );
  939. pNewTarget->Release();
  940. }
  941. if (m_bAutoGamma && GetFrame()==0)
  942. {
  943. if (strstr(GetDriverDescription(), "nvidia") ||
  944. strstr(GetDriverDescription(), "nVidia") ||
  945. strstr(GetDriverDescription(), "NVidia") ||
  946. strstr(GetDriverDescription(), "NVIDIA"))
  947. m_n16BitGamma = 2;
  948. else if (strstr(GetDriverDescription(), "ATI RAGE MOBILITY M"))
  949. m_n16BitGamma = 2;
  950. else
  951. m_n16BitGamma = 0;
  952. }
  953. ComputeGridAlphaValues();
  954. // do the warping for this frame [warp shader]
  955. if (!m_pState->m_bBlending)
  956. {
  957. // no blend
  958. if (bNewPresetUsesWarpShader)
  959. WarpedBlit_Shaders(1, false, false, false, false);
  960. else
  961. WarpedBlit_NoShaders(1, false, false, false, false);
  962. }
  963. else
  964. {
  965. // blending
  966. // WarpedBlit( nPass, bAlphaBlend, bFlipAlpha, bCullTiles, bFlipCulling )
  967. // note: alpha values go from 0..1 during a blend.
  968. // note: bFlipCulling==false means tiles with alpha>0 will draw.
  969. // bFlipCulling==true means tiles with alpha<255 will draw.
  970. if (bOldPresetUsesWarpShader && bNewPresetUsesWarpShader)
  971. {
  972. WarpedBlit_Shaders (0, false, false, true, true);
  973. WarpedBlit_Shaders (1, true, false, true, false);
  974. }
  975. else if (!bOldPresetUsesWarpShader && bNewPresetUsesWarpShader)
  976. {
  977. WarpedBlit_NoShaders(0, false, false, true, true);
  978. WarpedBlit_Shaders (1, true, false, true, false);
  979. }
  980. else if (bOldPresetUsesWarpShader && !bNewPresetUsesWarpShader)
  981. {
  982. WarpedBlit_Shaders (0, false, false, true, true);
  983. WarpedBlit_NoShaders(1, true, false, true, false);
  984. }
  985. else if (!bOldPresetUsesWarpShader && !bNewPresetUsesWarpShader)
  986. {
  987. //WarpedBlit_NoShaders(0, false, false, true, true);
  988. //WarpedBlit_NoShaders(1, true, false, true, false);
  989. // special case - all the blending just happens in the vertex UV's, so just pretend there's no blend.
  990. WarpedBlit_NoShaders(1, false, false, false, false);
  991. }
  992. }
  993. if (m_nMaxPSVersion > 0)
  994. BlurPasses();
  995. // draw audio data
  996. DrawCustomShapes(); // draw these first; better for feedback if the waves draw *over* them.
  997. DrawCustomWaves();
  998. DrawWave(mysound.fWave[0], mysound.fWave[1]);
  999. DrawSprites();
  1000. float fProgress = (GetTime() - m_supertext.fStartTime) / m_supertext.fDuration;
  1001. // if song title animation just ended, burn it into the VS:
  1002. if (m_supertext.fStartTime >= 0 &&
  1003. fProgress >= 1.0f &&
  1004. !m_supertext.bRedrawSuperText)
  1005. {
  1006. ShowSongTitleAnim(m_nTexSizeX, m_nTexSizeY, 1.0f);
  1007. }
  1008. // Change the rendertarget back to the original setup
  1009. lpDevice->SetTexture(0, NULL);
  1010. lpDevice->SetRenderTarget(0, pBackBuffer );
  1011. //lpDevice->SetDepthStencilSurface( pZBuffer );
  1012. SafeRelease(pBackBuffer);
  1013. //SafeRelease(pZBuffer);
  1014. // show it to the user [composite shader]
  1015. if (!m_pState->m_bBlending)
  1016. {
  1017. // no blend
  1018. if (bNewPresetUsesCompShader)
  1019. ShowToUser_Shaders(1, false, false, false, false);
  1020. else
  1021. ShowToUser_NoShaders();//1, false, false, false, false);
  1022. }
  1023. else
  1024. {
  1025. // blending
  1026. // ShowToUser( nPass, bAlphaBlend, bFlipAlpha, bCullTiles, bFlipCulling )
  1027. // note: alpha values go from 0..1 during a blend.
  1028. // note: bFlipCulling==false means tiles with alpha>0 will draw.
  1029. // bFlipCulling==true means tiles with alpha<255 will draw.
  1030. // NOTE: ShowToUser_NoShaders() must always come before ShowToUser_Shaders(),
  1031. // because it always draws the full quad (it can't do tile culling or alpha blending).
  1032. // [third case here]
  1033. if (bOldPresetUsesCompShader && bNewPresetUsesCompShader)
  1034. {
  1035. ShowToUser_Shaders (0, false, false, true, true);
  1036. ShowToUser_Shaders (1, true, false, true, false);
  1037. }
  1038. else if (!bOldPresetUsesCompShader && bNewPresetUsesCompShader)
  1039. {
  1040. ShowToUser_NoShaders();
  1041. ShowToUser_Shaders (1, true, false, true, false);
  1042. }
  1043. else if (bOldPresetUsesCompShader && !bNewPresetUsesCompShader)
  1044. {
  1045. // THA FUNKY REVERSAL
  1046. //ShowToUser_Shaders (0);
  1047. //ShowToUser_NoShaders(1);
  1048. ShowToUser_NoShaders();
  1049. ShowToUser_Shaders (0, true, true, true, true);
  1050. }
  1051. else if (!bOldPresetUsesCompShader && !bNewPresetUsesCompShader)
  1052. {
  1053. // special case - all the blending just happens in the blended state vars, so just pretend there's no blend.
  1054. ShowToUser_NoShaders();//1, false, false, false, false);
  1055. }
  1056. }
  1057. // finally, render song title animation to back buffer
  1058. if (m_supertext.fStartTime >= 0 &&
  1059. !m_supertext.bRedrawSuperText)
  1060. {
  1061. ShowSongTitleAnim(GetWidth(), GetHeight(), min(fProgress, 0.9999f));
  1062. if (fProgress >= 1.0f)
  1063. m_supertext.fStartTime = -1.0f; // 'off' state
  1064. }
  1065. DrawUserSprites();
  1066. // flip buffers
  1067. IDirect3DTexture9* pTemp = m_lpVS[0];
  1068. m_lpVS[0] = m_lpVS[1];
  1069. m_lpVS[1] = pTemp;
  1070. /*
  1071. // FIXME - remove EnforceMaxFPS() if never used
  1072. //EnforceMaxFPS(!(m_nLoadingPreset==1 || m_nLoadingPreset==2 || m_nLoadingPreset==4 || m_nLoadingPreset==5)); // this call just turns it on or off; doesn't do it now...
  1073. //EnforceMaxFPS(!(m_nLoadingPreset==2 || m_nLoadingPreset==5)); // this call just turns it on or off; doesn't do it now...
  1074. // FIXME - remove this stuff, and change 'm_last_raw_time' in pluginshell (and others) back to private.
  1075. static float fOldTime = 0;
  1076. float fNewTime = (float)((double)m_last_raw_time/(double)m_high_perf_timer_freq.QuadPart);
  1077. float dt = fNewTime-fOldTime;
  1078. if (m_nLoadingPreset != 0) {
  1079. char buf[256];
  1080. sprintf(buf, "m_nLoadingPreset==%d: dt=%d ms\n", m_nLoadingPreset, (int)(dt*1000) );
  1081. OutputDebugString(buf);
  1082. }
  1083. fOldTime = fNewTime;
  1084. */
  1085. }
  1086. void CPlugin::DrawMotionVectors()
  1087. {
  1088. // FLEXIBLE MOTION VECTOR FIELD
  1089. if ((float)*m_pState->var_pf_mv_a >= 0.001f)
  1090. {
  1091. //-------------------------------------------------------
  1092. LPDIRECT3DDEVICE9 lpDevice = GetDevice();
  1093. if (!lpDevice)
  1094. return;
  1095. lpDevice->SetTexture(0, NULL);
  1096. lpDevice->SetVertexShader(NULL);
  1097. lpDevice->SetFVF(WFVERTEX_FORMAT);
  1098. //-------------------------------------------------------
  1099. int x,y;
  1100. int nX = (int)(*m_pState->var_pf_mv_x);// + 0.999f);
  1101. int nY = (int)(*m_pState->var_pf_mv_y);// + 0.999f);
  1102. float dx = (float)*m_pState->var_pf_mv_x - nX;
  1103. float dy = (float)*m_pState->var_pf_mv_y - nY;
  1104. if (nX > 64) { nX = 64; dx = 0; }
  1105. if (nY > 48) { nY = 48; dy = 0; }
  1106. if (nX > 0 && nY > 0)
  1107. {
  1108. /*
  1109. float dx2 = m_fMotionVectorsTempDx;//(*m_pState->var_pf_mv_dx) * 0.05f*GetTime(); // 0..1 range
  1110. float dy2 = m_fMotionVectorsTempDy;//(*m_pState->var_pf_mv_dy) * 0.05f*GetTime(); // 0..1 range
  1111. if (GetFps() > 2.0f && GetFps() < 300.0f)
  1112. {
  1113. dx2 += (float)(*m_pState->var_pf_mv_dx) * 0.05f / GetFps();
  1114. dy2 += (float)(*m_pState->var_pf_mv_dy) * 0.05f / GetFps();
  1115. }
  1116. if (dx2 > 1.0f) dx2 -= (int)dx2;
  1117. if (dy2 > 1.0f) dy2 -= (int)dy2;
  1118. if (dx2 < 0.0f) dx2 = 1.0f - (-dx2 - (int)(-dx2));
  1119. if (dy2 < 0.0f) dy2 = 1.0f - (-dy2 - (int)(-dy2));
  1120. // hack: when there is only 1 motion vector on the screem, to keep it in
  1121. // the center, we gradually migrate it toward 0.5.
  1122. dx2 = dx2*0.995f + 0.5f*0.005f;
  1123. dy2 = dy2*0.995f + 0.5f*0.005f;
  1124. // safety catch
  1125. if (dx2 < 0 || dx2 > 1 || dy2 < 0 || dy2 > 1)
  1126. {
  1127. dx2 = 0.5f;
  1128. dy2 = 0.5f;
  1129. }
  1130. m_fMotionVectorsTempDx = dx2;
  1131. m_fMotionVectorsTempDy = dy2;*/
  1132. float dx2 = (float)(*m_pState->var_pf_mv_dx);
  1133. float dy2 = (float)(*m_pState->var_pf_mv_dy);
  1134. float len_mult = (float)*m_pState->var_pf_mv_l;
  1135. if (dx < 0) dx = 0;
  1136. if (dy < 0) dy = 0;
  1137. if (dx > 1) dx = 1;
  1138. if (dy > 1) dy = 1;
  1139. //dx = dx * 1.0f/(float)nX;
  1140. //dy = dy * 1.0f/(float)nY;
  1141. float inv_texsize = 1.0f/(float)m_nTexSizeX;
  1142. float min_len = 1.0f*inv_texsize;
  1143. WFVERTEX v[(64+1)*2];
  1144. ZeroMemory(v, sizeof(WFVERTEX)*(64+1)*2);
  1145. v[0].Diffuse = D3DCOLOR_RGBA_01((float)*m_pState->var_pf_mv_r,(float)*m_pState->var_pf_mv_g,(float)*m_pState->var_pf_mv_b,(float)*m_pState->var_pf_mv_a);
  1146. for (x=1; x<(nX+1)*2; x++)
  1147. v[x].Diffuse = v[0].Diffuse;
  1148. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  1149. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
  1150. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
  1151. for (y=0; y<nY; y++)
  1152. {
  1153. float fy = (y + 0.25f)/(float)(nY + dy + 0.25f - 1.0f);
  1154. // now move by offset
  1155. fy -= dy2;
  1156. if (fy > 0.0001f && fy < 0.9999f)
  1157. {
  1158. int n = 0;
  1159. for (x=0; x<nX; x++)
  1160. {
  1161. //float fx = (x + 0.25f)/(float)(nX + dx + 0.25f - 1.0f);
  1162. float fx = (x + 0.25f)/(float)(nX + dx + 0.25f - 1.0f);
  1163. // now move by offset
  1164. fx += dx2;
  1165. if (fx > 0.0001f && fx < 0.9999f)
  1166. {
  1167. float fx2, fy2;
  1168. ReversePropagatePoint(fx, fy, &fx2, &fy2); // NOTE: THIS IS REALLY A REVERSE-PROPAGATION
  1169. //fx2 = fx*2 - fx2;
  1170. //fy2 = fy*2 - fy2;
  1171. //fx2 = fx + 1.0f/(float)m_nTexSize;
  1172. //fy2 = 1-(fy + 1.0f/(float)m_nTexSize);
  1173. // enforce minimum trail lengths:
  1174. {
  1175. float dx = (fx2 - fx);
  1176. float dy = (fy2 - fy);
  1177. dx *= len_mult;
  1178. dy *= len_mult;
  1179. float len = sqrtf(dx*dx + dy*dy);
  1180. if (len > min_len)
  1181. {
  1182. }
  1183. else if (len > 0.00000001f)
  1184. {
  1185. len = min_len/len;
  1186. dx *= len;
  1187. dy *= len;
  1188. }
  1189. else
  1190. {
  1191. dx = min_len;
  1192. dy = min_len;
  1193. }
  1194. fx2 = fx + dx;
  1195. fy2 = fy + dy;
  1196. }
  1197. /**/
  1198. v[n].x = fx * 2.0f - 1.0f;
  1199. v[n].y = fy * 2.0f - 1.0f;
  1200. v[n+1].x = fx2 * 2.0f - 1.0f;
  1201. v[n+1].y = fy2 * 2.0f - 1.0f;
  1202. // actually, project it in the reverse direction
  1203. //v[n+1].x = v[n].x*2.0f - v[n+1].x;// + dx*2;
  1204. //v[n+1].y = v[n].y*2.0f - v[n+1].y;// + dy*2;
  1205. //v[n].x += dx*2;
  1206. //v[n].y += dy*2;
  1207. n += 2;
  1208. }
  1209. }
  1210. // draw it
  1211. lpDevice->DrawPrimitiveUP(D3DPT_LINELIST, n/2, v, sizeof(WFVERTEX));
  1212. }
  1213. }
  1214. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  1215. }
  1216. }
  1217. }
  1218. /*
  1219. void CPlugin::UpdateSongInfo()
  1220. {
  1221. if (m_bShowSongTitle || m_bSongTitleAnims)
  1222. {
  1223. char szOldSongMessage[512];
  1224. lstrcpy(szOldSongMessage, m_szSongMessage);
  1225. if (::GetWindowText(m_hWndParent, m_szSongMessage, sizeof(m_szSongMessage)))
  1226. {
  1227. // remove ' - Winamp' at end
  1228. if (strlen(m_szSongMessage) > 9)
  1229. {
  1230. int check_pos = strlen(m_szSongMessage) - 9;
  1231. if (lstrcmp(" - Winamp", (char *)(m_szSongMessage + check_pos)) == 0)
  1232. m_szSongMessage[check_pos] = 0;
  1233. }
  1234. // remove ' - Winamp [Paused]' at end
  1235. if (strlen(m_szSongMessage) > 18)
  1236. {
  1237. int check_pos = strlen(m_szSongMessage) - 18;
  1238. if (lstrcmp(" - Winamp [Paused]", (char *)(m_szSongMessage + check_pos)) == 0)
  1239. m_szSongMessage[check_pos] = 0;
  1240. }
  1241. // remove song # and period from beginning
  1242. char *p = m_szSongMessage;
  1243. while (*p >= '0' && *p <= '9') p++;
  1244. if (*p == '.' && *(p+1) == ' ')
  1245. {
  1246. p += 2;
  1247. int pos = 0;
  1248. while (*p != 0)
  1249. {
  1250. m_szSongMessage[pos++] = *p;
  1251. p++;
  1252. }
  1253. m_szSongMessage[pos++] = 0;
  1254. }
  1255. // fix &'s for display
  1256. /*
  1257. {
  1258. int pos = 0;
  1259. int len = strlen(m_szSongMessage);
  1260. while (m_szSongMessage[pos])
  1261. {
  1262. if (m_szSongMessage[pos] == '&')
  1263. {
  1264. for (int x=len; x>=pos; x--)
  1265. m_szSongMessage[x+1] = m_szSongMessage[x];
  1266. len++;
  1267. pos++;
  1268. }
  1269. pos++;
  1270. }
  1271. }*/
  1272. /*
  1273. if (m_bSongTitleAnims &&
  1274. ((lstrcmp(szOldSongMessage, m_szSongMessage) != 0) || (GetFrame()==0)))
  1275. {
  1276. // launch song title animation
  1277. LaunchSongTitleAnim();
  1278. /*
  1279. m_supertext.bRedrawSuperText = true;
  1280. m_supertext.bIsSongTitle = true;
  1281. lstrcpy(m_supertext.szText, m_szSongMessage);
  1282. lstrcpy(m_supertext.nFontFace, m_szTitleFontFace);
  1283. m_supertext.fFontSize = (float)m_nTitleFontSize;
  1284. m_supertext.bBold = m_bTitleFontBold;
  1285. m_supertext.bItal = m_bTitleFontItalic;
  1286. m_supertext.fX = 0.5f;
  1287. m_supertext.fY = 0.5f;
  1288. m_supertext.fGrowth = 1.0f;
  1289. m_supertext.fDuration = m_fSongTitleAnimDuration;
  1290. m_supertext.nColorR = 255;
  1291. m_supertext.nColorG = 255;
  1292. m_supertext.nColorB = 255;
  1293. m_supertext.fStartTime = GetTime();
  1294. */
  1295. /* }
  1296. }
  1297. else
  1298. {
  1299. sprintf(m_szSongMessage, "<couldn't get song title>");
  1300. }
  1301. }
  1302. m_nTrackPlaying = SendMessage(m_hWndParent,WM_USER, 0, 125);
  1303. // append song time
  1304. if (m_bShowSongTime && m_nSongPosMS >= 0)
  1305. {
  1306. float time_s = m_nSongPosMS*0.001f;
  1307. int minutes = (int)(time_s/60);
  1308. time_s -= minutes*60;
  1309. int seconds = (int)time_s;
  1310. time_s -= seconds;
  1311. int dsec = (int)(time_s*100);
  1312. sprintf(m_szSongTime, "%d:%02d.%02d", minutes, seconds, dsec);
  1313. }
  1314. // append song length
  1315. if (m_bShowSongLen && m_nSongLenMS > 0)
  1316. {
  1317. int len_s = m_nSongLenMS/1000;
  1318. int minutes = len_s/60;
  1319. int seconds = len_s - minutes*60;
  1320. char buf[512];
  1321. sprintf(buf, " / %d:%02d", minutes, seconds);
  1322. lstrcat(m_szSongTime, buf);
  1323. }
  1324. }
  1325. */
  1326. bool CPlugin::ReversePropagatePoint(float fx, float fy, float *fx2, float *fy2)
  1327. {
  1328. //float fy = y/(float)nMotionVectorsY;
  1329. int y0 = (int)(fy*m_nGridY);
  1330. float dy = fy*m_nGridY - y0;
  1331. //float fx = x/(float)nMotionVectorsX;
  1332. int x0 = (int)(fx*m_nGridX);
  1333. float dx = fx*m_nGridX - x0;
  1334. int x1 = x0 + 1;
  1335. int y1 = y0 + 1;
  1336. if (x0 < 0) return false;
  1337. if (y0 < 0) return false;
  1338. //if (x1 < 0) return false;
  1339. //if (y1 < 0) return false;
  1340. //if (x0 > m_nGridX) return false;
  1341. //if (y0 > m_nGridY) return false;
  1342. if (x1 > m_nGridX) return false;
  1343. if (y1 > m_nGridY) return false;
  1344. float tu, tv;
  1345. tu = m_verts[y0*(m_nGridX+1)+x0].tu * (1-dx)*(1-dy);
  1346. tv = m_verts[y0*(m_nGridX+1)+x0].tv * (1-dx)*(1-dy);
  1347. tu += m_verts[y0*(m_nGridX+1)+x1].tu * (dx)*(1-dy);
  1348. tv += m_verts[y0*(m_nGridX+1)+x1].tv * (dx)*(1-dy);
  1349. tu += m_verts[y1*(m_nGridX+1)+x0].tu * (1-dx)*(dy);
  1350. tv += m_verts[y1*(m_nGridX+1)+x0].tv * (1-dx)*(dy);
  1351. tu += m_verts[y1*(m_nGridX+1)+x1].tu * (dx)*(dy);
  1352. tv += m_verts[y1*(m_nGridX+1)+x1].tv * (dx)*(dy);
  1353. *fx2 = tu;
  1354. *fy2 = 1.0f - tv;
  1355. return true;
  1356. }
  1357. void CPlugin::GetSafeBlurMinMax(CState* pState, float* blur_min, float* blur_max)
  1358. {
  1359. blur_min[0] = (float)*pState->var_pf_blur1min;
  1360. blur_min[1] = (float)*pState->var_pf_blur2min;
  1361. blur_min[2] = (float)*pState->var_pf_blur3min;
  1362. blur_max[0] = (float)*pState->var_pf_blur1max;
  1363. blur_max[1] = (float)*pState->var_pf_blur2max;
  1364. blur_max[2] = (float)*pState->var_pf_blur3max;
  1365. // check that precision isn't wasted in later blur passes [...min-max gap can't grow!]
  1366. // also, if min-max are close to each other, push them apart:
  1367. const float fMinDist = 0.1f;
  1368. if (blur_max[0] - blur_min[0] < fMinDist) {
  1369. float avg = (blur_min[0] + blur_max[0])*0.5f;
  1370. blur_min[0] = avg - fMinDist*0.5f;
  1371. blur_max[0] = avg - fMinDist*0.5f;
  1372. }
  1373. blur_max[1] = min(blur_max[0], blur_max[1]);
  1374. blur_min[1] = max(blur_min[0], blur_min[1]);
  1375. if (blur_max[1] - blur_min[1] < fMinDist) {
  1376. float avg = (blur_min[1] + blur_max[1])*0.5f;
  1377. blur_min[1] = avg - fMinDist*0.5f;
  1378. blur_max[1] = avg - fMinDist*0.5f;
  1379. }
  1380. blur_max[2] = min(blur_max[1], blur_max[2]);
  1381. blur_min[2] = max(blur_min[1], blur_min[2]);
  1382. if (blur_max[2] - blur_min[2] < fMinDist) {
  1383. float avg = (blur_min[2] + blur_max[2])*0.5f;
  1384. blur_min[2] = avg - fMinDist*0.5f;
  1385. blur_max[2] = avg - fMinDist*0.5f;
  1386. }
  1387. }
  1388. void CPlugin::BlurPasses()
  1389. {
  1390. #if (NUM_BLUR_TEX>0)
  1391. // Note: Blur is currently a little funky. It blurs the *current* frame after warp;
  1392. // this way, it lines up well with the composite pass. However, if you switch
  1393. // presets instantly, to one whose *warp* shader uses the blur texture,
  1394. // it will be outdated (just for one frame). Oh well.
  1395. // This also means that when sampling the blurred textures in the warp shader,
  1396. // they are one frame old. This isn't too big a deal. Getting them to match
  1397. // up for the composite pass is probably more important.
  1398. LPDIRECT3DDEVICE9 lpDevice = GetDevice();
  1399. if (!lpDevice)
  1400. return;
  1401. int passes = min(NUM_BLUR_TEX, m_nHighestBlurTexUsedThisFrame*2);
  1402. if (passes==0)
  1403. return;
  1404. LPDIRECT3DSURFACE9 pBackBuffer=NULL;//, pZBuffer=NULL;
  1405. lpDevice->GetRenderTarget( 0, &pBackBuffer );
  1406. //lpDevice->SetFVF( MYVERTEX_FORMAT );
  1407. lpDevice->SetVertexShader( m_BlurShaders[0].vs.ptr );
  1408. lpDevice->SetVertexDeclaration(m_pMyVertDecl);
  1409. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  1410. DWORD wrap = D3DTADDRESS_CLAMP;//D3DTADDRESS_WRAP;// : D3DTADDRESS_CLAMP;
  1411. lpDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, wrap);
  1412. lpDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, wrap);
  1413. lpDevice->SetSamplerState(0, D3DSAMP_ADDRESSW, wrap);
  1414. lpDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
  1415. lpDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
  1416. lpDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
  1417. lpDevice->SetSamplerState(0, D3DSAMP_MAXANISOTROPY, 1);
  1418. IDirect3DSurface9* pNewTarget = NULL;
  1419. // clear texture bindings
  1420. for (int i=0; i<16; i++)
  1421. lpDevice->SetTexture(i, NULL);
  1422. // set up fullscreen quad
  1423. MYVERTEX v[4];
  1424. v[0].x = -1;
  1425. v[0].y = -1;
  1426. v[1].x = 1;
  1427. v[1].y = -1;
  1428. v[2].x = -1;
  1429. v[2].y = 1;
  1430. v[3].x = 1;
  1431. v[3].y = 1;
  1432. v[0].tu = 0; //kiv: upside-down?
  1433. v[0].tv = 0;
  1434. v[1].tu = 1;
  1435. v[1].tv = 0;
  1436. v[2].tu = 0;
  1437. v[2].tv = 1;
  1438. v[3].tu = 1;
  1439. v[3].tv = 1;
  1440. const float w[8] = { 4.0f, 3.8f, 3.5f, 2.9f, 1.9f, 1.2f, 0.7f, 0.3f }; //<- user can specify these
  1441. float edge_darken = (float)*m_pState->var_pf_blur1_edge_darken;
  1442. float blur_min[3], blur_max[3];
  1443. GetSafeBlurMinMax(m_pState, blur_min, blur_max);
  1444. float fscale[3];
  1445. float fbias[3];
  1446. // figure out the progressive scale & bias needed, at each step,
  1447. // to go from one [min..max] range to the next.
  1448. float temp_min, temp_max;
  1449. fscale[0] = 1.0f / (blur_max[0] - blur_min[0]);
  1450. fbias [0] = -blur_min[0] * fscale[0];
  1451. temp_min = (blur_min[1] - blur_min[0]) / (blur_max[0] - blur_min[0]);
  1452. temp_max = (blur_max[1] - blur_min[0]) / (blur_max[0] - blur_min[0]);
  1453. fscale[1] = 1.0f / (temp_max - temp_min);
  1454. fbias [1] = -temp_min * fscale[1];
  1455. temp_min = (blur_min[2] - blur_min[1]) / (blur_max[1] - blur_min[1]);
  1456. temp_max = (blur_max[2] - blur_min[1]) / (blur_max[1] - blur_min[1]);
  1457. fscale[2] = 1.0f / (temp_max - temp_min);
  1458. fbias [2] = -temp_min * fscale[2];
  1459. // note: warped blit just rendered from VS0 to VS1.
  1460. for (int i=0; i<passes; i++)
  1461. {
  1462. // hook up correct render target
  1463. if (m_lpBlur[i]->GetSurfaceLevel(0, &pNewTarget) != D3D_OK)
  1464. return;
  1465. lpDevice->SetRenderTarget(0, pNewTarget);
  1466. pNewTarget->Release();
  1467. // hook up correct source texture - assume there is only one, at stage 0
  1468. lpDevice->SetTexture(0, (i==0) ? m_lpVS[0] : m_lpBlur[i-1]);
  1469. // set pixel shader
  1470. lpDevice->SetPixelShader (m_BlurShaders[i%2].ps.ptr);
  1471. // set constants
  1472. LPD3DXCONSTANTTABLE pCT = m_BlurShaders[i%2].ps.CT;
  1473. D3DXHANDLE* h = m_BlurShaders[i%2].ps.params.const_handles;
  1474. int srcw = (i==0) ? GetWidth() : m_nBlurTexW[i-1];
  1475. int srch = (i==0) ? GetHeight() : m_nBlurTexH[i-1];
  1476. D3DXVECTOR4 srctexsize = D3DXVECTOR4( (float)srcw, (float)srch, 1.0f/(float)srcw, 1.0f/(float)srch );
  1477. float fscale_now = fscale[i/2];
  1478. float fbias_now = fbias[i/2];
  1479. if (i%2==0)
  1480. {
  1481. // pass 1 (long horizontal pass)
  1482. //-------------------------------------
  1483. const float w1 = w[0] + w[1];
  1484. const float w2 = w[2] + w[3];
  1485. const float w3 = w[4] + w[5];
  1486. const float w4 = w[6] + w[7];
  1487. const float d1 = 0 + 2*w[1]/w1;
  1488. const float d2 = 2 + 2*w[3]/w2;
  1489. const float d3 = 4 + 2*w[5]/w3;
  1490. const float d4 = 6 + 2*w[7]/w4;
  1491. const float w_div = 0.5f/(w1+w2+w3+w4);
  1492. //-------------------------------------
  1493. //float4 _c0; // source texsize (.xy), and inverse (.zw)
  1494. //float4 _c1; // w1..w4
  1495. //float4 _c2; // d1..d4
  1496. //float4 _c3; // scale, bias, w_div, 0
  1497. //-------------------------------------
  1498. if (h[0]) pCT->SetVector( lpDevice, h[0], &srctexsize );
  1499. if (h[1]) pCT->SetVector( lpDevice, h[1], &D3DXVECTOR4( w1,w2,w3,w4 ));
  1500. if (h[2]) pCT->SetVector( lpDevice, h[2], &D3DXVECTOR4( d1,d2,d3,d4 ));
  1501. if (h[3]) pCT->SetVector( lpDevice, h[3], &D3DXVECTOR4( fscale_now,fbias_now,w_div,0));
  1502. }
  1503. else
  1504. {
  1505. // pass 2 (short vertical pass)
  1506. //-------------------------------------
  1507. const float w1 = w[0]+w[1] + w[2]+w[3];
  1508. const float w2 = w[4]+w[5] + w[6]+w[7];
  1509. const float d1 = 0 + 2*((w[2]+w[3])/w1);
  1510. const float d2 = 2 + 2*((w[6]+w[7])/w2);
  1511. const float w_div = 1.0f/((w1+w2)*2);
  1512. //-------------------------------------
  1513. //float4 _c0; // source texsize (.xy), and inverse (.zw)
  1514. //float4 _c5; // w1,w2,d1,d2
  1515. //float4 _c6; // w_div, edge_darken_c1, edge_darken_c2, edge_darken_c3
  1516. //-------------------------------------
  1517. if (h[0]) pCT->SetVector( lpDevice, h[0], &srctexsize );
  1518. if (h[5]) pCT->SetVector( lpDevice, h[5], &D3DXVECTOR4( w1,w2,d1,d2 ));
  1519. if (h[6])
  1520. {
  1521. // note: only do this first time; if you do it many times,
  1522. // then the super-blurred levels will have big black lines along the top & left sides.
  1523. if (i==1)
  1524. pCT->SetVector( lpDevice, h[6], &D3DXVECTOR4( w_div,(1-edge_darken),edge_darken,5.0f )); //darken edges
  1525. else
  1526. pCT->SetVector( lpDevice, h[6], &D3DXVECTOR4( w_div,1.0f,0.0f,5.0f )); // don't darken
  1527. }
  1528. }
  1529. // draw fullscreen quad
  1530. lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, v, sizeof(MYVERTEX));
  1531. // clear texture bindings
  1532. lpDevice->SetTexture(0, NULL);
  1533. }
  1534. lpDevice->SetRenderTarget(0, pBackBuffer);
  1535. pBackBuffer->Release();
  1536. lpDevice->SetPixelShader( NULL );
  1537. lpDevice->SetVertexShader( NULL );
  1538. lpDevice->SetTexture(0, NULL);
  1539. lpDevice->SetFVF( MYVERTEX_FORMAT );
  1540. #endif
  1541. m_nHighestBlurTexUsedThisFrame = 0;
  1542. }
  1543. void CPlugin::ComputeGridAlphaValues()
  1544. {
  1545. float fBlend = m_pState->m_fBlendProgress;//max(0,min(1,(m_pState->m_fBlendProgress*1.6f - 0.3f)));
  1546. /*switch(code) //if (nPassOverride==0)
  1547. {
  1548. //case 8:
  1549. //case 9:
  1550. //case 12:
  1551. //case 13:
  1552. // note - these are the 4 cases where the old preset uses a warp shader, but new preset doesn't.
  1553. fBlend = 1-fBlend; // <-- THIS IS THE KEY - FLIPS THE ALPHAS AND EVERYTHING ELSE JUST WORKS.
  1554. break;
  1555. }*/
  1556. //fBlend = 1-fBlend; // <-- THIS IS THE KEY - FLIPS THE ALPHAS AND EVERYTHING ELSE JUST WORKS.
  1557. bool bBlending = m_pState->m_bBlending;//(fBlend >= 0.0001f && fBlend <= 0.9999f);
  1558. // warp stuff
  1559. float fWarpTime = GetTime() * m_pState->m_fWarpAnimSpeed;
  1560. float fWarpScaleInv = 1.0f / m_pState->m_fWarpScale.eval(GetTime());
  1561. float f[4];
  1562. f[0] = 11.68f + 4.0f*cosf(fWarpTime*1.413f + 10);
  1563. f[1] = 8.77f + 3.0f*cosf(fWarpTime*1.113f + 7);
  1564. f[2] = 10.54f + 3.0f*cosf(fWarpTime*1.233f + 3);
  1565. f[3] = 11.49f + 4.0f*cosf(fWarpTime*0.933f + 5);
  1566. // texel alignment
  1567. float texel_offset_x = 0.5f / (float)m_nTexSizeX;
  1568. float texel_offset_y = 0.5f / (float)m_nTexSizeY;
  1569. int num_reps = (m_pState->m_bBlending) ? 2 : 1;
  1570. int start_rep = 0;
  1571. // FIRST WE HAVE 1-2 PASSES FOR CRUNCHING THE PER-VERTEX EQUATIONS
  1572. for (int rep=start_rep; rep<num_reps; rep++)
  1573. {
  1574. // to blend the two PV equations together, we simulate both to get the final UV coords,
  1575. // then we blend those final UV coords. We also write out an alpha value so that
  1576. // the second DRAW pass below (which might use a different shader) can do blending.
  1577. CState *pState;
  1578. if (rep==0)
  1579. pState = m_pState;
  1580. else
  1581. pState = m_pOldState;
  1582. // cache the doubles as floats so that computations are a bit faster
  1583. float fZoom = (float)(*pState->var_pf_zoom);
  1584. float fZoomExp = (float)(*pState->var_pf_zoomexp);
  1585. float fRot = (float)(*pState->var_pf_rot);
  1586. float fWarp = (float)(*pState->var_pf_warp);
  1587. float fCX = (float)(*pState->var_pf_cx);
  1588. float fCY = (float)(*pState->var_pf_cy);
  1589. float fDX = (float)(*pState->var_pf_dx);
  1590. float fDY = (float)(*pState->var_pf_dy);
  1591. float fSX = (float)(*pState->var_pf_sx);
  1592. float fSY = (float)(*pState->var_pf_sy);
  1593. int n = 0;
  1594. for (int y=0; y<=m_nGridY; y++)
  1595. {
  1596. for (int x=0; x<=m_nGridX; x++)
  1597. {
  1598. // Note: x, y, z are now set at init. time - no need to mess with them!
  1599. //m_verts[n].x = i/(float)m_nGridX*2.0f - 1.0f;
  1600. //m_verts[n].y = j/(float)m_nGridY*2.0f - 1.0f;
  1601. //m_verts[n].z = 0.0f;
  1602. if (pState->m_pp_codehandle)
  1603. {
  1604. // restore all the variables to their original states,
  1605. // run the user-defined equations,
  1606. // then move the results into local vars for computation as floats
  1607. *pState->var_pv_x = (double)(m_verts[n].x* 0.5f*m_fAspectX + 0.5f);
  1608. *pState->var_pv_y = (double)(m_verts[n].y*-0.5f*m_fAspectY + 0.5f);
  1609. *pState->var_pv_rad = (double)m_vertinfo[n].rad;
  1610. *pState->var_pv_ang = (double)m_vertinfo[n].ang;
  1611. *pState->var_pv_zoom = *pState->var_pf_zoom;
  1612. *pState->var_pv_zoomexp = *pState->var_pf_zoomexp;
  1613. *pState->var_pv_rot = *pState->var_pf_rot;
  1614. *pState->var_pv_warp = *pState->var_pf_warp;
  1615. *pState->var_pv_cx = *pState->var_pf_cx;
  1616. *pState->var_pv_cy = *pState->var_pf_cy;
  1617. *pState->var_pv_dx = *pState->var_pf_dx;
  1618. *pState->var_pv_dy = *pState->var_pf_dy;
  1619. *pState->var_pv_sx = *pState->var_pf_sx;
  1620. *pState->var_pv_sy = *pState->var_pf_sy;
  1621. //*pState->var_pv_time = *pState->var_pv_time; // (these are all now initialized
  1622. //*pState->var_pv_bass = *pState->var_pv_bass; // just once per frame)
  1623. //*pState->var_pv_mid = *pState->var_pv_mid;
  1624. //*pState->var_pv_treb = *pState->var_pv_treb;
  1625. //*pState->var_pv_bass_att = *pState->var_pv_bass_att;
  1626. //*pState->var_pv_mid_att = *pState->var_pv_mid_att;
  1627. //*pState->var_pv_treb_att = *pState->var_pv_treb_att;
  1628. #ifndef _NO_EXPR_
  1629. NSEEL_code_execute(pState->m_pp_codehandle);
  1630. #endif
  1631. fZoom = (float)(*pState->var_pv_zoom);
  1632. fZoomExp = (float)(*pState->var_pv_zoomexp);
  1633. fRot = (float)(*pState->var_pv_rot);
  1634. fWarp = (float)(*pState->var_pv_warp);
  1635. fCX = (float)(*pState->var_pv_cx);
  1636. fCY = (float)(*pState->var_pv_cy);
  1637. fDX = (float)(*pState->var_pv_dx);
  1638. fDY = (float)(*pState->var_pv_dy);
  1639. fSX = (float)(*pState->var_pv_sx);
  1640. fSY = (float)(*pState->var_pv_sy);
  1641. }
  1642. float fZoom2 = powf(fZoom, powf(fZoomExp, m_vertinfo[n].rad*2.0f - 1.0f));
  1643. // initial texcoords, w/built-in zoom factor
  1644. float fZoom2Inv = 1.0f/fZoom2;
  1645. float u = m_verts[n].x*m_fAspectX*0.5f*fZoom2Inv + 0.5f;
  1646. float v = -m_verts[n].y*m_fAspectY*0.5f*fZoom2Inv + 0.5f;
  1647. //float u_orig = u;
  1648. //float v_orig = v;
  1649. //m_verts[n].tr = u_orig + texel_offset_x;
  1650. //m_verts[n].ts = v_orig + texel_offset_y;
  1651. // stretch on X, Y:
  1652. u = (u - fCX)/fSX + fCX;
  1653. v = (v - fCY)/fSY + fCY;
  1654. // warping:
  1655. //if (fWarp > 0.001f || fWarp < -0.001f)
  1656. //{
  1657. u += fWarp*0.0035f*sinf(fWarpTime*0.333f + fWarpScaleInv*(m_verts[n].x*f[0] - m_verts[n].y*f[3]));
  1658. v += fWarp*0.0035f*cosf(fWarpTime*0.375f - fWarpScaleInv*(m_verts[n].x*f[2] + m_verts[n].y*f[1]));
  1659. u += fWarp*0.0035f*cosf(fWarpTime*0.753f - fWarpScaleInv*(m_verts[n].x*f[1] - m_verts[n].y*f[2]));
  1660. v += fWarp*0.0035f*sinf(fWarpTime*0.825f + fWarpScaleInv*(m_verts[n].x*f[0] + m_verts[n].y*f[3]));
  1661. //}
  1662. // rotation:
  1663. float u2 = u - fCX;
  1664. float v2 = v - fCY;
  1665. float cos_rot = cosf(fRot);
  1666. float sin_rot = sinf(fRot);
  1667. u = u2*cos_rot - v2*sin_rot + fCX;
  1668. v = u2*sin_rot + v2*cos_rot + fCY;
  1669. // translation:
  1670. u -= fDX;
  1671. v -= fDY;
  1672. // undo aspect ratio fix:
  1673. u = (u-0.5f)*m_fInvAspectX + 0.5f;
  1674. v = (v-0.5f)*m_fInvAspectY + 0.5f;
  1675. // final half-texel-offset translation:
  1676. u += texel_offset_x;
  1677. v += texel_offset_y;
  1678. if (rep==0)
  1679. {
  1680. // UV's for m_pState
  1681. m_verts[n].tu = u;
  1682. m_verts[n].tv = v;
  1683. m_verts[n].Diffuse = 0xFFFFFFFF;
  1684. }
  1685. else
  1686. {
  1687. // blend to UV's for m_pOldState
  1688. float mix2 = m_vertinfo[n].a*fBlend + m_vertinfo[n].c;//fCosineBlend2;
  1689. mix2 = max(0,min(1,mix2));
  1690. // if fBlend un-flipped, then mix2 is 0 at the beginning of a blend, 1 at the end...
  1691. // and alphas are 0 at the beginning, 1 at the end.
  1692. m_verts[n].tu = m_verts[n].tu*(mix2) + u*(1-mix2);
  1693. m_verts[n].tv = m_verts[n].tv*(mix2) + v*(1-mix2);
  1694. // this sets the alpha values for blending between two presets:
  1695. m_verts[n].Diffuse = 0x00FFFFFF | (((DWORD)(mix2*255))<<24);
  1696. }
  1697. n++;
  1698. }
  1699. }
  1700. }
  1701. }
  1702. void CPlugin::WarpedBlit_NoShaders(int nPass, bool bAlphaBlend, bool bFlipAlpha, bool bCullTiles, bool bFlipCulling)
  1703. {
  1704. MungeFPCW(NULL); // puts us in single-precision mode & disables exceptions
  1705. LPDIRECT3DDEVICE9 lpDevice = GetDevice();
  1706. if (!lpDevice)
  1707. return;
  1708. if (!wcscmp(m_pState->m_szDesc, INVALID_PRESET_DESC))
  1709. {
  1710. // if no valid preset loaded, clear the target to black, and return
  1711. lpDevice->Clear(0, NULL, D3DCLEAR_TARGET, 0x00000000, 1.0f, 0);
  1712. return;
  1713. }
  1714. lpDevice->SetTexture(0, m_lpVS[0]);
  1715. lpDevice->SetVertexShader( NULL );
  1716. lpDevice->SetPixelShader( NULL );
  1717. lpDevice->SetFVF( MYVERTEX_FORMAT );
  1718. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  1719. // stages 0 and 1 always just use bilinear filtering.
  1720. lpDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
  1721. lpDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
  1722. lpDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
  1723. lpDevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
  1724. lpDevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
  1725. lpDevice->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
  1726. // note: this texture stage state setup works for 0 or 1 texture.
  1727. // if you set a texture, it will be modulated with the current diffuse color.
  1728. // if you don't set a texture, it will just use the current diffuse color.
  1729. lpDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
  1730. lpDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
  1731. lpDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE);
  1732. lpDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
  1733. lpDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
  1734. lpDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE );
  1735. lpDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
  1736. DWORD texaddr = (*m_pState->var_pf_wrap > m_fSnapPoint) ? D3DTADDRESS_WRAP : D3DTADDRESS_CLAMP;
  1737. lpDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, texaddr);
  1738. lpDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, texaddr);
  1739. lpDevice->SetSamplerState(0, D3DSAMP_ADDRESSW, texaddr);
  1740. // decay
  1741. float fDecay = (float)(*m_pState->var_pf_decay);
  1742. //if (m_pState->m_bBlending)
  1743. // fDecay = fDecay*(fCosineBlend) + (1.0f-fCosineBlend)*((float)(*m_pOldState->var_pf_decay));
  1744. if (m_n16BitGamma > 0 &&
  1745. (GetBackBufFormat()==D3DFMT_R5G6B5 || GetBackBufFormat()==D3DFMT_X1R5G5B5 || GetBackBufFormat()==D3DFMT_A1R5G5B5 || GetBackBufFormat()==D3DFMT_A4R4G4B4) &&
  1746. fDecay < 0.9999f)
  1747. {
  1748. fDecay = min(fDecay, (32.0f - m_n16BitGamma)/32.0f);
  1749. }
  1750. D3DCOLOR cDecay = D3DCOLOR_RGBA_01(fDecay,fDecay,fDecay,1);
  1751. // hurl the triangle strips at the video card
  1752. int poly;
  1753. for (poly=0; poly<(m_nGridX+1)*2; poly++)
  1754. m_verts_temp[poly].Diffuse = cDecay;
  1755. if (bAlphaBlend)
  1756. {
  1757. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  1758. if (bFlipAlpha)
  1759. {
  1760. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_INVSRCALPHA);
  1761. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_SRCALPHA);
  1762. }
  1763. else
  1764. {
  1765. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
  1766. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
  1767. }
  1768. }
  1769. else
  1770. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  1771. int nAlphaTestValue = 0;
  1772. if (bFlipCulling)
  1773. nAlphaTestValue = 1-nAlphaTestValue;
  1774. // Hurl the triangles at the video card.
  1775. // We're going to un-index it, so that we don't stress any crappy (AHEM intel g33)
  1776. // drivers out there.
  1777. // If we're blending, we'll skip any polygon that is all alpha-blended out.
  1778. // This also respects the MaxPrimCount limit of the video card.
  1779. MYVERTEX tempv[1024 * 3];
  1780. int max_prims_per_batch = min( GetCaps()->MaxPrimitiveCount, (sizeof(tempv)/sizeof(tempv[0]))/3) - 4;
  1781. int primCount = m_nGridX*m_nGridY*2;
  1782. int src_idx = 0;
  1783. int prims_sent = 0;
  1784. while (src_idx < primCount*3)
  1785. {
  1786. int prims_queued = 0;
  1787. int i=0;
  1788. while (prims_queued < max_prims_per_batch && src_idx < primCount*3)
  1789. {
  1790. // copy 3 verts
  1791. for (int j=0; j<3; j++)
  1792. {
  1793. tempv[i++] = m_verts[ m_indices_list[src_idx++] ];
  1794. // don't forget to flip sign on Y and factor in the decay color!:
  1795. tempv[i-1].y *= -1;
  1796. tempv[i-1].Diffuse = (cDecay & 0x00FFFFFF) | (tempv[i-1].Diffuse & 0xFF000000);
  1797. }
  1798. if (bCullTiles)
  1799. {
  1800. DWORD d1 = (tempv[i-3].Diffuse >> 24);
  1801. DWORD d2 = (tempv[i-2].Diffuse >> 24);
  1802. DWORD d3 = (tempv[i-1].Diffuse >> 24);
  1803. bool bIsNeeded;
  1804. if (nAlphaTestValue)
  1805. bIsNeeded = ((d1 & d2 & d3) < 255);//(d1 < 255) || (d2 < 255) || (d3 < 255);
  1806. else
  1807. bIsNeeded = ((d1|d2|d3) > 0);//(d1 > 0) || (d2 > 0) || (d3 > 0);
  1808. if (!bIsNeeded)
  1809. i -= 3;
  1810. else
  1811. prims_queued++;
  1812. }
  1813. else
  1814. prims_queued++;
  1815. }
  1816. if (prims_queued > 0)
  1817. lpDevice->DrawPrimitiveUP( D3DPT_TRIANGLELIST, prims_queued, tempv, sizeof(MYVERTEX) );
  1818. }
  1819. /*
  1820. if (!bCullTiles)
  1821. {
  1822. assert(!bAlphaBlend); //not handled yet
  1823. // draw normally - just a full triangle strip for each half-row of cells
  1824. // (even if we are blending, it is between two pre-pixel-shader presets,
  1825. // so the blend all happens exclusively in the per-vertex equations.)
  1826. for (int strip=0; strip<m_nGridY*2; strip++)
  1827. {
  1828. int index = strip * (m_nGridX+2);
  1829. for (poly=0; poly<m_nGridX+2; poly++)
  1830. {
  1831. int ref_vert = m_indices_strip[index];
  1832. m_verts_temp[poly].x = m_verts[ref_vert].x;
  1833. m_verts_temp[poly].y = -m_verts[ref_vert].y;
  1834. m_verts_temp[poly].z = m_verts[ref_vert].z;
  1835. m_verts_temp[poly].tu = m_verts[ref_vert].tu;
  1836. m_verts_temp[poly].tv = m_verts[ref_vert].tv;
  1837. //m_verts_temp[poly].Diffuse = cDecay; this is done just once - see jsut above
  1838. index++;
  1839. }
  1840. lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, m_nGridX, (void*)m_verts_temp, sizeof(MYVERTEX));
  1841. }
  1842. }
  1843. else
  1844. {
  1845. // we're blending to/from a new pixel-shader enabled preset;
  1846. // only draw the cells needed! (an optimization)
  1847. int nAlphaTestValue = 0;
  1848. if (bFlipCulling)
  1849. nAlphaTestValue = 1-nAlphaTestValue;
  1850. int idx[2048];
  1851. for (int y=0; y<m_nGridY; y++)
  1852. {
  1853. // copy verts & flip sign on Y
  1854. int ref_vert = y*(m_nGridX+1);
  1855. for (int i=0; i<(m_nGridX+1)*2; i++)
  1856. {
  1857. m_verts_temp[i].x = m_verts[ref_vert].x;
  1858. m_verts_temp[i].y = -m_verts[ref_vert].y;
  1859. m_verts_temp[i].z = m_verts[ref_vert].z;
  1860. m_verts_temp[i].tu = m_verts[ref_vert].tu;
  1861. m_verts_temp[i].tv = m_verts[ref_vert].tv;
  1862. m_verts_temp[i].Diffuse = (cDecay & 0x00FFFFFF) | (m_verts[ref_vert].Diffuse & 0xFF000000);
  1863. ref_vert++;
  1864. }
  1865. // create (smart) indices
  1866. int count = 0;
  1867. int nVert = 0;
  1868. bool bWasNeeded;
  1869. ref_vert = (y)*(m_nGridX+1);
  1870. DWORD d1 = (m_verts[ref_vert ].Diffuse >> 24);
  1871. DWORD d2 = (m_verts[ref_vert+m_nGridX+1].Diffuse >> 24);
  1872. if (nAlphaTestValue)
  1873. bWasNeeded = (d1 < 255) || (d2 < 255);
  1874. else
  1875. bWasNeeded = (d1 > 0) || (d2 > 0);
  1876. for (i=0; i<m_nGridX; i++)
  1877. {
  1878. bool bIsNeeded;
  1879. DWORD d1 = (m_verts[ref_vert+1 ].Diffuse >> 24);
  1880. DWORD d2 = (m_verts[ref_vert+1+m_nGridX+1].Diffuse >> 24);
  1881. if (nAlphaTestValue)
  1882. bIsNeeded = (d1 < 255) || (d2 < 255);
  1883. else
  1884. bIsNeeded = (d1 > 0) || (d2 > 0);
  1885. if (bIsNeeded || bWasNeeded)
  1886. {
  1887. idx[count++] = nVert;
  1888. idx[count++] = nVert+1;
  1889. idx[count++] = nVert+m_nGridX+1;
  1890. idx[count++] = nVert+m_nGridX+1;
  1891. idx[count++] = nVert+1;
  1892. idx[count++] = nVert+m_nGridX+2;
  1893. }
  1894. bWasNeeded = bIsNeeded;
  1895. nVert++;
  1896. ref_vert++;
  1897. }
  1898. lpDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, (m_nGridX+1)*2, count/3, (void*)idx, D3DFMT_INDEX32, (void*)m_verts_temp, sizeof(MYVERTEX));
  1899. }
  1900. }/**/
  1901. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  1902. }
  1903. void CPlugin::WarpedBlit_Shaders(int nPass, bool bAlphaBlend, bool bFlipAlpha, bool bCullTiles, bool bFlipCulling)
  1904. {
  1905. // if nPass==0, it draws old preset (blending 1 of 2).
  1906. // if nPass==1, it draws new preset (blending 2 of 2, OR done blending)
  1907. MungeFPCW(NULL); // puts us in single-precision mode & disables exceptions
  1908. LPDIRECT3DDEVICE9 lpDevice = GetDevice();
  1909. if (!lpDevice)
  1910. return;
  1911. if (!wcscmp(m_pState->m_szDesc, INVALID_PRESET_DESC))
  1912. {
  1913. // if no valid preset loaded, clear the target to black, and return
  1914. lpDevice->Clear(0, NULL, D3DCLEAR_TARGET, 0x00000000, 1.0f, 0);
  1915. return;
  1916. }
  1917. //float fBlend = m_pState->m_fBlendProgress;//max(0,min(1,(m_pState->m_fBlendProgress*1.6f - 0.3f)));
  1918. //if (nPassOverride==0)
  1919. // fBlend = 1-fBlend; // <-- THIS IS THE KEY - FLIPS THE ALPHAS AND EVERYTHING ELSE JUST WORKS.
  1920. //bool bBlending = m_pState->m_bBlending;//(fBlend >= 0.0001f && fBlend <= 0.9999f);
  1921. //lpDevice->SetTexture(0, m_lpVS[0]);
  1922. lpDevice->SetVertexShader( NULL );
  1923. lpDevice->SetFVF( MYVERTEX_FORMAT );
  1924. // texel alignment
  1925. float texel_offset_x = 0.5f / (float)m_nTexSizeX;
  1926. float texel_offset_y = 0.5f / (float)m_nTexSizeY;
  1927. int nAlphaTestValue = 0;
  1928. if (bFlipCulling)
  1929. nAlphaTestValue = 1-nAlphaTestValue;
  1930. if (bAlphaBlend)
  1931. {
  1932. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  1933. if (bFlipAlpha)
  1934. {
  1935. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_INVSRCALPHA);
  1936. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_SRCALPHA);
  1937. }
  1938. else
  1939. {
  1940. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
  1941. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
  1942. }
  1943. }
  1944. else
  1945. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  1946. int pass = nPass;
  1947. {
  1948. // PASS 0: draw using *blended per-vertex motion vectors*, but with the OLD warp shader.
  1949. // PASS 1: draw using *blended per-vertex motion vectors*, but with the NEW warp shader.
  1950. PShaderInfo* si = (pass==0) ? &m_OldShaders.warp : &m_shaders.warp;
  1951. CState* state = (pass==0) ? m_pOldState : m_pState;
  1952. lpDevice->SetVertexDeclaration(m_pMyVertDecl);
  1953. lpDevice->SetVertexShader(m_fallbackShaders_vs.warp.ptr);
  1954. lpDevice->SetPixelShader (si->ptr);
  1955. ApplyShaderParams( &(si->params), si->CT, state );
  1956. // Hurl the triangles at the video card.
  1957. // We're going to un-index it, so that we don't stress any crappy (AHEM intel g33)
  1958. // drivers out there.
  1959. // We divide it into the two halves of the screen (top/bottom) so we can hack
  1960. // the 'ang' values along the angle-wrap seam, halfway through the draw.
  1961. // If we're blending, we'll skip any polygon that is all alpha-blended out.
  1962. // This also respects the MaxPrimCount limit of the video card.
  1963. MYVERTEX tempv[1024 * 3];
  1964. int max_prims_per_batch = min( GetCaps()->MaxPrimitiveCount, (sizeof(tempv)/sizeof(tempv[0]))/3) - 4;
  1965. for (int half=0; half<2; half++)
  1966. {
  1967. // hack / restore the ang values along the angle-wrap [0 <-> 2pi] seam...
  1968. float new_ang = half ? 3.1415926535897932384626433832795f : -3.1415926535897932384626433832795f;
  1969. int y_offset = (m_nGridY/2) * (m_nGridX+1);
  1970. for (int x=0; x<m_nGridX/2; x++)
  1971. m_verts[y_offset + x].ang = new_ang;
  1972. // send half of the polys
  1973. int primCount = m_nGridX*m_nGridY*2 / 2; // in this case, to draw HALF the polys
  1974. int src_idx = 0;
  1975. int src_idx_offset = half * primCount*3;
  1976. int prims_sent = 0;
  1977. while (src_idx < primCount*3)
  1978. {
  1979. int prims_queued = 0;
  1980. int i=0;
  1981. while (prims_queued < max_prims_per_batch && src_idx < primCount*3)
  1982. {
  1983. // copy 3 verts
  1984. for (int j=0; j<3; j++)
  1985. tempv[i++] = m_verts[ m_indices_list[src_idx_offset + src_idx++] ];
  1986. if (bCullTiles)
  1987. {
  1988. DWORD d1 = (tempv[i-3].Diffuse >> 24);
  1989. DWORD d2 = (tempv[i-2].Diffuse >> 24);
  1990. DWORD d3 = (tempv[i-1].Diffuse >> 24);
  1991. bool bIsNeeded;
  1992. if (nAlphaTestValue)
  1993. bIsNeeded = ((d1 & d2 & d3) < 255);//(d1 < 255) || (d2 < 255) || (d3 < 255);
  1994. else
  1995. bIsNeeded = ((d1|d2|d3) > 0);//(d1 > 0) || (d2 > 0) || (d3 > 0);
  1996. if (!bIsNeeded)
  1997. i -= 3;
  1998. else
  1999. prims_queued++;
  2000. }
  2001. else
  2002. prims_queued++;
  2003. }
  2004. if (prims_queued > 0)
  2005. lpDevice->DrawPrimitiveUP( D3DPT_TRIANGLELIST, prims_queued, tempv, sizeof(MYVERTEX) );
  2006. }
  2007. }
  2008. }
  2009. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  2010. RestoreShaderParams();
  2011. }
  2012. void CPlugin::DrawCustomShapes()
  2013. {
  2014. LPDIRECT3DDEVICE9 lpDevice = GetDevice();
  2015. if (!lpDevice)
  2016. return;
  2017. //lpDevice->SetTexture(0, m_lpVS[0]);//NULL);
  2018. //lpDevice->SetVertexShader( SPRITEVERTEX_FORMAT );
  2019. int num_reps = (m_pState->m_bBlending) ? 2 : 1;
  2020. for (int rep=0; rep<num_reps; rep++)
  2021. {
  2022. CState *pState = (rep==0) ? m_pState : m_pOldState;
  2023. float alpha_mult = 1;
  2024. if (num_reps==2)
  2025. alpha_mult = (rep==0) ? m_pState->m_fBlendProgress : (1-m_pState->m_fBlendProgress);
  2026. for (int i=0; i<MAX_CUSTOM_SHAPES; i++)
  2027. {
  2028. if (pState->m_shape[i].enabled)
  2029. {
  2030. /*
  2031. int bAdditive = 0;
  2032. int nSides = 3;//3 + ((int)GetTime() % 8);
  2033. int bThickOutline = 0;
  2034. float x = 0.5f + 0.1f*cosf(GetTime()*0.8f+1);
  2035. float y = 0.5f + 0.1f*sinf(GetTime()*0.8f+1);
  2036. float rad = 0.15f + 0.07f*sinf(GetTime()*1.1f+3);
  2037. float ang = GetTime()*1.5f;
  2038. // inside colors
  2039. float r = 1;
  2040. float g = 0;
  2041. float b = 0;
  2042. float a = 0.4f;//0.1f + 0.1f*sinf(GetTime()*0.31f);
  2043. // outside colors
  2044. float r2 = 0;
  2045. float g2 = 1;
  2046. float b2 = 0;
  2047. float a2 = 0;
  2048. // border colors
  2049. float border_r = 1;
  2050. float border_g = 1;
  2051. float border_b = 1;
  2052. float border_a = 0.5f;
  2053. */
  2054. for (int instance=0; instance<pState->m_shape[i].instances; instance++)
  2055. {
  2056. // 1. execute per-frame code
  2057. LoadCustomShapePerFrameEvallibVars(pState, i, instance);
  2058. #ifndef _NO_EXPR_
  2059. if (pState->m_shape[i].m_pf_codehandle)
  2060. {
  2061. NSEEL_code_execute(pState->m_shape[i].m_pf_codehandle);
  2062. }
  2063. #endif
  2064. // save changes to t1-t8 this frame
  2065. /*
  2066. pState->m_shape[i].t_values_after_init_code[0] = *pState->m_shape[i].var_pf_t1;
  2067. pState->m_shape[i].t_values_after_init_code[1] = *pState->m_shape[i].var_pf_t2;
  2068. pState->m_shape[i].t_values_after_init_code[2] = *pState->m_shape[i].var_pf_t3;
  2069. pState->m_shape[i].t_values_after_init_code[3] = *pState->m_shape[i].var_pf_t4;
  2070. pState->m_shape[i].t_values_after_init_code[4] = *pState->m_shape[i].var_pf_t5;
  2071. pState->m_shape[i].t_values_after_init_code[5] = *pState->m_shape[i].var_pf_t6;
  2072. pState->m_shape[i].t_values_after_init_code[6] = *pState->m_shape[i].var_pf_t7;
  2073. pState->m_shape[i].t_values_after_init_code[7] = *pState->m_shape[i].var_pf_t8;
  2074. */
  2075. int sides = (int)(*pState->m_shape[i].var_pf_sides);
  2076. if (sides<3) sides=3;
  2077. if (sides>100) sides=100;
  2078. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  2079. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
  2080. lpDevice->SetRenderState(D3DRS_DESTBLEND, ((int)(*pState->m_shape[i].var_pf_additive) != 0) ? D3DBLEND_ONE : D3DBLEND_INVSRCALPHA);
  2081. SPRITEVERTEX v[512]; // for textured shapes (has texcoords)
  2082. WFVERTEX v2[512]; // for untextured shapes + borders
  2083. v[0].x = (float)(*pState->m_shape[i].var_pf_x* 2-1);// * ASPECT;
  2084. v[0].y = (float)(*pState->m_shape[i].var_pf_y*-2+1);
  2085. v[0].z = 0;
  2086. v[0].tu = 0.5f;
  2087. v[0].tv = 0.5f;
  2088. v[0].Diffuse =
  2089. ((((int)(*pState->m_shape[i].var_pf_a * 255 * alpha_mult)) & 0xFF) << 24) |
  2090. ((((int)(*pState->m_shape[i].var_pf_r * 255)) & 0xFF) << 16) |
  2091. ((((int)(*pState->m_shape[i].var_pf_g * 255)) & 0xFF) << 8) |
  2092. ((((int)(*pState->m_shape[i].var_pf_b * 255)) & 0xFF) );
  2093. v[1].Diffuse =
  2094. ((((int)(*pState->m_shape[i].var_pf_a2 * 255 * alpha_mult)) & 0xFF) << 24) |
  2095. ((((int)(*pState->m_shape[i].var_pf_r2 * 255)) & 0xFF) << 16) |
  2096. ((((int)(*pState->m_shape[i].var_pf_g2 * 255)) & 0xFF) << 8) |
  2097. ((((int)(*pState->m_shape[i].var_pf_b2 * 255)) & 0xFF) );
  2098. int j = 1;
  2099. for (j=1; j<sides+1; j++)
  2100. {
  2101. float t = (j-1)/(float)sides;
  2102. v[j].x = v[0].x + (float)*pState->m_shape[i].var_pf_rad*cosf(t*3.1415927f*2 + (float)*pState->m_shape[i].var_pf_ang + 3.1415927f*0.25f)*m_fAspectY; // DON'T TOUCH!
  2103. v[j].y = v[0].y + (float)*pState->m_shape[i].var_pf_rad*sinf(t*3.1415927f*2 + (float)*pState->m_shape[i].var_pf_ang + 3.1415927f*0.25f); // DON'T TOUCH!
  2104. v[j].z = 0;
  2105. v[j].tu = 0.5f + 0.5f*cosf(t*3.1415927f*2 + (float)*pState->m_shape[i].var_pf_tex_ang + 3.1415927f*0.25f)/((float)*pState->m_shape[i].var_pf_tex_zoom) * m_fAspectY; // DON'T TOUCH!
  2106. v[j].tv = 0.5f + 0.5f*sinf(t*3.1415927f*2 + (float)*pState->m_shape[i].var_pf_tex_ang + 3.1415927f*0.25f)/((float)*pState->m_shape[i].var_pf_tex_zoom); // DON'T TOUCH!
  2107. v[j].Diffuse = v[1].Diffuse;
  2108. }
  2109. v[sides+1] = v[1];
  2110. if ((int)(*pState->m_shape[i].var_pf_textured) != 0)
  2111. {
  2112. // draw textured version
  2113. lpDevice->SetTexture(0, m_lpVS[0]);
  2114. lpDevice->SetVertexShader( NULL );
  2115. lpDevice->SetFVF( SPRITEVERTEX_FORMAT );
  2116. lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, sides, (void*)v, sizeof(SPRITEVERTEX));
  2117. }
  2118. else
  2119. {
  2120. // no texture
  2121. for (j=0; j < sides+2; j++)
  2122. {
  2123. v2[j].x = v[j].x;
  2124. v2[j].y = v[j].y;
  2125. v2[j].z = v[j].z;
  2126. v2[j].Diffuse = v[j].Diffuse;
  2127. }
  2128. lpDevice->SetTexture(0, NULL);
  2129. lpDevice->SetVertexShader( NULL );
  2130. lpDevice->SetFVF( WFVERTEX_FORMAT );
  2131. lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, sides, (void*)v2, sizeof(WFVERTEX));
  2132. }
  2133. // DRAW BORDER
  2134. if (*pState->m_shape[i].var_pf_border_a > 0)
  2135. {
  2136. lpDevice->SetTexture(0, NULL);
  2137. lpDevice->SetVertexShader( NULL );
  2138. lpDevice->SetFVF( WFVERTEX_FORMAT );
  2139. v2[0].Diffuse =
  2140. ((((int)(*pState->m_shape[i].var_pf_border_a * 255 * alpha_mult)) & 0xFF) << 24) |
  2141. ((((int)(*pState->m_shape[i].var_pf_border_r * 255)) & 0xFF) << 16) |
  2142. ((((int)(*pState->m_shape[i].var_pf_border_g * 255)) & 0xFF) << 8) |
  2143. ((((int)(*pState->m_shape[i].var_pf_border_b * 255)) & 0xFF) );
  2144. for (j=0; j<sides+2; j++)
  2145. {
  2146. v2[j].x = v[j].x;
  2147. v2[j].y = v[j].y;
  2148. v2[j].z = v[j].z;
  2149. v2[j].Diffuse = v2[0].Diffuse;
  2150. }
  2151. int its = ((int)(*pState->m_shape[i].var_pf_thick) != 0) ? 4 : 1;
  2152. float x_inc = 2.0f / (float)m_nTexSizeX;
  2153. float y_inc = 2.0f / (float)m_nTexSizeY;
  2154. for (int it=0; it<its; it++)
  2155. {
  2156. switch(it)
  2157. {
  2158. case 0: break;
  2159. case 1: for (j=0; j<sides+2; j++) v2[j].x += x_inc; break; // draw fat dots
  2160. case 2: for (j=0; j<sides+2; j++) v2[j].y += y_inc; break; // draw fat dots
  2161. case 3: for (j=0; j<sides+2; j++) v2[j].x -= x_inc; break; // draw fat dots
  2162. }
  2163. lpDevice->DrawPrimitiveUP(D3DPT_LINESTRIP, sides, (void*)&v2[1], sizeof(WFVERTEX));
  2164. }
  2165. }
  2166. lpDevice->SetTexture(0, m_lpVS[0]);
  2167. lpDevice->SetVertexShader( NULL );
  2168. lpDevice->SetFVF( SPRITEVERTEX_FORMAT );
  2169. }
  2170. }
  2171. }
  2172. }
  2173. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  2174. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
  2175. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
  2176. }
  2177. void CPlugin::LoadCustomShapePerFrameEvallibVars(CState* pState, int i, int instance)
  2178. {
  2179. *pState->m_shape[i].var_pf_time = (double)(GetTime() - m_fStartTime);
  2180. *pState->m_shape[i].var_pf_frame = (double)GetFrame();
  2181. *pState->m_shape[i].var_pf_fps = (double)GetFps();
  2182. *pState->m_shape[i].var_pf_progress = (GetTime() - m_fPresetStartTime) / (m_fNextPresetTime - m_fPresetStartTime);
  2183. *pState->m_shape[i].var_pf_bass = (double)mysound.imm_rel[0];
  2184. *pState->m_shape[i].var_pf_mid = (double)mysound.imm_rel[1];
  2185. *pState->m_shape[i].var_pf_treb = (double)mysound.imm_rel[2];
  2186. *pState->m_shape[i].var_pf_bass_att = (double)mysound.avg_rel[0];
  2187. *pState->m_shape[i].var_pf_mid_att = (double)mysound.avg_rel[1];
  2188. *pState->m_shape[i].var_pf_treb_att = (double)mysound.avg_rel[2];
  2189. int vi = 0;
  2190. for (vi=0; vi<NUM_Q_VAR; vi++)
  2191. *pState->m_shape[i].var_pf_q[vi] = *pState->var_pf_q[vi];
  2192. for (vi=0; vi<NUM_T_VAR; vi++)
  2193. *pState->m_shape[i].var_pf_t[vi] = pState->m_shape[i].t_values_after_init_code[vi];
  2194. *pState->m_shape[i].var_pf_x = pState->m_shape[i].x;
  2195. *pState->m_shape[i].var_pf_y = pState->m_shape[i].y;
  2196. *pState->m_shape[i].var_pf_rad = pState->m_shape[i].rad;
  2197. *pState->m_shape[i].var_pf_ang = pState->m_shape[i].ang;
  2198. *pState->m_shape[i].var_pf_tex_zoom = pState->m_shape[i].tex_zoom;
  2199. *pState->m_shape[i].var_pf_tex_ang = pState->m_shape[i].tex_ang;
  2200. *pState->m_shape[i].var_pf_sides = pState->m_shape[i].sides;
  2201. *pState->m_shape[i].var_pf_additive = pState->m_shape[i].additive;
  2202. *pState->m_shape[i].var_pf_textured = pState->m_shape[i].textured;
  2203. *pState->m_shape[i].var_pf_instances = pState->m_shape[i].instances;
  2204. *pState->m_shape[i].var_pf_instance = instance;
  2205. *pState->m_shape[i].var_pf_thick = pState->m_shape[i].thickOutline;
  2206. *pState->m_shape[i].var_pf_r = pState->m_shape[i].r;
  2207. *pState->m_shape[i].var_pf_g = pState->m_shape[i].g;
  2208. *pState->m_shape[i].var_pf_b = pState->m_shape[i].b;
  2209. *pState->m_shape[i].var_pf_a = pState->m_shape[i].a;
  2210. *pState->m_shape[i].var_pf_r2 = pState->m_shape[i].r2;
  2211. *pState->m_shape[i].var_pf_g2 = pState->m_shape[i].g2;
  2212. *pState->m_shape[i].var_pf_b2 = pState->m_shape[i].b2;
  2213. *pState->m_shape[i].var_pf_a2 = pState->m_shape[i].a2;
  2214. *pState->m_shape[i].var_pf_border_r = pState->m_shape[i].border_r;
  2215. *pState->m_shape[i].var_pf_border_g = pState->m_shape[i].border_g;
  2216. *pState->m_shape[i].var_pf_border_b = pState->m_shape[i].border_b;
  2217. *pState->m_shape[i].var_pf_border_a = pState->m_shape[i].border_a;
  2218. }
  2219. void CPlugin::LoadCustomWavePerFrameEvallibVars(CState* pState, int i)
  2220. {
  2221. *pState->m_wave[i].var_pf_time = (double)(GetTime() - m_fStartTime);
  2222. *pState->m_wave[i].var_pf_frame = (double)GetFrame();
  2223. *pState->m_wave[i].var_pf_fps = (double)GetFps();
  2224. *pState->m_wave[i].var_pf_progress = (GetTime() - m_fPresetStartTime) / (m_fNextPresetTime - m_fPresetStartTime);
  2225. *pState->m_wave[i].var_pf_bass = (double)mysound.imm_rel[0];
  2226. *pState->m_wave[i].var_pf_mid = (double)mysound.imm_rel[1];
  2227. *pState->m_wave[i].var_pf_treb = (double)mysound.imm_rel[2];
  2228. *pState->m_wave[i].var_pf_bass_att = (double)mysound.avg_rel[0];
  2229. *pState->m_wave[i].var_pf_mid_att = (double)mysound.avg_rel[1];
  2230. *pState->m_wave[i].var_pf_treb_att = (double)mysound.avg_rel[2];
  2231. int vi = 0;
  2232. for (vi=0; vi<NUM_Q_VAR; vi++)
  2233. *pState->m_wave[i].var_pf_q[vi] = *pState->var_pf_q[vi];
  2234. for (vi=0; vi<NUM_T_VAR; vi++)
  2235. *pState->m_wave[i].var_pf_t[vi] = pState->m_wave[i].t_values_after_init_code[vi];
  2236. *pState->m_wave[i].var_pf_r = pState->m_wave[i].r;
  2237. *pState->m_wave[i].var_pf_g = pState->m_wave[i].g;
  2238. *pState->m_wave[i].var_pf_b = pState->m_wave[i].b;
  2239. *pState->m_wave[i].var_pf_a = pState->m_wave[i].a;
  2240. *pState->m_wave[i].var_pf_samples = pState->m_wave[i].samples;
  2241. }
  2242. // does a better-than-linear smooth on a wave. Roughly doubles the # of points.
  2243. int SmoothWave(WFVERTEX* vi, int nVertsIn, WFVERTEX* vo)
  2244. {
  2245. const float c1 = -0.15f;
  2246. const float c2 = 1.15f;
  2247. const float c3 = 1.15f;
  2248. const float c4 = -0.15f;
  2249. const float inv_sum = 1.0f/(c1+c2+c3+c4);
  2250. int j = 0;
  2251. int i_below = 0;
  2252. int i_above;
  2253. int i_above2 = 1;
  2254. for (int i=0; i<nVertsIn-1; i++)
  2255. {
  2256. i_above = i_above2;
  2257. i_above2 = min(nVertsIn-1,i+2);
  2258. vo[j] = vi[i];
  2259. vo[j+1].x = (c1*vi[i_below].x + c2*vi[i].x + c3*vi[i_above].x + c4*vi[i_above2].x)*inv_sum;
  2260. vo[j+1].y = (c1*vi[i_below].y + c2*vi[i].y + c3*vi[i_above].y + c4*vi[i_above2].y)*inv_sum;
  2261. vo[j+1].z = 0;
  2262. vo[j+1].Diffuse = vi[i].Diffuse;//0xFFFF0080;
  2263. i_below = i;
  2264. j += 2;
  2265. }
  2266. vo[j++] = vi[nVertsIn-1];
  2267. return j;
  2268. }
  2269. void CPlugin::DrawCustomWaves()
  2270. {
  2271. LPDIRECT3DDEVICE9 lpDevice = GetDevice();
  2272. if (!lpDevice)
  2273. return;
  2274. lpDevice->SetTexture(0, NULL);
  2275. lpDevice->SetVertexShader( NULL );
  2276. lpDevice->SetFVF( WFVERTEX_FORMAT );
  2277. // note: read in all sound data from CPluginShell's m_sound
  2278. int num_reps = (m_pState->m_bBlending) ? 2 : 1;
  2279. for (int rep=0; rep<num_reps; rep++)
  2280. {
  2281. CState *pState = (rep==0) ? m_pState : m_pOldState;
  2282. float alpha_mult = 1;
  2283. if (num_reps==2)
  2284. alpha_mult = (rep==0) ? m_pState->m_fBlendProgress : (1-m_pState->m_fBlendProgress);
  2285. for (int i=0; i<MAX_CUSTOM_WAVES; i++)
  2286. {
  2287. if (pState->m_wave[i].enabled)
  2288. {
  2289. int nSamples = pState->m_wave[i].samples;
  2290. int max_samples = pState->m_wave[i].bSpectrum ? 512 : NUM_WAVEFORM_SAMPLES;
  2291. if (nSamples > max_samples)
  2292. nSamples = max_samples;
  2293. nSamples -= pState->m_wave[i].sep;
  2294. // 1. execute per-frame code
  2295. LoadCustomWavePerFrameEvallibVars(pState, i);
  2296. // 2.a. do just a once-per-frame init for the *per-point* *READ-ONLY* variables
  2297. // (the non-read-only ones will be reset/restored at the start of each vertex)
  2298. *pState->m_wave[i].var_pp_time = *pState->m_wave[i].var_pf_time;
  2299. *pState->m_wave[i].var_pp_fps = *pState->m_wave[i].var_pf_fps;
  2300. *pState->m_wave[i].var_pp_frame = *pState->m_wave[i].var_pf_frame;
  2301. *pState->m_wave[i].var_pp_progress = *pState->m_wave[i].var_pf_progress;
  2302. *pState->m_wave[i].var_pp_bass = *pState->m_wave[i].var_pf_bass;
  2303. *pState->m_wave[i].var_pp_mid = *pState->m_wave[i].var_pf_mid;
  2304. *pState->m_wave[i].var_pp_treb = *pState->m_wave[i].var_pf_treb;
  2305. *pState->m_wave[i].var_pp_bass_att = *pState->m_wave[i].var_pf_bass_att;
  2306. *pState->m_wave[i].var_pp_mid_att = *pState->m_wave[i].var_pf_mid_att;
  2307. *pState->m_wave[i].var_pp_treb_att = *pState->m_wave[i].var_pf_treb_att;
  2308. NSEEL_code_execute(pState->m_wave[i].m_pf_codehandle);
  2309. int vi = 0;
  2310. for (vi=0; vi<NUM_Q_VAR; vi++)
  2311. *pState->m_wave[i].var_pp_q[vi] = *pState->m_wave[i].var_pf_q[vi];
  2312. for (vi=0; vi<NUM_T_VAR; vi++)
  2313. *pState->m_wave[i].var_pp_t[vi] = *pState->m_wave[i].var_pf_t[vi];
  2314. nSamples = (int)*pState->m_wave[i].var_pf_samples;
  2315. nSamples = min(512, nSamples);
  2316. if ((nSamples >= 2) || (pState->m_wave[i].bUseDots && nSamples >= 1))
  2317. {
  2318. int j;
  2319. float tempdata[2][512];
  2320. float mult = ((pState->m_wave[i].bSpectrum) ? 0.15f : 0.004f) * pState->m_wave[i].scaling * pState->m_fWaveScale.eval(-1);
  2321. float *pdata1 = (pState->m_wave[i].bSpectrum) ? m_sound.fSpectrum[0] : m_sound.fWaveform[0];
  2322. float *pdata2 = (pState->m_wave[i].bSpectrum) ? m_sound.fSpectrum[1] : m_sound.fWaveform[1];
  2323. // initialize tempdata[2][512]
  2324. int j0 = (pState->m_wave[i].bSpectrum) ? 0 : (max_samples - nSamples)/2/**(1-pState->m_wave[i].bSpectrum)*/ - pState->m_wave[i].sep/2;
  2325. int j1 = (pState->m_wave[i].bSpectrum) ? 0 : (max_samples - nSamples)/2/**(1-pState->m_wave[i].bSpectrum)*/ + pState->m_wave[i].sep/2;
  2326. float t = (pState->m_wave[i].bSpectrum) ? (max_samples - pState->m_wave[i].sep)/(float)nSamples : 1;
  2327. float mix1 = powf(pState->m_wave[i].smoothing*0.98f, 0.5f); // lower exponent -> more default smoothing
  2328. float mix2 = 1-mix1;
  2329. // SMOOTHING:
  2330. tempdata[0][0] = pdata1[j0];
  2331. tempdata[1][0] = pdata2[j1];
  2332. for (j=1; j<nSamples; j++)
  2333. {
  2334. tempdata[0][j] = pdata1[(int)(j*t)+j0]*mix2 + tempdata[0][j-1]*mix1;
  2335. tempdata[1][j] = pdata2[(int)(j*t)+j1]*mix2 + tempdata[1][j-1]*mix1;
  2336. }
  2337. // smooth again, backwards: [this fixes the asymmetry of the beginning & end..]
  2338. for (j=nSamples-2; j>=0; j--)
  2339. {
  2340. tempdata[0][j] = tempdata[0][j]*mix2 + tempdata[0][j+1]*mix1;
  2341. tempdata[1][j] = tempdata[1][j]*mix2 + tempdata[1][j+1]*mix1;
  2342. }
  2343. // finally, scale to final size:
  2344. for (j=0; j<nSamples; j++)
  2345. {
  2346. tempdata[0][j] *= mult;
  2347. tempdata[1][j] *= mult;
  2348. }
  2349. // 2. for each point, execute per-point code
  2350. // to do:
  2351. // -add any of the m_wave[i].xxx menu-accessible vars to the code?
  2352. WFVERTEX v[1024];
  2353. float j_mult = 1.0f/(float)(nSamples-1);
  2354. for (j=0; j<nSamples; j++)
  2355. {
  2356. float t = j*j_mult;
  2357. float value1 = tempdata[0][j];
  2358. float value2 = tempdata[1][j];
  2359. *pState->m_wave[i].var_pp_sample = t;
  2360. *pState->m_wave[i].var_pp_value1 = value1;
  2361. *pState->m_wave[i].var_pp_value2 = value2;
  2362. *pState->m_wave[i].var_pp_x = 0.5f + value1;
  2363. *pState->m_wave[i].var_pp_y = 0.5f + value2;
  2364. *pState->m_wave[i].var_pp_r = *pState->m_wave[i].var_pf_r;
  2365. *pState->m_wave[i].var_pp_g = *pState->m_wave[i].var_pf_g;
  2366. *pState->m_wave[i].var_pp_b = *pState->m_wave[i].var_pf_b;
  2367. *pState->m_wave[i].var_pp_a = *pState->m_wave[i].var_pf_a;
  2368. #ifndef _NO_EXPR_
  2369. NSEEL_code_execute(pState->m_wave[i].m_pp_codehandle);
  2370. #endif
  2371. v[j].x = (float)(*pState->m_wave[i].var_pp_x* 2-1)*m_fInvAspectX;
  2372. v[j].y = (float)(*pState->m_wave[i].var_pp_y*-2+1)*m_fInvAspectY;
  2373. v[j].z = 0;
  2374. v[j].Diffuse =
  2375. ((((int)(*pState->m_wave[i].var_pp_a * 255 * alpha_mult)) & 0xFF) << 24) |
  2376. ((((int)(*pState->m_wave[i].var_pp_r * 255)) & 0xFF) << 16) |
  2377. ((((int)(*pState->m_wave[i].var_pp_g * 255)) & 0xFF) << 8) |
  2378. ((((int)(*pState->m_wave[i].var_pp_b * 255)) & 0xFF) );
  2379. }
  2380. // save changes to t1-t8 this frame
  2381. /*
  2382. pState->m_wave[i].t_values_after_init_code[0] = *pState->m_wave[i].var_pp_t1;
  2383. pState->m_wave[i].t_values_after_init_code[1] = *pState->m_wave[i].var_pp_t2;
  2384. pState->m_wave[i].t_values_after_init_code[2] = *pState->m_wave[i].var_pp_t3;
  2385. pState->m_wave[i].t_values_after_init_code[3] = *pState->m_wave[i].var_pp_t4;
  2386. pState->m_wave[i].t_values_after_init_code[4] = *pState->m_wave[i].var_pp_t5;
  2387. pState->m_wave[i].t_values_after_init_code[5] = *pState->m_wave[i].var_pp_t6;
  2388. pState->m_wave[i].t_values_after_init_code[6] = *pState->m_wave[i].var_pp_t7;
  2389. pState->m_wave[i].t_values_after_init_code[7] = *pState->m_wave[i].var_pp_t8;
  2390. */
  2391. // 3. smooth it
  2392. WFVERTEX v2[2048];
  2393. WFVERTEX *pVerts = v;
  2394. if (!pState->m_wave[i].bUseDots)
  2395. {
  2396. nSamples = SmoothWave(v, nSamples, v2);
  2397. pVerts = v2;
  2398. }
  2399. // 4. draw it
  2400. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  2401. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
  2402. lpDevice->SetRenderState(D3DRS_DESTBLEND, pState->m_wave[i].bAdditive ? D3DBLEND_ONE : D3DBLEND_INVSRCALPHA);
  2403. float ptsize = (float)((m_nTexSizeX >= 1024) ? 2 : 1) + (pState->m_wave[i].bDrawThick ? 1 : 0);
  2404. if (pState->m_wave[i].bUseDots)
  2405. lpDevice->SetRenderState(D3DRS_POINTSIZE, *((DWORD*)&ptsize) );
  2406. int its = (pState->m_wave[i].bDrawThick && !pState->m_wave[i].bUseDots) ? 4 : 1;
  2407. float x_inc = 2.0f / (float)m_nTexSizeX;
  2408. float y_inc = 2.0f / (float)m_nTexSizeY;
  2409. for (int it=0; it<its; it++)
  2410. {
  2411. switch(it)
  2412. {
  2413. case 0: break;
  2414. case 1: for (j=0; j<nSamples; j++) pVerts[j].x += x_inc; break; // draw fat dots
  2415. case 2: for (j=0; j<nSamples; j++) pVerts[j].y += y_inc; break; // draw fat dots
  2416. case 3: for (j=0; j<nSamples; j++) pVerts[j].x -= x_inc; break; // draw fat dots
  2417. }
  2418. lpDevice->DrawPrimitiveUP(pState->m_wave[i].bUseDots ? D3DPT_POINTLIST : D3DPT_LINESTRIP, nSamples - (pState->m_wave[i].bUseDots ? 0 : 1), (void*)pVerts, sizeof(WFVERTEX));
  2419. }
  2420. ptsize = 1.0f;
  2421. if (pState->m_wave[i].bUseDots)
  2422. lpDevice->SetRenderState(D3DRS_POINTSIZE, *((DWORD*)&ptsize) );
  2423. }
  2424. }
  2425. }
  2426. }
  2427. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  2428. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
  2429. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
  2430. }
  2431. void CPlugin::DrawWave(float *fL, float *fR)
  2432. {
  2433. LPDIRECT3DDEVICE9 lpDevice = GetDevice();
  2434. if (!lpDevice)
  2435. return;
  2436. lpDevice->SetTexture(0, NULL);
  2437. lpDevice->SetVertexShader( NULL );
  2438. lpDevice->SetFVF( WFVERTEX_FORMAT );
  2439. int i;
  2440. WFVERTEX v1[576+1], v2[576+1];
  2441. /*
  2442. m_lpD3DDev->SetRenderState(D3DRENDERSTATE_SHADEMODE, D3DSHADE_GOURAUD); //D3DSHADE_FLAT
  2443. m_lpD3DDev->SetRenderState(D3DRENDERSTATE_SPECULARENABLE, FALSE);
  2444. m_lpD3DDev->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
  2445. if (m_D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_DITHER)
  2446. m_lpD3DDev->SetRenderState(D3DRENDERSTATE_DITHERENABLE, TRUE);
  2447. m_lpD3DDev->SetRenderState(D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
  2448. m_lpD3DDev->SetRenderState(D3DRENDERSTATE_LIGHTING, FALSE);
  2449. m_lpD3DDev->SetRenderState(D3DRENDERSTATE_COLORVERTEX, TRUE);
  2450. m_lpD3DDev->SetRenderState(D3DRENDERSTATE_FILLMODE, D3DFILL_WIREFRAME); // vs. SOLID
  2451. m_lpD3DDev->SetRenderState(D3DRENDERSTATE_AMBIENT, D3DCOLOR_RGBA_01(1,1,1,1));
  2452. hr = m_lpD3DDev->SetTexture(0, NULL);
  2453. if (hr != D3D_OK)
  2454. {
  2455. //dumpmsg("Draw(): ERROR: SetTexture");
  2456. //IdentifyD3DError(hr);
  2457. }
  2458. */
  2459. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  2460. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
  2461. lpDevice->SetRenderState(D3DRS_DESTBLEND, (*m_pState->var_pf_wave_additive) ? D3DBLEND_ONE : D3DBLEND_INVSRCALPHA);
  2462. //float cr = m_pState->m_waveR.eval(GetTime());
  2463. //float cg = m_pState->m_waveG.eval(GetTime());
  2464. //float cb = m_pState->m_waveB.eval(GetTime());
  2465. float cr = (float)(*m_pState->var_pf_wave_r);
  2466. float cg = (float)(*m_pState->var_pf_wave_g);
  2467. float cb = (float)(*m_pState->var_pf_wave_b);
  2468. float cx = (float)(*m_pState->var_pf_wave_x);
  2469. float cy = (float)(*m_pState->var_pf_wave_y); // note: it was backwards (top==1) in the original milkdrop, so we keep it that way!
  2470. float fWaveParam = (float)(*m_pState->var_pf_wave_mystery);
  2471. /*if (m_pState->m_bBlending)
  2472. {
  2473. cr = cr*(m_pState->m_fBlendProgress) + (1.0f-m_pState->m_fBlendProgress)*((float)(*m_pOldState->var_pf_wave_r));
  2474. cg = cg*(m_pState->m_fBlendProgress) + (1.0f-m_pState->m_fBlendProgress)*((float)(*m_pOldState->var_pf_wave_g));
  2475. cb = cb*(m_pState->m_fBlendProgress) + (1.0f-m_pState->m_fBlendProgress)*((float)(*m_pOldState->var_pf_wave_b));
  2476. cx = cx*(m_pState->m_fBlendProgress) + (1.0f-m_pState->m_fBlendProgress)*((float)(*m_pOldState->var_pf_wave_x));
  2477. cy = cy*(m_pState->m_fBlendProgress) + (1.0f-m_pState->m_fBlendProgress)*((float)(*m_pOldState->var_pf_wave_y));
  2478. fWaveParam = fWaveParam*(m_pState->m_fBlendProgress) + (1.0f-m_pState->m_fBlendProgress)*((float)(*m_pOldState->var_pf_wave_mystery));
  2479. }*/
  2480. if (cr < 0) cr = 0;
  2481. if (cg < 0) cg = 0;
  2482. if (cb < 0) cb = 0;
  2483. if (cr > 1) cr = 1;
  2484. if (cg > 1) cg = 1;
  2485. if (cb > 1) cb = 1;
  2486. // maximize color:
  2487. if (*m_pState->var_pf_wave_brighten)
  2488. {
  2489. float fMaximizeWaveColorAmount = 1.0f;
  2490. float max = cr;
  2491. if (max < cg) max = cg;
  2492. if (max < cb) max = cb;
  2493. if (max > 0.01f)
  2494. {
  2495. cr = cr/max*fMaximizeWaveColorAmount + cr*(1.0f - fMaximizeWaveColorAmount);
  2496. cg = cg/max*fMaximizeWaveColorAmount + cg*(1.0f - fMaximizeWaveColorAmount);
  2497. cb = cb/max*fMaximizeWaveColorAmount + cb*(1.0f - fMaximizeWaveColorAmount);
  2498. }
  2499. }
  2500. float fWavePosX = cx*2.0f - 1.0f; // go from 0..1 user-range to -1..1 D3D range
  2501. float fWavePosY = cy*2.0f - 1.0f;
  2502. float bass_rel = mysound.imm[0];
  2503. float mid_rel = mysound.imm[1];
  2504. float treble_rel = mysound.imm[2];
  2505. int sample_offset = 0;
  2506. int new_wavemode = (int)(*m_pState->var_pf_wave_mode) % NUM_WAVES; // since it can be changed from per-frame code!
  2507. int its = (m_pState->m_bBlending && (new_wavemode != m_pState->m_nOldWaveMode)) ? 2 : 1;
  2508. int nVerts1 = 0;
  2509. int nVerts2 = 0;
  2510. int nBreak1 = -1;
  2511. int nBreak2 = -1;
  2512. float alpha1, alpha2;
  2513. for (int it=0; it<its; it++)
  2514. {
  2515. int wave = (it==0) ? new_wavemode : m_pState->m_nOldWaveMode;
  2516. int nVerts = NUM_WAVEFORM_SAMPLES; // allowed to peek ahead 64 (i.e. left is [i], right is [i+64])
  2517. int nBreak = -1;
  2518. float fWaveParam2 = fWaveParam;
  2519. //std::string fWaveParam; // kill its scope
  2520. if ((wave==0 || wave==1 || wave==4) && (fWaveParam2 < -1 || fWaveParam2 > 1))
  2521. {
  2522. //fWaveParam2 = max(fWaveParam2, -1.0f);
  2523. //fWaveParam2 = min(fWaveParam2, 1.0f);
  2524. fWaveParam2 = fWaveParam2*0.5f + 0.5f;
  2525. fWaveParam2 -= floorf(fWaveParam2);
  2526. fWaveParam2 = fabsf(fWaveParam2);
  2527. fWaveParam2 = fWaveParam2*2-1;
  2528. }
  2529. WFVERTEX *v = (it==0) ? v1 : v2;
  2530. ZeroMemory(v, sizeof(WFVERTEX)*nVerts);
  2531. float alpha = (float)(*m_pState->var_pf_wave_a);//m_pState->m_fWaveAlpha.eval(GetTime());
  2532. switch(wave)
  2533. {
  2534. case 0:
  2535. // circular wave
  2536. nVerts /= 2;
  2537. sample_offset = (NUM_WAVEFORM_SAMPLES-nVerts)/2;//mysound.GoGoAlignatron(nVerts * 12/10); // only call this once nVerts is final!
  2538. if (m_pState->m_bModWaveAlphaByVolume)
  2539. alpha *= ((mysound.imm_rel[0] + mysound.imm_rel[1] + mysound.imm_rel[2])*0.333f - m_pState->m_fModWaveAlphaStart.eval(GetTime()))/(m_pState->m_fModWaveAlphaEnd.eval(GetTime()) - m_pState->m_fModWaveAlphaStart.eval(GetTime()));
  2540. if (alpha < 0) alpha = 0;
  2541. if (alpha > 1) alpha = 1;
  2542. //color = D3DCOLOR_RGBA_01(cr, cg, cb, alpha);
  2543. {
  2544. float inv_nverts_minus_one = 1.0f/(float)(nVerts-1);
  2545. for (i=0; i<nVerts; i++)
  2546. {
  2547. float rad = 0.5f + 0.4f*fR[i+sample_offset] + fWaveParam2;
  2548. float ang = (i)*inv_nverts_minus_one*6.28f + GetTime()*0.2f;
  2549. if (i < nVerts/10)
  2550. {
  2551. float mix = i/(nVerts*0.1f);
  2552. mix = 0.5f - 0.5f*cosf(mix * 3.1416f);
  2553. float rad_2 = 0.5f + 0.4f*fR[i + nVerts + sample_offset] + fWaveParam2;
  2554. rad = rad_2*(1.0f-mix) + rad*(mix);
  2555. }
  2556. v[i].x = rad*cosf(ang) *m_fAspectY + fWavePosX; // 0.75 = adj. for aspect ratio
  2557. v[i].y = rad*sinf(ang) *m_fAspectX + fWavePosY;
  2558. //v[i].Diffuse = color;
  2559. }
  2560. }
  2561. // dupe last vertex to connect the lines; skip if blending
  2562. if (!m_pState->m_bBlending)
  2563. {
  2564. nVerts++;
  2565. memcpy(&v[nVerts-1], &v[0], sizeof(WFVERTEX));
  2566. }
  2567. break;
  2568. case 1:
  2569. // x-y osc. that goes around in a spiral, in time
  2570. alpha *= 1.25f;
  2571. if (m_pState->m_bModWaveAlphaByVolume)
  2572. alpha *= ((mysound.imm_rel[0] + mysound.imm_rel[1] + mysound.imm_rel[2])*0.333f - m_pState->m_fModWaveAlphaStart.eval(GetTime()))/(m_pState->m_fModWaveAlphaEnd.eval(GetTime()) - m_pState->m_fModWaveAlphaStart.eval(GetTime()));
  2573. if (alpha < 0) alpha = 0;
  2574. if (alpha > 1) alpha = 1;
  2575. //color = D3DCOLOR_RGBA_01(cr, cg, cb, alpha);
  2576. nVerts /= 2;
  2577. for (i=0; i<nVerts; i++)
  2578. {
  2579. float rad = 0.53f + 0.43f*fR[i] + fWaveParam2;
  2580. float ang = fL[i+32] * 1.57f + GetTime()*2.3f;
  2581. v[i].x = rad*cosf(ang) *m_fAspectY + fWavePosX; // 0.75 = adj. for aspect ratio
  2582. v[i].y = rad*sinf(ang) *m_fAspectX + fWavePosY;
  2583. //v[i].Diffuse = color;//(D3DCOLOR_RGBA_01(cr, cg, cb, alpha*min(1, max(0, fL[i])));
  2584. }
  2585. break;
  2586. case 2:
  2587. // centered spiro (alpha constant)
  2588. // aimed at not being so sound-responsive, but being very "nebula-like"
  2589. // difference is that alpha is constant (and faint), and waves a scaled way up
  2590. switch(m_nTexSizeX)
  2591. {
  2592. case 256: alpha *= 0.07f; break;
  2593. case 512: alpha *= 0.09f; break;
  2594. case 1024: alpha *= 0.11f; break;
  2595. case 2048: alpha *= 0.13f; break;
  2596. }
  2597. if (m_pState->m_bModWaveAlphaByVolume)
  2598. alpha *= ((mysound.imm_rel[0] + mysound.imm_rel[1] + mysound.imm_rel[2])*0.333f - m_pState->m_fModWaveAlphaStart.eval(GetTime()))/(m_pState->m_fModWaveAlphaEnd.eval(GetTime()) - m_pState->m_fModWaveAlphaStart.eval(GetTime()));
  2599. if (alpha < 0) alpha = 0;
  2600. if (alpha > 1) alpha = 1;
  2601. //color = D3DCOLOR_RGBA_01(cr, cg, cb, alpha);
  2602. for (i=0; i<nVerts; i++)
  2603. {
  2604. v[i].x = fR[i ] *m_fAspectY + fWavePosX;//((pR[i] ^ 128) - 128)/90.0f * ASPECT; // 0.75 = adj. for aspect ratio
  2605. v[i].y = fL[i+32] *m_fAspectX + fWavePosY;//((pL[i+32] ^ 128) - 128)/90.0f;
  2606. //v[i].Diffuse = color;
  2607. }
  2608. break;
  2609. case 3:
  2610. // centered spiro (alpha tied to volume)
  2611. // aimed at having a strong audio-visual tie-in
  2612. // colors are always bright (no darks)
  2613. switch(m_nTexSizeX)
  2614. {
  2615. case 256: alpha = 0.075f; break;
  2616. case 512: alpha = 0.150f; break;
  2617. case 1024: alpha = 0.220f; break;
  2618. case 2048: alpha = 0.330f; break;
  2619. }
  2620. alpha *= 1.3f;
  2621. alpha *= powf(treble_rel, 2.0f);
  2622. if (m_pState->m_bModWaveAlphaByVolume)
  2623. alpha *= ((mysound.imm_rel[0] + mysound.imm_rel[1] + mysound.imm_rel[2])*0.333f - m_pState->m_fModWaveAlphaStart.eval(GetTime()))/(m_pState->m_fModWaveAlphaEnd.eval(GetTime()) - m_pState->m_fModWaveAlphaStart.eval(GetTime()));
  2624. if (alpha < 0) alpha = 0;
  2625. if (alpha > 1) alpha = 1;
  2626. //color = D3DCOLOR_RGBA_01(cr, cg, cb, alpha);
  2627. for (i=0; i<nVerts; i++)
  2628. {
  2629. v[i].x = fR[i ] *m_fAspectY + fWavePosX;//((pR[i] ^ 128) - 128)/90.0f * ASPECT; // 0.75 = adj. for aspect ratio
  2630. v[i].y = fL[i+32] *m_fAspectX + fWavePosY;//((pL[i+32] ^ 128) - 128)/90.0f;
  2631. //v[i].Diffuse = color;
  2632. }
  2633. break;
  2634. case 4:
  2635. // horizontal "script", left channel
  2636. if (nVerts > m_nTexSizeX/3)
  2637. nVerts = m_nTexSizeX/3;
  2638. sample_offset = (NUM_WAVEFORM_SAMPLES-nVerts)/2;//mysound.GoGoAlignatron(nVerts + 25); // only call this once nVerts is final!
  2639. /*
  2640. if (treble_rel > treb_thresh_for_wave6)
  2641. {
  2642. //alpha = 1.0f;
  2643. treb_thresh_for_wave6 = treble_rel * 1.025f;
  2644. }
  2645. else
  2646. {
  2647. alpha *= 0.2f;
  2648. treb_thresh_for_wave6 *= 0.996f; // fixme: make this fps-independent
  2649. }
  2650. */
  2651. if (m_pState->m_bModWaveAlphaByVolume)
  2652. alpha *= ((mysound.imm_rel[0] + mysound.imm_rel[1] + mysound.imm_rel[2])*0.333f - m_pState->m_fModWaveAlphaStart.eval(GetTime()))/(m_pState->m_fModWaveAlphaEnd.eval(GetTime()) - m_pState->m_fModWaveAlphaStart.eval(GetTime()));
  2653. if (alpha < 0) alpha = 0;
  2654. if (alpha > 1) alpha = 1;
  2655. //color = D3DCOLOR_RGBA_01(cr, cg, cb, alpha);
  2656. {
  2657. float w1 = 0.45f + 0.5f*(fWaveParam2*0.5f + 0.5f); // 0.1 - 0.9
  2658. float w2 = 1.0f - w1;
  2659. float inv_nverts = 1.0f/(float)(nVerts);
  2660. for (i=0; i<nVerts; i++)
  2661. {
  2662. v[i].x = -1.0f + 2.0f*(i*inv_nverts) + fWavePosX;
  2663. v[i].y = fL[i+sample_offset]*0.47f + fWavePosY;//((pL[i] ^ 128) - 128)/270.0f;
  2664. v[i].x += fR[i+25+sample_offset]*0.44f;//((pR[i+25] ^ 128) - 128)/290.0f;
  2665. //v[i].Diffuse = color;
  2666. // momentum
  2667. if (i>1)
  2668. {
  2669. v[i].x = v[i].x*w2 + w1*(v[i-1].x*2.0f - v[i-2].x);
  2670. v[i].y = v[i].y*w2 + w1*(v[i-1].y*2.0f - v[i-2].y);
  2671. }
  2672. }
  2673. /*
  2674. // center on Y
  2675. float avg_y = 0;
  2676. for (i=0; i<nVerts; i++)
  2677. avg_y += v[i].y;
  2678. avg_y /= (float)nVerts;
  2679. avg_y *= 0.5f; // damp the movement
  2680. for (i=0; i<nVerts; i++)
  2681. v[i].y -= avg_y;
  2682. */
  2683. }
  2684. break;
  2685. case 5:
  2686. // weird explosive complex # thingy
  2687. switch(m_nTexSizeX)
  2688. {
  2689. case 256: alpha *= 0.07f; break;
  2690. case 512: alpha *= 0.09f; break;
  2691. case 1024: alpha *= 0.11f; break;
  2692. case 2048: alpha *= 0.13f; break;
  2693. }
  2694. if (m_pState->m_bModWaveAlphaByVolume)
  2695. alpha *= ((mysound.imm_rel[0] + mysound.imm_rel[1] + mysound.imm_rel[2])*0.333f - m_pState->m_fModWaveAlphaStart.eval(GetTime()))/(m_pState->m_fModWaveAlphaEnd.eval(GetTime()) - m_pState->m_fModWaveAlphaStart.eval(GetTime()));
  2696. if (alpha < 0) alpha = 0;
  2697. if (alpha > 1) alpha = 1;
  2698. //color = D3DCOLOR_RGBA_01(cr, cg, cb, alpha);
  2699. {
  2700. float cos_rot = cosf(GetTime()*0.3f);
  2701. float sin_rot = sinf(GetTime()*0.3f);
  2702. for (i=0; i<nVerts; i++)
  2703. {
  2704. float x0 = (fR[i]*fL[i+32] + fL[i]*fR[i+32]);
  2705. float y0 = (fR[i]*fR[i] - fL[i+32]*fL[i+32]);
  2706. v[i].x = (x0*cos_rot - y0*sin_rot)*m_fAspectY + fWavePosX;
  2707. v[i].y = (x0*sin_rot + y0*cos_rot)*m_fAspectX + fWavePosY;
  2708. //v[i].Diffuse = color;
  2709. }
  2710. }
  2711. break;
  2712. case 6:
  2713. case 7:
  2714. case 8:
  2715. // 6: angle-adjustable left channel, with temporal wave alignment;
  2716. // fWaveParam2 controls the angle at which it's drawn
  2717. // fWavePosX slides the wave away from the center, transversely.
  2718. // fWavePosY does nothing
  2719. //
  2720. // 7: same, except there are two channels shown, and
  2721. // fWavePosY determines the separation distance.
  2722. //
  2723. // 8: same as 6, except using the spectrum analyzer (UNFINISHED)
  2724. //
  2725. nVerts /= 2;
  2726. if (nVerts > m_nTexSizeX/3)
  2727. nVerts = m_nTexSizeX/3;
  2728. if (wave==8)
  2729. nVerts = 256;
  2730. else
  2731. sample_offset = (NUM_WAVEFORM_SAMPLES-nVerts)/2;//mysound.GoGoAlignatron(nVerts); // only call this once nVerts is final!
  2732. if (m_pState->m_bModWaveAlphaByVolume)
  2733. alpha *= ((mysound.imm_rel[0] + mysound.imm_rel[1] + mysound.imm_rel[2])*0.333f - m_pState->m_fModWaveAlphaStart.eval(GetTime()))/(m_pState->m_fModWaveAlphaEnd.eval(GetTime()) - m_pState->m_fModWaveAlphaStart.eval(GetTime()));
  2734. if (alpha < 0) alpha = 0;
  2735. if (alpha > 1) alpha = 1;
  2736. //color = D3DCOLOR_RGBA_01(cr, cg, cb, alpha);
  2737. {
  2738. float ang = 1.57f*fWaveParam2; // from -PI/2 to PI/2
  2739. float dx = cosf(ang);
  2740. float dy = sinf(ang);
  2741. float edge_x[2], edge_y[2];
  2742. //edge_x[0] = fWavePosX - dx*3.0f;
  2743. //edge_y[0] = fWavePosY - dy*3.0f;
  2744. //edge_x[1] = fWavePosX + dx*3.0f;
  2745. //edge_y[1] = fWavePosY + dy*3.0f;
  2746. edge_x[0] = fWavePosX*cosf(ang + 1.57f) - dx*3.0f;
  2747. edge_y[0] = fWavePosX*sinf(ang + 1.57f) - dy*3.0f;
  2748. edge_x[1] = fWavePosX*cosf(ang + 1.57f) + dx*3.0f;
  2749. edge_y[1] = fWavePosX*sinf(ang + 1.57f) + dy*3.0f;
  2750. for (i=0; i<2; i++) // for each point defining the line
  2751. {
  2752. // clip the point against 4 edges of screen
  2753. // be a bit lenient (use +/-1.1 instead of +/-1.0)
  2754. // so the dual-wave doesn't end too soon, after the channels are moved apart
  2755. for (int j=0; j<4; j++)
  2756. {
  2757. float t;
  2758. bool bClip = false;
  2759. switch(j)
  2760. {
  2761. case 0:
  2762. if (edge_x[i] > 1.1f)
  2763. {
  2764. t = (1.1f - edge_x[1-i]) / (edge_x[i] - edge_x[1-i]);
  2765. bClip = true;
  2766. }
  2767. break;
  2768. case 1:
  2769. if (edge_x[i] < -1.1f)
  2770. {
  2771. t = (-1.1f - edge_x[1-i]) / (edge_x[i] - edge_x[1-i]);
  2772. bClip = true;
  2773. }
  2774. break;
  2775. case 2:
  2776. if (edge_y[i] > 1.1f)
  2777. {
  2778. t = (1.1f - edge_y[1-i]) / (edge_y[i] - edge_y[1-i]);
  2779. bClip = true;
  2780. }
  2781. break;
  2782. case 3:
  2783. if (edge_y[i] < -1.1f)
  2784. {
  2785. t = (-1.1f - edge_y[1-i]) / (edge_y[i] - edge_y[1-i]);
  2786. bClip = true;
  2787. }
  2788. break;
  2789. }
  2790. if (bClip)
  2791. {
  2792. float dx = edge_x[i] - edge_x[1-i];
  2793. float dy = edge_y[i] - edge_y[1-i];
  2794. edge_x[i] = edge_x[1-i] + dx*t;
  2795. edge_y[i] = edge_y[1-i] + dy*t;
  2796. }
  2797. }
  2798. }
  2799. dx = (edge_x[1] - edge_x[0]) / (float)nVerts;
  2800. dy = (edge_y[1] - edge_y[0]) / (float)nVerts;
  2801. float ang2 = atan2f(dy,dx);
  2802. float perp_dx = cosf(ang2 + 1.57f);
  2803. float perp_dy = sinf(ang2 + 1.57f);
  2804. if (wave == 6)
  2805. for (i=0; i<nVerts; i++)
  2806. {
  2807. v[i].x = edge_x[0] + dx*i + perp_dx*0.25f*fL[i + sample_offset];
  2808. v[i].y = edge_y[0] + dy*i + perp_dy*0.25f*fL[i + sample_offset];
  2809. //v[i].Diffuse = color;
  2810. }
  2811. else if (wave == 8)
  2812. //256 verts
  2813. for (i=0; i<nVerts; i++)
  2814. {
  2815. float f = 0.1f*logf(mysound.fSpecLeft[i*2] + mysound.fSpecLeft[i*2+1]);
  2816. v[i].x = edge_x[0] + dx*i + perp_dx*f;
  2817. v[i].y = edge_y[0] + dy*i + perp_dy*f;
  2818. //v[i].Diffuse = color;
  2819. }
  2820. else
  2821. {
  2822. float sep = powf(fWavePosY*0.5f + 0.5f, 2.0f);
  2823. for (i=0; i<nVerts; i++)
  2824. {
  2825. v[i].x = edge_x[0] + dx*i + perp_dx*(0.25f*fL[i + sample_offset] + sep);
  2826. v[i].y = edge_y[0] + dy*i + perp_dy*(0.25f*fL[i + sample_offset] + sep);
  2827. //v[i].Diffuse = color;
  2828. }
  2829. //D3DPRIMITIVETYPE primtype = (*m_pState->var_pf_wave_usedots) ? D3DPT_POINTLIST : D3DPT_LINESTRIP;
  2830. //m_lpD3DDev->DrawPrimitive(primtype, D3DFVF_LVERTEX, (LPVOID)v, nVerts, NULL);
  2831. for (i=0; i<nVerts; i++)
  2832. {
  2833. v[i+nVerts].x = edge_x[0] + dx*i + perp_dx*(0.25f*fR[i + sample_offset] - sep);
  2834. v[i+nVerts].y = edge_y[0] + dy*i + perp_dy*(0.25f*fR[i + sample_offset] - sep);
  2835. //v[i+nVerts].Diffuse = color;
  2836. }
  2837. nBreak = nVerts;
  2838. nVerts *= 2;
  2839. }
  2840. }
  2841. break;
  2842. }
  2843. if (it==0)
  2844. {
  2845. nVerts1 = nVerts;
  2846. nBreak1 = nBreak;
  2847. alpha1 = alpha;
  2848. }
  2849. else
  2850. {
  2851. nVerts2 = nVerts;
  2852. nBreak2 = nBreak;
  2853. alpha2 = alpha;
  2854. }
  2855. }
  2856. // v1[] is for the current waveform
  2857. // v2[] is for the old waveform (from prev. preset - only used if blending)
  2858. // nVerts1 is the # of vertices in v1
  2859. // nVerts2 is the # of vertices in v2
  2860. // nBreak1 is the index of the point at which to break the solid line in v1[] (-1 if no break)
  2861. // nBreak2 is the index of the point at which to break the solid line in v2[] (-1 if no break)
  2862. float mix = CosineInterp(m_pState->m_fBlendProgress);
  2863. float mix2 = 1.0f - mix;
  2864. // blend 2 waveforms
  2865. if (nVerts2 > 0)
  2866. {
  2867. // note: this won't yet handle the case where (nBreak1 > 0 && nBreak2 > 0)
  2868. // in this case, code must break wave into THREE segments
  2869. float m = (nVerts2-1)/(float)nVerts1;
  2870. float x,y;
  2871. for (int i=0; i<nVerts1; i++)
  2872. {
  2873. float fIdx = i*m;
  2874. int nIdx = (int)fIdx;
  2875. float t = fIdx - nIdx;
  2876. if (nIdx == nBreak2-1)
  2877. {
  2878. x = v2[nIdx].x;
  2879. y = v2[nIdx].y;
  2880. nBreak1 = i+1;
  2881. }
  2882. else
  2883. {
  2884. x = v2[nIdx].x*(1-t) + v2[nIdx+1].x*(t);
  2885. y = v2[nIdx].y*(1-t) + v2[nIdx+1].y*(t);
  2886. }
  2887. v1[i].x = v1[i].x*(mix) + x*(mix2);
  2888. v1[i].y = v1[i].y*(mix) + y*(mix2);
  2889. }
  2890. }
  2891. // determine alpha
  2892. if (nVerts2 > 0)
  2893. {
  2894. alpha1 = alpha1*(mix) + alpha2*(1.0f-mix);
  2895. }
  2896. // apply color & alpha
  2897. // ALSO reverse all y values, to stay consistent with the pre-VMS milkdrop,
  2898. // which DIDN'T:
  2899. v1[0].Diffuse = D3DCOLOR_RGBA_01(cr, cg, cb, alpha1);
  2900. for (i=0; i<nVerts1; i++)
  2901. {
  2902. v1[i].Diffuse = v1[0].Diffuse;
  2903. v1[i].y = -v1[i].y;
  2904. }
  2905. // don't draw wave if (possibly blended) alpha is less than zero.
  2906. if (alpha1 < 0.004f)
  2907. goto SKIP_DRAW_WAVE;
  2908. // TESSELLATE - smooth the wave, one time.
  2909. WFVERTEX* pVerts = v1;
  2910. WFVERTEX vTess[(576+3)*2];
  2911. if (1)
  2912. {
  2913. if (nBreak1==-1)
  2914. {
  2915. nVerts1 = SmoothWave(v1, nVerts1, vTess);
  2916. }
  2917. else
  2918. {
  2919. int oldBreak = nBreak1;
  2920. nBreak1 = SmoothWave(v1, nBreak1, vTess);
  2921. nVerts1 = SmoothWave(&v1[oldBreak], nVerts1-oldBreak, &vTess[nBreak1]) + nBreak1;
  2922. }
  2923. pVerts = vTess;
  2924. }
  2925. // draw primitives
  2926. {
  2927. //D3DPRIMITIVETYPE primtype = (*m_pState->var_pf_wave_usedots) ? D3DPT_POINTLIST : D3DPT_LINESTRIP;
  2928. float x_inc = 2.0f / (float)m_nTexSizeX;
  2929. float y_inc = 2.0f / (float)m_nTexSizeY;
  2930. int drawing_its = ((*m_pState->var_pf_wave_thick || *m_pState->var_pf_wave_usedots) && (m_nTexSizeX >= 512)) ? 4 : 1;
  2931. for (int it=0; it<drawing_its; it++)
  2932. {
  2933. int j;
  2934. switch(it)
  2935. {
  2936. case 0: break;
  2937. case 1: for (j=0; j<nVerts1; j++) pVerts[j].x += x_inc; break; // draw fat dots
  2938. case 2: for (j=0; j<nVerts1; j++) pVerts[j].y += y_inc; break; // draw fat dots
  2939. case 3: for (j=0; j<nVerts1; j++) pVerts[j].x -= x_inc; break; // draw fat dots
  2940. }
  2941. if (nBreak1 == -1)
  2942. {
  2943. if (*m_pState->var_pf_wave_usedots)
  2944. lpDevice->DrawPrimitiveUP(D3DPT_POINTLIST, nVerts1, (void*)pVerts, sizeof(WFVERTEX));
  2945. else
  2946. lpDevice->DrawPrimitiveUP(D3DPT_LINESTRIP, nVerts1-1, (void*)pVerts, sizeof(WFVERTEX));
  2947. }
  2948. else
  2949. {
  2950. if (*m_pState->var_pf_wave_usedots)
  2951. {
  2952. lpDevice->DrawPrimitiveUP(D3DPT_POINTLIST, nBreak1, (void*)pVerts, sizeof(WFVERTEX));
  2953. lpDevice->DrawPrimitiveUP(D3DPT_POINTLIST, nVerts1-nBreak1, (void*)&pVerts[nBreak1], sizeof(WFVERTEX));
  2954. }
  2955. else
  2956. {
  2957. lpDevice->DrawPrimitiveUP(D3DPT_LINESTRIP, nBreak1-1, (void*)pVerts, sizeof(WFVERTEX));
  2958. lpDevice->DrawPrimitiveUP(D3DPT_LINESTRIP, nVerts1-nBreak1-1, (void*)&pVerts[nBreak1], sizeof(WFVERTEX));
  2959. }
  2960. }
  2961. }
  2962. }
  2963. SKIP_DRAW_WAVE:
  2964. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  2965. }
  2966. void CPlugin::DrawSprites()
  2967. {
  2968. LPDIRECT3DDEVICE9 lpDevice = GetDevice();
  2969. if (!lpDevice)
  2970. return;
  2971. lpDevice->SetTexture(0, NULL);
  2972. lpDevice->SetVertexShader( NULL );
  2973. lpDevice->SetFVF( WFVERTEX_FORMAT );
  2974. if (*m_pState->var_pf_darken_center)
  2975. {
  2976. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  2977. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);//SRCALPHA);
  2978. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
  2979. WFVERTEX v3[6];
  2980. ZeroMemory(v3, sizeof(WFVERTEX)*6);
  2981. // colors:
  2982. v3[0].Diffuse = D3DCOLOR_RGBA_01(0, 0, 0, 3.0f/32.0f);
  2983. v3[1].Diffuse = D3DCOLOR_RGBA_01(0, 0, 0, 0.0f/32.0f);
  2984. v3[2].Diffuse = v3[1].Diffuse;
  2985. v3[3].Diffuse = v3[1].Diffuse;
  2986. v3[4].Diffuse = v3[1].Diffuse;
  2987. v3[5].Diffuse = v3[1].Diffuse;
  2988. // positioning:
  2989. float fHalfSize = 0.05f;
  2990. v3[0].x = 0.0f;
  2991. v3[1].x = 0.0f - fHalfSize*m_fAspectY;
  2992. v3[2].x = 0.0f;
  2993. v3[3].x = 0.0f + fHalfSize*m_fAspectY;
  2994. v3[4].x = 0.0f;
  2995. v3[5].x = v3[1].x;
  2996. v3[0].y = 0.0f;
  2997. v3[1].y = 0.0f;
  2998. v3[2].y = 0.0f - fHalfSize;
  2999. v3[3].y = 0.0f;
  3000. v3[4].y = 0.0f + fHalfSize;
  3001. v3[5].y = v3[1].y;
  3002. //v3[0].tu = 0; v3[1].tu = 1; v3[2].tu = 0; v3[3].tu = 1;
  3003. //v3[0].tv = 1; v3[1].tv = 1; v3[2].tv = 0; v3[3].tv = 0;
  3004. lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 4, (LPVOID)v3, sizeof(WFVERTEX));
  3005. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  3006. }
  3007. // do borders
  3008. {
  3009. float fOuterBorderSize = (float)*m_pState->var_pf_ob_size;
  3010. float fInnerBorderSize = (float)*m_pState->var_pf_ib_size;
  3011. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  3012. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
  3013. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
  3014. for (int it=0; it<2; it++)
  3015. {
  3016. WFVERTEX v3[4];
  3017. ZeroMemory(v3, sizeof(WFVERTEX)*4);
  3018. // colors:
  3019. float r = (it==0) ? (float)*m_pState->var_pf_ob_r : (float)*m_pState->var_pf_ib_r;
  3020. float g = (it==0) ? (float)*m_pState->var_pf_ob_g : (float)*m_pState->var_pf_ib_g;
  3021. float b = (it==0) ? (float)*m_pState->var_pf_ob_b : (float)*m_pState->var_pf_ib_b;
  3022. float a = (it==0) ? (float)*m_pState->var_pf_ob_a : (float)*m_pState->var_pf_ib_a;
  3023. if (a > 0.001f)
  3024. {
  3025. v3[0].Diffuse = D3DCOLOR_RGBA_01(r,g,b,a);
  3026. v3[1].Diffuse = v3[0].Diffuse;
  3027. v3[2].Diffuse = v3[0].Diffuse;
  3028. v3[3].Diffuse = v3[0].Diffuse;
  3029. // positioning:
  3030. float fInnerRad = (it==0) ? 1.0f - fOuterBorderSize : 1.0f - fOuterBorderSize - fInnerBorderSize;
  3031. float fOuterRad = (it==0) ? 1.0f : 1.0f - fOuterBorderSize;
  3032. v3[0].x = fInnerRad;
  3033. v3[1].x = fOuterRad;
  3034. v3[2].x = fOuterRad;
  3035. v3[3].x = fInnerRad;
  3036. v3[0].y = fInnerRad;
  3037. v3[1].y = fOuterRad;
  3038. v3[2].y = -fOuterRad;
  3039. v3[3].y = -fInnerRad;
  3040. for (int rot=0; rot<4; rot++)
  3041. {
  3042. lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, (LPVOID)v3, sizeof(WFVERTEX));
  3043. // rotate by 90 degrees
  3044. for (int v=0; v<4; v++)
  3045. {
  3046. float t = 1.570796327f;
  3047. float x = v3[v].x;
  3048. float y = v3[v].y;
  3049. v3[v].x = x*cosf(t) - y*sinf(t);
  3050. v3[v].y = x*sinf(t) + y*cosf(t);
  3051. }
  3052. }
  3053. }
  3054. }
  3055. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  3056. }
  3057. }
  3058. /*
  3059. bool CPlugin::SetMilkdropRenderTarget(LPDIRECTDRAWSURFACE7 lpSurf, int w, int h, char *szErrorMsg)
  3060. {
  3061. HRESULT hr = m_lpD3DDev->SetRenderTarget(0, lpSurf, 0);
  3062. if (hr != D3D_OK)
  3063. {
  3064. //if (szErrorMsg && szErrorMsg[0]) dumpmsg(szErrorMsg);
  3065. //IdentifyD3DError(hr);
  3066. return false;
  3067. }
  3068. //DDSURFACEDESC2 ddsd;
  3069. //ddsd.dwSize = sizeof(ddsd);
  3070. //lpSurf->GetSurfaceDesc(&ddsd);
  3071. D3DVIEWPORT7 viewData;
  3072. ZeroMemory(&viewData, sizeof(D3DVIEWPORT7));
  3073. viewData.dwWidth = w; // not: in windowed mode, when lpSurf is the back buffer, chances are good that w,h are smaller than the full surface size (since real size is fullscreen, but we're only using a portion of it as big as the window).
  3074. viewData.dwHeight = h;
  3075. hr = m_lpD3DDev->SetViewport(&viewData);
  3076. return true;
  3077. }
  3078. */
  3079. void CPlugin::DrawUserSprites() // from system memory, to back buffer.
  3080. {
  3081. LPDIRECT3DDEVICE9 lpDevice = GetDevice();
  3082. if (!lpDevice)
  3083. return;
  3084. lpDevice->SetTexture(0, NULL);
  3085. lpDevice->SetVertexShader( NULL );
  3086. lpDevice->SetFVF( SPRITEVERTEX_FORMAT );
  3087. //lpDevice->SetRenderState(D3DRS_WRAP0, 0);
  3088. //lpDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
  3089. //lpDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
  3090. //lpDevice->SetSamplerState(0, D3DSAMP_ADDRESSW, D3DTADDRESS_WRAP);
  3091. // reset these to the standard safe mode:
  3092. lpDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
  3093. lpDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
  3094. lpDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE);
  3095. lpDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
  3096. lpDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
  3097. lpDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE );
  3098. lpDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
  3099. /*
  3100. lpDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD); //D3DSHADE_GOURAUD
  3101. lpDevice->SetRenderState(D3DRS_SPECULARENABLE, FALSE);
  3102. lpDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
  3103. if (m_D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_DITHER)
  3104. lpDevice->SetRenderState(D3DRS_DITHERENABLE, TRUE);
  3105. lpDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
  3106. lpDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
  3107. lpDevice->SetRenderState(D3DRS_COLORVERTEX, TRUE);
  3108. lpDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); // vs. wireframe
  3109. lpDevice->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_RGBA_01(1,1,1,1));
  3110. lpDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTFG_LINEAR );
  3111. lpDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTFN_LINEAR );
  3112. lpDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTFP_LINEAR );
  3113. */
  3114. for (int iSlot=0; iSlot < NUM_TEX; iSlot++)
  3115. {
  3116. if (m_texmgr.m_tex[iSlot].pSurface)
  3117. {
  3118. int k;
  3119. // set values of input variables:
  3120. *(m_texmgr.m_tex[iSlot].var_time) = (double)(GetTime() - m_texmgr.m_tex[iSlot].fStartTime);
  3121. *(m_texmgr.m_tex[iSlot].var_frame) = (double)(GetFrame() - m_texmgr.m_tex[iSlot].nStartFrame);
  3122. *(m_texmgr.m_tex[iSlot].var_fps) = (double)GetFps();
  3123. *(m_texmgr.m_tex[iSlot].var_progress) = (double)m_pState->m_fBlendProgress;
  3124. *(m_texmgr.m_tex[iSlot].var_bass) = (double)mysound.imm_rel[0];
  3125. *(m_texmgr.m_tex[iSlot].var_mid) = (double)mysound.imm_rel[1];
  3126. *(m_texmgr.m_tex[iSlot].var_treb) = (double)mysound.imm_rel[2];
  3127. *(m_texmgr.m_tex[iSlot].var_bass_att) = (double)mysound.avg_rel[0];
  3128. *(m_texmgr.m_tex[iSlot].var_mid_att) = (double)mysound.avg_rel[1];
  3129. *(m_texmgr.m_tex[iSlot].var_treb_att) = (double)mysound.avg_rel[2];
  3130. // evaluate expressions
  3131. #ifndef _NO_EXPR_
  3132. if (m_texmgr.m_tex[iSlot].m_codehandle)
  3133. {
  3134. NSEEL_code_execute(m_texmgr.m_tex[iSlot].m_codehandle);
  3135. }
  3136. #endif
  3137. bool bKillSprite = (*m_texmgr.m_tex[iSlot].var_done != 0.0);
  3138. bool bBurnIn = (*m_texmgr.m_tex[iSlot].var_burn != 0.0);
  3139. // Remember the original backbuffer and zbuffer
  3140. LPDIRECT3DSURFACE9 pBackBuffer=NULL;//, pZBuffer=NULL;
  3141. lpDevice->GetRenderTarget( 0, &pBackBuffer );
  3142. //lpDevice->GetDepthStencilSurface( &pZBuffer );
  3143. if (/*bKillSprite &&*/ bBurnIn)
  3144. {
  3145. // set up to render [from NULL] to VS1 (for burn-in).
  3146. lpDevice->SetTexture(0, NULL);
  3147. IDirect3DSurface9* pNewTarget = NULL;
  3148. if (m_lpVS[1]->GetSurfaceLevel(0, &pNewTarget) != D3D_OK)
  3149. return;
  3150. lpDevice->SetRenderTarget(0, pNewTarget );
  3151. //lpDevice->SetDepthStencilSurface( NULL );
  3152. pNewTarget->Release();
  3153. lpDevice->SetTexture(0, NULL);
  3154. }
  3155. // finally, use the results to draw the sprite.
  3156. if (lpDevice->SetTexture(0, m_texmgr.m_tex[iSlot].pSurface) != D3D_OK)
  3157. return;
  3158. SPRITEVERTEX v3[4];
  3159. ZeroMemory(v3, sizeof(SPRITEVERTEX)*4);
  3160. /*
  3161. int dest_w, dest_h;
  3162. {
  3163. LPDIRECT3DSURFACE9 pRT;
  3164. lpDevice->GetRenderTarget( 0, &pRT );
  3165. D3DSURFACE_DESC desc;
  3166. pRT->GetDesc(&desc);
  3167. dest_w = desc.Width;
  3168. dest_h = desc.Height;
  3169. pRT->Release();
  3170. }*/
  3171. float x = min(1000.0f, max(-1000.0f, (float)(*m_texmgr.m_tex[iSlot].var_x) * 2.0f - 1.0f ));
  3172. float y = min(1000.0f, max(-1000.0f, (float)(*m_texmgr.m_tex[iSlot].var_y) * 2.0f - 1.0f ));
  3173. float sx = min(1000.0f, max(-1000.0f, (float)(*m_texmgr.m_tex[iSlot].var_sx) ));
  3174. float sy = min(1000.0f, max(-1000.0f, (float)(*m_texmgr.m_tex[iSlot].var_sy) ));
  3175. float rot = (float)(*m_texmgr.m_tex[iSlot].var_rot);
  3176. int flipx = (*m_texmgr.m_tex[iSlot].var_flipx == 0.0) ? 0 : 1;
  3177. int flipy = (*m_texmgr.m_tex[iSlot].var_flipy == 0.0) ? 0 : 1;
  3178. float repeatx = min(100.0f, max(0.01f, (float)(*m_texmgr.m_tex[iSlot].var_repeatx) ));
  3179. float repeaty = min(100.0f, max(0.01f, (float)(*m_texmgr.m_tex[iSlot].var_repeaty) ));
  3180. int blendmode = min(4, max(0, ((int)(*m_texmgr.m_tex[iSlot].var_blendmode))));
  3181. float r = min(1.0f, max(0.0f, ((float)(*m_texmgr.m_tex[iSlot].var_r))));
  3182. float g = min(1.0f, max(0.0f, ((float)(*m_texmgr.m_tex[iSlot].var_g))));
  3183. float b = min(1.0f, max(0.0f, ((float)(*m_texmgr.m_tex[iSlot].var_b))));
  3184. float a = min(1.0f, max(0.0f, ((float)(*m_texmgr.m_tex[iSlot].var_a))));
  3185. // set x,y coords
  3186. v3[0+flipx].x = -sx;
  3187. v3[1-flipx].x = sx;
  3188. v3[2+flipx].x = -sx;
  3189. v3[3-flipx].x = sx;
  3190. v3[0+flipy*2].y = -sy;
  3191. v3[1+flipy*2].y = -sy;
  3192. v3[2-flipy*2].y = sy;
  3193. v3[3-flipy*2].y = sy;
  3194. // first aspect ratio: adjust for non-1:1 images
  3195. {
  3196. float aspect = m_texmgr.m_tex[iSlot].img_h / (float)m_texmgr.m_tex[iSlot].img_w;
  3197. if (aspect < 1)
  3198. for (k=0; k<4; k++) v3[k].y *= aspect; // wide image
  3199. else
  3200. for (k=0; k<4; k++) v3[k].x /= aspect; // tall image
  3201. }
  3202. // 2D rotation
  3203. {
  3204. float cos_rot = cosf(rot);
  3205. float sin_rot = sinf(rot);
  3206. for (k=0; k<4; k++)
  3207. {
  3208. float x2 = v3[k].x*cos_rot - v3[k].y*sin_rot;
  3209. float y2 = v3[k].x*sin_rot + v3[k].y*cos_rot;
  3210. v3[k].x = x2;
  3211. v3[k].y = y2;
  3212. }
  3213. }
  3214. // translation
  3215. for (k=0; k<4; k++)
  3216. {
  3217. v3[k].x += x;
  3218. v3[k].y += y;
  3219. }
  3220. // second aspect ratio: normalize to width of screen
  3221. {
  3222. float aspect = GetWidth() / (float)(GetHeight());
  3223. if (aspect > 1)
  3224. for (k=0; k<4; k++) v3[k].y *= aspect;
  3225. else
  3226. for (k=0; k<4; k++) v3[k].x /= aspect;
  3227. }
  3228. // third aspect ratio: adjust for burn-in
  3229. if (bKillSprite && bBurnIn) // final render-to-VS1
  3230. {
  3231. float aspect = GetWidth()/(float)(GetHeight()*4.0f/3.0f);
  3232. if (aspect < 1.0f)
  3233. for (k=0; k<4; k++) v3[k].x *= aspect;
  3234. else
  3235. for (k=0; k<4; k++) v3[k].y /= aspect;
  3236. }
  3237. // finally, flip 'y' for annoying DirectX
  3238. //for (k=0; k<4; k++) v3[k].y *= -1.0f;
  3239. // set u,v coords
  3240. {
  3241. float dtu = 0.5f;// / (float)m_texmgr.m_tex[iSlot].tex_w;
  3242. float dtv = 0.5f;// / (float)m_texmgr.m_tex[iSlot].tex_h;
  3243. v3[0].tu = -dtu;
  3244. v3[1].tu = dtu;///*m_texmgr.m_tex[iSlot].img_w / (float)m_texmgr.m_tex[iSlot].tex_w*/ - dtu;
  3245. v3[2].tu = -dtu;
  3246. v3[3].tu = dtu;///*m_texmgr.m_tex[iSlot].img_w / (float)m_texmgr.m_tex[iSlot].tex_w*/ - dtu;
  3247. v3[0].tv = -dtv;
  3248. v3[1].tv = -dtv;
  3249. v3[2].tv = dtv;///*m_texmgr.m_tex[iSlot].img_h / (float)m_texmgr.m_tex[iSlot].tex_h*/ - dtv;
  3250. v3[3].tv = dtv;///*m_texmgr.m_tex[iSlot].img_h / (float)m_texmgr.m_tex[iSlot].tex_h*/ - dtv;
  3251. // repeat on x,y
  3252. for (k=0; k<4; k++)
  3253. {
  3254. v3[k].tu = (v3[k].tu - 0.0f)*repeatx + 0.5f;
  3255. v3[k].tv = (v3[k].tv - 0.0f)*repeaty + 0.5f;
  3256. }
  3257. }
  3258. // blendmodes src alpha: dest alpha:
  3259. // 0 blend r,g,b=modulate a=opacity SRCALPHA INVSRCALPHA
  3260. // 1 decal r,g,b=modulate a=modulate D3DBLEND_ONE D3DBLEND_ZERO
  3261. // 2 additive r,g,b=modulate a=modulate D3DBLEND_ONE D3DBLEND_ONE
  3262. // 3 srccolor r,g,b=no effect a=no effect SRCCOLOR INVSRCCOLOR
  3263. // 4 colorkey r,g,b=modulate a=no effect
  3264. switch(blendmode)
  3265. {
  3266. case 0:
  3267. default:
  3268. // alpha blend
  3269. /*
  3270. Q. I am rendering with alpha blending and setting the alpha
  3271. of the diffuse vertex component to determine the opacity.
  3272. It works when there is no texture set, but as soon as I set
  3273. a texture the alpha that I set is no longer applied. Why?
  3274. The problem originates in the texture blending stages, rather
  3275. than in the subsequent alpha blending. Alpha can come from
  3276. several possible sources. If this has not been specified,
  3277. then the alpha will be taken from the texture, if one is selected.
  3278. If no texture is selected, then the default will use the alpha
  3279. channel of the diffuse vertex component.
  3280. Explicitly specifying the diffuse vertex component as the source
  3281. for alpha will insure that the alpha is drawn from the alpha value
  3282. you set, whether a texture is selected or not:
  3283. pDevice->SetSamplerState(D3DSAMP_ALPHAOP,D3DTOP_SELECTARG1);
  3284. pDevice->SetSamplerState(D3DSAMP_ALPHAARG1,D3DTA_DIFFUSE);
  3285. If you later need to use the texture alpha as the source, set
  3286. D3DSAMP_ALPHAARG1 to D3DTA_TEXTURE.
  3287. */
  3288. lpDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
  3289. lpDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
  3290. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  3291. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
  3292. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
  3293. for (k=0; k<4; k++) v3[k].Diffuse = D3DCOLOR_RGBA_01(r,g,b,a);
  3294. break;
  3295. case 1:
  3296. // decal
  3297. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  3298. //lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
  3299. //lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
  3300. for (k=0; k<4; k++) v3[k].Diffuse = D3DCOLOR_RGBA_01(r*a,g*a,b*a,1);
  3301. break;
  3302. case 2:
  3303. // additive
  3304. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  3305. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
  3306. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
  3307. for (k=0; k<4; k++) v3[k].Diffuse = D3DCOLOR_RGBA_01(r*a,g*a,b*a,1);
  3308. break;
  3309. case 3:
  3310. // srccolor
  3311. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  3312. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCCOLOR);
  3313. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCCOLOR);
  3314. for (k=0; k<4; k++) v3[k].Diffuse = D3DCOLOR_RGBA_01(1,1,1,1);
  3315. break;
  3316. case 4:
  3317. // color keyed texture: use the alpha value in the texture to
  3318. // determine which texels get drawn.
  3319. /*lpDevice->SetRenderState(D3DRS_ALPHAREF, 0);
  3320. lpDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_NOTEQUAL);
  3321. lpDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
  3322. */
  3323. lpDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
  3324. lpDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
  3325. lpDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE);
  3326. lpDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
  3327. lpDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
  3328. lpDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
  3329. lpDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_TEXTURE);
  3330. lpDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
  3331. // also, smoothly blend this in-between texels:
  3332. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  3333. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
  3334. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
  3335. for (k=0; k<4; k++) v3[k].Diffuse = D3DCOLOR_RGBA_01(r,g,b,a);
  3336. break;
  3337. }
  3338. lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, (LPVOID)v3, sizeof(SPRITEVERTEX));
  3339. if (/*bKillSprite &&*/ bBurnIn) // final render-to-VS1
  3340. {
  3341. // Change the rendertarget back to the original setup
  3342. lpDevice->SetTexture(0, NULL);
  3343. lpDevice->SetRenderTarget( 0, pBackBuffer );
  3344. //lpDevice->SetDepthStencilSurface( pZBuffer );
  3345. lpDevice->SetTexture(0, m_texmgr.m_tex[iSlot].pSurface);
  3346. // undo aspect ratio changes (that were used to fit it to VS1):
  3347. {
  3348. float aspect = GetWidth()/(float)(GetHeight()*4.0f/3.0f);
  3349. if (aspect < 1.0f)
  3350. for (k=0; k<4; k++) v3[k].x /= aspect;
  3351. else
  3352. for (k=0; k<4; k++) v3[k].y *= aspect;
  3353. }
  3354. lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, (LPVOID)v3, sizeof(SPRITEVERTEX));
  3355. }
  3356. SafeRelease(pBackBuffer);
  3357. //SafeRelease(pZBuffer);
  3358. if (bKillSprite)
  3359. {
  3360. KillSprite(iSlot);
  3361. }
  3362. lpDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
  3363. lpDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE );
  3364. lpDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
  3365. }
  3366. }
  3367. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  3368. // reset these to the standard safe mode:
  3369. lpDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
  3370. lpDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
  3371. lpDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE);
  3372. lpDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
  3373. lpDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
  3374. lpDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE );
  3375. lpDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
  3376. }
  3377. void CPlugin::UvToMathSpace(float u, float v, float* rad, float* ang)
  3378. {
  3379. // (screen space = -1..1 on both axes; corresponds to UV space)
  3380. // uv space = [0..1] on both axes
  3381. // "math" space = what the preset authors are used to:
  3382. // upper left = [0,0]
  3383. // bottom right = [1,1]
  3384. // rad == 1 at corners of screen
  3385. // ang == 0 at three o'clock, and increases counter-clockwise (to 6.28).
  3386. float px = (u*2-1) * m_fAspectX; // probably 1.0
  3387. float py = (v*2-1) * m_fAspectY; // probably <1
  3388. *rad = sqrtf(px*px + py*py) / sqrtf(m_fAspectX*m_fAspectX + m_fAspectY*m_fAspectY);
  3389. *ang = atan2f(py, px);
  3390. if (*ang < 0)
  3391. *ang += 6.2831853071796f;
  3392. }
  3393. void CPlugin::RestoreShaderParams()
  3394. {
  3395. LPDIRECT3DDEVICE9 lpDevice = GetDevice();
  3396. int i = 0;
  3397. for (i=0; i<2; i++)
  3398. {
  3399. lpDevice->SetSamplerState(i, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);//texaddr);
  3400. lpDevice->SetSamplerState(i, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);//texaddr);
  3401. lpDevice->SetSamplerState(i, D3DSAMP_ADDRESSW, D3DTADDRESS_WRAP);//texaddr);
  3402. lpDevice->SetSamplerState(i, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
  3403. lpDevice->SetSamplerState(i, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
  3404. lpDevice->SetSamplerState(i, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
  3405. }
  3406. for (i=0; i<4; i++)
  3407. lpDevice->SetTexture( i, NULL );
  3408. lpDevice->SetVertexShader(NULL);
  3409. //lpDevice->SetVertexDeclaration(NULL); -directx debug runtime complains heavily about this
  3410. lpDevice->SetPixelShader(NULL);
  3411. }
  3412. void CPlugin::ApplyShaderParams(CShaderParams* p, LPD3DXCONSTANTTABLE pCT, CState* pState)
  3413. {
  3414. LPDIRECT3DDEVICE9 lpDevice = GetDevice();
  3415. //if (p->texbind_vs >= 0) lpDevice->SetTexture( p->texbind_vs , m_lpVS[0] );
  3416. //if (p->texbind_noise >= 0) lpDevice->SetTexture( p->texbind_noise, m_pTexNoise );
  3417. // bind textures
  3418. int i = 0;
  3419. for (i=0; i<sizeof(p->m_texture_bindings)/sizeof(p->m_texture_bindings[0]); i++)
  3420. {
  3421. if (p->m_texcode[i] == TEX_VS)
  3422. lpDevice->SetTexture(i, m_lpVS[0]);
  3423. else
  3424. lpDevice->SetTexture(i, p->m_texture_bindings[i].texptr);
  3425. // also set up sampler stage, if anything is bound here...
  3426. if (p->m_texcode[i]==TEX_VS || p->m_texture_bindings[i].texptr)
  3427. {
  3428. bool bAniso = false;
  3429. DWORD HQFilter = bAniso ? D3DTEXF_ANISOTROPIC : D3DTEXF_LINEAR;
  3430. DWORD wrap = p->m_texture_bindings[i].bWrap ? D3DTADDRESS_WRAP : D3DTADDRESS_CLAMP;
  3431. DWORD filter = p->m_texture_bindings[i].bBilinear ? HQFilter : D3DTEXF_POINT;
  3432. lpDevice->SetSamplerState(i, D3DSAMP_ADDRESSU, wrap);
  3433. lpDevice->SetSamplerState(i, D3DSAMP_ADDRESSV, wrap);
  3434. lpDevice->SetSamplerState(i, D3DSAMP_ADDRESSW, wrap);
  3435. lpDevice->SetSamplerState(i, D3DSAMP_MAGFILTER, filter);
  3436. lpDevice->SetSamplerState(i, D3DSAMP_MINFILTER, filter);
  3437. lpDevice->SetSamplerState(i, D3DSAMP_MIPFILTER, filter);
  3438. //lpDevice->SetSamplerState(i, D3DSAMP_MAXANISOTROPY, bAniso ? 4 : 1); //FIXME:ANISO
  3439. }
  3440. // finally, if it was a blur texture, note that
  3441. if (p->m_texcode[i] >= TEX_BLUR1 && p->m_texcode[i] <= TEX_BLUR_LAST)
  3442. m_nHighestBlurTexUsedThisFrame = max(m_nHighestBlurTexUsedThisFrame, ((int)p->m_texcode[i] - (int)TEX_BLUR1) + 1);
  3443. }
  3444. // bind "texsize_XYZ" params
  3445. int N = p->texsize_params.size();
  3446. for (i=0; i<N; i++)
  3447. {
  3448. TexSizeParamInfo* q = &(p->texsize_params[i]);
  3449. pCT->SetVector( lpDevice, q->texsize_param, &D3DXVECTOR4((float)q->w,(float)q->h,1.0f/q->w,1.0f/q->h));
  3450. }
  3451. float time_since_preset_start = GetTime() - pState->GetPresetStartTime();
  3452. float time_since_preset_start_wrapped = time_since_preset_start - (int)(time_since_preset_start/10000)*10000;
  3453. float time = GetTime() - m_fStartTime;
  3454. float progress = (GetTime() - m_fPresetStartTime) / (m_fNextPresetTime - m_fPresetStartTime);
  3455. float mip_x = logf((float)GetWidth())/logf(2.0f);
  3456. float mip_y = logf((float)GetWidth())/logf(2.0f);
  3457. float mip_avg = 0.5f*(mip_x + mip_y);
  3458. float aspect_x = 1;
  3459. float aspect_y = 1;
  3460. if (GetWidth() > GetHeight())
  3461. aspect_y = GetHeight()/(float)GetWidth();
  3462. else
  3463. aspect_x = GetWidth()/(float)GetHeight();
  3464. float blur_min[3], blur_max[3];
  3465. GetSafeBlurMinMax(pState, blur_min, blur_max);
  3466. // bind float4's
  3467. if (p->rand_frame ) pCT->SetVector( lpDevice, p->rand_frame , &m_rand_frame );
  3468. if (p->rand_preset) pCT->SetVector( lpDevice, p->rand_preset, &pState->m_rand_preset );
  3469. D3DXHANDLE* h = p->const_handles;
  3470. if (h[0]) pCT->SetVector( lpDevice, h[0], &D3DXVECTOR4( aspect_x, aspect_y, 1.0f/aspect_x, 1.0f/aspect_y ));
  3471. if (h[1]) pCT->SetVector( lpDevice, h[1], &D3DXVECTOR4(0, 0, 0, 0 ));
  3472. if (h[2]) pCT->SetVector( lpDevice, h[2], &D3DXVECTOR4(time_since_preset_start_wrapped, GetFps(), (float)GetFrame(), progress));
  3473. if (h[3]) pCT->SetVector( lpDevice, h[3], &D3DXVECTOR4(mysound.imm_rel[0], mysound.imm_rel[1], mysound.imm_rel[2], 0.3333f*(mysound.imm_rel[0], mysound.imm_rel[1], mysound.imm_rel[2]) ));
  3474. if (h[4]) pCT->SetVector( lpDevice, h[4], &D3DXVECTOR4(mysound.avg_rel[0], mysound.avg_rel[1], mysound.avg_rel[2], 0.3333f*(mysound.avg_rel[0], mysound.avg_rel[1], mysound.avg_rel[2]) ));
  3475. if (h[5]) pCT->SetVector( lpDevice, h[5], &D3DXVECTOR4( blur_max[0]-blur_min[0], blur_min[0], blur_max[1]-blur_min[1], blur_min[1] ));
  3476. if (h[6]) pCT->SetVector( lpDevice, h[6], &D3DXVECTOR4( blur_max[2]-blur_min[2], blur_min[2], blur_min[0], blur_max[0] ));
  3477. if (h[7]) pCT->SetVector( lpDevice, h[7], &D3DXVECTOR4((float)m_nTexSizeX, (float)m_nTexSizeY, 1.0f/(float)m_nTexSizeX, 1.0f/(float)m_nTexSizeY ));
  3478. if (h[8]) pCT->SetVector( lpDevice, h[8], &D3DXVECTOR4( 0.5f+0.5f*cosf(time* 0.329f+1.2f),
  3479. 0.5f+0.5f*cosf(time* 1.293f+3.9f),
  3480. 0.5f+0.5f*cosf(time* 5.070f+2.5f),
  3481. 0.5f+0.5f*cosf(time*20.051f+5.4f)
  3482. ));
  3483. if (h[9]) pCT->SetVector( lpDevice, h[9], &D3DXVECTOR4( 0.5f+0.5f*sinf(time* 0.329f+1.2f),
  3484. 0.5f+0.5f*sinf(time* 1.293f+3.9f),
  3485. 0.5f+0.5f*sinf(time* 5.070f+2.5f),
  3486. 0.5f+0.5f*sinf(time*20.051f+5.4f)
  3487. ));
  3488. if (h[10]) pCT->SetVector( lpDevice, h[10], &D3DXVECTOR4( 0.5f+0.5f*cosf(time*0.0050f+2.7f),
  3489. 0.5f+0.5f*cosf(time*0.0085f+5.3f),
  3490. 0.5f+0.5f*cosf(time*0.0133f+4.5f),
  3491. 0.5f+0.5f*cosf(time*0.0217f+3.8f)
  3492. ));
  3493. if (h[11]) pCT->SetVector( lpDevice, h[11], &D3DXVECTOR4( 0.5f+0.5f*sinf(time*0.0050f+2.7f),
  3494. 0.5f+0.5f*sinf(time*0.0085f+5.3f),
  3495. 0.5f+0.5f*sinf(time*0.0133f+4.5f),
  3496. 0.5f+0.5f*sinf(time*0.0217f+3.8f)
  3497. ));
  3498. if (h[12]) pCT->SetVector( lpDevice, h[12], &D3DXVECTOR4( mip_x, mip_y, mip_avg, 0 ));
  3499. if (h[13]) pCT->SetVector( lpDevice, h[13], &D3DXVECTOR4( blur_min[1], blur_max[1], blur_min[2], blur_max[2] ));
  3500. // write q vars
  3501. int num_q_float4s = sizeof(p->q_const_handles)/sizeof(p->q_const_handles[0]);
  3502. for (i=0; i<num_q_float4s; i++)
  3503. {
  3504. if (p->q_const_handles[i])
  3505. pCT->SetVector( lpDevice, p->q_const_handles[i], &D3DXVECTOR4(
  3506. (float)*pState->var_pf_q[i*4+0],
  3507. (float)*pState->var_pf_q[i*4+1],
  3508. (float)*pState->var_pf_q[i*4+2],
  3509. (float)*pState->var_pf_q[i*4+3] ));
  3510. }
  3511. // write matrices
  3512. for (i=0; i<20; i++)
  3513. {
  3514. if (p->rot_mat[i])
  3515. {
  3516. D3DXMATRIX mx,my,mz,mxlate,temp;
  3517. pMatrixRotationX(&mx, pState->m_rot_base[i].x + pState->m_rot_speed[i].x*time);
  3518. pMatrixRotationY(&my, pState->m_rot_base[i].y + pState->m_rot_speed[i].y*time);
  3519. pMatrixRotationZ(&mz, pState->m_rot_base[i].z + pState->m_rot_speed[i].z*time);
  3520. pMatrixTranslation(&mxlate, pState->m_xlate[i].x, pState->m_xlate[i].y, pState->m_xlate[i].z);
  3521. pMatrixMultiply(&temp, &mx, &mxlate);
  3522. pMatrixMultiply(&temp, &temp, &mz);
  3523. pMatrixMultiply(&temp, &temp, &my);
  3524. pCT->SetMatrix(lpDevice, p->rot_mat[i], &temp);
  3525. }
  3526. }
  3527. // the last 4 are totally random, each frame
  3528. for (i=20; i<24; i++)
  3529. {
  3530. if (p->rot_mat[i])
  3531. {
  3532. D3DXMATRIX mx,my,mz,mxlate,temp;
  3533. pMatrixRotationX(&mx, FRAND * 6.28f);
  3534. pMatrixRotationY(&my, FRAND * 6.28f);
  3535. pMatrixRotationZ(&mz, FRAND * 6.28f);
  3536. pMatrixTranslation(&mxlate, FRAND, FRAND, FRAND);
  3537. pMatrixMultiply(&temp, &mx, &mxlate);
  3538. pMatrixMultiply(&temp, &temp, &mz);
  3539. pMatrixMultiply(&temp, &temp, &my);
  3540. pCT->SetMatrix(lpDevice, p->rot_mat[i], &temp);
  3541. }
  3542. }
  3543. }
  3544. void CPlugin::ShowToUser_NoShaders()//int bRedraw, int nPassOverride)
  3545. {
  3546. // note: this one has to draw the whole screen! (one big quad)
  3547. LPDIRECT3DDEVICE9 lpDevice = GetDevice();
  3548. if (!lpDevice)
  3549. return;
  3550. lpDevice->SetTexture(0, m_lpVS[1]);
  3551. lpDevice->SetVertexShader( NULL );
  3552. lpDevice->SetPixelShader( NULL );
  3553. lpDevice->SetFVF( SPRITEVERTEX_FORMAT );
  3554. // stages 0 and 1 always just use bilinear filtering.
  3555. lpDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
  3556. lpDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
  3557. lpDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
  3558. lpDevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
  3559. lpDevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
  3560. lpDevice->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
  3561. // note: this texture stage state setup works for 0 or 1 texture.
  3562. // if you set a texture, it will be modulated with the current diffuse color.
  3563. // if you don't set a texture, it will just use the current diffuse color.
  3564. lpDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
  3565. lpDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
  3566. lpDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE);
  3567. lpDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
  3568. lpDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
  3569. lpDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE );
  3570. lpDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
  3571. float fZoom = 1.0f;
  3572. SPRITEVERTEX v3[4];
  3573. ZeroMemory(v3, sizeof(SPRITEVERTEX)*4);
  3574. // extend the poly we draw by 1 pixel around the viewable image area,
  3575. // in case the video card wraps u/v coords with a +0.5-texel offset
  3576. // (otherwise, a 1-pixel-wide line of the image would wrap at the top and left edges).
  3577. float fOnePlusInvWidth = 1.0f + 1.0f/(float)GetWidth();
  3578. float fOnePlusInvHeight = 1.0f + 1.0f/(float)GetHeight();
  3579. v3[0].x = -fOnePlusInvWidth;
  3580. v3[1].x = fOnePlusInvWidth;
  3581. v3[2].x = -fOnePlusInvWidth;
  3582. v3[3].x = fOnePlusInvWidth;
  3583. v3[0].y = fOnePlusInvHeight;
  3584. v3[1].y = fOnePlusInvHeight;
  3585. v3[2].y = -fOnePlusInvHeight;
  3586. v3[3].y = -fOnePlusInvHeight;
  3587. //float aspect = GetWidth() / (float)(GetHeight()/(ASPECT)/**4.0f/3.0f*/);
  3588. float aspect = GetWidth() / (float)(GetHeight()*m_fInvAspectY/**4.0f/3.0f*/);
  3589. float x_aspect_mult = 1.0f;
  3590. float y_aspect_mult = 1.0f;
  3591. if (aspect>1)
  3592. y_aspect_mult = aspect;
  3593. else
  3594. x_aspect_mult = 1.0f/aspect;
  3595. for (int n=0; n<4; n++)
  3596. {
  3597. v3[n].x *= x_aspect_mult;
  3598. v3[n].y *= y_aspect_mult;
  3599. }
  3600. {
  3601. float shade[4][3] = {
  3602. { 1.0f, 1.0f, 1.0f },
  3603. { 1.0f, 1.0f, 1.0f },
  3604. { 1.0f, 1.0f, 1.0f },
  3605. { 1.0f, 1.0f, 1.0f } }; // for each vertex, then each comp.
  3606. float fShaderAmount = m_pState->m_fShader.eval(GetTime());
  3607. if (fShaderAmount > 0.001f)
  3608. {
  3609. for (int i=0; i<4; i++)
  3610. {
  3611. shade[i][0] = 0.6f + 0.3f*sinf(GetTime()*30.0f*0.0143f + 3 + i*21 + m_fRandStart[3]);
  3612. shade[i][1] = 0.6f + 0.3f*sinf(GetTime()*30.0f*0.0107f + 1 + i*13 + m_fRandStart[1]);
  3613. shade[i][2] = 0.6f + 0.3f*sinf(GetTime()*30.0f*0.0129f + 6 + i*9 + m_fRandStart[2]);
  3614. float max = ((shade[i][0] > shade[i][1]) ? shade[i][0] : shade[i][1]);
  3615. if (shade[i][2] > max) max = shade[i][2];
  3616. for (int k=0; k<3; k++)
  3617. {
  3618. shade[i][k] /= max;
  3619. shade[i][k] = 0.5f + 0.5f*shade[i][k];
  3620. }
  3621. for (int k=0; k<3; k++)
  3622. {
  3623. shade[i][k] = shade[i][k]*(fShaderAmount) + 1.0f*(1.0f - fShaderAmount);
  3624. }
  3625. v3[i].Diffuse = D3DCOLOR_RGBA_01(shade[i][0],shade[i][1],shade[i][2],1);
  3626. }
  3627. }
  3628. float fVideoEchoZoom = (float)(*m_pState->var_pf_echo_zoom);//m_pState->m_fVideoEchoZoom.eval(GetTime());
  3629. float fVideoEchoAlpha = (float)(*m_pState->var_pf_echo_alpha);//m_pState->m_fVideoEchoAlpha.eval(GetTime());
  3630. int nVideoEchoOrientation = (int) (*m_pState->var_pf_echo_orient) % 4;//m_pState->m_nVideoEchoOrientation;
  3631. float fGammaAdj = (float)(*m_pState->var_pf_gamma);//m_pState->m_fGammaAdj.eval(GetTime());
  3632. if (m_pState->m_bBlending &&
  3633. m_pState->m_fVideoEchoAlpha.eval(GetTime()) > 0.01f &&
  3634. m_pState->m_fVideoEchoAlphaOld > 0.01f &&
  3635. m_pState->m_nVideoEchoOrientation != m_pState->m_nVideoEchoOrientationOld)
  3636. {
  3637. if (m_pState->m_fBlendProgress < m_fSnapPoint)
  3638. {
  3639. nVideoEchoOrientation = m_pState->m_nVideoEchoOrientationOld;
  3640. fVideoEchoAlpha *= 1.0f - 2.0f*CosineInterp(m_pState->m_fBlendProgress);
  3641. }
  3642. else
  3643. {
  3644. fVideoEchoAlpha *= 2.0f*CosineInterp(m_pState->m_fBlendProgress) - 1.0f;
  3645. }
  3646. }
  3647. if (fVideoEchoAlpha > 0.001f)
  3648. {
  3649. // video echo
  3650. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  3651. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
  3652. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
  3653. for (int i=0; i<2; i++)
  3654. {
  3655. fZoom = (i==0) ? 1.0f : fVideoEchoZoom;
  3656. float temp_lo = 0.5f - 0.5f/fZoom;
  3657. float temp_hi = 0.5f + 0.5f/fZoom;
  3658. v3[0].tu = temp_lo;
  3659. v3[0].tv = temp_hi;
  3660. v3[1].tu = temp_hi;
  3661. v3[1].tv = temp_hi;
  3662. v3[2].tu = temp_lo;
  3663. v3[2].tv = temp_lo;
  3664. v3[3].tu = temp_hi;
  3665. v3[3].tv = temp_lo;
  3666. // flipping
  3667. if (i==1)
  3668. {
  3669. for (int j=0; j<4; j++)
  3670. {
  3671. if (nVideoEchoOrientation % 2)
  3672. v3[j].tu = 1.0f - v3[j].tu;
  3673. if (nVideoEchoOrientation >= 2)
  3674. v3[j].tv = 1.0f - v3[j].tv;
  3675. }
  3676. }
  3677. float mix = (i==1) ? fVideoEchoAlpha : 1.0f - fVideoEchoAlpha;
  3678. for (int k=0; k<4; k++)
  3679. v3[k].Diffuse = D3DCOLOR_RGBA_01(mix*shade[k][0],mix*shade[k][1],mix*shade[k][2],1);
  3680. lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, (void*)v3, sizeof(SPRITEVERTEX));
  3681. if (i==0)
  3682. {
  3683. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
  3684. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
  3685. }
  3686. if (fGammaAdj > 0.001f)
  3687. {
  3688. // draw layer 'i' a 2nd (or 3rd, or 4th...) time, additively
  3689. int nRedraws = (int)(fGammaAdj - 0.0001f);
  3690. float gamma;
  3691. for (int nRedraw=0; nRedraw < nRedraws; nRedraw++)
  3692. {
  3693. if (nRedraw == nRedraws-1)
  3694. gamma = fGammaAdj - (int)(fGammaAdj - 0.0001f);
  3695. else
  3696. gamma = 1.0f;
  3697. for (int k=0; k<4; k++)
  3698. v3[k].Diffuse = D3DCOLOR_RGBA_01(gamma*mix*shade[k][0],gamma*mix*shade[k][1],gamma*mix*shade[k][2],1);
  3699. lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, (void*)v3, sizeof(SPRITEVERTEX));
  3700. }
  3701. }
  3702. }
  3703. }
  3704. else
  3705. {
  3706. // no video echo
  3707. v3[0].tu = 0; v3[1].tu = 1; v3[2].tu = 0; v3[3].tu = 1;
  3708. v3[0].tv = 1; v3[1].tv = 1; v3[2].tv = 0; v3[3].tv = 0;
  3709. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  3710. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
  3711. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
  3712. // draw it iteratively, solid the first time, and additively after that
  3713. int nPasses = (int)(fGammaAdj - 0.001f) + 1;
  3714. float gamma;
  3715. for (int nPass=0; nPass < nPasses; nPass++)
  3716. {
  3717. if (nPass == nPasses - 1)
  3718. gamma = fGammaAdj - (float)nPass;
  3719. else
  3720. gamma = 1.0f;
  3721. for (int k=0; k<4; k++)
  3722. v3[k].Diffuse = D3DCOLOR_RGBA_01(gamma*shade[k][0],gamma*shade[k][1],gamma*shade[k][2],1);
  3723. lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, (void*)v3, sizeof(SPRITEVERTEX));
  3724. if (nPass==0)
  3725. {
  3726. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  3727. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
  3728. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
  3729. }
  3730. }
  3731. }
  3732. SPRITEVERTEX v3[4];
  3733. ZeroMemory(v3, sizeof(SPRITEVERTEX)*4);
  3734. float fOnePlusInvWidth = 1.0f + 1.0f/(float)GetWidth();
  3735. float fOnePlusInvHeight = 1.0f + 1.0f/(float)GetHeight();
  3736. v3[0].x = -fOnePlusInvWidth;
  3737. v3[1].x = fOnePlusInvWidth;
  3738. v3[2].x = -fOnePlusInvWidth;
  3739. v3[3].x = fOnePlusInvWidth;
  3740. v3[0].y = fOnePlusInvHeight;
  3741. v3[1].y = fOnePlusInvHeight;
  3742. v3[2].y = -fOnePlusInvHeight;
  3743. v3[3].y = -fOnePlusInvHeight;
  3744. for (int i=0; i<4; i++) v3[i].Diffuse = D3DCOLOR_RGBA_01(1,1,1,1);
  3745. if (*m_pState->var_pf_brighten &&
  3746. (GetCaps()->SrcBlendCaps & D3DPBLENDCAPS_INVDESTCOLOR ) &&
  3747. (GetCaps()->DestBlendCaps & D3DPBLENDCAPS_DESTCOLOR)
  3748. )
  3749. {
  3750. // square root filter
  3751. //lpDevice->SetRenderState(D3DRS_COLORVERTEX, FALSE); //?
  3752. //lpDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT); //?
  3753. lpDevice->SetTexture(0, NULL);
  3754. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  3755. // first, a perfect invert
  3756. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_INVDESTCOLOR);
  3757. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
  3758. lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, (void*)v3, sizeof(SPRITEVERTEX));
  3759. // then modulate by self (square it)
  3760. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
  3761. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_DESTCOLOR);
  3762. lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, (void*)v3, sizeof(SPRITEVERTEX));
  3763. // then another perfect invert
  3764. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_INVDESTCOLOR);
  3765. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
  3766. lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, (void*)v3, sizeof(SPRITEVERTEX));
  3767. }
  3768. if (*m_pState->var_pf_darken &&
  3769. (GetCaps()->DestBlendCaps & D3DPBLENDCAPS_DESTCOLOR)
  3770. )
  3771. {
  3772. // squaring filter
  3773. //lpDevice->SetRenderState(D3DRS_COLORVERTEX, FALSE); //?
  3774. //lpDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT); //?
  3775. lpDevice->SetTexture(0, NULL);
  3776. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  3777. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
  3778. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_DESTCOLOR);
  3779. lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, (void*)v3, sizeof(SPRITEVERTEX));
  3780. //lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_DESTCOLOR);
  3781. //lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
  3782. //lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, (void*)v3, sizeof(SPRITEVERTEX));
  3783. }
  3784. if (*m_pState->var_pf_solarize &&
  3785. (GetCaps()->SrcBlendCaps & D3DPBLENDCAPS_DESTCOLOR ) &&
  3786. (GetCaps()->DestBlendCaps & D3DPBLENDCAPS_INVDESTCOLOR)
  3787. )
  3788. {
  3789. //lpDevice->SetRenderState(D3DRS_COLORVERTEX, FALSE); //?
  3790. //lpDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT); //?
  3791. lpDevice->SetTexture(0, NULL);
  3792. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  3793. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
  3794. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVDESTCOLOR);
  3795. lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, (void*)v3, sizeof(SPRITEVERTEX));
  3796. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_DESTCOLOR);
  3797. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
  3798. lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, (void*)v3, sizeof(SPRITEVERTEX));
  3799. }
  3800. if (*m_pState->var_pf_invert &&
  3801. (GetCaps()->SrcBlendCaps & D3DPBLENDCAPS_INVDESTCOLOR )
  3802. )
  3803. {
  3804. //lpDevice->SetRenderState(D3DRS_COLORVERTEX, FALSE); //?
  3805. //lpDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT); //?
  3806. lpDevice->SetTexture(0, NULL);
  3807. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  3808. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_INVDESTCOLOR);
  3809. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
  3810. lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, (void*)v3, sizeof(SPRITEVERTEX));
  3811. }
  3812. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  3813. }
  3814. }
  3815. void CPlugin::ShowToUser_Shaders(int nPass, bool bAlphaBlend, bool bFlipAlpha, bool bCullTiles, bool bFlipCulling)//int bRedraw, int nPassOverride, bool bFlipAlpha)
  3816. {
  3817. LPDIRECT3DDEVICE9 lpDevice = GetDevice();
  3818. if (!lpDevice)
  3819. return;
  3820. //lpDevice->SetTexture(0, m_lpVS[1]);
  3821. lpDevice->SetVertexShader( NULL );
  3822. lpDevice->SetFVF( MYVERTEX_FORMAT );
  3823. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  3824. float fZoom = 1.0f;
  3825. float aspect = GetWidth() / (float)(GetHeight()*m_fInvAspectY/**4.0f/3.0f*/);
  3826. float x_aspect_mult = 1.0f;
  3827. float y_aspect_mult = 1.0f;
  3828. if (aspect>1)
  3829. y_aspect_mult = aspect;
  3830. else
  3831. x_aspect_mult = 1.0f/aspect;
  3832. // hue shader
  3833. float shade[4][3] = {
  3834. { 1.0f, 1.0f, 1.0f },
  3835. { 1.0f, 1.0f, 1.0f },
  3836. { 1.0f, 1.0f, 1.0f },
  3837. { 1.0f, 1.0f, 1.0f } }; // for each vertex, then each comp.
  3838. float fShaderAmount = 1;//since we don't know if shader uses it or not! m_pState->m_fShader.eval(GetTime());
  3839. if (fShaderAmount > 0.001f || m_pState->m_bBlending)
  3840. {
  3841. // pick 4 colors for the 4 corners
  3842. for (int i=0; i<4; i++)
  3843. {
  3844. shade[i][0] = 0.6f + 0.3f*sinf(GetTime()*30.0f*0.0143f + 3 + i*21 + m_fRandStart[3]);
  3845. shade[i][1] = 0.6f + 0.3f*sinf(GetTime()*30.0f*0.0107f + 1 + i*13 + m_fRandStart[1]);
  3846. shade[i][2] = 0.6f + 0.3f*sinf(GetTime()*30.0f*0.0129f + 6 + i*9 + m_fRandStart[2]);
  3847. float max = ((shade[i][0] > shade[i][1]) ? shade[i][0] : shade[i][1]);
  3848. if (shade[i][2] > max) max = shade[i][2];
  3849. for (int k=0; k<3; k++)
  3850. {
  3851. shade[i][k] /= max;
  3852. shade[i][k] = 0.5f + 0.5f*shade[i][k];
  3853. }
  3854. // note: we now pass the raw hue shader colors down; the shader can only use a certain % if it wants.
  3855. //for (k=0; k<3; k++)
  3856. // shade[i][k] = shade[i][k]*(fShaderAmount) + 1.0f*(1.0f - fShaderAmount);
  3857. //m_comp_verts[i].Diffuse = D3DCOLOR_RGBA_01(shade[i][0],shade[i][1],shade[i][2],1);
  3858. }
  3859. // interpolate the 4 colors & apply to all the verts
  3860. for (int j=0; j<FCGSY; j++)
  3861. {
  3862. for (int i=0; i<FCGSX; i++)
  3863. {
  3864. MYVERTEX* p = &m_comp_verts[i + j*FCGSX];
  3865. float x = p->x*0.5f + 0.5f;
  3866. float y = p->y*0.5f + 0.5f;
  3867. float col[3] = { 1, 1, 1 };
  3868. if (fShaderAmount > 0.001f)
  3869. {
  3870. for (int c=0; c<3; c++)
  3871. col[c] = shade[0][c]*( x)*( y) +
  3872. shade[1][c]*(1-x)*( y) +
  3873. shade[2][c]*( x)*(1-y) +
  3874. shade[3][c]*(1-x)*(1-y);
  3875. }
  3876. // TO DO: improve interp here?
  3877. // TO DO: during blend, only send the triangles needed
  3878. // if blending, also set up the alpha values - pull them from the alphas used for the Warped Blit
  3879. double alpha = 1;
  3880. if (m_pState->m_bBlending)
  3881. {
  3882. x *= (m_nGridX + 1);
  3883. y *= (m_nGridY + 1);
  3884. x = max(min(x,m_nGridX-1),0);
  3885. y = max(min(y,m_nGridY-1),0);
  3886. int nx = (int)x;
  3887. int ny = (int)y;
  3888. double dx = x - nx;
  3889. double dy = y - ny;
  3890. double alpha00 = (m_verts[(ny )*(m_nGridX+1) + (nx )].Diffuse >> 24);
  3891. double alpha01 = (m_verts[(ny )*(m_nGridX+1) + (nx+1)].Diffuse >> 24);
  3892. double alpha10 = (m_verts[(ny+1)*(m_nGridX+1) + (nx )].Diffuse >> 24);
  3893. double alpha11 = (m_verts[(ny+1)*(m_nGridX+1) + (nx+1)].Diffuse >> 24);
  3894. alpha = alpha00*(1-dx)*(1-dy) +
  3895. alpha01*( dx)*(1-dy) +
  3896. alpha10*(1-dx)*( dy) +
  3897. alpha11*( dx)*( dy);
  3898. alpha /= 255.0f;
  3899. //if (bFlipAlpha)
  3900. // alpha = 1-alpha;
  3901. //alpha = (m_verts[y*(m_nGridX+1) + x].Diffuse >> 24) / 255.0f;
  3902. }
  3903. p->Diffuse = D3DCOLOR_RGBA_01(col[0],col[1],col[2],alpha);
  3904. }
  3905. }
  3906. }
  3907. int nAlphaTestValue = 0;
  3908. if (bFlipCulling)
  3909. nAlphaTestValue = 1-nAlphaTestValue;
  3910. if (bAlphaBlend)
  3911. {
  3912. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  3913. if (bFlipAlpha)
  3914. {
  3915. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_INVSRCALPHA);
  3916. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_SRCALPHA);
  3917. }
  3918. else
  3919. {
  3920. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
  3921. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
  3922. }
  3923. }
  3924. else
  3925. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  3926. // Now do the final composite blit, fullscreen;
  3927. // or do it twice, alpha-blending, if we're blending between two sets of shaders.
  3928. int pass = nPass;
  3929. {
  3930. // PASS 0: draw using *blended per-vertex motion vectors*, but with the OLD comp shader.
  3931. // PASS 1: draw using *blended per-vertex motion vectors*, but with the NEW comp shader.
  3932. PShaderInfo* si = (pass==0) ? &m_OldShaders.comp : &m_shaders.comp;
  3933. CState* state = (pass==0) ? m_pOldState : m_pState;
  3934. lpDevice->SetVertexDeclaration(m_pMyVertDecl);
  3935. lpDevice->SetVertexShader(m_fallbackShaders_vs.comp.ptr);
  3936. lpDevice->SetPixelShader (si->ptr);
  3937. ApplyShaderParams( &(si->params), si->CT, state );
  3938. // Hurl the triangles at the video card.
  3939. // We're going to un-index it, so that we don't stress any crappy (AHEM intel g33)
  3940. // drivers out there. Not a big deal - only ~800 polys / 24kb of data.
  3941. // If we're blending, we'll skip any polygon that is all alpha-blended out.
  3942. // This also respects the MaxPrimCount limit of the video card.
  3943. MYVERTEX tempv[1024 * 3];
  3944. int primCount = (FCGSX-2)*(FCGSY-2)*2; // although, some might not be drawn!
  3945. int max_prims_per_batch = min( GetCaps()->MaxPrimitiveCount, (sizeof(tempv)/sizeof(tempv[0]))/3) - 4;
  3946. int src_idx = 0;
  3947. while (src_idx < primCount*3)
  3948. {
  3949. int prims_queued = 0;
  3950. int i=0;
  3951. while (prims_queued < max_prims_per_batch && src_idx < primCount*3)
  3952. {
  3953. // copy 3 verts
  3954. for (int j=0; j<3; j++)
  3955. tempv[i++] = m_comp_verts[ m_comp_indices[src_idx++] ];
  3956. if (bCullTiles)
  3957. {
  3958. DWORD d1 = (tempv[i-3].Diffuse >> 24);
  3959. DWORD d2 = (tempv[i-2].Diffuse >> 24);
  3960. DWORD d3 = (tempv[i-1].Diffuse >> 24);
  3961. bool bIsNeeded;
  3962. if (nAlphaTestValue)
  3963. bIsNeeded = ((d1 & d2 & d3) < 255);//(d1 < 255) || (d2 < 255) || (d3 < 255);
  3964. else
  3965. bIsNeeded = ((d1|d2|d3) > 0);//(d1 > 0) || (d2 > 0) || (d3 > 0);
  3966. if (!bIsNeeded)
  3967. i -= 3;
  3968. else
  3969. prims_queued++;
  3970. }
  3971. else
  3972. prims_queued++;
  3973. }
  3974. if (prims_queued > 0)
  3975. lpDevice->DrawPrimitiveUP( D3DPT_TRIANGLELIST, prims_queued, tempv, sizeof(MYVERTEX) );
  3976. }
  3977. }
  3978. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  3979. RestoreShaderParams();
  3980. }
  3981. void CPlugin::ShowSongTitleAnim(int w, int h, float fProgress)
  3982. {
  3983. int i,x,y;
  3984. if (!m_lpDDSTitle) // this *can* be NULL, if not much video mem!
  3985. return;
  3986. LPDIRECT3DDEVICE9 lpDevice = GetDevice();
  3987. if (!lpDevice)
  3988. return;
  3989. lpDevice->SetTexture(0, m_lpDDSTitle);
  3990. lpDevice->SetVertexShader( NULL );
  3991. lpDevice->SetFVF( SPRITEVERTEX_FORMAT );
  3992. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  3993. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
  3994. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
  3995. SPRITEVERTEX v3[128];
  3996. ZeroMemory(v3, sizeof(SPRITEVERTEX)*128);
  3997. if (m_supertext.bIsSongTitle)
  3998. {
  3999. // positioning:
  4000. float fSizeX = 50.0f / (float)m_supertext.nFontSizeUsed * powf(1.5f, m_supertext.fFontSize - 2.0f);
  4001. float fSizeY = fSizeX * m_nTitleTexSizeY/(float)m_nTitleTexSizeX;// * m_nWidth/(float)m_nHeight;
  4002. if (fSizeX > 0.88f)
  4003. {
  4004. fSizeY *= 0.88f/fSizeX;
  4005. fSizeX = 0.88f;
  4006. }
  4007. //fixme
  4008. if (fProgress < 1.0f)//(w!=h) // regular render-to-backbuffer
  4009. {
  4010. //float aspect = w/(float)(h*4.0f/3.0f);
  4011. //fSizeY *= aspect;
  4012. }
  4013. else // final render-to-VS0
  4014. {
  4015. //float aspect = GetWidth()/(float)(GetHeight()*4.0f/3.0f);
  4016. //if (aspect < 1.0f)
  4017. //{
  4018. // fSizeX *= aspect;
  4019. // fSizeY *= aspect;
  4020. //}
  4021. //fSizeY *= -1;
  4022. }
  4023. //if (fSizeX > 0.92f) fSizeX = 0.92f;
  4024. //if (fSizeY > 0.92f) fSizeY = 0.92f;
  4025. i = 0;
  4026. float vert_clip = VERT_CLIP;//1.0f;//0.45f; // warning: visible clipping has been observed at 0.4!
  4027. for (y=0; y<8; y++)
  4028. {
  4029. for (x=0; x<16; x++)
  4030. {
  4031. v3[i].tu = x/15.0f;
  4032. v3[i].tv = (y/7.0f - 0.5f)*vert_clip + 0.5f;
  4033. v3[i].x = (v3[i].tu*2.0f - 1.0f)*fSizeX;
  4034. v3[i].y = (v3[i].tv*2.0f - 1.0f)*fSizeY;
  4035. if (fProgress >= 1.0f)
  4036. v3[i].y += 1.0f/(float)m_nTexSizeY; //this is a pretty hacky guess @ getting it to align...
  4037. i++;
  4038. }
  4039. }
  4040. // warping
  4041. float ramped_progress = max(0.0f, 1-fProgress*1.5f);
  4042. float t2 = powf(ramped_progress, 1.8f)*1.3f;
  4043. for (y=0; y<8; y++)
  4044. {
  4045. for (x=0; x<16; x++)
  4046. {
  4047. i = y*16+x;
  4048. v3[i].x += t2*0.070f*sinf(GetTime()*0.31f + v3[i].x*0.39f - v3[i].y*1.94f);
  4049. v3[i].x += t2*0.044f*sinf(GetTime()*0.81f - v3[i].x*1.91f + v3[i].y*0.27f);
  4050. v3[i].x += t2*0.061f*sinf(GetTime()*1.31f + v3[i].x*0.61f + v3[i].y*0.74f);
  4051. v3[i].y += t2*0.061f*sinf(GetTime()*0.37f + v3[i].x*1.83f + v3[i].y*0.69f);
  4052. v3[i].y += t2*0.070f*sinf(GetTime()*0.67f + v3[i].x*0.42f - v3[i].y*1.39f);
  4053. v3[i].y += t2*0.087f*sinf(GetTime()*1.07f + v3[i].x*3.55f + v3[i].y*0.89f);
  4054. }
  4055. }
  4056. // scale down over time
  4057. float scale = 1.01f/(powf(fProgress, 0.21f) + 0.01f);
  4058. for (i=0; i<128; i++)
  4059. {
  4060. v3[i].x *= scale;
  4061. v3[i].y *= scale;
  4062. }
  4063. }
  4064. else
  4065. {
  4066. // positioning:
  4067. float fSizeX = (float)m_nTexSizeX/1024.0f * 100.0f / (float)m_supertext.nFontSizeUsed * powf(1.033f, m_supertext.fFontSize - 50.0f);
  4068. float fSizeY = fSizeX * m_nTitleTexSizeY/(float)m_nTitleTexSizeX;
  4069. //fixme
  4070. if (fProgress < 1.0f)//w!=h) // regular render-to-backbuffer
  4071. {
  4072. //float aspect = w/(float)(h*4.0f/3.0f);
  4073. //fSizeY *= aspect;
  4074. }
  4075. else // final render-to-VS0
  4076. {
  4077. //float aspect = GetWidth()/(float)(GetHeight()*4.0f/3.0f);
  4078. //if (aspect < 1.0f)
  4079. //{
  4080. // fSizeX *= aspect;
  4081. // fSizeY *= aspect;
  4082. //}
  4083. //fSizeY *= -1;
  4084. }
  4085. //if (fSize > 0.92f) fSize = 0.92f;
  4086. i = 0;
  4087. float vert_clip = VERT_CLIP;//0.67f; // warning: visible clipping has been observed at 0.5 (for very short strings) and even 0.6 (for wingdings)!
  4088. for (y=0; y<8; y++)
  4089. {
  4090. for (x=0; x<16; x++)
  4091. {
  4092. v3[i].tu = x/15.0f;
  4093. v3[i].tv = (y/7.0f - 0.5f)*vert_clip + 0.5f;
  4094. v3[i].x = (v3[i].tu*2.0f - 1.0f)*fSizeX;
  4095. v3[i].y = (v3[i].tv*2.0f - 1.0f)*fSizeY;
  4096. if (fProgress >= 1.0f)
  4097. v3[i].y += 1.0f/(float)m_nTexSizeY; //this is a pretty hacky guess @ getting it to align...
  4098. i++;
  4099. }
  4100. }
  4101. // apply 'growth' factor and move to user-specified (x,y)
  4102. //if (fabsf(m_supertext.fGrowth-1.0f) > 0.001f)
  4103. {
  4104. float t = (1.0f)*(1-fProgress) + (fProgress)*(m_supertext.fGrowth);
  4105. float dx = (m_supertext.fX*2-1);
  4106. float dy = (m_supertext.fY*2-1);
  4107. if (w!=h) // regular render-to-backbuffer
  4108. {
  4109. float aspect = w/(float)(h*4.0f/3.0f);
  4110. if (aspect < 1)
  4111. dx /= aspect;
  4112. else
  4113. dy *= aspect;
  4114. }
  4115. for (i=0; i<128; i++)
  4116. {
  4117. // note: (x,y) are in (-1,1) range, but m_supertext.f{X|Y} are in (0..1) range
  4118. v3[i].x = (v3[i].x)*t + dx;
  4119. v3[i].y = (v3[i].y)*t + dy;
  4120. }
  4121. }
  4122. }
  4123. WORD indices[7*15*6];
  4124. i = 0;
  4125. for (y=0; y<7; y++)
  4126. {
  4127. for (x=0; x<15; x++)
  4128. {
  4129. indices[i++] = y*16 + x;
  4130. indices[i++] = y*16 + x + 1;
  4131. indices[i++] = y*16 + x + 16;
  4132. indices[i++] = y*16 + x + 1;
  4133. indices[i++] = y*16 + x + 16;
  4134. indices[i++] = y*16 + x + 17;
  4135. }
  4136. }
  4137. // final flip on y
  4138. //for (i=0; i<128; i++)
  4139. // v3[i].y *= -1.0f;
  4140. for (i=0; i<128; i++)
  4141. //v3[i].y /= ASPECT_Y;
  4142. v3[i].y *= m_fInvAspectY;
  4143. for (int it=0; it<2; it++)
  4144. {
  4145. // colors
  4146. {
  4147. float t;
  4148. if (m_supertext.bIsSongTitle)
  4149. t = powf(fProgress, 0.3f)*1.0f;
  4150. else
  4151. t = CosineInterp(min(1.0f, (fProgress/m_supertext.fFadeTime)));
  4152. if (it==0)
  4153. v3[0].Diffuse = D3DCOLOR_RGBA_01(t,t,t,t);
  4154. else
  4155. v3[0].Diffuse = D3DCOLOR_RGBA_01(t*m_supertext.nColorR/255.0f,t*m_supertext.nColorG/255.0f,t*m_supertext.nColorB/255.0f,t);
  4156. for (i=1; i<128; i++)
  4157. v3[i].Diffuse = v3[0].Diffuse;
  4158. }
  4159. // nudge down & right for shadow, up & left for solid text
  4160. float offset_x = 0, offset_y = 0;
  4161. switch(it)
  4162. {
  4163. case 0:
  4164. offset_x = 2.0f/(float)m_nTitleTexSizeX;
  4165. offset_y = 2.0f/(float)m_nTitleTexSizeY;
  4166. break;
  4167. case 1:
  4168. offset_x = -4.0f/(float)m_nTitleTexSizeX;
  4169. offset_y = -4.0f/(float)m_nTitleTexSizeY;
  4170. break;
  4171. }
  4172. for (i=0; i<128; i++)
  4173. {
  4174. v3[i].x += offset_x;
  4175. v3[i].y += offset_y;
  4176. }
  4177. if (it == 0)
  4178. {
  4179. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);//SRCALPHA);
  4180. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCCOLOR);
  4181. }
  4182. else
  4183. {
  4184. lpDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);//SRCALPHA);
  4185. lpDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
  4186. }
  4187. lpDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, 128, 15*7*6/3, indices, D3DFMT_INDEX16, v3, sizeof(SPRITEVERTEX));
  4188. }
  4189. lpDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  4190. }