// SetBlendMode sets the blending mode. Blending modes are different ways to do // color blending. See BlendMode constants to see how they operate. func SetBlendMode(mode BlendMode) { fn := gl.FUNC_ADD srcRGB := gl.ONE srcA := gl.ONE dstRGB := gl.ZERO dstA := gl.ZERO switch mode { case BLENDMODE_ALPHA: srcRGB = gl.SRC_ALPHA srcA = gl.ONE dstRGB = gl.ONE_MINUS_SRC_ALPHA dstA = gl.ONE_MINUS_SRC_ALPHA case BLENDMODE_MULTIPLICATIVE: srcRGB = gl.DST_COLOR srcA = gl.DST_COLOR dstRGB = gl.ZERO dstA = gl.ZERO case BLENDMODE_PREMULTIPLIED: srcRGB = gl.ONE srcA = gl.ONE dstRGB = gl.ONE_MINUS_SRC_ALPHA dstA = gl.ONE_MINUS_SRC_ALPHA case BLENDMODE_SUBTRACTIVE: fn = gl.FUNC_REVERSE_SUBTRACT case BLENDMODE_ADDITIVE: srcRGB = gl.SRC_ALPHA srcA = gl.SRC_ALPHA dstRGB = gl.ONE dstA = gl.ONE case BLENDMODE_SCREEN: srcRGB = gl.ONE srcA = gl.ONE dstRGB = gl.ONE_MINUS_SRC_COLOR dstA = gl.ONE_MINUS_SRC_COLOR break case BLENDMODE_REPLACE: srcRGB = gl.ONE srcA = gl.ONE dstRGB = gl.ZERO dstA = gl.ZERO } gl.BlendEquation(gl.Enum(fn)) gl.BlendFuncSeparate(gl.Enum(srcRGB), gl.Enum(dstRGB), gl.Enum(srcA), gl.Enum(dstA)) states.back().blend_mode = mode }
// Draw satisfies the Drawable interface. Inputs are as follows // x, y, r, sx, sy, ox, oy, kx, ky // x, y are position // r is rotation // sx, sy is the scale, if sy is not given sy will equal sx // ox, oy are offset // kx, ky are the shear. If ky is not given ky will equal kx func (mesh *Mesh) Draw(args ...float32) { prepareDraw(generateModelMatFromArgs(args)) mesh.bindTexture() mesh.bindEnabledAttributes() min, max := mesh.GetDrawRange() if mesh.ibo != nil && mesh.elementCount > 0 { mesh.ibo.drawElements(uint32(mesh.mode), min, max-min+1) } else { gl.DrawArrays(gl.Enum(mesh.mode), min, max-min+1) } }
// setTextureUnit activates a texture unit func setTextureUnit(textureunit int) error { if textureunit < 0 || textureunit >= len(gl_state.boundTextures) { return fmt.Errorf("Invalid texture unit index (%v).", textureunit) } if textureunit != gl_state.curTextureUnit { gl.ActiveTexture(gl.Enum(gl.TEXTURE0 + uint32(textureunit))) } gl_state.curTextureUnit = textureunit return nil }
// 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 }
// 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) }
// SetStencilTest configures or disables stencil testing. When stencil testing is // enabled, the geometry of everything that is drawn afterward will be clipped/stencilled // out based on a comparison between the arguments of this function and the stencil // value of each pixel that the geometry touches. The stencil values of pixels are // affected via Stencil/StencilEXT. func SetStencilTest(compare CompareMode, value int32) { if gl_state.writingToStencil { return } states.back().stencilCompare = compare states.back().stencilTestValue = value if compare == COMPARE_ALWAYS { gl.Disable(gl.STENCIL_TEST) return } if gl_state.currentCanvas != nil { gl_state.currentCanvas.checkCreateStencil() } gl.Enable(gl.STENCIL_TEST) gl.StencilFunc(gl.Enum(compare), int(value), 0xFF) gl.StencilOp(gl.KEEP, gl.KEEP, gl.REPLACE) }
// InitContext will initiate the opengl context with a viewport in the size of // w x h. This is generally called from the game loop and wont generally need to // be called unless you are rolling your own game loop. func InitContext(w, h int32) { if gl_state.initialized { return } // Okay, setup OpenGL. gl.ContextWatcher.OnMakeCurrent(nil) //Get system info opengl_version = gl.GetString(gl.VERSION) opengl_vendor = gl.GetString(gl.VENDOR) gl_state.defaultFBO = gl.GetBoundFramebuffer() gl.GetIntegerv(gl.VIEWPORT, gl_state.viewport) // And the current scissor - but we need to compensate for GL scissors // starting at the bottom left instead of top left. gl.GetIntegerv(gl.SCISSOR_BOX, states.back().scissorBox) states.back().scissorBox[1] = gl_state.viewport[3] - (states.back().scissorBox[1] + states.back().scissorBox[3]) initMaxValues() //check shim code glcolor := []float32{1.0, 1.0, 1.0, 1.0} gl.VertexAttrib4fv(attrib_color, glcolor) gl.VertexAttrib4fv(attrib_constantcolor, glcolor) useVertexAttribArrays(0) // Enable blending gl.Enable(gl.BLEND) SetBlendMode(BLENDMODE_ALPHA) // Auto-generated mipmaps should be the best quality possible gl.Hint(gl.GENERATE_MIPMAP_HINT, gl.NICEST) // Make sure antialiasing works when set elsewhere enableMultisample() //check shim code // Set pixel row alignment gl.PixelStorei(gl.UNPACK_ALIGNMENT, 1) //default matricies gl_state.projectionStack = matstack.NewMatStack() gl_state.viewStack = matstack.NewMatStack() //stacks are initialized with ident matricies on top SetViewportSize(w, h) SetBackgroundColor(0, 0, 0, 255) gl_state.boundTextures = make([]gl.Texture, maxTextureUnits) curgltextureunit := gl.GetInteger(gl.ACTIVE_TEXTURE) gl_state.curTextureUnit = int(curgltextureunit - gl.TEXTURE0) // Retrieve currently bound textures for each texture unit. for i := 0; i < len(gl_state.boundTextures); i++ { gl.ActiveTexture(gl.Enum(gl.TEXTURE0 + uint32(i))) gl_state.boundTextures[i] = gl.Texture{Value: uint32(gl.GetInteger(gl.TEXTURE_BINDING_2D))} } gl.ActiveTexture(gl.Enum(curgltextureunit)) createDefaultTexture() setTextureUnit(0) // We always need a default shader. defaultShader = NewShader() gl_state.initialized = true loadAllVolatile() //have to set this after loadallvolatile() so we are sure the default shader is loaded SetShader(nil) }
func (buffer *indexBuffer) drawElementsLocal(mode uint32, offset, size int) { gl.DrawElements(gl.Enum(mode), size, gl.UNSIGNED_INT, gl.Ptr(&buffer.data[offset])) }
func (buffer *indexBuffer) drawElements(mode uint32, offset, size int) { buffer.bind() defer buffer.unbind() gl.DrawElements(gl.Enum(mode), size, gl.UNSIGNED_INT, gl.PtrOffset(offset*4)) }