diff --git a/canvas.go b/canvas.go index 8525dd4..cee2eb3 100644 --- a/canvas.go +++ b/canvas.go @@ -501,8 +501,6 @@ func (cv *Canvas) useShader(style *drawStyle) (vertexLoc uint32) { length := dir.len() dir = dir.divf(length) gli.Uniform2f(lgr.canvasSize, float32(cv.fw), float32(cv.fh)) - inv := cv.state.transform.invert().f32() - gli.UniformMatrix3fv(lgr.invmat, 1, false, &inv[0]) gli.Uniform2f(lgr.from, float32(from[0]), float32(from[1])) gli.Uniform2f(lgr.dir, float32(dir[0]), float32(dir[1])) gli.Uniform1f(lgr.len, float32(length)) @@ -521,8 +519,6 @@ func (cv *Canvas) useShader(style *drawStyle) (vertexLoc uint32) { length := dir.len() dir = dir.divf(length) gli.Uniform2f(rgr.canvasSize, float32(cv.fw), float32(cv.fh)) - inv := cv.state.transform.invert().f32() - gli.UniformMatrix3fv(rgr.invmat, 1, false, &inv[0]) gli.Uniform2f(rgr.from, float32(from[0]), float32(from[1])) gli.Uniform2f(rgr.to, float32(to[0]), float32(to[1])) gli.Uniform2f(rgr.dir, float32(dir[0]), float32(dir[1])) @@ -538,8 +534,6 @@ func (cv *Canvas) useShader(style *drawStyle) (vertexLoc uint32) { gli.ActiveTexture(gl_TEXTURE0) gli.BindTexture(gl_TEXTURE_2D, img.tex) gli.Uniform2f(ipr.canvasSize, float32(cv.fw), float32(cv.fh)) - inv := cv.state.transform.invert().f32() - gli.UniformMatrix3fv(ipr.invmat, 1, false, &inv[0]) gli.Uniform2f(ipr.imageSize, float32(img.w), float32(img.h)) gli.Uniform1i(ipr.image, 0) gli.Uniform1f(ipr.globalAlpha, float32(cv.state.globalAlpha)) @@ -566,8 +560,6 @@ func (cv *Canvas) useAlphaShader(style *drawStyle, alphaTexSlot int32) (vertexLo length := dir.len() dir = dir.divf(length) gli.Uniform2f(lgar.canvasSize, float32(cv.fw), float32(cv.fh)) - inv := cv.state.transform.invert().f32() - gli.UniformMatrix3fv(lgar.invmat, 1, false, &inv[0]) gli.Uniform2f(lgar.from, float32(from[0]), float32(from[1])) gli.Uniform2f(lgar.dir, float32(dir[0]), float32(dir[1])) gli.Uniform1f(lgar.len, float32(length)) @@ -587,8 +579,6 @@ func (cv *Canvas) useAlphaShader(style *drawStyle, alphaTexSlot int32) (vertexLo length := dir.len() dir = dir.divf(length) gli.Uniform2f(rgar.canvasSize, float32(cv.fw), float32(cv.fh)) - inv := cv.state.transform.invert().f32() - gli.UniformMatrix3fv(rgar.invmat, 1, false, &inv[0]) gli.Uniform2f(rgar.from, float32(from[0]), float32(from[1])) gli.Uniform2f(rgar.to, float32(to[0]), float32(to[1])) gli.Uniform2f(rgar.dir, float32(dir[0]), float32(dir[1])) @@ -605,8 +595,6 @@ func (cv *Canvas) useAlphaShader(style *drawStyle, alphaTexSlot int32) (vertexLo gli.ActiveTexture(gl_TEXTURE0) gli.BindTexture(gl_TEXTURE_2D, img.tex) gli.Uniform2f(ipar.canvasSize, float32(cv.fw), float32(cv.fh)) - inv := cv.state.transform.invert().f32() - gli.UniformMatrix3fv(ipar.invmat, 1, false, &inv[0]) gli.Uniform2f(ipar.imageSize, float32(img.w), float32(img.h)) gli.Uniform1i(ipar.image, 0) gli.Uniform1i(ipar.alphaTex, alphaTexSlot) diff --git a/canvas_test.go b/canvas_test.go index cf8bc19..e34bcae 100644 --- a/canvas_test.go +++ b/canvas_test.go @@ -3,6 +3,7 @@ package canvas_test import ( "fmt" "image/png" + "math" "os" "runtime" "strings" @@ -519,3 +520,52 @@ func TestTransform2(t *testing.T) { cv.Stroke() }) } + +func TestImage(t *testing.T) { + run(t, func(cv *canvas.Canvas) { + cv.DrawImage("testdata/cat.jpg", 5, 5, 40, 40) + cv.DrawImage("testdata/cat.jpg", 100, 100, 100, 100, 55, 55, 40, 40) + cv.Save() + cv.Translate(75, 25) + cv.Rotate(math.Pi / 2) + cv.Translate(-20, -20) + cv.DrawImage("testdata/cat.jpg", 0, 0, 40, 40) + cv.Restore() + cv.SetTransform(1, 0, 0.2, 1, 0, 0) + cv.DrawImage("testdata/cat.jpg", -8, 55, 40, 40) + }) +} + +func TestGradient(t *testing.T) { + run(t, func(cv *canvas.Canvas) { + cv.Translate(50, 50) + cv.Scale(0.8, 0.7) + cv.Rotate(math.Pi * 0.1) + cv.Translate(-50, -50) + + lg := canvas.NewLinearGradient(10, 10, 40, 20) + lg.AddColorStop(0, 0.5, 0, 0) + lg.AddColorStop(0.5, "#008000") + lg.AddColorStop(1, 0, 0, 128) + cv.SetFillStyle(lg) + cv.FillRect(0, 0, 50, 100) + + rg := canvas.NewRadialGradient(75, 15, 10, 75, 75, 20) + rg.AddColorStop(0, 1.0, 0, 0, 0.5) + rg.AddColorStop(0.5, "#00FF0080") + rg.AddColorStop(1, 0, 0, 255, 128) + cv.SetFillStyle(rg) + cv.FillRect(50, 0, 50, 100) + }) +} + +func TestImagePattern(t *testing.T) { + run(t, func(cv *canvas.Canvas) { + cv.Translate(50, 50) + cv.Scale(0.95, 1.05) + cv.Rotate(-math.Pi * 0.1) + + cv.SetFillStyle("testdata/cat.jpg") + cv.FillRect(-40, -40, 80, 80) + }) +} diff --git a/shaders.go b/shaders.go index 14f2c76..6274e3b 100644 --- a/shaders.go +++ b/shaders.go @@ -61,14 +61,12 @@ var linearGradientFS = ` precision mediump float; #endif varying vec2 v_cp; -uniform mat3 invmat; uniform sampler2D gradient; uniform vec2 from, dir; uniform float len; uniform float globalAlpha; void main() { - vec3 untf = vec3(v_cp, 1.0) * invmat; - vec2 v = untf.xy - from; + vec2 v = v_cp - from; float r = dot(v, dir) / len; r = clamp(r, 0.0, 1.0); vec4 col = texture2D(gradient, vec2(r, 0.0)); @@ -90,7 +88,6 @@ var radialGradientFS = ` precision mediump float; #endif varying vec2 v_cp; -uniform mat3 invmat; uniform sampler2D gradient; uniform vec2 from, to, dir; uniform float radFrom, radTo; @@ -100,13 +97,12 @@ bool isNaN(float v) { return v < 0.0 || 0.0 < v || v == 0.0 ? false : true; } void main() { - vec3 untf = vec3(v_cp, 1.0) * invmat; float o_a = 0.5 * sqrt( - pow(-2.0*from.x*from.x+2.0*from.x*to.x+2.0*from.x*untf.x-2.0*to.x*untf.x-2.0*from.y*from.y+2.0*from.y*to.y+2.0*from.y*untf.y-2.0*to.y*untf.y+2.0*radFrom*radFrom-2.0*radFrom*radTo, 2.0) - -4.0*(from.x*from.x-2.0*from.x*untf.x+untf.x*untf.x+from.y*from.y-2.0*from.y*untf.y+untf.y*untf.y-radFrom*radFrom) + pow(-2.0*from.x*from.x+2.0*from.x*to.x+2.0*from.x*v_cp.x-2.0*to.x*v_cp.x-2.0*from.y*from.y+2.0*from.y*to.y+2.0*from.y*v_cp.y-2.0*to.y*v_cp.y+2.0*radFrom*radFrom-2.0*radFrom*radTo, 2.0) + -4.0*(from.x*from.x-2.0*from.x*v_cp.x+v_cp.x*v_cp.x+from.y*from.y-2.0*from.y*v_cp.y+v_cp.y*v_cp.y-radFrom*radFrom) *(from.x*from.x-2.0*from.x*to.x+to.x*to.x+from.y*from.y-2.0*from.y*to.y+to.y*to.y-radFrom*radFrom+2.0*radFrom*radTo-radTo*radTo) ); - float o_b = (from.x*from.x-from.x*to.x-from.x*untf.x+to.x*untf.x+from.y*from.y-from.y*to.y-from.y*untf.y+to.y*untf.y-radFrom*radFrom+radFrom*radTo); + float o_b = (from.x*from.x-from.x*to.x-from.x*v_cp.x+to.x*v_cp.x+from.y*from.y-from.y*to.y-from.y*v_cp.y+to.y*v_cp.y-radFrom*radFrom+radFrom*radTo); float o_c = (from.x*from.x-2.0*from.x*to.x+to.x*to.x+from.y*from.y-2.0*from.y*to.y+to.y*to.y-radFrom*radFrom+2.0*radFrom*radTo-radTo*radTo); float o1 = (-o_a + o_b) / o_c; float o2 = (o_a + o_b) / o_c; @@ -136,12 +132,10 @@ precision mediump float; #endif varying vec2 v_cp; uniform vec2 imageSize; -uniform mat3 invmat; uniform sampler2D image; uniform float globalAlpha; void main() { - vec3 untf = vec3(v_cp, 1.0) * invmat; - vec4 col = texture2D(image, mod(untf.xy / imageSize, 1.0)); + vec4 col = texture2D(image, mod(v_cp / imageSize, 1.0)); col.a *= globalAlpha; gl_FragColor = col; }` @@ -187,15 +181,13 @@ precision mediump float; varying vec2 v_cp; varying vec2 v_atc; varying vec2 v_texCoord; -uniform mat3 invmat; uniform sampler2D gradient; uniform vec2 from, dir; uniform float len; uniform sampler2D alphaTex; uniform float globalAlpha; void main() { - vec3 untf = vec3(v_cp, 1.0) * invmat; - vec2 v = untf.xy - from; + vec2 v = v_cp.xy - from; float r = dot(v, dir) / len; r = clamp(r, 0.0, 1.0); vec4 col = texture2D(gradient, vec2(r, 0.0)); @@ -220,7 +212,6 @@ precision mediump float; #endif varying vec2 v_cp; varying vec2 v_atc; -uniform mat3 invmat; uniform sampler2D gradient; uniform vec2 from, to, dir; uniform float radFrom, radTo; @@ -231,13 +222,12 @@ bool isNaN(float v) { return v < 0.0 || 0.0 < v || v == 0.0 ? false : true; } void main() { - vec3 untf = vec3(v_cp, 1.0) * invmat; float o_a = 0.5 * sqrt( - pow(-2.0*from.x*from.x+2.0*from.x*to.x+2.0*from.x*untf.x-2.0*to.x*untf.x-2.0*from.y*from.y+2.0*from.y*to.y+2.0*from.y*untf.y-2.0*to.y*untf.y+2.0*radFrom*radFrom-2.0*radFrom*radTo, 2.0) - -4.0*(from.x*from.x-2.0*from.x*untf.x+untf.x*untf.x+from.y*from.y-2.0*from.y*untf.y+untf.y*untf.y-radFrom*radFrom) + pow(-2.0*from.x*from.x+2.0*from.x*to.x+2.0*from.x*v_cp.x-2.0*to.x*v_cp.x-2.0*from.y*from.y+2.0*from.y*to.y+2.0*from.y*v_cp.y-2.0*to.y*v_cp.y+2.0*radFrom*radFrom-2.0*radFrom*radTo, 2.0) + -4.0*(from.x*from.x-2.0*from.x*v_cp.x+v_cp.x*v_cp.x+from.y*from.y-2.0*from.y*v_cp.y+v_cp.y*v_cp.y-radFrom*radFrom) *(from.x*from.x-2.0*from.x*to.x+to.x*to.x+from.y*from.y-2.0*from.y*to.y+to.y*to.y-radFrom*radFrom+2.0*radFrom*radTo-radTo*radTo) ); - float o_b = (from.x*from.x-from.x*to.x-from.x*untf.x+to.x*untf.x+from.y*from.y-from.y*to.y-from.y*untf.y+to.y*untf.y-radFrom*radFrom+radFrom*radTo); + float o_b = (from.x*from.x-from.x*to.x-from.x*v_cp.x+to.x*v_cp.x+from.y*from.y-from.y*to.y-from.y*v_cp.y+to.y*v_cp.y-radFrom*radFrom+radFrom*radTo); float o_c = (from.x*from.x-2.0*from.x*to.x+to.x*to.x+from.y*from.y-2.0*from.y*to.y+to.y*to.y-radFrom*radFrom+2.0*radFrom*radTo-radTo*radTo); float o1 = (-o_a + o_b) / o_c; float o2 = (o_a + o_b) / o_c; @@ -270,13 +260,11 @@ precision mediump float; varying vec2 v_cp; varying vec2 v_atc; uniform vec2 imageSize; -uniform mat3 invmat; uniform sampler2D image; uniform sampler2D alphaTex; uniform float globalAlpha; void main() { - vec3 untf = vec3(v_cp, 1.0) * invmat; - vec4 col = texture2D(image, mod(untf.xy / imageSize, 1.0)); + vec4 col = texture2D(image, mod(v_cp / imageSize, 1.0)); col.a *= texture2D(alphaTex, v_atc).a * globalAlpha; gl_FragColor = col; }` diff --git a/testdata/Gradient.png b/testdata/Gradient.png new file mode 100755 index 0000000..7b46ec7 Binary files /dev/null and b/testdata/Gradient.png differ diff --git a/testdata/Image.png b/testdata/Image.png new file mode 100755 index 0000000..d6a35e5 Binary files /dev/null and b/testdata/Image.png differ diff --git a/testdata/ImagePattern.png b/testdata/ImagePattern.png new file mode 100755 index 0000000..0b45986 Binary files /dev/null and b/testdata/ImagePattern.png differ diff --git a/testdata/cat.jpg b/testdata/cat.jpg new file mode 100755 index 0000000..27bcece Binary files /dev/null and b/testdata/cat.jpg differ