diff --git a/pixelgl/canvas.go b/pixelgl/canvas.go index e04df06..2cb310b 100644 --- a/pixelgl/canvas.go +++ b/pixelgl/canvas.go @@ -19,7 +19,7 @@ import ( // It supports TrianglesPosition, TrianglesColor, TrianglesPicture and PictureColor. type Canvas struct { gf *GLFrame - shader *glShader + shader *GLShader cmp pixel.ComposeMethod mat mgl32.Mat3 @@ -39,9 +39,8 @@ func NewCanvas(bounds pixel.Rect) *Canvas { col: mgl32.Vec4{1, 1, 1, 1}, } - baseShader(c) + c.shader = NewGLShader(baseCanvasFragmentShader) c.SetBounds(bounds) - c.shader.update() return c } @@ -49,22 +48,28 @@ func NewCanvas(bounds pixel.Rect) *Canvas { // attribute variable. If the uniform already exists, including defaults, they will be reassigned // to the new value. The value can be a pointer. func (c *Canvas) SetUniform(name string, value interface{}) { - c.shader.setUniform(name, value) + c.shader.SetUniform(name, value) } // SetFragmentShader allows you to set a new fragment shader on the underlying // framebuffer. Argument "src" is the GLSL source, not a filename. func (c *Canvas) SetFragmentShader(src string) { c.shader.fs = src - c.shader.update() + c.shader.Update() } // MakeTriangles creates a specialized copy of the supplied Triangles that draws onto this Canvas. // // TrianglesPosition, TrianglesColor and TrianglesPicture are supported. func (c *Canvas) MakeTriangles(t pixel.Triangles) pixel.TargetTriangles { + if gt, ok := t.(*GLTriangles); ok { + return &canvasTriangles{ + GLTriangles: gt, + dst: c, + } + } return &canvasTriangles{ - GLTriangles: NewGLTriangles(c.shader.s, t), + GLTriangles: NewGLTriangles(c.shader, t), dst: c, } } @@ -290,15 +295,15 @@ func (ct *canvasTriangles) draw(tex *glhf.Texture, bounds pixel.Rect) { setBlendFunc(cmp) frame := ct.dst.gf.Frame() - shader := ct.dst.shader.s + shader := ct.shader.s frame.Begin() shader.Begin() - ct.dst.shader.uniformDefaults.transform = mat - ct.dst.shader.uniformDefaults.colormask = col + ct.shader.uniformDefaults.transform = mat + ct.shader.uniformDefaults.colormask = col dstBounds := ct.dst.Bounds() - ct.dst.shader.uniformDefaults.bounds = mgl32.Vec4{ + ct.shader.uniformDefaults.bounds = mgl32.Vec4{ float32(dstBounds.Min.X), float32(dstBounds.Min.Y), float32(dstBounds.W()), @@ -306,15 +311,15 @@ func (ct *canvasTriangles) draw(tex *glhf.Texture, bounds pixel.Rect) { } bx, by, bw, bh := intBounds(bounds) - ct.dst.shader.uniformDefaults.texbounds = mgl32.Vec4{ + ct.shader.uniformDefaults.texbounds = mgl32.Vec4{ float32(bx), float32(by), float32(bw), float32(bh), } - for loc, u := range ct.dst.shader.uniforms { - ct.dst.shader.s.SetUniformAttr(loc, u.Value()) + for loc, u := range ct.shader.uniforms { + ct.shader.s.SetUniformAttr(loc, u.Value()) } if clip, has := ct.ClipRect(); has { @@ -360,17 +365,3 @@ func (cp *canvasPicture) Draw(t pixel.TargetTriangles) { } ct.draw(cp.GLPicture.Texture(), cp.GLPicture.Bounds()) } - -const ( - canvasPosition int = iota - canvasColor - canvasTexCoords - canvasIntensity -) - -var defaultCanvasVertexFormat = glhf.AttrFormat{ - canvasPosition: {Name: "aPosition", Type: glhf.Vec2}, - canvasColor: {Name: "aColor", Type: glhf.Vec4}, - canvasTexCoords: {Name: "aTexCoords", Type: glhf.Vec2}, - canvasIntensity: {Name: "aIntensity", Type: glhf.Float}, -} diff --git a/pixelgl/glshader.go b/pixelgl/glshader.go index 5023579..d472cca 100644 --- a/pixelgl/glshader.go +++ b/pixelgl/glshader.go @@ -7,10 +7,10 @@ import ( "github.com/pkg/errors" ) -// glShader is a type to assist with managing a canvas's underlying +// GLShader is a type to assist with managing a canvas's underlying // shader configuration. This allows for customization of shaders on // a per canvas basis. -type glShader struct { +type GLShader struct { s *glhf.Shader vf, uf glhf.AttrFormat vs, fs string @@ -32,8 +32,42 @@ type gsUniformAttr struct { ispointer bool } -// reinitialize GLShader data and recompile the underlying gl shader object -func (gs *glShader) update() { +const ( + canvasPosition int = iota + canvasColor + canvasTexCoords + canvasIntensity +) + +var defaultCanvasVertexFormat = glhf.AttrFormat{ + canvasPosition: {Name: "aPosition", Type: glhf.Vec2}, + canvasColor: {Name: "aColor", Type: glhf.Vec4}, + canvasTexCoords: {Name: "aTexCoords", Type: glhf.Vec2}, + canvasIntensity: {Name: "aIntensity", Type: glhf.Float}, +} + +// Sets up a base shader with everything needed for a Pixel +// canvas to render correctly. The defaults can be overridden +// by simply using the SetUniform function. +func NewGLShader(fragmentShader string) *GLShader { + gs := &GLShader{ + vf: defaultCanvasVertexFormat, + vs: baseCanvasVertexShader, + fs: fragmentShader, + } + + gs.SetUniform("uTransform", &gs.uniformDefaults.transform) + gs.SetUniform("uColorMask", &gs.uniformDefaults.colormask) + gs.SetUniform("uBounds", &gs.uniformDefaults.bounds) + gs.SetUniform("uTexBounds", &gs.uniformDefaults.texbounds) + + gs.Update() + + return gs +} + +// Update reinitialize GLShader data and recompile the underlying gl shader object +func (gs *GLShader) Update() { gs.uf = nil for _, u := range gs.uniforms { gs.uf = append(gs.uf, glhf.Attr{ @@ -59,7 +93,7 @@ func (gs *glShader) update() { } // gets the uniform index from GLShader -func (gs *glShader) getUniform(Name string) int { +func (gs *GLShader) getUniform(Name string) int { for i, u := range gs.uniforms { if u.Name == Name { return i @@ -75,7 +109,7 @@ func (gs *glShader) getUniform(Name string) int { // // utime := float32(time.Since(starttime)).Seconds()) // mycanvas.shader.AddUniform("u_time", &utime) -func (gs *glShader) setUniform(name string, value interface{}) { +func (gs *GLShader) SetUniform(name string, value interface{}) { t, p := getAttrType(value) if loc := gs.getUniform(name); loc > -1 { gs.uniforms[loc].Name = name @@ -92,24 +126,6 @@ func (gs *glShader) setUniform(name string, value interface{}) { }) } -// Sets up a base shader with everything needed for a Pixel -// canvas to render correctly. The defaults can be overridden -// by simply using the SetUniform function. -func baseShader(c *Canvas) { - gs := &glShader{ - vf: defaultCanvasVertexFormat, - vs: baseCanvasVertexShader, - fs: baseCanvasFragmentShader, - } - - gs.setUniform("uTransform", &gs.uniformDefaults.transform) - gs.setUniform("uColorMask", &gs.uniformDefaults.colormask) - gs.setUniform("uBounds", &gs.uniformDefaults.bounds) - gs.setUniform("uTexBounds", &gs.uniformDefaults.texbounds) - - c.shader = gs -} - // Value returns the attribute's concrete value. If the stored value // is a pointer, we return the dereferenced value. func (gu *gsUniformAttr) Value() interface{} { diff --git a/pixelgl/gltriangles.go b/pixelgl/gltriangles.go index 557f420..1cbcbe0 100644 --- a/pixelgl/gltriangles.go +++ b/pixelgl/gltriangles.go @@ -15,7 +15,7 @@ import ( type GLTriangles struct { vs *glhf.VertexSlice data []float32 - shader *glhf.Shader + shader *GLShader clip pixel.Rect } @@ -28,11 +28,11 @@ var ( // NewGLTriangles returns GLTriangles initialized with the data from the supplied Triangles. // // Only draw the Triangles using the provided Shader. -func NewGLTriangles(shader *glhf.Shader, t pixel.Triangles) *GLTriangles { +func NewGLTriangles(shader *GLShader, t pixel.Triangles) *GLTriangles { var gt *GLTriangles mainthread.Call(func() { gt = &GLTriangles{ - vs: glhf.MakeVertexSlice(shader, 0, t.Len()), + vs: glhf.MakeVertexSlice(shader.s, 0, t.Len()), shader: shader, } }) @@ -49,7 +49,7 @@ func (gt *GLTriangles) VertexSlice() *glhf.VertexSlice { } // Shader returns the GLTriangles's associated shader. -func (gt *GLTriangles) Shader() *glhf.Shader { +func (gt *GLTriangles) Shader() *GLShader { return gt.shader }