diff --git a/canvas.go b/canvas.go index c902809..0f96c86 100644 --- a/canvas.go +++ b/canvas.go @@ -259,11 +259,13 @@ var linearGradientFS = ` precision mediump float; #endif varying vec2 v_cp; +uniform mat3 invmat; uniform sampler1D gradient; uniform vec2 from, dir; uniform float len; void main() { - vec2 v = v_cp - from; + 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); @@ -282,6 +284,7 @@ var radialGradientFS = ` precision mediump float; #endif varying vec2 v_cp; +uniform mat3 invmat; uniform sampler1D gradient; uniform vec2 from, to, dir; uniform float radFrom, radTo; @@ -290,12 +293,13 @@ bool isNaN(float v) { return v < 0.0 || 0.0 < v || v == 0.0 ? false : true; } void main() { + vec3 untf = vec3(v_cp, 1.0) * invmat; float o_a = 0.5 * sqrt( - pow(-2.0*from.x*from.x+2.0*from.x*to.x+2.0*from.x*v_cp.x-2.0*to.x*v_cp.x-2.0*from.y*from.y+2.0*from.y*to.y+2.0*from.y*v_cp.y-2.0*to.y*v_cp.y+2.0*radFrom*radFrom-2.0*radFrom*radTo, 2.0) - -4.0*(from.x*from.x-2.0*from.x*v_cp.x+v_cp.x*v_cp.x+from.y*from.y-2.0*from.y*v_cp.y+v_cp.y*v_cp.y-radFrom*radFrom) + pow(-2.0*from.x*from.x+2.0*from.x*to.x+2.0*from.x*untf.x-2.0*to.x*untf.x-2.0*from.y*from.y+2.0*from.y*to.y+2.0*from.y*untf.y-2.0*to.y*untf.y+2.0*radFrom*radFrom-2.0*radFrom*radTo, 2.0) + -4.0*(from.x*from.x-2.0*from.x*untf.x+untf.x*untf.x+from.y*from.y-2.0*from.y*untf.y+untf.y*untf.y-radFrom*radFrom) *(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*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_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_c = (from.x*from.x-2.0*from.x*to.x+to.x*to.x+from.y*from.y-2.0*from.y*to.y+to.y*to.y-radFrom*radFrom+2.0*radFrom*radTo-radTo*radTo); float o1 = (-o_a + o_b) / o_c; float o2 = (o_a + o_b) / o_c; @@ -322,9 +326,11 @@ precision mediump float; #endif varying vec2 v_cp; uniform vec2 imageSize; +uniform mat3 invmat; uniform sampler2D image; void main() { - gl_FragColor = texture2D(image, mod(v_cp / imageSize, 1.0)); + vec3 untf = vec3(v_cp, 1.0) * invmat; + gl_FragColor = texture2D(image, mod(untf.xy / imageSize, 1.0)); //gl_FragColor = vec4(v_cp * 0.1, 0.0, 1.0); }` @@ -384,6 +390,8 @@ func (cv *Canvas) useShader(style *drawStyle) (vertexLoc uint32) { length := dir.Len() dir = dir.DivF(length) gli.Uniform2f(lgr.canvasSize, cv.fw, cv.fh) + inv := cv.state.transform.Invert() + gli.UniformMatrix3fv(lgr.invmat, 1, false, &inv[0]) gli.Uniform2f(lgr.from, from[0], from[1]) gli.Uniform2f(lgr.dir, dir[0], dir[1]) gli.Uniform1f(lgr.len, length) @@ -401,6 +409,8 @@ func (cv *Canvas) useShader(style *drawStyle) (vertexLoc uint32) { length := dir.Len() dir = dir.DivF(length) gli.Uniform2f(rgr.canvasSize, cv.fw, cv.fh) + inv := cv.state.transform.Invert() + gli.UniformMatrix3fv(rgr.invmat, 1, false, &inv[0]) gli.Uniform2f(rgr.from, from[0], from[1]) gli.Uniform2f(rgr.to, to[0], to[1]) gli.Uniform2f(rgr.dir, dir[0], dir[1]) @@ -415,6 +425,8 @@ func (cv *Canvas) useShader(style *drawStyle) (vertexLoc uint32) { gli.ActiveTexture(gl_TEXTURE0) gli.BindTexture(gl_TEXTURE_2D, img.tex) gli.Uniform2f(ipr.canvasSize, cv.fw, cv.fh) + inv := cv.state.transform.Invert() + gli.UniformMatrix3fv(ipr.invmat, 1, false, &inv[0]) gli.Uniform2f(ipr.imageSize, float32(img.w), float32(img.h)) gli.Uniform1i(ipr.image, 0) return ipr.vertex diff --git a/made_shaders.go b/made_shaders.go index 33b3618..4ea2bac 100755 --- a/made_shaders.go +++ b/made_shaders.go @@ -6,107 +6,6 @@ import ( "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 { id uint32 vertex uint32 @@ -208,117 +107,6 @@ func loadTextureShader() (*textureShader, error) { 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 { id uint32 vertex uint32 @@ -418,10 +206,114 @@ func loadSolidShader() (*solidShader, error) { 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:\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.invmat = gli.GetUniformLocation(program, gli.Str("invmat\x00")) + result.image = gli.GetUniformLocation(program, gli.Str("image\x00")) + + return result, nil +} + type linearGradientShader struct { id uint32 vertex uint32 canvasSize int32 + invmat int32 gradient int32 from int32 dir int32 @@ -515,6 +407,7 @@ func loadLinearGradientShader() (*linearGradientShader, error) { 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")) @@ -522,3 +415,116 @@ func loadLinearGradientShader() (*linearGradientShader, error) { 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:\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.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 +}