added image patterns

This commit is contained in:
Thomas Friedel 2018-02-09 11:21:27 +01:00
parent bed6cdc50a
commit 3710a446b5
2 changed files with 258 additions and 111 deletions

View file

@ -39,6 +39,7 @@ type drawState struct {
color glColor color glColor
radialGradient *RadialGradient radialGradient *RadialGradient
linearGradient *LinearGradient linearGradient *LinearGradient
image *Image
} }
stroke struct { stroke struct {
color glColor color glColor
@ -128,6 +129,7 @@ var (
tr *textureShader tr *textureShader
lgr *linearGradientShader lgr *linearGradientShader
rgr *radialGradientShader rgr *radialGradientShader
ipr *imagePatternShader
glChan = make(chan func()) glChan = make(chan func())
) )
@ -172,6 +174,15 @@ func LoadGL(glimpl GL) (err error) {
return return
} }
ipr, err = loadImagePatternShader()
if err != nil {
return
}
err = glError()
if err != nil {
return
}
gli.GenBuffers(1, &buf) gli.GenBuffers(1, &buf)
err = glError() err = glError()
if err != nil { if err != nil {
@ -285,6 +296,26 @@ void main() {
float r = radFrom + o * (radTo - radFrom); float r = radFrom + o * (radTo - radFrom);
gl_FragColor = texture1D(gradient, o); gl_FragColor = texture1D(gradient, o);
}` }`
var imagePatternVS = `
attribute vec2 vertex;
uniform vec2 canvasSize;
varying vec2 v_cp;
void main() {
v_cp = vertex;
vec2 glp = vertex * 2.0 / canvasSize - 1.0;
gl_Position = vec4(glp.x, -glp.y, 0.0, 1.0);
}`
var imagePatternFS = `
#ifdef GL_ES
precision mediump float;
#endif
varying vec2 v_cp;
uniform vec2 imageSize;
uniform sampler2D image;
void main() {
gl_FragColor = texture2D(image, mod(v_cp / imageSize, 1.0));
//gl_FragColor = vec4(v_cp * 0.1, 0.0, 1.0);
}`
func glError() error { func glError() error {
glErr := gli.GetError() glErr := gli.GetError()
@ -299,6 +330,7 @@ func (cv *Canvas) SetFillStyle(value ...interface{}) {
cv.state.fill.color = glColor{} cv.state.fill.color = glColor{}
cv.state.fill.linearGradient = nil cv.state.fill.linearGradient = nil
cv.state.fill.radialGradient = nil cv.state.fill.radialGradient = nil
cv.state.fill.image = nil
if len(value) == 1 { if len(value) == 1 {
switch v := value[0].(type) { switch v := value[0].(type) {
case *LinearGradient: case *LinearGradient:
@ -307,6 +339,9 @@ func (cv *Canvas) SetFillStyle(value ...interface{}) {
case *RadialGradient: case *RadialGradient:
cv.state.fill.radialGradient = v cv.state.fill.radialGradient = v
return return
case *Image:
cv.state.fill.image = v
return
} }
} }
c, ok := parseColor(value...) c, ok := parseColor(value...)
@ -458,6 +493,17 @@ func (cv *Canvas) FillRect(x, y, w, h float32) {
gli.EnableVertexAttribArray(rgr.vertex) gli.EnableVertexAttribArray(rgr.vertex)
gli.DrawArrays(gl_TRIANGLE_FAN, 0, 4) gli.DrawArrays(gl_TRIANGLE_FAN, 0, 4)
gli.DisableVertexAttribArray(rgr.vertex) gli.DisableVertexAttribArray(rgr.vertex)
} else if img := cv.state.fill.image; img != nil {
gli.UseProgram(ipr.id)
gli.VertexAttribPointer(ipr.vertex, 2, gl_FLOAT, false, 0, nil)
gli.ActiveTexture(gl_TEXTURE0)
gli.BindTexture(gl_TEXTURE_1D, img.tex)
gli.Uniform2f(ipr.canvasSize, cv.fw, cv.fh)
gli.Uniform2f(ipr.imageSize, float32(img.w), float32(img.h))
gli.Uniform1i(ipr.image, 0)
gli.EnableVertexAttribArray(ipr.vertex)
gli.DrawArrays(gl_TRIANGLE_FAN, 0, 4)
gli.DisableVertexAttribArray(ipr.vertex)
} else { } else {
gli.UseProgram(sr.id) gli.UseProgram(sr.id)
gli.VertexAttribPointer(sr.vertex, 2, gl_FLOAT, false, 0, nil) gli.VertexAttribPointer(sr.vertex, 2, gl_FLOAT, false, 0, nil)

View file

@ -6,6 +6,107 @@ import (
"strings" "strings"
) )
type imagePatternShader struct {
id uint32
vertex uint32
canvasSize int32
imageSize 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:\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")
}
if glErr := gli.GetError(); glErr != gl_NO_ERROR {
return nil, errors.New("error compiling shader part, 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:\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")
}
if glErr := gli.GetError(); glErr != gl_NO_ERROR {
return nil, errors.New("error compiling shader part, 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:\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")
}
if glErr := gli.GetError(); glErr != gl_NO_ERROR {
return nil, errors.New("error linking shader, 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.image = gli.GetUniformLocation(program, gli.Str("image\x00"))
return result, nil
}
type textureShader struct { type textureShader struct {
id uint32 id uint32
vertex uint32 vertex uint32
@ -107,6 +208,117 @@ func loadTextureShader() (*textureShader, error) {
return result, nil return result, nil
} }
type radialGradientShader struct {
id uint32
vertex uint32
canvasSize 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:\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")
}
if glErr := gli.GetError(); glErr != gl_NO_ERROR {
return nil, errors.New("error compiling shader part, 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:\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")
}
if glErr := gli.GetError(); glErr != gl_NO_ERROR {
return nil, errors.New("error compiling shader part, 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:\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")
}
if glErr := gli.GetError(); glErr != gl_NO_ERROR {
return nil, errors.New("error linking shader, 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.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 solidShader struct { type solidShader struct {
id uint32 id uint32
vertex uint32 vertex uint32
@ -310,114 +522,3 @@ func loadLinearGradientShader() (*linearGradientShader, error) {
return result, nil return result, nil
} }
type radialGradientShader struct {
id uint32
vertex uint32
canvasSize 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:\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")
}
if glErr := gli.GetError(); glErr != gl_NO_ERROR {
return nil, errors.New("error compiling shader part, 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:\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")
}
if glErr := gli.GetError(); glErr != gl_NO_ERROR {
return nil, errors.New("error compiling shader part, 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:\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")
}
if glErr := gli.GetError(); glErr != gl_NO_ERROR {
return nil, errors.New("error linking shader, 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.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
}