diff --git a/pixelgl/attr.go b/pixelgl/attr.go deleted file mode 100644 index c540bd1..0000000 --- a/pixelgl/attr.go +++ /dev/null @@ -1,102 +0,0 @@ -package pixelgl - -import "github.com/go-gl/mathgl/mgl32" - -// AttrType is the attribute's identifier -type AttrType int - -// List of all possible attribute types. -const ( - Int AttrType = iota - Float - Vec2 - Vec3 - Vec4 - Mat2 - Mat23 - Mat24 - Mat3 - Mat32 - Mat34 - Mat4 - Mat42 - Mat43 - Intp // pointers - Floatp - Vec2p - Vec3p - Vec4p - Mat2p - Mat23p - Mat24p - Mat3p - Mat32p - Mat34p - Mat4p - Mat42p - Mat43p -) - -// Returns the type identifier for any (supported) variable type -func getAttrType(v interface{}) AttrType { - switch v.(type) { - case int32: - return Int - case float32: - return Float - case mgl32.Vec2: - return Vec2 - case mgl32.Vec3: - return Vec3 - case mgl32.Vec4: - return Vec4 - case mgl32.Mat2: - return Mat2 - case mgl32.Mat2x3: - return Mat23 - case mgl32.Mat2x4: - return Mat24 - case mgl32.Mat3: - return Mat3 - case mgl32.Mat3x2: - return Mat32 - case mgl32.Mat3x4: - return Mat34 - case mgl32.Mat4: - return Mat4 - case mgl32.Mat4x2: - return Mat42 - case mgl32.Mat4x3: - return Mat43 - case *mgl32.Vec2: - return Vec2p - case *mgl32.Vec3: - return Vec3p - case *mgl32.Vec4: - return Vec4p - case *mgl32.Mat2: - return Mat2p - case *mgl32.Mat2x3: - return Mat23p - case *mgl32.Mat2x4: - return Mat24p - case *mgl32.Mat3: - return Mat3p - case *mgl32.Mat3x2: - return Mat32p - case *mgl32.Mat3x4: - return Mat34p - case *mgl32.Mat4: - return Mat4p - case *mgl32.Mat4x2: - return Mat42p - case *mgl32.Mat4x3: - return Mat43p - case *int32: - return Intp - case *float32: - return Floatp - default: - panic("invalid AttrType") - } -} diff --git a/pixelgl/canvas.go b/pixelgl/canvas.go index 66c2ac4..1e82fee 100644 --- a/pixelgl/canvas.go +++ b/pixelgl/canvas.go @@ -43,21 +43,21 @@ func NewCanvas(bounds pixel.Rect) *Canvas { return c } -// BindUniform will add a uniform with any supported underlying variable -// if the uniform already exists, including defaults, they will be reassigned -// to the new value -func (c *Canvas) BindUniform(Name string, Value interface{}) { +// SetUniform will update the named uniform with the value of any supported underlying +// 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.AddUniform(Name, Value) } // UpdateShader needs to be called after any changes to the underlying GLShader -// are made (ie, BindUniform(), SetFragmentShader()...) +// are made, such as, SetUniform, SetFragmentShader... func (c *Canvas) UpdateShader() { c.shader.update() } -// SetFragmentShader allows you to define a new fragment shader on the underlying -// GLShader. fs is the GLSL source, not a filename +// SetFragmentShader allows you to set a new fragment shader on the underlying +// framebuffer. Argument "fs" is the GLSL source, not a filename. func (c *Canvas) SetFragmentShader(fs string) { c.shader.fs = fs } @@ -204,7 +204,7 @@ func (c *Canvas) setUniforms(texbounds pixel.Rect) { } for loc, u := range c.shader.uniforms { - c.shader.s.SetUniformAttr(loc, u.Value) + c.shader.s.SetUniformAttr(loc, u.Value()) } } @@ -336,7 +336,7 @@ func (ct *canvasTriangles) draw(tex *glhf.Texture, bounds pixel.Rect) { } for loc, u := range ct.dst.shader.uniforms { - ct.dst.shader.s.SetUniformAttr(loc, u.Value) + ct.dst.shader.s.SetUniformAttr(loc, u.Value()) } if tex == nil { diff --git a/pixelgl/glshader.go b/pixelgl/glshader.go index 9d2e8fe..865c6fd 100644 --- a/pixelgl/glshader.go +++ b/pixelgl/glshader.go @@ -10,28 +10,27 @@ import ( // 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 { - s *glhf.Shader - vf, uf glhf.AttrFormat - vs, fs string +type GLShader struct { + s *glhf.Shader + vf, uf glhf.AttrFormat + vs, fs string - uniforms []gsUniformAttr + uniforms []gsUniformAttr - uniformDefaults struct { - transform mgl32.Mat3 - colormask mgl32.Vec4 - bounds mgl32.Vec4 - texbounds mgl32.Vec4 - } + uniformDefaults struct { + transform mgl32.Mat3 + colormask mgl32.Vec4 + bounds mgl32.Vec4 + texbounds mgl32.Vec4 } +} - gsUniformAttr struct { - Name string - Type AttrType - Value interface{} - } -) +type gsUniformAttr struct { + Name string + Type glhf.AttrType + value interface{} + ispointer bool +} // reinitialize GLShader data and recompile the underlying gl shader object func (gs *GLShader) update() { @@ -39,7 +38,7 @@ func (gs *GLShader) update() { for _, u := range gs.uniforms { gs.uf = append(gs.uf, glhf.Attr{ Name: u.Name, - Type: glhf.AttrType(u.Type), + Type: u.Type, }) } var shader *glhf.Shader @@ -69,31 +68,33 @@ func (gs *GLShader) getUniform(Name string) int { return -1 } -// AddUniform appends a custom uniform name and value to the shader +// AddUniform appends a custom uniform name and value to the shader. +// if the uniform already exists, it will simply be overwritten. // -// To add a time uniform for example: -// -// utime := float32(time.Since(starttime)).Seconds()) -// mycanvas.shader.AddUniform("u_time", &utime) +// example: // +// utime := float32(time.Since(starttime)).Seconds()) +// mycanvas.shader.AddUniform("u_time", &utime) func (gs *GLShader) AddUniform(Name string, Value interface{}) { - Type := getAttrType(Value) + t, p := getAttrType(Value) if loc := gs.getUniform(Name); loc > -1 { gs.uniforms[loc].Name = Name - gs.uniforms[loc].Type = Type - gs.uniforms[loc].Value = Value + gs.uniforms[loc].Type = t + gs.uniforms[loc].ispointer = p + gs.uniforms[loc].value = Value return } gs.uniforms = append(gs.uniforms, gsUniformAttr{ - Name: Name, - Type: Type, - Value: Value, + Name: Name, + Type: t, + ispointer: p, + value: Value, }) } -// Sets up a base shader with everything needed for a pixel +// Sets up a base shader with everything needed for a Pixel // canvas to render correctly. The defaults can be overridden -// by simply using AddUniform() +// by simply using the AddUniform function. func baseShader(c *Canvas) { gs := &GLShader{ vf: defaultCanvasVertexFormat, @@ -109,6 +110,111 @@ func baseShader(c *Canvas) { 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{} { + if !gu.ispointer { + return gu.value + } + switch gu.Type { + case glhf.Vec2: + return *gu.value.(*mgl32.Vec2) + case glhf.Vec3: + return *gu.value.(*mgl32.Vec3) + case glhf.Vec4: + return *gu.value.(*mgl32.Vec4) + case glhf.Mat2: + return *gu.value.(*mgl32.Mat2) + case glhf.Mat23: + return *gu.value.(*mgl32.Mat2x3) + case glhf.Mat24: + return *gu.value.(*mgl32.Mat2x4) + case glhf.Mat3: + return *gu.value.(*mgl32.Mat3) + case glhf.Mat32: + return *gu.value.(*mgl32.Mat3x2) + case glhf.Mat34: + return *gu.value.(*mgl32.Mat3x4) + case glhf.Mat4: + return *gu.value.(*mgl32.Mat4) + case glhf.Mat42: + return *gu.value.(*mgl32.Mat4x2) + case glhf.Mat43: + return *gu.value.(*mgl32.Mat4x3) + case glhf.Int: + return *gu.value.(*int32) + case glhf.Float: + return *gu.value.(*float32) + default: + panic("invalid attrtype") + } +} + +// Returns the type identifier for any (supported) attribute variable type +// and whether or not it is a pointer of that type. +func getAttrType(v interface{}) (glhf.AttrType, bool) { + switch v.(type) { + case int32: + return glhf.Int, false + case float32: + return glhf.Float, false + case mgl32.Vec2: + return glhf.Vec2, false + case mgl32.Vec3: + return glhf.Vec3, false + case mgl32.Vec4: + return glhf.Vec4, false + case mgl32.Mat2: + return glhf.Mat2, false + case mgl32.Mat2x3: + return glhf.Mat23, false + case mgl32.Mat2x4: + return glhf.Mat24, false + case mgl32.Mat3: + return glhf.Mat3, false + case mgl32.Mat3x2: + return glhf.Mat32, false + case mgl32.Mat3x4: + return glhf.Mat34, false + case mgl32.Mat4: + return glhf.Mat4, false + case mgl32.Mat4x2: + return glhf.Mat42, false + case mgl32.Mat4x3: + return glhf.Mat43, false + case *mgl32.Vec2: + return glhf.Vec2, true + case *mgl32.Vec3: + return glhf.Vec3, true + case *mgl32.Vec4: + return glhf.Vec4, true + case *mgl32.Mat2: + return glhf.Mat2, true + case *mgl32.Mat2x3: + return glhf.Mat23, true + case *mgl32.Mat2x4: + return glhf.Mat24, true + case *mgl32.Mat3: + return glhf.Mat3, true + case *mgl32.Mat3x2: + return glhf.Mat32, true + case *mgl32.Mat3x4: + return glhf.Mat34, true + case *mgl32.Mat4: + return glhf.Mat4, true + case *mgl32.Mat4x2: + return glhf.Mat42, true + case *mgl32.Mat4x3: + return glhf.Mat43, true + case *int32: + return glhf.Int, true + case *float32: + return glhf.Float, true + default: + panic("invalid AttrType") + } +} + var defaultCanvasVertexShader = ` #version 330 core diff --git a/pixelgl/window.go b/pixelgl/window.go index de7bb0d..2d646c5 100644 --- a/pixelgl/window.go +++ b/pixelgl/window.go @@ -425,7 +425,7 @@ func (w *Window) Color(at pixel.Vec) pixel.RGBA { return w.canvas.Color(at) } -// GetCanvas returns the window's underlying Canvas -func (w *Window) GetCanvas() *Canvas { +// Canvas returns the window's underlying Canvas +func (w *Window) Canvas() *Canvas { return w.canvas }