// newFBO will generate a new Frame Buffer Object for use with the canvas func newFBO(texture gl.Texture) (gl.Framebuffer, uint32) { // get currently bound fbo to reset to it later current_fbo := gl.GetBoundFramebuffer() framebuffer := gl.CreateFramebuffer() gl.BindFramebuffer(gl.FRAMEBUFFER, framebuffer) if texture.Valid() { gl.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0) // Initialize the texture to transparent black. gl.ClearColor(0.0, 0.0, 0.0, 0.0) gl.Clear(gl.COLOR_BUFFER_BIT) } status := gl.CheckFramebufferStatus(gl.FRAMEBUFFER) // unbind framebuffer gl.BindFramebuffer(gl.FRAMEBUFFER, current_fbo) return framebuffer, uint32(status) }
// StencilExt operates like stencil but with access to change the stencil action, // value, and keepvalues. // // action: How to modify any stencil values of pixels that are touched by what's // drawn in the stencil function. // // value: The new stencil value to use for pixels if the "replace" stencil action // is used. Has no effect with other stencil actions. Must be between 0 and 255. // // keepvalues: True to preserve old stencil values of pixels, false to re-set // every pixel's stencil value to 0 before executing the stencil function. Clear // will also re-set all stencil values. func StencilExt(stencil_func func(), action StencilAction, value int32, keepvalues bool) { gl_state.writingToStencil = true if !keepvalues { gl.Clear(gl.STENCIL_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) } if gl_state.currentCanvas != nil { gl_state.currentCanvas.checkCreateStencil() } gl.Enable(gl.STENCIL_TEST) gl.ColorMask(false, false, false, false) gl.StencilFunc(gl.ALWAYS, int(value), 0xFF) gl.StencilOp(gl.KEEP, gl.KEEP, gl.Enum(action)) stencil_func() gl_state.writingToStencil = false SetColorMask(states.back().colorMask) SetStencilTest(states.back().stencilCompare, states.back().stencilTestValue) }
// checkCreateStencil if a stencil is set on a canvas then we need to create // some buffers to handle this. func (canvas *Canvas) checkCreateStencil() bool { // Do nothing if we've already created the stencil buffer. if canvas.depth_stencil.Valid() { return true } if gl_state.currentCanvas != canvas { gl.BindFramebuffer(gl.FRAMEBUFFER, canvas.fbo) } format := gl.STENCIL_INDEX8 attachment := gl.STENCIL_ATTACHMENT canvas.depth_stencil = gl.CreateRenderbuffer() gl.BindRenderbuffer(gl.RENDERBUFFER, canvas.depth_stencil) gl.RenderbufferStorage(gl.RENDERBUFFER, gl.Enum(format), int(canvas.width), int(canvas.height)) // Attach the stencil buffer to the framebuffer object. gl.FramebufferRenderbuffer(gl.FRAMEBUFFER, gl.Enum(attachment), gl.RENDERBUFFER, canvas.depth_stencil) gl.BindRenderbuffer(gl.RENDERBUFFER, gl.Renderbuffer{}) success := (gl.CheckFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) // We don't want the stencil buffer filled with garbage. if success { gl.Clear(gl.STENCIL_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) } else { gl.DeleteRenderbuffer(canvas.depth_stencil) canvas.depth_stencil = gl.Renderbuffer{} } if gl_state.currentCanvas != nil && gl_state.currentCanvas != canvas { gl.BindFramebuffer(gl.FRAMEBUFFER, gl_state.currentCanvas.fbo) } else if gl_state.currentCanvas == nil { gl.BindFramebuffer(gl.FRAMEBUFFER, getDefaultFBO()) } return success }
// Clear will clear everything already rendered to the screen and set is all to // the *Color provided. func ClearC(c *Color) { gl.ClearColor(c[0], c[1], c[2], c[3]) gl.Clear(gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) }