Exemple #1
0
// drawScene renders the 3D models consisting of one VAO
func (tag *trtag) drawScene() {
	gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
	tag.checkError("gl.Clear")
	gl.UseProgram(tag.shaders)
	tag.checkError("gl.UseProgram")
	gl.BindVertexArray(tag.vao)
	tag.checkError("gl.BindVertexArray")

	// Use a modelview matrix and quaternion to rotate the 3D object.
	tag.mvp64.SetQ(lin.NewQ().SetAa(0, 1, 0, lin.Rad(-tag.rotateAngle)))
	tag.mvp64.TranslateMT(0, 0, -4)
	tag.mvp64.Mult(tag.mvp64, tag.persp)
	tag.mvp32 = renderMatrix(tag.mvp64, tag.mvp32)
	gl.UniformMatrix4fv(tag.mvpRef, 1, false, tag.mvp32.Pointer())
	if err := gl.GetError(); err != 0 {
		fmt.Printf("gl.UniformMatrix error %d\n", err)
	}
	gl.DrawElements(gl.TRIANGLES, int32(len(tag.faces)), gl.UNSIGNED_BYTE, gl.Pointer(nil))
	if err := gl.GetError(); err != 0 {
		fmt.Printf("gl.DrawElements error %d\n", err)
	}

	// cleanup
	gl.UseProgram(0)
	tag.checkError("gl.UseProgram-0")
	gl.BindVertexArray(0)
	tag.checkError("gl.BindVertexArray-0")

	// rotate based on time... not on how fast the computer runs.
	if time.Now().Sub(tag.lastTime).Seconds() > 0.01 {
		tag.rotateAngle += 1
		tag.lastTime = time.Now()
	}
}
Exemple #2
0
// Implements Renderer interface.
func (gc *opengl) BindShader(sh *data.Shader) (pref uint32, err error) {
	pref = gl.CreateProgram()

	// FUTURE: get rid of BindAttribLocation and use layout instead.
	//         this needs GLSL 330 instead of 150
	//         eg: layout(location=0) in vec4 in_position;
	gl.BindAttribLocation(pref, 0, "in_v") // matches vattr in bindModel
	gl.BindAttribLocation(pref, 1, "in_n") // matches nattr in bindModel
	gl.BindAttribLocation(pref, 2, "in_t") // matches tattr in bindModel

	// compile and link the shader program.
	if glerr := gl.BindProgram(pref, sh.Vsh, sh.Fsh); glerr != nil {
		err = fmt.Errorf("Failed to create shader program: %s\n", glerr)
		return
	}

	// initialize the uniform references
	var errmsg string
	for label, _ := range sh.Uniforms {
		if uid := gl.GetUniformLocation(pref, label); uid >= 0 {
			sh.Uniforms[label] = uid
		} else {
			errnum := gl.GetError()
			errmsg += fmt.Sprintf("No %s uniform in shader %X\n", label, errnum)
		}
	}
	if len(errmsg) > 0 {
		err = errors.New(errmsg)
	}
	if glerr := gl.GetError(); glerr != gl.NO_ERROR {
		log.Printf("opengl:bindShader need to find and fix error %X", glerr)
	}
	return
}
Exemple #3
0
// Implements Renderer interface.
func (gc *opengl) BindTexture(texture *data.Texture) (err error) {
	if texture == nil {
		return
	}
	if glerr := gl.GetError(); glerr != gl.NO_ERROR {
		log.Printf("opengl:bindTexture need to find and fix prior error %X", glerr)
	}
	gl.GenTextures(1, &(texture.Tid))
	gl.BindTexture(gl.TEXTURE_2D, texture.Tid)

	// ensure image is in RGBA format
	b := texture.Img.Bounds()
	rgba := image.NewRGBA(image.Rect(0, 0, b.Dx(), b.Dy()))
	draw.Draw(rgba, rgba.Bounds(), texture.Img, b.Min, draw.Src)
	width, height := int32(b.Dx()), int32(b.Dy())
	gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Pointer(&(rgba.Pix[0])))
	gl.GenerateMipmap(gl.TEXTURE_2D)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR)
	if glerr := gl.GetError(); glerr != gl.NO_ERROR {
		err = fmt.Errorf("Failed binding texture %s\n", texture.Name)
	}
	return
}
Exemple #4
0
// checkError helps to debug OpenGL errors by printing out when the occur.
func (tag *trtag) checkError(txt string) {
	cnt := 0
	err := gl.GetError()
	for err != 0 {
		fmt.Printf("%s error %d::%d\n", txt, cnt, err)
		err = gl.GetError()
		cnt++
		if cnt > 10 {
			os.Exit(-1)
		}
	}
}
Exemple #5
0
// Implements Renderer interface.
func (gc *opengl) BindModel(mesh *data.Mesh) (err error) {
	if glerr := gl.GetError(); glerr != gl.NO_ERROR {
		log.Printf("opengl:bindModel need to find and fix prior error %X", glerr)
	}

	// Gather the one scene into this one vertex array object.
	gl.GenVertexArrays(1, &(mesh.Vao))
	gl.BindVertexArray(mesh.Vao)

	// vertex data.
	var vbuff uint32
	gl.GenBuffers(1, &vbuff)
	gl.BindBuffer(gl.ARRAY_BUFFER, vbuff)
	gl.BufferData(gl.ARRAY_BUFFER, int64(len(mesh.V)*4), gl.Pointer(&(mesh.V[0])), gl.STATIC_DRAW)
	var vattr uint32 = 0
	gl.VertexAttribPointer(vattr, 4, gl.FLOAT, false, 0, 0)
	gl.EnableVertexAttribArray(vattr)

	// normal data.
	var nbuff uint32
	gl.GenBuffers(1, &nbuff)
	gl.BindBuffer(gl.ARRAY_BUFFER, nbuff)
	gl.BufferData(gl.ARRAY_BUFFER, int64(len(mesh.N)*4), gl.Pointer(&(mesh.N[0])), gl.STATIC_DRAW)
	var nattr uint32 = 1
	gl.VertexAttribPointer(nattr, 3, gl.FLOAT, false, 0, 0)
	gl.EnableVertexAttribArray(nattr)

	// texture coordatinate, 2 float32's
	if len(mesh.T) > 0 {
		var tbuff uint32
		gl.GenBuffers(1, &tbuff)
		gl.BindBuffer(gl.ARRAY_BUFFER, tbuff)
		gl.BufferData(gl.ARRAY_BUFFER, int64(len(mesh.T)*4), gl.Pointer(&(mesh.T[0])), gl.STATIC_DRAW)
		var tattr uint32 = 2
		gl.VertexAttribPointer(tattr, 2, gl.FLOAT, false, 0, 0)
		gl.EnableVertexAttribArray(tattr)
	}

	// faces data, uint16 in this case, so 2 bytes per element.
	var fbuff uint32
	gl.GenBuffers(1, &fbuff)
	gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, fbuff)
	gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, int64(len(mesh.F)*2), gl.Pointer(&(mesh.F[0])), gl.STATIC_DRAW)
	if glerr := gl.GetError(); glerr != gl.NO_ERROR {
		err = fmt.Errorf("Failed binding model %s\n", mesh.Name)
	}
	return
}
Exemple #6
0
// Implements Renderer interface.
func (gc *opengl) BindGlyphs(mesh *data.Mesh) (err error) {
	if glerr := gl.GetError(); glerr != gl.NO_ERROR {
		log.Printf("opengl:bindGlyphs need to find and fix prior error %X", glerr)
	}

	// Reuse existing vertex array object, otherwise create one.
	if mesh.Vao == 0 {
		gl.GenVertexArrays(1, &(mesh.Vao))
	}
	gl.BindVertexArray(mesh.Vao)

	// Reuse existing vertex buffer, otherwise create one.
	if mesh.Vbuf == 0 {
		gl.GenBuffers(1, &(mesh.Vbuf))
	}
	gl.BindBuffer(gl.ARRAY_BUFFER, mesh.Vbuf)
	gl.BufferData(gl.ARRAY_BUFFER, int64(len(mesh.V)*4), gl.Pointer(&(mesh.V[0])), gl.DYNAMIC_DRAW)
	var vattr uint32 = 0
	gl.VertexAttribPointer(vattr, 4, gl.FLOAT, false, 0, 0)
	gl.EnableVertexAttribArray(vattr)

	// Reuse existing texture buffer, otherwise create one.
	if mesh.Tbuf == 0 {
		gl.GenBuffers(1, &(mesh.Tbuf))
	}
	gl.BindBuffer(gl.ARRAY_BUFFER, mesh.Tbuf)
	gl.BufferData(gl.ARRAY_BUFFER, int64(len(mesh.T)*4), gl.Pointer(&(mesh.T[0])), gl.DYNAMIC_DRAW)
	var tattr uint32 = 2
	gl.VertexAttribPointer(tattr, 2, gl.FLOAT, false, 0, 0)
	gl.EnableVertexAttribArray(tattr)

	// Reuse existing faces buffer, otherwise create one.
	if mesh.Fbuf == 0 {
		gl.GenBuffers(1, &mesh.Fbuf)
	}
	gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh.Fbuf)
	gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, int64(len(mesh.F)*2), gl.Pointer(&(mesh.F[0])), gl.DYNAMIC_DRAW)
	if glerr := gl.GetError(); glerr != gl.NO_ERROR {
		err = fmt.Errorf("Failed binding glyphs %s\n", mesh.Name)
	}
	return
}
Exemple #7
0
// initTexture loads the texture and binds it to the graphics device.
func (tb *tbtag) initTexture() {
	texture := &data.Texture{}
	loader := data.NewLoader()
	if loader.Load("image", &texture); texture != nil {
		tb.texture = texture
		gl.GenTextures(1, &texture.Tid)
		gl.BindTexture(gl.TEXTURE_2D, texture.Tid)
		gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
		gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)

		// ensure image is in RGBA format
		b := texture.Img.Bounds()
		rgba := image.NewRGBA(image.Rect(0, 0, b.Dx(), b.Dy()))
		draw.Draw(rgba, rgba.Bounds(), texture.Img, b.Min, draw.Src)
		width, height := int32(b.Dx()), int32(b.Dy())
		gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Pointer(&(rgba.Pix[0])))
		if glerr := gl.GetError(); glerr != gl.NO_ERROR {
			fmt.Printf("Failed binding texture image.png\n")
		}
	} else {
		fmt.Println("Could not load image.png file.")
	}

}