Example #1
0
func (r *GlowRenderer) Draw() (err error) {
	gl.UseProgram(r.shader)
	gl.Uniform1i(r.textureUnitLoc, 0)
	gl.BindBuffer(gl.ARRAY_BUFFER, r.coords)
	gl.EnableVertexAttribArray(r.positionLoc)
	gl.VertexAttribPointer(r.positionLoc, 3, gl.FLOAT, false, 5*4, gl.PtrOffset(0))
	gl.EnableVertexAttribArray(r.textureLoc)
	gl.VertexAttribPointer(r.textureLoc, 2, gl.FLOAT, false, 5*4, gl.PtrOffset(3*4))
	gl.Uniform1i(r.blurAmountLoc, int32(r.blur))
	gl.Uniform1f(r.blurScaleLoc, r.scale)
	gl.Uniform1f(r.blurStrengthLoc, r.strength)
	gl.Uniform2f(r.bufferDimensionsLoc, float32(r.width), float32(r.height))

	gl.BindFramebuffer(gl.FRAMEBUFFER, r.BlurFb)
	gl.Viewport(0, 0, int32(r.width), int32(r.height))
	gl.ActiveTexture(gl.TEXTURE0)
	gl.BindTexture(gl.TEXTURE_2D, r.GlowTex)
	gl.Uniform1i(r.orientationLoc, 0)
	gl.DrawArrays(gl.TRIANGLE_STRIP, 0, 4)
	gl.BindFramebuffer(gl.FRAMEBUFFER, 0)

	gl.Viewport(0, 0, int32(r.oldwidth), int32(r.oldheight))
	gl.BlendFunc(gl.ONE, gl.ONE)
	gl.BindTexture(gl.TEXTURE_2D, r.BlurTex)
	gl.Uniform1i(r.orientationLoc, 1)
	gl.DrawArrays(gl.TRIANGLE_STRIP, 0, 4)

	gl.BindBuffer(gl.ARRAY_BUFFER, 0)
	gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
	return nil
}
Example #2
0
func (lr *LinesRenderer) Draw(line *LineGeometry, mv mgl32.Mat4, style *LineStyle) (err error) {
	var (
		dataBytes    int   = len(line.Vertices) * int(lr.stride)
		indexBytes   int   = len(line.Indices) * int(lr.stride)
		elementCount int32 = int32(len(line.Indices))
		r, g, b, a         = style.Color.RGBA()
	)
	gl.Uniform1f(lr.thicknessLoc, style.Thickness)
	gl.Uniform1f(lr.innerLoc, style.Inner)
	gl.Uniform4f(lr.colorLoc, float32(r)/255.0, float32(g)/255.0, float32(b)/255.0, float32(a)/255.0)
	gl.UniformMatrix4fv(lr.modelviewLoc, 1, false, &mv[0])
	if dataBytes > lr.bufferBytes {
		lr.bufferBytes = dataBytes
		gl.BufferData(gl.ARRAY_BUFFER, dataBytes, gl.Ptr(line.Vertices), gl.STREAM_DRAW)
		gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, indexBytes, gl.Ptr(line.Indices), gl.STREAM_DRAW)
	} else {
		gl.BufferSubData(gl.ARRAY_BUFFER, 0, dataBytes, gl.Ptr(line.Vertices))
		gl.BufferSubData(gl.ELEMENT_ARRAY_BUFFER, 0, indexBytes, gl.Ptr(line.Indices))
	}
	gl.DrawElements(gl.TRIANGLES, elementCount, gl.UNSIGNED_INT, gl.PtrOffset(0))
	if e := gl.GetError(); e != 0 {
		err = fmt.Errorf("ERROR: OpenGL error %X", e)
	}
	return
}
Example #3
0
// Rendering this LineRender.
func (lr *LineRender) Render() {
	// Binding the appropriate information.
	gl.BindVertexArray(lr.vao)
	gl.BindBuffer(gl.ARRAY_BUFFER, lr.vbo)
	gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, lr.ebo)
	gl.UseProgram(lr.shaderProgram)

	// Loading up vertex attributes.
	vertAttrib := uint32(gl.GetAttribLocation(lr.shaderProgram, gl.Str("vert\x00")))
	gl.EnableVertexAttribArray(vertAttrib)
	gl.VertexAttribPointer(vertAttrib, 2, gl.FLOAT, false, 2*4, gl.PtrOffset(0))

	// Line thickness information.
	gl.Uniform1f(
		gl.GetUniformLocation(lr.shaderProgram, gl.Str("in_thickness\x00")),
		lr.weight)

	// Fragment shader color information.
	gl.Uniform4f(
		gl.GetUniformLocation(lr.shaderProgram, gl.Str("in_color\x00")),
		lr.color.Red,
		lr.color.Green,
		lr.color.Blue,
		lr.color.Alpha)

	gl.BindFragDataLocation(lr.shaderProgram, 0, gl.Str("out_color\x00"))

	// Performing the render.
	gl.DrawElements(gl.LINE_STRIP, lr.points, gl.UNSIGNED_INT, nil)
}
Example #4
0
func renderMarker(metrics *metrics, m *game.Marker, x, y int) {
	switch m.State {
	case game.MarkerShowing:
		var val string
		switch {
		case m.ChainLevel > 0:
			val = "x" + strconv.Itoa(m.ChainLevel+1)

		case m.ComboLevel > 3:
			val = strconv.Itoa(m.ComboLevel)

		default:
			return
		}

		sc := float32(0.5)

		tx := -float32(len(val)-1) * sc
		ty := metrics.globalTranslationY + cellTranslationY*-float32(y) + easeOutCubic(m.StateProgress(metrics.fudge), 0, 0.5)
		tz := metrics.globalTranslationZ + cellTranslationZ/2 + 0.1

		ry := metrics.globalRotationY + metrics.cellRotationY*-float32(x)
		yq := newAxisAngleQuaternion(yAxis, ry)
		qm := newQuaternionMatrix(yq.normalize())

		gl.Uniform1f(brightnessUniform, 0)
		gl.Uniform1f(alphaUniform, easeOutCubic(m.StateProgress(metrics.fudge), 1, -1))

		for _, rune := range val {
			text := markerRuneText[rune]

			m := newScaleMatrix(sc, sc, sc)
			m = m.mult(newTranslationMatrix(tx, ty, tz))
			m = m.mult(qm)
			gl.UniformMatrix4fv(modelMatrixUniform, 1, false, &m[0])

			gl.Uniform1i(textureUniform, int32(text.texture)-1)
			squareMesh.drawElements()
			tx++
		}

		gl.Uniform1i(textureUniform, int32(boardTexture)-1)
	}
}
Example #5
0
func SetUniformF(shader, variable string, f float32) error {
	prog, ok := shader_progs[shader]
	if !ok {
		return fmt.Errorf("Tried to set a uniform in an unknown shader '%s'", shader)
	}
	bvariable := []byte(fmt.Sprintf("%s\x00", variable))
	loc := gl.GetUniformLocation(prog, (*uint8)(unsafe.Pointer(&bvariable[0])))
	gl.Uniform1f(loc, f)
	return nil
}
Example #6
0
func renderCellBlock(metrics *metrics, c *game.Cell, x, y int) {
	bv := float32(0)
	if c.Block.State == game.BlockFlashing {
		bv = pulse(metrics.g.GlobalPulse+metrics.fudge, 0, 0.5, 1.5)
	}
	gl.Uniform1f(brightnessUniform, bv)

	m := metrics.blockMatrix(c.Block, x, y)
	gl.UniformMatrix4fv(modelMatrixUniform, 1, false, &m[0])
	blockMeshes[c.Block.Color].drawElements()
}
Example #7
0
func renderHUD(g *game.Game, fudge float32) {
	gl.UniformMatrix4fv(projectionViewMatrixUniform, 1, false, &orthoProjectionViewMatrix[0])
	gl.Uniform1f(grayscaleUniform, 0)
	gl.Uniform1f(brightnessUniform, 0)
	gl.Uniform1f(alphaUniform, 1)

	i := 1
	renderText := func(item game.HUDItem, val string) {
		text := hudItemText[item]
		x := float32(winWidth)/4*float32(i) - text.width/2
		y := float32(winHeight) - text.height*2
		text.render(x, y)

		var valWidth, valHeight float32
		for _, rune := range val {
			text := hudRuneText[rune]
			valWidth += text.width
			if text.height > valHeight {
				valHeight = text.height
			}
		}

		x = float32(winWidth)/4*float32(i) - valWidth/2
		y -= valHeight * 1.5
		for _, rune := range val {
			text := hudRuneText[rune]
			text.render(x, y)
			x += text.width
		}

		i++
	}

	renderText(game.HUDItemSpeed, formattedSpeed(g))
	renderText(game.HUDItemTime, formattedTime(g))
	renderText(game.HUDItemScore, formattedScore(g))
}
Example #8
0
// RenderString must be called on the render thread.  x and y are the initial position of the pen,
// in screen coordinates, and height is the height of a full line of text, in screen coordinates.
func (d *Dictionary) RenderString(str string, x, y, height float64) {
	if str == "" {
		return
	}
	// No synchronization necessary because everything is run serially on the render thread anyway.
	if d.strs == nil {
		d.strs = make(map[string]strData)
	}
	data, ok := d.strs[str]
	if !ok {
		data = d.bindString(str)
		d.strs[str] = data
	}

	render.EnableShader("glop.font")
	defer render.EnableShader("")

	gl.ActiveTexture(gl.TEXTURE0)
	gl.BindTexture(gl.TEXTURE_2D, d.atlas.texture)
	location, _ := render.GetUniformLocation("glop.font", "tex")
	gl.Uniform1i(location, 0)
	gl.BindSampler(0, d.atlas.sampler)

	location, _ = render.GetUniformLocation("glop.font", "height")
	gl.Uniform1f(location, float32(height))

	var viewport [4]int32
	gl.GetIntegerv(gl.VIEWPORT, &viewport[0])
	location, _ = render.GetUniformLocation("glop.font", "screen")
	gl.Uniform2f(location, float32(viewport[2]), float32(viewport[3]))

	location, _ = render.GetUniformLocation("glop.font", "pen")
	gl.Uniform2f(location, float32(x)+float32(viewport[0]), float32(y)+float32(viewport[1]))

	location, _ = render.GetUniformLocation("glop.font", "textColor")
	gl.Uniform3f(location, d.color[0], d.color[1], d.color[2])

	gl.Enable(gl.BLEND)
	gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
	gl.BindVertexArray(data.varrays[0])
	gl.DrawArrays(gl.TRIANGLES, 0, data.count)
}
Example #9
0
func renderMenu(g *game.Game, fudge float32) {
	ease := func(start, change float32) float32 {
		return easeOutCubic(g.StateProgress(fudge), start, change)
	}

	alpha := float32(1)
	switch g.State {
	case game.GameInitial, game.GamePaused:
		alpha = ease(0, 1)

	case game.GamePlaying, game.GameExiting:
		alpha = ease(1, -1)
	}

	// Don't render the menu if it is invisible.
	if alpha == 0 {
		return
	}

	gl.UniformMatrix4fv(projectionViewMatrixUniform, 1, false, &orthoProjectionViewMatrix[0])
	gl.Uniform1f(grayscaleUniform, 0)
	gl.Uniform1f(brightnessUniform, 0)
	gl.Uniform1f(alphaUniform, alpha)
	gl.Uniform1f(mixAmountUniform, 0)

	menu := g.Menu
	titleText := menuTitleText[menu.ID]
	totalHeight := titleText.height * 2
	for _, item := range menu.Items {
		totalHeight += float32(menuItemFontSize) * 2
		if !item.SingleChoice() {
			totalHeight += float32(menuItemFontSize) * 2
		}
	}

	currentY := (float32(winHeight) + totalHeight) / 2

	centerX := func(txt *renderableText) float32 {
		return (float32(winWidth) - txt.width) / 2
	}

	renderText := func(text *renderableText) {
		currentY -= text.height
		text.render(centerX(text), currentY)
		currentY -= text.height // add spacing for next item
	}

	// TODO(btmura): split these out into separate functions

	renderSlider := func(item *game.MenuItem) {
		val := strconv.Itoa(item.Slider.Value)

		var valWidth, valHeight float32
		for _, rune := range val {
			text := menuRuneText[rune]
			valWidth += text.width
			if text.height > valHeight {
				valHeight = text.height
			}
		}

		currentY -= valHeight
		x := (float32(winWidth) - valWidth) / 2
		for _, rune := range val {
			text := menuRuneText[rune]
			text.render(x, currentY)
			x += text.width
		}
		currentY -= valHeight
	}

	renderMenuItem := func(index int, item *game.MenuItem) {
		var brightness float32
		if menu.FocusedIndex == index {
			switch {
			case menu.Selected:
				brightness = pulse(g.GlobalPulse+fudge, 1, 1, 1)

			case item.SingleChoice():
				brightness = pulse(g.GlobalPulse+fudge, 1, 0.3, 0.06)

			default:
				brightness = 1
			}
		}
		gl.Uniform1f(brightnessUniform, brightness)
		renderText(menuItemText[item.ID])
		switch {
		case item.Selector != nil:
			renderText(menuChoiceText[item.Selector.Value()])

		case item.Slider != nil:
			renderSlider(item)
		}
	}

	renderText(titleText)
	for i, item := range menu.Items {
		renderMenuItem(i, item)
	}
}
Example #10
0
func renderCellFragments(metrics *metrics, c *game.Cell, x, y int) {
	const (
		nw = iota
		ne
		se
		sw
	)

	render := func(sc, rx, ry, rz float32, dir int) {
		m := newScaleMatrix(sc, sc, sc)
		m = m.mult(newTranslationMatrix(rx, ry, rz))
		m = m.mult(metrics.blockMatrix(c.Block, x, y))
		gl.UniformMatrix4fv(modelMatrixUniform, 1, false, &m[0])
		fragmentMeshes[c.Block.Color][dir].drawElements()
	}

	ease := func(start, change float32) float32 {
		return easeOutCubic(c.Block.StateProgress(metrics.fudge), start, change)
	}

	var bv float32
	var av float32
	switch c.Block.State {
	case game.BlockCracking, game.BlockCracked:
		av = 1
	case game.BlockExploding:
		bv = ease(0, 1)
		av = ease(1, -1)
	}
	gl.Uniform1f(brightnessUniform, bv)
	gl.Uniform1f(alphaUniform, av)

	const (
		maxCrack  = 0.03
		maxExpand = 0.02
	)
	var rs float32
	var rt float32
	var j float32
	switch c.Block.State {
	case game.BlockCracking:
		rs = ease(1, 1+maxExpand)
		rt = ease(0, maxCrack)
		j = pulse(c.Block.StateProgress(metrics.fudge), 0, 0.5, 1.5)
	case game.BlockCracked:
		rs = 1
		rt = maxCrack
	case game.BlockExploding:
		rs = ease(1, -1)
		rt = ease(maxCrack, math.Pi*0.75)
	}

	const szt = 0.5 // starting z translation since model is 0.5 in depth
	wx, ex := -rt, rt
	fz, bz := rt+szt, -rt-szt

	const amp = 1
	ny := rt + amp*float32(math.Sin(float64(rt)))
	sy := -rt + amp*(float32(math.Cos(float64(-rt)))-1)

	render(rs, wx+j, ny+j, fz, nw) // front north west
	render(rs, ex+j, ny+j, fz, ne) // front north east

	render(rs, wx+j, ny+j, bz, nw) // back north west
	render(rs, ex+j, ny+j, bz, ne) // back north east

	render(rs, wx+j, sy+j, fz, sw) // front south west
	render(rs, ex+j, sy+j, fz, se) // front south east

	render(rs, wx+j, sy+j, bz, sw) // back south west
	render(rs, ex+j, sy+j, bz, se) // back south east
}
Example #11
0
func renderBoard(g *game.Game, fudge float32) bool {
	if g.Board == nil {
		return false
	}

	b := g.Board

	metrics := newMetrics(g, fudge)

	gl.UniformMatrix4fv(projectionViewMatrixUniform, 1, false, &perspectiveProjectionViewMatrix[0])
	gl.Uniform3fv(mixColorUniform, 1, &blackColor[0])

	globalGrayscale := float32(1)
	globalDarkness := float32(0.8)
	var boardDarkness float32

	gameEase := func(start, change float32) float32 {
		return easeOutCubic(g.StateProgress(fudge), start, change)
	}
	boardEase := func(start, change float32) float32 {
		return easeOutCubic(b.StateProgress(fudge), start, change)
	}

	switch g.State {
	case game.GamePlaying:
		globalGrayscale = gameEase(1, -1)
		globalDarkness = gameEase(0.8, -0.8)

	case game.GamePaused:
		globalGrayscale = gameEase(0, 1)
		globalDarkness = gameEase(0, 0.8)

	case game.GameExiting:
		globalGrayscale = 1
		globalDarkness = gameEase(0.8, 1)
	}

	switch b.State {
	case game.BoardEntering:
		boardDarkness = boardEase(1, -1)

	case game.BoardExiting:
		boardDarkness = boardEase(0, 1)
	}

	finalDarkness := globalDarkness
	if finalDarkness < boardDarkness {
		finalDarkness = boardDarkness
	}
	gl.Uniform1f(mixAmountUniform, finalDarkness)

	gl.Uniform1i(textureUniform, int32(boardTexture)-1)

	for i := 0; i <= 2; i++ {
		gl.Uniform1f(grayscaleUniform, globalGrayscale)
		gl.Uniform1f(brightnessUniform, 0)
		gl.Uniform1f(alphaUniform, 1)

		if i == 0 {
			renderSelector(metrics)
		}

		for y, r := range b.Rings {
			for x, c := range r.Cells {
				switch i {
				case 0: // draw opaque objects
					switch c.Block.State {
					case game.BlockStatic,
						game.BlockSwappingFromLeft,
						game.BlockSwappingFromRight,
						game.BlockDroppingFromAbove,
						game.BlockFlashing:
						renderCellBlock(metrics, c, x, y)

					case game.BlockCracking, game.BlockCracked:
						renderCellFragments(metrics, c, x, y)
					}

				case 1: // draw transparent objects
					switch c.Block.State {
					case game.BlockExploding:
						renderCellFragments(metrics, c, x, y)
					}
					renderMarker(metrics, c.Marker, x, y)
				}
			}
		}
	}

	// Render the spare rings.

	// Set brightness to zero for all spare rings.
	gl.Uniform1f(brightnessUniform, 0)

	for y, r := range b.SpareRings {
		// Set grayscale value. First spare rings becomes colored. Rest are gray.
		grayscale := float32(1)
		if y == 0 {
			grayscale = easeInExpo(b.RiseProgress(fudge), 1, -1)
		}
		if grayscale < globalGrayscale {
			grayscale = globalGrayscale
		}
		gl.Uniform1f(grayscaleUniform, grayscale)

		// Set alpha value. Last spare ring fades in. Rest are opaque.
		alpha := float32(1)
		if y == len(b.SpareRings)-1 {
			alpha = easeInExpo(b.RiseProgress(fudge), 0, 1)
		}
		gl.Uniform1f(alphaUniform, alpha)

		// Render the spare rings below the normal rings.
		for x, c := range r.Cells {
			renderCellBlock(metrics, c, x, y+b.RingCount)
		}
	}

	return true
}