implemented globalAlpha

This commit is contained in:
Thomas Friedel 2018-04-09 17:39:26 +02:00
parent 3fcf95cc86
commit e75355ac37
6 changed files with 688 additions and 607 deletions

View file

@ -25,14 +25,15 @@ type Canvas struct {
} }
type drawState struct { type drawState struct {
transform mat transform mat
fill drawStyle fill drawStyle
stroke drawStyle stroke drawStyle
font *Font font *Font
fontSize float64 fontSize float64
lineWidth float64 lineWidth float64
lineJoin lineJoin lineJoin lineJoin
lineEnd lineEnd lineEnd lineEnd
globalAlpha float64
lineDash []float64 lineDash []float64
lineDashPoint int lineDashPoint int
@ -86,6 +87,9 @@ func New(x, y, w, h int) *Canvas {
stateStack: make([]drawState, 0, 20), stateStack: make([]drawState, 0, 20),
} }
cv.state.lineWidth = 1 cv.state.lineWidth = 1
cv.state.globalAlpha = 1
cv.state.fill.color = glColor{a: 1}
cv.state.stroke.color = glColor{a: 1}
cv.state.transform = matIdentity() cv.state.transform = matIdentity()
return cv return cv
} }
@ -329,6 +333,7 @@ func (cv *Canvas) useShader(style *drawStyle) (vertexLoc uint32) {
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))
gli.Uniform1i(lgr.gradient, 0) gli.Uniform1i(lgr.gradient, 0)
gli.Uniform1f(lgr.globalAlpha, float32(cv.state.globalAlpha))
return lgr.vertex return lgr.vertex
} }
if rg := style.radialGradient; rg != nil { if rg := style.radialGradient; rg != nil {
@ -351,6 +356,7 @@ func (cv *Canvas) useShader(style *drawStyle) (vertexLoc uint32) {
gli.Uniform1f(rgr.radTo, float32(rg.radTo)) gli.Uniform1f(rgr.radTo, float32(rg.radTo))
gli.Uniform1f(rgr.len, float32(length)) gli.Uniform1f(rgr.len, float32(length))
gli.Uniform1i(rgr.gradient, 0) gli.Uniform1i(rgr.gradient, 0)
gli.Uniform1f(rgr.globalAlpha, float32(cv.state.globalAlpha))
return rgr.vertex return rgr.vertex
} }
if img := style.image; img != nil { if img := style.image; img != nil {
@ -362,6 +368,7 @@ func (cv *Canvas) useShader(style *drawStyle) (vertexLoc uint32) {
gli.UniformMatrix3fv(ipr.invmat, 1, false, &inv[0]) 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))
return ipr.vertex return ipr.vertex
} }
@ -369,6 +376,7 @@ func (cv *Canvas) useShader(style *drawStyle) (vertexLoc uint32) {
gli.Uniform2f(sr.canvasSize, float32(cv.fw), float32(cv.fh)) gli.Uniform2f(sr.canvasSize, float32(cv.fw), float32(cv.fh))
c := style.color c := style.color
gli.Uniform4f(sr.color, float32(c.r), float32(c.g), float32(c.b), float32(c.a)) gli.Uniform4f(sr.color, float32(c.r), float32(c.g), float32(c.b), float32(c.a))
gli.Uniform1f(sr.globalAlpha, float32(cv.state.globalAlpha))
return sr.vertex return sr.vertex
} }
@ -391,6 +399,7 @@ func (cv *Canvas) useAlphaShader(style *drawStyle, alphaTexSlot int32) (vertexLo
gli.Uniform1f(lgar.len, float32(length)) gli.Uniform1f(lgar.len, float32(length))
gli.Uniform1i(lgar.gradient, 0) gli.Uniform1i(lgar.gradient, 0)
gli.Uniform1i(lgar.alphaTex, alphaTexSlot) gli.Uniform1i(lgar.alphaTex, alphaTexSlot)
gli.Uniform1f(lgar.globalAlpha, float32(cv.state.globalAlpha))
return lgar.vertex, lgar.alphaTexCoord return lgar.vertex, lgar.alphaTexCoord
} }
if rg := style.radialGradient; rg != nil { if rg := style.radialGradient; rg != nil {
@ -414,6 +423,7 @@ func (cv *Canvas) useAlphaShader(style *drawStyle, alphaTexSlot int32) (vertexLo
gli.Uniform1f(rgar.len, float32(length)) gli.Uniform1f(rgar.len, float32(length))
gli.Uniform1i(rgar.gradient, 0) gli.Uniform1i(rgar.gradient, 0)
gli.Uniform1i(rgar.alphaTex, alphaTexSlot) gli.Uniform1i(rgar.alphaTex, alphaTexSlot)
gli.Uniform1f(rgar.globalAlpha, float32(cv.state.globalAlpha))
return rgar.vertex, rgar.alphaTexCoord return rgar.vertex, rgar.alphaTexCoord
} }
if img := style.image; img != nil { if img := style.image; img != nil {
@ -426,6 +436,7 @@ func (cv *Canvas) useAlphaShader(style *drawStyle, alphaTexSlot int32) (vertexLo
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)
gli.Uniform1f(ipar.globalAlpha, float32(cv.state.globalAlpha))
return ipar.vertex, ipar.alphaTexCoord return ipar.vertex, ipar.alphaTexCoord
} }
@ -434,6 +445,7 @@ func (cv *Canvas) useAlphaShader(style *drawStyle, alphaTexSlot int32) (vertexLo
c := style.color c := style.color
gli.Uniform4f(sar.color, float32(c.r), float32(c.g), float32(c.b), float32(c.a)) gli.Uniform4f(sar.color, float32(c.r), float32(c.g), float32(c.b), float32(c.a))
gli.Uniform1i(sar.alphaTex, alphaTexSlot) gli.Uniform1i(sar.alphaTex, alphaTexSlot)
gli.Uniform1f(sar.globalAlpha, float32(cv.state.globalAlpha))
return sar.vertex, sar.alphaTexCoord return sar.vertex, sar.alphaTexCoord
} }
@ -498,6 +510,11 @@ func (cv *Canvas) SetLineDash(dash []float64) {
cv.state.lineDashOffset = 0 cv.state.lineDashOffset = 0
} }
// SetGlobalAlpha sets the global alpha value
func (cv *Canvas) SetGlobalAlpha(alpha float64) {
cv.state.globalAlpha = alpha
}
// Save saves the current draw state to a stack // Save saves the current draw state to a stack
func (cv *Canvas) Save() { func (cv *Canvas) Save() {
cv.stateStack = append(cv.stateStack, cv.state) cv.stateStack = append(cv.stateStack, cv.state)

View file

@ -85,6 +85,7 @@ func (cv *Canvas) PutImageData(img *image.RGBA, x, y int) {
gli.UseProgram(ir.id) gli.UseProgram(ir.id)
gli.Uniform1i(ir.image, 0) gli.Uniform1i(ir.image, 0)
gli.Uniform2f(ir.canvasSize, float32(cv.fw), float32(cv.fh)) gli.Uniform2f(ir.canvasSize, float32(cv.fw), float32(cv.fh))
gli.Uniform1f(ir.globalAlpha, 1)
gli.VertexAttribPointer(ir.vertex, 2, gl_FLOAT, false, 0, nil) gli.VertexAttribPointer(ir.vertex, 2, gl_FLOAT, false, 0, nil)
gli.VertexAttribPointer(ir.texCoord, 2, gl_FLOAT, false, 0, gli.PtrOffset(8*4)) gli.VertexAttribPointer(ir.texCoord, 2, gl_FLOAT, false, 0, gli.PtrOffset(8*4))
gli.EnableVertexAttribArray(ir.vertex) gli.EnableVertexAttribArray(ir.vertex)

View file

@ -260,6 +260,7 @@ func (cv *Canvas) DrawImage(image interface{}, coords ...float64) {
gli.UseProgram(ir.id) gli.UseProgram(ir.id)
gli.Uniform1i(ir.image, 0) gli.Uniform1i(ir.image, 0)
gli.Uniform2f(ir.canvasSize, float32(cv.fw), float32(cv.fh)) gli.Uniform2f(ir.canvasSize, float32(cv.fw), float32(cv.fh))
gli.Uniform1f(ir.globalAlpha, float32(cv.state.globalAlpha))
gli.VertexAttribPointer(ir.vertex, 2, gl_FLOAT, false, 0, nil) gli.VertexAttribPointer(ir.vertex, 2, gl_FLOAT, false, 0, nil)
gli.VertexAttribPointer(ir.texCoord, 2, gl_FLOAT, false, 0, gli.PtrOffset(8*4)) gli.VertexAttribPointer(ir.texCoord, 2, gl_FLOAT, false, 0, gli.PtrOffset(8*4))
gli.EnableVertexAttribArray(ir.vertex) gli.EnableVertexAttribArray(ir.vertex)

File diff suppressed because it is too large Load diff

View file

@ -465,31 +465,65 @@ func (cv *Canvas) Fill() {
return return
} }
cv.activate() cv.activate()
var triBuf [1000]float32
tris := triBuf[:0]
tris = append(tris, 0, 0, float32(cv.fw), 0, float32(cv.fw), float32(cv.fh), 0, 0, float32(cv.fw), float32(cv.fh), 0, float32(cv.fh))
start := 0 start := 0
for i, p := range cv.polyPath { for i, p := range cv.polyPath {
if p.flags&pathMove == 0 { if p.flags&pathMove == 0 {
continue continue
} }
if i >= start+3 { if i >= start+3 {
cv.fillPoly(cv.polyPath[start:i]) tris = cv.appendSubPathTriangles(tris, cv.polyPath[start:i])
} }
start = i start = i
} }
if len(cv.polyPath) >= start+3 { if len(cv.polyPath) >= start+3 {
cv.fillPoly(cv.polyPath[start:]) tris = cv.appendSubPathTriangles(tris, cv.polyPath[start:])
} }
} if len(tris) == 0 {
func (cv *Canvas) fillPoly(path []pathPoint) {
if len(path) < 3 {
return return
} }
cv.activate()
gli.BindBuffer(gl_ARRAY_BUFFER, buf) gli.BindBuffer(gl_ARRAY_BUFFER, buf)
var triBuf [1000]float32 gli.BufferData(gl_ARRAY_BUFFER, len(tris)*4, unsafe.Pointer(&tris[0]), gl_STREAM_DRAW)
var tris []float32
gli.ColorMask(false, false, false, false)
gli.StencilFunc(gl_ALWAYS, 1, 0xFF)
gli.StencilOp(gl_REPLACE, gl_REPLACE, gl_REPLACE)
gli.StencilMask(0x01)
gli.UseProgram(sr.id)
gli.Uniform4f(sr.color, 0, 0, 0, 0)
gli.Uniform2f(sr.canvasSize, float32(cv.fw), float32(cv.fh))
gli.EnableVertexAttribArray(sr.vertex)
gli.VertexAttribPointer(sr.vertex, 2, gl_FLOAT, false, 0, nil)
gli.DrawArrays(gl_TRIANGLES, 6, int32(len(tris)/2-6))
gli.DisableVertexAttribArray(sr.vertex)
gli.ColorMask(true, true, true, true)
gli.StencilFunc(gl_EQUAL, 1, 0xFF)
gli.StencilMask(0xFF)
vertex := cv.useShader(&cv.state.fill)
gli.EnableVertexAttribArray(vertex)
gli.VertexAttribPointer(vertex, 2, gl_FLOAT, false, 0, nil)
gli.DrawArrays(gl_TRIANGLES, 0, 6)
gli.DisableVertexAttribArray(vertex)
gli.StencilOp(gl_KEEP, gl_KEEP, gl_KEEP)
gli.StencilFunc(gl_ALWAYS, 0, 0xFF)
gli.StencilMask(0x01)
gli.Clear(gl_STENCIL_BUFFER_BIT)
gli.StencilMask(0xFF)
}
func (cv *Canvas) appendSubPathTriangles(tris []float32, path []pathPoint) []float32 {
if path[len(path)-1].flags&pathIsConvex != 0 { if path[len(path)-1].flags&pathIsConvex != 0 {
p0, p1 := path[0].tf, path[1].tf p0, p1 := path[0].tf, path[1].tf
last := len(path) last := len(path)
@ -500,18 +534,9 @@ func (cv *Canvas) fillPoly(path []pathPoint) {
} }
} else { } else {
path = cv.cutIntersections(path) path = cv.cutIntersections(path)
tris = triangulatePath(path, triBuf[:0]) tris = triangulatePath(path, tris)
if len(tris) == 0 {
return
}
} }
gli.BufferData(gl_ARRAY_BUFFER, len(tris)*4, unsafe.Pointer(&tris[0]), gl_STREAM_DRAW) return tris
vertex := cv.useShader(&cv.state.fill)
gli.EnableVertexAttribArray(vertex)
gli.VertexAttribPointer(vertex, 2, gl_FLOAT, false, 0, nil)
gli.DrawArrays(gl_TRIANGLES, 0, int32(len(tris)/2))
gli.DisableVertexAttribArray(vertex)
} }
func (cv *Canvas) Clip() { func (cv *Canvas) Clip() {

View file

@ -15,8 +15,11 @@ precision mediump float;
#endif #endif
varying vec2 v_texCoord; varying vec2 v_texCoord;
uniform sampler2D image; uniform sampler2D image;
uniform float globalAlpha;
void main() { void main() {
gl_FragColor = texture2D(image, v_texCoord); vec4 col = texture2D(image, v_texCoord);
col.a *= globalAlpha;
gl_FragColor = col;
}` }`
var solidVS = ` var solidVS = `
@ -31,8 +34,11 @@ var solidFS = `
precision mediump float; precision mediump float;
#endif #endif
uniform vec4 color; uniform vec4 color;
uniform float globalAlpha;
void main() { void main() {
gl_FragColor = color; vec4 col = color;
col.a *= globalAlpha;
gl_FragColor = col;
}` }`
var linearGradientVS = ` var linearGradientVS = `
@ -53,12 +59,15 @@ uniform mat3 invmat;
uniform sampler1D gradient; uniform sampler1D gradient;
uniform vec2 from, dir; uniform vec2 from, dir;
uniform float len; uniform float len;
uniform float globalAlpha;
void main() { void main() {
vec3 untf = vec3(v_cp, 1.0) * invmat; vec3 untf = vec3(v_cp, 1.0) * invmat;
vec2 v = untf.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);
gl_FragColor = texture1D(gradient, r); vec4 col = texture1D(gradient, r);
col.a *= globalAlpha;
gl_FragColor = col;
}` }`
var radialGradientVS = ` var radialGradientVS = `
@ -80,6 +89,7 @@ uniform sampler1D gradient;
uniform vec2 from, to, dir; uniform vec2 from, to, dir;
uniform float radFrom, radTo; uniform float radFrom, radTo;
uniform float len; uniform float len;
uniform float globalAlpha;
bool isNaN(float v) { 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;
} }
@ -99,8 +109,10 @@ void main() {
return; return;
} }
float o = max(o1, o2); float o = max(o1, o2);
float r = radFrom + o * (radTo - radFrom); //float r = radFrom + o * (radTo - radFrom);
gl_FragColor = texture1D(gradient, o); vec4 col = texture1D(gradient, o);
col.a *= globalAlpha;
gl_FragColor = col;
}` }`
var imagePatternVS = ` var imagePatternVS = `
@ -120,9 +132,12 @@ varying vec2 v_cp;
uniform vec2 imageSize; uniform vec2 imageSize;
uniform mat3 invmat; uniform mat3 invmat;
uniform sampler2D image; uniform sampler2D image;
uniform float globalAlpha;
void main() { void main() {
vec3 untf = vec3(v_cp, 1.0) * invmat; vec3 untf = vec3(v_cp, 1.0) * invmat;
gl_FragColor = texture2D(image, mod(untf.xy / imageSize, 1.0)); vec4 col = texture2D(image, mod(untf.xy / imageSize, 1.0));
col.a *= globalAlpha;
gl_FragColor = col;
}` }`
var solidAlphaVS = ` var solidAlphaVS = `
@ -141,9 +156,10 @@ precision mediump float;
varying vec2 v_atc; varying vec2 v_atc;
uniform vec4 color; uniform vec4 color;
uniform sampler2D alphaTex; uniform sampler2D alphaTex;
uniform float globalAlpha;
void main() { void main() {
vec4 col = color; vec4 col = color;
col.a *= texture2D(alphaTex, v_atc).a; col.a *= texture2D(alphaTex, v_atc).a * globalAlpha;
gl_FragColor = col; gl_FragColor = col;
}` }`
@ -170,13 +186,14 @@ uniform sampler1D gradient;
uniform vec2 from, dir; uniform vec2 from, dir;
uniform float len; uniform float len;
uniform sampler2D alphaTex; uniform sampler2D alphaTex;
uniform float globalAlpha;
void main() { void main() {
vec3 untf = vec3(v_cp, 1.0) * invmat; vec3 untf = vec3(v_cp, 1.0) * invmat;
vec2 v = untf.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 = texture1D(gradient, r); vec4 col = texture1D(gradient, r);
col.a *= texture2D(alphaTex, v_atc).a; col.a *= texture2D(alphaTex, v_atc).a * globalAlpha;
gl_FragColor = col; gl_FragColor = col;
}` }`
@ -203,6 +220,7 @@ uniform vec2 from, to, dir;
uniform float radFrom, radTo; uniform float radFrom, radTo;
uniform float len; uniform float len;
uniform sampler2D alphaTex; uniform sampler2D alphaTex;
uniform float globalAlpha;
bool isNaN(float v) { 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;
} }
@ -224,7 +242,7 @@ void main() {
float o = max(o1, o2); float o = max(o1, o2);
float r = radFrom + o * (radTo - radFrom); float r = radFrom + o * (radTo - radFrom);
vec4 col = texture1D(gradient, o); vec4 col = texture1D(gradient, o);
col.a *= texture2D(alphaTex, v_atc).a; col.a *= texture2D(alphaTex, v_atc).a * globalAlpha;
gl_FragColor = col; gl_FragColor = col;
}` }`
@ -249,9 +267,10 @@ uniform vec2 imageSize;
uniform mat3 invmat; uniform mat3 invmat;
uniform sampler2D image; uniform sampler2D image;
uniform sampler2D alphaTex; uniform sampler2D alphaTex;
uniform float globalAlpha;
void main() { void main() {
vec3 untf = vec3(v_cp, 1.0) * invmat; vec3 untf = vec3(v_cp, 1.0) * invmat;
vec4 col = texture2D(image, mod(untf.xy / imageSize, 1.0)); vec4 col = texture2D(image, mod(untf.xy / imageSize, 1.0));
col.a *= texture2D(alphaTex, v_atc).a; col.a *= texture2D(alphaTex, v_atc).a * globalAlpha;
gl_FragColor = col; gl_FragColor = col;
}` }`