Beispiel #1
0
func runGameLoop(window *glfw.Window) {
	for !window.ShouldClose() {
		// update objects
		updateObjects()

		// hit detection
		hitDetection()

		// ---------------------------------------------------------------
		// draw calls
		gl.Clear(gl.COLOR_BUFFER_BIT)

		drawCurrentScore()
		drawHighScore()

		if isGameWon() {
			drawWinningScreen()
		} else if isGameLost() {
			drawGameOverScreen()
		}

		// draw everything 9 times in a 3x3 grid stitched together for seamless clipping
		for x := -1.0; x < 2.0; x++ {
			for y := -1.0; y < 2.0; y++ {
				gl.MatrixMode(gl.MODELVIEW)
				gl.PushMatrix()
				gl.Translated(gameWidth*x, gameHeight*y, 0)

				drawObjects()

				gl.PopMatrix()
			}
		}

		gl.Flush()
		window.SwapBuffers()
		glfw.PollEvents()

		// switch resolution
		if altEnter {
			window.Destroy()

			fullscreen = !fullscreen
			var err error
			window, err = initWindow()
			if err != nil {
				panic(err)
			}

			altEnter = false

			gl.LineWidth(1)
			if fullscreen {
				gl.LineWidth(2)
			}
		}
	}
}
Beispiel #2
0
func (sg *OpenGLGraphics) Line(x0, y0, x1, y1 int, style chart.Style) {
	//log.Panicf("Unimplemented: %s", whoami())
	defer glh.OpenGLSentinel()()

	gl.LineWidth(float32(style.LineWidth))

	// TODO: line stipple?
	//sc := chart.Color2RGBA(style.LineColor, uint8(style.Alpha*255))
	//log.Printf("color: %s %d %d %d %d", style.FillColor, sc.R, sc.G, sc.B, sc.A)

	glh.ColorC(style.LineColor)
	//sc := style.LineColor
	//gl.Color4ub(sc.R, sc.G, sc.B, sc.A)
	// TODO: Check this works

	glh.With(glh.Attrib{gl.ENABLE_BIT | gl.COLOR_BUFFER_BIT}, func() {
		gl.Enable(gl.BLEND)
		gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)

		glh.With(glh.Primitive{gl.LINES}, func() {
			gl.Vertex2i(x0, y0)
			gl.Vertex2i(x1, y1)
		})
	})
}
Beispiel #3
0
func (m *Map) Draw() {

	gl.PushMatrix()
	gl.PushAttrib(gl.CURRENT_BIT | gl.ENABLE_BIT | gl.LIGHTING_BIT | gl.POLYGON_BIT | gl.LINE_BIT)

	gl.EnableClientState(gl.VERTEX_ARRAY)
	gl.VertexPointer(3, gl.FLOAT, 0, m.vertices)

	gl.EnableClientState(gl.NORMAL_ARRAY)
	gl.NormalPointer(gl.FLOAT, 0, m.normals)

	// gl.EnableClientState(gl.TEXTURE_COORD_ARRAY)
	// gl.TexCoordPointer(2, gl.FLOAT, 0, m.texcoords)

	gl.EnableClientState(gl.COLOR_ARRAY)
	gl.ColorPointer(3, gl.FLOAT, 0, m.colors)

	// draw solids
	gl.Enable(gl.COLOR_MATERIAL)
	// gl.DrawArrays(gl.TRIANGLE_STRIP, 0, len(m.vertices)/3)

	gl.PolygonMode(gl.FRONT_AND_BACK, gl.LINE)
	gl.LineWidth(1.0)
	gl.Color4f(1, 1, 1, 1)
	gl.DrawArrays(gl.TRIANGLE_STRIP, 0, len(m.vertices)/3)

	gl.PopAttrib()
	gl.PopMatrix()

}
Beispiel #4
0
func (m *Map) Draw() {

	// gl.Enable(gl.PRIMITIVE_RESTART)
	// gl.PrimitiveRestartIndex(PRIMITIVE_RESTART)
	gl.EnableClientState(gl.VERTEX_ARRAY)
	gl.Translatef(float32(m.gridSize/2), float32(m.gridSize/2), 0)

	if m.renderSmooth {
		gl.Enable(gl.BLEND)
		gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
		gl.Enable(gl.POLYGON_SMOOTH)
		gl.Hint(gl.POLYGON_SMOOTH_HINT, gl.NICEST)
	}

	if m.renderMode == 1 {
		gl.LineWidth(1)
		gl.VertexPointer(2, gl.FLOAT, 0, m.gridLines)
		gl.Color3f(0.2, 0.2, 0.2)
		gl.DrawArrays(gl.LINES, 0, len(m.gridLines)/2)
		gl.PolygonMode(gl.FRONT_AND_BACK, gl.LINE)
	}

	for _, vl := range m.vl {
		if len(vl.vertices) > 0 {
			gl.VertexPointer(2, gl.FLOAT, 0, vl.vertices)
			gl.Color3f(vl.colors[0], vl.colors[1], vl.colors[2])
			gl.DrawElements(gl.TRIANGLES, len(vl.indices), gl.UNSIGNED_INT, vl.indices)
		}
	}

}
Beispiel #5
0
func main() {

	if !glfw.Init() {
		log.Fatal("glfw failed to initialize")
	}
	defer glfw.Terminate()

	window, err := glfw.CreateWindow(640, 480, "Deformable", nil, nil)
	if err != nil {
		log.Fatal(err.Error())
	}

	window.MakeContextCurrent()
	glfw.SwapInterval(1)
	window.SetMouseButtonCallback(handleMouseButton)
	window.SetKeyCallback(handleKeyDown)
	window.SetInputMode(glfw.Cursor, glfw.CursorHidden)

	gl.Init()
	initGL()

	i := 16
	m = GenerateMap(1600/i, 1200/i, i)
	for running && !window.ShouldClose() {

		x, y := window.GetCursorPosition()

		if drawing != 0 {
			m.Add(int(x)+int(camera[0]), int(y)+int(camera[1]), drawing, brushSizes[currentBrushSize])
		}

		gl.Clear(gl.COLOR_BUFFER_BIT)
		gl.LoadIdentity()

		gl.PushMatrix()
		gl.PushAttrib(gl.CURRENT_BIT | gl.ENABLE_BIT | gl.LIGHTING_BIT | gl.POLYGON_BIT | gl.LINE_BIT)
		gl.Translatef(-camera[0], -camera[1], 0)
		m.Draw()
		gl.PopAttrib()
		gl.PopMatrix()

		gl.PushAttrib(gl.COLOR_BUFFER_BIT)
		gl.LineWidth(2)
		gl.Enable(gl.BLEND)
		gl.BlendFunc(gl.ONE_MINUS_DST_COLOR, gl.ZERO)
		// gl.Enable(gl.LINE_SMOOTH)
		// gl.Hint(gl.LINE_SMOOTH_HINT, gl.NICEST)

		gl.Translatef(float32(x), float32(y), 0)

		gl.EnableClientState(gl.VERTEX_ARRAY)
		gl.VertexPointer(2, gl.DOUBLE, 0, cursorVerts)
		gl.DrawArrays(gl.LINE_LOOP, 0, 24)
		gl.PopAttrib()

		window.SwapBuffers()
		glfw.PollEvents()
	}

}
Beispiel #6
0
func (p *Planetoid) Render(dp float64) {
	glh.With(glh.Matrix{gl.MODELVIEW}, func() {

		gl.Rotated(p.rising_node, 0, 1, 0)
		gl.Rotated(p.inclination, 0, 0, 1)

		gl.Rotated(p.phase0+p.phase, 0, 1, 0)
		p.phase += dp*10 + (1 - p.apogee)

		glh.With(glh.Matrix{gl.MODELVIEW}, func() {
			// TODO: Compute position correctly
			gl.Translated(p.apogee, 0, 0)
			Sphere(p.radius, 3)
		})

		// TODO: Avoid depth thrashing when trails overlap
		// Trail
		glh.With(glh.Matrix{gl.MODELVIEW}, func() {
			gl.Rotated(90, 1, 0, 0)
			gl.Scaled(p.apogee, p.apogee, 1)

			gl.LineWidth(2)
			glh.With(glh.Disable(gl.LIGHTING), func() {
				p.circle.Render(gl.LINE_STRIP)
			})
		})
	})
}
Beispiel #7
0
func renderSwitch(s *Switch) {
	gl.LoadIdentity()
	// TODO constant
	v := SwitchSize / 2
	x, y := float32(s.X+v), float32(s.Y+v)
	gl.Translatef(x, y, 0)
	// Render the switch
	gl.Color3f(1, 1, 1)
	gl.Begin(gl.TRIANGLE_FAN)
	gl.Vertex2d(0, 0)
	vv := float64(v)
	for i := float64(0); i <= SwitchSegments; i++ {
		a := 2 * math.Pi * i / SwitchSegments
		gl.Vertex2d(math.Sin(a)*vv, math.Cos(a)*vv)
	}
	gl.End()

	if LineWidth != 0 {
		// Render the shape
		gl.Color3i(0, 0, 0)
		gl.LineWidth(LineWidth)
		gl.Begin(gl.LINE_LOOP)
		for i := float64(0); i <= SwitchSegments; i++ {
			a := 2 * math.Pi * i / SwitchSegments
			gl.Vertex2d(math.Sin(a)*vv, math.Cos(a)*vv)
		}
		gl.End()
	}

	// Write the switch name
	gl.LoadIdentity()
	w, h := fonts[6].Metrics(s.name)
	gl.Color3i(0, 0, 0)
	fonts[6].Printf(x-float32(w)/2, y-float32(h)/2+2, s.name)
}
Beispiel #8
0
func renderCorner(color ColorDef, ww, hh, start float64, radius, lineWidth float32) {
	setColor(color)
	max := BlockCornerSegments * (start + 1)
	// Render the corner
	gl.Begin(gl.TRIANGLE_FAN)
	gl.Vertex2d(ww, hh)
	for i := start * BlockCornerSegments; i <= max; i++ {
		a := math.Pi / 2 * i / BlockCornerSegments
		x := math.Cos(a) * float64(radius)
		y := math.Sin(a) * float64(radius)
		gl.Vertex2d(ww+x, hh+y)
	}
	gl.End()

	if lineWidth != 0 {
		// Render the shape
		gl.LineWidth(lineWidth)
		gl.Color3i(0, 0, 0)
		gl.Begin(gl.LINE_STRIP)
		for i := start * BlockCornerSegments; i <= max; i++ {
			a := math.Pi / 2 * i / BlockCornerSegments
			x := math.Cos(a) * float64(radius)
			y := math.Sin(a) * float64(radius)
			gl.Vertex2d(ww+x, hh+y)
		}
		gl.End()
	}
}
Beispiel #9
0
func main() {
	glut.InitDisplayMode(glut.SINGLE | glut.RGB)
	glut.InitWindowSize(465, 250)
	glut.CreateWindow("GLUT bitmap & stroke font example")
	gl.ClearColor(1.0, 1.0, 1.0, 1.0)
	gl.Color3f(0, 0, 0)
	gl.LineWidth(3.0)
	glut.DisplayFunc(display)
	glut.ReshapeFunc(reshape)
	glut.MainLoop()
}
Beispiel #10
0
func (sg *OpenGLGraphics) Rect(x, y, w, h int, style chart.Style) {
	// log.Panicf("Unimplemented: %s", whoami())
	x, y, w, h = chart.SanitizeRect(x, y, w, h, style.LineWidth)
	defer glh.OpenGLSentinel()()

	//

	glh.With(glh.Attrib{gl.ENABLE_BIT | gl.COLOR_BUFFER_BIT}, func() {
		glh.ColorC(style.FillColor)

		gl.Enable(gl.BLEND)
		gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)

		gl.Begin(gl.QUADS)
		glh.Squarei(x, y, w, h)
		gl.End()
	})

	if style.LineWidth != 0 {
		gl.LineWidth(float32(style.LineWidth))
		//log.Print("Linewidth: ", float32(style.LineWidth))

		glh.With(glh.Attrib{gl.ENABLE_BIT | gl.COLOR_BUFFER_BIT}, func() {
			glh.ColorC(style.LineColor)

			gl.Enable(gl.BLEND)
			gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)

			gl.Begin(gl.LINE_LOOP)
			glh.Squarei(x, y, w, h)
			gl.End()
		})
	}

	// linecol := style.LineColor
	// if linecol != "" {
	// 	s = fmt.Sprintf("stroke:%s; ", linecol)
	// } else {
	// 	linecol = "#808080"
	// }
	// s += fmt.Sprintf("stroke-width: %d; ", style.LineWidth)
	// s += fmt.Sprintf("opacity: %.2f; ", 1-style.Alpha)
	// if style.FillColor != "" {
	// 	s += fmt.Sprintf("fill: %s; fill-opacity: %.2f", style.FillColor, 1-style.Alpha)
	// } else {
	// 	s += "fill-opacity: 0"
	// }
	// sg.svg.Rect(x, y, w, h, s)
	// GenericRect(sg, x, y, w, h, style) // TODO
}
Beispiel #11
0
// initGL initializes GLFW and OpenGL.
func initGL() error {
	err := glfw.Init()
	if err != nil {
		return err
	}

	glfw.OpenWindowHint(glfw.FsaaSamples, 4)
	glfw.OpenWindowHint(glfw.WindowNoResize, gl.TRUE)

	err = glfw.OpenWindow(512, 512, 8, 8, 8, 8, 32, 0, glfw.Windowed)
	if err != nil {
		glfw.Terminate()
		return err
	}

	glfw.SetWindowTitle("Meshbuffer 3D example")
	glfw.SetSwapInterval(1)
	glfw.SetWindowSizeCallback(onResize)
	glfw.SetKeyCallback(onKey)

	gl.Init()
	if err = glh.CheckGLError(); err != nil {
		return err
	}

	gl.Enable(gl.DEPTH_TEST)
	gl.Enable(gl.MULTISAMPLE)
	gl.Disable(gl.LIGHTING)

	//gl.ClearColor(0.2, 0.2, 0.23, 1.0)
	gl.ClearColor(0, 0, 0, 1.0)
	gl.ShadeModel(gl.SMOOTH)
	gl.LineWidth(2)
	gl.ClearDepth(1)
	gl.DepthFunc(gl.LEQUAL)
	gl.Hint(gl.PERSPECTIVE_CORRECTION_HINT, gl.NICEST)
	gl.ColorMaterial(gl.FRONT_AND_BACK, gl.AMBIENT_AND_DIFFUSE)
	return nil
}
Beispiel #12
0
// Draw `text` at `x`, `y`.
func (text *Text) Draw(x, y int) {
	var w, h = text.W, text.H

	if text.Flipped {
		h = -h
	}
	With(Attrib{gl.ENABLE_BIT | gl.COLOR_BUFFER_BIT}, func() {
		gl.Enable(gl.BLEND)
		gl.BlendFunc(gl.SRC_ALPHA, gl.DST_ALPHA)
		//gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
		With(text, func() {
			gl.TexEnvi(gl.TEXTURE_ENV, gl.TEXTURE_ENV_MODE, gl.MODULATE)
			DrawQuadi(x, y, w, h)
		})
	})

	if text.DebugRect {
		gl.LineWidth(1)
		With(Primitive{gl.LINE_LOOP}, func() {
			sp := 0
			Squarei(x-sp, y+sp, w+sp*2, h-sp*2)
		})
	}
}
Beispiel #13
0
// Draws a cross on the screen with known lengths, useful for understanding
// screen dimensions
func DebugLines() {
	gl.MatrixMode(gl.PROJECTION)
	gl.PushMatrix()
	//gl.LoadIdentity()
	//gl.Ortho(-2.1, 6.1, -4, 8, 1, -1)
	gl.MatrixMode(gl.MODELVIEW)
	gl.PushMatrix()
	gl.LoadIdentity()

	gl.LoadIdentity()
	gl.LineWidth(5)
	gl.Color4f(1, 1, 0, 1)
	gl.Begin(gl.LINES)
	gl.Vertex2d(0, -1.6)
	gl.Vertex2d(0, 0.8)
	gl.Vertex2d(-0.8, 0)
	gl.Vertex2d(0.8, 0)
	gl.End()
	gl.PopMatrix()

	gl.MatrixMode(gl.PROJECTION)
	gl.PopMatrix()
	gl.MatrixMode(gl.MODELVIEW)
}
Beispiel #14
0
func (sg *OpenGLGraphics) Scatter(points []chart.EPoint, plotstyle chart.PlotStyle, style chart.Style) {
	//log.Panicf("Unimplemented: %s", whoami())
	//chart.GenericScatter(sg, points, plotstyle, style)

	// TODO: Implement error bars/symbols

	buffer := glh.NewMeshBuffer(glh.RenderArrays,
		glh.NewPositionAttr(2, gl.DOUBLE, gl.STATIC_DRAW),
		glh.NewColorAttr(3, gl.UNSIGNED_INT, gl.STATIC_DRAW))

	// var vertices glh.ColorVertices

	positions := make([]float64, len(points)*2)
	colors := make([]uint32, len(points)*3)

	for _, p := range points {
		r, g, b, _ := style.LineColor.RGBA()

		colors = append(colors, r, g, b)
		positions = append(positions, p.X, p.Y)

		// vertices.Add(glh.ColorVertex{
		// 	glh.MkRGBA(style.LineColor),
		// 	glh.Vertex{float32(p.X), float32(p.Y)}})
	}

	buffer.Add()

	if style.LineWidth != 0 {
		gl.LineWidth(float32(style.LineWidth))
	} else {
		gl.LineWidth(1)
	}

	glh.With(glh.Attrib{gl.ENABLE_BIT | gl.COLOR_BUFFER_BIT}, func() {
		gl.Enable(gl.BLEND)
		gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)

		buffer.Render(gl.LINE_STRIP)
	})

	/***********************************************
	// First pass: Error bars
	ebs := style
	ebs.LineColor, ebs.LineWidth, ebs.LineStyle = ebs.FillColor, 1, chart.SolidLine
	if ebs.LineColor == "" {
		ebs.LineColor = "#404040"
	}
	if ebs.LineWidth == 0 {
		ebs.LineWidth = 1
	}
	for _, p := range points {
		xl, yl, xh, yh := p.BoundingBox()
		// fmt.Printf("Draw %d: %f %f-%f\n", i, p.DeltaX, xl,xh)
		if !math.IsNaN(p.DeltaX) {
			sg.Line(int(xl), int(p.Y), int(xh), int(p.Y), ebs)
		}
		if !math.IsNaN(p.DeltaY) {
			sg.Line(int(p.X), int(yl), int(p.X), int(yh), ebs)
		}
	}

	// Second pass: Line
	if (plotstyle&chart.PlotStyleLines) != 0 && len(points) > 0 {
		path := fmt.Sprintf("M %d,%d", int(points[0].X), int(points[0].Y))
		for i := 1; i < len(points); i++ {
			path += fmt.Sprintf("L %d,%d", int(points[i].X), int(points[i].Y))
		}
		st := linestyle(style)
		sg.svg.Path(path, st)
	}

	// Third pass: symbols
	if (plotstyle&chart.PlotStylePoints) != 0 && len(points) != 0 {
		for _, p := range points {
			sg.Symbol(int(p.X), int(p.Y), style)
		}
	}

	****************************************************/
}
Beispiel #15
0
func (block *Block) Draw(start, N int64, detailed bool) {
	if block.tex == nil {
		block.RequestTexture()
	}

	switch detailed {
	case true:
		block.detail_needed = true
		if block.vertex_data == nil {
			// Hey, we need vertices but don't have them! Let's fix that..
			block.RequestVertices()
		}
	default:
		block.detail_needed = false
	}

	width := uint64(len(block.display_active_pages)) * *PAGE_SIZE
	if width == 0 {
		width = 1
	}

	vc := glh.NewMeshBuffer(glh.RenderArrays,
		glh.NewPositionAttr(2, gl.FLOAT, gl.STATIC_DRAW),
		glh.NewPositionAttr(4, gl.UNSIGNED_INT, gl.STATIC_DRAW),
	)

	colors := make([]int32, 0)
	positions := make([]float32, 0)

	// var vc glh.ColorVertices

	if *pageboundaries {
		// boundary_color := color.RGBA{64, 64, 64, 255}

		// If we try and draw too many of these, X will hang
		if width / *PAGE_SIZE < 10000 {
			for p := uint64(0); p <= width; p += *PAGE_SIZE {
				x := float32(p) / float32(width)
				x = (x - 0.5) * 4

				colors = append(colors, 64, 64, 64, 255)
				positions = append(positions, x, float32(N))

				// vc.Add(glh.ColorVertex{boundary_color, glh.Vertex{x, 0}})
				// vc.Add(glh.ColorVertex{boundary_color, glh.Vertex{x, float32(N)}})
			}
		}
	}

	var border_color [4]float64

	gl.LineWidth(1)
	glh.With(&Timer{Name: "DrawPartial"}, func() {
		var x1, y1, x2, y2 float64
		glh.With(glh.Matrix{gl.MODELVIEW}, func() {
			// TODO: A little less co-ordinate insanity?
			gl.Translated(0, -2, 0)
			gl.Scaled(1, 4/float64(*nback), 1)
			gl.Translated(0, -float64(start), 0)

			x1, y1 = glh.ProjToWindow(-2, 0)
			x2, y2 = glh.ProjToWindow(-2+WIDTH, float64(N))

		})
		border_color = [4]float64{1, 1, 1, 1}

		glh.With(glh.Matrix{gl.MODELVIEW}, func() {
			gl.Translated(0, -2, 0)
			gl.Scaled(1, 4/float64(*nback), 1)
			gl.Translated(0, -float64(start), 0)

			// Page boundaries
			// TODO: Use different blending scheme on textured quads so that the
			//       lines show through
			glh.With(glh.Attrib{gl.ENABLE_BIT}, func() {
				gl.Disable(gl.LINE_SMOOTH)
				// vc.Draw(gl.LINES)
				vc.Render(gl.LINES)
			})
		})

		if block.tex != nil && (!detailed || block.vertex_data == nil) {
			border_color = [4]float64{0, 0, 1, 1}
			glh.With(glh.WindowCoords{Invert: true}, func() {
				gl.Color4f(1, 1, 1, 1)
				// Render textured block quad
				glh.With(block.tex, func() {
					glh.DrawQuadd(x1, y1, x2-x1, y2-y1)
				})
				glh.With(glh.Primitive{gl.LINES}, func() {
					glh.Squared(x1, y1, x2-x1, y2-y1)
				})
			})
			if block.vertex_data != nil && !block.detail_needed {
				// TODO: figure out when we can unload
				// Hey, we can unload you, because you are not needed
				block.vertex_data = nil
			}

		}
		if detailed && block.vertex_data != nil {
			glh.With(glh.Matrix{gl.MODELVIEW}, func() {
				// TODO: A little less co-ordinate insanity?
				gl.Translated(0, -2, 0)
				gl.Scaled(1, 4/float64(*nback), 1)
				gl.Translated(0, -float64(start), 0)

				gl.PointSize(2)
				block.vertex_data.Render(gl.POINTS)
			})
		}

		glh.With(glh.WindowCoords{Invert: true}, func() {
			// Block boundaries
			gl.Color4dv(&border_color)

			gl.LineWidth(1)
			glh.With(glh.Primitive{gl.LINE_LOOP}, func() {
				glh.Squared(x1, y1, x2-x1, y2-y1)
			})
		})
	})
}
Beispiel #16
0
func renderBlock_(color ColorDef, w, h, radius, lineWidth float32) {
	setColor(color)
	gl.Begin(gl.QUADS)
	// Render inner square
	gl.Vertex2f(radius, radius)
	gl.Vertex2f(radius, h-radius)
	gl.Vertex2f(w-radius, h-radius)
	gl.Vertex2f(w-radius, radius)
	// Render top square
	gl.Vertex2f(radius, h-radius)
	gl.Vertex2f(radius, h)
	gl.Vertex2f(w-radius, h)
	gl.Vertex2f(w-radius, h-radius)
	// Render bottom square
	gl.Vertex2f(radius, radius)
	gl.Vertex2f(radius, 0)
	gl.Vertex2f(w-radius, 0)
	gl.Vertex2f(w-radius, radius)
	// Render left square
	gl.Vertex2f(w-radius, radius)
	gl.Vertex2f(w, radius)
	gl.Vertex2f(w, h-radius)
	gl.Vertex2f(w-radius, h-radius)
	// Render right square
	gl.Vertex2f(radius, radius)
	gl.Vertex2f(0, radius)
	gl.Vertex2f(0, h-radius)
	gl.Vertex2f(radius, h-radius)
	gl.End()
	// Render bottom right corner
	ww, hh := float64(w-radius), float64(h-radius)
	renderCorner(color, ww, hh, 0, radius, lineWidth)
	// Render bottom left corner
	ww, hh = float64(radius), float64(h-radius)
	renderCorner(color, ww, hh, 1, radius, lineWidth)
	// Render top left corner
	ww, hh = float64(radius), float64(radius)
	renderCorner(color, ww, hh, 2, radius, lineWidth)
	// Render top right corner
	ww, hh = float64(w-radius), float64(radius)
	renderCorner(color, ww, hh, 3, radius, lineWidth)

	if lineWidth != 0 {
		// Render the shape
		gl.LineWidth(lineWidth)
		gl.Color3i(0, 0, 0)
		gl.Begin(gl.LINES)

		gl.Vertex2f(radius, 0)
		gl.Vertex2f(w-radius, 0)

		gl.Vertex2f(0, radius)
		gl.Vertex2f(0, h-radius)

		gl.Vertex2f(w, radius)
		gl.Vertex2f(w, h-radius)

		gl.Vertex2f(radius, h)
		gl.Vertex2f(w-radius, h)

		gl.End()
	}
	gl.PopMatrix()
}