func (polyline *polyLine) drawTriangles(is_looping bool) { var overdraw []mgl32.Vec2 if polyline.overdraw { overdraw = polyline.renderOverdraw(is_looping) } numindices := int(math.Max(float64(len(polyline.vertices)/4), float64(len(overdraw)/4))) indices := newAltQuadIndices(numindices) prepareDraw(nil) bindTexture(gl_state.defaultTexture) useVertexAttribArrays(attribflag_pos) gl.VertexAttribPointer(attrib_pos, 2, gl.FLOAT, false, 0, gl.Ptr(polyline.vertices)) gl.DrawElements(gl.TRIANGLES, (len(polyline.vertices)/4)*6, gl.UNSIGNED_SHORT, gl.Ptr(indices)) if polyline.overdraw { c := GetColor() colors := polyline.generateColorArray(len(overdraw), c) useVertexAttribArrays(attribflag_pos | attribflag_color) gl.VertexAttribPointer(attrib_color, 4, gl.UNSIGNED_BYTE, true, 0, gl.Ptr(colors)) gl.VertexAttribPointer(attrib_pos, 2, gl.FLOAT, false, 0, gl.Ptr(overdraw)) gl.DrawElements(gl.TRIANGLES, (len(overdraw)/4)*6, gl.UNSIGNED_SHORT, gl.Ptr(indices)) SetColorC(c) } indices.Release() }
// drawv will take in verticies from the public draw calls and draw the texture // with the verticies and the model matrix func (texture *Texture) drawv(model *mgl32.Mat4, vertices []float32) { prepareDraw(model) bindTexture(texture.getHandle()) useVertexAttribArrays(attribflag_pos | attribflag_texcoord) gl.VertexAttribPointer(attrib_pos, 2, gl.FLOAT, false, 4*4, gl.Ptr(vertices)) gl.VertexAttribPointer(attrib_texcoord, 2, gl.FLOAT, false, 4*4, gl.Ptr(&vertices[2])) gl.DrawArrays(gl.TRIANGLE_STRIP, 0, 4) }
// Point will draw a point on the screen at x, y position. The size of the point // is dependant on the point size set with SetPointSize. func Point(x, y float32) { prepareDraw(nil) bindTexture(gl_state.defaultTexture) useVertexAttribArrays(attribflag_pos) gl.VertexAttribPointer(attrib_pos, 2, gl.FLOAT, false, 0, gl.Ptr([]float32{x, y})) gl.DrawArrays(gl.POINTS, 0, 1) }
// Circlep will draw a circle at x, y with a radius as specified. // radiusx and radiusy will specify how much the width will be along those axis // points specifies how many points should be generated in the arc. // If it is lower it will look jagged. If it is higher it will hit performace. // The drawmode specifies either a fill or line draw func Ellipsep(mode DrawMode, x, y, radiusx, radiusy float32, points int) { two_pi := math.Pi * 2.0 if points <= 0 { points = 1 } angle_shift := float32(two_pi) / float32(points) phi := float32(0.0) coords := make([]float32, 2*(points+1)) for i := 0; i < points; i++ { phi += angle_shift coords[2*i+0] = x + radiusx*float32(math.Cos(float64(phi))) coords[2*i+1] = y + radiusy*float32(math.Sin(float64(phi))) } coords[2*points+0] = coords[0] coords[2*points+1] = coords[1] if mode == LINE { PolyLine(coords) } else { prepareDraw(nil) bindTexture(gl_state.defaultTexture) useVertexAttribArrays(attribflag_pos) gl.VertexAttribPointer(attrib_pos, 2, gl.FLOAT, false, 0, gl.Ptr(coords)) gl.DrawArrays(gl.TRIANGLE_FAN, 0, len(coords)/2-1) } }
func (buffer *vertexBuffer) bufferStatic() { if buffer.modified_size == 0 { return } // Upload the mapped data to the buffer. gl.BufferSubData(gl.ARRAY_BUFFER, buffer.modified_offset*4, buffer.modified_size*4, gl.Ptr(&buffer.data[buffer.modified_offset])) }
func (buffer *vertexBuffer) loadVolatile() bool { buffer.vbo = gl.CreateBuffer() buffer.bind() defer buffer.unbind() gl.BufferData(gl.ARRAY_BUFFER, len(buffer.data)*4, gl.Ptr(buffer.data), uint32(buffer.usage)) return true }
func (polyline *polyLine) drawTriangleStrip(is_looping bool) { prepareDraw(nil) bindTexture(gl_state.defaultTexture) useVertexAttribArrays(attribflag_pos) gl.VertexAttribPointer(attrib_pos, 2, gl.FLOAT, false, 0, gl.Ptr(polyline.vertices)) gl.DrawArrays(gl.TRIANGLE_STRIP, 0, len(polyline.vertices)) if polyline.overdraw { // prepare colors: c := GetColor() overdraw := polyline.renderOverdraw(is_looping) colors := polyline.generateColorArray(len(overdraw), c) useVertexAttribArrays(attribflag_pos | attribflag_color) gl.VertexAttribPointer(attrib_color, 4, gl.UNSIGNED_BYTE, true, 0, gl.Ptr(colors)) gl.VertexAttribPointer(attrib_pos, 2, gl.FLOAT, false, 0, gl.Ptr(overdraw)) gl.DrawArrays(gl.TRIANGLE_STRIP, 0, len(overdraw)) SetColorC(c) } }
// Polygon will draw a closed polygon with an array in the form of x1, y1, x2, y2, x3, y3, ..... xn, yn // The drawmode specifies either a fill or line draw func Polygon(mode DrawMode, coords []float32) { coords = append(coords, coords[0], coords[1]) if mode == LINE { PolyLine(coords) } else { prepareDraw(nil) bindTexture(gl_state.defaultTexture) useVertexAttribArrays(attribflag_pos) gl.VertexAttribPointer(attrib_pos, 2, gl.FLOAT, false, 0, gl.Ptr(coords)) gl.DrawArrays(gl.TRIANGLE_FAN, 0, len(coords)/2-1) } }
// Set the 'default' texture (id 0) as a repeating white pixel. Otherwise, // texture2D calls inside a shader would return black when drawing graphics // primitives, which would create the need to use different "passthrough" // shaders for untextured primitives vs images. func createDefaultTexture() { gl_state.defaultTexture = gl.CreateTexture() bindTexture(gl_state.defaultTexture) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT) pix := []byte{255, 255, 255, 255} gl.TexImage2D(gl.TEXTURE_2D, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(pix)) }
// Arcp is like Arc except that you can define how many points you want to generate // the arc. // If it is lower it will look jagged. If it is higher it will hit performace. // The drawmode specifies either a fill or line draw func Arcp(mode DrawMode, x, y, radius, angle1, angle2 float32, points int) { // Nothing to display with no points or equal angles. (Or is there with line mode?) if points <= 0 || angle1 == angle2 { return } // Oh, you want to draw a circle? if math.Abs(float64(angle1-angle2)) >= (2.0 * math.Pi) { Circlep(mode, x, y, radius, points) return } angle_shift := (angle2 - angle1) / float32(points) // Bail on precision issues. if angle_shift == 0.0 { return } phi := angle1 num_coords := (points + 3) * 2 coords := make([]float32, num_coords) coords[0] = x coords[num_coords-2] = x coords[1] = y coords[num_coords-1] = y for i := 0; i <= points; i++ { phi = phi + angle_shift coords[2*(i+1)] = x + radius*float32(math.Cos(float64(phi))) coords[2*(i+1)+1] = y + radius*float32(math.Sin(float64(phi))) } if mode == LINE { PolyLine(coords) } else { prepareDraw(nil) bindTexture(gl_state.defaultTexture) useVertexAttribArrays(attribflag_pos) gl.VertexAttribPointer(attrib_pos, 2, gl.FLOAT, false, 0, gl.Ptr(coords)) gl.DrawArrays(gl.TRIANGLE_FAN, 0, len(coords)/2-1) } }
// newImageTexture will generate a texture from an image. It will automatically // upload the image data to the texture. func newImageTexture(img image.Image, mipmaps bool) (*Texture, error) { bounds := img.Bounds() new_texture := newTexture(int32(bounds.Dx()), int32(bounds.Dy()), mipmaps) //generate a uniform image and upload to vram rgba := image.NewRGBA(img.Bounds()) draw.Draw(rgba, bounds, img, image.Point{0, 0}, draw.Src) bindTexture(new_texture.getHandle()) gl.TexImage2D(gl.TEXTURE_2D, 0, bounds.Dx(), bounds.Dy(), gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(rgba.Pix)) if new_texture.mipmaps { new_texture.generateMipmaps() } return new_texture, nil }
func (buffer *vertexBuffer) bufferStream() { // "orphan" current buffer to avoid implicit synchronisation on the GPU: // http://www.seas.upenn.edu/~pcozzi/OpenGLInsights/OpenGLInsights-AsynchronousBufferTransfers.pdf gl.BufferData(gl.ARRAY_BUFFER, len(buffer.data)*4, gl.Ptr(nil), uint32(buffer.usage)) gl.BufferData(gl.ARRAY_BUFFER, len(buffer.data)*4, gl.Ptr(buffer.data), uint32(buffer.usage)) }
func (buffer *indexBuffer) drawElementsLocal(mode uint32, offset, size int) { gl.DrawElements(gl.Enum(mode), size, gl.UNSIGNED_INT, gl.Ptr(&buffer.data[offset])) }