implemented shadowBlur (wip)

This commit is contained in:
Thomas Friedel 2018-07-27 14:11:47 +02:00
parent 0cb030619e
commit f2225e857a
9 changed files with 860 additions and 276 deletions

View file

@ -50,6 +50,7 @@ type drawState struct {
shadowColor glColor
shadowOffsetX float64
shadowOffsetY float64
shadowBlur float64
/*
The current transformation matrix.
@ -190,14 +191,22 @@ var (
lgar *linearGradientAlphaShader
ipar *imagePatternAlphaShader
ir *imageShader
offScrTex uint32
offScrW int
offScrH int
renderStencilBuf uint32
frameBuf uint32
gauss15r *gaussian15Shader
gauss63r *gaussian63Shader
gauss255r *gaussian255Shader
offscr1 offscreenBuffer
offscr2 offscreenBuffer
glChan = make(chan func())
)
type offscreenBuffer struct {
tex uint32
w int
h int
renderStencilBuf uint32
frameBuf uint32
}
// LoadGL needs to be called once per GL context to load the GL assets
// that canvas needs. The parameter is an implementation of the GL interface
// in this package that should make this package neutral to GL implementations.
@ -288,6 +297,33 @@ func LoadGL(glimpl GL) (err error) {
return
}
gauss15r, err = loadGaussian15Shader()
if err != nil {
return
}
err = glError()
if err != nil {
return
}
gauss63r, err = loadGaussian63Shader()
if err != nil {
return
}
err = glError()
if err != nil {
return
}
gauss255r, err = loadGaussian255Shader()
if err != nil {
return
}
err = glError()
if err != nil {
return
}
gli.GenBuffers(1, &buf)
err = glError()
if err != nil {
@ -514,32 +550,33 @@ func (cv *Canvas) useAlphaShader(style *drawStyle, alphaTexSlot int32) (vertexLo
return sar.vertex, sar.alphaTexCoord
}
func (cv *Canvas) enableTextureRenderTarget() {
if offScrW != cv.w || offScrH != cv.h {
if offScrW != 0 && offScrH != 0 {
gli.DeleteTextures(1, &offScrTex)
gli.DeleteFramebuffers(1, &frameBuf)
gli.DeleteRenderbuffers(1, &renderStencilBuf)
func (cv *Canvas) enableTextureRenderTarget(offscr *offscreenBuffer) {
if offscr.w != cv.w || offscr.h != cv.h {
if offscr.w != 0 && offscr.h != 0 {
gli.DeleteTextures(1, &offscr.tex)
gli.DeleteFramebuffers(1, &offscr.frameBuf)
gli.DeleteRenderbuffers(1, &offscr.renderStencilBuf)
}
offScrW = cv.w
offScrH = cv.h
offscr.w = cv.w
offscr.h = cv.h
gli.GenTextures(1, &offScrTex)
gli.BindTexture(gl_TEXTURE_2D, offScrTex)
gli.ActiveTexture(gl_TEXTURE0)
gli.GenTextures(1, &offscr.tex)
gli.BindTexture(gl_TEXTURE_2D, offscr.tex)
// todo do non-power-of-two textures work everywhere?
gli.TexImage2D(gl_TEXTURE_2D, 0, gl_RGB, int32(cv.w), int32(cv.h), 0, gl_RGB, gl_UNSIGNED_BYTE, nil)
gli.TexImage2D(gl_TEXTURE_2D, 0, gl_RGBA, int32(cv.w), int32(cv.h), 0, gl_RGBA, gl_UNSIGNED_BYTE, nil)
gli.TexParameteri(gl_TEXTURE_2D, gl_TEXTURE_MAG_FILTER, gl_NEAREST)
gli.TexParameteri(gl_TEXTURE_2D, gl_TEXTURE_MIN_FILTER, gl_NEAREST)
gli.GenFramebuffers(1, &frameBuf)
gli.BindFramebuffer(gl_FRAMEBUFFER, frameBuf)
gli.GenFramebuffers(1, &offscr.frameBuf)
gli.BindFramebuffer(gl_FRAMEBUFFER, offscr.frameBuf)
gli.GenRenderbuffers(1, &renderStencilBuf)
gli.BindRenderbuffer(gl_RENDERBUFFER, renderStencilBuf)
gli.GenRenderbuffers(1, &offscr.renderStencilBuf)
gli.BindRenderbuffer(gl_RENDERBUFFER, offscr.renderStencilBuf)
gli.RenderbufferStorage(gl_RENDERBUFFER, gl_DEPTH_STENCIL, int32(cv.w), int32(cv.h))
gli.FramebufferRenderbuffer(gl_FRAMEBUFFER, gl_DEPTH_STENCIL_ATTACHMENT, gl_RENDERBUFFER, renderStencilBuf)
gli.FramebufferRenderbuffer(gl_FRAMEBUFFER, gl_DEPTH_STENCIL_ATTACHMENT, gl_RENDERBUFFER, offscr.renderStencilBuf)
gli.FramebufferTexture(gl_FRAMEBUFFER, gl_COLOR_ATTACHMENT0, offScrTex, 0)
gli.FramebufferTexture(gl_FRAMEBUFFER, gl_COLOR_ATTACHMENT0, offscr.tex, 0)
if gli.CheckFramebufferStatus(gl_FRAMEBUFFER) != gl_FRAMEBUFFER_COMPLETE {
// todo this should maybe not panic
@ -548,7 +585,7 @@ func (cv *Canvas) enableTextureRenderTarget() {
gli.Clear(gl_COLOR_BUFFER_BIT | gl_STENCIL_BUFFER_BIT)
} else {
gli.BindFramebuffer(gl_FRAMEBUFFER, frameBuf)
gli.BindFramebuffer(gl_FRAMEBUFFER, offscr.frameBuf)
}
}
@ -556,11 +593,6 @@ func (cv *Canvas) disableTextureRenderTarget() {
gli.BindFramebuffer(gl_FRAMEBUFFER, 0)
}
func (cv *Canvas) renderOffscreenTexture() {
img := Image{w: cv.w, h: cv.h, tex: offScrTex}
cv.DrawImage(&img, 0, 0, cv.fw, cv.fh)
}
// SetLineWidth sets the line width for any line drawing calls
func (cv *Canvas) SetLineWidth(width float64) {
if width < 0 {
@ -720,3 +752,9 @@ func (cv *Canvas) SetShadowOffset(x, y float64) {
cv.state.shadowOffsetX = x
cv.state.shadowOffsetY = y
}
// SetShadowBlur sets the gaussian blur radius of the shadow
// (0 for no blur)
func (cv *Canvas) SetShadowBlur(r float64) {
cv.state.shadowBlur = r
}

View file

@ -181,6 +181,9 @@ func (_ GLImpl) TexSubImage2D(target uint32, level int32, xoffset int32, yoffset
func (_ GLImpl) Uniform1f(location int32, v0 float32) {
gl.Uniform1f(location, v0)
}
func (_ GLImpl) Uniform1fv(location int32, count int32, v *float32) {
gl.Uniform1fv(location, count, v)
}
func (_ GLImpl) Uniform1i(location int32, v0 int32) {
gl.Uniform1i(location, v0)
}

View file

@ -309,3 +309,66 @@ func (cv *Canvas) DrawImage(image interface{}, coords ...float64) {
gli.StencilFunc(gl_ALWAYS, 0, 0xFF)
}
func (cv *Canvas) drawImageTemp(image interface{}, coords ...float64) {
img := getImage(image)
if img == nil {
return
}
if img.deleted {
return
}
cv.activate()
var sx, sy, sw, sh, dx, dy, dw, dh float64
sw, sh = float64(img.w), float64(img.h)
dw, dh = float64(img.w), float64(img.h)
if len(coords) == 2 {
dx, dy = coords[0], coords[1]
} else if len(coords) == 4 {
dx, dy = coords[0], coords[1]
dw, dh = coords[2], coords[3]
} else if len(coords) == 8 {
sx, sy = coords[0], coords[1]
sw, sh = coords[2], coords[3]
dx, dy = coords[4], coords[5]
dw, dh = coords[6], coords[7]
}
sx /= float64(img.w)
sy /= float64(img.h)
sw /= float64(img.w)
sh /= float64(img.h)
p0 := vec{dx, dy}
p1 := vec{dx, dy + dh}
p2 := vec{dx + dw, dy + dh}
p3 := vec{dx + dw, dy}
gli.StencilFunc(gl_EQUAL, 0, 0xFF)
gli.BindBuffer(gl_ARRAY_BUFFER, shadowBuf)
data := [16]float32{float32(p0[0]), float32(p0[1]), float32(p1[0]), float32(p1[1]), float32(p2[0]), float32(p2[1]), float32(p3[0]), float32(p3[1]),
float32(sx), float32(sy), float32(sx), float32(sy + sh), float32(sx + sw), float32(sy + sh), float32(sx + sw), float32(sy)}
gli.BufferData(gl_ARRAY_BUFFER, len(data)*4, unsafe.Pointer(&data[0]), gl_STREAM_DRAW)
gli.ActiveTexture(gl_TEXTURE0)
gli.BindTexture(gl_TEXTURE_2D, img.tex)
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, 0)
gli.VertexAttribPointer(ir.texCoord, 2, gl_FLOAT, false, 0, 8*4)
gli.EnableVertexAttribArray(ir.vertex)
gli.EnableVertexAttribArray(ir.texCoord)
gli.DrawArrays(gl_TRIANGLE_FAN, 0, 4)
gli.DisableVertexAttribArray(ir.vertex)
gli.DisableVertexAttribArray(ir.texCoord)
gli.StencilFunc(gl_ALWAYS, 0, 0xFF)
}

View file

@ -5,63 +5,58 @@ import (
"fmt"
)
type radialGradientShader struct {
type gaussian63Shader struct {
id uint32
vertex uint32
texCoord uint32
canvasSize int32
invmat int32
gradient int32
from int32
to int32
dir int32
radFrom int32
radTo int32
len int32
globalAlpha int32
kernelScale int32
image int32
kernel int32
}
func loadRadialGradientShader() (*radialGradientShader, error) {
func loadGaussian63Shader() (*gaussian63Shader, error) {
var vs, fs, program uint32
{
vs = gli.CreateShader(gl_VERTEX_SHADER)
gli.ShaderSource(vs, radialGradientVS)
gli.ShaderSource(vs, gaussian63VS)
gli.CompileShader(vs)
shLog := gli.GetShaderInfoLog(vs)
if len(shLog) > 0 {
fmt.Printf("VERTEX_SHADER compilation log for radialGradientVS:\n\n%s\n", shLog)
fmt.Printf("VERTEX_SHADER compilation log for gaussian63VS:\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")
return nil, errors.New("Error compiling GL_VERTEX_SHADER shader part for gaussian63VS")
}
if glErr := gli.GetError(); glErr != gl_NO_ERROR {
return nil, errors.New("error compiling shader part for radialGradientVS, glError: " + fmt.Sprint(glErr))
return nil, errors.New("error compiling shader part for gaussian63VS, glError: " + fmt.Sprint(glErr))
}
}
{
fs = gli.CreateShader(gl_FRAGMENT_SHADER)
gli.ShaderSource(fs, radialGradientFS)
gli.ShaderSource(fs, gaussian63FS)
gli.CompileShader(fs)
shLog := gli.GetShaderInfoLog(fs)
if len(shLog) > 0 {
fmt.Printf("FRAGMENT_SHADER compilation log for radialGradientFS:\n\n%s\n", shLog)
fmt.Printf("FRAGMENT_SHADER compilation log for gaussian63FS:\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")
return nil, errors.New("Error compiling GL_FRAGMENT_SHADER shader part for gaussian63FS")
}
if glErr := gli.GetError(); glErr != gl_NO_ERROR {
return nil, errors.New("error compiling shader part for radialGradientFS, glError: " + fmt.Sprint(glErr))
return nil, errors.New("error compiling shader part for gaussian63FS, glError: " + fmt.Sprint(glErr))
}
}
@ -73,7 +68,7 @@ func loadRadialGradientShader() (*radialGradientShader, error) {
shLog := gli.GetProgramInfoLog(program)
if len(shLog) > 0 {
fmt.Printf("Shader link log for radialGradientFS:\n\n%s\n", shLog)
fmt.Printf("Shader link log for gaussian63FS:\n\n%s\n", shLog)
}
var status int32
@ -81,26 +76,21 @@ func loadRadialGradientShader() (*radialGradientShader, error) {
if status != gl_TRUE {
gli.DeleteShader(vs)
gli.DeleteShader(fs)
return nil, errors.New("error linking shader for radialGradientFS")
return nil, errors.New("error linking shader for gaussian63FS")
}
if glErr := gli.GetError(); glErr != gl_NO_ERROR {
return nil, errors.New("error linking shader for radialGradientFS, glError: " + fmt.Sprint(glErr))
return nil, errors.New("error linking shader for gaussian63FS, glError: " + fmt.Sprint(glErr))
}
}
result := &radialGradientShader{}
result := &gaussian63Shader{}
result.id = program
result.vertex = uint32(gli.GetAttribLocation(program, "vertex"))
result.texCoord = uint32(gli.GetAttribLocation(program, "texCoord"))
result.canvasSize = gli.GetUniformLocation(program, "canvasSize")
result.invmat = gli.GetUniformLocation(program, "invmat")
result.gradient = gli.GetUniformLocation(program, "gradient")
result.from = gli.GetUniformLocation(program, "from")
result.to = gli.GetUniformLocation(program, "to")
result.dir = gli.GetUniformLocation(program, "dir")
result.radFrom = gli.GetUniformLocation(program, "radFrom")
result.radTo = gli.GetUniformLocation(program, "radTo")
result.len = gli.GetUniformLocation(program, "len")
result.globalAlpha = gli.GetUniformLocation(program, "globalAlpha")
result.kernelScale = gli.GetUniformLocation(program, "kernelScale")
result.image = gli.GetUniformLocation(program, "image")
result.kernel = gli.GetUniformLocation(program, "kernel")
return result, nil
}
@ -191,190 +181,6 @@ func loadSolidShader() (*solidShader, error) {
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
{
vs = gli.CreateShader(gl_VERTEX_SHADER)
gli.ShaderSource(vs, solidAlphaVS)
gli.CompileShader(vs)
shLog := gli.GetShaderInfoLog(vs)
if len(shLog) > 0 {
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))
}
}
{
fs = gli.CreateShader(gl_FRAGMENT_SHADER)
gli.ShaderSource(fs, solidAlphaFS)
gli.CompileShader(fs)
shLog := gli.GetShaderInfoLog(fs)
if len(shLog) > 0 {
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)
shLog := gli.GetProgramInfoLog(program)
if len(shLog) > 0 {
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, "vertex"))
result.alphaTexCoord = uint32(gli.GetAttribLocation(program, "alphaTexCoord"))
result.canvasSize = gli.GetUniformLocation(program, "canvasSize")
result.color = gli.GetUniformLocation(program, "color")
result.alphaTex = gli.GetUniformLocation(program, "alphaTex")
result.globalAlpha = gli.GetUniformLocation(program, "globalAlpha")
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
{
vs = gli.CreateShader(gl_VERTEX_SHADER)
gli.ShaderSource(vs, linearGradientVS)
gli.CompileShader(vs)
shLog := gli.GetShaderInfoLog(vs)
if len(shLog) > 0 {
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))
}
}
{
fs = gli.CreateShader(gl_FRAGMENT_SHADER)
gli.ShaderSource(fs, linearGradientFS)
gli.CompileShader(fs)
shLog := gli.GetShaderInfoLog(fs)
if len(shLog) > 0 {
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)
shLog := gli.GetProgramInfoLog(program)
if len(shLog) > 0 {
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, "vertex"))
result.canvasSize = gli.GetUniformLocation(program, "canvasSize")
result.invmat = gli.GetUniformLocation(program, "invmat")
result.gradient = gli.GetUniformLocation(program, "gradient")
result.from = gli.GetUniformLocation(program, "from")
result.dir = gli.GetUniformLocation(program, "dir")
result.len = gli.GetUniformLocation(program, "len")
result.globalAlpha = gli.GetUniformLocation(program, "globalAlpha")
return result, nil
}
type linearGradientAlphaShader struct {
id uint32
vertex uint32
@ -577,57 +383,58 @@ func loadRadialGradientAlphaShader() (*radialGradientAlphaShader, error) {
return result, nil
}
type imageShader struct {
type gaussian15Shader struct {
id uint32
vertex uint32
texCoord uint32
canvasSize int32
kernelScale int32
image int32
globalAlpha int32
kernel int32
}
func loadImageShader() (*imageShader, error) {
func loadGaussian15Shader() (*gaussian15Shader, error) {
var vs, fs, program uint32
{
vs = gli.CreateShader(gl_VERTEX_SHADER)
gli.ShaderSource(vs, imageVS)
gli.ShaderSource(vs, gaussian15VS)
gli.CompileShader(vs)
shLog := gli.GetShaderInfoLog(vs)
if len(shLog) > 0 {
fmt.Printf("VERTEX_SHADER compilation log for imageVS:\n\n%s\n", shLog)
fmt.Printf("VERTEX_SHADER compilation log for gaussian15VS:\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 imageVS")
return nil, errors.New("Error compiling GL_VERTEX_SHADER shader part for gaussian15VS")
}
if glErr := gli.GetError(); glErr != gl_NO_ERROR {
return nil, errors.New("error compiling shader part for imageVS, glError: " + fmt.Sprint(glErr))
return nil, errors.New("error compiling shader part for gaussian15VS, glError: " + fmt.Sprint(glErr))
}
}
{
fs = gli.CreateShader(gl_FRAGMENT_SHADER)
gli.ShaderSource(fs, imageFS)
gli.ShaderSource(fs, gaussian15FS)
gli.CompileShader(fs)
shLog := gli.GetShaderInfoLog(fs)
if len(shLog) > 0 {
fmt.Printf("FRAGMENT_SHADER compilation log for imageFS:\n\n%s\n", shLog)
fmt.Printf("FRAGMENT_SHADER compilation log for gaussian15FS:\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 imageFS")
return nil, errors.New("Error compiling GL_FRAGMENT_SHADER shader part for gaussian15FS")
}
if glErr := gli.GetError(); glErr != gl_NO_ERROR {
return nil, errors.New("error compiling shader part for imageFS, glError: " + fmt.Sprint(glErr))
return nil, errors.New("error compiling shader part for gaussian15FS, glError: " + fmt.Sprint(glErr))
}
}
@ -639,7 +446,7 @@ func loadImageShader() (*imageShader, error) {
shLog := gli.GetProgramInfoLog(program)
if len(shLog) > 0 {
fmt.Printf("Shader link log for imageFS:\n\n%s\n", shLog)
fmt.Printf("Shader link log for gaussian15FS:\n\n%s\n", shLog)
}
var status int32
@ -647,20 +454,21 @@ func loadImageShader() (*imageShader, error) {
if status != gl_TRUE {
gli.DeleteShader(vs)
gli.DeleteShader(fs)
return nil, errors.New("error linking shader for imageFS")
return nil, errors.New("error linking shader for gaussian15FS")
}
if glErr := gli.GetError(); glErr != gl_NO_ERROR {
return nil, errors.New("error linking shader for imageFS, glError: " + fmt.Sprint(glErr))
return nil, errors.New("error linking shader for gaussian15FS, glError: " + fmt.Sprint(glErr))
}
}
result := &imageShader{}
result := &gaussian15Shader{}
result.id = program
result.vertex = uint32(gli.GetAttribLocation(program, "vertex"))
result.texCoord = uint32(gli.GetAttribLocation(program, "texCoord"))
result.canvasSize = gli.GetUniformLocation(program, "canvasSize")
result.kernelScale = gli.GetUniformLocation(program, "kernelScale")
result.image = gli.GetUniformLocation(program, "image")
result.globalAlpha = gli.GetUniformLocation(program, "globalAlpha")
result.kernel = gli.GetUniformLocation(program, "kernel")
return result, nil
}
@ -755,6 +563,468 @@ func loadImagePatternShader() (*imagePatternShader, error) {
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
{
vs = gli.CreateShader(gl_VERTEX_SHADER)
gli.ShaderSource(vs, solidAlphaVS)
gli.CompileShader(vs)
shLog := gli.GetShaderInfoLog(vs)
if len(shLog) > 0 {
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))
}
}
{
fs = gli.CreateShader(gl_FRAGMENT_SHADER)
gli.ShaderSource(fs, solidAlphaFS)
gli.CompileShader(fs)
shLog := gli.GetShaderInfoLog(fs)
if len(shLog) > 0 {
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)
shLog := gli.GetProgramInfoLog(program)
if len(shLog) > 0 {
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, "vertex"))
result.alphaTexCoord = uint32(gli.GetAttribLocation(program, "alphaTexCoord"))
result.canvasSize = gli.GetUniformLocation(program, "canvasSize")
result.color = gli.GetUniformLocation(program, "color")
result.alphaTex = gli.GetUniformLocation(program, "alphaTex")
result.globalAlpha = gli.GetUniformLocation(program, "globalAlpha")
return result, nil
}
type gaussian255Shader struct {
id uint32
vertex uint32
texCoord uint32
canvasSize int32
kernelScale int32
image int32
kernel int32
}
func loadGaussian255Shader() (*gaussian255Shader, error) {
var vs, fs, program uint32
{
vs = gli.CreateShader(gl_VERTEX_SHADER)
gli.ShaderSource(vs, gaussian255VS)
gli.CompileShader(vs)
shLog := gli.GetShaderInfoLog(vs)
if len(shLog) > 0 {
fmt.Printf("VERTEX_SHADER compilation log for gaussian255VS:\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 gaussian255VS")
}
if glErr := gli.GetError(); glErr != gl_NO_ERROR {
return nil, errors.New("error compiling shader part for gaussian255VS, glError: " + fmt.Sprint(glErr))
}
}
{
fs = gli.CreateShader(gl_FRAGMENT_SHADER)
gli.ShaderSource(fs, gaussian255FS)
gli.CompileShader(fs)
shLog := gli.GetShaderInfoLog(fs)
if len(shLog) > 0 {
fmt.Printf("FRAGMENT_SHADER compilation log for gaussian255FS:\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 gaussian255FS")
}
if glErr := gli.GetError(); glErr != gl_NO_ERROR {
return nil, errors.New("error compiling shader part for gaussian255FS, glError: " + fmt.Sprint(glErr))
}
}
{
program = gli.CreateProgram()
gli.AttachShader(program, vs)
gli.AttachShader(program, fs)
gli.LinkProgram(program)
shLog := gli.GetProgramInfoLog(program)
if len(shLog) > 0 {
fmt.Printf("Shader link log for gaussian255FS:\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 gaussian255FS")
}
if glErr := gli.GetError(); glErr != gl_NO_ERROR {
return nil, errors.New("error linking shader for gaussian255FS, glError: " + fmt.Sprint(glErr))
}
}
result := &gaussian255Shader{}
result.id = program
result.vertex = uint32(gli.GetAttribLocation(program, "vertex"))
result.texCoord = uint32(gli.GetAttribLocation(program, "texCoord"))
result.canvasSize = gli.GetUniformLocation(program, "canvasSize")
result.kernelScale = gli.GetUniformLocation(program, "kernelScale")
result.image = gli.GetUniformLocation(program, "image")
result.kernel = gli.GetUniformLocation(program, "kernel")
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
globalAlpha int32
}
func loadRadialGradientShader() (*radialGradientShader, error) {
var vs, fs, program uint32
{
vs = gli.CreateShader(gl_VERTEX_SHADER)
gli.ShaderSource(vs, radialGradientVS)
gli.CompileShader(vs)
shLog := gli.GetShaderInfoLog(vs)
if len(shLog) > 0 {
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))
}
}
{
fs = gli.CreateShader(gl_FRAGMENT_SHADER)
gli.ShaderSource(fs, radialGradientFS)
gli.CompileShader(fs)
shLog := gli.GetShaderInfoLog(fs)
if len(shLog) > 0 {
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)
shLog := gli.GetProgramInfoLog(program)
if len(shLog) > 0 {
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, "vertex"))
result.canvasSize = gli.GetUniformLocation(program, "canvasSize")
result.invmat = gli.GetUniformLocation(program, "invmat")
result.gradient = gli.GetUniformLocation(program, "gradient")
result.from = gli.GetUniformLocation(program, "from")
result.to = gli.GetUniformLocation(program, "to")
result.dir = gli.GetUniformLocation(program, "dir")
result.radFrom = gli.GetUniformLocation(program, "radFrom")
result.radTo = gli.GetUniformLocation(program, "radTo")
result.len = gli.GetUniformLocation(program, "len")
result.globalAlpha = gli.GetUniformLocation(program, "globalAlpha")
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
{
vs = gli.CreateShader(gl_VERTEX_SHADER)
gli.ShaderSource(vs, linearGradientVS)
gli.CompileShader(vs)
shLog := gli.GetShaderInfoLog(vs)
if len(shLog) > 0 {
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))
}
}
{
fs = gli.CreateShader(gl_FRAGMENT_SHADER)
gli.ShaderSource(fs, linearGradientFS)
gli.CompileShader(fs)
shLog := gli.GetShaderInfoLog(fs)
if len(shLog) > 0 {
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)
shLog := gli.GetProgramInfoLog(program)
if len(shLog) > 0 {
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, "vertex"))
result.canvasSize = gli.GetUniformLocation(program, "canvasSize")
result.invmat = gli.GetUniformLocation(program, "invmat")
result.gradient = gli.GetUniformLocation(program, "gradient")
result.from = gli.GetUniformLocation(program, "from")
result.dir = gli.GetUniformLocation(program, "dir")
result.len = gli.GetUniformLocation(program, "len")
result.globalAlpha = gli.GetUniformLocation(program, "globalAlpha")
return result, nil
}
type imageShader struct {
id uint32
vertex uint32
texCoord uint32
canvasSize int32
image int32
globalAlpha int32
}
func loadImageShader() (*imageShader, error) {
var vs, fs, program uint32
{
vs = gli.CreateShader(gl_VERTEX_SHADER)
gli.ShaderSource(vs, imageVS)
gli.CompileShader(vs)
shLog := gli.GetShaderInfoLog(vs)
if len(shLog) > 0 {
fmt.Printf("VERTEX_SHADER compilation log for imageVS:\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 imageVS")
}
if glErr := gli.GetError(); glErr != gl_NO_ERROR {
return nil, errors.New("error compiling shader part for imageVS, glError: " + fmt.Sprint(glErr))
}
}
{
fs = gli.CreateShader(gl_FRAGMENT_SHADER)
gli.ShaderSource(fs, imageFS)
gli.CompileShader(fs)
shLog := gli.GetShaderInfoLog(fs)
if len(shLog) > 0 {
fmt.Printf("FRAGMENT_SHADER compilation log for imageFS:\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 imageFS")
}
if glErr := gli.GetError(); glErr != gl_NO_ERROR {
return nil, errors.New("error compiling shader part for imageFS, glError: " + fmt.Sprint(glErr))
}
}
{
program = gli.CreateProgram()
gli.AttachShader(program, vs)
gli.AttachShader(program, fs)
gli.LinkProgram(program)
shLog := gli.GetProgramInfoLog(program)
if len(shLog) > 0 {
fmt.Printf("Shader link log for imageFS:\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 imageFS")
}
if glErr := gli.GetError(); glErr != gl_NO_ERROR {
return nil, errors.New("error linking shader for imageFS, glError: " + fmt.Sprint(glErr))
}
}
result := &imageShader{}
result.id = program
result.vertex = uint32(gli.GetAttribLocation(program, "vertex"))
result.texCoord = uint32(gli.GetAttribLocation(program, "texCoord"))
result.canvasSize = gli.GetUniformLocation(program, "canvasSize")
result.image = gli.GetUniformLocation(program, "image")
result.globalAlpha = gli.GetUniformLocation(program, "globalAlpha")
return result, nil
}
type imagePatternAlphaShader struct {
id uint32
vertex uint32

View file

@ -116,9 +116,12 @@ func shaderFindInputVariables(source string) []ShaderInput {
if !isAttrib && !isUniform {
continue
}
for i := 2; i < len(parts); i++ {
for _, part := range parts[2:] {
if idx := strings.IndexByte(part, '['); idx >= 0 {
part = part[:idx]
}
inputs = append(inputs, ShaderInput{
Name: parts[i],
Name: part,
IsAttrib: isAttrib,
IsUniform: isUniform})
}

View file

@ -844,6 +844,7 @@ type GL interface {
TexParameteri(target uint32, pname uint32, param int32)
TexSubImage2D(target uint32, level int32, xoffset int32, yoffset int32, width int32, height int32, format uint32, xtype uint32, pixels unsafe.Pointer)
Uniform1f(location int32, v0 float32)
Uniform1fv(location int32, count int32, v *float32)
Uniform1i(location int32, v0 int32)
Uniform2f(location int32, v0 float32, v1 float32)
Uniform4f(location int32, v0 float32, v1 float32, v2 float32, v3 float32)

View file

@ -1,5 +1,11 @@
package canvas
import (
"bytes"
"fmt"
"strings"
)
var imageVS = `
attribute vec2 vertex, texCoord;
uniform vec2 canvasSize;
@ -274,3 +280,94 @@ void main() {
col.a *= texture2D(alphaTex, v_atc).a * globalAlpha;
gl_FragColor = col;
}`
var gaussian15VS = `
attribute vec2 vertex, texCoord;
uniform vec2 canvasSize;
varying vec2 v_texCoord;
void main() {
v_texCoord = texCoord;
vec2 glp = vertex * 2.0 / canvasSize - 1.0;
gl_Position = vec4(glp.x, -glp.y, 0.0, 1.0);
}`
var gaussian15FS = `
#ifdef GL_ES
precision mediump float;
#endif
varying vec2 v_texCoord;
uniform vec2 kernelScale;
uniform sampler2D image;
uniform float kernel[15];
void main() {
vec4 color = vec4(0.0, 0.0, 0.0, 0.0);
_SUM_
gl_FragColor = color;
}`
var gaussian63VS = `
attribute vec2 vertex, texCoord;
uniform vec2 canvasSize;
varying vec2 v_texCoord;
void main() {
v_texCoord = texCoord;
vec2 glp = vertex * 2.0 / canvasSize - 1.0;
gl_Position = vec4(glp.x, -glp.y, 0.0, 1.0);
}`
var gaussian63FS = `
#ifdef GL_ES
precision mediump float;
#endif
varying vec2 v_texCoord;
uniform vec2 kernelScale;
uniform sampler2D image;
uniform float kernel[63];
void main() {
vec4 color = vec4(0.0, 0.0, 0.0, 0.0);
_SUM_
gl_FragColor = color;
}`
var gaussian255VS = `
attribute vec2 vertex, texCoord;
uniform vec2 canvasSize;
varying vec2 v_texCoord;
void main() {
v_texCoord = texCoord;
vec2 glp = vertex * 2.0 / canvasSize - 1.0;
gl_Position = vec4(glp.x, -glp.y, 0.0, 1.0);
}`
var gaussian255FS = `
#ifdef GL_ES
precision mediump float;
#endif
varying vec2 v_texCoord;
uniform vec2 kernelScale;
uniform sampler2D image;
uniform float kernel[255];
void main() {
vec4 color = vec4(0.0, 0.0, 0.0, 0.0);
_SUM_
gl_FragColor = color;
}`
func init() {
fstr := "\tcolor += texture2D(image, v_texCoord + vec2(%.1f * kernelScale.x, %.1f * kernelScale.y)) * kernel[%d];\n"
bb := bytes.Buffer{}
for i := 0; i < 255; i++ {
off := float64(i) - 127
fmt.Fprintf(&bb, fstr, off, off, i)
}
gaussian255FS = strings.Replace(gaussian255FS, "_SUM_", bb.String(), -1)
bb.Reset()
for i := 0; i < 63; i++ {
off := float64(i) - 31
fmt.Fprintf(&bb, fstr, off, off, i)
}
gaussian63FS = strings.Replace(gaussian63FS, "_SUM_", bb.String(), -1)
bb.Reset()
for i := 0; i < 15; i++ {
off := float64(i) - 7
fmt.Fprintf(&bb, fstr, off, off, i)
}
gaussian15FS = strings.Replace(gaussian15FS, "_SUM_", bb.String(), -1)
}

View file

@ -2,6 +2,7 @@ package canvas
import (
"image"
"math"
"unsafe"
)
@ -10,6 +11,12 @@ func (cv *Canvas) drawShadow(tris []float32) {
return
}
if cv.state.shadowBlur > 0 {
cv.enableTextureRenderTarget(&offscr1)
gli.ClearColor(0, 0, 0, 0)
gli.Clear(gl_COLOR_BUFFER_BIT | gl_STENCIL_BUFFER_BIT)
}
ox, oy := float32(cv.state.shadowOffsetX), float32(cv.state.shadowOffsetY)
count := len(tris)
@ -53,12 +60,22 @@ func (cv *Canvas) drawShadow(tris []float32) {
gli.Clear(gl_STENCIL_BUFFER_BIT)
gli.StencilMask(0xFF)
if cv.state.shadowBlur > 0 {
cv.drawBlurredShadow()
}
}
func (cv *Canvas) drawTextShadow(offset image.Point, strWidth, strHeight int, x, y float64) {
x += cv.state.shadowOffsetX
y += cv.state.shadowOffsetY
if cv.state.shadowBlur > 0 {
cv.enableTextureRenderTarget(&offscr1)
gli.ClearColor(0, 0, 0, 0)
gli.Clear(gl_COLOR_BUFFER_BIT | gl_STENCIL_BUFFER_BIT)
}
gli.StencilFunc(gl_EQUAL, 0, 0xFF)
gli.BindBuffer(gl_ARRAY_BUFFER, buf)
@ -92,4 +109,93 @@ func (cv *Canvas) drawTextShadow(offset image.Point, strWidth, strHeight int, x,
gli.ActiveTexture(gl_TEXTURE0)
gli.StencilFunc(gl_ALWAYS, 0, 0xFF)
if cv.state.shadowBlur > 0 {
cv.drawBlurredShadow()
}
}
func (cv *Canvas) drawBlurredShadow() {
gli.BlendFunc(gl_ONE, gl_ONE_MINUS_SRC_ALPHA)
var kernel [255]float32
gaussianKernel(cv.state.shadowBlur, kernel[:])
cv.enableTextureRenderTarget(&offscr2)
gli.ClearColor(0, 0, 0, 0)
gli.Clear(gl_COLOR_BUFFER_BIT | gl_STENCIL_BUFFER_BIT)
gli.StencilFunc(gl_EQUAL, 0, 0xFF)
gli.BindBuffer(gl_ARRAY_BUFFER, shadowBuf)
data := [16]float32{0, 0, 0, float32(cv.h), float32(cv.w), float32(cv.h), float32(cv.w), 0, 0, 0, 0, 1, 1, 1, 1, 0}
gli.BufferData(gl_ARRAY_BUFFER, len(data)*4, unsafe.Pointer(&data[0]), gl_STREAM_DRAW)
gli.ActiveTexture(gl_TEXTURE0)
gli.BindTexture(gl_TEXTURE_2D, offscr1.tex)
gli.UseProgram(gauss255r.id)
gli.Uniform1i(gauss255r.image, 0)
gli.Uniform2f(gauss255r.canvasSize, float32(cv.fw), float32(cv.fh))
gli.Uniform2f(gauss255r.kernelScale, 1.0/float32(cv.fw), 0.0)
gli.Uniform1fv(gauss255r.kernel, int32(len(kernel)), &kernel[0])
gli.VertexAttribPointer(gauss255r.vertex, 2, gl_FLOAT, false, 0, 0)
gli.VertexAttribPointer(gauss255r.texCoord, 2, gl_FLOAT, false, 0, 8*4)
gli.EnableVertexAttribArray(gauss255r.vertex)
gli.EnableVertexAttribArray(gauss255r.texCoord)
gli.DrawArrays(gl_TRIANGLE_FAN, 0, 4)
gli.DisableVertexAttribArray(gauss255r.vertex)
gli.DisableVertexAttribArray(gauss255r.texCoord)
gli.StencilFunc(gl_ALWAYS, 0, 0xFF)
cv.disableTextureRenderTarget()
gli.StencilFunc(gl_EQUAL, 0, 0xFF)
gli.BindBuffer(gl_ARRAY_BUFFER, shadowBuf)
data = [16]float32{0, 0, 0, float32(cv.h), float32(cv.w), float32(cv.h), float32(cv.w), 0, 0, 0, 0, 1, 1, 1, 1, 0}
gli.BufferData(gl_ARRAY_BUFFER, len(data)*4, unsafe.Pointer(&data[0]), gl_STREAM_DRAW)
gli.ActiveTexture(gl_TEXTURE0)
gli.BindTexture(gl_TEXTURE_2D, offscr2.tex)
gli.UseProgram(gauss255r.id)
gli.Uniform1i(gauss255r.image, 0)
gli.Uniform2f(gauss255r.canvasSize, float32(cv.fw), float32(cv.fh))
gli.Uniform2f(gauss255r.kernelScale, 0.0, 1.0/float32(cv.fh))
gli.Uniform1fv(gauss255r.kernel, int32(len(kernel)), &kernel[0])
gli.VertexAttribPointer(gauss255r.vertex, 2, gl_FLOAT, false, 0, 0)
gli.VertexAttribPointer(gauss255r.texCoord, 2, gl_FLOAT, false, 0, 8*4)
gli.EnableVertexAttribArray(gauss255r.vertex)
gli.EnableVertexAttribArray(gauss255r.texCoord)
gli.DrawArrays(gl_TRIANGLE_FAN, 0, 4)
gli.DisableVertexAttribArray(gauss255r.vertex)
gli.DisableVertexAttribArray(gauss255r.texCoord)
gli.StencilFunc(gl_ALWAYS, 0, 0xFF)
gli.BlendFunc(gl_SRC_ALPHA, gl_ONE_MINUS_SRC_ALPHA)
}
func gaussianKernel(stddev float64, target []float32) {
stddevSqr := stddev * stddev
center := float64(len(target) / 2)
factor := 1.0 / math.Sqrt(2*math.Pi*stddevSqr)
for i := range target {
x := float64(i) - center
target[i] = float32(factor * math.Pow(math.E, -x*x/(2*stddevSqr)))
}
normalizeKernel(target)
}
func normalizeKernel(kernel []float32) {
var sum float32
for _, v := range kernel {
sum += v
}
factor := 1.0 / sum
for i := range kernel {
kernel[i] *= factor
}
}

View file

@ -220,13 +220,16 @@ func (cv *Canvas) FillText(str string, x, y float64) {
gli.DisableVertexAttribArray(vertex)
gli.DisableVertexAttribArray(alphaTexCoord)
gli.ActiveTexture(gl_TEXTURE0)
gli.ActiveTexture(gl_TEXTURE1)
gli.BindTexture(gl_TEXTURE_2D, alphaTex)
gli.StencilFunc(gl_ALWAYS, 0, 0xFF)
for y := 0; y < strHeight; y++ {
gli.TexSubImage2D(gl_TEXTURE_2D, 0, 0, int32(alphaTexSize-1-y), int32(strWidth), 1, gl_ALPHA, gl_UNSIGNED_BYTE, gli.Ptr(&zeroes[0]))
}
gli.ActiveTexture(gl_TEXTURE0)
}
// TextMetrics is the result of a MeasureText call