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
// Creating a RenderObject with a given shaderProgram, texture, and set of
// vertices.
func CreateRenderObject(shaderProgram ShaderProgram, texture Texture, vertices []float32) *RenderObject {
	renderObject := new(RenderObject)

	// Creating the basic information.
	renderObject.shaderProgram = uint32(shaderProgram)
	renderObject.texture = uint32(texture)

	gl.GenVertexArrays(1, &renderObject.vao)
	gl.GenBuffers(1, &renderObject.vbo)
	gl.GenBuffers(1, &renderObject.ebo)

	// Filling the RenderObject with information.
	gl.BindVertexArray(renderObject.vao)
	gl.BindBuffer(gl.ARRAY_BUFFER, renderObject.vbo)
	gl.BufferData(gl.ARRAY_BUFFER, len(vertices)*4, gl.Ptr(vertices), gl.STATIC_DRAW)

	gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, renderObject.ebo)
	vertOrder := []uint32{
		0, 1, 2,
		2, 3, 0,
	}
	gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, len(vertOrder)*4, gl.Ptr(vertOrder), gl.STATIC_DRAW)

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

	// Loading up texture attributes.
	texAttrib := uint32(gl.GetAttribLocation(renderObject.shaderProgram, gl.Str("vertTexCoord\x00")))
	gl.EnableVertexAttribArray(texAttrib)
	gl.VertexAttribPointer(texAttrib, 2, gl.FLOAT, false, 4*4, gl.PtrOffset(2*4))

	return renderObject
}
Example #3
0
func LoadText(f *Font) (t *Text) {
	t = new(Text)
	t.font = f

	// text hover values
	// "resting state" of a text object is the min scale
	t.ScaleMin = 1.0
	t.ScaleMax = 1.1
	t.SetScale(1)

	// size of glfloat
	glfloat_size := int32(4)

	// stride of the buffered data
	xy_count := int32(2)
	stride := xy_count + int32(2)

	gl.GenVertexArrays(1, &t.vao)
	gl.GenBuffers(1, &t.vbo)
	gl.GenBuffers(1, &t.ebo)

	// vao
	gl.BindVertexArray(t.vao)

	gl.ActiveTexture(gl.TEXTURE0)
	gl.BindTexture(gl.TEXTURE_2D, t.font.textureID)

	// vbo
	// specify the buffer for which the VertexAttribPointer calls apply
	gl.BindBuffer(gl.ARRAY_BUFFER, t.vbo)

	gl.EnableVertexAttribArray(t.font.centeredPosition)
	gl.VertexAttribPointer(
		t.font.centeredPosition,
		2,
		gl.FLOAT,
		false,
		glfloat_size*stride,
		gl.PtrOffset(0),
	)

	gl.EnableVertexAttribArray(t.font.uv)
	gl.VertexAttribPointer(
		t.font.uv,
		2,
		gl.FLOAT,
		false,
		glfloat_size*stride,
		gl.PtrOffset(int(glfloat_size*xy_count)),
	)

	// ebo
	gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, t.ebo)

	// i am guessing that order is important here
	gl.BindVertexArray(0)
	gl.BindBuffer(gl.ARRAY_BUFFER, 0)
	gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, 0)
	return t
}
Example #4
0
func (tr *TextRenderer) Bind() error {
	gl.UseProgram(tr.Program)
	if e := gl.GetError(); e != 0 {
		return fmt.Errorf("ERROR: %X", e)
	}
	gl.Uniform1i(tr.TextureUnitLoc, 0)
	if e := gl.GetError(); e != 0 {
		return fmt.Errorf("ERROR: %X", e)
	}
	gl.BindBuffer(gl.ARRAY_BUFFER, tr.VBO)
	if e := gl.GetError(); e != 0 {
		return fmt.Errorf("ERROR: %X", e)
	}
	gl.EnableVertexAttribArray(tr.PositionLoc)
	gl.VertexAttribPointer(tr.PositionLoc, 3, gl.FLOAT, false, 5*4, gl.PtrOffset(0))
	if e := gl.GetError(); e != 0 {
		return fmt.Errorf("ERROR: %X", e)
	}
	gl.EnableVertexAttribArray(tr.TextureLoc)
	gl.VertexAttribPointer(tr.TextureLoc, 2, gl.FLOAT, false, 5*4, gl.PtrOffset(3*4))
	if e := gl.GetError(); e != 0 {
		return fmt.Errorf("ERROR: %X", e)
	}
	gl.UniformMatrix4fv(tr.ProjectionLoc, 1, false, &tr.Renderer.Camera.Projection[0])
	if e := gl.GetError(); e != 0 {
		return fmt.Errorf("ERROR: %X", e)
	}
	return nil
}
Example #5
0
//Fstri draws a fullscreen triangle such that it covers the entire screen with uv coordinates from [0,0]-[1,1]
func Fstri() {
	fstri.vao.Bind()
	defer fstri.vao.Unbind()
	gl.EnableVertexAttribArray(0)
	fstri.pos.Bind(gl.ARRAY_BUFFER)
	gl.VertexAttribPointer(0, 2, gl.FLOAT, false, 0, nil)

	gl.EnableVertexAttribArray(1)
	fstri.uv.Bind(gl.ARRAY_BUFFER)
	gl.VertexAttribPointer(1, 2, gl.FLOAT, false, 0, nil)

	gl.DrawArrays(gl.TRIANGLES, 0, 3)
}
Example #6
0
func (r *BatchRenderer) Draw(batch *Batch, x, y, rot float32) error {
	batch.Texture.Bind()
	gl.BindBuffer(gl.ARRAY_BUFFER, batch.Buffer)
	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))
	m := mgl32.Translate3D(x, y, 0.0).Mul4(mgl32.HomogRotate3DZ(rot))
	gl.UniformMatrix4fv(r.ModelViewLoc, 1, false, &m[0])
	gl.Uniform2f(r.TexOffsetLoc, batch.textureOffset.X(), batch.textureOffset.Y())
	gl.DrawArrays(gl.TRIANGLES, 0, int32(batch.Count))
	gl.BindBuffer(gl.ARRAY_BUFFER, 0)
	return nil
}
Example #7
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 #8
0
func (lr *LinesRenderer) Bind() (err error) {
	gl.UseProgram(lr.program)
	gl.BindBuffer(gl.ARRAY_BUFFER, lr.buffer)
	gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, lr.indexBuffer)
	gl.EnableVertexAttribArray(lr.positionLoc)
	gl.EnableVertexAttribArray(lr.normalLoc)
	gl.EnableVertexAttribArray(lr.miterLoc)
	gl.VertexAttribPointer(lr.positionLoc, 2, gl.FLOAT, false, lr.stride, lr.offPosition)
	gl.VertexAttribPointer(lr.normalLoc, 2, gl.FLOAT, false, lr.stride, lr.offNormal)
	gl.VertexAttribPointer(lr.miterLoc, 1, gl.FLOAT, false, lr.stride, lr.offMiter)
	gl.UniformMatrix4fv(lr.projectionLoc, 1, false, &lr.Renderer.Camera.Projection[0])
	if e := gl.GetError(); e != 0 {
		err = fmt.Errorf("ERROR: OpenGL error %X", e)
	}
	return
}
Example #9
0
func customLandscapeBinder(renderer fizzle.Renderer, r *fizzle.Renderable, shader *fizzle.RenderShader) {
	shaderCombo1 := shader.GetAttribLocation("VERTEX_COLOR")
	if shaderCombo1 >= 0 {
		gl.BindBuffer(gl.ARRAY_BUFFER, r.Core.ComboVBO1)
		gl.EnableVertexAttribArray(uint32(shaderCombo1))
		gl.VertexAttribPointer(uint32(shaderCombo1), 3, gl.FLOAT, false, 0, gl.PtrOffset(0))
	}
}
Example #10
0
func (ps *ParticleSystem) Render(delta float64, VP glm.Mat4, camera glm.Vec3) {
	ps.time += delta

	//do update

	ps.gTime.Uniform1f(float32(ps.time) * 1000)
	ps.gDeltaTimeMillis.Uniform1f(float32(delta) * 1000)

	//bind the rand texture
	//m_randomTexture.Bind(RANDOM_TEXTURE_UNIT);

	gl.Enable(gl.RASTERIZER_DISCARD)
	ps.buffers[ps.currentVB].Bind(gl.ARRAY_BUFFER)
	ps.transformfeedbacks[ps.currentTFB].Bind()
	gl.EnableVertexAttribArray(0)
	gl.EnableVertexAttribArray(1)
	gl.EnableVertexAttribArray(2)
	gl.EnableVertexAttribArray(3)

	gl.VertexAttribPointer(0, 1, gl.FLOAT, false, int32(unsafe.Sizeof(Particle{})), unsafe.Pointer(uintptr(0)))
	gl.VertexAttribPointer(1, 3, gl.FLOAT, false, int32(unsafe.Sizeof(Particle{})), unsafe.Pointer(uintptr(4)))
	gl.VertexAttribPointer(2, 3, gl.FLOAT, false, int32(unsafe.Sizeof(Particle{})), unsafe.Pointer(uintptr(16)))
	gl.VertexAttribPointer(3, 1, gl.FLOAT, false, int32(unsafe.Sizeof(Particle{})), unsafe.Pointer(uintptr(28)))

	gl.BeginTransformFeedback(gl.POINTS)

	if ps.isFirst {
		gl.DrawArrays(gl.POINTS, 0, 1)
		ps.isFirst = false
	} else {
		gl.DrawTransformFeedback(gl.POINTS, uint32(ps.transformfeedbacks[ps.currentVB]))
	}
	gl.EndTransformFeedback()
	gl.DisableVertexAttribArray(0)
	gl.DisableVertexAttribArray(1)
	gl.DisableVertexAttribArray(2)
	gl.DisableVertexAttribArray(3)

	//do render
	ps.currentVB = ps.currentTFB
	ps.currentTFB = (ps.currentTFB + 1) & 0x1
}
Example #11
0
func (r *EffectsRenderer) Draw() (err error) {
	gl.UseProgram(r.shader)
	gl.Uniform1i(r.textureUnitLoc, 0)
	gl.Uniform3f(r.colorLoc, r.Color[0], r.Color[1], r.Color[2])
	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.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.texture)
	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 #12
0
func BindBuffers() { //vertexData *OpenGLVertexInfo) {

	vertexData := &vertexDataTest

	// check to see if there are any vertices at all to bind
	if len(vertexData.vertexData) == 0 {
		return
	}

	gl.BindBuffer(gl.ARRAY_BUFFER, vbo)
	gl.BufferData(gl.ARRAY_BUFFER, len(vertexData.vertexData)*4, gl.Ptr(vertexData.vertexData), gl.DYNAMIC_DRAW)

	positionAttrib := uint32(gl.GetAttribLocation(program, gl.Str("vertexPosition_modelspace\x00")))
	gl.EnableVertexAttribArray(positionAttrib)
	gl.VertexAttribPointer(positionAttrib, 3, gl.FLOAT, false, 4*NUM_ATTRIBUTES, gl.PtrOffset(0))

	colorAttrib := uint32(gl.GetAttribLocation(program, gl.Str("diffuse\x00")))
	gl.EnableVertexAttribArray(colorAttrib)
	gl.VertexAttribPointer(colorAttrib, 4, gl.FLOAT, false, 4*NUM_ATTRIBUTES, gl.PtrOffset(3*4))

	uvAttrib := uint32(gl.GetAttribLocation(program, gl.Str("vertexUV\x00")))
	gl.EnableVertexAttribArray(uvAttrib)
	gl.VertexAttribPointer(uvAttrib, 2, gl.FLOAT, false, 4*NUM_ATTRIBUTES, gl.PtrOffset(7*4))

	mNormAttrib := uint32(gl.GetAttribLocation(program, gl.Str("mNorm\x00")))
	gl.EnableVertexAttribArray(mNormAttrib)
	gl.VertexAttribPointer(mNormAttrib, 3, gl.FLOAT, false, 4*NUM_ATTRIBUTES, gl.PtrOffset(9*4))

	wNormAttrib := uint32(gl.GetAttribLocation(program, gl.Str("wNorm\x00")))
	gl.EnableVertexAttribArray(wNormAttrib)
	gl.VertexAttribPointer(wNormAttrib, 3, gl.FLOAT, false, 4*NUM_ATTRIBUTES, gl.PtrOffset(12*4))

	shaderMode := uint32(gl.GetAttribLocation(program, gl.Str("mode\x00")))
	gl.EnableVertexAttribArray(shaderMode)
	gl.VertexAttribPointer(shaderMode, 1, gl.FLOAT, false, 4*NUM_ATTRIBUTES, gl.PtrOffset(15*4))

	samplerIdx := uint32(gl.GetAttribLocation(program, gl.Str("samplerIdx\x00")))
	gl.EnableVertexAttribArray(samplerIdx)
	gl.VertexAttribPointer(samplerIdx, 1, gl.FLOAT, false, 4*NUM_ATTRIBUTES, gl.PtrOffset(16*4))

	// gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementvbo)
	// gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, len(vertexData.Elements)*4, gl.Ptr(vertexData.Elements), gl.STATIC_DRAW)

	// gl.ActiveTexture(gl.TEXTURE0)
	// gl.BindTexture(gl.TEXTURE_2D, 1)
}
Example #13
0
func NewFramerateRenderer() (r *Framerate, err error) {
	r = &Framerate{
		shader: core.NewProgram(),
		data:   newFramerateData(120),
	}
	if err = r.shader.Load(FRAMERATE_VERTEX, FRAMERATE_FRAGMENT); err != nil {
		return
	}
	r.shader.Bind()
	gl.GenBuffers(1, &r.vbo)
	gl.BindBuffer(gl.ARRAY_BUFFER, r.vbo)
	var (
		point       framerateDataPoint
		locPosition = uint32(gl.GetAttribLocation(r.shader.ID(), gl.Str("v_Position\x00")))
		offPosition = gl.PtrOffset(int(unsafe.Offsetof(point.pos)))
	)
	r.stride = int32(unsafe.Sizeof(point))
	r.locColor = gl.GetUniformLocation(r.shader.ID(), gl.Str("v_Color\x00"))
	r.locModelView = gl.GetUniformLocation(r.shader.ID(), gl.Str("m_ModelView\x00"))
	r.locProjection = gl.GetUniformLocation(r.shader.ID(), gl.Str("m_Projection\x00"))
	gl.EnableVertexAttribArray(locPosition)
	gl.VertexAttribPointer(locPosition, 2, gl.FLOAT, false, r.stride, offPosition)
	return
}
Example #14
0
func (tr *SpriteRenderer) Draw(instances []SpriteConfig) error {
	var (
		bytesNeeded int
		byteoffset  int
		count       int32
		data        unsafe.Pointer
		float       float32 = 0
		floatSize   uint32
		i           uint32
		offset      unsafe.Pointer
		sprite      SpriteConfig
		stride      int32
	)

	floatSize = uint32(unsafe.Sizeof(float))
	stride = int32(unsafe.Sizeof(sprite))

	gl.UseProgram(tr.program)
	gl.Uniform1i(tr.textureUnitLoc, 0)

	// Instance data binding
	gl.BindBuffer(gl.ARRAY_BUFFER, tr.instanceVBO)
	count = int32(len(instances))
	bytesNeeded = int(stride * count)
	data = gl.Ptr(instances)
	if bytesNeeded > tr.instanceBytes {
		gl.BufferData(gl.ARRAY_BUFFER, bytesNeeded, data, gl.STREAM_DRAW)
		tr.instanceBytes = bytesNeeded
	} else {
		gl.BufferSubData(gl.ARRAY_BUFFER, 0, bytesNeeded, data)
	}

	gl.EnableVertexAttribArray(tr.translationLoc)
	gl.VertexAttribPointer(tr.translationLoc, 3, gl.FLOAT, false, stride, tr.offAttrX)
	gl.VertexAttribDivisor(tr.translationLoc, 1)

	gl.EnableVertexAttribArray(tr.rotationLoc)
	gl.VertexAttribPointer(tr.rotationLoc, 3, gl.FLOAT, false, stride, tr.offAttrRotationX)
	gl.VertexAttribDivisor(tr.rotationLoc, 1)

	gl.EnableVertexAttribArray(tr.scaleLoc)
	gl.VertexAttribPointer(tr.scaleLoc, 3, gl.FLOAT, false, stride, tr.offAttrScaleX)
	gl.VertexAttribDivisor(tr.scaleLoc, 1)

	gl.EnableVertexAttribArray(tr.colorLoc)
	gl.VertexAttribPointer(tr.colorLoc, 4, gl.FLOAT, false, stride, tr.offAttrColor)
	gl.VertexAttribDivisor(tr.colorLoc, 1)

	for i = 0; i < 4; i++ {
		byteoffset = int(i * 4 * floatSize)
		offset = gl.PtrOffset(tr.offAttrPointAdj + byteoffset)
		gl.EnableVertexAttribArray(tr.pointAdjLoc + i)
		gl.VertexAttribPointer(tr.pointAdjLoc+i, 4, gl.FLOAT, false, stride, offset)
		gl.VertexAttribDivisor(tr.pointAdjLoc+i, 1)

		offset = gl.PtrOffset(tr.offAttrTextureAdj + byteoffset)
		gl.EnableVertexAttribArray(tr.textureAdjLoc + i)
		gl.VertexAttribPointer(tr.textureAdjLoc+i, 4, gl.FLOAT, false, stride, offset)
		gl.VertexAttribDivisor(tr.textureAdjLoc+i, 1)
	}
	// Projection
	gl.UniformMatrix4fv(tr.projectionLoc, 1, false, &tr.Renderer.Camera.Projection[0])

	// Actually draw.
	gl.DrawArraysInstanced(gl.TRIANGLES, 0, 6, int32(len(instances)))

	// Undo instance attr repetition.
	gl.VertexAttribDivisor(tr.translationLoc, 0)
	gl.VertexAttribDivisor(tr.rotationLoc, 0)
	gl.VertexAttribDivisor(tr.scaleLoc, 0)
	gl.VertexAttribDivisor(tr.colorLoc, 0)
	for i = 0; i < 4; i++ {
		gl.VertexAttribDivisor(tr.pointAdjLoc+i, 0)
		gl.VertexAttribDivisor(tr.textureAdjLoc+i, 0)
	}

	gl.BindBuffer(gl.ARRAY_BUFFER, 0)
	return nil
}
Example #15
0
func CreateContext(width, height int) Context {
	vertexShader := `
#version 330
uniform mat4 projection;
uniform mat4 camera;
uniform mat4 model;
in vec3 vert;
void main() {
    gl_Position = projection * camera * model * vec4(vert, 1);
}
` + "\x00"

	fragmentShader := `
#version 330
uniform vec4 color;
out vec4 outputColor;
void main() {
    outputColor = color;
}
` + "\x00"

	vertices := []float32{
		0.0, 0.0, 0.0,
		1.0, 0.0, 0.0,
		1.0, 1.0, 0.0,
		1.0, 1.0, 0.0,
		0.0, 1.0, 0.0,
		0.0, 0.0, 0.0,
	}

	if err := glfw.Init(); err != nil {
		log.Fatalln("failed to initialize glfw:", err)
	}
	// defer glfw.Terminate()

	glfw.WindowHint(glfw.Resizable, glfw.False)
	glfw.WindowHint(glfw.ContextVersionMajor, 3)
	glfw.WindowHint(glfw.ContextVersionMinor, 3)
	glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile)
	glfw.WindowHint(glfw.OpenGLForwardCompatible, glfw.True)
	window, err := glfw.CreateWindow(width, height, "OpenGL", nil, nil)
	if err != nil {
		panic(err)
	}
	window.MakeContextCurrent()

	if err := gl.Init(); err != nil {
		panic(err)
	}

	program, err := newProgram(vertexShader, fragmentShader)
	if err != nil {
		panic(err)
	}

	gl.UseProgram(program)

	projection := mgl32.Ortho2D(0, 800, 0, 600)
	projectionUniform := gl.GetUniformLocation(program, gl.Str("projection\x00"))
	gl.UniformMatrix4fv(projectionUniform, 1, false, &projection[0])

	camera := mgl32.LookAtV(mgl32.Vec3{0, 0, 0.5}, mgl32.Vec3{0, 0, 0}, mgl32.Vec3{0, 1, 0})
	cameraUniform := gl.GetUniformLocation(program, gl.Str("camera\x00"))
	gl.UniformMatrix4fv(cameraUniform, 1, false, &camera[0])

	model := mgl32.Ident4()
	modelUniform := gl.GetUniformLocation(program, gl.Str("model\x00"))
	gl.UniformMatrix4fv(modelUniform, 1, false, &model[0])

	var vao uint32
	gl.GenVertexArrays(1, &vao)
	gl.BindVertexArray(vao)

	var vbo uint32
	gl.GenBuffers(1, &vbo)
	gl.BindBuffer(gl.ARRAY_BUFFER, vbo)
	gl.BufferData(gl.ARRAY_BUFFER, len(vertices)*4, gl.Ptr(vertices), gl.STATIC_DRAW)

	vertAttrib := uint32(gl.GetAttribLocation(program, gl.Str("vert\x00")))
	gl.EnableVertexAttribArray(vertAttrib)
	gl.VertexAttribPointer(vertAttrib, 3, gl.FLOAT, false, 3*4, gl.PtrOffset(0))

	gl.Enable(gl.DEPTH_TEST)
	gl.DepthFunc(gl.LESS)

	return Context{Window: window, program: program}
}
Example #16
0
func main() {
	vertices, normals := obj.Parse(os.Args[1])

	// initialize GLFW
	if err := glfw.Init(); err != nil {
		panic(err)
	}
	defer glfw.Terminate()

	// set opengl core profile 3.3
	glfw.WindowHint(glfw.ContextVersionMajor, 3)
	glfw.WindowHint(glfw.ContextVersionMinor, 3)
	glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile)
	glfw.WindowHint(glfw.OpenGLForwardCompatible, glfw.True)

	window, err := glfw.CreateWindow(640, 480, "GOpenGL", nil, nil)
	if err != nil {
		panic(err)
	}
	window.MakeContextCurrent()

	// initialise OpenGL library
	if err := gl.Init(); err != nil {
		panic(err)
	}

	// link program from shaders
	program, err := newProgram("vertex.glsl", "fragment.glsl")
	if err != nil {
		panic(err)
	}
	gl.UseProgram(program)

	// vertex attribute object holds links between attributes and vbo
	var vao uint32
	gl.GenVertexArrays(1, &vao)
	gl.BindVertexArray(vao)

	// vertex buffer with per-vertex data
	var vbo [2]uint32
	gl.GenBuffers(2, &vbo[0])

	// position data
	gl.BindBuffer(gl.ARRAY_BUFFER, vbo[0])
	gl.BufferData(gl.ARRAY_BUFFER, len(vertices)*4, gl.Ptr(vertices), gl.STATIC_DRAW)

	// set up position attribute with layout of vertices
	posAttrib := uint32(gl.GetAttribLocation(program, gl.Str("position\x00")))
	gl.VertexAttribPointer(posAttrib, 3, gl.FLOAT, false, 3*4, gl.PtrOffset(0))
	gl.EnableVertexAttribArray(posAttrib)

	// normal data
	gl.BindBuffer(gl.ARRAY_BUFFER, vbo[1])
	gl.BufferData(gl.ARRAY_BUFFER, len(normals)*4, gl.Ptr(normals), gl.STATIC_DRAW)

	normAttrib := uint32(gl.GetAttribLocation(program, gl.Str("normal\x00")))
	gl.VertexAttribPointer(normAttrib, 3, gl.FLOAT, false, 3*4, gl.PtrOffset(0))
	gl.EnableVertexAttribArray(normAttrib)

	uniModel := gl.GetUniformLocation(program, gl.Str("model\x00"))
	uniView := gl.GetUniformLocation(program, gl.Str("view\x00"))
	uniProj := gl.GetUniformLocation(program, gl.Str("proj\x00"))

	matView := mgl32.LookAt(2.0, 2.0, 2.0,
		0.0, 0.0, 0.0,
		0.0, 0.0, 1.0)
	gl.UniformMatrix4fv(uniView, 1, false, &matView[0])

	matProj := mgl32.Perspective(mgl32.DegToRad(45.0), 640.0/480.0, 1.0, 10.0)
	gl.UniformMatrix4fv(uniProj, 1, false, &matProj[0])

	uniLightDir := gl.GetUniformLocation(program, gl.Str("lightDir\x00"))
	uniLightCol := gl.GetUniformLocation(program, gl.Str("lightCol\x00"))

	gl.Uniform3f(uniLightDir, -0.5, 0.0, -1.0)
	gl.Uniform3f(uniLightCol, 0.0, 0.5, 0.5)

	startTime := glfw.GetTime()
	gl.Enable(gl.DEPTH_TEST)
	gl.ClearColor(1.0, 1.0, 1.0, 1.0)

	for !window.ShouldClose() {
		// clear buffer
		gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)

		matRot := mgl32.HomogRotate3DZ(float32(glfw.GetTime() - startTime))
		gl.UniformMatrix4fv(uniModel, 1, false, &matRot[0])

		gl.DrawArrays(gl.TRIANGLES, 0, int32(len(vertices)))

		window.SwapBuffers()
		glfw.PollEvents()
	}
}
Example #17
0
func main() {
	// init glfw
	if err := glfw.Init(); err != nil {
		panic(err)
	}

	defer glfw.Terminate()

	glfw.WindowHint(glfw.Resizable, glfw.False)
	glfw.WindowHint(glfw.ContextVersionMajor, 4)
	glfw.WindowHint(glfw.ContextVersionMinor, 1)
	glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile)
	glfw.WindowHint(glfw.OpenGLForwardCompatible, glfw.True)

	// make an application window
	window, err := glfw.CreateWindow(windowWidth, windowHeight, "Hello", nil, nil)
	if err != nil {
		panic(err)
	}
	window.MakeContextCurrent()

	// init gl
	if err := gl.Init(); err != nil {
		panic(err)
	}
	fmt.Println("OpenGL version", gl.GoStr(gl.GetString(gl.VERSION)))

	// create vertex & fragment shader
	program, err := newProgram(vertexShader, fragmentShader)
	if err != nil {
		panic(err)
	}
	gl.UseProgram(program)

	gl.BindFragDataLocation(program, 0, gl.Str("fc\x00"))

	points := []float32{
		-0.5, -0.5,
		0.5, 0.5,
		0.5, -0.5,
		-0.5, 0.5,
	}

	vertices := []uint32{
		0, 2, 1, 3,
	}

	// configure the vertex data
	var vao uint32
	gl.GenVertexArrays(1, &vao)
	gl.BindVertexArray(vao)

	defer gl.BindVertexArray(0)

	var vbo uint32
	gl.GenBuffers(1, &vbo)
	gl.BindBuffer(gl.ARRAY_BUFFER, vbo)
	gl.BufferData(gl.ARRAY_BUFFER, len(points)*4, gl.Ptr(points), gl.STATIC_DRAW)

	var ibo uint32
	gl.GenBuffers(1, &ibo)
	gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo)
	gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, len(vertices)*4, gl.Ptr(vertices), gl.STATIC_DRAW)

	vertAttrib := uint32(gl.GetAttribLocation(program, gl.Str("pv\x00")))
	gl.EnableVertexAttribArray(vertAttrib)
	gl.VertexAttribPointer(vertAttrib, 2, gl.FLOAT, false, 2*4, gl.PtrOffset(0))

	// global settings
	gl.Enable(gl.DEPTH_TEST)
	gl.DepthFunc(gl.LESS)
	gl.ClearColor(1.0, 1.0, 1.0, 1.0)

	for !window.ShouldClose() {
		gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)

		gl.UseProgram(program)

		gl.BindVertexArray(vao)

		gl.DrawElements(gl.LINE_LOOP, 4, gl.UNSIGNED_INT, gl.PtrOffset(0))

		window.SwapBuffers()
		glfw.PollEvents()
	}
}
Example #18
0
func main() {
	// init glfw
	if err := glfw.Init(); err != nil {
		panic(err)
	}

	defer glfw.Terminate()

	glfw.WindowHint(glfw.Resizable, glfw.False)
	glfw.WindowHint(glfw.ContextVersionMajor, 4)
	glfw.WindowHint(glfw.ContextVersionMinor, 1)
	glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile)
	glfw.WindowHint(glfw.OpenGLForwardCompatible, glfw.True)

	// make an application window
	window, err := glfw.CreateWindow(windowWidth, windowHeight, "Transform", nil, nil)
	if err != nil {
		panic(err)
	}
	window.MakeContextCurrent()

	// init gl
	if err := gl.Init(); err != nil {
		panic(err)
	}
	fmt.Println("OpenGL version", gl.GoStr(gl.GetString(gl.VERSION)))

	// create vertex & fragment shader
	program, err := newProgram(vertexShader, fragmentShader)
	if err != nil {
		panic(err)
	}
	gl.UseProgram(program)

	projection := mgl32.Perspective(mgl32.DegToRad(45.0), float32(windowWidth)/windowHeight, 0.1, 10.0)
	projectionUniform := gl.GetUniformLocation(program, gl.Str("projection\x00"))
	gl.UniformMatrix4fv(projectionUniform, 1, false, &projection[0])

	camera := mgl32.LookAtV(
		mgl32.Vec3{3, 3, 3},
		mgl32.Vec3{0, 0, 0},
		mgl32.Vec3{0, 1, 0},
	)
	cameraUniform := gl.GetUniformLocation(program, gl.Str("camera\x00"))
	gl.UniformMatrix4fv(cameraUniform, 1, false, &camera[0])

	model := mgl32.Ident4()
	modelUniform := gl.GetUniformLocation(program, gl.Str("model\x00"))
	gl.UniformMatrix4fv(modelUniform, 1, false, &model[0])

	gl.BindFragDataLocation(program, 0, gl.Str("vert\x00"))

	points := []float32{
		-0.9, -0.9, -0.9,
		0.9, -0.9, -0.9,
		0.9, -0.9, 0.9,
		-0.9, -0.9, 0.9,
		-0.9, 0.9, -0.9,
		0.9, 0.9, -0.9,
		0.9, 0.9, 0.9,
		-0.9, 0.9, 0.9,
	}

	vertices := []uint32{
		0, 1,
		1, 2,
		2, 3,
		3, 0,
		0, 4,
		1, 5,
		2, 6,
		3, 7,
		4, 5,
		5, 6,
		6, 7,
		7, 4,
	}

	// configure the vertex data
	var vao uint32
	gl.GenVertexArrays(1, &vao)
	gl.BindVertexArray(vao)

	defer gl.BindVertexArray(0)

	var vbo uint32
	gl.GenBuffers(1, &vbo)
	gl.BindBuffer(gl.ARRAY_BUFFER, vbo)
	gl.BufferData(gl.ARRAY_BUFFER, len(points)*4, gl.Ptr(points), gl.STATIC_DRAW)

	var ibo uint32
	gl.GenBuffers(1, &ibo)
	gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo)
	gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, len(vertices)*4, gl.Ptr(vertices), gl.STATIC_DRAW)

	vertAttrib := uint32(gl.GetAttribLocation(program, gl.Str("vert\x00")))
	gl.EnableVertexAttribArray(vertAttrib)
	gl.VertexAttribPointer(vertAttrib, 3, gl.FLOAT, false, 3*4, gl.PtrOffset(0))

	// global settings
	gl.Enable(gl.DEPTH_TEST)
	gl.DepthFunc(gl.LESS)
	gl.ClearColor(0.0, 0.0, 0.0, 1.0)

	angleX := 0.0
	angleY := 0.0
	angleZ := 0.0
	previousTime := glfw.GetTime()

	for !window.ShouldClose() {
		gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)

		time := glfw.GetTime()
		elapsed := time - previousTime
		previousTime = time

		angleX += math.Sin((elapsed / period) * math.Pi * 2.0)
		angleY += math.Sin((elapsed / period) / 6.0 * math.Pi * 2.0)
		angleZ += math.Sin((elapsed / period) / 3.0 * math.Pi * 2.0)
		model = mgl32.HomogRotate3DY(float32(angleY)).Mul4(mgl32.HomogRotate3DX(float32(angleX))).Mul4(mgl32.HomogRotate3DZ(float32(angleZ)))
		gl.UseProgram(program)
		gl.UniformMatrix4fv(modelUniform, 1, false, &model[0])

		gl.BindVertexArray(vao)

		gl.DrawElements(gl.LINES, int32(len(vertices)), gl.UNSIGNED_INT, gl.PtrOffset(0))

		window.SwapBuffers()
		glfw.PollEvents()
	}
}
Example #19
0
func createMeshes(objs []*obj) []*mesh {
	var vertexTable []*objVertex
	var normalTable []*objNormal
	var texCoordTable []*objTexCoord

	var vertices []float32
	var normals []float32
	var texCoords []float32

	elementIndexMap := map[objFaceElement]uint16{}
	var nextIndex uint16

	var meshes []*mesh
	var iboNames []uint32

	for _, o := range objs {
		for _, v := range o.vertices {
			vertexTable = append(vertexTable, v)
		}
		for _, n := range o.normals {
			normalTable = append(normalTable, n)
		}
		for _, tc := range o.texCoords {
			texCoordTable = append(texCoordTable, tc)
		}

		var indices []uint16
		for _, f := range o.faces {
			for _, e := range f {
				if _, exists := elementIndexMap[e]; !exists {
					elementIndexMap[e] = nextIndex
					nextIndex++

					v := vertexTable[e.vertexIndex-1]
					vertices = append(vertices, v.x, v.y, v.z)

					n := normalTable[e.normalIndex-1]
					normals = append(normals, n.x, n.y, n.z)

					// Flip the y-axis to convert from OBJ to OpenGL.
					// OpenGL considers the origin to be lower left.
					// OBJ considers the origin to be upper left.
					tc := texCoordTable[e.texCoordIndex-1]
					texCoords = append(texCoords, tc.s, 1.0-tc.t)
				}

				indices = append(indices, elementIndexMap[e])
			}
		}

		meshes = append(meshes, &mesh{
			id:    o.id,
			count: int32(len(indices)),
		})
		iboNames = append(iboNames, createElementArrayBuffer(indices))
	}

	log.Printf("vertices: %d", len(vertexTable))
	log.Printf("normals: %d", len(normalTable))
	log.Printf("texCoords: %d", len(texCoordTable))

	vbo := createArrayBuffer(vertices)
	nbo := createArrayBuffer(normals)
	tbo := createArrayBuffer(texCoords)

	const (
		positionLocation = iota
		normalLocation
		texCoordLocation
	)

	for i, m := range meshes {
		gl.GenVertexArrays(1, &m.vao)
		gl.BindVertexArray(m.vao)

		gl.BindBuffer(gl.ARRAY_BUFFER, vbo)
		gl.EnableVertexAttribArray(positionLocation)
		gl.VertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 0, gl.PtrOffset(0))

		gl.BindBuffer(gl.ARRAY_BUFFER, nbo)
		gl.EnableVertexAttribArray(normalLocation)
		gl.VertexAttribPointer(normalLocation, 3, gl.FLOAT, false, 0, gl.PtrOffset(0))

		gl.BindBuffer(gl.ARRAY_BUFFER, tbo)
		gl.EnableVertexAttribArray(texCoordLocation)
		gl.VertexAttribPointer(texCoordLocation, 2, gl.FLOAT, false, 0, gl.PtrOffset(0))

		gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, iboNames[i])
		gl.BindVertexArray(0)
	}

	return meshes
}
Example #20
0
func (a *VertexAttribute) vertexAttrib(l uint32, size int32, xtype uint32, offset uintptr, divisor uint32) {
	var offsetPtr = gl.PtrOffset(int(offset))
	gl.EnableVertexAttribArray(a.location + l)
	gl.VertexAttribPointer(a.location+l, size, xtype, false, int32(a.stride), offsetPtr)
	gl.VertexAttribDivisor(a.location+l, divisor)
}
Example #21
0
//SetPos sets de Position attribute in the shader argument
func (vertexArray *VertexArray) SetPos(shader blankShader.BlankShader) {
	vertAttrib := uint32(gl.GetAttribLocation(shader.Handle, gl.Str("pos\x00")))
	gl.EnableVertexAttribArray(vertAttrib)
	gl.VertexAttribPointer(vertAttrib, 3, gl.FLOAT, false, 5*4, gl.PtrOffset(0))
	vertexArray.handlePos = vertAttrib
}
Example #22
0
func loadBoundingBox(f *Font, X1 Point, X2 Point) (b *BoundingBox, err error) {
	b = new(BoundingBox)
	b.font = f

	// create shader program and define attributes and uniforms
	b.program, err = NewProgram(boxVertexShaderSource, boxFragmentShaderSource)
	if err != nil {
		return b, err
	}

	// ebo, vbo data
	b.vboIndexCount = 4 * 2 // 4 indexes per bounding box (containing 2 position)
	b.eboIndexCount = 6     // each rune requires 6 triangle indices for a quad
	b.vboData = make([]float32, b.vboIndexCount, b.vboIndexCount)
	b.eboData = make([]int32, b.eboIndexCount, b.eboIndexCount)
	b.makeBufferData(X1, X2)
	if f.IsDebug {
		fmt.Printf("bounding %v %v\n", X1, X2)
		fmt.Printf("bounding vbo data\n%v\n", b.vboData)
		fmt.Printf("bounding ebo data\n%v\n", b.eboData)
	}

	// attributes
	b.centeredPosition = uint32(gl.GetAttribLocation(b.program, gl.Str("centered_position\x00")))

	// uniforms
	b.finalPositionUniform = gl.GetUniformLocation(b.program, gl.Str("final_position\x00"))
	b.orthographicMatrixUniform = gl.GetUniformLocation(b.program, gl.Str("orthographic_matrix\x00"))

	// size of glfloat
	glfloatSize := int32(4)

	gl.GenVertexArrays(1, &b.vao)
	gl.GenBuffers(1, &b.vbo)
	gl.GenBuffers(1, &b.ebo)

	// vao
	gl.BindVertexArray(b.vao)

	// vbo
	// specify the buffer for which the VertexAttribPointer calls apply
	gl.BindBuffer(gl.ARRAY_BUFFER, b.vbo)

	gl.EnableVertexAttribArray(b.centeredPosition)
	gl.VertexAttribPointer(
		b.centeredPosition,
		2,
		gl.FLOAT,
		false,
		0,
		gl.PtrOffset(0),
	)
	gl.BufferData(gl.ARRAY_BUFFER, int(glfloatSize)*b.vboIndexCount, gl.Ptr(b.vboData), gl.DYNAMIC_DRAW)

	gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, b.ebo)
	gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, int(glfloatSize)*b.eboIndexCount, gl.Ptr(b.eboData), gl.DYNAMIC_DRAW)
	gl.BindVertexArray(0)

	// not necesssary, but i just want to better understand using vertex arrays
	gl.BindBuffer(gl.ARRAY_BUFFER, 0)
	gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, 0)

	return b, nil
}
Example #23
0
func (r *Renderable) Draw(perspective mgl.Mat4, view mgl.Mat4) {
	gl.UseProgram(r.Shader)
	gl.BindVertexArray(r.Vao)

	model := r.GetTransformMat4()

	var mvp mgl.Mat4
	shaderMvp := getUniformLocation(r.Shader, "MVP_MATRIX")
	if shaderMvp >= 0 {
		mvp = perspective.Mul4(view).Mul4(model)
		gl.UniformMatrix4fv(shaderMvp, 1, false, &mvp[0])
	}

	shaderMv := getUniformLocation(r.Shader, "MV_MATRIX")
	if shaderMv >= 0 {
		mv := view.Mul4(model)
		gl.UniformMatrix4fv(shaderMv, 1, false, &mv[0])
	}

	shaderTex0 := getUniformLocation(r.Shader, "DIFFUSE_TEX")
	if shaderTex0 >= 0 {
		gl.ActiveTexture(gl.TEXTURE0)
		gl.BindTexture(gl.TEXTURE_2D, r.Tex0)
		gl.Uniform1i(shaderTex0, 0)
	}

	shaderColor := getUniformLocation(r.Shader, "MATERIAL_DIFFUSE")
	if shaderColor >= 0 {
		gl.Uniform4f(shaderColor, r.Color[0], r.Color[1], r.Color[2], r.Color[3])
	}

	shaderTex1 := getUniformLocation(r.Shader, "MATERIAL_TEX_0")
	if shaderTex1 >= 0 {
		gl.ActiveTexture(gl.TEXTURE0)
		gl.BindTexture(gl.TEXTURE_2D, r.Tex0)
		gl.Uniform1i(shaderTex1, 0)
	}

	shaderCameraWorldPos := getUniformLocation(r.Shader, "CAMERA_WORLD_POSITION")
	if shaderCameraWorldPos >= 0 {
		gl.Uniform3f(shaderCameraWorldPos, -view[12], -view[13], -view[14])
	}

	shaderPosition := getAttribLocation(r.Shader, "VERTEX_POSITION")
	if shaderPosition >= 0 {
		gl.BindBuffer(gl.ARRAY_BUFFER, r.VertVBO)
		gl.EnableVertexAttribArray(uint32(shaderPosition))
		gl.VertexAttribPointer(uint32(shaderPosition), 3, gl.FLOAT, false, 0, gl.PtrOffset(0))
	}

	shaderNormal := getAttribLocation(r.Shader, "VERTEX_NORMAL")
	if shaderNormal >= 0 {
		gl.BindBuffer(gl.ARRAY_BUFFER, r.NormsVBO)
		gl.EnableVertexAttribArray(uint32(shaderNormal))
		gl.VertexAttribPointer(uint32(shaderNormal), 3, gl.FLOAT, false, 0, gl.PtrOffset(0))
	}

	shaderVertUv := getAttribLocation(r.Shader, "VERTEX_UV_0")
	if shaderVertUv >= 0 {
		gl.BindBuffer(gl.ARRAY_BUFFER, r.UvVBO)
		gl.EnableVertexAttribArray(uint32(shaderVertUv))
		gl.VertexAttribPointer(uint32(shaderVertUv), 2, gl.FLOAT, false, 0, gl.PtrOffset(0))
	}

	gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, r.ElementsVBO)
	gl.DrawElements(gl.TRIANGLES, int32(r.FaceCount*3), gl.UNSIGNED_INT, gl.PtrOffset(0))
	gl.BindVertexArray(0)
}
Example #24
0
// bindString generates all of the vertex buffers and vertex arrays for a single constant line of
// text.  No error checking is done.
func (d *Dictionary) bindString(str string) strData {
	var data strData
	gl.GenVertexArrays(1, &data.varrays[0])
	gl.BindVertexArray(data.varrays[0])
	gl.GenBuffers(2, &data.vbuffers[0])

	var positions, texcoords []float32

	var pen pos
	var prev rune
	for _, r := range str {
		ri := d.Runes[r]

		var scale float32 = 1.0 / float32(d.GlyphMax.Dy())

		var posMin, posMax pos
		posMin.x = pen.x + float32(ri.GlyphBounds.Min.X)*scale
		posMin.y = pen.y + float32(ri.GlyphBounds.Min.Y)*scale
		posMax.x = pen.x + float32(ri.GlyphBounds.Max.X)*scale
		posMax.y = pen.y + float32(ri.GlyphBounds.Max.Y)*scale

		var texMin, texMax pos
		texMin.x = float32(ri.PixBounds.Min.X) / float32(d.Dx)
		texMin.y = float32(ri.PixBounds.Min.Y) / float32(d.Dy)
		texMax.x = float32(ri.PixBounds.Max.X) / float32(d.Dx)
		texMax.y = float32(ri.PixBounds.Max.Y) / float32(d.Dy)
		pen.x += float32(ri.AdvanceWidth) * scale
		pen.x += float32(d.Kerning[RunePair{prev, r}]) * scale
		// pen.x -= float32(d.Kerning[RunePair{prev, r}]) * scale

		positions = append(positions, posMin.x) // lower left
		positions = append(positions, posMin.y)
		positions = append(positions, posMin.x) // upper left
		positions = append(positions, posMax.y)
		positions = append(positions, posMax.x) // upper right
		positions = append(positions, posMax.y)
		positions = append(positions, posMin.x) // lower left
		positions = append(positions, posMin.y)
		positions = append(positions, posMax.x) // upper right
		positions = append(positions, posMax.y)
		positions = append(positions, posMax.x) // lower right
		positions = append(positions, posMin.y)
		texcoords = append(texcoords, texMin.x) // lower left
		texcoords = append(texcoords, texMax.y)
		texcoords = append(texcoords, texMin.x) // upper left
		texcoords = append(texcoords, texMin.y)
		texcoords = append(texcoords, texMax.x) // upper right
		texcoords = append(texcoords, texMin.y)
		texcoords = append(texcoords, texMin.x) // lower left
		texcoords = append(texcoords, texMax.y)
		texcoords = append(texcoords, texMax.x) // upper right
		texcoords = append(texcoords, texMin.y)
		texcoords = append(texcoords, texMax.x) // lower right
		texcoords = append(texcoords, texMax.y)

		prev = r
	}
	data.count = int32(len(positions))
	gl.BindBuffer(gl.ARRAY_BUFFER, data.vbuffers[0])
	gl.BufferData(gl.ARRAY_BUFFER, len(positions)*int(unsafe.Sizeof(positions[0])), gl.Ptr(&positions[0]), gl.STATIC_DRAW)
	location, _ := render.GetAttribLocation("glop.font", "position")
	gl.EnableVertexAttribArray(uint32(location))
	gl.VertexAttribPointer(uint32(location), 2, gl.FLOAT, false, 0, gl.PtrOffset(0))

	gl.BindBuffer(gl.ARRAY_BUFFER, data.vbuffers[1])
	gl.BufferData(gl.ARRAY_BUFFER, len(texcoords)*int(unsafe.Sizeof(texcoords[0])), gl.Ptr(&texcoords[0]), gl.STATIC_DRAW)
	location, _ = render.GetAttribLocation("glop.font", "texCoord")
	gl.EnableVertexAttribArray(uint32(location))
	gl.VertexAttribPointer(uint32(location), 2, gl.FLOAT, false, 0, gl.PtrOffset(0))

	return data
}