added an offscreen canvas

This commit is contained in:
Thomas Friedel 2018-10-31 12:30:39 +01:00
parent d7513ddf4d
commit 6f74599567
2 changed files with 45 additions and 68 deletions

View file

@ -24,6 +24,10 @@ type Canvas struct {
state drawState
stateStack []drawState
offscreen bool
offscrBuf offscreenBuffer
offscrImg Image
}
type drawState struct {
@ -118,6 +122,15 @@ func New(x, y, w, h int) *Canvas {
return cv
}
// NewOffscreen creates a new canvas with the given size. It
// does not render directly to the screen but renders to a
// texture instead
func NewOffscreen(w, h int) *Canvas {
cv := New(0, 0, w, h)
cv.offscreen = true
return cv
}
// SetSize changes the internal size of the canvas. This would
// usually be called for example when the window is resized
//
@ -131,9 +144,11 @@ func (cv *Canvas) SetSize(w, h int) {
// SetBounds updates the bounds of the canvas. This would
// usually be called for example when the window is resized
func (cv *Canvas) SetBounds(x, y, w, h int) {
if !cv.offscreen {
cv.x, cv.y = x, y
cv.w, cv.h = w, h
cv.fx, cv.fy = float64(x), float64(y)
}
cv.w, cv.h = w, h
cv.fw, cv.fh = float64(w), float64(h)
activeCanvas = nil
}
@ -155,7 +170,16 @@ func (cv *Canvas) tf(v vec) vec {
// Activate makes the canvas active and sets the viewport. Only needs
// to be called if any other GL code changes the viewport
func (cv *Canvas) Activate() {
if cv.offscreen {
gli.Viewport(0, 0, int32(cv.w), int32(cv.h))
cv.enableTextureRenderTarget(&cv.offscrBuf)
cv.offscrImg.w = cv.offscrBuf.w
cv.offscrImg.h = cv.offscrBuf.h
cv.offscrImg.tex = cv.offscrBuf.tex
} else {
gli.Viewport(int32(cv.x), int32(cv.y), int32(cv.w), int32(cv.h))
cv.disableTextureRenderTarget()
}
cv.applyScissor()
gli.Clear(gl_STENCIL_BUFFER_BIT)
}
@ -609,7 +633,11 @@ func (cv *Canvas) enableTextureRenderTarget(offscr *offscreenBuffer) {
}
func (cv *Canvas) disableTextureRenderTarget() {
if cv.offscreen {
cv.enableTextureRenderTarget(&cv.offscrBuf)
} else {
gli.BindFramebuffer(gl_FRAMEBUFFER, 0)
}
}
// SetLineWidth sets the line width for any line drawing calls

View file

@ -275,7 +275,14 @@ func (img *Image) Replace(src interface{}) {
// Where dx/dy/dw/dh are the destination coordinates and sx/sy/sw/sh are the
// source coordinates
func (cv *Canvas) DrawImage(image interface{}, coords ...float64) {
img := getImage(image)
var img *Image
var flip bool
if cv2, ok := image.(*Canvas); ok && cv2.offscreen {
img = &cv2.offscrImg
flip = true
} else {
img = getImage(image)
}
if img == nil {
return
@ -302,6 +309,11 @@ func (cv *Canvas) DrawImage(image interface{}, coords ...float64) {
dw, dh = coords[6], coords[7]
}
if flip {
dy += dh
dh = -dh
}
sx /= float64(img.w)
sy /= float64(img.h)
sw /= float64(img.w)
@ -354,66 +366,3 @@ 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)
}