shader_test.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926
  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. "image"
  17. "image/color"
  18. "testing"
  19. . "github.com/hajimehoshi/ebiten"
  20. )
  21. func TestShaderFill(t *testing.T) {
  22. const w, h = 16, 16
  23. dst, _ := NewImage(w, h, FilterDefault)
  24. s, err := NewShader([]byte(`package main
  25. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  26. return vec4(1, 0, 0, 1)
  27. }
  28. `))
  29. if err != nil {
  30. t.Fatal(err)
  31. }
  32. dst.DrawRectShader(w/2, h/2, s, nil)
  33. for j := 0; j < h; j++ {
  34. for i := 0; i < w; i++ {
  35. got := dst.At(i, j).(color.RGBA)
  36. var want color.RGBA
  37. if i < w/2 && j < h/2 {
  38. want = color.RGBA{0xff, 0, 0, 0xff}
  39. }
  40. if got != want {
  41. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  42. }
  43. }
  44. }
  45. }
  46. func TestShaderFillWithDrawImage(t *testing.T) {
  47. const w, h = 16, 16
  48. dst, _ := NewImage(w, h, FilterDefault)
  49. s, err := NewShader([]byte(`package main
  50. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  51. return vec4(1, 0, 0, 1)
  52. }
  53. `))
  54. if err != nil {
  55. t.Fatal(err)
  56. }
  57. src, _ := NewImage(w/2, h/2, FilterDefault)
  58. op := &DrawRectShaderOptions{}
  59. op.Images[0] = src
  60. dst.DrawRectShader(w/2, h/2, s, op)
  61. for j := 0; j < h; j++ {
  62. for i := 0; i < w; i++ {
  63. got := dst.At(i, j).(color.RGBA)
  64. var want color.RGBA
  65. if i < w/2 && j < h/2 {
  66. want = color.RGBA{0xff, 0, 0, 0xff}
  67. }
  68. if got != want {
  69. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  70. }
  71. }
  72. }
  73. }
  74. func TestShaderFillWithDrawTriangles(t *testing.T) {
  75. const w, h = 16, 16
  76. dst, _ := NewImage(w, h, FilterDefault)
  77. s, err := NewShader([]byte(`package main
  78. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  79. return vec4(1, 0, 0, 1)
  80. }
  81. `))
  82. if err != nil {
  83. t.Fatal(err)
  84. }
  85. src, _ := NewImage(w/2, h/2, FilterDefault)
  86. op := &DrawTrianglesShaderOptions{}
  87. op.Images[0] = src
  88. vs := []Vertex{
  89. {
  90. DstX: 0,
  91. DstY: 0,
  92. SrcX: 0,
  93. SrcY: 0,
  94. ColorR: 1,
  95. ColorG: 1,
  96. ColorB: 1,
  97. ColorA: 1,
  98. },
  99. {
  100. DstX: w,
  101. DstY: 0,
  102. SrcX: w / 2,
  103. SrcY: 0,
  104. ColorR: 1,
  105. ColorG: 1,
  106. ColorB: 1,
  107. ColorA: 1,
  108. },
  109. {
  110. DstX: 0,
  111. DstY: h,
  112. SrcX: 0,
  113. SrcY: h / 2,
  114. ColorR: 1,
  115. ColorG: 1,
  116. ColorB: 1,
  117. ColorA: 1,
  118. },
  119. {
  120. DstX: w,
  121. DstY: h,
  122. SrcX: w / 2,
  123. SrcY: h / 2,
  124. ColorR: 1,
  125. ColorG: 1,
  126. ColorB: 1,
  127. ColorA: 1,
  128. },
  129. }
  130. is := []uint16{0, 1, 2, 1, 2, 3}
  131. dst.DrawTrianglesShader(vs, is, s, op)
  132. for j := 0; j < h; j++ {
  133. for i := 0; i < w; i++ {
  134. got := dst.At(i, j).(color.RGBA)
  135. want := color.RGBA{0xff, 0, 0, 0xff}
  136. if got != want {
  137. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  138. }
  139. }
  140. }
  141. }
  142. func TestShaderFunction(t *testing.T) {
  143. const w, h = 16, 16
  144. dst, _ := NewImage(w, h, FilterDefault)
  145. s, err := NewShader([]byte(`package main
  146. func clr(red float) (float, float, float, float) {
  147. return red, 0, 0, 1
  148. }
  149. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  150. return vec4(clr(1))
  151. }
  152. `))
  153. if err != nil {
  154. t.Fatal(err)
  155. }
  156. dst.DrawRectShader(w, h, s, nil)
  157. for j := 0; j < h; j++ {
  158. for i := 0; i < w; i++ {
  159. got := dst.At(i, j).(color.RGBA)
  160. want := color.RGBA{0xff, 0, 0, 0xff}
  161. if got != want {
  162. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  163. }
  164. }
  165. }
  166. }
  167. func TestShaderShadowing(t *testing.T) {
  168. if _, err := NewShader([]byte(`package main
  169. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  170. var position vec4
  171. return position
  172. }
  173. `)); err == nil {
  174. t.Errorf("error must be non-nil but was nil")
  175. }
  176. }
  177. func TestShaderDuplicatedVariables(t *testing.T) {
  178. if _, err := NewShader([]byte(`package main
  179. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  180. var foo vec4
  181. var foo vec4
  182. return foo
  183. }
  184. `)); err == nil {
  185. t.Errorf("error must be non-nil but was nil")
  186. }
  187. if _, err := NewShader([]byte(`package main
  188. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  189. var foo, foo vec4
  190. return foo
  191. }
  192. `)); err == nil {
  193. t.Errorf("error must be non-nil but was nil")
  194. }
  195. if _, err := NewShader([]byte(`package main
  196. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  197. var foo vec4
  198. foo := vec4(0)
  199. return foo
  200. }
  201. `)); err == nil {
  202. t.Errorf("error must be non-nil but was nil")
  203. }
  204. if _, err := NewShader([]byte(`package main
  205. func Foo() (vec4, vec4) {
  206. return vec4(0), vec4(0)
  207. }
  208. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  209. foo, foo := Foo()
  210. return foo
  211. }
  212. `)); err == nil {
  213. t.Errorf("error must be non-nil but was nil")
  214. }
  215. }
  216. func TestShaderNoMain(t *testing.T) {
  217. if _, err := NewShader([]byte(`package main
  218. `)); err == nil {
  219. t.Errorf("error must be non-nil but was nil")
  220. }
  221. }
  222. func TestShaderNoNewVariables(t *testing.T) {
  223. if _, err := NewShader([]byte(`package main
  224. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  225. _ := 1
  226. return vec4(0)
  227. }
  228. `)); err == nil {
  229. t.Errorf("error must be non-nil but was nil")
  230. }
  231. if _, err := NewShader([]byte(`package main
  232. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  233. _, _ := 1, 1
  234. return vec4(0)
  235. }
  236. `)); err == nil {
  237. t.Errorf("error must be non-nil but was nil")
  238. }
  239. if _, err := NewShader([]byte(`package main
  240. func Foo() (int, int) {
  241. return 1, 1
  242. }
  243. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  244. _, _ := Foo()
  245. return vec4(0)
  246. }
  247. `)); err == nil {
  248. t.Errorf("error must be non-nil but was nil")
  249. }
  250. if _, err := NewShader([]byte(`package main
  251. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  252. a, _ := 1, 1
  253. _ = a
  254. return vec4(0)
  255. }
  256. `)); err != nil {
  257. t.Error(err)
  258. }
  259. if _, err := NewShader([]byte(`package main
  260. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  261. _, a := 1, 1
  262. _ = a
  263. return vec4(0)
  264. }
  265. `)); err != nil {
  266. t.Error(err)
  267. }
  268. }
  269. func TestShaderWrongReturn(t *testing.T) {
  270. if _, err := NewShader([]byte(`package main
  271. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  272. return 0.0
  273. }
  274. `)); err == nil {
  275. t.Errorf("error must be non-nil but was nil")
  276. }
  277. if _, err := NewShader([]byte(`package main
  278. func Foo() (float, float) {
  279. return 0
  280. }
  281. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  282. return vec4(0)
  283. }
  284. `)); err == nil {
  285. t.Errorf("error must be non-nil but was nil")
  286. }
  287. if _, err := NewShader([]byte(`package main
  288. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  289. }
  290. `)); err == nil {
  291. t.Errorf("error must be non-nil but was nil")
  292. }
  293. if _, err := NewShader([]byte(`package main
  294. func Foo() float {
  295. }
  296. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  297. return vec4(0)
  298. }
  299. `)); err == nil {
  300. t.Errorf("error must be non-nil but was nil")
  301. }
  302. }
  303. func TestShaderMultipleValueReturn(t *testing.T) {
  304. if _, err := NewShader([]byte(`package main
  305. func Foo() (float, float) {
  306. return 0.0
  307. }
  308. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  309. return vec4(0)
  310. }
  311. `)); err == nil {
  312. t.Errorf("error must be non-nil but was nil")
  313. }
  314. if _, err := NewShader([]byte(`package main
  315. func Foo() float {
  316. return 0.0, 0.0
  317. }
  318. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  319. return vec4(0)
  320. }
  321. `)); err == nil {
  322. t.Errorf("error must be non-nil but was nil")
  323. }
  324. if _, err := NewShader([]byte(`package main
  325. func Foo() (float, float, float) {
  326. return 0.0, 0.0
  327. }
  328. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  329. return vec4(0)
  330. }
  331. `)); err == nil {
  332. t.Errorf("error must be non-nil but was nil")
  333. }
  334. if _, err := NewShader([]byte(`package main
  335. func Foo() (float, float) {
  336. return 0.0, 0.0
  337. }
  338. func Foo2() (float, float, float) {
  339. return Foo()
  340. }
  341. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  342. return vec4(0)
  343. }
  344. `)); err == nil {
  345. t.Errorf("error must be non-nil but was nil")
  346. }
  347. if _, err := NewShader([]byte(`package main
  348. func Foo() (float, float, float) {
  349. return 0.0, 0.0, 0.0
  350. }
  351. func Foo2() (float, float, float) {
  352. return Foo()
  353. }
  354. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  355. return vec4(0.0)
  356. }
  357. `)); err != nil {
  358. t.Error(err)
  359. }
  360. }
  361. func TestShaderInit(t *testing.T) {
  362. if _, err := NewShader([]byte(`package main
  363. func init() {
  364. }
  365. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  366. return vec4(0)
  367. }
  368. `)); err == nil {
  369. t.Errorf("error must be non-nil but was nil")
  370. }
  371. }
  372. func TestShaderUnspportedSyntax(t *testing.T) {
  373. if _, err := NewShader([]byte(`package main
  374. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  375. x := func() {
  376. }
  377. _ = x
  378. return vec4(0)
  379. }
  380. `)); err == nil {
  381. t.Errorf("error must be non-nil but was nil")
  382. }
  383. if _, err := NewShader([]byte(`package main
  384. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  385. go func() {
  386. }()
  387. return vec4(0)
  388. }
  389. `)); err == nil {
  390. t.Errorf("error must be non-nil but was nil")
  391. }
  392. if _, err := NewShader([]byte(`package main
  393. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  394. ch := make(chan int)
  395. _ = ch
  396. return vec4(0)
  397. }
  398. `)); err == nil {
  399. t.Errorf("error must be non-nil but was nil")
  400. }
  401. if _, err := NewShader([]byte(`package main
  402. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  403. x := 1i
  404. _ = x
  405. return vec4(0)
  406. }
  407. `)); err == nil {
  408. t.Errorf("error must be non-nil but was nil")
  409. }
  410. if _, err := NewShader([]byte(`package main
  411. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  412. var x [4]float
  413. y := x[1:2]
  414. _ = y
  415. return vec4(0)
  416. }
  417. `)); err == nil {
  418. t.Errorf("error must be non-nil but was nil")
  419. }
  420. if _, err := NewShader([]byte(`package main
  421. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  422. var x [4]float
  423. y := x[1:2:3]
  424. _ = y
  425. return vec4(0)
  426. }
  427. `)); err == nil {
  428. t.Errorf("error must be non-nil but was nil")
  429. }
  430. }
  431. func TestShaderUninitializedUniformVariables(t *testing.T) {
  432. const w, h = 16, 16
  433. dst, _ := NewImage(w, h, FilterDefault)
  434. s, err := NewShader([]byte(`package main
  435. var U vec4
  436. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  437. return U
  438. }
  439. `))
  440. if err != nil {
  441. t.Fatal(err)
  442. }
  443. dst.DrawRectShader(w, h, s, nil)
  444. for j := 0; j < h; j++ {
  445. for i := 0; i < w; i++ {
  446. got := dst.At(i, j).(color.RGBA)
  447. var want color.RGBA
  448. if got != want {
  449. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  450. }
  451. }
  452. }
  453. }
  454. func TestShaderForbidAssigningSpecialVariables(t *testing.T) {
  455. if _, err := NewShader([]byte(`package main
  456. var U vec4
  457. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  458. U = vec4(0)
  459. return vec4(0)
  460. }
  461. `)); err == nil {
  462. t.Errorf("error must be non-nil but was nil")
  463. }
  464. if _, err := NewShader([]byte(`package main
  465. var U vec4
  466. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  467. U.x = 0
  468. return vec4(0)
  469. }
  470. `)); err == nil {
  471. t.Errorf("error must be non-nil but was nil")
  472. }
  473. if _, err := NewShader([]byte(`package main
  474. var U [2]vec4
  475. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  476. U[0] = vec4(0)
  477. return vec4(0)
  478. }
  479. `)); err == nil {
  480. t.Errorf("error must be non-nil but was nil")
  481. }
  482. if _, err := NewShader([]byte(`package main
  483. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  484. texCoord = vec2(0)
  485. return vec4(0)
  486. }
  487. `)); err == nil {
  488. t.Errorf("error must be non-nil but was nil")
  489. }
  490. if _, err := NewShader([]byte(`package main
  491. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  492. texCoord.x = 0
  493. return vec4(0)
  494. }
  495. `)); err == nil {
  496. t.Errorf("error must be non-nil but was nil")
  497. }
  498. }
  499. func TestShaderBoolLiteral(t *testing.T) {
  500. if _, err := NewShader([]byte(`package main
  501. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  502. true := vec4(0)
  503. return true
  504. }
  505. `)); err != nil {
  506. t.Errorf("error must be nil but was non-nil")
  507. }
  508. }
  509. func TestShaderUnusedVariable(t *testing.T) {
  510. if _, err := NewShader([]byte(`package main
  511. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  512. x := 0
  513. return vec4(0)
  514. }
  515. `)); err == nil {
  516. t.Errorf("error must be non-nil but was nil")
  517. }
  518. if _, err := NewShader([]byte(`package main
  519. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  520. x := 0
  521. x = 1
  522. return vec4(0)
  523. }
  524. `)); err == nil {
  525. t.Errorf("error must be non-nil but was nil")
  526. }
  527. if _, err := NewShader([]byte(`package main
  528. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  529. x := vec4(0)
  530. x.x = 1
  531. return vec4(0)
  532. }
  533. `)); err != nil {
  534. t.Error(err)
  535. }
  536. // Increment statement treats a variable 'used'.
  537. // https://play.golang.org/p/2RuYMrSLjt3
  538. if _, err := NewShader([]byte(`package main
  539. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  540. x := 0
  541. x++
  542. return vec4(0)
  543. }
  544. `)); err != nil {
  545. t.Error(err)
  546. }
  547. if _, err := NewShader([]byte(`package main
  548. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  549. var a int
  550. return vec4(0)
  551. }
  552. `)); err == nil {
  553. t.Errorf("error must be non-nil but was nil")
  554. }
  555. if _, err := NewShader([]byte(`package main
  556. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  557. var a, b int
  558. return vec4(0)
  559. }
  560. `)); err == nil {
  561. t.Errorf("error must be non-nil but was nil")
  562. }
  563. }
  564. func TestShaderBlankLhs(t *testing.T) {
  565. if _, err := NewShader([]byte(`package main
  566. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  567. x := _
  568. _ = x
  569. return vec4(0)
  570. }
  571. `)); err == nil {
  572. t.Errorf("error must be non-nil but was nil")
  573. }
  574. if _, err := NewShader([]byte(`package main
  575. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  576. var x int = _
  577. _ = x
  578. return vec4(0)
  579. }
  580. `)); err == nil {
  581. t.Errorf("error must be non-nil but was nil")
  582. }
  583. if _, err := NewShader([]byte(`package main
  584. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  585. x := 1
  586. x = _
  587. _ = x
  588. return vec4(0)
  589. }
  590. `)); err == nil {
  591. t.Errorf("error must be non-nil but was nil")
  592. }
  593. if _, err := NewShader([]byte(`package main
  594. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  595. x := 1 + _
  596. _ = x
  597. return vec4(0)
  598. }
  599. `)); err == nil {
  600. t.Errorf("error must be non-nil but was nil")
  601. }
  602. if _, err := NewShader([]byte(`package main
  603. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  604. _++
  605. return vec4(0)
  606. }
  607. `)); err == nil {
  608. t.Errorf("error must be non-nil but was nil")
  609. }
  610. if _, err := NewShader([]byte(`package main
  611. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  612. _ += 1
  613. return vec4(0)
  614. }
  615. `)); err == nil {
  616. t.Errorf("error must be non-nil but was nil")
  617. }
  618. if _, err := NewShader([]byte(`package main
  619. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  620. _.x = 1
  621. return vec4(0)
  622. }
  623. `)); err == nil {
  624. t.Errorf("error must be non-nil but was nil")
  625. }
  626. }
  627. func TestShaderMatrix(t *testing.T) {
  628. const w, h = 16, 16
  629. dst, _ := NewImage(w, h, FilterDefault)
  630. s, err := NewShader([]byte(`package main
  631. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  632. var a, b mat4
  633. a[0] = vec4(0.125, 0.0625, 0.0625, 0.0625)
  634. a[1] = vec4(0.25, 0.25, 0.0625, 0.1875)
  635. a[2] = vec4(0.1875, 0.125, 0.25, 0.25)
  636. a[3] = vec4(0.0625, 0.1875, 0.125, 0.25)
  637. b[0] = vec4(0.0625, 0.125, 0.0625, 0.125)
  638. b[1] = vec4(0.125, 0.1875, 0.25, 0.0625)
  639. b[2] = vec4(0.125, 0.125, 0.1875, 0.1875)
  640. b[3] = vec4(0.25, 0.0625, 0.125, 0.0625)
  641. return vec4((a * b * vec4(1, 1, 1, 1)).xyz, 1)
  642. }
  643. `))
  644. if err != nil {
  645. t.Fatal(err)
  646. }
  647. src, _ := NewImage(w, h, FilterDefault)
  648. op := &DrawRectShaderOptions{}
  649. op.Images[0] = src
  650. dst.DrawRectShader(w, h, s, op)
  651. for j := 0; j < h; j++ {
  652. for i := 0; i < w; i++ {
  653. got := dst.At(i, j).(color.RGBA)
  654. want := color.RGBA{87, 82, 71, 255}
  655. if got != want {
  656. t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
  657. }
  658. }
  659. }
  660. }
  661. func TestShaderSubImage(t *testing.T) {
  662. const w, h = 16, 16
  663. s, err := NewShader([]byte(`package main
  664. func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
  665. r := imageSrc0At(texCoord).r
  666. g := imageSrc1At(texCoord).g
  667. return vec4(r, g, 0, 1)
  668. }
  669. `))
  670. if err != nil {
  671. t.Fatal(err)
  672. }
  673. src0, _ := NewImage(w, h, FilterDefault)
  674. pix0 := make([]byte, 4*w*h)
  675. for j := 0; j < h; j++ {
  676. for i := 0; i < w; i++ {
  677. if 2 <= i && i < 10 && 3 <= j && j < 11 {
  678. pix0[4*(j*w+i)] = 0xff
  679. pix0[4*(j*w+i)+1] = 0
  680. pix0[4*(j*w+i)+2] = 0
  681. pix0[4*(j*w+i)+3] = 0xff
  682. }
  683. }
  684. }
  685. src0.ReplacePixels(pix0)
  686. src0 = src0.SubImage(image.Rect(2, 3, 10, 11)).(*Image)
  687. src1, _ := NewImage(w, h, FilterDefault)
  688. pix1 := make([]byte, 4*w*h)
  689. for j := 0; j < h; j++ {
  690. for i := 0; i < w; i++ {
  691. if 6 <= i && i < 14 && 8 <= j && j < 16 {
  692. pix1[4*(j*w+i)] = 0
  693. pix1[4*(j*w+i)+1] = 0xff
  694. pix1[4*(j*w+i)+2] = 0
  695. pix1[4*(j*w+i)+3] = 0xff
  696. }
  697. }
  698. }
  699. src1.ReplacePixels(pix1)
  700. src1 = src1.SubImage(image.Rect(6, 8, 14, 16)).(*Image)
  701. testPixels := func(testname string, dst *Image) {
  702. for j := 0; j < h; j++ {
  703. for i := 0; i < w; i++ {
  704. got := dst.At(i, j).(color.RGBA)
  705. var want color.RGBA
  706. if i < w/2 && j < h/2 {
  707. want = color.RGBA{0xff, 0xff, 0, 0xff}
  708. }
  709. if got != want {
  710. t.Errorf("%s dst.At(%d, %d): got: %v, want: %v", testname, i, j, got, want)
  711. }
  712. }
  713. }
  714. }
  715. t.Run("DrawRectShader", func(t *testing.T) {
  716. dst, _ := NewImage(w, h, FilterDefault)
  717. op := &DrawRectShaderOptions{}
  718. op.Images[0] = src0
  719. op.Images[1] = src1
  720. dst.DrawRectShader(w/2, h/2, s, op)
  721. testPixels("DrawRectShader", dst)
  722. })
  723. t.Run("DrawTrianglesShader", func(t *testing.T) {
  724. dst, _ := NewImage(w, h, FilterDefault)
  725. vs := []Vertex{
  726. {
  727. DstX: 0,
  728. DstY: 0,
  729. SrcX: 2,
  730. SrcY: 3,
  731. ColorR: 1,
  732. ColorG: 1,
  733. ColorB: 1,
  734. ColorA: 1,
  735. },
  736. {
  737. DstX: w / 2,
  738. DstY: 0,
  739. SrcX: 10,
  740. SrcY: 3,
  741. ColorR: 1,
  742. ColorG: 1,
  743. ColorB: 1,
  744. ColorA: 1,
  745. },
  746. {
  747. DstX: 0,
  748. DstY: h / 2,
  749. SrcX: 2,
  750. SrcY: 11,
  751. ColorR: 1,
  752. ColorG: 1,
  753. ColorB: 1,
  754. ColorA: 1,
  755. },
  756. {
  757. DstX: w / 2,
  758. DstY: h / 2,
  759. SrcX: 10,
  760. SrcY: 11,
  761. ColorR: 1,
  762. ColorG: 1,
  763. ColorB: 1,
  764. ColorA: 1,
  765. },
  766. }
  767. is := []uint16{0, 1, 2, 1, 2, 3}
  768. op := &DrawTrianglesShaderOptions{}
  769. op.Images[0] = src0
  770. op.Images[1] = src1
  771. dst.DrawTrianglesShader(vs, is, s, op)
  772. testPixels("DrawTrianglesShader", dst)
  773. })
  774. }