Merge pull request #246 from dusk125/tri_shader
#244 GLTriangle's fragment shader is used when rendered by the Canvas.
This commit is contained in:
commit
6e34aae429
|
@ -19,7 +19,7 @@ import (
|
||||||
// It supports TrianglesPosition, TrianglesColor, TrianglesPicture and PictureColor.
|
// It supports TrianglesPosition, TrianglesColor, TrianglesPicture and PictureColor.
|
||||||
type Canvas struct {
|
type Canvas struct {
|
||||||
gf *GLFrame
|
gf *GLFrame
|
||||||
shader *glShader
|
shader *GLShader
|
||||||
|
|
||||||
cmp pixel.ComposeMethod
|
cmp pixel.ComposeMethod
|
||||||
mat mgl32.Mat3
|
mat mgl32.Mat3
|
||||||
|
@ -39,9 +39,8 @@ func NewCanvas(bounds pixel.Rect) *Canvas {
|
||||||
col: mgl32.Vec4{1, 1, 1, 1},
|
col: mgl32.Vec4{1, 1, 1, 1},
|
||||||
}
|
}
|
||||||
|
|
||||||
baseShader(c)
|
c.shader = NewGLShader(baseCanvasFragmentShader)
|
||||||
c.SetBounds(bounds)
|
c.SetBounds(bounds)
|
||||||
c.shader.update()
|
|
||||||
return c
|
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
|
// attribute variable. If the uniform already exists, including defaults, they will be reassigned
|
||||||
// to the new value. The value can be a pointer.
|
// to the new value. The value can be a pointer.
|
||||||
func (c *Canvas) SetUniform(name string, value interface{}) {
|
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
|
// SetFragmentShader allows you to set a new fragment shader on the underlying
|
||||||
// framebuffer. Argument "src" is the GLSL source, not a filename.
|
// framebuffer. Argument "src" is the GLSL source, not a filename.
|
||||||
func (c *Canvas) SetFragmentShader(src string) {
|
func (c *Canvas) SetFragmentShader(src string) {
|
||||||
c.shader.fs = src
|
c.shader.fs = src
|
||||||
c.shader.update()
|
c.shader.Update()
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeTriangles creates a specialized copy of the supplied Triangles that draws onto this Canvas.
|
// MakeTriangles creates a specialized copy of the supplied Triangles that draws onto this Canvas.
|
||||||
//
|
//
|
||||||
// TrianglesPosition, TrianglesColor and TrianglesPicture are supported.
|
// TrianglesPosition, TrianglesColor and TrianglesPicture are supported.
|
||||||
func (c *Canvas) MakeTriangles(t pixel.Triangles) pixel.TargetTriangles {
|
func (c *Canvas) MakeTriangles(t pixel.Triangles) pixel.TargetTriangles {
|
||||||
|
if gt, ok := t.(*GLTriangles); ok {
|
||||||
|
return &canvasTriangles{
|
||||||
|
GLTriangles: gt,
|
||||||
|
dst: c,
|
||||||
|
}
|
||||||
|
}
|
||||||
return &canvasTriangles{
|
return &canvasTriangles{
|
||||||
GLTriangles: NewGLTriangles(c.shader.s, t),
|
GLTriangles: NewGLTriangles(c.shader, t),
|
||||||
dst: c,
|
dst: c,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -290,15 +295,15 @@ func (ct *canvasTriangles) draw(tex *glhf.Texture, bounds pixel.Rect) {
|
||||||
setBlendFunc(cmp)
|
setBlendFunc(cmp)
|
||||||
|
|
||||||
frame := ct.dst.gf.Frame()
|
frame := ct.dst.gf.Frame()
|
||||||
shader := ct.dst.shader.s
|
shader := ct.shader.s
|
||||||
|
|
||||||
frame.Begin()
|
frame.Begin()
|
||||||
shader.Begin()
|
shader.Begin()
|
||||||
|
|
||||||
ct.dst.shader.uniformDefaults.transform = mat
|
ct.shader.uniformDefaults.transform = mat
|
||||||
ct.dst.shader.uniformDefaults.colormask = col
|
ct.shader.uniformDefaults.colormask = col
|
||||||
dstBounds := ct.dst.Bounds()
|
dstBounds := ct.dst.Bounds()
|
||||||
ct.dst.shader.uniformDefaults.bounds = mgl32.Vec4{
|
ct.shader.uniformDefaults.bounds = mgl32.Vec4{
|
||||||
float32(dstBounds.Min.X),
|
float32(dstBounds.Min.X),
|
||||||
float32(dstBounds.Min.Y),
|
float32(dstBounds.Min.Y),
|
||||||
float32(dstBounds.W()),
|
float32(dstBounds.W()),
|
||||||
|
@ -306,15 +311,15 @@ func (ct *canvasTriangles) draw(tex *glhf.Texture, bounds pixel.Rect) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bx, by, bw, bh := intBounds(bounds)
|
bx, by, bw, bh := intBounds(bounds)
|
||||||
ct.dst.shader.uniformDefaults.texbounds = mgl32.Vec4{
|
ct.shader.uniformDefaults.texbounds = mgl32.Vec4{
|
||||||
float32(bx),
|
float32(bx),
|
||||||
float32(by),
|
float32(by),
|
||||||
float32(bw),
|
float32(bw),
|
||||||
float32(bh),
|
float32(bh),
|
||||||
}
|
}
|
||||||
|
|
||||||
for loc, u := range ct.dst.shader.uniforms {
|
for loc, u := range ct.shader.uniforms {
|
||||||
ct.dst.shader.s.SetUniformAttr(loc, u.Value())
|
ct.shader.s.SetUniformAttr(loc, u.Value())
|
||||||
}
|
}
|
||||||
|
|
||||||
if clip, has := ct.ClipRect(); has {
|
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())
|
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},
|
|
||||||
}
|
|
||||||
|
|
|
@ -7,10 +7,10 @@ import (
|
||||||
"github.com/pkg/errors"
|
"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
|
// shader configuration. This allows for customization of shaders on
|
||||||
// a per canvas basis.
|
// a per canvas basis.
|
||||||
type glShader struct {
|
type GLShader struct {
|
||||||
s *glhf.Shader
|
s *glhf.Shader
|
||||||
vf, uf glhf.AttrFormat
|
vf, uf glhf.AttrFormat
|
||||||
vs, fs string
|
vs, fs string
|
||||||
|
@ -32,8 +32,42 @@ type gsUniformAttr struct {
|
||||||
ispointer bool
|
ispointer bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// reinitialize GLShader data and recompile the underlying gl shader object
|
const (
|
||||||
func (gs *glShader) update() {
|
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
|
gs.uf = nil
|
||||||
for _, u := range gs.uniforms {
|
for _, u := range gs.uniforms {
|
||||||
gs.uf = append(gs.uf, glhf.Attr{
|
gs.uf = append(gs.uf, glhf.Attr{
|
||||||
|
@ -59,7 +93,7 @@ func (gs *glShader) update() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// gets the uniform index from GLShader
|
// 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 {
|
for i, u := range gs.uniforms {
|
||||||
if u.Name == Name {
|
if u.Name == Name {
|
||||||
return i
|
return i
|
||||||
|
@ -75,7 +109,7 @@ func (gs *glShader) getUniform(Name string) int {
|
||||||
//
|
//
|
||||||
// utime := float32(time.Since(starttime)).Seconds())
|
// utime := float32(time.Since(starttime)).Seconds())
|
||||||
// mycanvas.shader.AddUniform("u_time", &utime)
|
// 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)
|
t, p := getAttrType(value)
|
||||||
if loc := gs.getUniform(name); loc > -1 {
|
if loc := gs.getUniform(name); loc > -1 {
|
||||||
gs.uniforms[loc].Name = name
|
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
|
// Value returns the attribute's concrete value. If the stored value
|
||||||
// is a pointer, we return the dereferenced value.
|
// is a pointer, we return the dereferenced value.
|
||||||
func (gu *gsUniformAttr) Value() interface{} {
|
func (gu *gsUniformAttr) Value() interface{} {
|
||||||
|
|
|
@ -15,7 +15,7 @@ import (
|
||||||
type GLTriangles struct {
|
type GLTriangles struct {
|
||||||
vs *glhf.VertexSlice
|
vs *glhf.VertexSlice
|
||||||
data []float32
|
data []float32
|
||||||
shader *glhf.Shader
|
shader *GLShader
|
||||||
clip pixel.Rect
|
clip pixel.Rect
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,11 +28,11 @@ var (
|
||||||
// NewGLTriangles returns GLTriangles initialized with the data from the supplied Triangles.
|
// NewGLTriangles returns GLTriangles initialized with the data from the supplied Triangles.
|
||||||
//
|
//
|
||||||
// Only draw the Triangles using the provided Shader.
|
// 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
|
var gt *GLTriangles
|
||||||
mainthread.Call(func() {
|
mainthread.Call(func() {
|
||||||
gt = &GLTriangles{
|
gt = &GLTriangles{
|
||||||
vs: glhf.MakeVertexSlice(shader, 0, t.Len()),
|
vs: glhf.MakeVertexSlice(shader.s, 0, t.Len()),
|
||||||
shader: shader,
|
shader: shader,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -49,7 +49,7 @@ func (gt *GLTriangles) VertexSlice() *glhf.VertexSlice {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shader returns the GLTriangles's associated shader.
|
// Shader returns the GLTriangles's associated shader.
|
||||||
func (gt *GLTriangles) Shader() *glhf.Shader {
|
func (gt *GLTriangles) Shader() *GLShader {
|
||||||
return gt.shader
|
return gt.shader
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue