github.com/cybriq/giocore@v0.0.7-0.20210703034601-cfb9cb5f3900/gpu/internal/rendertest/transform_test.go (about) 1 package rendertest 2 3 import ( 4 "image" 5 "math" 6 "testing" 7 8 "golang.org/x/image/colornames" 9 10 "github.com/cybriq/giocore/f32" 11 "github.com/cybriq/giocore/op" 12 "github.com/cybriq/giocore/op/clip" 13 "github.com/cybriq/giocore/op/paint" 14 ) 15 16 func TestPaintOffset(t *testing.T) { 17 run(t, func(o *op.Ops) { 18 op.Offset(f32.Pt(10, 20)).Add(o) 19 paint.FillShape(o, red, clip.Rect(image.Rect(0, 0, 50, 50)).Op()) 20 }, func(r result) { 21 r.expect(0, 0, transparent) 22 r.expect(59, 30, colornames.Red) 23 r.expect(60, 30, transparent) 24 r.expect(10, 70, transparent) 25 }) 26 } 27 28 func TestPaintRotate(t *testing.T) { 29 run(t, func(o *op.Ops) { 30 a := f32.Affine2D{}.Rotate(f32.Pt(40, 40), -math.Pi/8) 31 op.Affine(a).Add(o) 32 paint.FillShape(o, red, clip.Rect(image.Rect(20, 20, 60, 60)).Op()) 33 }, func(r result) { 34 r.expect(40, 40, colornames.Red) 35 r.expect(50, 19, colornames.Red) 36 r.expect(59, 19, transparent) 37 r.expect(21, 21, transparent) 38 }) 39 } 40 41 func TestPaintShear(t *testing.T) { 42 run(t, func(o *op.Ops) { 43 a := f32.Affine2D{}.Shear(f32.Point{}, math.Pi/4, 0) 44 op.Affine(a).Add(o) 45 paint.FillShape(o, red, clip.Rect(image.Rect(0, 0, 40, 40)).Op()) 46 }, func(r result) { 47 r.expect(10, 30, transparent) 48 }) 49 } 50 51 func TestClipPaintOffset(t *testing.T) { 52 run(t, func(o *op.Ops) { 53 clip.RRect{Rect: f32.Rect(10, 10, 30, 30)}.Add(o) 54 op.Offset(f32.Pt(20, 20)).Add(o) 55 paint.FillShape(o, red, clip.Rect(image.Rect(0, 0, 100, 100)).Op()) 56 }, func(r result) { 57 r.expect(0, 0, transparent) 58 r.expect(19, 19, transparent) 59 r.expect(20, 20, colornames.Red) 60 r.expect(30, 30, transparent) 61 }) 62 } 63 64 func TestClipOffset(t *testing.T) { 65 run(t, func(o *op.Ops) { 66 op.Offset(f32.Pt(20, 20)).Add(o) 67 clip.RRect{Rect: f32.Rect(10, 10, 30, 30)}.Add(o) 68 paint.FillShape(o, red, clip.Rect(image.Rect(0, 0, 100, 100)).Op()) 69 }, func(r result) { 70 r.expect(0, 0, transparent) 71 r.expect(29, 29, transparent) 72 r.expect(30, 30, colornames.Red) 73 r.expect(49, 49, colornames.Red) 74 r.expect(50, 50, transparent) 75 }) 76 } 77 78 func TestClipScale(t *testing.T) { 79 run(t, func(o *op.Ops) { 80 a := f32.Affine2D{}.Scale(f32.Point{}, f32.Pt(2, 2)).Offset(f32.Pt(10, 10)) 81 op.Affine(a).Add(o) 82 clip.RRect{Rect: f32.Rect(10, 10, 20, 20)}.Add(o) 83 paint.FillShape(o, red, clip.Rect(image.Rect(0, 0, 1000, 1000)).Op()) 84 }, func(r result) { 85 r.expect(19+10, 19+10, transparent) 86 r.expect(20+10, 20+10, colornames.Red) 87 r.expect(39+10, 39+10, colornames.Red) 88 r.expect(40+10, 40+10, transparent) 89 }) 90 } 91 92 func TestClipRotate(t *testing.T) { 93 run(t, func(o *op.Ops) { 94 op.Affine(f32.Affine2D{}.Rotate(f32.Pt(40, 40), -math.Pi/4)).Add(o) 95 clip.RRect{Rect: f32.Rect(30, 30, 50, 50)}.Add(o) 96 paint.FillShape(o, red, clip.Rect(image.Rect(0, 40, 100, 100)).Op()) 97 }, func(r result) { 98 r.expect(39, 39, transparent) 99 r.expect(41, 41, colornames.Red) 100 r.expect(50, 50, transparent) 101 }) 102 } 103 104 func TestOffsetTexture(t *testing.T) { 105 run(t, func(o *op.Ops) { 106 op.Offset(f32.Pt(15, 15)).Add(o) 107 squares.Add(o) 108 scale(50.0/512, 50.0/512).Add(o) 109 paint.PaintOp{}.Add(o) 110 }, func(r result) { 111 r.expect(14, 20, transparent) 112 r.expect(66, 20, transparent) 113 r.expect(16, 64, colornames.Green) 114 r.expect(64, 16, colornames.Green) 115 }) 116 } 117 118 func TestOffsetScaleTexture(t *testing.T) { 119 run(t, func(o *op.Ops) { 120 op.Offset(f32.Pt(15, 15)).Add(o) 121 squares.Add(o) 122 op.Affine(f32.Affine2D{}.Scale(f32.Point{}, f32.Pt(2, 1))).Add(o) 123 scale(50.0/512, 50.0/512).Add(o) 124 paint.PaintOp{}.Add(o) 125 }, func(r result) { 126 r.expect(114, 64, colornames.Blue) 127 r.expect(116, 64, transparent) 128 }) 129 } 130 131 func TestRotateTexture(t *testing.T) { 132 run(t, func(o *op.Ops) { 133 defer op.Save(o).Load() 134 squares.Add(o) 135 a := f32.Affine2D{}.Offset(f32.Pt(30, 30)).Rotate(f32.Pt(40, 40), math.Pi/4) 136 op.Affine(a).Add(o) 137 scale(20.0/512, 20.0/512).Add(o) 138 paint.PaintOp{}.Add(o) 139 }, func(r result) { 140 r.expect(40, 40-12, colornames.Blue) 141 r.expect(40+12, 40, colornames.Green) 142 }) 143 } 144 145 func TestRotateClipTexture(t *testing.T) { 146 run(t, func(o *op.Ops) { 147 squares.Add(o) 148 a := f32.Affine2D{}.Rotate(f32.Pt(40, 40), math.Pi/8) 149 op.Affine(a).Add(o) 150 clip.RRect{Rect: f32.Rect(30, 30, 50, 50)}.Add(o) 151 op.Affine(f32.Affine2D{}.Offset(f32.Pt(10, 10))).Add(o) 152 scale(60.0/512, 60.0/512).Add(o) 153 paint.PaintOp{}.Add(o) 154 }, func(r result) { 155 r.expect(0, 0, transparent) 156 r.expect(37, 39, colornames.Green) 157 r.expect(36, 39, colornames.Green) 158 r.expect(35, 39, colornames.Green) 159 r.expect(34, 39, colornames.Green) 160 r.expect(33, 39, colornames.Green) 161 }) 162 } 163 164 func TestComplicatedTransform(t *testing.T) { 165 run(t, func(o *op.Ops) { 166 squares.Add(o) 167 168 clip.RRect{Rect: f32.Rect(0, 0, 100, 100), SE: 50, SW: 50, NW: 50, NE: 50}.Add(o) 169 170 a := f32.Affine2D{}.Shear(f32.Point{}, math.Pi/4, 0) 171 op.Affine(a).Add(o) 172 clip.RRect{Rect: f32.Rect(0, 0, 50, 40)}.Add(o) 173 174 scale(50.0/512, 50.0/512).Add(o) 175 paint.PaintOp{}.Add(o) 176 }, func(r result) { 177 r.expect(20, 5, transparent) 178 }) 179 } 180 181 func TestTransformOrder(t *testing.T) { 182 // check the ordering of operations bot in affine and in gpu stack. 183 run(t, func(o *op.Ops) { 184 a := f32.Affine2D{}.Offset(f32.Pt(64, 64)) 185 op.Affine(a).Add(o) 186 187 b := f32.Affine2D{}.Scale(f32.Point{}, f32.Pt(8, 8)) 188 op.Affine(b).Add(o) 189 190 c := f32.Affine2D{}.Offset(f32.Pt(-10, -10)).Scale(f32.Point{}, f32.Pt(0.5, 0.5)) 191 op.Affine(c).Add(o) 192 paint.FillShape(o, red, clip.Rect(image.Rect(0, 0, 20, 20)).Op()) 193 }, func(r result) { 194 // centered and with radius 40 195 r.expect(64-41, 64, transparent) 196 r.expect(64-39, 64, colornames.Red) 197 r.expect(64+39, 64, colornames.Red) 198 r.expect(64+41, 64, transparent) 199 }) 200 }