1
0

shader_test.go 59 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829
  1. // Copyright 2020 The Ebiten Authors
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package ebiten_test
  15. import (
  16. "fmt"
  17. "image"
  18. "image/color"
  19. "math"
  20. "testing"
  21. "github.com/hajimehoshi/ebiten/v2"
  22. "github.com/hajimehoshi/ebiten/v2/internal/builtinshader"
  23. )
  24. func TestShaderFill(t *testing.T) {
  25. const w, h = 16, 16
  26. dst := ebiten.NewImage(w, h)
  27. s, err := ebiten.NewShader([]byte(`//kage:unit pixels
  28. package main
  29. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  30. return vec4(1, 0, 0, 1)
  31. }
  32. `))
  33. if err != nil {
  34. t.Fatal(err)
  35. }
  36. dst.DrawRectShader(w/2, h/2, s, nil)
  37. for j := 0; j < h; j++ {
  38. for i := 0; i < w; i++ {
  39. got := dst.At(i, j).(color.RGBA)
  40. var want color.RGBA
  41. if i < w/2 && j < h/2 {
  42. want = color.RGBA{R: 0xff, A: 0xff}
  43. }
  44. if got != want {
  45. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  46. }
  47. }
  48. }
  49. }
  50. func TestShaderFillWithDrawImage(t *testing.T) {
  51. const w, h = 16, 16
  52. dst := ebiten.NewImage(w, h)
  53. s, err := ebiten.NewShader([]byte(`//kage:unit pixels
  54. package main
  55. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  56. return vec4(1, 0, 0, 1)
  57. }
  58. `))
  59. if err != nil {
  60. t.Fatal(err)
  61. }
  62. src := ebiten.NewImage(w/2, h/2)
  63. op := &ebiten.DrawRectShaderOptions{}
  64. op.Images[0] = src
  65. dst.DrawRectShader(w/2, h/2, s, op)
  66. for j := 0; j < h; j++ {
  67. for i := 0; i < w; i++ {
  68. got := dst.At(i, j).(color.RGBA)
  69. var want color.RGBA
  70. if i < w/2 && j < h/2 {
  71. want = color.RGBA{R: 0xff, A: 0xff}
  72. }
  73. if got != want {
  74. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  75. }
  76. }
  77. }
  78. }
  79. // Issue #2525
  80. func TestShaderWithDrawImageDoesNotWreckTextureUnits(t *testing.T) {
  81. const w, h = 16, 16
  82. rect := image.Rectangle{Max: image.Point{X: w, Y: h}}
  83. dst := ebiten.NewImageWithOptions(rect, &ebiten.NewImageOptions{Unmanaged: true})
  84. s, err := ebiten.NewShader([]byte(`//kage:unit pixels
  85. package main
  86. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  87. return imageSrc0At(srcPos)
  88. }
  89. `))
  90. if err != nil {
  91. t.Fatal(err)
  92. }
  93. src0 := ebiten.NewImageWithOptions(rect, &ebiten.NewImageOptions{Unmanaged: true})
  94. src0.Fill(color.RGBA{R: 25, G: 0xff, B: 25, A: 0xff})
  95. src1 := ebiten.NewImageWithOptions(rect, &ebiten.NewImageOptions{Unmanaged: true})
  96. src1.Fill(color.RGBA{R: 0xff, A: 0xff})
  97. op := &ebiten.DrawRectShaderOptions{}
  98. op.CompositeMode = ebiten.CompositeModeCopy
  99. op.Images[0] = src0
  100. op.Images[1] = src1
  101. dst.DrawRectShader(w, h, s, op)
  102. op.Images[0] = src1
  103. op.Images[1] = nil
  104. dst.DrawRectShader(w, h, s, op) // dst should now be identical to src1.
  105. // With issue #2525, instead, GL_TEXTURE0 is active but with src0 bound
  106. // while binding src1 gets skipped!
  107. // This means that src0, not src1, got copied to dst.
  108. // Demonstrate the bug with a write to src1, which will actually end up on src0.
  109. // Validated later.
  110. var buf []byte
  111. for i := 0; i < w*h; i++ {
  112. buf = append(buf, 2, 5, 2, 5)
  113. }
  114. src1.WritePixels(buf)
  115. // Verify that src1 was copied to dst.
  116. for j := 0; j < h; j++ {
  117. for i := 0; i < w; i++ {
  118. got := dst.At(i, j).(color.RGBA)
  119. want := color.RGBA{R: 0xff, A: 0xff}
  120. if got != want {
  121. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  122. }
  123. }
  124. }
  125. // Fix up texture unit assignment by binding a different texture.
  126. op.Images[0] = src1
  127. dst.DrawRectShader(w, h, s, op)
  128. op.Images[0] = src0
  129. dst.DrawRectShader(w, h, s, op)
  130. // Verify that src0 was copied to dst and not overwritten above.
  131. for j := 0; j < h; j++ {
  132. for i := 0; i < w; i++ {
  133. got := dst.At(i, j).(color.RGBA)
  134. want := color.RGBA{R: 25, G: 0xff, B: 25, A: 0xff}
  135. if got != want {
  136. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  137. }
  138. }
  139. }
  140. }
  141. func TestShaderFillWithDrawTriangles(t *testing.T) {
  142. const w, h = 16, 16
  143. dst := ebiten.NewImage(w, h)
  144. s, err := ebiten.NewShader([]byte(`//kage:unit pixels
  145. package main
  146. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  147. return vec4(1, 0, 0, 1)
  148. }
  149. `))
  150. if err != nil {
  151. t.Fatal(err)
  152. }
  153. src := ebiten.NewImage(w/2, h/2)
  154. op := &ebiten.DrawTrianglesShaderOptions{}
  155. op.Images[0] = src
  156. vs := []ebiten.Vertex{
  157. {
  158. DstX: 0,
  159. DstY: 0,
  160. SrcX: 0,
  161. SrcY: 0,
  162. ColorR: 1,
  163. ColorG: 1,
  164. ColorB: 1,
  165. ColorA: 1,
  166. },
  167. {
  168. DstX: w,
  169. DstY: 0,
  170. SrcX: w / 2,
  171. SrcY: 0,
  172. ColorR: 1,
  173. ColorG: 1,
  174. ColorB: 1,
  175. ColorA: 1,
  176. },
  177. {
  178. DstX: 0,
  179. DstY: h,
  180. SrcX: 0,
  181. SrcY: h / 2,
  182. ColorR: 1,
  183. ColorG: 1,
  184. ColorB: 1,
  185. ColorA: 1,
  186. },
  187. {
  188. DstX: w,
  189. DstY: h,
  190. SrcX: w / 2,
  191. SrcY: h / 2,
  192. ColorR: 1,
  193. ColorG: 1,
  194. ColorB: 1,
  195. ColorA: 1,
  196. },
  197. }
  198. is := []uint16{0, 1, 2, 1, 2, 3}
  199. dst.DrawTrianglesShader(vs, is, s, op)
  200. for j := 0; j < h; j++ {
  201. for i := 0; i < w; i++ {
  202. got := dst.At(i, j).(color.RGBA)
  203. want := color.RGBA{R: 0xff, A: 0xff}
  204. if got != want {
  205. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  206. }
  207. }
  208. }
  209. }
  210. func TestShaderFunction(t *testing.T) {
  211. const w, h = 16, 16
  212. dst := ebiten.NewImage(w, h)
  213. s, err := ebiten.NewShader([]byte(`//kage:unit pixels
  214. package main
  215. func clr(red float) (float, float, float, float) {
  216. return red, 0, 0, 1
  217. }
  218. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  219. return vec4(clr(1))
  220. }
  221. `))
  222. if err != nil {
  223. t.Fatal(err)
  224. }
  225. dst.DrawRectShader(w, h, s, nil)
  226. for j := 0; j < h; j++ {
  227. for i := 0; i < w; i++ {
  228. got := dst.At(i, j).(color.RGBA)
  229. want := color.RGBA{R: 0xff, A: 0xff}
  230. if got != want {
  231. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  232. }
  233. }
  234. }
  235. }
  236. func TestShaderUninitializedUniformVariables(t *testing.T) {
  237. const w, h = 16, 16
  238. dst := ebiten.NewImage(w, h)
  239. s, err := ebiten.NewShader([]byte(`//kage:unit pixels
  240. package main
  241. var U vec4
  242. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  243. return U
  244. }
  245. `))
  246. if err != nil {
  247. t.Fatal(err)
  248. }
  249. dst.DrawRectShader(w, h, s, nil)
  250. for j := 0; j < h; j++ {
  251. for i := 0; i < w; i++ {
  252. got := dst.At(i, j).(color.RGBA)
  253. var want color.RGBA
  254. if got != want {
  255. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  256. }
  257. }
  258. }
  259. }
  260. func TestShaderMatrix(t *testing.T) {
  261. const w, h = 16, 16
  262. dst := ebiten.NewImage(w, h)
  263. s, err := ebiten.NewShader([]byte(`//kage:unit pixels
  264. package main
  265. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  266. var a, b mat4
  267. a[0] = vec4(0.125, 0.0625, 0.0625, 0.0625)
  268. a[1] = vec4(0.25, 0.25, 0.0625, 0.1875)
  269. a[2] = vec4(0.1875, 0.125, 0.25, 0.25)
  270. a[3] = vec4(0.0625, 0.1875, 0.125, 0.25)
  271. b[0] = vec4(0.0625, 0.125, 0.0625, 0.125)
  272. b[1] = vec4(0.125, 0.1875, 0.25, 0.0625)
  273. b[2] = vec4(0.125, 0.125, 0.1875, 0.1875)
  274. b[3] = vec4(0.25, 0.0625, 0.125, 0.0625)
  275. return vec4((a * b * vec4(1, 1, 1, 1)).xyz, 1)
  276. }
  277. `))
  278. if err != nil {
  279. t.Fatal(err)
  280. }
  281. src := ebiten.NewImage(w, h)
  282. op := &ebiten.DrawRectShaderOptions{}
  283. op.Images[0] = src
  284. dst.DrawRectShader(w, h, s, op)
  285. for j := 0; j < h; j++ {
  286. for i := 0; i < w; i++ {
  287. got := dst.At(i, j).(color.RGBA)
  288. want := color.RGBA{R: 87, G: 82, B: 71, A: 255}
  289. if got != want {
  290. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  291. }
  292. }
  293. }
  294. }
  295. func TestShaderSubImage(t *testing.T) {
  296. const w, h = 16, 16
  297. s, err := ebiten.NewShader([]byte(`//kage:unit pixels
  298. package main
  299. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  300. r := imageSrc0At(srcPos).r
  301. g := imageSrc1At(srcPos).g
  302. return vec4(r, g, 0, 1)
  303. }
  304. `))
  305. if err != nil {
  306. t.Fatal(err)
  307. }
  308. src0 := ebiten.NewImage(w, h)
  309. pix0 := make([]byte, 4*w*h)
  310. for j := 0; j < h; j++ {
  311. for i := 0; i < w; i++ {
  312. if 2 <= i && i < 10 && 3 <= j && j < 11 {
  313. pix0[4*(j*w+i)] = 0xff
  314. pix0[4*(j*w+i)+1] = 0
  315. pix0[4*(j*w+i)+2] = 0
  316. pix0[4*(j*w+i)+3] = 0xff
  317. }
  318. }
  319. }
  320. src0.WritePixels(pix0)
  321. src0 = src0.SubImage(image.Rect(2, 3, 10, 11)).(*ebiten.Image)
  322. src1 := ebiten.NewImage(w, h)
  323. pix1 := make([]byte, 4*w*h)
  324. for j := 0; j < h; j++ {
  325. for i := 0; i < w; i++ {
  326. if 6 <= i && i < 14 && 8 <= j && j < 16 {
  327. pix1[4*(j*w+i)] = 0
  328. pix1[4*(j*w+i)+1] = 0xff
  329. pix1[4*(j*w+i)+2] = 0
  330. pix1[4*(j*w+i)+3] = 0xff
  331. }
  332. }
  333. }
  334. src1.WritePixels(pix1)
  335. src1 = src1.SubImage(image.Rect(6, 8, 14, 16)).(*ebiten.Image)
  336. testPixels := func(testname string, dst *ebiten.Image) {
  337. for j := 0; j < h; j++ {
  338. for i := 0; i < w; i++ {
  339. got := dst.At(i, j).(color.RGBA)
  340. var want color.RGBA
  341. if i < w/2 && j < h/2 {
  342. want = color.RGBA{R: 0xff, G: 0xff, A: 0xff}
  343. }
  344. if got != want {
  345. t.Errorf("%s dst.At(%d, %d): got: %v, want: %v", testname, i, j, got, want)
  346. }
  347. }
  348. }
  349. }
  350. t.Run("DrawRectShader", func(t *testing.T) {
  351. dst := ebiten.NewImage(w, h)
  352. op := &ebiten.DrawRectShaderOptions{}
  353. op.Images[0] = src0
  354. op.Images[1] = src1
  355. dst.DrawRectShader(w/2, h/2, s, op)
  356. testPixels("DrawRectShader", dst)
  357. })
  358. t.Run("DrawTrianglesShader", func(t *testing.T) {
  359. dst := ebiten.NewImage(w, h)
  360. vs := []ebiten.Vertex{
  361. {
  362. DstX: 0,
  363. DstY: 0,
  364. SrcX: 2,
  365. SrcY: 3,
  366. ColorR: 1,
  367. ColorG: 1,
  368. ColorB: 1,
  369. ColorA: 1,
  370. },
  371. {
  372. DstX: w / 2,
  373. DstY: 0,
  374. SrcX: 10,
  375. SrcY: 3,
  376. ColorR: 1,
  377. ColorG: 1,
  378. ColorB: 1,
  379. ColorA: 1,
  380. },
  381. {
  382. DstX: 0,
  383. DstY: h / 2,
  384. SrcX: 2,
  385. SrcY: 11,
  386. ColorR: 1,
  387. ColorG: 1,
  388. ColorB: 1,
  389. ColorA: 1,
  390. },
  391. {
  392. DstX: w / 2,
  393. DstY: h / 2,
  394. SrcX: 10,
  395. SrcY: 11,
  396. ColorR: 1,
  397. ColorG: 1,
  398. ColorB: 1,
  399. ColorA: 1,
  400. },
  401. }
  402. is := []uint16{0, 1, 2, 1, 2, 3}
  403. op := &ebiten.DrawTrianglesShaderOptions{}
  404. op.Images[0] = src0
  405. op.Images[1] = src1
  406. dst.DrawTrianglesShader(vs, is, s, op)
  407. testPixels("DrawTrianglesShader", dst)
  408. })
  409. }
  410. // Issue #1404
  411. func TestShaderDerivatives(t *testing.T) {
  412. t.Skip("the results of dfdx, dfdy, and fwidth are indeterministic (#2583)")
  413. const w, h = 16, 16
  414. s, err := ebiten.NewShader([]byte(`//kage:unit pixels
  415. package main
  416. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  417. p := imageSrc0At(srcPos)
  418. return vec4(abs(dfdx(p.r)), abs(dfdy(p.g)), 0, 1)
  419. }
  420. `))
  421. if err != nil {
  422. t.Fatal(err)
  423. }
  424. dst := ebiten.NewImage(w, h)
  425. src := ebiten.NewImage(w, h)
  426. pix := make([]byte, 4*w*h)
  427. for j := 0; j < h; j++ {
  428. for i := 0; i < w; i++ {
  429. if i < w/2 {
  430. pix[4*(j*w+i)] = 0xff
  431. }
  432. if j < h/2 {
  433. pix[4*(j*w+i)+1] = 0xff
  434. }
  435. pix[4*(j*w+i)+3] = 0xff
  436. }
  437. }
  438. src.WritePixels(pix)
  439. op := &ebiten.DrawRectShaderOptions{}
  440. op.Images[0] = src
  441. dst.DrawRectShader(w, h, s, op)
  442. // The results of the edges might be unreliable. Skip the edges.
  443. for j := 1; j < h-1; j++ {
  444. for i := 1; i < w-1; i++ {
  445. got := dst.At(i, j).(color.RGBA)
  446. want := color.RGBA{A: 0xff}
  447. if i == w/2-1 || i == w/2 {
  448. want.R = 0xff
  449. }
  450. if j == h/2-1 || j == h/2 {
  451. want.G = 0xff
  452. }
  453. if got != want {
  454. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  455. }
  456. }
  457. }
  458. }
  459. // Issue #1701
  460. func TestShaderDerivatives2(t *testing.T) {
  461. t.Skip("the results of dfdx, dfdy, and fwidth are indeterministic (#2583)")
  462. const w, h = 16, 16
  463. s, err := ebiten.NewShader([]byte(`//kage:unit pixels
  464. package main
  465. // This function uses dfdx and then should not be in GLSL's vertex shader (#1701).
  466. func Foo(p vec4) vec4 {
  467. return vec4(abs(dfdx(p.r)), abs(dfdy(p.g)), 0, 1)
  468. }
  469. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  470. p := imageSrc0At(srcPos)
  471. return Foo(p)
  472. }
  473. `))
  474. if err != nil {
  475. t.Fatal(err)
  476. }
  477. dst := ebiten.NewImage(w, h)
  478. src := ebiten.NewImage(w, h)
  479. pix := make([]byte, 4*w*h)
  480. for j := 0; j < h; j++ {
  481. for i := 0; i < w; i++ {
  482. if i < w/2 {
  483. pix[4*(j*w+i)] = 0xff
  484. }
  485. if j < h/2 {
  486. pix[4*(j*w+i)+1] = 0xff
  487. }
  488. pix[4*(j*w+i)+3] = 0xff
  489. }
  490. }
  491. src.WritePixels(pix)
  492. op := &ebiten.DrawRectShaderOptions{}
  493. op.Images[0] = src
  494. dst.DrawRectShader(w, h, s, op)
  495. // The results of the edges might be unreliable. Skip the edges.
  496. for j := 1; j < h-1; j++ {
  497. for i := 1; i < w-1; i++ {
  498. got := dst.At(i, j).(color.RGBA)
  499. want := color.RGBA{A: 0xff}
  500. if i == w/2-1 || i == w/2 {
  501. want.R = 0xff
  502. }
  503. if j == h/2-1 || j == h/2 {
  504. want.G = 0xff
  505. }
  506. if got != want {
  507. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  508. }
  509. }
  510. }
  511. }
  512. // Issue #1754
  513. func TestShaderUniformFirstElement(t *testing.T) {
  514. shaders := []struct {
  515. Name string
  516. Shader string
  517. Uniforms map[string]any
  518. }{
  519. {
  520. Name: "float array",
  521. Shader: `//kage:unit pixels
  522. package main
  523. var C [2]float
  524. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  525. return vec4(C[0], 1, 1, 1)
  526. }`,
  527. Uniforms: map[string]any{
  528. "C": []float32{1, 1},
  529. },
  530. },
  531. {
  532. Name: "float one-element array",
  533. Shader: `//kage:unit pixels
  534. package main
  535. var C [1]float
  536. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  537. return vec4(C[0], 1, 1, 1)
  538. }`,
  539. Uniforms: map[string]any{
  540. "C": []float32{1},
  541. },
  542. },
  543. {
  544. Name: "matrix array",
  545. Shader: `//kage:unit pixels
  546. package main
  547. var C [2]mat2
  548. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  549. return vec4(C[0][0][0], 1, 1, 1)
  550. }`,
  551. Uniforms: map[string]any{
  552. "C": []float32{1, 0, 0, 0, 0, 0, 0, 0},
  553. },
  554. },
  555. }
  556. for _, shader := range shaders {
  557. shader := shader
  558. t.Run(shader.Name, func(t *testing.T) {
  559. const w, h = 1, 1
  560. dst := ebiten.NewImage(w, h)
  561. defer dst.Deallocate()
  562. s, err := ebiten.NewShader([]byte(shader.Shader))
  563. if err != nil {
  564. t.Fatal(err)
  565. }
  566. defer s.Deallocate()
  567. op := &ebiten.DrawRectShaderOptions{}
  568. op.Uniforms = shader.Uniforms
  569. dst.DrawRectShader(w, h, s, op)
  570. if got, want := dst.At(0, 0), (color.RGBA{R: 0xff, G: 0xff, B: 0xff, A: 0xff}); got != want {
  571. t.Errorf("got: %v, want: %v", got, want)
  572. }
  573. })
  574. }
  575. }
  576. // Issue #2006
  577. func TestShaderFuncMod(t *testing.T) {
  578. const w, h = 16, 16
  579. dst := ebiten.NewImage(w, h)
  580. s, err := ebiten.NewShader([]byte(`//kage:unit pixels
  581. package main
  582. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  583. r := mod(-0.25, 1.0)
  584. return vec4(r, 0, 0, 1)
  585. }
  586. `))
  587. if err != nil {
  588. t.Fatal(err)
  589. }
  590. dst.DrawRectShader(w/2, h/2, s, nil)
  591. for j := 0; j < h; j++ {
  592. for i := 0; i < w; i++ {
  593. got := dst.At(i, j).(color.RGBA)
  594. var want color.RGBA
  595. if i < w/2 && j < h/2 {
  596. want = color.RGBA{R: 0xc0, A: 0xff}
  597. }
  598. if !sameColors(got, want, 2) {
  599. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  600. }
  601. }
  602. }
  603. }
  604. func TestShaderMatrixInitialize(t *testing.T) {
  605. const w, h = 16, 16
  606. src := ebiten.NewImage(w, h)
  607. src.Fill(color.RGBA{R: 0x10, G: 0x20, B: 0x30, A: 0xff})
  608. dst := ebiten.NewImage(w, h)
  609. s, err := ebiten.NewShader([]byte(`//kage:unit pixels
  610. package main
  611. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  612. return mat4(2) * imageSrc0At(srcPos);
  613. }
  614. `))
  615. if err != nil {
  616. t.Fatal(err)
  617. }
  618. op := &ebiten.DrawRectShaderOptions{}
  619. op.Images[0] = src
  620. dst.DrawRectShader(w, h, s, op)
  621. for j := 0; j < h; j++ {
  622. for i := 0; i < w; i++ {
  623. got := dst.At(i, j).(color.RGBA)
  624. want := color.RGBA{R: 0x20, G: 0x40, B: 0x60, A: 0xff}
  625. if !sameColors(got, want, 2) {
  626. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  627. }
  628. }
  629. }
  630. }
  631. // Issue #2029
  632. func TestShaderModVectorAndFloat(t *testing.T) {
  633. const w, h = 16, 16
  634. dst := ebiten.NewImage(w, h)
  635. s, err := ebiten.NewShader([]byte(`//kage:unit pixels
  636. package main
  637. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  638. r := mod(vec3(0.25, 0.5, 0.75), 0.5)
  639. return vec4(r, 1)
  640. }
  641. `))
  642. if err != nil {
  643. t.Fatal(err)
  644. }
  645. dst.DrawRectShader(w, h, s, nil)
  646. for j := 0; j < h; j++ {
  647. for i := 0; i < w; i++ {
  648. got := dst.At(i, j).(color.RGBA)
  649. want := color.RGBA{R: 0x40, B: 0x40, A: 0xff}
  650. if !sameColors(got, want, 2) {
  651. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  652. }
  653. }
  654. }
  655. }
  656. func TestShaderTextureAt(t *testing.T) {
  657. const w, h = 16, 16
  658. src := ebiten.NewImage(w, h)
  659. src.Fill(color.RGBA{R: 0x10, G: 0x20, B: 0x30, A: 0xff})
  660. dst := ebiten.NewImage(w, h)
  661. s, err := ebiten.NewShader([]byte(`//kage:unit pixels
  662. package main
  663. func textureAt(uv vec2) vec4 {
  664. return imageSrc0UnsafeAt(uv)
  665. }
  666. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  667. return textureAt(srcPos)
  668. }
  669. `))
  670. if err != nil {
  671. t.Fatal(err)
  672. }
  673. op := &ebiten.DrawRectShaderOptions{}
  674. op.Images[0] = src
  675. dst.DrawRectShader(w, h, s, op)
  676. for j := 0; j < h; j++ {
  677. for i := 0; i < w; i++ {
  678. got := dst.At(i, j).(color.RGBA)
  679. want := color.RGBA{R: 0x10, G: 0x20, B: 0x30, A: 0xff}
  680. if !sameColors(got, want, 2) {
  681. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  682. }
  683. }
  684. }
  685. }
  686. func TestShaderAtan2(t *testing.T) {
  687. const w, h = 16, 16
  688. src := ebiten.NewImage(w, h)
  689. src.Fill(color.RGBA{R: 0x10, G: 0x20, B: 0x30, A: 0xff})
  690. dst := ebiten.NewImage(w, h)
  691. s, err := ebiten.NewShader([]byte(`//kage:unit pixels
  692. package main
  693. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  694. y := vec4(1, 1, 1, 1)
  695. x := vec4(1, 1, 1, 1)
  696. return atan2(y, x)
  697. }
  698. `))
  699. if err != nil {
  700. t.Fatal(err)
  701. }
  702. op := &ebiten.DrawRectShaderOptions{}
  703. op.Images[0] = src
  704. dst.DrawRectShader(w, h, s, op)
  705. for j := 0; j < h; j++ {
  706. for i := 0; i < w; i++ {
  707. got := dst.At(i, j).(color.RGBA)
  708. v := byte(math.Floor(0xff * math.Pi / 4))
  709. want := color.RGBA{R: v, G: v, B: v, A: v}
  710. if !sameColors(got, want, 2) {
  711. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  712. }
  713. }
  714. }
  715. }
  716. func TestShaderUniformMatrix2(t *testing.T) {
  717. const w, h = 16, 16
  718. dst := ebiten.NewImage(w, h)
  719. s, err := ebiten.NewShader([]byte(`//kage:unit pixels
  720. package main
  721. var Mat2 mat2
  722. var F float
  723. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  724. return vec4(F * Mat2 * vec2(1), 1, 1)
  725. }
  726. `))
  727. if err != nil {
  728. t.Fatal(err)
  729. }
  730. op := &ebiten.DrawRectShaderOptions{}
  731. op.Uniforms = map[string]any{
  732. "Mat2": []float32{
  733. 1.0 / 256.0, 2.0 / 256.0,
  734. 3.0 / 256.0, 4.0 / 256.0,
  735. },
  736. "F": float32(2),
  737. }
  738. dst.DrawRectShader(w, h, s, op)
  739. for j := 0; j < h; j++ {
  740. for i := 0; i < w; i++ {
  741. got := dst.At(i, j).(color.RGBA)
  742. want := color.RGBA{R: 8, G: 12, B: 0xff, A: 0xff}
  743. if !sameColors(got, want, 2) {
  744. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  745. }
  746. }
  747. }
  748. }
  749. func TestShaderUniformMatrix2Array(t *testing.T) {
  750. const w, h = 16, 16
  751. dst := ebiten.NewImage(w, h)
  752. s, err := ebiten.NewShader([]byte(`//kage:unit pixels
  753. package main
  754. var Mat2 [2]mat2
  755. var F float
  756. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  757. return vec4(F * Mat2[0] * Mat2[1] * vec2(1), 1, 1)
  758. }
  759. `))
  760. if err != nil {
  761. t.Fatal(err)
  762. }
  763. op := &ebiten.DrawRectShaderOptions{}
  764. op.Uniforms = map[string]any{
  765. "Mat2": []float32{
  766. 1.0 / 256.0, 2.0 / 256.0,
  767. 3.0 / 256.0, 4.0 / 256.0,
  768. 5.0 / 256.0, 6.0 / 256.0,
  769. 7.0 / 256.0, 8.0 / 256.0,
  770. },
  771. "F": float32(256),
  772. }
  773. dst.DrawRectShader(w, h, s, op)
  774. for j := 0; j < h; j++ {
  775. for i := 0; i < w; i++ {
  776. got := dst.At(i, j).(color.RGBA)
  777. want := color.RGBA{R: 54, G: 80, B: 0xff, A: 0xff}
  778. if !sameColors(got, want, 2) {
  779. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  780. }
  781. }
  782. }
  783. }
  784. func TestShaderUniformMatrix3(t *testing.T) {
  785. const w, h = 16, 16
  786. dst := ebiten.NewImage(w, h)
  787. s, err := ebiten.NewShader([]byte(`//kage:unit pixels
  788. package main
  789. var Mat3 mat3
  790. var F float
  791. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  792. return vec4(F * Mat3 * vec3(1), 1)
  793. }
  794. `))
  795. if err != nil {
  796. t.Fatal(err)
  797. }
  798. op := &ebiten.DrawRectShaderOptions{}
  799. op.Uniforms = map[string]any{
  800. "Mat3": []float32{
  801. 1.0 / 256.0, 2.0 / 256.0, 3.0 / 256.0,
  802. 4.0 / 256.0, 5.0 / 256.0, 6.0 / 256.0,
  803. 7.0 / 256.0, 8.0 / 256.0, 9.0 / 256.0,
  804. },
  805. "F": float32(2),
  806. }
  807. dst.DrawRectShader(w, h, s, op)
  808. for j := 0; j < h; j++ {
  809. for i := 0; i < w; i++ {
  810. got := dst.At(i, j).(color.RGBA)
  811. want := color.RGBA{R: 24, G: 30, B: 36, A: 0xff}
  812. if !sameColors(got, want, 2) {
  813. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  814. }
  815. }
  816. }
  817. }
  818. func TestShaderUniformMatrix3Array(t *testing.T) {
  819. const w, h = 16, 16
  820. dst := ebiten.NewImage(w, h)
  821. s, err := ebiten.NewShader([]byte(`//kage:unit pixels
  822. package main
  823. var Mat3 [2]mat3
  824. var F float
  825. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  826. return vec4(F * Mat3[0] * Mat3[1] * vec3(1), 1)
  827. }
  828. `))
  829. if err != nil {
  830. t.Fatal(err)
  831. }
  832. op := &ebiten.DrawRectShaderOptions{}
  833. op.Uniforms = map[string]any{
  834. "Mat3": []float32{
  835. 1.0 / 256.0, 2.0 / 256.0, 3.0 / 256.0,
  836. 4.0 / 256.0, 5.0 / 256.0, 6.0 / 256.0,
  837. 7.0 / 256.0, 8.0 / 256.0, 9.0 / 256.0,
  838. 10.0 / 256.0, 11.0 / 256.0, 12.0 / 256.0,
  839. 13.0 / 256.0, 14.0 / 256.0, 15.0 / 256.0,
  840. 16.0 / 256.0, 17.0 / 256.0, 18.0 / 256.0,
  841. },
  842. "F": float32(3),
  843. }
  844. dst.DrawRectShader(w, h, s, op)
  845. for j := 0; j < h; j++ {
  846. for i := 0; i < w; i++ {
  847. got := dst.At(i, j).(color.RGBA)
  848. want := color.RGBA{R: 6, G: 8, B: 9, A: 0xff}
  849. if !sameColors(got, want, 2) {
  850. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  851. }
  852. }
  853. }
  854. }
  855. func TestShaderUniformMatrix4(t *testing.T) {
  856. const w, h = 16, 16
  857. dst := ebiten.NewImage(w, h)
  858. s, err := ebiten.NewShader([]byte(`//kage:unit pixels
  859. package main
  860. var Mat4 mat4
  861. var F float
  862. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  863. return F * Mat4 * vec4(1)
  864. }
  865. `))
  866. if err != nil {
  867. t.Fatal(err)
  868. }
  869. op := &ebiten.DrawRectShaderOptions{}
  870. op.Uniforms = map[string]any{
  871. "Mat4": []float32{
  872. 1.0 / 256.0, 2.0 / 256.0, 3.0 / 256.0, 4.0 / 256.0,
  873. 5.0 / 256.0, 6.0 / 256.0, 7.0 / 256.0, 8.0 / 256.0,
  874. 9.0 / 256.0, 10.0 / 256.0, 11.0 / 256.0, 12.0 / 256.0,
  875. 13.0 / 256.0, 14.0 / 256.0, 15.0 / 256.0, 16.0 / 256.0,
  876. },
  877. "F": float32(4),
  878. }
  879. dst.DrawRectShader(w, h, s, op)
  880. for j := 0; j < h; j++ {
  881. for i := 0; i < w; i++ {
  882. got := dst.At(i, j).(color.RGBA)
  883. want := color.RGBA{R: 112, G: 128, B: 143, A: 159}
  884. if !sameColors(got, want, 2) {
  885. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  886. }
  887. }
  888. }
  889. }
  890. func TestShaderUniformMatrix4Array(t *testing.T) {
  891. const w, h = 16, 16
  892. dst := ebiten.NewImage(w, h)
  893. s, err := ebiten.NewShader([]byte(`//kage:unit pixels
  894. package main
  895. var Mat4 [2]mat4
  896. var F float
  897. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  898. return F * Mat4[0] * Mat4[1] * vec4(1)
  899. }
  900. `))
  901. if err != nil {
  902. t.Fatal(err)
  903. }
  904. op := &ebiten.DrawRectShaderOptions{}
  905. op.Uniforms = map[string]any{
  906. "Mat4": []float32{
  907. 1.0 / 256.0, 2.0 / 256.0, 3.0 / 256.0, 4.0 / 256.0,
  908. 5.0 / 256.0, 6.0 / 256.0, 7.0 / 256.0, 8.0 / 256.0,
  909. 9.0 / 256.0, 10.0 / 256.0, 11.0 / 256.0, 12.0 / 256.0,
  910. 13.0 / 256.0, 14.0 / 256.0, 15.0 / 256.0, 16.0 / 256.0,
  911. 17.0 / 256.0, 18.0 / 256.0, 19.0 / 256.0, 20.0 / 256.0,
  912. 21.0 / 256.0, 22.0 / 256.0, 23.0 / 256.0, 24.0 / 256.0,
  913. 25.0 / 256.0, 26.0 / 256.0, 27.0 / 256.0, 28.0 / 256.0,
  914. 29.0 / 256.0, 30.0 / 256.0, 31.0 / 256.0, 32.0 / 256.0,
  915. },
  916. "F": float32(4),
  917. }
  918. dst.DrawRectShader(w, h, s, op)
  919. for j := 0; j < h; j++ {
  920. for i := 0; i < w; i++ {
  921. got := dst.At(i, j).(color.RGBA)
  922. want := color.RGBA{R: 44, G: 50, B: 56, A: 62}
  923. if !sameColors(got, want, 2) {
  924. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  925. }
  926. }
  927. }
  928. }
  929. func TestShaderOptionsNegativeBounds(t *testing.T) {
  930. const w, h = 16, 16
  931. s, err := ebiten.NewShader([]byte(`//kage:unit pixels
  932. package main
  933. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  934. r := imageSrc0At(srcPos).r
  935. g := imageSrc1At(srcPos).g
  936. return vec4(r, g, 0, 1)
  937. }
  938. `))
  939. if err != nil {
  940. t.Fatal(err)
  941. }
  942. const offset0 = -4
  943. src0 := ebiten.NewImageWithOptions(image.Rect(offset0, offset0, w+offset0, h+offset0), nil)
  944. pix0 := make([]byte, 4*w*h)
  945. for j := 0; j < h; j++ {
  946. for i := 0; i < w; i++ {
  947. if 2 <= i && i < 10 && 3 <= j && j < 11 {
  948. pix0[4*(j*w+i)] = 0xff
  949. pix0[4*(j*w+i)+1] = 0
  950. pix0[4*(j*w+i)+2] = 0
  951. pix0[4*(j*w+i)+3] = 0xff
  952. }
  953. }
  954. }
  955. src0.WritePixels(pix0)
  956. src0 = src0.SubImage(image.Rect(2+offset0, 3+offset0, 10+offset0, 11+offset0)).(*ebiten.Image)
  957. const offset1 = -6
  958. src1 := ebiten.NewImageWithOptions(image.Rect(offset1, offset1, w+offset1, h+offset1), nil)
  959. pix1 := make([]byte, 4*w*h)
  960. for j := 0; j < h; j++ {
  961. for i := 0; i < w; i++ {
  962. if 6 <= i && i < 14 && 8 <= j && j < 16 {
  963. pix1[4*(j*w+i)] = 0
  964. pix1[4*(j*w+i)+1] = 0xff
  965. pix1[4*(j*w+i)+2] = 0
  966. pix1[4*(j*w+i)+3] = 0xff
  967. }
  968. }
  969. }
  970. src1.WritePixels(pix1)
  971. src1 = src1.SubImage(image.Rect(6+offset1, 8+offset1, 14+offset1, 16+offset1)).(*ebiten.Image)
  972. const offset2 = -2
  973. testPixels := func(testname string, dst *ebiten.Image) {
  974. for j := offset2; j < h+offset2; j++ {
  975. for i := offset2; i < w+offset2; i++ {
  976. got := dst.At(i, j).(color.RGBA)
  977. var want color.RGBA
  978. if 0 <= i && i < w/2 && 0 <= j && j < h/2 {
  979. want = color.RGBA{R: 0xff, G: 0xff, A: 0xff}
  980. }
  981. if got != want {
  982. t.Errorf("%s dst.At(%d, %d): got: %v, want: %v", testname, i, j, got, want)
  983. }
  984. }
  985. }
  986. }
  987. t.Run("DrawRectShader", func(t *testing.T) {
  988. dst := ebiten.NewImageWithOptions(image.Rect(offset2, offset2, w+offset2, h+offset2), nil)
  989. op := &ebiten.DrawRectShaderOptions{}
  990. op.Images[0] = src0
  991. op.Images[1] = src1
  992. dst.DrawRectShader(w/2, h/2, s, op)
  993. testPixels("DrawRectShader", dst)
  994. })
  995. t.Run("DrawTrianglesShader", func(t *testing.T) {
  996. dst := ebiten.NewImageWithOptions(image.Rect(offset2, offset2, w+offset2, h+offset2), nil)
  997. vs := []ebiten.Vertex{
  998. {
  999. DstX: 0,
  1000. DstY: 0,
  1001. SrcX: 2 + offset0,
  1002. SrcY: 3 + offset0,
  1003. ColorR: 1,
  1004. ColorG: 1,
  1005. ColorB: 1,
  1006. ColorA: 1,
  1007. },
  1008. {
  1009. DstX: w / 2,
  1010. DstY: 0,
  1011. SrcX: 10 + offset0,
  1012. SrcY: 3 + offset0,
  1013. ColorR: 1,
  1014. ColorG: 1,
  1015. ColorB: 1,
  1016. ColorA: 1,
  1017. },
  1018. {
  1019. DstX: 0,
  1020. DstY: h / 2,
  1021. SrcX: 2 + offset0,
  1022. SrcY: 11 + offset0,
  1023. ColorR: 1,
  1024. ColorG: 1,
  1025. ColorB: 1,
  1026. ColorA: 1,
  1027. },
  1028. {
  1029. DstX: w / 2,
  1030. DstY: h / 2,
  1031. SrcX: 10 + offset0,
  1032. SrcY: 11 + offset0,
  1033. ColorR: 1,
  1034. ColorG: 1,
  1035. ColorB: 1,
  1036. ColorA: 1,
  1037. },
  1038. }
  1039. is := []uint16{0, 1, 2, 1, 2, 3}
  1040. op := &ebiten.DrawTrianglesShaderOptions{}
  1041. op.Images[0] = src0
  1042. op.Images[1] = src1
  1043. dst.DrawTrianglesShader(vs, is, s, op)
  1044. testPixels("DrawTrianglesShader", dst)
  1045. })
  1046. }
  1047. // Issue #2186
  1048. func TestShaderVectorEqual(t *testing.T) {
  1049. const w, h = 16, 16
  1050. dst := ebiten.NewImage(w, h)
  1051. s, err := ebiten.NewShader([]byte(`//kage:unit pixels
  1052. package main
  1053. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  1054. a := vec3(1)
  1055. b := vec3(1)
  1056. if a == b {
  1057. return vec4(1, 0, 0, 1)
  1058. } else {
  1059. return vec4(0, 1, 0, 1)
  1060. }
  1061. }
  1062. `))
  1063. if err != nil {
  1064. t.Fatal(err)
  1065. }
  1066. dst.DrawRectShader(w, h, s, nil)
  1067. for j := 0; j < h; j++ {
  1068. for i := 0; i < w; i++ {
  1069. got := dst.At(i, j).(color.RGBA)
  1070. want := color.RGBA{R: 0xff, A: 0xff}
  1071. if !sameColors(got, want, 2) {
  1072. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  1073. }
  1074. }
  1075. }
  1076. }
  1077. // Issue #1969
  1078. func TestShaderDiscard(t *testing.T) {
  1079. const w, h = 16, 16
  1080. dst := ebiten.NewImage(w, h)
  1081. dst.Fill(color.RGBA{R: 0xff, A: 0xff})
  1082. src := ebiten.NewImage(w, h)
  1083. pix := make([]byte, 4*w*h)
  1084. for j := 0; j < h; j++ {
  1085. for i := 0; i < w; i++ {
  1086. if i >= w/2 || j >= h/2 {
  1087. continue
  1088. }
  1089. pix[4*(j*w+i)+3] = 0xff
  1090. }
  1091. }
  1092. src.WritePixels(pix)
  1093. s, err := ebiten.NewShader([]byte(`//kage:unit pixels
  1094. package main
  1095. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  1096. p := imageSrc0At(srcPos)
  1097. if p.a == 0 {
  1098. discard()
  1099. } else {
  1100. return vec4(0, 1, 0, 1)
  1101. }
  1102. }
  1103. `))
  1104. if err != nil {
  1105. t.Fatal(err)
  1106. }
  1107. op := &ebiten.DrawRectShaderOptions{}
  1108. op.Images[0] = src
  1109. dst.DrawRectShader(w, h, s, op)
  1110. for j := 0; j < h; j++ {
  1111. for i := 0; i < w; i++ {
  1112. got := dst.At(i, j).(color.RGBA)
  1113. want := color.RGBA{G: 0xff, A: 0xff}
  1114. if i >= w/2 || j >= h/2 {
  1115. want = color.RGBA{R: 0xff, A: 0xff}
  1116. }
  1117. if !sameColors(got, want, 2) {
  1118. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  1119. }
  1120. }
  1121. }
  1122. }
  1123. // Issue #2245, #2247
  1124. func TestShaderDrawRect(t *testing.T) {
  1125. const (
  1126. dstW = 16
  1127. dstH = 16
  1128. srcW = 8
  1129. srcH = 8
  1130. )
  1131. dst := ebiten.NewImage(dstW, dstH)
  1132. src := ebiten.NewImage(srcW, srcH)
  1133. s, err := ebiten.NewShader([]byte(`//kage:unit pixels
  1134. package main
  1135. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  1136. // Adjust srcPos into [0, 1].
  1137. srcPos -= imageSrc0Origin()
  1138. srcPos /= imageSrc0Size()
  1139. if srcPos.x >= 0.5 && srcPos.y >= 0.5 {
  1140. return vec4(1, 0, 0, 1)
  1141. }
  1142. return vec4(0, 1, 0, 1)
  1143. }
  1144. `))
  1145. if err != nil {
  1146. t.Fatal(err)
  1147. }
  1148. const (
  1149. offsetX = (dstW - srcW) / 2
  1150. offsetY = (dstH - srcH) / 2
  1151. )
  1152. op := &ebiten.DrawRectShaderOptions{}
  1153. op.GeoM.Translate(offsetX, offsetY)
  1154. op.Images[0] = src
  1155. dst.DrawRectShader(srcW, srcH, s, op)
  1156. for j := 0; j < dstH; j++ {
  1157. for i := 0; i < dstW; i++ {
  1158. got := dst.At(i, j).(color.RGBA)
  1159. var want color.RGBA
  1160. if offsetX <= i && i < offsetX+srcW && offsetY <= j && j < offsetY+srcH {
  1161. if offsetX+srcW/2 <= i && offsetY+srcH/2 <= j {
  1162. want = color.RGBA{R: 0xff, A: 0xff}
  1163. } else {
  1164. want = color.RGBA{G: 0xff, A: 0xff}
  1165. }
  1166. }
  1167. if got != want {
  1168. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  1169. }
  1170. }
  1171. }
  1172. }
  1173. func TestShaderDrawRectColorScale(t *testing.T) {
  1174. const w, h = 16, 16
  1175. dst := ebiten.NewImage(w, h)
  1176. s, err := ebiten.NewShader([]byte(`//kage:unit pixels
  1177. package main
  1178. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  1179. return color
  1180. }
  1181. `))
  1182. if err != nil {
  1183. t.Fatal(err)
  1184. }
  1185. op := &ebiten.DrawRectShaderOptions{}
  1186. op.ColorScale.SetR(4.0 / 8.0)
  1187. op.ColorScale.SetG(5.0 / 8.0)
  1188. op.ColorScale.SetB(6.0 / 8.0)
  1189. op.ColorScale.SetA(7.0 / 8.0)
  1190. op.ColorScale.ScaleWithColor(color.RGBA{R: 0x40, G: 0x80, B: 0xc0, A: 0xff})
  1191. dst.DrawRectShader(w, h, s, op)
  1192. for j := 0; j < h; j++ {
  1193. for i := 0; i < w; i++ {
  1194. got := dst.At(i, j).(color.RGBA)
  1195. want := color.RGBA{R: 0x20, G: 0x50, B: 0x90, A: 0xe0}
  1196. if !sameColors(got, want, 1) {
  1197. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  1198. }
  1199. }
  1200. }
  1201. }
  1202. func TestShaderUniformInt(t *testing.T) {
  1203. const ints = `//kage:unit pixels
  1204. package main
  1205. var U0 int
  1206. var U1 int
  1207. var U2 int
  1208. var U3 int
  1209. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  1210. return vec4(float(U0)/255.0, float(U1)/255.0, float(U2)/255.0, float(U3)/255.0)
  1211. }
  1212. `
  1213. const intArray = `//kage:unit pixels
  1214. package main
  1215. var U [4]int
  1216. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  1217. return vec4(float(U[0])/255.0, float(U[1])/255.0, float(U[2])/255.0, float(U[3])/255.0)
  1218. }
  1219. `
  1220. const intVec = `//kage:unit pixels
  1221. package main
  1222. var U0 ivec4
  1223. var U1 [2]ivec3
  1224. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  1225. return vec4(float(U0.x)/255.0, float(U0.y)/255.0, float(U1[0].z)/255.0, float(U1[1].x)/255.0)
  1226. }
  1227. `
  1228. testCases := []struct {
  1229. Name string
  1230. Uniforms map[string]any
  1231. Shader string
  1232. Want color.RGBA
  1233. }{
  1234. {
  1235. Name: "0xff",
  1236. Uniforms: map[string]any{
  1237. "U0": 0xff,
  1238. "U1": 0xff,
  1239. "U2": 0xff,
  1240. "U3": 0xff,
  1241. },
  1242. Shader: ints,
  1243. Want: color.RGBA{R: 0xff, G: 0xff, B: 0xff, A: 0xff},
  1244. },
  1245. {
  1246. Name: "int",
  1247. Uniforms: map[string]any{
  1248. "U0": int8(0x24),
  1249. "U1": int16(0x3f),
  1250. "U2": int32(0x6a),
  1251. "U3": int64(0x88),
  1252. },
  1253. Shader: ints,
  1254. Want: color.RGBA{R: 0x24, G: 0x3f, B: 0x6a, A: 0x88},
  1255. },
  1256. {
  1257. Name: "uint",
  1258. Uniforms: map[string]any{
  1259. "U0": uint8(0x85),
  1260. "U1": uint16(0xa3),
  1261. "U2": uint32(0x08),
  1262. "U3": uint64(0xd3),
  1263. },
  1264. Shader: ints,
  1265. Want: color.RGBA{R: 0x85, G: 0xa3, B: 0x08, A: 0xd3},
  1266. },
  1267. {
  1268. Name: "0xff,slice",
  1269. Uniforms: map[string]any{
  1270. "U": []int{0xff, 0xff, 0xff, 0xff},
  1271. },
  1272. Shader: intArray,
  1273. Want: color.RGBA{R: 0xff, G: 0xff, B: 0xff, A: 0xff},
  1274. },
  1275. {
  1276. Name: "int,slice",
  1277. Uniforms: map[string]any{
  1278. "U": []int16{0x24, 0x3f, 0x6a, 0x88},
  1279. },
  1280. Shader: intArray,
  1281. Want: color.RGBA{R: 0x24, G: 0x3f, B: 0x6a, A: 0x88},
  1282. },
  1283. {
  1284. Name: "uint,slice",
  1285. Uniforms: map[string]any{
  1286. "U": []uint8{0x85, 0xa3, 0x08, 0xd3},
  1287. },
  1288. Shader: intArray,
  1289. Want: color.RGBA{R: 0x85, G: 0xa3, B: 0x08, A: 0xd3},
  1290. },
  1291. {
  1292. Name: "0xff,array",
  1293. Uniforms: map[string]any{
  1294. "U": [...]int{0xff, 0xff, 0xff, 0xff},
  1295. },
  1296. Shader: intArray,
  1297. Want: color.RGBA{R: 0xff, G: 0xff, B: 0xff, A: 0xff},
  1298. },
  1299. {
  1300. Name: "int,array",
  1301. Uniforms: map[string]any{
  1302. "U": [...]int16{0x24, 0x3f, 0x6a, 0x88},
  1303. },
  1304. Shader: intArray,
  1305. Want: color.RGBA{R: 0x24, G: 0x3f, B: 0x6a, A: 0x88},
  1306. },
  1307. {
  1308. Name: "uint,array",
  1309. Uniforms: map[string]any{
  1310. "U": [...]uint8{0x85, 0xa3, 0x08, 0xd3},
  1311. },
  1312. Shader: intArray,
  1313. Want: color.RGBA{R: 0x85, G: 0xa3, B: 0x08, A: 0xd3},
  1314. },
  1315. {
  1316. Name: "0xff,array",
  1317. Uniforms: map[string]any{
  1318. "U": [...]int{0xff, 0xff, 0xff, 0xff},
  1319. },
  1320. Shader: intArray,
  1321. Want: color.RGBA{R: 0xff, G: 0xff, B: 0xff, A: 0xff},
  1322. },
  1323. {
  1324. Name: "int,array",
  1325. Uniforms: map[string]any{
  1326. "U": [...]int16{0x24, 0x3f, 0x6a, 0x88},
  1327. },
  1328. Shader: intArray,
  1329. Want: color.RGBA{R: 0x24, G: 0x3f, B: 0x6a, A: 0x88},
  1330. },
  1331. {
  1332. Name: "uint,array",
  1333. Uniforms: map[string]any{
  1334. "U": [...]uint8{0x85, 0xa3, 0x08, 0xd3},
  1335. },
  1336. Shader: intArray,
  1337. Want: color.RGBA{R: 0x85, G: 0xa3, B: 0x08, A: 0xd3},
  1338. },
  1339. {
  1340. Name: "0xff,ivec",
  1341. Uniforms: map[string]any{
  1342. "U0": [...]int{0xff, 0xff, 0xff, 0xff},
  1343. "U1": [...]int{0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
  1344. },
  1345. Shader: intVec,
  1346. Want: color.RGBA{R: 0xff, G: 0xff, B: 0xff, A: 0xff},
  1347. },
  1348. {
  1349. Name: "int,ivec",
  1350. Uniforms: map[string]any{
  1351. "U0": [...]int16{0x24, 0x3f, 0x6a, 0x88},
  1352. "U1": [...]int16{0x85, 0xa3, 0x08, 0xd3, 0x13, 0x19},
  1353. },
  1354. Shader: intVec,
  1355. Want: color.RGBA{R: 0x24, G: 0x3f, B: 0x08, A: 0xd3},
  1356. },
  1357. {
  1358. Name: "uint,ivec",
  1359. Uniforms: map[string]any{
  1360. "U0": [...]uint8{0x24, 0x3f, 0x6a, 0x88},
  1361. "U1": [...]uint8{0x85, 0xa3, 0x08, 0xd3, 0x13, 0x19},
  1362. },
  1363. Shader: intVec,
  1364. Want: color.RGBA{R: 0x24, G: 0x3f, B: 0x08, A: 0xd3},
  1365. },
  1366. }
  1367. for _, tc := range testCases {
  1368. tc := tc
  1369. t.Run(tc.Name, func(t *testing.T) {
  1370. const w, h = 1, 1
  1371. dst := ebiten.NewImage(w, h)
  1372. defer dst.Deallocate()
  1373. s, err := ebiten.NewShader([]byte(tc.Shader))
  1374. if err != nil {
  1375. t.Fatal(err)
  1376. }
  1377. defer s.Deallocate()
  1378. op := &ebiten.DrawRectShaderOptions{}
  1379. op.Uniforms = tc.Uniforms
  1380. dst.DrawRectShader(w, h, s, op)
  1381. if got, want := dst.At(0, 0).(color.RGBA), tc.Want; !sameColors(got, want, 1) {
  1382. t.Errorf("got: %v, want: %v", got, want)
  1383. }
  1384. })
  1385. }
  1386. }
  1387. // Issue #2463
  1388. func TestShaderUniformVec3Array(t *testing.T) {
  1389. const shader = `//kage:unit pixels
  1390. package main
  1391. var U [4]vec3
  1392. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  1393. return vec4(U[0].x/255.0, U[1].y/255.0, U[2].z/255.0, U[3].x/255.0)
  1394. }
  1395. `
  1396. const w, h = 1, 1
  1397. dst := ebiten.NewImage(w, h)
  1398. defer dst.Deallocate()
  1399. s, err := ebiten.NewShader([]byte(shader))
  1400. if err != nil {
  1401. t.Fatal(err)
  1402. }
  1403. defer s.Deallocate()
  1404. op := &ebiten.DrawRectShaderOptions{}
  1405. op.Uniforms = map[string]any{
  1406. "U": []float32{
  1407. 0x24, 0x3f, 0x6a,
  1408. 0x88, 0x85, 0xa3,
  1409. 0x08, 0xd3, 0x13,
  1410. 0x19, 0x8a, 0x2e,
  1411. },
  1412. }
  1413. dst.DrawRectShader(w, h, s, op)
  1414. if got, want := dst.At(0, 0).(color.RGBA), (color.RGBA{R: 0x24, G: 0x85, B: 0x13, A: 0x19}); !sameColors(got, want, 1) {
  1415. t.Errorf("got: %v, want: %v", got, want)
  1416. }
  1417. }
  1418. func TestShaderIVecMod(t *testing.T) {
  1419. cases := []struct {
  1420. source string
  1421. want color.RGBA
  1422. }{
  1423. {
  1424. source: `a := ivec4(0x24, 0x3f, 0x6a, 0x88)
  1425. return vec4(a)/255`,
  1426. want: color.RGBA{R: 0x24, G: 0x3f, B: 0x6a, A: 0x88},
  1427. },
  1428. {
  1429. source: `a := ivec4(0x24, 0x3f, 0x6a, 0x88)
  1430. a %= 0x85
  1431. return vec4(a)/255`,
  1432. want: color.RGBA{R: 0x24, G: 0x3f, B: 0x6a, A: 0x03},
  1433. },
  1434. {
  1435. source: `a := ivec4(0x24, 0x3f, 0x6a, 0x88)
  1436. a %= ivec4(0x85, 0xa3, 0x08, 0xd3)
  1437. return vec4(a)/255`,
  1438. want: color.RGBA{R: 0x24, G: 0x3f, B: 0x02, A: 0x88},
  1439. },
  1440. {
  1441. source: `a := ivec4(0x24, 0x3f, 0x6a, 0x88)
  1442. b := a % 0x85
  1443. return vec4(b)/255`,
  1444. want: color.RGBA{R: 0x24, G: 0x3f, B: 0x6a, A: 0x03},
  1445. },
  1446. {
  1447. source: `a := ivec4(0x24, 0x3f, 0x6a, 0x88)
  1448. b := a % ivec4(0x85, 0xa3, 0x08, 0xd3)
  1449. return vec4(b)/255`,
  1450. want: color.RGBA{R: 0x24, G: 0x3f, B: 0x02, A: 0x88},
  1451. },
  1452. }
  1453. for _, tc := range cases {
  1454. shader := fmt.Sprintf(`//kage:unit pixels
  1455. package main
  1456. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  1457. %s
  1458. }
  1459. `, tc.source)
  1460. const w, h = 1, 1
  1461. dst := ebiten.NewImage(w, h)
  1462. defer dst.Deallocate()
  1463. s, err := ebiten.NewShader([]byte(shader))
  1464. if err != nil {
  1465. t.Fatal(err)
  1466. }
  1467. defer s.Deallocate()
  1468. op := &ebiten.DrawRectShaderOptions{}
  1469. dst.DrawRectShader(w, h, s, op)
  1470. if got, want := dst.At(0, 0).(color.RGBA), tc.want; !sameColors(got, want, 1) {
  1471. t.Errorf("%s: got: %v, want: %v", tc.source, got, want)
  1472. }
  1473. }
  1474. }
  1475. func TestShaderTexelAndPixel(t *testing.T) {
  1476. const dstW, dstH = 13, 17
  1477. const srcW, srcH = 19, 23
  1478. dstTexel := ebiten.NewImage(dstW, dstH)
  1479. dstPixel := ebiten.NewImage(dstW, dstH)
  1480. src := ebiten.NewImage(srcW, srcH)
  1481. shaderTexel, err := ebiten.NewShader([]byte(fmt.Sprintf(`//kage:unit texels
  1482. package main
  1483. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  1484. pos := (srcPos - imageSrc0Origin()) / imageSrc0Size()
  1485. pos *= vec2(%d, %d)
  1486. pos /= 255
  1487. return vec4(pos.x, pos.y, 0, 1)
  1488. }
  1489. `, srcW, srcH)))
  1490. if err != nil {
  1491. t.Fatal(err)
  1492. }
  1493. shaderPixel, err := ebiten.NewShader([]byte(`//kage:unit pixels
  1494. package main
  1495. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  1496. pos := srcPos - imageSrc0Origin()
  1497. pos /= 255
  1498. return vec4(pos.x, pos.y, 0, 1)
  1499. }
  1500. `))
  1501. if err != nil {
  1502. t.Fatal(err)
  1503. }
  1504. op := &ebiten.DrawRectShaderOptions{}
  1505. op.Images[0] = src
  1506. dstTexel.DrawRectShader(src.Bounds().Dx(), src.Bounds().Dy(), shaderTexel, op)
  1507. dstPixel.DrawRectShader(src.Bounds().Dx(), src.Bounds().Dy(), shaderPixel, op)
  1508. for j := 0; j < dstH; j++ {
  1509. for i := 0; i < dstW; i++ {
  1510. c0 := dstTexel.At(i, j).(color.RGBA)
  1511. c1 := dstPixel.At(i, j).(color.RGBA)
  1512. if !sameColors(c0, c1, 1) {
  1513. t.Errorf("dstTexel.At(%d, %d) %v != dstPixel.At(%d, %d) %v", i, j, c0, i, j, c1)
  1514. }
  1515. }
  1516. }
  1517. }
  1518. func TestShaderDifferentTextureSizes(t *testing.T) {
  1519. src0 := ebiten.NewImageWithOptions(image.Rect(0, 0, 20, 4000), &ebiten.NewImageOptions{
  1520. Unmanaged: true,
  1521. }).SubImage(image.Rect(4, 1025, 6, 1028)).(*ebiten.Image)
  1522. defer src0.Deallocate()
  1523. src1 := ebiten.NewImageWithOptions(image.Rect(0, 0, 4000, 20), &ebiten.NewImageOptions{
  1524. Unmanaged: true,
  1525. }).SubImage(image.Rect(2047, 7, 2049, 10)).(*ebiten.Image)
  1526. defer src1.Deallocate()
  1527. src0.Fill(color.RGBA{0x10, 0x20, 0x30, 0xff})
  1528. src1.Fill(color.RGBA{0x30, 0x20, 0x10, 0xff})
  1529. for _, unit := range []string{"texels", "pixels"} {
  1530. unit := unit
  1531. t.Run(fmt.Sprintf("unit %s", unit), func(t *testing.T) {
  1532. shader, err := ebiten.NewShader([]byte(fmt.Sprintf(`//kage:unit %s
  1533. package main
  1534. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  1535. return imageSrc0At(srcPos) + imageSrc1At(srcPos)
  1536. }
  1537. `, unit)))
  1538. if err != nil {
  1539. t.Fatal(err)
  1540. }
  1541. defer shader.Deallocate()
  1542. dst := ebiten.NewImage(2, 3)
  1543. defer dst.Deallocate()
  1544. op := &ebiten.DrawRectShaderOptions{}
  1545. op.Images[0] = src0
  1546. op.Images[1] = src1
  1547. dst.DrawRectShader(2, 3, shader, op)
  1548. for j := 0; j < 3; j++ {
  1549. for i := 0; i < 2; i++ {
  1550. got := dst.At(i, j).(color.RGBA)
  1551. want := color.RGBA{0x40, 0x40, 0x40, 0xff}
  1552. if !sameColors(got, want, 1) {
  1553. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  1554. }
  1555. }
  1556. }
  1557. })
  1558. }
  1559. }
  1560. func TestShaderIVec(t *testing.T) {
  1561. const w, h = 16, 16
  1562. dst := ebiten.NewImage(w, h)
  1563. src := ebiten.NewImage(w, h)
  1564. pix := make([]byte, 4*w*h)
  1565. for j := 0; j < h; j++ {
  1566. for i := 0; i < w; i++ {
  1567. pix[4*(j*w+i)] = byte(i)
  1568. pix[4*(j*w+i)+1] = byte(j)
  1569. pix[4*(j*w+i)+3] = 0xff
  1570. }
  1571. }
  1572. src.WritePixels(pix)
  1573. // Test that ivec2 can take any float values that can be casted to integers.
  1574. // This seems the common behavior in shading languages like GLSL, Metal, and HLSL.
  1575. shader, err := ebiten.NewShader([]byte(`//kage:unit pixels
  1576. package main
  1577. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  1578. pos := ivec2(3, 4)
  1579. return imageSrc0At(vec2(pos) + imageSrc0Origin())
  1580. }
  1581. `))
  1582. if err != nil {
  1583. t.Fatal(err)
  1584. }
  1585. op := &ebiten.DrawRectShaderOptions{}
  1586. op.Images[0] = src
  1587. dst.DrawRectShader(w, h, shader, op)
  1588. got := dst.At(0, 0).(color.RGBA)
  1589. want := color.RGBA{3, 4, 0, 0xff}
  1590. if got != want {
  1591. t.Errorf("got: %v, want: %v", got, want)
  1592. }
  1593. }
  1594. func TestShaderUniformSizes(t *testing.T) {
  1595. const w, h = 16, 16
  1596. dst := ebiten.NewImage(w, h)
  1597. s, err := ebiten.NewShader([]byte(`//kage:unit pixels
  1598. package main
  1599. var U vec4
  1600. var V [3]float
  1601. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  1602. return vec4(0)
  1603. }
  1604. `))
  1605. if err != nil {
  1606. t.Fatal(err)
  1607. }
  1608. tests := []struct {
  1609. uniforms map[string]any
  1610. err bool
  1611. }{
  1612. {
  1613. uniforms: nil,
  1614. err: false,
  1615. },
  1616. {
  1617. uniforms: map[string]any{
  1618. "U": 1,
  1619. },
  1620. err: true,
  1621. },
  1622. {
  1623. uniforms: map[string]any{
  1624. "U": "1",
  1625. },
  1626. err: true,
  1627. },
  1628. {
  1629. uniforms: map[string]any{
  1630. "U": []int32{1, 2, 3},
  1631. },
  1632. err: true,
  1633. },
  1634. {
  1635. uniforms: map[string]any{
  1636. "U": []int32{1, 2, 3, 4},
  1637. },
  1638. err: false,
  1639. },
  1640. {
  1641. uniforms: map[string]any{
  1642. "U": []int32{1, 2, 3, 4, 5},
  1643. },
  1644. err: true,
  1645. },
  1646. {
  1647. uniforms: map[string]any{
  1648. "V": 1,
  1649. },
  1650. err: true,
  1651. },
  1652. {
  1653. uniforms: map[string]any{
  1654. "V": "1",
  1655. },
  1656. err: true,
  1657. },
  1658. {
  1659. uniforms: map[string]any{
  1660. "V": []int32{1, 2},
  1661. },
  1662. err: true,
  1663. },
  1664. {
  1665. uniforms: map[string]any{
  1666. "V": []int32{1, 2, 3},
  1667. },
  1668. err: false,
  1669. },
  1670. {
  1671. uniforms: map[string]any{
  1672. "V": []int32{1, 2, 3, 4},
  1673. },
  1674. err: true,
  1675. },
  1676. }
  1677. for _, tc := range tests {
  1678. tc := tc
  1679. t.Run(fmt.Sprintf("%v", tc.uniforms), func(t *testing.T) {
  1680. defer func() {
  1681. r := recover()
  1682. if r != nil && !tc.err {
  1683. t.Errorf("DrawRectShader must not panic but did")
  1684. } else if r == nil && tc.err {
  1685. t.Errorf("DrawRectShader must panic but does not")
  1686. }
  1687. }()
  1688. op := &ebiten.DrawRectShaderOptions{}
  1689. op.Uniforms = tc.uniforms
  1690. dst.DrawRectShader(w, h, s, op)
  1691. })
  1692. }
  1693. }
  1694. // Issue #2709
  1695. func TestShaderUniformDefaultValue(t *testing.T) {
  1696. const w, h = 16, 16
  1697. dst := ebiten.NewImage(w, h)
  1698. s, err := ebiten.NewShader([]byte(`//kage:unit pixels
  1699. package main
  1700. var U vec4
  1701. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  1702. return U
  1703. }
  1704. `))
  1705. if err != nil {
  1706. t.Fatal(err)
  1707. }
  1708. // Draw with a uniform variable value.
  1709. op := &ebiten.DrawRectShaderOptions{}
  1710. op.Uniforms = map[string]any{
  1711. "U": [...]float32{1, 1, 1, 1},
  1712. }
  1713. dst.DrawRectShader(w, h, s, op)
  1714. for j := 0; j < h; j++ {
  1715. for i := 0; i < w; i++ {
  1716. got := dst.At(i, j).(color.RGBA)
  1717. want := color.RGBA{0xff, 0xff, 0xff, 0xff}
  1718. if got != want {
  1719. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  1720. }
  1721. }
  1722. }
  1723. // Draw without a uniform variable value. In this case, the uniform variable value should be 0.
  1724. dst.Clear()
  1725. op.Uniforms = nil
  1726. dst.DrawRectShader(w, h, s, op)
  1727. for j := 0; j < h; j++ {
  1728. for i := 0; i < w; i++ {
  1729. got := dst.At(i, j).(color.RGBA)
  1730. want := color.RGBA{0, 0, 0, 0}
  1731. if got != want {
  1732. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  1733. }
  1734. }
  1735. }
  1736. }
  1737. // Issue #2166
  1738. func TestShaderDrawRectWithoutSource(t *testing.T) {
  1739. const (
  1740. dstW = 16
  1741. dstH = 16
  1742. srcW = 8
  1743. srcH = 8
  1744. )
  1745. src := ebiten.NewImage(srcW, srcH)
  1746. for _, unit := range []string{"pixels", "texels"} {
  1747. s, err := ebiten.NewShader([]byte(fmt.Sprintf(`//kage:unit %s
  1748. package main
  1749. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  1750. t := srcPos
  1751. size := imageSrc0Size()
  1752. // If the unit is texels and no source images are specified, size is always 0.
  1753. if size == vec2(0) {
  1754. // Even in this case, t is in pixels (0, 0) to (8, 8).
  1755. if t.x >= 4 && t.y >= 4 {
  1756. return vec4(1, 0, 1, 1)
  1757. }
  1758. return vec4(0, 1, 1, 1)
  1759. }
  1760. // Adjust srcPos into [0, 1].
  1761. t -= imageSrc0Origin()
  1762. if size != vec2(0) {
  1763. t /= size
  1764. }
  1765. if t.x >= 0.5 && t.y >= 0.5 {
  1766. return vec4(1, 0, 0, 1)
  1767. }
  1768. return vec4(0, 1, 0, 1)
  1769. }
  1770. `, unit)))
  1771. if err != nil {
  1772. t.Fatal(err)
  1773. }
  1774. for _, withSrc := range []bool{false, true} {
  1775. withSrc := withSrc
  1776. title := "WithSrc,unit=" + unit
  1777. if !withSrc {
  1778. title = "WithoutSrc,unit=" + unit
  1779. }
  1780. t.Run(title, func(t *testing.T) {
  1781. dst := ebiten.NewImage(dstW, dstH)
  1782. const (
  1783. offsetX = (dstW - srcW) / 2
  1784. offsetY = (dstH - srcH) / 2
  1785. )
  1786. op := &ebiten.DrawRectShaderOptions{}
  1787. op.GeoM.Translate(offsetX, offsetY)
  1788. if withSrc {
  1789. op.Images[0] = src
  1790. }
  1791. dst.DrawRectShader(srcW, srcH, s, op)
  1792. for j := 0; j < dstH; j++ {
  1793. for i := 0; i < dstW; i++ {
  1794. got := dst.At(i, j).(color.RGBA)
  1795. var want color.RGBA
  1796. if offsetX <= i && i < offsetX+srcW && offsetY <= j && j < offsetY+srcH {
  1797. var blue byte
  1798. if !withSrc && unit == "texels" {
  1799. blue = 0xff
  1800. }
  1801. if offsetX+srcW/2 <= i && offsetY+srcH/2 <= j {
  1802. want = color.RGBA{0xff, 0, blue, 0xff}
  1803. } else {
  1804. want = color.RGBA{0, 0xff, blue, 0xff}
  1805. }
  1806. }
  1807. if got != want {
  1808. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  1809. }
  1810. }
  1811. }
  1812. })
  1813. }
  1814. }
  1815. }
  1816. // Issue #2719
  1817. func TestShaderMatrixDivFloat(t *testing.T) {
  1818. const w, h = 16, 16
  1819. src := ebiten.NewImage(w, h)
  1820. src.Fill(color.RGBA{R: 0x10, G: 0x20, B: 0x30, A: 0xff})
  1821. dst := ebiten.NewImage(w, h)
  1822. s, err := ebiten.NewShader([]byte(`//kage:unit pixels
  1823. package main
  1824. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  1825. var x = 2.0
  1826. return mat4(3) / x * imageSrc0At(srcPos);
  1827. }
  1828. `))
  1829. if err != nil {
  1830. t.Fatal(err)
  1831. }
  1832. op := &ebiten.DrawRectShaderOptions{}
  1833. op.Images[0] = src
  1834. dst.DrawRectShader(w, h, s, op)
  1835. for j := 0; j < h; j++ {
  1836. for i := 0; i < w; i++ {
  1837. got := dst.At(i, j).(color.RGBA)
  1838. want := color.RGBA{R: 0x18, G: 0x30, B: 0x48, A: 0xff}
  1839. if !sameColors(got, want, 2) {
  1840. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  1841. }
  1842. }
  1843. }
  1844. }
  1845. func TestShaderDifferentSourceSizes(t *testing.T) {
  1846. src0 := ebiten.NewImageWithOptions(image.Rect(0, 0, 20, 4000), &ebiten.NewImageOptions{
  1847. Unmanaged: true,
  1848. }).SubImage(image.Rect(4, 1025, 7, 1029)).(*ebiten.Image) // 3x4
  1849. defer src0.Deallocate()
  1850. src1 := ebiten.NewImageWithOptions(image.Rect(0, 0, 4000, 20), &ebiten.NewImageOptions{
  1851. Unmanaged: true,
  1852. }).SubImage(image.Rect(2047, 7, 2049, 10)).(*ebiten.Image) // 2x3
  1853. defer src1.Deallocate()
  1854. src0.Fill(color.RGBA{0x10, 0x20, 0x30, 0xff})
  1855. src1.Fill(color.RGBA{0x30, 0x20, 0x10, 0xff})
  1856. for _, unit := range []string{"texels", "pixels"} {
  1857. unit := unit
  1858. t.Run(fmt.Sprintf("unit %s", unit), func(t *testing.T) {
  1859. if unit == "texels" {
  1860. defer func() {
  1861. if r := recover(); r == nil {
  1862. t.Errorf("DrawTrianglesShader must panic with different sizes but not (unit=%s)", unit)
  1863. }
  1864. }()
  1865. }
  1866. shader, err := ebiten.NewShader([]byte(fmt.Sprintf(`//kage:unit %s
  1867. package main
  1868. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  1869. return imageSrc0At(srcPos) + imageSrc1At(srcPos)
  1870. }
  1871. `, unit)))
  1872. if err != nil {
  1873. t.Fatal(err)
  1874. }
  1875. defer shader.Deallocate()
  1876. dst := ebiten.NewImage(3, 4)
  1877. defer dst.Deallocate()
  1878. op := &ebiten.DrawTrianglesShaderOptions{}
  1879. op.Images[0] = src0
  1880. op.Images[1] = src1
  1881. vs := []ebiten.Vertex{
  1882. {
  1883. DstX: 0,
  1884. DstY: 0,
  1885. SrcX: 4,
  1886. SrcY: 1025,
  1887. ColorR: 1,
  1888. ColorG: 1,
  1889. ColorB: 1,
  1890. ColorA: 1,
  1891. },
  1892. {
  1893. DstX: 3,
  1894. DstY: 0,
  1895. SrcX: 7,
  1896. SrcY: 1025,
  1897. ColorR: 1,
  1898. ColorG: 1,
  1899. ColorB: 1,
  1900. ColorA: 1,
  1901. },
  1902. {
  1903. DstX: 0,
  1904. DstY: 4,
  1905. SrcX: 4,
  1906. SrcY: 1029,
  1907. ColorR: 1,
  1908. ColorG: 1,
  1909. ColorB: 1,
  1910. ColorA: 1,
  1911. },
  1912. {
  1913. DstX: 3,
  1914. DstY: 4,
  1915. SrcX: 7,
  1916. SrcY: 1029,
  1917. ColorR: 1,
  1918. ColorG: 1,
  1919. ColorB: 1,
  1920. ColorA: 1,
  1921. },
  1922. }
  1923. is := []uint16{0, 1, 2, 1, 2, 3}
  1924. dst.DrawTrianglesShader(vs, is, shader, op)
  1925. if unit == "texel" {
  1926. t.Fatal("not reached")
  1927. }
  1928. for j := 0; j < 4; j++ {
  1929. for i := 0; i < 3; i++ {
  1930. got := dst.At(i, j).(color.RGBA)
  1931. var want color.RGBA
  1932. if i < 2 && j < 3 {
  1933. want = color.RGBA{0x40, 0x40, 0x40, 0xff}
  1934. } else {
  1935. want = color.RGBA{0x10, 0x20, 0x30, 0xff}
  1936. }
  1937. if !sameColors(got, want, 1) {
  1938. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  1939. }
  1940. }
  1941. }
  1942. })
  1943. }
  1944. }
  1945. // Issue #2752
  1946. func TestShaderBitwiseOperator(t *testing.T) {
  1947. const w, h = 16, 16
  1948. src := ebiten.NewImage(w, h)
  1949. src.Fill(color.RGBA{R: 0x24, G: 0x3f, B: 0x6a, A: 0xff})
  1950. for _, assign := range []bool{false, true} {
  1951. assign := assign
  1952. name := "op"
  1953. if assign {
  1954. name = "op+assign"
  1955. }
  1956. t.Run(name, func(t *testing.T) {
  1957. var code string
  1958. if assign {
  1959. code = ` v.rgb &= 0x5a
  1960. v.rgb |= 0x30
  1961. v.rgb ^= 0x8d`
  1962. } else {
  1963. code = ` v.rgb = v.rgb & 0x5a
  1964. v.rgb = v.rgb | 0x30
  1965. v.rgb = v.rgb ^ 0x8d`
  1966. }
  1967. s, err := ebiten.NewShader([]byte(fmt.Sprintf(`//kage:unit pixels
  1968. package main
  1969. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  1970. v := ivec4(imageSrc0At(srcPos) * 0xff)
  1971. %s
  1972. return vec4(v) / 0xff;
  1973. }
  1974. `, code)))
  1975. if err != nil {
  1976. t.Fatal(err)
  1977. }
  1978. dst := ebiten.NewImage(w, h)
  1979. op := &ebiten.DrawRectShaderOptions{}
  1980. op.Images[0] = src
  1981. dst.DrawRectShader(w, h, s, op)
  1982. for j := 0; j < h; j++ {
  1983. for i := 0; i < w; i++ {
  1984. got := dst.At(i, j).(color.RGBA)
  1985. want := color.RGBA{R: 0xbd, G: 0xb7, B: 0xf7, A: 0xff}
  1986. if !sameColors(got, want, 2) {
  1987. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  1988. }
  1989. }
  1990. }
  1991. })
  1992. }
  1993. }
  1994. func TestShaderDispose(t *testing.T) {
  1995. const w, h = 16, 16
  1996. dst := ebiten.NewImage(w, h)
  1997. s, err := ebiten.NewShader([]byte(`//kage:unit pixels
  1998. package main
  1999. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  2000. return vec4(1, 0, 0, 1)
  2001. }
  2002. `))
  2003. if err != nil {
  2004. t.Fatal(err)
  2005. }
  2006. dst.DrawRectShader(w/2, h/2, s, nil)
  2007. for j := 0; j < h; j++ {
  2008. for i := 0; i < w; i++ {
  2009. got := dst.At(i, j).(color.RGBA)
  2010. var want color.RGBA
  2011. if i < w/2 && j < h/2 {
  2012. want = color.RGBA{R: 0xff, A: 0xff}
  2013. }
  2014. if got != want {
  2015. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  2016. }
  2017. }
  2018. }
  2019. s.Dispose()
  2020. dst.Clear()
  2021. defer func() {
  2022. if e := recover(); e == nil {
  2023. panic("DrawRectShader with a disposed shader must panic but not")
  2024. }
  2025. }()
  2026. dst.DrawRectShader(w/2, h/2, s, nil)
  2027. }
  2028. func TestShaderDeallocate(t *testing.T) {
  2029. const w, h = 16, 16
  2030. dst := ebiten.NewImage(w, h)
  2031. s, err := ebiten.NewShader([]byte(`//kage:unit pixels
  2032. package main
  2033. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  2034. return vec4(1, 0, 0, 1)
  2035. }
  2036. `))
  2037. if err != nil {
  2038. t.Fatal(err)
  2039. }
  2040. dst.DrawRectShader(w/2, h/2, s, nil)
  2041. for j := 0; j < h; j++ {
  2042. for i := 0; i < w; i++ {
  2043. got := dst.At(i, j).(color.RGBA)
  2044. var want color.RGBA
  2045. if i < w/2 && j < h/2 {
  2046. want = color.RGBA{R: 0xff, A: 0xff}
  2047. }
  2048. if got != want {
  2049. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  2050. }
  2051. }
  2052. }
  2053. // Even after Deallocate is called, the shader is still available.
  2054. s.Deallocate()
  2055. dst.Clear()
  2056. dst.DrawRectShader(w/2, h/2, s, nil)
  2057. for j := 0; j < h; j++ {
  2058. for i := 0; i < w; i++ {
  2059. got := dst.At(i, j).(color.RGBA)
  2060. var want color.RGBA
  2061. if i < w/2 && j < h/2 {
  2062. want = color.RGBA{R: 0xff, A: 0xff}
  2063. }
  2064. if got != want {
  2065. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  2066. }
  2067. }
  2068. }
  2069. }
  2070. // Issue #2923
  2071. func TestShaderReturnArray(t *testing.T) {
  2072. const w, h = 16, 16
  2073. dst := ebiten.NewImage(w, h)
  2074. s, err := ebiten.NewShader([]byte(`//kage:unit pixels
  2075. package main
  2076. func foo() [4]float {
  2077. return [4]float{0.25, 0.5, 0.75, 1}
  2078. }
  2079. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  2080. a := foo()
  2081. return vec4(a[0], a[1], a[2], a[3])
  2082. }
  2083. `))
  2084. if err != nil {
  2085. t.Fatal(err)
  2086. }
  2087. dst.DrawRectShader(w, h, s, nil)
  2088. for j := 0; j < h; j++ {
  2089. for i := 0; i < w; i++ {
  2090. got := dst.At(i, j).(color.RGBA)
  2091. want := color.RGBA{R: 0x40, G: 0x80, B: 0xc0, A: 0xff}
  2092. if !sameColors(got, want, 2) {
  2093. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  2094. }
  2095. }
  2096. }
  2097. }
  2098. // Issue #2798
  2099. func TestShaderInvalidPremultipliedAlphaColor(t *testing.T) {
  2100. // This test checks the rendering result when the shader returns an invalid premultiplied alpha color.
  2101. // The result values are kept and not clamped.
  2102. const w, h = 16, 16
  2103. dst := ebiten.NewImage(w, h)
  2104. s, err := ebiten.NewShader([]byte(`//kage:unit pixels
  2105. package main
  2106. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  2107. return vec4(1, 0.75, 0.5, 0.25)
  2108. }
  2109. `))
  2110. if err != nil {
  2111. t.Fatal(err)
  2112. }
  2113. dst.DrawRectShader(w, h, s, nil)
  2114. for j := 0; j < h; j++ {
  2115. for i := 0; i < w; i++ {
  2116. got := dst.At(i, j).(color.RGBA)
  2117. want := color.RGBA{R: 0xff, G: 0xc0, B: 0x80, A: 0x40}
  2118. if !sameColors(got, want, 2) {
  2119. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  2120. }
  2121. }
  2122. }
  2123. dst.Clear()
  2124. s, err = ebiten.NewShader([]byte(`//kage:unit pixels
  2125. package main
  2126. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  2127. return vec4(1, 0.75, 0.5, 0)
  2128. }
  2129. `))
  2130. if err != nil {
  2131. t.Fatal(err)
  2132. }
  2133. dst.DrawRectShader(w, h, s, nil)
  2134. for j := 0; j < h; j++ {
  2135. for i := 0; i < w; i++ {
  2136. got := dst.At(i, j).(color.RGBA)
  2137. want := color.RGBA{R: 0xff, G: 0xc0, B: 0x80, A: 0}
  2138. if !sameColors(got, want, 2) {
  2139. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  2140. }
  2141. }
  2142. }
  2143. }
  2144. // Issue #2933
  2145. func TestShaderIncDecStmt(t *testing.T) {
  2146. const w, h = 16, 16
  2147. dst := ebiten.NewImage(w, h)
  2148. s, err := ebiten.NewShader([]byte(`//kage:unit pixels
  2149. package main
  2150. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  2151. a := 0
  2152. a++
  2153. b := -0.5
  2154. b++
  2155. c := ivec2(0)
  2156. c++
  2157. d := vec2(-0.25)
  2158. d++
  2159. return vec4(float(a), b, float(c.x), d.y)
  2160. }
  2161. `))
  2162. if err != nil {
  2163. t.Fatal(err)
  2164. }
  2165. dst.DrawRectShader(w, h, s, nil)
  2166. for j := 0; j < h; j++ {
  2167. for i := 0; i < w; i++ {
  2168. got := dst.At(i, j).(color.RGBA)
  2169. want := color.RGBA{R: 0xff, G: 0x80, B: 0xff, A: 0xc0}
  2170. if !sameColors(got, want, 2) {
  2171. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  2172. }
  2173. }
  2174. }
  2175. dst.Clear()
  2176. s, err = ebiten.NewShader([]byte(`//kage:unit pixels
  2177. package main
  2178. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  2179. a := 1
  2180. a--
  2181. b := 1.5
  2182. b--
  2183. c := ivec2(1)
  2184. c--
  2185. d := vec2(1.25)
  2186. d--
  2187. return vec4(float(a), b, float(c.x), d.y)
  2188. }
  2189. `))
  2190. if err != nil {
  2191. t.Fatal(err)
  2192. }
  2193. dst.DrawRectShader(w, h, s, nil)
  2194. for j := 0; j < h; j++ {
  2195. for i := 0; i < w; i++ {
  2196. got := dst.At(i, j).(color.RGBA)
  2197. want := color.RGBA{R: 0x00, G: 0x80, B: 0x00, A: 0x40}
  2198. if !sameColors(got, want, 2) {
  2199. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  2200. }
  2201. }
  2202. }
  2203. }
  2204. // Issue #2934
  2205. func TestShaderAssignConst(t *testing.T) {
  2206. const w, h = 16, 16
  2207. dst := ebiten.NewImage(w, h)
  2208. s, err := ebiten.NewShader([]byte(`//kage:unit pixels
  2209. package main
  2210. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  2211. a := 0.0
  2212. a = 1
  2213. b, c := 0.0, 0.0
  2214. b, c = 1, 1
  2215. d := 0.0
  2216. d += 1
  2217. return vec4(a, b, c, d)
  2218. }
  2219. `))
  2220. if err != nil {
  2221. t.Fatal(err)
  2222. }
  2223. dst.DrawRectShader(w, h, s, nil)
  2224. for j := 0; j < h; j++ {
  2225. for i := 0; i < w; i++ {
  2226. got := dst.At(i, j).(color.RGBA)
  2227. want := color.RGBA{R: 0xff, G: 0xff, B: 0xff, A: 0xff}
  2228. if !sameColors(got, want, 2) {
  2229. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  2230. }
  2231. }
  2232. }
  2233. }
  2234. func TestShaderCustomValues(t *testing.T) {
  2235. const w, h = 16, 16
  2236. dst := ebiten.NewImage(w, h)
  2237. s, err := ebiten.NewShader([]byte(`//kage:unit pixels
  2238. package main
  2239. func Fragment(dstPos vec4, srcPos vec2, color vec4, custom vec4) vec4 {
  2240. return custom
  2241. }
  2242. `))
  2243. if err != nil {
  2244. t.Fatal(err)
  2245. }
  2246. clr := color.RGBA{R: 0x10, G: 0x20, B: 0x30, A: 0x40}
  2247. dst.DrawTrianglesShader([]ebiten.Vertex{
  2248. {
  2249. DstX: 0,
  2250. DstY: 0,
  2251. SrcX: 0,
  2252. SrcY: 0,
  2253. ColorR: 1,
  2254. ColorG: 1,
  2255. ColorB: 1,
  2256. ColorA: 1,
  2257. Custom0: float32(clr.R) / 0xff,
  2258. Custom1: float32(clr.G) / 0xff,
  2259. Custom2: float32(clr.B) / 0xff,
  2260. Custom3: float32(clr.A) / 0xff,
  2261. },
  2262. {
  2263. DstX: w,
  2264. DstY: 0,
  2265. SrcX: w,
  2266. SrcY: 0,
  2267. ColorR: 1,
  2268. ColorG: 1,
  2269. ColorB: 1,
  2270. ColorA: 1,
  2271. Custom0: float32(clr.R) / 0xff,
  2272. Custom1: float32(clr.G) / 0xff,
  2273. Custom2: float32(clr.B) / 0xff,
  2274. Custom3: float32(clr.A) / 0xff,
  2275. },
  2276. {
  2277. DstX: 0,
  2278. DstY: h,
  2279. SrcX: 0,
  2280. SrcY: h,
  2281. ColorR: 1,
  2282. ColorG: 1,
  2283. ColorB: 1,
  2284. ColorA: 1,
  2285. Custom0: float32(clr.R) / 0xff,
  2286. Custom1: float32(clr.G) / 0xff,
  2287. Custom2: float32(clr.B) / 0xff,
  2288. Custom3: float32(clr.A) / 0xff,
  2289. },
  2290. {
  2291. DstX: w,
  2292. DstY: h,
  2293. SrcX: w,
  2294. SrcY: h,
  2295. ColorR: 1,
  2296. ColorG: 1,
  2297. ColorB: 1,
  2298. ColorA: 1,
  2299. Custom0: float32(clr.R) / 0xff,
  2300. Custom1: float32(clr.G) / 0xff,
  2301. Custom2: float32(clr.B) / 0xff,
  2302. Custom3: float32(clr.A) / 0xff,
  2303. },
  2304. }, []uint16{0, 1, 2, 1, 2, 3}, s, nil)
  2305. for j := 0; j < h; j++ {
  2306. for i := 0; i < w; i++ {
  2307. got := dst.At(i, j).(color.RGBA)
  2308. want := clr
  2309. if !sameColors(got, want, 2) {
  2310. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  2311. }
  2312. }
  2313. }
  2314. }
  2315. func TestShaderFragmentLessArguments(t *testing.T) {
  2316. const w, h = 16, 16
  2317. s0, err := ebiten.NewShader([]byte(`//kage:unit pixels
  2318. package main
  2319. func Fragment() vec4 {
  2320. return vec4(1, 0, 0, 1)
  2321. }
  2322. `))
  2323. if err != nil {
  2324. t.Fatal(err)
  2325. }
  2326. s1, err := ebiten.NewShader([]byte(`//kage:unit pixels
  2327. package main
  2328. func Fragment(dstPos vec4) vec4 {
  2329. return vec4(0, 1, 0, 1)
  2330. }
  2331. `))
  2332. if err != nil {
  2333. t.Fatal(err)
  2334. }
  2335. s2, err := ebiten.NewShader([]byte(`//kage:unit pixels
  2336. package main
  2337. func Fragment(dstPos vec4, srcPos vec2) vec4 {
  2338. return vec4(0, 0, 1, 1)
  2339. }
  2340. `))
  2341. if err != nil {
  2342. t.Fatal(err)
  2343. }
  2344. dst := ebiten.NewImage(w, h)
  2345. for idx, s := range []*ebiten.Shader{s0, s1, s2} {
  2346. dst.Clear()
  2347. dst.DrawTrianglesShader([]ebiten.Vertex{
  2348. {
  2349. DstX: 0,
  2350. DstY: 0,
  2351. SrcX: 0,
  2352. SrcY: 0,
  2353. ColorR: 1,
  2354. ColorG: 1,
  2355. ColorB: 1,
  2356. ColorA: 1,
  2357. },
  2358. {
  2359. DstX: w,
  2360. DstY: 0,
  2361. SrcX: w,
  2362. SrcY: 0,
  2363. ColorR: 1,
  2364. ColorG: 1,
  2365. ColorB: 1,
  2366. ColorA: 1,
  2367. },
  2368. {
  2369. DstX: 0,
  2370. DstY: h,
  2371. SrcX: 0,
  2372. SrcY: h,
  2373. ColorR: 1,
  2374. ColorG: 1,
  2375. ColorB: 1,
  2376. ColorA: 1,
  2377. },
  2378. {
  2379. DstX: w,
  2380. DstY: h,
  2381. SrcX: w,
  2382. SrcY: h,
  2383. ColorR: 1,
  2384. ColorG: 1,
  2385. ColorB: 1,
  2386. ColorA: 1,
  2387. },
  2388. }, []uint16{0, 1, 2, 1, 2, 3}, s, nil)
  2389. for j := 0; j < h; j++ {
  2390. for i := 0; i < w; i++ {
  2391. got := dst.At(i, j).(color.RGBA)
  2392. var want color.RGBA
  2393. switch idx {
  2394. case 0:
  2395. want = color.RGBA{R: 0xff, A: 0xff}
  2396. case 1:
  2397. want = color.RGBA{G: 0xff, A: 0xff}
  2398. case 2:
  2399. want = color.RGBA{B: 0xff, A: 0xff}
  2400. }
  2401. if !sameColors(got, want, 2) {
  2402. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  2403. }
  2404. }
  2405. }
  2406. }
  2407. }
  2408. func TestShaderArray(t *testing.T) {
  2409. const w, h = 16, 16
  2410. dst := ebiten.NewImage(w, h)
  2411. s, err := ebiten.NewShader([]byte(`//kage:unit pixels
  2412. package main
  2413. func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
  2414. a := [4]float{1}
  2415. b := [4]float{1, 1}
  2416. c := [4]float{1, 1, 1}
  2417. d := [4]float{1, 1, 1, 1}
  2418. return vec4(a[3], b[3], c[3], d[3])
  2419. }
  2420. `))
  2421. if err != nil {
  2422. t.Fatal(err)
  2423. }
  2424. dst.DrawRectShader(w, h, s, nil)
  2425. for j := 0; j < h; j++ {
  2426. for i := 0; i < w; i++ {
  2427. got := dst.At(i, j).(color.RGBA)
  2428. want := color.RGBA{R: 0x00, G: 0x00, B: 0x00, A: 0xff}
  2429. if !sameColors(got, want, 2) {
  2430. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  2431. }
  2432. }
  2433. }
  2434. }
  2435. func BenchmarkBuiltinShader(b *testing.B) {
  2436. // Create a shader to cache the shader compilation result.
  2437. _ = ebiten.BuiltinShader(builtinshader.FilterNearest, builtinshader.AddressUnsafe, false)
  2438. for i := 0; i < b.N; i++ {
  2439. _ = ebiten.BuiltinShader(builtinshader.FilterNearest, builtinshader.AddressUnsafe, false)
  2440. }
  2441. }