added some tests; improved gradient and image pattern transformations
This commit is contained in:
parent
65ebe6af69
commit
6091afb755
7 changed files with 60 additions and 34 deletions
12
canvas.go
12
canvas.go
|
@ -501,8 +501,6 @@ func (cv *Canvas) useShader(style *drawStyle) (vertexLoc uint32) {
|
||||||
length := dir.len()
|
length := dir.len()
|
||||||
dir = dir.divf(length)
|
dir = dir.divf(length)
|
||||||
gli.Uniform2f(lgr.canvasSize, float32(cv.fw), float32(cv.fh))
|
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.from, float32(from[0]), float32(from[1]))
|
||||||
gli.Uniform2f(lgr.dir, float32(dir[0]), float32(dir[1]))
|
gli.Uniform2f(lgr.dir, float32(dir[0]), float32(dir[1]))
|
||||||
gli.Uniform1f(lgr.len, float32(length))
|
gli.Uniform1f(lgr.len, float32(length))
|
||||||
|
@ -521,8 +519,6 @@ func (cv *Canvas) useShader(style *drawStyle) (vertexLoc uint32) {
|
||||||
length := dir.len()
|
length := dir.len()
|
||||||
dir = dir.divf(length)
|
dir = dir.divf(length)
|
||||||
gli.Uniform2f(rgr.canvasSize, float32(cv.fw), float32(cv.fh))
|
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.from, float32(from[0]), float32(from[1]))
|
||||||
gli.Uniform2f(rgr.to, float32(to[0]), float32(to[1]))
|
gli.Uniform2f(rgr.to, float32(to[0]), float32(to[1]))
|
||||||
gli.Uniform2f(rgr.dir, float32(dir[0]), float32(dir[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.ActiveTexture(gl_TEXTURE0)
|
||||||
gli.BindTexture(gl_TEXTURE_2D, img.tex)
|
gli.BindTexture(gl_TEXTURE_2D, img.tex)
|
||||||
gli.Uniform2f(ipr.canvasSize, float32(cv.fw), float32(cv.fh))
|
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.Uniform2f(ipr.imageSize, float32(img.w), float32(img.h))
|
||||||
gli.Uniform1i(ipr.image, 0)
|
gli.Uniform1i(ipr.image, 0)
|
||||||
gli.Uniform1f(ipr.globalAlpha, float32(cv.state.globalAlpha))
|
gli.Uniform1f(ipr.globalAlpha, float32(cv.state.globalAlpha))
|
||||||
|
@ -566,8 +560,6 @@ func (cv *Canvas) useAlphaShader(style *drawStyle, alphaTexSlot int32) (vertexLo
|
||||||
length := dir.len()
|
length := dir.len()
|
||||||
dir = dir.divf(length)
|
dir = dir.divf(length)
|
||||||
gli.Uniform2f(lgar.canvasSize, float32(cv.fw), float32(cv.fh))
|
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.from, float32(from[0]), float32(from[1]))
|
||||||
gli.Uniform2f(lgar.dir, float32(dir[0]), float32(dir[1]))
|
gli.Uniform2f(lgar.dir, float32(dir[0]), float32(dir[1]))
|
||||||
gli.Uniform1f(lgar.len, float32(length))
|
gli.Uniform1f(lgar.len, float32(length))
|
||||||
|
@ -587,8 +579,6 @@ func (cv *Canvas) useAlphaShader(style *drawStyle, alphaTexSlot int32) (vertexLo
|
||||||
length := dir.len()
|
length := dir.len()
|
||||||
dir = dir.divf(length)
|
dir = dir.divf(length)
|
||||||
gli.Uniform2f(rgar.canvasSize, float32(cv.fw), float32(cv.fh))
|
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.from, float32(from[0]), float32(from[1]))
|
||||||
gli.Uniform2f(rgar.to, float32(to[0]), float32(to[1]))
|
gli.Uniform2f(rgar.to, float32(to[0]), float32(to[1]))
|
||||||
gli.Uniform2f(rgar.dir, float32(dir[0]), float32(dir[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.ActiveTexture(gl_TEXTURE0)
|
||||||
gli.BindTexture(gl_TEXTURE_2D, img.tex)
|
gli.BindTexture(gl_TEXTURE_2D, img.tex)
|
||||||
gli.Uniform2f(ipar.canvasSize, float32(cv.fw), float32(cv.fh))
|
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.Uniform2f(ipar.imageSize, float32(img.w), float32(img.h))
|
||||||
gli.Uniform1i(ipar.image, 0)
|
gli.Uniform1i(ipar.image, 0)
|
||||||
gli.Uniform1i(ipar.alphaTex, alphaTexSlot)
|
gli.Uniform1i(ipar.alphaTex, alphaTexSlot)
|
||||||
|
|
|
@ -3,6 +3,7 @@ package canvas_test
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"image/png"
|
"image/png"
|
||||||
|
"math"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -519,3 +520,52 @@ func TestTransform2(t *testing.T) {
|
||||||
cv.Stroke()
|
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)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
32
shaders.go
32
shaders.go
|
@ -61,14 +61,12 @@ var linearGradientFS = `
|
||||||
precision mediump float;
|
precision mediump float;
|
||||||
#endif
|
#endif
|
||||||
varying vec2 v_cp;
|
varying vec2 v_cp;
|
||||||
uniform mat3 invmat;
|
|
||||||
uniform sampler2D gradient;
|
uniform sampler2D gradient;
|
||||||
uniform vec2 from, dir;
|
uniform vec2 from, dir;
|
||||||
uniform float len;
|
uniform float len;
|
||||||
uniform float globalAlpha;
|
uniform float globalAlpha;
|
||||||
void main() {
|
void main() {
|
||||||
vec3 untf = vec3(v_cp, 1.0) * invmat;
|
vec2 v = v_cp - from;
|
||||||
vec2 v = untf.xy - from;
|
|
||||||
float r = dot(v, dir) / len;
|
float r = dot(v, dir) / len;
|
||||||
r = clamp(r, 0.0, 1.0);
|
r = clamp(r, 0.0, 1.0);
|
||||||
vec4 col = texture2D(gradient, vec2(r, 0.0));
|
vec4 col = texture2D(gradient, vec2(r, 0.0));
|
||||||
|
@ -90,7 +88,6 @@ var radialGradientFS = `
|
||||||
precision mediump float;
|
precision mediump float;
|
||||||
#endif
|
#endif
|
||||||
varying vec2 v_cp;
|
varying vec2 v_cp;
|
||||||
uniform mat3 invmat;
|
|
||||||
uniform sampler2D gradient;
|
uniform sampler2D gradient;
|
||||||
uniform vec2 from, to, dir;
|
uniform vec2 from, to, dir;
|
||||||
uniform float radFrom, radTo;
|
uniform float radFrom, radTo;
|
||||||
|
@ -100,13 +97,12 @@ bool isNaN(float v) {
|
||||||
return v < 0.0 || 0.0 < v || v == 0.0 ? false : true;
|
return v < 0.0 || 0.0 < v || v == 0.0 ? false : true;
|
||||||
}
|
}
|
||||||
void main() {
|
void main() {
|
||||||
vec3 untf = vec3(v_cp, 1.0) * invmat;
|
|
||||||
float o_a = 0.5 * sqrt(
|
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)
|
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*untf.x+untf.x*untf.x+from.y*from.y-2.0*from.y*untf.y+untf.y*untf.y-radFrom*radFrom)
|
-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)
|
*(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 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 o1 = (-o_a + o_b) / o_c;
|
||||||
float o2 = (o_a + o_b) / o_c;
|
float o2 = (o_a + o_b) / o_c;
|
||||||
|
@ -136,12 +132,10 @@ precision mediump float;
|
||||||
#endif
|
#endif
|
||||||
varying vec2 v_cp;
|
varying vec2 v_cp;
|
||||||
uniform vec2 imageSize;
|
uniform vec2 imageSize;
|
||||||
uniform mat3 invmat;
|
|
||||||
uniform sampler2D image;
|
uniform sampler2D image;
|
||||||
uniform float globalAlpha;
|
uniform float globalAlpha;
|
||||||
void main() {
|
void main() {
|
||||||
vec3 untf = vec3(v_cp, 1.0) * invmat;
|
vec4 col = texture2D(image, mod(v_cp / imageSize, 1.0));
|
||||||
vec4 col = texture2D(image, mod(untf.xy / imageSize, 1.0));
|
|
||||||
col.a *= globalAlpha;
|
col.a *= globalAlpha;
|
||||||
gl_FragColor = col;
|
gl_FragColor = col;
|
||||||
}`
|
}`
|
||||||
|
@ -187,15 +181,13 @@ precision mediump float;
|
||||||
varying vec2 v_cp;
|
varying vec2 v_cp;
|
||||||
varying vec2 v_atc;
|
varying vec2 v_atc;
|
||||||
varying vec2 v_texCoord;
|
varying vec2 v_texCoord;
|
||||||
uniform mat3 invmat;
|
|
||||||
uniform sampler2D gradient;
|
uniform sampler2D gradient;
|
||||||
uniform vec2 from, dir;
|
uniform vec2 from, dir;
|
||||||
uniform float len;
|
uniform float len;
|
||||||
uniform sampler2D alphaTex;
|
uniform sampler2D alphaTex;
|
||||||
uniform float globalAlpha;
|
uniform float globalAlpha;
|
||||||
void main() {
|
void main() {
|
||||||
vec3 untf = vec3(v_cp, 1.0) * invmat;
|
vec2 v = v_cp.xy - from;
|
||||||
vec2 v = untf.xy - from;
|
|
||||||
float r = dot(v, dir) / len;
|
float r = dot(v, dir) / len;
|
||||||
r = clamp(r, 0.0, 1.0);
|
r = clamp(r, 0.0, 1.0);
|
||||||
vec4 col = texture2D(gradient, vec2(r, 0.0));
|
vec4 col = texture2D(gradient, vec2(r, 0.0));
|
||||||
|
@ -220,7 +212,6 @@ precision mediump float;
|
||||||
#endif
|
#endif
|
||||||
varying vec2 v_cp;
|
varying vec2 v_cp;
|
||||||
varying vec2 v_atc;
|
varying vec2 v_atc;
|
||||||
uniform mat3 invmat;
|
|
||||||
uniform sampler2D gradient;
|
uniform sampler2D gradient;
|
||||||
uniform vec2 from, to, dir;
|
uniform vec2 from, to, dir;
|
||||||
uniform float radFrom, radTo;
|
uniform float radFrom, radTo;
|
||||||
|
@ -231,13 +222,12 @@ bool isNaN(float v) {
|
||||||
return v < 0.0 || 0.0 < v || v == 0.0 ? false : true;
|
return v < 0.0 || 0.0 < v || v == 0.0 ? false : true;
|
||||||
}
|
}
|
||||||
void main() {
|
void main() {
|
||||||
vec3 untf = vec3(v_cp, 1.0) * invmat;
|
|
||||||
float o_a = 0.5 * sqrt(
|
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)
|
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*untf.x+untf.x*untf.x+from.y*from.y-2.0*from.y*untf.y+untf.y*untf.y-radFrom*radFrom)
|
-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)
|
*(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 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 o1 = (-o_a + o_b) / o_c;
|
||||||
float o2 = (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_cp;
|
||||||
varying vec2 v_atc;
|
varying vec2 v_atc;
|
||||||
uniform vec2 imageSize;
|
uniform vec2 imageSize;
|
||||||
uniform mat3 invmat;
|
|
||||||
uniform sampler2D image;
|
uniform sampler2D image;
|
||||||
uniform sampler2D alphaTex;
|
uniform sampler2D alphaTex;
|
||||||
uniform float globalAlpha;
|
uniform float globalAlpha;
|
||||||
void main() {
|
void main() {
|
||||||
vec3 untf = vec3(v_cp, 1.0) * invmat;
|
vec4 col = texture2D(image, mod(v_cp / imageSize, 1.0));
|
||||||
vec4 col = texture2D(image, mod(untf.xy / imageSize, 1.0));
|
|
||||||
col.a *= texture2D(alphaTex, v_atc).a * globalAlpha;
|
col.a *= texture2D(alphaTex, v_atc).a * globalAlpha;
|
||||||
gl_FragColor = col;
|
gl_FragColor = col;
|
||||||
}`
|
}`
|
||||||
|
|
BIN
testdata/Gradient.png
vendored
Executable file
BIN
testdata/Gradient.png
vendored
Executable file
Binary file not shown.
After Width: | Height: | Size: 2.2 KiB |
BIN
testdata/Image.png
vendored
Executable file
BIN
testdata/Image.png
vendored
Executable file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
BIN
testdata/ImagePattern.png
vendored
Executable file
BIN
testdata/ImagePattern.png
vendored
Executable file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
BIN
testdata/cat.jpg
vendored
Executable file
BIN
testdata/cat.jpg
vendored
Executable file
Binary file not shown.
After Width: | Height: | Size: 132 KiB |
Loading…
Reference in a new issue