diff --git a/batch.go b/batch.go index c69d617bb6c8d3146aba6500325c6f853d9e7421..b0d5e0a6b758126b507d6d6d87f32441906a7744 100644 --- a/batch.go +++ b/batch.go @@ -12,7 +12,8 @@ import ( // To put an object into a Batch, just draw it onto it: // object.Draw(batch) type Batch struct { - cont TrianglesDrawer + cont TrianglesDrawer + fixpic *Picture pic *Picture mat mgl32.Mat3 @@ -27,8 +28,8 @@ type Batch struct { // Note, that if the container does not support TrianglesColor, color masking will not work. func NewBatch(pic *Picture, container Triangles) *Batch { return &Batch{ - cont: TrianglesDrawer{Triangles: container}, - pic: pic, + cont: TrianglesDrawer{Triangles: container}, + fixpic: pic, } } @@ -39,7 +40,7 @@ func (b *Batch) Clear() { // Draw draws all objects that are currently in the Batch onto another Target. func (b *Batch) Draw(t Target) { - t.SetPicture(b.pic) + t.SetPicture(b.fixpic) b.cont.Draw(t) } @@ -52,15 +53,16 @@ func (b *Batch) MakeTriangles(t Triangles) Triangles { } } -// SetPicture only checks, whether the supplied Picture has the same underlying Picture as the fixed -// Picture of this Batch. If that is not true, this method panics. +// SetPicture sets the current Picture that will be used with the following draws. The underlying +// Texture of this Picture must be same as the underlying Texture of the Batch's Picture. func (b *Batch) SetPicture(p *Picture) { if p == nil { return } - if p.Texture() != b.pic.Texture() { - panic("batch: attempted to draw with a different Picture") + if p.Texture() != b.fixpic.Texture() { + panic("batch: attempted to draw with a different underlying Picture") } + b.pic = p } // SetTransform sets transforms used in the following draws onto the Batch. @@ -96,7 +98,9 @@ func (bt *batchTriangles) Draw() { }) bt.data[i].Position = V(float64(transPos.X()), float64(transPos.Y())) bt.data[i].Color = bt.data[i].Color.Mul(bt.batch.col) - //TODO: texture + if bt.batch.pic != nil && bt.data[i].Texture != V(-1, -1) { + bt.data[i].Texture = pictureBounds(bt.batch.pic, bt.data[i].Texture) + } } bt.trans.Update(&bt.data) bt.batch.cont.Append(bt.trans) diff --git a/util.go b/util.go index ce46294408f766d7be735bfd8d5ceeee78eb0a4f..6aafdb80489d7d2fc7d81f0bd88153cca254ceac 100644 --- a/util.go +++ b/util.go @@ -12,6 +12,17 @@ func clamp(x, low, high float64) float64 { return x } +func lerp(x float64, a, b Vec) Vec { + return a.Scaled(1-x) + b.Scaled(x) +} + +func lerp2d(x, a, b Vec) Vec { + return V( + lerp(x.X(), a, b).X(), + lerp(x.Y(), a, b).Y(), + ) +} + func transformToMat(t ...Transform) mgl32.Mat3 { mat := mgl32.Ident3() for i := range t { @@ -19,3 +30,11 @@ func transformToMat(t ...Transform) mgl32.Mat3 { } return mat } + +func pictureBounds(p *Picture, v Vec) Vec { + w, h := float64(p.Texture().Width()), float64(p.Texture().Height()) + a := p.Bounds().Pos + b := p.Bounds().Pos + p.Bounds().Size + u := lerp2d(v, a, b) + return V(u.X()/w, u.Y()/h) +} diff --git a/window.go b/window.go index 8d70cd9e9d42fdec4e8635d0da5c3c63cb844de2..bc953b513cb0ca52130dd7b2065886e63e2679c6 100644 --- a/window.go +++ b/window.go @@ -66,6 +66,7 @@ type Window struct { pic *Picture mat mgl32.Mat3 col mgl32.Vec4 + bnd mgl32.Vec4 // need to save these to correctly restore a fullscreen window restore struct { @@ -374,12 +375,14 @@ func (wt *windowTriangles) Draw() { pic := wt.w.pic // avoid mat := wt.w.mat // race col := wt.w.col // condition + bnd := wt.w.bnd pixelgl.DoNoBlock(func() { wt.w.begin() wt.w.shader.SetUniformAttr(transformMat3, mat) wt.w.shader.SetUniformAttr(maskColorVec4, col) + wt.w.shader.SetUniformAttr(boundsVec4, bnd) if pic != nil { pic.Texture().Begin() @@ -514,6 +517,14 @@ func (w *Window) MakeTriangles(t Triangles) Triangles { // SetPicture sets a Picture that will be used in subsequent drawings onto the window. func (w *Window) SetPicture(p *Picture) { + if p != nil { + min := pictureBounds(p, V(0, 0)) + max := pictureBounds(p, V(1, 1)) + w.bnd = mgl32.Vec4{ + float32(min.X()), float32(min.Y()), + float32(max.X()), float32(max.Y()), + } + } w.pic = p } @@ -552,11 +563,13 @@ var defaultVertexFormat = pixelgl.AttrFormat{ const ( maskColorVec4 int = iota transformMat3 + boundsVec4 ) var defaultUniformFormat = pixelgl.AttrFormat{ {Name: "maskColor", Type: pixelgl.Vec4}, {Name: "transform", Type: pixelgl.Mat3}, + {Name: "bounds", Type: pixelgl.Vec4}, } var defaultVertexShader = ` @@ -587,13 +600,20 @@ in vec2 Texture; out vec4 color; uniform vec4 maskColor; +uniform vec4 bounds; uniform sampler2D tex; void main() { + vec2 boundsMin = bounds.xy; + vec2 boundsMax = bounds.zw; + + float tx = boundsMin.x * (1 - Texture.x) + boundsMax.x * Texture.x; + float ty = boundsMin.y * (1 - Texture.y) + boundsMax.y * Texture.y; + if (Texture == vec2(-1, -1)) { color = maskColor * Color; } else { - color = maskColor * Color * texture(tex, vec2(Texture.x, 1 - Texture.y)); + color = maskColor * Color * texture(tex, vec2(tx, 1 - ty)); } } `