diff --git a/canvas.go b/canvas.go index 25a7cc0..83c2fac 100644 --- a/canvas.go +++ b/canvas.go @@ -25,14 +25,15 @@ type Canvas struct { } type drawState struct { - transform mat - fill drawStyle - stroke drawStyle - font *Font - fontSize float64 - lineWidth float64 - lineJoin lineJoin - lineEnd lineEnd + transform mat + fill drawStyle + stroke drawStyle + font *Font + fontSize float64 + lineWidth float64 + lineJoin lineJoin + lineEnd lineEnd + globalAlpha float64 lineDash []float64 lineDashPoint int @@ -86,6 +87,9 @@ func New(x, y, w, h int) *Canvas { stateStack: make([]drawState, 0, 20), } 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() 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.Uniform1f(lgr.len, float32(length)) gli.Uniform1i(lgr.gradient, 0) + gli.Uniform1f(lgr.globalAlpha, float32(cv.state.globalAlpha)) return lgr.vertex } 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.len, float32(length)) gli.Uniform1i(rgr.gradient, 0) + gli.Uniform1f(rgr.globalAlpha, float32(cv.state.globalAlpha)) return rgr.vertex } 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.Uniform2f(ipr.imageSize, float32(img.w), float32(img.h)) gli.Uniform1i(ipr.image, 0) + gli.Uniform1f(ipr.globalAlpha, float32(cv.state.globalAlpha)) 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)) c := style.color 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 } @@ -391,6 +399,7 @@ func (cv *Canvas) useAlphaShader(style *drawStyle, alphaTexSlot int32) (vertexLo gli.Uniform1f(lgar.len, float32(length)) gli.Uniform1i(lgar.gradient, 0) gli.Uniform1i(lgar.alphaTex, alphaTexSlot) + gli.Uniform1f(lgar.globalAlpha, float32(cv.state.globalAlpha)) return lgar.vertex, lgar.alphaTexCoord } 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.Uniform1i(rgar.gradient, 0) gli.Uniform1i(rgar.alphaTex, alphaTexSlot) + gli.Uniform1f(rgar.globalAlpha, float32(cv.state.globalAlpha)) return rgar.vertex, rgar.alphaTexCoord } 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.Uniform1i(ipar.image, 0) gli.Uniform1i(ipar.alphaTex, alphaTexSlot) + gli.Uniform1f(ipar.globalAlpha, float32(cv.state.globalAlpha)) return ipar.vertex, ipar.alphaTexCoord } @@ -434,6 +445,7 @@ func (cv *Canvas) useAlphaShader(style *drawStyle, alphaTexSlot int32) (vertexLo c := style.color gli.Uniform4f(sar.color, float32(c.r), float32(c.g), float32(c.b), float32(c.a)) gli.Uniform1i(sar.alphaTex, alphaTexSlot) + gli.Uniform1f(sar.globalAlpha, float32(cv.state.globalAlpha)) return sar.vertex, sar.alphaTexCoord } @@ -498,6 +510,11 @@ func (cv *Canvas) SetLineDash(dash []float64) { 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 func (cv *Canvas) Save() { cv.stateStack = append(cv.stateStack, cv.state) diff --git a/imagedata.go b/imagedata.go index a38888c..e739291 100644 --- a/imagedata.go +++ b/imagedata.go @@ -85,6 +85,7 @@ func (cv *Canvas) PutImageData(img *image.RGBA, x, y int) { gli.UseProgram(ir.id) gli.Uniform1i(ir.image, 0) 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.texCoord, 2, gl_FLOAT, false, 0, gli.PtrOffset(8*4)) gli.EnableVertexAttribArray(ir.vertex) diff --git a/images.go b/images.go index 828f4fe..837b510 100644 --- a/images.go +++ b/images.go @@ -260,6 +260,7 @@ func (cv *Canvas) DrawImage(image interface{}, coords ...float64) { gli.UseProgram(ir.id) gli.Uniform1i(ir.image, 0) 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.texCoord, 2, gl_FLOAT, false, 0, gli.PtrOffset(8*4)) gli.EnableVertexAttribArray(ir.vertex) diff --git a/made_shaders.go b/made_shaders.go index 3a0c677..5ba1498 100755 --- a/made_shaders.go +++ b/made_shaders.go @@ -6,22 +6,26 @@ import ( "strings" ) -type linearGradientShader struct { - id uint32 - vertex uint32 - canvasSize int32 - invmat int32 - gradient int32 - from int32 - dir int32 - len int32 +type radialGradientShader struct { + id uint32 + vertex uint32 + canvasSize int32 + invmat int32 + gradient int32 + from int32 + to int32 + dir int32 + radFrom int32 + radTo int32 + len int32 + globalAlpha int32 } -func loadLinearGradientShader() (*linearGradientShader, error) { +func loadRadialGradientShader() (*radialGradientShader, error) { var vs, fs, program uint32 { - csource, freeFunc := gli.Strs(linearGradientVS + "\x00") + csource, freeFunc := gli.Strs(radialGradientVS + "\x00") defer freeFunc() vs = gli.CreateShader(gl_VERTEX_SHADER) @@ -33,22 +37,22 @@ func loadLinearGradientShader() (*linearGradientShader, error) { if logLength > 0 { shLog := strings.Repeat("\x00", int(logLength+1)) gli.GetShaderInfoLog(vs, logLength, nil, gli.Str(shLog)) - fmt.Printf("VERTEX_SHADER compilation log for linearGradientVS:\n\n%s\n", shLog) + fmt.Printf("VERTEX_SHADER compilation log for radialGradientVS:\n\n%s\n", shLog) } var status int32 gli.GetShaderiv(vs, gl_COMPILE_STATUS, &status) if status != gl_TRUE { gli.DeleteShader(vs) - return nil, errors.New("Error compiling GL_VERTEX_SHADER shader part for linearGradientVS") + return nil, errors.New("Error compiling GL_VERTEX_SHADER shader part for radialGradientVS") } if glErr := gli.GetError(); glErr != gl_NO_ERROR { - return nil, errors.New("error compiling shader part for linearGradientVS, glError: " + fmt.Sprint(glErr)) + return nil, errors.New("error compiling shader part for radialGradientVS, glError: " + fmt.Sprint(glErr)) } } { - csource, freeFunc := gli.Strs(linearGradientFS + "\x00") + csource, freeFunc := gli.Strs(radialGradientFS + "\x00") defer freeFunc() fs = gli.CreateShader(gl_FRAGMENT_SHADER) @@ -60,17 +64,17 @@ func loadLinearGradientShader() (*linearGradientShader, error) { if logLength > 0 { shLog := strings.Repeat("\x00", int(logLength+1)) gli.GetShaderInfoLog(fs, logLength, nil, gli.Str(shLog)) - fmt.Printf("FRAGMENT_SHADER compilation log for linearGradientFS:\n\n%s\n", shLog) + fmt.Printf("FRAGMENT_SHADER compilation log for radialGradientFS:\n\n%s\n", shLog) } var status int32 gli.GetShaderiv(fs, gl_COMPILE_STATUS, &status) if status != gl_TRUE { gli.DeleteShader(fs) - return nil, errors.New("Error compiling GL_FRAGMENT_SHADER shader part for linearGradientFS") + return nil, errors.New("Error compiling GL_FRAGMENT_SHADER shader part for radialGradientFS") } if glErr := gli.GetError(); glErr != gl_NO_ERROR { - return nil, errors.New("error compiling shader part for linearGradientFS, glError: " + fmt.Sprint(glErr)) + return nil, errors.New("error compiling shader part for radialGradientFS, glError: " + fmt.Sprint(glErr)) } } @@ -85,7 +89,7 @@ func loadLinearGradientShader() (*linearGradientShader, error) { if logLength > 0 { shLog := strings.Repeat("\x00", int(logLength+1)) gli.GetProgramInfoLog(program, logLength, nil, gli.Str(shLog)) - fmt.Printf("Shader link log for linearGradientFS:\n\n%s\n", shLog) + fmt.Printf("Shader link log for radialGradientFS:\n\n%s\n", shLog) } var status int32 @@ -93,446 +97,26 @@ func loadLinearGradientShader() (*linearGradientShader, error) { if status != gl_TRUE { gli.DeleteShader(vs) gli.DeleteShader(fs) - return nil, errors.New("error linking shader for linearGradientFS") + return nil, errors.New("error linking shader for radialGradientFS") } if glErr := gli.GetError(); glErr != gl_NO_ERROR { - return nil, errors.New("error linking shader for linearGradientFS, glError: " + fmt.Sprint(glErr)) + return nil, errors.New("error linking shader for radialGradientFS, glError: " + fmt.Sprint(glErr)) } } - result := &linearGradientShader{} + result := &radialGradientShader{} result.id = program result.vertex = uint32(gli.GetAttribLocation(program, gli.Str("vertex\x00"))) result.canvasSize = gli.GetUniformLocation(program, gli.Str("canvasSize\x00")) result.invmat = gli.GetUniformLocation(program, gli.Str("invmat\x00")) result.gradient = gli.GetUniformLocation(program, gli.Str("gradient\x00")) result.from = gli.GetUniformLocation(program, gli.Str("from\x00")) + result.to = gli.GetUniformLocation(program, gli.Str("to\x00")) result.dir = gli.GetUniformLocation(program, gli.Str("dir\x00")) + result.radFrom = gli.GetUniformLocation(program, gli.Str("radFrom\x00")) + result.radTo = gli.GetUniformLocation(program, gli.Str("radTo\x00")) result.len = gli.GetUniformLocation(program, gli.Str("len\x00")) - - return result, nil -} - -type linearGradientAlphaShader struct { - id uint32 - vertex uint32 - alphaTexCoord uint32 - canvasSize int32 - invmat int32 - gradient int32 - from int32 - dir int32 - len int32 - alphaTex int32 -} - -func loadLinearGradientAlphaShader() (*linearGradientAlphaShader, error) { - var vs, fs, program uint32 - - { - csource, freeFunc := gli.Strs(linearGradientAlphaVS + "\x00") - defer freeFunc() - - vs = gli.CreateShader(gl_VERTEX_SHADER) - gli.ShaderSource(vs, 1, csource, nil) - gli.CompileShader(vs) - - var logLength int32 - gli.GetShaderiv(vs, gl_INFO_LOG_LENGTH, &logLength) - if logLength > 0 { - shLog := strings.Repeat("\x00", int(logLength+1)) - gli.GetShaderInfoLog(vs, logLength, nil, gli.Str(shLog)) - fmt.Printf("VERTEX_SHADER compilation log for linearGradientAlphaVS:\n\n%s\n", shLog) - } - - var status int32 - gli.GetShaderiv(vs, gl_COMPILE_STATUS, &status) - if status != gl_TRUE { - gli.DeleteShader(vs) - return nil, errors.New("Error compiling GL_VERTEX_SHADER shader part for linearGradientAlphaVS") - } - if glErr := gli.GetError(); glErr != gl_NO_ERROR { - return nil, errors.New("error compiling shader part for linearGradientAlphaVS, glError: " + fmt.Sprint(glErr)) - } - } - - { - csource, freeFunc := gli.Strs(linearGradientAlphaFS + "\x00") - defer freeFunc() - - fs = gli.CreateShader(gl_FRAGMENT_SHADER) - gli.ShaderSource(fs, 1, csource, nil) - gli.CompileShader(fs) - - var logLength int32 - gli.GetShaderiv(fs, gl_INFO_LOG_LENGTH, &logLength) - if logLength > 0 { - shLog := strings.Repeat("\x00", int(logLength+1)) - gli.GetShaderInfoLog(fs, logLength, nil, gli.Str(shLog)) - fmt.Printf("FRAGMENT_SHADER compilation log for linearGradientAlphaFS:\n\n%s\n", shLog) - } - - var status int32 - gli.GetShaderiv(fs, gl_COMPILE_STATUS, &status) - if status != gl_TRUE { - gli.DeleteShader(fs) - return nil, errors.New("Error compiling GL_FRAGMENT_SHADER shader part for linearGradientAlphaFS") - } - if glErr := gli.GetError(); glErr != gl_NO_ERROR { - return nil, errors.New("error compiling shader part for linearGradientAlphaFS, glError: " + fmt.Sprint(glErr)) - } - } - - { - program = gli.CreateProgram() - gli.AttachShader(program, vs) - gli.AttachShader(program, fs) - gli.LinkProgram(program) - - var logLength int32 - gli.GetProgramiv(program, gl_INFO_LOG_LENGTH, &logLength) - if logLength > 0 { - shLog := strings.Repeat("\x00", int(logLength+1)) - gli.GetProgramInfoLog(program, logLength, nil, gli.Str(shLog)) - fmt.Printf("Shader link log for linearGradientAlphaFS:\n\n%s\n", shLog) - } - - var status int32 - gli.GetProgramiv(program, gl_LINK_STATUS, &status) - if status != gl_TRUE { - gli.DeleteShader(vs) - gli.DeleteShader(fs) - return nil, errors.New("error linking shader for linearGradientAlphaFS") - } - if glErr := gli.GetError(); glErr != gl_NO_ERROR { - return nil, errors.New("error linking shader for linearGradientAlphaFS, glError: " + fmt.Sprint(glErr)) - } - } - - result := &linearGradientAlphaShader{} - result.id = program - result.vertex = uint32(gli.GetAttribLocation(program, gli.Str("vertex\x00"))) - result.alphaTexCoord = uint32(gli.GetAttribLocation(program, gli.Str("alphaTexCoord\x00"))) - result.canvasSize = gli.GetUniformLocation(program, gli.Str("canvasSize\x00")) - result.invmat = gli.GetUniformLocation(program, gli.Str("invmat\x00")) - result.gradient = gli.GetUniformLocation(program, gli.Str("gradient\x00")) - result.from = gli.GetUniformLocation(program, gli.Str("from\x00")) - result.dir = gli.GetUniformLocation(program, gli.Str("dir\x00")) - result.len = gli.GetUniformLocation(program, gli.Str("len\x00")) - result.alphaTex = gli.GetUniformLocation(program, gli.Str("alphaTex\x00")) - - return result, nil -} - -type imagePatternAlphaShader struct { - id uint32 - vertex uint32 - alphaTexCoord uint32 - canvasSize int32 - imageSize int32 - invmat int32 - image int32 - alphaTex int32 -} - -func loadImagePatternAlphaShader() (*imagePatternAlphaShader, error) { - var vs, fs, program uint32 - - { - csource, freeFunc := gli.Strs(imagePatternAlphaVS + "\x00") - defer freeFunc() - - vs = gli.CreateShader(gl_VERTEX_SHADER) - gli.ShaderSource(vs, 1, csource, nil) - gli.CompileShader(vs) - - var logLength int32 - gli.GetShaderiv(vs, gl_INFO_LOG_LENGTH, &logLength) - if logLength > 0 { - shLog := strings.Repeat("\x00", int(logLength+1)) - gli.GetShaderInfoLog(vs, logLength, nil, gli.Str(shLog)) - fmt.Printf("VERTEX_SHADER compilation log for imagePatternAlphaVS:\n\n%s\n", shLog) - } - - var status int32 - gli.GetShaderiv(vs, gl_COMPILE_STATUS, &status) - if status != gl_TRUE { - gli.DeleteShader(vs) - return nil, errors.New("Error compiling GL_VERTEX_SHADER shader part for imagePatternAlphaVS") - } - if glErr := gli.GetError(); glErr != gl_NO_ERROR { - return nil, errors.New("error compiling shader part for imagePatternAlphaVS, glError: " + fmt.Sprint(glErr)) - } - } - - { - csource, freeFunc := gli.Strs(imagePatternAlphaFS + "\x00") - defer freeFunc() - - fs = gli.CreateShader(gl_FRAGMENT_SHADER) - gli.ShaderSource(fs, 1, csource, nil) - gli.CompileShader(fs) - - var logLength int32 - gli.GetShaderiv(fs, gl_INFO_LOG_LENGTH, &logLength) - if logLength > 0 { - shLog := strings.Repeat("\x00", int(logLength+1)) - gli.GetShaderInfoLog(fs, logLength, nil, gli.Str(shLog)) - fmt.Printf("FRAGMENT_SHADER compilation log for imagePatternAlphaFS:\n\n%s\n", shLog) - } - - var status int32 - gli.GetShaderiv(fs, gl_COMPILE_STATUS, &status) - if status != gl_TRUE { - gli.DeleteShader(fs) - return nil, errors.New("Error compiling GL_FRAGMENT_SHADER shader part for imagePatternAlphaFS") - } - if glErr := gli.GetError(); glErr != gl_NO_ERROR { - return nil, errors.New("error compiling shader part for imagePatternAlphaFS, glError: " + fmt.Sprint(glErr)) - } - } - - { - program = gli.CreateProgram() - gli.AttachShader(program, vs) - gli.AttachShader(program, fs) - gli.LinkProgram(program) - - var logLength int32 - gli.GetProgramiv(program, gl_INFO_LOG_LENGTH, &logLength) - if logLength > 0 { - shLog := strings.Repeat("\x00", int(logLength+1)) - gli.GetProgramInfoLog(program, logLength, nil, gli.Str(shLog)) - fmt.Printf("Shader link log for imagePatternAlphaFS:\n\n%s\n", shLog) - } - - var status int32 - gli.GetProgramiv(program, gl_LINK_STATUS, &status) - if status != gl_TRUE { - gli.DeleteShader(vs) - gli.DeleteShader(fs) - return nil, errors.New("error linking shader for imagePatternAlphaFS") - } - if glErr := gli.GetError(); glErr != gl_NO_ERROR { - return nil, errors.New("error linking shader for imagePatternAlphaFS, glError: " + fmt.Sprint(glErr)) - } - } - - result := &imagePatternAlphaShader{} - result.id = program - result.vertex = uint32(gli.GetAttribLocation(program, gli.Str("vertex\x00"))) - result.alphaTexCoord = uint32(gli.GetAttribLocation(program, gli.Str("alphaTexCoord\x00"))) - result.canvasSize = gli.GetUniformLocation(program, gli.Str("canvasSize\x00")) - result.imageSize = gli.GetUniformLocation(program, gli.Str("imageSize\x00")) - result.invmat = gli.GetUniformLocation(program, gli.Str("invmat\x00")) - result.image = gli.GetUniformLocation(program, gli.Str("image\x00")) - result.alphaTex = gli.GetUniformLocation(program, gli.Str("alphaTex\x00")) - - return result, nil -} - -type imagePatternShader struct { - id uint32 - vertex uint32 - canvasSize int32 - imageSize int32 - invmat int32 - image int32 -} - -func loadImagePatternShader() (*imagePatternShader, error) { - var vs, fs, program uint32 - - { - csource, freeFunc := gli.Strs(imagePatternVS + "\x00") - defer freeFunc() - - vs = gli.CreateShader(gl_VERTEX_SHADER) - gli.ShaderSource(vs, 1, csource, nil) - gli.CompileShader(vs) - - var logLength int32 - gli.GetShaderiv(vs, gl_INFO_LOG_LENGTH, &logLength) - if logLength > 0 { - shLog := strings.Repeat("\x00", int(logLength+1)) - gli.GetShaderInfoLog(vs, logLength, nil, gli.Str(shLog)) - fmt.Printf("VERTEX_SHADER compilation log for imagePatternVS:\n\n%s\n", shLog) - } - - var status int32 - gli.GetShaderiv(vs, gl_COMPILE_STATUS, &status) - if status != gl_TRUE { - gli.DeleteShader(vs) - return nil, errors.New("Error compiling GL_VERTEX_SHADER shader part for imagePatternVS") - } - if glErr := gli.GetError(); glErr != gl_NO_ERROR { - return nil, errors.New("error compiling shader part for imagePatternVS, glError: " + fmt.Sprint(glErr)) - } - } - - { - csource, freeFunc := gli.Strs(imagePatternFS + "\x00") - defer freeFunc() - - fs = gli.CreateShader(gl_FRAGMENT_SHADER) - gli.ShaderSource(fs, 1, csource, nil) - gli.CompileShader(fs) - - var logLength int32 - gli.GetShaderiv(fs, gl_INFO_LOG_LENGTH, &logLength) - if logLength > 0 { - shLog := strings.Repeat("\x00", int(logLength+1)) - gli.GetShaderInfoLog(fs, logLength, nil, gli.Str(shLog)) - fmt.Printf("FRAGMENT_SHADER compilation log for imagePatternFS:\n\n%s\n", shLog) - } - - var status int32 - gli.GetShaderiv(fs, gl_COMPILE_STATUS, &status) - if status != gl_TRUE { - gli.DeleteShader(fs) - return nil, errors.New("Error compiling GL_FRAGMENT_SHADER shader part for imagePatternFS") - } - if glErr := gli.GetError(); glErr != gl_NO_ERROR { - return nil, errors.New("error compiling shader part for imagePatternFS, glError: " + fmt.Sprint(glErr)) - } - } - - { - program = gli.CreateProgram() - gli.AttachShader(program, vs) - gli.AttachShader(program, fs) - gli.LinkProgram(program) - - var logLength int32 - gli.GetProgramiv(program, gl_INFO_LOG_LENGTH, &logLength) - if logLength > 0 { - shLog := strings.Repeat("\x00", int(logLength+1)) - gli.GetProgramInfoLog(program, logLength, nil, gli.Str(shLog)) - fmt.Printf("Shader link log for imagePatternFS:\n\n%s\n", shLog) - } - - var status int32 - gli.GetProgramiv(program, gl_LINK_STATUS, &status) - if status != gl_TRUE { - gli.DeleteShader(vs) - gli.DeleteShader(fs) - return nil, errors.New("error linking shader for imagePatternFS") - } - if glErr := gli.GetError(); glErr != gl_NO_ERROR { - return nil, errors.New("error linking shader for imagePatternFS, glError: " + fmt.Sprint(glErr)) - } - } - - result := &imagePatternShader{} - result.id = program - result.vertex = uint32(gli.GetAttribLocation(program, gli.Str("vertex\x00"))) - result.canvasSize = gli.GetUniformLocation(program, gli.Str("canvasSize\x00")) - result.imageSize = gli.GetUniformLocation(program, gli.Str("imageSize\x00")) - result.invmat = gli.GetUniformLocation(program, gli.Str("invmat\x00")) - result.image = gli.GetUniformLocation(program, gli.Str("image\x00")) - - return result, nil -} - -type solidAlphaShader struct { - id uint32 - vertex uint32 - alphaTexCoord uint32 - canvasSize int32 - color int32 - alphaTex int32 -} - -func loadSolidAlphaShader() (*solidAlphaShader, error) { - var vs, fs, program uint32 - - { - csource, freeFunc := gli.Strs(solidAlphaVS + "\x00") - defer freeFunc() - - vs = gli.CreateShader(gl_VERTEX_SHADER) - gli.ShaderSource(vs, 1, csource, nil) - gli.CompileShader(vs) - - var logLength int32 - gli.GetShaderiv(vs, gl_INFO_LOG_LENGTH, &logLength) - if logLength > 0 { - shLog := strings.Repeat("\x00", int(logLength+1)) - gli.GetShaderInfoLog(vs, logLength, nil, gli.Str(shLog)) - fmt.Printf("VERTEX_SHADER compilation log for solidAlphaVS:\n\n%s\n", shLog) - } - - var status int32 - gli.GetShaderiv(vs, gl_COMPILE_STATUS, &status) - if status != gl_TRUE { - gli.DeleteShader(vs) - return nil, errors.New("Error compiling GL_VERTEX_SHADER shader part for solidAlphaVS") - } - if glErr := gli.GetError(); glErr != gl_NO_ERROR { - return nil, errors.New("error compiling shader part for solidAlphaVS, glError: " + fmt.Sprint(glErr)) - } - } - - { - csource, freeFunc := gli.Strs(solidAlphaFS + "\x00") - defer freeFunc() - - fs = gli.CreateShader(gl_FRAGMENT_SHADER) - gli.ShaderSource(fs, 1, csource, nil) - gli.CompileShader(fs) - - var logLength int32 - gli.GetShaderiv(fs, gl_INFO_LOG_LENGTH, &logLength) - if logLength > 0 { - shLog := strings.Repeat("\x00", int(logLength+1)) - gli.GetShaderInfoLog(fs, logLength, nil, gli.Str(shLog)) - fmt.Printf("FRAGMENT_SHADER compilation log for solidAlphaFS:\n\n%s\n", shLog) - } - - var status int32 - gli.GetShaderiv(fs, gl_COMPILE_STATUS, &status) - if status != gl_TRUE { - gli.DeleteShader(fs) - return nil, errors.New("Error compiling GL_FRAGMENT_SHADER shader part for solidAlphaFS") - } - if glErr := gli.GetError(); glErr != gl_NO_ERROR { - return nil, errors.New("error compiling shader part for solidAlphaFS, glError: " + fmt.Sprint(glErr)) - } - } - - { - program = gli.CreateProgram() - gli.AttachShader(program, vs) - gli.AttachShader(program, fs) - gli.LinkProgram(program) - - var logLength int32 - gli.GetProgramiv(program, gl_INFO_LOG_LENGTH, &logLength) - if logLength > 0 { - shLog := strings.Repeat("\x00", int(logLength+1)) - gli.GetProgramInfoLog(program, logLength, nil, gli.Str(shLog)) - fmt.Printf("Shader link log for solidAlphaFS:\n\n%s\n", shLog) - } - - var status int32 - gli.GetProgramiv(program, gl_LINK_STATUS, &status) - if status != gl_TRUE { - gli.DeleteShader(vs) - gli.DeleteShader(fs) - return nil, errors.New("error linking shader for solidAlphaFS") - } - if glErr := gli.GetError(); glErr != gl_NO_ERROR { - return nil, errors.New("error linking shader for solidAlphaFS, glError: " + fmt.Sprint(glErr)) - } - } - - result := &solidAlphaShader{} - result.id = program - result.vertex = uint32(gli.GetAttribLocation(program, gli.Str("vertex\x00"))) - result.alphaTexCoord = uint32(gli.GetAttribLocation(program, gli.Str("alphaTexCoord\x00"))) - result.canvasSize = gli.GetUniformLocation(program, gli.Str("canvasSize\x00")) - result.color = gli.GetUniformLocation(program, gli.Str("color\x00")) - result.alphaTex = gli.GetUniformLocation(program, gli.Str("alphaTex\x00")) + result.globalAlpha = gli.GetUniformLocation(program, gli.Str("globalAlpha\x00")) return result, nil } @@ -551,6 +135,7 @@ type radialGradientAlphaShader struct { radTo int32 len int32 alphaTex int32 + globalAlpha int32 } func loadRadialGradientAlphaShader() (*radialGradientAlphaShader, error) { @@ -650,15 +235,336 @@ func loadRadialGradientAlphaShader() (*radialGradientAlphaShader, error) { result.radTo = gli.GetUniformLocation(program, gli.Str("radTo\x00")) result.len = gli.GetUniformLocation(program, gli.Str("len\x00")) result.alphaTex = gli.GetUniformLocation(program, gli.Str("alphaTex\x00")) + result.globalAlpha = gli.GetUniformLocation(program, gli.Str("globalAlpha\x00")) + + return result, nil +} + +type imagePatternShader struct { + id uint32 + vertex uint32 + canvasSize int32 + imageSize int32 + invmat int32 + image int32 + globalAlpha int32 +} + +func loadImagePatternShader() (*imagePatternShader, error) { + var vs, fs, program uint32 + + { + csource, freeFunc := gli.Strs(imagePatternVS + "\x00") + defer freeFunc() + + vs = gli.CreateShader(gl_VERTEX_SHADER) + gli.ShaderSource(vs, 1, csource, nil) + gli.CompileShader(vs) + + var logLength int32 + gli.GetShaderiv(vs, gl_INFO_LOG_LENGTH, &logLength) + if logLength > 0 { + shLog := strings.Repeat("\x00", int(logLength+1)) + gli.GetShaderInfoLog(vs, logLength, nil, gli.Str(shLog)) + fmt.Printf("VERTEX_SHADER compilation log for imagePatternVS:\n\n%s\n", shLog) + } + + var status int32 + gli.GetShaderiv(vs, gl_COMPILE_STATUS, &status) + if status != gl_TRUE { + gli.DeleteShader(vs) + return nil, errors.New("Error compiling GL_VERTEX_SHADER shader part for imagePatternVS") + } + if glErr := gli.GetError(); glErr != gl_NO_ERROR { + return nil, errors.New("error compiling shader part for imagePatternVS, glError: " + fmt.Sprint(glErr)) + } + } + + { + csource, freeFunc := gli.Strs(imagePatternFS + "\x00") + defer freeFunc() + + fs = gli.CreateShader(gl_FRAGMENT_SHADER) + gli.ShaderSource(fs, 1, csource, nil) + gli.CompileShader(fs) + + var logLength int32 + gli.GetShaderiv(fs, gl_INFO_LOG_LENGTH, &logLength) + if logLength > 0 { + shLog := strings.Repeat("\x00", int(logLength+1)) + gli.GetShaderInfoLog(fs, logLength, nil, gli.Str(shLog)) + fmt.Printf("FRAGMENT_SHADER compilation log for imagePatternFS:\n\n%s\n", shLog) + } + + var status int32 + gli.GetShaderiv(fs, gl_COMPILE_STATUS, &status) + if status != gl_TRUE { + gli.DeleteShader(fs) + return nil, errors.New("Error compiling GL_FRAGMENT_SHADER shader part for imagePatternFS") + } + if glErr := gli.GetError(); glErr != gl_NO_ERROR { + return nil, errors.New("error compiling shader part for imagePatternFS, glError: " + fmt.Sprint(glErr)) + } + } + + { + program = gli.CreateProgram() + gli.AttachShader(program, vs) + gli.AttachShader(program, fs) + gli.LinkProgram(program) + + var logLength int32 + gli.GetProgramiv(program, gl_INFO_LOG_LENGTH, &logLength) + if logLength > 0 { + shLog := strings.Repeat("\x00", int(logLength+1)) + gli.GetProgramInfoLog(program, logLength, nil, gli.Str(shLog)) + fmt.Printf("Shader link log for imagePatternFS:\n\n%s\n", shLog) + } + + var status int32 + gli.GetProgramiv(program, gl_LINK_STATUS, &status) + if status != gl_TRUE { + gli.DeleteShader(vs) + gli.DeleteShader(fs) + return nil, errors.New("error linking shader for imagePatternFS") + } + if glErr := gli.GetError(); glErr != gl_NO_ERROR { + return nil, errors.New("error linking shader for imagePatternFS, glError: " + fmt.Sprint(glErr)) + } + } + + result := &imagePatternShader{} + result.id = program + result.vertex = uint32(gli.GetAttribLocation(program, gli.Str("vertex\x00"))) + result.canvasSize = gli.GetUniformLocation(program, gli.Str("canvasSize\x00")) + result.imageSize = gli.GetUniformLocation(program, gli.Str("imageSize\x00")) + result.invmat = gli.GetUniformLocation(program, gli.Str("invmat\x00")) + result.image = gli.GetUniformLocation(program, gli.Str("image\x00")) + result.globalAlpha = gli.GetUniformLocation(program, gli.Str("globalAlpha\x00")) + + return result, nil +} + +type imagePatternAlphaShader struct { + id uint32 + vertex uint32 + alphaTexCoord uint32 + canvasSize int32 + imageSize int32 + invmat int32 + image int32 + alphaTex int32 + globalAlpha int32 +} + +func loadImagePatternAlphaShader() (*imagePatternAlphaShader, error) { + var vs, fs, program uint32 + + { + csource, freeFunc := gli.Strs(imagePatternAlphaVS + "\x00") + defer freeFunc() + + vs = gli.CreateShader(gl_VERTEX_SHADER) + gli.ShaderSource(vs, 1, csource, nil) + gli.CompileShader(vs) + + var logLength int32 + gli.GetShaderiv(vs, gl_INFO_LOG_LENGTH, &logLength) + if logLength > 0 { + shLog := strings.Repeat("\x00", int(logLength+1)) + gli.GetShaderInfoLog(vs, logLength, nil, gli.Str(shLog)) + fmt.Printf("VERTEX_SHADER compilation log for imagePatternAlphaVS:\n\n%s\n", shLog) + } + + var status int32 + gli.GetShaderiv(vs, gl_COMPILE_STATUS, &status) + if status != gl_TRUE { + gli.DeleteShader(vs) + return nil, errors.New("Error compiling GL_VERTEX_SHADER shader part for imagePatternAlphaVS") + } + if glErr := gli.GetError(); glErr != gl_NO_ERROR { + return nil, errors.New("error compiling shader part for imagePatternAlphaVS, glError: " + fmt.Sprint(glErr)) + } + } + + { + csource, freeFunc := gli.Strs(imagePatternAlphaFS + "\x00") + defer freeFunc() + + fs = gli.CreateShader(gl_FRAGMENT_SHADER) + gli.ShaderSource(fs, 1, csource, nil) + gli.CompileShader(fs) + + var logLength int32 + gli.GetShaderiv(fs, gl_INFO_LOG_LENGTH, &logLength) + if logLength > 0 { + shLog := strings.Repeat("\x00", int(logLength+1)) + gli.GetShaderInfoLog(fs, logLength, nil, gli.Str(shLog)) + fmt.Printf("FRAGMENT_SHADER compilation log for imagePatternAlphaFS:\n\n%s\n", shLog) + } + + var status int32 + gli.GetShaderiv(fs, gl_COMPILE_STATUS, &status) + if status != gl_TRUE { + gli.DeleteShader(fs) + return nil, errors.New("Error compiling GL_FRAGMENT_SHADER shader part for imagePatternAlphaFS") + } + if glErr := gli.GetError(); glErr != gl_NO_ERROR { + return nil, errors.New("error compiling shader part for imagePatternAlphaFS, glError: " + fmt.Sprint(glErr)) + } + } + + { + program = gli.CreateProgram() + gli.AttachShader(program, vs) + gli.AttachShader(program, fs) + gli.LinkProgram(program) + + var logLength int32 + gli.GetProgramiv(program, gl_INFO_LOG_LENGTH, &logLength) + if logLength > 0 { + shLog := strings.Repeat("\x00", int(logLength+1)) + gli.GetProgramInfoLog(program, logLength, nil, gli.Str(shLog)) + fmt.Printf("Shader link log for imagePatternAlphaFS:\n\n%s\n", shLog) + } + + var status int32 + gli.GetProgramiv(program, gl_LINK_STATUS, &status) + if status != gl_TRUE { + gli.DeleteShader(vs) + gli.DeleteShader(fs) + return nil, errors.New("error linking shader for imagePatternAlphaFS") + } + if glErr := gli.GetError(); glErr != gl_NO_ERROR { + return nil, errors.New("error linking shader for imagePatternAlphaFS, glError: " + fmt.Sprint(glErr)) + } + } + + result := &imagePatternAlphaShader{} + result.id = program + result.vertex = uint32(gli.GetAttribLocation(program, gli.Str("vertex\x00"))) + result.alphaTexCoord = uint32(gli.GetAttribLocation(program, gli.Str("alphaTexCoord\x00"))) + result.canvasSize = gli.GetUniformLocation(program, gli.Str("canvasSize\x00")) + result.imageSize = gli.GetUniformLocation(program, gli.Str("imageSize\x00")) + result.invmat = gli.GetUniformLocation(program, gli.Str("invmat\x00")) + result.image = gli.GetUniformLocation(program, gli.Str("image\x00")) + result.alphaTex = gli.GetUniformLocation(program, gli.Str("alphaTex\x00")) + result.globalAlpha = gli.GetUniformLocation(program, gli.Str("globalAlpha\x00")) + + return result, nil +} + +type solidAlphaShader struct { + id uint32 + vertex uint32 + alphaTexCoord uint32 + canvasSize int32 + color int32 + alphaTex int32 + globalAlpha int32 +} + +func loadSolidAlphaShader() (*solidAlphaShader, error) { + var vs, fs, program uint32 + + { + csource, freeFunc := gli.Strs(solidAlphaVS + "\x00") + defer freeFunc() + + vs = gli.CreateShader(gl_VERTEX_SHADER) + gli.ShaderSource(vs, 1, csource, nil) + gli.CompileShader(vs) + + var logLength int32 + gli.GetShaderiv(vs, gl_INFO_LOG_LENGTH, &logLength) + if logLength > 0 { + shLog := strings.Repeat("\x00", int(logLength+1)) + gli.GetShaderInfoLog(vs, logLength, nil, gli.Str(shLog)) + fmt.Printf("VERTEX_SHADER compilation log for solidAlphaVS:\n\n%s\n", shLog) + } + + var status int32 + gli.GetShaderiv(vs, gl_COMPILE_STATUS, &status) + if status != gl_TRUE { + gli.DeleteShader(vs) + return nil, errors.New("Error compiling GL_VERTEX_SHADER shader part for solidAlphaVS") + } + if glErr := gli.GetError(); glErr != gl_NO_ERROR { + return nil, errors.New("error compiling shader part for solidAlphaVS, glError: " + fmt.Sprint(glErr)) + } + } + + { + csource, freeFunc := gli.Strs(solidAlphaFS + "\x00") + defer freeFunc() + + fs = gli.CreateShader(gl_FRAGMENT_SHADER) + gli.ShaderSource(fs, 1, csource, nil) + gli.CompileShader(fs) + + var logLength int32 + gli.GetShaderiv(fs, gl_INFO_LOG_LENGTH, &logLength) + if logLength > 0 { + shLog := strings.Repeat("\x00", int(logLength+1)) + gli.GetShaderInfoLog(fs, logLength, nil, gli.Str(shLog)) + fmt.Printf("FRAGMENT_SHADER compilation log for solidAlphaFS:\n\n%s\n", shLog) + } + + var status int32 + gli.GetShaderiv(fs, gl_COMPILE_STATUS, &status) + if status != gl_TRUE { + gli.DeleteShader(fs) + return nil, errors.New("Error compiling GL_FRAGMENT_SHADER shader part for solidAlphaFS") + } + if glErr := gli.GetError(); glErr != gl_NO_ERROR { + return nil, errors.New("error compiling shader part for solidAlphaFS, glError: " + fmt.Sprint(glErr)) + } + } + + { + program = gli.CreateProgram() + gli.AttachShader(program, vs) + gli.AttachShader(program, fs) + gli.LinkProgram(program) + + var logLength int32 + gli.GetProgramiv(program, gl_INFO_LOG_LENGTH, &logLength) + if logLength > 0 { + shLog := strings.Repeat("\x00", int(logLength+1)) + gli.GetProgramInfoLog(program, logLength, nil, gli.Str(shLog)) + fmt.Printf("Shader link log for solidAlphaFS:\n\n%s\n", shLog) + } + + var status int32 + gli.GetProgramiv(program, gl_LINK_STATUS, &status) + if status != gl_TRUE { + gli.DeleteShader(vs) + gli.DeleteShader(fs) + return nil, errors.New("error linking shader for solidAlphaFS") + } + if glErr := gli.GetError(); glErr != gl_NO_ERROR { + return nil, errors.New("error linking shader for solidAlphaFS, glError: " + fmt.Sprint(glErr)) + } + } + + result := &solidAlphaShader{} + result.id = program + result.vertex = uint32(gli.GetAttribLocation(program, gli.Str("vertex\x00"))) + result.alphaTexCoord = uint32(gli.GetAttribLocation(program, gli.Str("alphaTexCoord\x00"))) + result.canvasSize = gli.GetUniformLocation(program, gli.Str("canvasSize\x00")) + result.color = gli.GetUniformLocation(program, gli.Str("color\x00")) + result.alphaTex = gli.GetUniformLocation(program, gli.Str("alphaTex\x00")) + result.globalAlpha = gli.GetUniformLocation(program, gli.Str("globalAlpha\x00")) return result, nil } type solidShader struct { - id uint32 - vertex uint32 - canvasSize int32 - color int32 + id uint32 + vertex uint32 + canvasSize int32 + color int32 + globalAlpha int32 } func loadSolidShader() (*solidShader, error) { @@ -749,16 +655,240 @@ func loadSolidShader() (*solidShader, error) { result.vertex = uint32(gli.GetAttribLocation(program, gli.Str("vertex\x00"))) result.canvasSize = gli.GetUniformLocation(program, gli.Str("canvasSize\x00")) result.color = gli.GetUniformLocation(program, gli.Str("color\x00")) + result.globalAlpha = gli.GetUniformLocation(program, gli.Str("globalAlpha\x00")) + + return result, nil +} + +type linearGradientShader struct { + id uint32 + vertex uint32 + canvasSize int32 + invmat int32 + gradient int32 + from int32 + dir int32 + len int32 + globalAlpha int32 +} + +func loadLinearGradientShader() (*linearGradientShader, error) { + var vs, fs, program uint32 + + { + csource, freeFunc := gli.Strs(linearGradientVS + "\x00") + defer freeFunc() + + vs = gli.CreateShader(gl_VERTEX_SHADER) + gli.ShaderSource(vs, 1, csource, nil) + gli.CompileShader(vs) + + var logLength int32 + gli.GetShaderiv(vs, gl_INFO_LOG_LENGTH, &logLength) + if logLength > 0 { + shLog := strings.Repeat("\x00", int(logLength+1)) + gli.GetShaderInfoLog(vs, logLength, nil, gli.Str(shLog)) + fmt.Printf("VERTEX_SHADER compilation log for linearGradientVS:\n\n%s\n", shLog) + } + + var status int32 + gli.GetShaderiv(vs, gl_COMPILE_STATUS, &status) + if status != gl_TRUE { + gli.DeleteShader(vs) + return nil, errors.New("Error compiling GL_VERTEX_SHADER shader part for linearGradientVS") + } + if glErr := gli.GetError(); glErr != gl_NO_ERROR { + return nil, errors.New("error compiling shader part for linearGradientVS, glError: " + fmt.Sprint(glErr)) + } + } + + { + csource, freeFunc := gli.Strs(linearGradientFS + "\x00") + defer freeFunc() + + fs = gli.CreateShader(gl_FRAGMENT_SHADER) + gli.ShaderSource(fs, 1, csource, nil) + gli.CompileShader(fs) + + var logLength int32 + gli.GetShaderiv(fs, gl_INFO_LOG_LENGTH, &logLength) + if logLength > 0 { + shLog := strings.Repeat("\x00", int(logLength+1)) + gli.GetShaderInfoLog(fs, logLength, nil, gli.Str(shLog)) + fmt.Printf("FRAGMENT_SHADER compilation log for linearGradientFS:\n\n%s\n", shLog) + } + + var status int32 + gli.GetShaderiv(fs, gl_COMPILE_STATUS, &status) + if status != gl_TRUE { + gli.DeleteShader(fs) + return nil, errors.New("Error compiling GL_FRAGMENT_SHADER shader part for linearGradientFS") + } + if glErr := gli.GetError(); glErr != gl_NO_ERROR { + return nil, errors.New("error compiling shader part for linearGradientFS, glError: " + fmt.Sprint(glErr)) + } + } + + { + program = gli.CreateProgram() + gli.AttachShader(program, vs) + gli.AttachShader(program, fs) + gli.LinkProgram(program) + + var logLength int32 + gli.GetProgramiv(program, gl_INFO_LOG_LENGTH, &logLength) + if logLength > 0 { + shLog := strings.Repeat("\x00", int(logLength+1)) + gli.GetProgramInfoLog(program, logLength, nil, gli.Str(shLog)) + fmt.Printf("Shader link log for linearGradientFS:\n\n%s\n", shLog) + } + + var status int32 + gli.GetProgramiv(program, gl_LINK_STATUS, &status) + if status != gl_TRUE { + gli.DeleteShader(vs) + gli.DeleteShader(fs) + return nil, errors.New("error linking shader for linearGradientFS") + } + if glErr := gli.GetError(); glErr != gl_NO_ERROR { + return nil, errors.New("error linking shader for linearGradientFS, glError: " + fmt.Sprint(glErr)) + } + } + + result := &linearGradientShader{} + result.id = program + result.vertex = uint32(gli.GetAttribLocation(program, gli.Str("vertex\x00"))) + result.canvasSize = gli.GetUniformLocation(program, gli.Str("canvasSize\x00")) + result.invmat = gli.GetUniformLocation(program, gli.Str("invmat\x00")) + result.gradient = gli.GetUniformLocation(program, gli.Str("gradient\x00")) + result.from = gli.GetUniformLocation(program, gli.Str("from\x00")) + result.dir = gli.GetUniformLocation(program, gli.Str("dir\x00")) + result.len = gli.GetUniformLocation(program, gli.Str("len\x00")) + result.globalAlpha = gli.GetUniformLocation(program, gli.Str("globalAlpha\x00")) + + return result, nil +} + +type linearGradientAlphaShader struct { + id uint32 + vertex uint32 + alphaTexCoord uint32 + canvasSize int32 + invmat int32 + gradient int32 + from int32 + dir int32 + len int32 + alphaTex int32 + globalAlpha int32 +} + +func loadLinearGradientAlphaShader() (*linearGradientAlphaShader, error) { + var vs, fs, program uint32 + + { + csource, freeFunc := gli.Strs(linearGradientAlphaVS + "\x00") + defer freeFunc() + + vs = gli.CreateShader(gl_VERTEX_SHADER) + gli.ShaderSource(vs, 1, csource, nil) + gli.CompileShader(vs) + + var logLength int32 + gli.GetShaderiv(vs, gl_INFO_LOG_LENGTH, &logLength) + if logLength > 0 { + shLog := strings.Repeat("\x00", int(logLength+1)) + gli.GetShaderInfoLog(vs, logLength, nil, gli.Str(shLog)) + fmt.Printf("VERTEX_SHADER compilation log for linearGradientAlphaVS:\n\n%s\n", shLog) + } + + var status int32 + gli.GetShaderiv(vs, gl_COMPILE_STATUS, &status) + if status != gl_TRUE { + gli.DeleteShader(vs) + return nil, errors.New("Error compiling GL_VERTEX_SHADER shader part for linearGradientAlphaVS") + } + if glErr := gli.GetError(); glErr != gl_NO_ERROR { + return nil, errors.New("error compiling shader part for linearGradientAlphaVS, glError: " + fmt.Sprint(glErr)) + } + } + + { + csource, freeFunc := gli.Strs(linearGradientAlphaFS + "\x00") + defer freeFunc() + + fs = gli.CreateShader(gl_FRAGMENT_SHADER) + gli.ShaderSource(fs, 1, csource, nil) + gli.CompileShader(fs) + + var logLength int32 + gli.GetShaderiv(fs, gl_INFO_LOG_LENGTH, &logLength) + if logLength > 0 { + shLog := strings.Repeat("\x00", int(logLength+1)) + gli.GetShaderInfoLog(fs, logLength, nil, gli.Str(shLog)) + fmt.Printf("FRAGMENT_SHADER compilation log for linearGradientAlphaFS:\n\n%s\n", shLog) + } + + var status int32 + gli.GetShaderiv(fs, gl_COMPILE_STATUS, &status) + if status != gl_TRUE { + gli.DeleteShader(fs) + return nil, errors.New("Error compiling GL_FRAGMENT_SHADER shader part for linearGradientAlphaFS") + } + if glErr := gli.GetError(); glErr != gl_NO_ERROR { + return nil, errors.New("error compiling shader part for linearGradientAlphaFS, glError: " + fmt.Sprint(glErr)) + } + } + + { + program = gli.CreateProgram() + gli.AttachShader(program, vs) + gli.AttachShader(program, fs) + gli.LinkProgram(program) + + var logLength int32 + gli.GetProgramiv(program, gl_INFO_LOG_LENGTH, &logLength) + if logLength > 0 { + shLog := strings.Repeat("\x00", int(logLength+1)) + gli.GetProgramInfoLog(program, logLength, nil, gli.Str(shLog)) + fmt.Printf("Shader link log for linearGradientAlphaFS:\n\n%s\n", shLog) + } + + var status int32 + gli.GetProgramiv(program, gl_LINK_STATUS, &status) + if status != gl_TRUE { + gli.DeleteShader(vs) + gli.DeleteShader(fs) + return nil, errors.New("error linking shader for linearGradientAlphaFS") + } + if glErr := gli.GetError(); glErr != gl_NO_ERROR { + return nil, errors.New("error linking shader for linearGradientAlphaFS, glError: " + fmt.Sprint(glErr)) + } + } + + result := &linearGradientAlphaShader{} + result.id = program + result.vertex = uint32(gli.GetAttribLocation(program, gli.Str("vertex\x00"))) + result.alphaTexCoord = uint32(gli.GetAttribLocation(program, gli.Str("alphaTexCoord\x00"))) + result.canvasSize = gli.GetUniformLocation(program, gli.Str("canvasSize\x00")) + result.invmat = gli.GetUniformLocation(program, gli.Str("invmat\x00")) + result.gradient = gli.GetUniformLocation(program, gli.Str("gradient\x00")) + result.from = gli.GetUniformLocation(program, gli.Str("from\x00")) + result.dir = gli.GetUniformLocation(program, gli.Str("dir\x00")) + result.len = gli.GetUniformLocation(program, gli.Str("len\x00")) + result.alphaTex = gli.GetUniformLocation(program, gli.Str("alphaTex\x00")) + result.globalAlpha = gli.GetUniformLocation(program, gli.Str("globalAlpha\x00")) return result, nil } type imageShader struct { - id uint32 - vertex uint32 - texCoord uint32 - canvasSize int32 - image int32 + id uint32 + vertex uint32 + texCoord uint32 + canvasSize int32 + image int32 + globalAlpha int32 } func loadImageShader() (*imageShader, error) { @@ -850,119 +980,7 @@ func loadImageShader() (*imageShader, error) { result.texCoord = uint32(gli.GetAttribLocation(program, gli.Str("texCoord\x00"))) result.canvasSize = gli.GetUniformLocation(program, gli.Str("canvasSize\x00")) result.image = gli.GetUniformLocation(program, gli.Str("image\x00")) - - return result, nil -} - -type radialGradientShader struct { - id uint32 - vertex uint32 - canvasSize int32 - invmat int32 - gradient int32 - from int32 - to int32 - dir int32 - radFrom int32 - radTo int32 - len int32 -} - -func loadRadialGradientShader() (*radialGradientShader, error) { - var vs, fs, program uint32 - - { - csource, freeFunc := gli.Strs(radialGradientVS + "\x00") - defer freeFunc() - - vs = gli.CreateShader(gl_VERTEX_SHADER) - gli.ShaderSource(vs, 1, csource, nil) - gli.CompileShader(vs) - - var logLength int32 - gli.GetShaderiv(vs, gl_INFO_LOG_LENGTH, &logLength) - if logLength > 0 { - shLog := strings.Repeat("\x00", int(logLength+1)) - gli.GetShaderInfoLog(vs, logLength, nil, gli.Str(shLog)) - fmt.Printf("VERTEX_SHADER compilation log for radialGradientVS:\n\n%s\n", shLog) - } - - var status int32 - gli.GetShaderiv(vs, gl_COMPILE_STATUS, &status) - if status != gl_TRUE { - gli.DeleteShader(vs) - return nil, errors.New("Error compiling GL_VERTEX_SHADER shader part for radialGradientVS") - } - if glErr := gli.GetError(); glErr != gl_NO_ERROR { - return nil, errors.New("error compiling shader part for radialGradientVS, glError: " + fmt.Sprint(glErr)) - } - } - - { - csource, freeFunc := gli.Strs(radialGradientFS + "\x00") - defer freeFunc() - - fs = gli.CreateShader(gl_FRAGMENT_SHADER) - gli.ShaderSource(fs, 1, csource, nil) - gli.CompileShader(fs) - - var logLength int32 - gli.GetShaderiv(fs, gl_INFO_LOG_LENGTH, &logLength) - if logLength > 0 { - shLog := strings.Repeat("\x00", int(logLength+1)) - gli.GetShaderInfoLog(fs, logLength, nil, gli.Str(shLog)) - fmt.Printf("FRAGMENT_SHADER compilation log for radialGradientFS:\n\n%s\n", shLog) - } - - var status int32 - gli.GetShaderiv(fs, gl_COMPILE_STATUS, &status) - if status != gl_TRUE { - gli.DeleteShader(fs) - return nil, errors.New("Error compiling GL_FRAGMENT_SHADER shader part for radialGradientFS") - } - if glErr := gli.GetError(); glErr != gl_NO_ERROR { - return nil, errors.New("error compiling shader part for radialGradientFS, glError: " + fmt.Sprint(glErr)) - } - } - - { - program = gli.CreateProgram() - gli.AttachShader(program, vs) - gli.AttachShader(program, fs) - gli.LinkProgram(program) - - var logLength int32 - gli.GetProgramiv(program, gl_INFO_LOG_LENGTH, &logLength) - if logLength > 0 { - shLog := strings.Repeat("\x00", int(logLength+1)) - gli.GetProgramInfoLog(program, logLength, nil, gli.Str(shLog)) - fmt.Printf("Shader link log for radialGradientFS:\n\n%s\n", shLog) - } - - var status int32 - gli.GetProgramiv(program, gl_LINK_STATUS, &status) - if status != gl_TRUE { - gli.DeleteShader(vs) - gli.DeleteShader(fs) - return nil, errors.New("error linking shader for radialGradientFS") - } - if glErr := gli.GetError(); glErr != gl_NO_ERROR { - return nil, errors.New("error linking shader for radialGradientFS, glError: " + fmt.Sprint(glErr)) - } - } - - result := &radialGradientShader{} - result.id = program - result.vertex = uint32(gli.GetAttribLocation(program, gli.Str("vertex\x00"))) - result.canvasSize = gli.GetUniformLocation(program, gli.Str("canvasSize\x00")) - result.invmat = gli.GetUniformLocation(program, gli.Str("invmat\x00")) - result.gradient = gli.GetUniformLocation(program, gli.Str("gradient\x00")) - result.from = gli.GetUniformLocation(program, gli.Str("from\x00")) - result.to = gli.GetUniformLocation(program, gli.Str("to\x00")) - result.dir = gli.GetUniformLocation(program, gli.Str("dir\x00")) - result.radFrom = gli.GetUniformLocation(program, gli.Str("radFrom\x00")) - result.radTo = gli.GetUniformLocation(program, gli.Str("radTo\x00")) - result.len = gli.GetUniformLocation(program, gli.Str("len\x00")) + result.globalAlpha = gli.GetUniformLocation(program, gli.Str("globalAlpha\x00")) return result, nil } diff --git a/paths.go b/paths.go index 17a2a6e..2c54e6a 100644 --- a/paths.go +++ b/paths.go @@ -465,31 +465,65 @@ func (cv *Canvas) Fill() { return } 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 for i, p := range cv.polyPath { if p.flags&pathMove == 0 { continue } if i >= start+3 { - cv.fillPoly(cv.polyPath[start:i]) + tris = cv.appendSubPathTriangles(tris, cv.polyPath[start:i]) } start = i } if len(cv.polyPath) >= start+3 { - cv.fillPoly(cv.polyPath[start:]) + tris = cv.appendSubPathTriangles(tris, cv.polyPath[start:]) } -} - -func (cv *Canvas) fillPoly(path []pathPoint) { - if len(path) < 3 { + if len(tris) == 0 { return } - cv.activate() - gli.BindBuffer(gl_ARRAY_BUFFER, buf) - var triBuf [1000]float32 - var tris []float32 + gli.BufferData(gl_ARRAY_BUFFER, len(tris)*4, unsafe.Pointer(&tris[0]), gl_STREAM_DRAW) + + 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 { p0, p1 := path[0].tf, path[1].tf last := len(path) @@ -500,18 +534,9 @@ func (cv *Canvas) fillPoly(path []pathPoint) { } } else { path = cv.cutIntersections(path) - tris = triangulatePath(path, triBuf[:0]) - if len(tris) == 0 { - return - } + tris = triangulatePath(path, tris) } - gli.BufferData(gl_ARRAY_BUFFER, len(tris)*4, unsafe.Pointer(&tris[0]), gl_STREAM_DRAW) - - 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) + return tris } func (cv *Canvas) Clip() { diff --git a/shaders.go b/shaders.go index 97a1525..bddde32 100644 --- a/shaders.go +++ b/shaders.go @@ -15,8 +15,11 @@ precision mediump float; #endif varying vec2 v_texCoord; uniform sampler2D image; +uniform float globalAlpha; void main() { - gl_FragColor = texture2D(image, v_texCoord); + vec4 col = texture2D(image, v_texCoord); + col.a *= globalAlpha; + gl_FragColor = col; }` var solidVS = ` @@ -31,8 +34,11 @@ var solidFS = ` precision mediump float; #endif uniform vec4 color; +uniform float globalAlpha; void main() { - gl_FragColor = color; + vec4 col = color; + col.a *= globalAlpha; + gl_FragColor = col; }` var linearGradientVS = ` @@ -53,12 +59,15 @@ uniform mat3 invmat; uniform sampler1D 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; float r = dot(v, dir) / len; 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 = ` @@ -80,6 +89,7 @@ uniform sampler1D gradient; uniform vec2 from, to, dir; uniform float radFrom, radTo; uniform float len; +uniform float globalAlpha; bool isNaN(float v) { return v < 0.0 || 0.0 < v || v == 0.0 ? false : true; } @@ -99,8 +109,10 @@ void main() { return; } float o = max(o1, o2); - float r = radFrom + o * (radTo - radFrom); - gl_FragColor = texture1D(gradient, o); + //float r = radFrom + o * (radTo - radFrom); + vec4 col = texture1D(gradient, o); + col.a *= globalAlpha; + gl_FragColor = col; }` var imagePatternVS = ` @@ -120,9 +132,12 @@ 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; - 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 = ` @@ -141,9 +156,10 @@ precision mediump float; varying vec2 v_atc; uniform vec4 color; uniform sampler2D alphaTex; +uniform float globalAlpha; void main() { vec4 col = color; - col.a *= texture2D(alphaTex, v_atc).a; + col.a *= texture2D(alphaTex, v_atc).a * globalAlpha; gl_FragColor = col; }` @@ -170,13 +186,14 @@ uniform sampler1D 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; float r = dot(v, dir) / len; r = clamp(r, 0.0, 1.0); vec4 col = texture1D(gradient, r); - col.a *= texture2D(alphaTex, v_atc).a; + col.a *= texture2D(alphaTex, v_atc).a * globalAlpha; gl_FragColor = col; }` @@ -203,6 +220,7 @@ uniform vec2 from, to, dir; uniform float radFrom, radTo; uniform float len; uniform sampler2D alphaTex; +uniform float globalAlpha; bool isNaN(float v) { return v < 0.0 || 0.0 < v || v == 0.0 ? false : true; } @@ -224,7 +242,7 @@ void main() { float o = max(o1, o2); float r = radFrom + o * (radTo - radFrom); vec4 col = texture1D(gradient, o); - col.a *= texture2D(alphaTex, v_atc).a; + col.a *= texture2D(alphaTex, v_atc).a * globalAlpha; gl_FragColor = col; }` @@ -249,9 +267,10 @@ 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)); - col.a *= texture2D(alphaTex, v_atc).a; + col.a *= texture2D(alphaTex, v_atc).a * globalAlpha; gl_FragColor = col; }`