Esempio n. 1
0
func (ms *ManaSource) Draw(local *LocalData, zoom float64, dx float64, dy float64) {
	if local.nodeTextureData == nil {
		//		gl.Enable(gl.TEXTURE_2D)
		local.nodeTextureData = make([]byte, ms.options.NumNodeRows*ms.options.NumNodeCols*3)
		gl.GenTextures(1, &local.nodeTextureId)
		gl.BindTexture(gl.TEXTURE_2D, local.nodeTextureId)
		gl.TexEnvf(gl.TEXTURE_ENV, gl.TEXTURE_ENV_MODE, gl.MODULATE)
		gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
		gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
		gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT)
		gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT)
		gl.TexImage2D(
			gl.TEXTURE_2D,
			0,
			gl.RGB,
			gl.Sizei(ms.options.NumNodeRows),
			gl.Sizei(ms.options.NumNodeCols),
			0,
			gl.RGB,
			gl.UNSIGNED_BYTE,
			gl.Pointer(&local.nodeTextureData[0]))
	}
	for i := range ms.rawNodes {
		for c := 0; c < 3; c++ {
			color_frac := ms.rawNodes[i].Mana[c] * 1.0 / ms.options.NodeMagnitude
			color_range := float64(ms.options.MaxNodeBrightness - ms.options.MinNodeBrightness)
			local.nodeTextureData[i*3+c] = byte(
				color_frac*color_range + float64(ms.options.MinNodeBrightness))
		}
	}
	gl.Enable(gl.TEXTURE_2D)
	//gl.ActiveTexture(gl.TEXTURE0)
	gl.BindTexture(gl.TEXTURE_2D, local.nodeTextureId)
	gl.TexSubImage2D(
		gl.TEXTURE_2D,
		0,
		0,
		0,
		gl.Sizei(ms.options.NumNodeRows),
		gl.Sizei(ms.options.NumNodeCols),
		gl.RGB,
		gl.UNSIGNED_BYTE,
		gl.Pointer(&local.nodeTextureData[0]))

	base.EnableShader("nodes")
	base.SetUniformI("nodes", "width", ms.options.NumNodeRows*3)
	base.SetUniformI("nodes", "height", ms.options.NumNodeCols*3)
	base.SetUniformI("nodes", "drains", 1)
	base.SetUniformI("nodes", "tex0", 0)
	base.SetUniformI("nodes", "tex1", 1)
	base.SetUniformF("nodes", "zoom", float32(zoom))
	gl.ActiveTexture(gl.TEXTURE0)
	gl.BindTexture(gl.TEXTURE_2D, local.nodeTextureId)

	// I have no idea why this value for move works, but it does.  So, hooray.
	move := (dx - dy) / 2
	texture.RenderAdvanced(move, -move, dy, dx, 3.1415926535/2, true)
	base.EnableShader("")
	gl.Disable(gl.TEXTURE_2D)
}
Esempio n. 2
0
// Draw draws the Sprite object.
func (sprite *Sprite) Draw(frame int) error {

	gl.BindBuffer(gl.ARRAY_BUFFER, sprite.shape.vertexBuffer)
	gl.VertexAttribPointer(gl.Uint(0), 2, gl.FLOAT, gl.FALSE, 0, gl.Offset(nil, 0))
	gl.BindAttribLocation(paunchEffect.program, gl.Uint(0), gl.GLString("position"))
	gl.BindBuffer(gl.ARRAY_BUFFER, 0)

	if sprite.texcoordBuffer != 0 {
		gl.ActiveTexture(gl.TEXTURE0)

		gl.BindBuffer(gl.ARRAY_BUFFER, sprite.texcoordBuffer)
		gl.VertexAttribPointer(gl.Uint(1), 2, gl.FLOAT, gl.FALSE, 0, gl.Offset(nil, 0))
		gl.BindAttribLocation(paunchEffect.program, gl.Uint(0), gl.GLString("texcoord"))
		gl.BindBuffer(gl.ARRAY_BUFFER, 0)

		gl.BindTexture(gl.TEXTURE_2D, sprite.texture[frame])
		gl.EnableVertexAttribArray(gl.Uint(1))
	}

	gl.EnableVertexAttribArray(gl.Uint(0))
	gl.DrawArrays(gl.TRIANGLES, 0, gl.Sizei(sprite.shape.size))
	gl.DisableVertexAttribArray(gl.Uint(0))
	gl.DisableVertexAttribArray(gl.Uint(1))

	gl.BindTexture(gl.TEXTURE_2D, 0)

	return checkForErrors()
}
Esempio n. 3
0
func (a *app) draw(t time.Time) {
	gl.Clear(gl.COLOR_BUFFER_BIT)
	img := a.img
	w := img.Rect.Dx()
	h := img.Rect.Dy()
	gl.ActiveTexture(gl.TEXTURE0)
	upload(1, img.Y, img.YStride, w, h)
	gl.ActiveTexture(gl.TEXTURE1)
	upload(2, img.Cb, img.CStride, w/2, h/2)
	gl.ActiveTexture(gl.TEXTURE2)
	upload(3, img.Cr, img.CStride, w/2, h/2)
	if *blend {
		pimg := a.pimg
		gl.Uniform1f(a.factorloc, factor(t,
			a.tbase.Add(pimg.Timecode),
			a.tbase.Add(img.Timecode)))
		gl.ActiveTexture(gl.TEXTURE3)
		upload(4, pimg.Y, pimg.YStride, w, h)
		gl.ActiveTexture(gl.TEXTURE4)
		upload(5, pimg.Cb, pimg.CStride, w/2, h/2)
		gl.ActiveTexture(gl.TEXTURE5)
		upload(6, pimg.Cr, pimg.CStride, w/2, h/2)
	}
	gl.DrawArrays(gl.TRIANGLE_STRIP, 0, 4)
}
Esempio n. 4
0
func (m *Model) draw() {
	m.shader.use()

	gl.ActiveTexture(gl.TEXTURE0)
	gl.BindTexture(gl.TEXTURE_2D, m.texture_id)
	gl.Uniform1i(m.shader.uniform_texture, 0)

	//texcoord
	if m.has_uv {
		gl.BindBuffer(gl.ARRAY_BUFFER, m.texcoord)
		gl.EnableVertexAttribArray(m.shader.attribute_texcoord)
		gl.VertexAttribPointer(
			m.shader.attribute_texcoord,
			2,
			gl.FLOAT,
			gl.FALSE,
			0,
			gl.Pointer(nil))
	}

	gl.BindBuffer(gl.ARRAY_BUFFER, m.buffer)
	gl.EnableVertexAttribArray(m.shader.attribute_vertex)
	gl.VertexAttribPointer(
		m.shader.attribute_vertex,
		3,
		gl.FLOAT,
		gl.FALSE,
		0,
		gl.Pointer(nil))

	gl.BindBuffer(gl.ARRAY_BUFFER, m.normal_buf)
	gl.EnableVertexAttribArray(m.shader.attribute_normal)
	gl.VertexAttribPointer(
		m.shader.attribute_normal,
		3,
		gl.FLOAT,
		gl.FALSE,
		0,
		gl.Pointer(nil))

	gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, m.index)
	gl.DrawElements(gl.TRIANGLES, gl.Sizei(len(m.indices)), gl.UNSIGNED_INT, gl.Pointer(nil))

	gl.BindBuffer(gl.ARRAY_BUFFER, 0)
	gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, 0)
	gl.DisableVertexAttribArray(m.shader.attribute_vertex)
	gl.DisableVertexAttribArray(m.shader.attribute_normal)
	if m.has_uv {
		gl.DisableVertexAttribArray(m.shader.attribute_texcoord)
	}

}
Esempio n. 5
0
// Need floor, right wall, and left wall matrices to draw the details
func (room *Room) render(floor, left, right mathgl.Mat4, zoom float32, base_alpha byte, drawables []Drawable, los_tex *LosTexture, floor_drawers []FloorDrawer) {
	do_color := func(r, g, b, a byte) {
		R, G, B, A := room.Color()
		A = alphaMult(A, base_alpha)
		gl.Color4ub(alphaMult(R, r), alphaMult(G, g), alphaMult(B, b), alphaMult(A, a))
	}
	gl.Enable(gl.TEXTURE_2D)
	gl.Enable(gl.BLEND)
	gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
	gl.Enable(gl.STENCIL_TEST)
	gl.ClearStencil(0)
	gl.Clear(gl.STENCIL_BUFFER_BIT)

	gl.EnableClientState(gl.VERTEX_ARRAY)
	gl.EnableClientState(gl.TEXTURE_COORD_ARRAY)
	defer gl.DisableClientState(gl.VERTEX_ARRAY)
	defer gl.DisableClientState(gl.TEXTURE_COORD_ARRAY)

	var vert roomVertex

	planes := []plane{
		{room.left_buffer, room.Wall, &left},
		{room.right_buffer, room.Wall, &right},
		{room.floor_buffer, room.Floor, &floor},
	}

	gl.PushMatrix()
	defer gl.PopMatrix()

	if los_tex != nil {
		gl.LoadMatrixf(&floor[0])
		gl.ClientActiveTexture(gl.TEXTURE1)
		gl.ActiveTexture(gl.TEXTURE1)
		gl.Enable(gl.TEXTURE_2D)
		gl.EnableClientState(gl.TEXTURE_COORD_ARRAY)
		los_tex.Bind()
		gl.BindBuffer(gl.ARRAY_BUFFER, room.vbuffer)
		gl.TexCoordPointer(2, gl.FLOAT, gl.Sizei(unsafe.Sizeof(vert)), gl.Pointer(unsafe.Offsetof(vert.los_u)))
		gl.ClientActiveTexture(gl.TEXTURE0)
		gl.ActiveTexture(gl.TEXTURE0)
		base.EnableShader("los")
		base.SetUniformI("los", "tex2", 1)
	}

	var mul, run mathgl.Mat4
	for _, plane := range planes {
		gl.LoadMatrixf(&floor[0])
		run.Assign(&floor)

		// Render the doors and cut out the stencil buffer so we leave them empty
		// if they're open
		switch plane.mat {
		case &left:
			gl.StencilFunc(gl.ALWAYS, 1, 1)
			gl.StencilOp(gl.REPLACE, gl.REPLACE, gl.REPLACE)
			for _, door := range room.Doors {
				if door.Facing != FarLeft {
					continue
				}
				door.TextureData().Bind()
				R, G, B, A := door.Color()
				do_color(R, G, B, alphaMult(A, room.far_left.wall_alpha))
				gl.ClientActiveTexture(gl.TEXTURE0)
				door.TextureData().Bind()
				if door.door_glids.floor_buffer != 0 {
					gl.BindBuffer(gl.ARRAY_BUFFER, door.threshold_glids.vbuffer)
					gl.VertexPointer(3, gl.FLOAT, gl.Sizei(unsafe.Sizeof(vert)), gl.Pointer(unsafe.Offsetof(vert.x)))
					gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, door.door_glids.floor_buffer)
					gl.TexCoordPointer(2, gl.FLOAT, gl.Sizei(unsafe.Sizeof(vert)), gl.Pointer(unsafe.Offsetof(vert.u)))
					gl.ClientActiveTexture(gl.TEXTURE1)
					gl.TexCoordPointer(2, gl.FLOAT, gl.Sizei(unsafe.Sizeof(vert)), gl.Pointer(unsafe.Offsetof(vert.los_u)))
					gl.DrawElements(gl.TRIANGLES, door.door_glids.floor_count, gl.UNSIGNED_SHORT, nil)
				}
			}
			gl.StencilFunc(gl.NOTEQUAL, 1, 1)
			gl.StencilOp(gl.KEEP, gl.KEEP, gl.KEEP)
			do_color(255, 255, 255, room.far_left.wall_alpha)

		case &right:
			gl.StencilFunc(gl.ALWAYS, 1, 1)
			gl.StencilOp(gl.REPLACE, gl.REPLACE, gl.REPLACE)
			for _, door := range room.Doors {
				if door.Facing != FarRight {
					continue
				}
				door.TextureData().Bind()
				R, G, B, A := door.Color()
				do_color(R, G, B, alphaMult(A, room.far_right.wall_alpha))
				gl.ClientActiveTexture(gl.TEXTURE0)
				door.TextureData().Bind()
				if door.door_glids.floor_buffer != 0 {
					gl.BindBuffer(gl.ARRAY_BUFFER, door.threshold_glids.vbuffer)
					gl.VertexPointer(3, gl.FLOAT, gl.Sizei(unsafe.Sizeof(vert)), gl.Pointer(unsafe.Offsetof(vert.x)))
					gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, door.door_glids.floor_buffer)
					gl.TexCoordPointer(2, gl.FLOAT, gl.Sizei(unsafe.Sizeof(vert)), gl.Pointer(unsafe.Offsetof(vert.u)))
					gl.ClientActiveTexture(gl.TEXTURE1)
					gl.TexCoordPointer(2, gl.FLOAT, gl.Sizei(unsafe.Sizeof(vert)), gl.Pointer(unsafe.Offsetof(vert.los_u)))
					gl.DrawElements(gl.TRIANGLES, door.door_glids.floor_count, gl.UNSIGNED_SHORT, nil)
				}
			}
			gl.StencilFunc(gl.NOTEQUAL, 1, 1)
			gl.StencilOp(gl.KEEP, gl.KEEP, gl.KEEP)
			do_color(255, 255, 255, room.far_right.wall_alpha)

		case &floor:
			gl.StencilFunc(gl.ALWAYS, 2, 2)
			gl.StencilOp(gl.REPLACE, gl.REPLACE, gl.REPLACE)
			do_color(255, 255, 255, 255)
		}

		gl.ClientActiveTexture(gl.TEXTURE0)
		gl.BindBuffer(gl.ARRAY_BUFFER, room.vbuffer)
		gl.VertexPointer(3, gl.FLOAT, gl.Sizei(unsafe.Sizeof(vert)), gl.Pointer(unsafe.Offsetof(vert.x)))
		gl.TexCoordPointer(2, gl.FLOAT, gl.Sizei(unsafe.Sizeof(vert)), gl.Pointer(unsafe.Offsetof(vert.u)))
		gl.ClientActiveTexture(gl.TEXTURE1)
		if los_tex != nil {
			los_tex.Bind()
		}
		gl.BindBuffer(gl.ARRAY_BUFFER, room.vbuffer)
		gl.TexCoordPointer(2, gl.FLOAT, gl.Sizei(unsafe.Sizeof(vert)), gl.Pointer(unsafe.Offsetof(vert.los_u)))
		// Now draw the walls
		gl.LoadMatrixf(&floor[0])
		plane.texture.Data().Bind()
		gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, plane.index_buffer)
		if (plane.mat == &left || plane.mat == &right) && strings.Contains(string(room.Wall.Path), "gradient.png") {
			base.EnableShader("gorey")
			base.SetUniformI("gorey", "tex", 0)
			base.SetUniformI("gorey", "foo", Foo)
			base.SetUniformF("gorey", "num_rows", Num_rows)
			base.SetUniformF("gorey", "noise_rate", Noise_rate)
			base.SetUniformF("gorey", "num_steps", Num_steps)
		}
		if plane.mat == &floor && strings.Contains(string(room.Floor.Path), "gradient.png") {
			base.EnableShader("gorey")
			base.SetUniformI("gorey", "tex", 0)
			base.SetUniformI("gorey", "foo", Foo)
			base.SetUniformF("gorey", "num_rows", Num_rows)
			base.SetUniformF("gorey", "noise_rate", Noise_rate)
			base.SetUniformF("gorey", "num_steps", Num_steps)
			zexp := math.Log(float64(zoom))
			frac := 1 - 1/zexp
			frac = (frac - 0.6) * 5.0
			switch {
			case frac > 0.7:
				base.SetUniformI("gorey", "range", 1)
			case frac > 0.3:
				base.SetUniformI("gorey", "range", 2)
			default:
				base.SetUniformI("gorey", "range", 3)
			}
		}
		if plane.mat == &floor {
			R, G, B, _ := room.Color()
			gl.Color4ub(R, G, B, 255)
		}
		gl.DrawElements(gl.TRIANGLES, gl.Sizei(room.floor_count), gl.UNSIGNED_SHORT, nil)
		if los_tex != nil {
			base.EnableShader("los")
		} else {
			base.EnableShader("")
		}
	}

	for _, wt := range room.WallTextures {
		if room.wall_texture_gl_map == nil {
			room.wall_texture_gl_map = make(map[*WallTexture]wallTextureGlIds)
			room.wall_texture_state_map = make(map[*WallTexture]wallTextureState)
		}
		ids := room.wall_texture_gl_map[wt]
		state := room.wall_texture_state_map[wt]
		var new_state wallTextureState
		new_state.flip = wt.Flip
		new_state.rot = wt.Rot
		new_state.x = wt.X
		new_state.y = wt.Y
		new_state.room.x = room.X
		new_state.room.y = room.Y
		new_state.room.dx = room.Size.Dx
		new_state.room.dy = room.Size.Dy
		if new_state != state {
			wt.setupGlStuff(room.X, room.Y, room.Size.Dx, room.Size.Dy, &ids)
			room.wall_texture_gl_map[wt] = ids
			room.wall_texture_state_map[wt] = new_state
		}
		gl.LoadMatrixf(&floor[0])
		if ids.vbuffer != 0 {
			wt.Texture.Data().Bind()
			R, G, B, A := wt.Color()

			gl.ClientActiveTexture(gl.TEXTURE0)
			gl.BindBuffer(gl.ARRAY_BUFFER, ids.vbuffer)
			gl.VertexPointer(3, gl.FLOAT, gl.Sizei(unsafe.Sizeof(vert)), gl.Pointer(unsafe.Offsetof(vert.x)))
			gl.TexCoordPointer(2, gl.FLOAT, gl.Sizei(unsafe.Sizeof(vert)), gl.Pointer(unsafe.Offsetof(vert.u)))
			gl.ClientActiveTexture(gl.TEXTURE1)
			gl.TexCoordPointer(2, gl.FLOAT, gl.Sizei(unsafe.Sizeof(vert)), gl.Pointer(unsafe.Offsetof(vert.los_u)))
			gl.ClientActiveTexture(gl.TEXTURE0)
			if ids.floor_buffer != 0 {
				gl.StencilFunc(gl.ALWAYS, 2, 2)
				gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, ids.floor_buffer)
				gl.Color4ub(R, G, B, A)
				gl.DrawElements(gl.TRIANGLES, ids.floor_count, gl.UNSIGNED_SHORT, nil)
			}
			if ids.left_buffer != 0 {
				gl.StencilFunc(gl.ALWAYS, 1, 1)
				gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, ids.left_buffer)
				do_color(R, G, B, alphaMult(A, room.far_left.wall_alpha))
				gl.DrawElements(gl.TRIANGLES, ids.left_count, gl.UNSIGNED_SHORT, nil)
			}
			if ids.right_buffer != 0 {
				gl.StencilFunc(gl.ALWAYS, 1, 1)
				gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, ids.right_buffer)
				do_color(R, G, B, alphaMult(A, room.far_right.wall_alpha))
				gl.DrawElements(gl.TRIANGLES, ids.right_count, gl.UNSIGNED_SHORT, nil)
			}
		}
	}
	base.EnableShader("marble")
	base.SetUniformI("marble", "tex2", 1)
	base.SetUniformF("marble", "room_x", float32(room.X))
	base.SetUniformF("marble", "room_y", float32(room.Y))
	for _, door := range room.Doors {
		door.setupGlStuff(room)
		if door.threshold_glids.vbuffer == 0 {
			continue
		}
		if door.AlwaysOpen() {
			continue
		}
		if door.highlight_threshold {
			gl.Color4ub(255, 255, 255, 255)
		} else {
			gl.Color4ub(128, 128, 128, 255)
		}
		gl.BindBuffer(gl.ARRAY_BUFFER, door.threshold_glids.vbuffer)
		gl.VertexPointer(3, gl.FLOAT, gl.Sizei(unsafe.Sizeof(vert)), gl.Pointer(unsafe.Offsetof(vert.x)))
		gl.TexCoordPointer(2, gl.FLOAT, gl.Sizei(unsafe.Sizeof(vert)), gl.Pointer(unsafe.Offsetof(vert.u)))
		gl.ClientActiveTexture(gl.TEXTURE1)
		gl.TexCoordPointer(2, gl.FLOAT, gl.Sizei(unsafe.Sizeof(vert)), gl.Pointer(unsafe.Offsetof(vert.los_u)))
		gl.ClientActiveTexture(gl.TEXTURE0)
		gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, door.threshold_glids.floor_buffer)
		gl.DrawElements(gl.TRIANGLES, door.threshold_glids.floor_count, gl.UNSIGNED_SHORT, nil)
	}
	base.EnableShader("")
	if los_tex != nil {
		base.EnableShader("")
		gl.ActiveTexture(gl.TEXTURE1)
		gl.Disable(gl.TEXTURE_2D)
		gl.ActiveTexture(gl.TEXTURE0)
		gl.ClientActiveTexture(gl.TEXTURE1)
		gl.DisableClientState(gl.TEXTURE_COORD_ARRAY)
		gl.ClientActiveTexture(gl.TEXTURE0)
	}

	run.Assign(&floor)
	mul.Translation(float32(-room.X), float32(-room.Y), 0)
	run.Multiply(&mul)
	gl.LoadMatrixf(&run[0])
	gl.StencilFunc(gl.EQUAL, 2, 3)
	gl.StencilOp(gl.KEEP, gl.KEEP, gl.KEEP)
	room_rect := image.Rect(room.X, room.Y, room.X+room.Size.Dx, room.Y+room.Size.Dy)
	for _, fd := range floor_drawers {
		x, y := fd.Pos()
		dx, dy := fd.Dims()
		if room_rect.Overlaps(image.Rect(x, y, x+dx, y+dy)) {
			fd.RenderOnFloor()
		}
	}

	do_color(255, 255, 255, 255)
	gl.LoadIdentity()
	gl.Disable(gl.STENCIL_TEST)
	room.renderFurniture(floor, 255, drawables, los_tex)

	gl.ClientActiveTexture(gl.TEXTURE1)
	gl.Disable(gl.TEXTURE_2D)
	gl.ClientActiveTexture(gl.TEXTURE0)
	base.EnableShader("")
}
Esempio n. 6
0
func (ms *ManaSource) Draw(gw *GameWindow, dx float64, dy float64) {
	if gw.nodeTextureData == nil {
		//		gl.Enable(gl.TEXTURE_2D)
		gw.nodeTextureData = make([]byte, ms.options.NumNodeRows*ms.options.NumNodeCols*3)
		gl.GenTextures(1, &gw.nodeTextureId)
		gl.BindTexture(gl.TEXTURE_2D, gw.nodeTextureId)
		gl.TexEnvf(gl.TEXTURE_ENV, gl.TEXTURE_ENV_MODE, gl.MODULATE)
		gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
		gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
		gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT)
		gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT)
		gl.TexImage2D(
			gl.TEXTURE_2D,
			0,
			gl.RGB,
			gl.Sizei(ms.options.NumNodeCols),
			gl.Sizei(ms.options.NumNodeRows),
			0,
			gl.RGB,
			gl.UNSIGNED_BYTE,
			gl.Pointer(&gw.nodeTextureData[0]))

		//		gl.ActiveTexture(gl.TEXTURE1)
		gl.GenTextures(1, &gw.nodeWarpingTexture)
		gl.BindTexture(gl.TEXTURE_1D, gw.nodeWarpingTexture)
		gl.TexEnvf(gl.TEXTURE_ENV, gl.TEXTURE_ENV_MODE, gl.MODULATE)
		gl.TexParameterf(gl.TEXTURE_1D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
		gl.TexParameterf(gl.TEXTURE_1D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
		gl.TexParameterf(gl.TEXTURE_1D, gl.TEXTURE_WRAP_S, gl.REPEAT)
		gl.TexParameterf(gl.TEXTURE_1D, gl.TEXTURE_WRAP_T, gl.REPEAT)
		gw.nodeWarpingData = make([]byte, 4*10)
		gl.TexImage1D(
			gl.TEXTURE_1D,
			0,
			gl.RGBA,
			gl.Sizei(len(gw.nodeWarpingData)/4),
			0,
			gl.RGBA,
			gl.UNSIGNED_BYTE,
			gl.Pointer(&gw.nodeWarpingData[0]))
	}

	for x := range ms.nodes {
		for y, node := range ms.nodes[x] {
			pos := 3 * (y*ms.options.NumNodeCols + x)
			for c := 0; c < 3; c++ {
				color_frac := node.Mana[c] * 1.0 / ms.options.NodeMagnitude
				color_range := float64(ms.options.MaxNodeBrightness - ms.options.MinNodeBrightness)
				gw.nodeTextureData[pos+c] = byte(
					color_frac*color_range + float64(ms.options.MinNodeBrightness))
			}
		}
	}
	gl.Enable(gl.TEXTURE_1D)
	gl.Enable(gl.TEXTURE_2D)
	//gl.ActiveTexture(gl.TEXTURE0)
	gl.BindTexture(gl.TEXTURE_2D, gw.nodeTextureId)
	gl.TexSubImage2D(
		gl.TEXTURE_2D,
		0,
		0,
		0,
		gl.Sizei(ms.options.NumNodeCols),
		gl.Sizei(ms.options.NumNodeRows),
		gl.RGB,
		gl.UNSIGNED_BYTE,
		gl.Pointer(&gw.nodeTextureData[0]))

	gl.ActiveTexture(gl.TEXTURE1)
	for i, ent := range gw.game.Ents {
		p := ent.Pos()
		gw.nodeWarpingData[3*i+0] = byte(p.X / float64(gw.game.Dx) * 255)
		gw.nodeWarpingData[3*i+1] = -byte(p.Y / float64(gw.game.Dy) * 255)
		gw.nodeWarpingData[3*i+2] = 255
	}
	gl.TexImage1D(
		gl.TEXTURE_1D,
		0,
		gl.RGBA,
		gl.Sizei(len(gw.nodeWarpingData)/4),
		0,
		gl.RGBA,
		gl.UNSIGNED_BYTE,
		gl.Pointer(&gw.nodeWarpingData[0]))

	base.EnableShader("nodes")
	base.SetUniformI("nodes", "width", ms.options.NumNodeCols)
	base.SetUniformI("nodes", "height", ms.options.NumNodeRows)
	base.SetUniformI("nodes", "drains", 1)
	base.SetUniformI("nodes", "tex0", 0)
	base.SetUniformI("nodes", "tex1", 1)
	gl.ActiveTexture(gl.TEXTURE1)
	gl.BindTexture(gl.TEXTURE_1D, gw.nodeWarpingTexture)
	gl.ActiveTexture(gl.TEXTURE0)
	gl.BindTexture(gl.TEXTURE_2D, gw.nodeTextureId)
	texture.Render(0, dy, dx, -dy)
	base.EnableShader("")
	gl.Disable(gl.TEXTURE_2D)
	gl.Disable(gl.TEXTURE_1D)
}