add support for Picture slicing (Batch and Window)

This commit is contained in:
faiface 2017-01-14 16:07:51 +01:00
parent 3b39cc60e9
commit c9f445787e
3 changed files with 53 additions and 10 deletions

View File

@ -12,7 +12,8 @@ import (
// To put an object into a Batch, just draw it onto it: // To put an object into a Batch, just draw it onto it:
// object.Draw(batch) // object.Draw(batch)
type Batch struct { type Batch struct {
cont TrianglesDrawer cont TrianglesDrawer
fixpic *Picture
pic *Picture pic *Picture
mat mgl32.Mat3 mat mgl32.Mat3
@ -27,8 +28,8 @@ type Batch struct {
// Note, that if the container does not support TrianglesColor, color masking will not work. // Note, that if the container does not support TrianglesColor, color masking will not work.
func NewBatch(pic *Picture, container Triangles) *Batch { func NewBatch(pic *Picture, container Triangles) *Batch {
return &Batch{ return &Batch{
cont: TrianglesDrawer{Triangles: container}, cont: TrianglesDrawer{Triangles: container},
pic: pic, fixpic: pic,
} }
} }
@ -39,7 +40,7 @@ func (b *Batch) Clear() {
// Draw draws all objects that are currently in the Batch onto another Target. // Draw draws all objects that are currently in the Batch onto another Target.
func (b *Batch) Draw(t Target) { func (b *Batch) Draw(t Target) {
t.SetPicture(b.pic) t.SetPicture(b.fixpic)
b.cont.Draw(t) 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 // SetPicture sets the current Picture that will be used with the following draws. The underlying
// Picture of this Batch. If that is not true, this method panics. // Texture of this Picture must be same as the underlying Texture of the Batch's Picture.
func (b *Batch) SetPicture(p *Picture) { func (b *Batch) SetPicture(p *Picture) {
if p == nil { if p == nil {
return return
} }
if p.Texture() != b.pic.Texture() { if p.Texture() != b.fixpic.Texture() {
panic("batch: attempted to draw with a different Picture") panic("batch: attempted to draw with a different underlying Picture")
} }
b.pic = p
} }
// SetTransform sets transforms used in the following draws onto the Batch. // 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].Position = V(float64(transPos.X()), float64(transPos.Y()))
bt.data[i].Color = bt.data[i].Color.Mul(bt.batch.col) 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.trans.Update(&bt.data)
bt.batch.cont.Append(bt.trans) bt.batch.cont.Append(bt.trans)

19
util.go
View File

@ -12,6 +12,17 @@ func clamp(x, low, high float64) float64 {
return x 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 { func transformToMat(t ...Transform) mgl32.Mat3 {
mat := mgl32.Ident3() mat := mgl32.Ident3()
for i := range t { for i := range t {
@ -19,3 +30,11 @@ func transformToMat(t ...Transform) mgl32.Mat3 {
} }
return mat 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)
}

View File

@ -66,6 +66,7 @@ type Window struct {
pic *Picture pic *Picture
mat mgl32.Mat3 mat mgl32.Mat3
col mgl32.Vec4 col mgl32.Vec4
bnd mgl32.Vec4
// need to save these to correctly restore a fullscreen window // need to save these to correctly restore a fullscreen window
restore struct { restore struct {
@ -374,12 +375,14 @@ func (wt *windowTriangles) Draw() {
pic := wt.w.pic // avoid pic := wt.w.pic // avoid
mat := wt.w.mat // race mat := wt.w.mat // race
col := wt.w.col // condition col := wt.w.col // condition
bnd := wt.w.bnd
pixelgl.DoNoBlock(func() { pixelgl.DoNoBlock(func() {
wt.w.begin() wt.w.begin()
wt.w.shader.SetUniformAttr(transformMat3, mat) wt.w.shader.SetUniformAttr(transformMat3, mat)
wt.w.shader.SetUniformAttr(maskColorVec4, col) wt.w.shader.SetUniformAttr(maskColorVec4, col)
wt.w.shader.SetUniformAttr(boundsVec4, bnd)
if pic != nil { if pic != nil {
pic.Texture().Begin() 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. // SetPicture sets a Picture that will be used in subsequent drawings onto the window.
func (w *Window) SetPicture(p *Picture) { 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 w.pic = p
} }
@ -552,11 +563,13 @@ var defaultVertexFormat = pixelgl.AttrFormat{
const ( const (
maskColorVec4 int = iota maskColorVec4 int = iota
transformMat3 transformMat3
boundsVec4
) )
var defaultUniformFormat = pixelgl.AttrFormat{ var defaultUniformFormat = pixelgl.AttrFormat{
{Name: "maskColor", Type: pixelgl.Vec4}, {Name: "maskColor", Type: pixelgl.Vec4},
{Name: "transform", Type: pixelgl.Mat3}, {Name: "transform", Type: pixelgl.Mat3},
{Name: "bounds", Type: pixelgl.Vec4},
} }
var defaultVertexShader = ` var defaultVertexShader = `
@ -587,13 +600,20 @@ in vec2 Texture;
out vec4 color; out vec4 color;
uniform vec4 maskColor; uniform vec4 maskColor;
uniform vec4 bounds;
uniform sampler2D tex; uniform sampler2D tex;
void main() { 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)) { if (Texture == vec2(-1, -1)) {
color = maskColor * Color; color = maskColor * Color;
} else { } else {
color = maskColor * Color * texture(tex, vec2(Texture.x, 1 - Texture.y)); color = maskColor * Color * texture(tex, vec2(tx, 1 - ty));
} }
} }
` `