func (c *glContext) stroke(call *glCall) { paths := c.paths[call.pathOffset : call.pathOffset+call.pathCount] if c.flags&StencilStrokes != 0 { gl.Enable(gl.STENCIL_TEST) c.setStencilMask(0xff) // Fill the stroke base without overlap c.setStencilFunc(gl.EQUAL, 0x00, 0xff) gl.StencilOp(gl.KEEP, gl.KEEP, gl.INCR) c.setUniforms(call.uniformOffset+1, call.image) checkError(c, "stroke fill 0") for i := range paths { path := &paths[i] gl.DrawArrays(gl.TRIANGLE_STRIP, path.strokeOffset, path.strokeCount) } // Draw anti-aliased pixels. c.setUniforms(call.uniformOffset, call.image) c.setStencilFunc(gl.EQUAL, 0x00, 0xff) gl.StencilOp(gl.KEEP, gl.KEEP, gl.KEEP) for i := range paths { path := &paths[i] gl.DrawArrays(gl.TRIANGLE_STRIP, path.strokeOffset, path.strokeCount) } // Clear stencil buffer. gl.ColorMask(false, false, false, false) c.setStencilFunc(gl.ALWAYS, 0x00, 0xff) gl.StencilOp(gl.ZERO, gl.ZERO, gl.ZERO) checkError(c, "stroke fill 1") for i := range paths { path := &paths[i] gl.DrawArrays(gl.TRIANGLE_STRIP, path.strokeOffset, path.strokeCount) } gl.ColorMask(true, true, true, true) gl.Disable(gl.STENCIL_TEST) } else { c.setUniforms(call.uniformOffset, call.image) checkError(c, "stroke fill") for i := range paths { path := &paths[i] gl.DrawArrays(gl.TRIANGLE_STRIP, path.strokeOffset, path.strokeCount) } } }
func (c *glContext) fill(call *glCall) { pathSentinel := call.pathOffset + call.pathCount // Draw shapes gl.Enable(gl.STENCIL_TEST) c.setStencilMask(0xff) c.setStencilFunc(gl.ALWAYS, 0x00, 0xff) gl.ColorMask(false, false, false, false) // set bindpoint for solid loc c.setUniforms(call.uniformOffset, 0) checkError(c, "fill simple") gl.StencilOpSeparate(gl.FRONT, gl.KEEP, gl.KEEP, gl.INCR_WRAP) gl.StencilOpSeparate(gl.BACK, gl.KEEP, gl.KEEP, gl.DECR_WRAP) gl.Disable(gl.CULL_FACE) for i := call.pathOffset; i < pathSentinel; i++ { path := &c.paths[i] gl.DrawArrays(gl.TRIANGLE_FAN, path.fillOffset, path.fillCount) } gl.Enable(gl.CULL_FACE) // Draw anti-aliased pixels gl.ColorMask(true, true, true, true) c.setUniforms(call.uniformOffset+1, call.image) if c.flags&AntiAlias != 0 { c.setStencilFunc(gl.EQUAL, 0x00, 0xff) gl.StencilOp(gl.KEEP, gl.KEEP, gl.KEEP) // Draw fringes for i := call.pathOffset; i < pathSentinel; i++ { path := &c.paths[i] gl.DrawArrays(gl.TRIANGLE_STRIP, path.strokeOffset, path.strokeCount) } } // Draw fill c.setStencilFunc(gl.NOTEQUAL, 0x00, 0xff) gl.StencilOp(gl.ZERO, gl.ZERO, gl.ZERO) gl.DrawArrays(gl.TRIANGLES, call.triangleOffset, call.triangleCount) gl.Disable(gl.STENCIL_TEST) }
func (p *glParams) renderFlush() { c := p.context if len(c.calls) > 0 { gl.UseProgram(c.shader.program) gl.BlendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA) gl.Enable(gl.CULL_FACE) gl.CullFace(gl.BACK) gl.FrontFace(gl.CCW) gl.Enable(gl.BLEND) gl.Disable(gl.DEPTH_TEST) gl.Disable(gl.SCISSOR_TEST) gl.ColorMask(true, true, true, true) gl.StencilMask(0xffffffff) gl.StencilOp(gl.KEEP, gl.KEEP, gl.KEEP) gl.StencilFunc(gl.ALWAYS, 0, 0xffffffff) gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, gl.Texture{}) c.stencilMask = 0xffffffff c.stencilFunc = gl.ALWAYS c.stencilFuncRef = 0 c.stencilFuncMask = 0xffffffff b := castFloat32ToByte(c.vertexes) //dumpLog("vertex:", c.vertexes) // Upload vertex data gl.BindBuffer(gl.ARRAY_BUFFER, c.vertexBuffer) gl.BufferData(gl.ARRAY_BUFFER, b, gl.STREAM_DRAW) gl.EnableVertexAttribArray(c.shader.vertexAttrib) gl.EnableVertexAttribArray(c.shader.tcoordAttrib) gl.VertexAttribPointer(c.shader.vertexAttrib, 2, gl.FLOAT, false, 4*4, 0) gl.VertexAttribPointer(c.shader.tcoordAttrib, 2, gl.FLOAT, false, 4*4, 8) // Set view and texture just once per frame. gl.Uniform1i(c.shader.locations[glnvgLocTEX], 0) gl.Uniform2fv(c.shader.locations[glnvgLocVIEWSIZE], c.view[:]) for i := range c.calls { call := &c.calls[i] switch call.callType { case glnvgFILL: c.fill(call) case glnvgCONVEXFILL: c.convexFill(call) case glnvgSTROKE: c.stroke(call) case glnvgTRIANGLES: c.triangles(call) } } gl.DisableVertexAttribArray(c.shader.vertexAttrib) gl.DisableVertexAttribArray(c.shader.tcoordAttrib) gl.Disable(gl.CULL_FACE) gl.BindBuffer(gl.ARRAY_BUFFER, gl.Buffer{}) gl.UseProgram(gl.Program{}) c.bindTexture(nil) } c.vertexes = c.vertexes[:0] c.paths = c.paths[:0] c.calls = c.calls[:0] c.uniforms = c.uniforms[:0] }