From 6f7459956795f6a77121681631153d390e5f78b3 Mon Sep 17 00:00:00 2001 From: Thomas Friedel Date: Wed, 31 Oct 2018 12:30:39 +0100 Subject: [PATCH] added an offscreen canvas --- canvas.go | 36 +++++++++++++++++++++++--- images.go | 77 ++++++++++--------------------------------------------- 2 files changed, 45 insertions(+), 68 deletions(-) diff --git a/canvas.go b/canvas.go index cc63f60..2d7815d 100644 --- a/canvas.go +++ b/canvas.go @@ -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) { - cv.x, cv.y = x, y + if !cv.offscreen { + cv.x, cv.y = x, y + cv.fx, cv.fy = float64(x), float64(y) + } cv.w, cv.h = w, h - cv.fx, cv.fy = float64(x), float64(y) 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() { - gli.Viewport(int32(cv.x), int32(cv.y), int32(cv.w), int32(cv.h)) + 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() { - gli.BindFramebuffer(gl_FRAMEBUFFER, 0) + if cv.offscreen { + cv.enableTextureRenderTarget(&cv.offscrBuf) + } else { + gli.BindFramebuffer(gl_FRAMEBUFFER, 0) + } } // SetLineWidth sets the line width for any line drawing calls diff --git a/images.go b/images.go index 6c63c62..a791000 100644 --- a/images.go +++ b/images.go @@ -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) -}