Beispiel #1
0
// Renderer implementation.
// BindTexture makes the texture available on the GPU.
func (gc *opengl) BindTexture(tid *uint32, img image.Image, repeat bool) (err error) {
	if glerr := gl.GetError(); glerr != gl.NO_ERROR {
		log.Printf("opengl:bindTexture need to find and fix prior error %X", glerr)
	}
	if *tid == 0 {
		gl.GenTextures(1, tid)
	}
	gl.BindTexture(gl.TEXTURE_2D, *tid)

	// FUTURE: check if RGBA, or NRGBA are alpha pre-multiplied. The docs say yes
	// for RGBA but the data is from PNG files which are not pre-multiplied
	// and the go png Decode looks like its reading values directly.
	var ptr gl.Pointer
	bounds := img.Bounds()
	width, height := int32(bounds.Dx()), int32(bounds.Dy())
	switch imgType := img.(type) {
	case *image.RGBA:
		i := img.(*image.RGBA)
		ptr = gl.Pointer(&(i.Pix[0]))
	case *image.NRGBA:
		i := img.(*image.NRGBA)
		ptr = gl.Pointer(&(i.Pix[0]))
	default:
		return fmt.Errorf("Unsupported image format %T", imgType)
	}
	gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, ptr)
	gl.GenerateMipmap(gl.TEXTURE_2D)
	gc.setTextureMode(*tid, repeat)
	if glerr := gl.GetError(); glerr != gl.NO_ERROR {
		err = fmt.Errorf("Failed binding texture %d\n", glerr)
	}
	return err
}
Beispiel #2
0
// Renderer implementation.
// BindMesh copies the given mesh data to the GPU
// and initializes the vao and buffer references.
func (gc *opengl) BindMesh(vao *uint32, vdata map[uint32]Data, fdata Data) error {
	if glerr := gl.GetError(); glerr != gl.NO_ERROR {
		return fmt.Errorf("BindMesh needs to find and fix prior error %X", glerr)
	}

	// Reuse existing vao's.
	if *vao == 0 {
		gl.GenVertexArrays(1, vao)
	}
	gl.BindVertexArray(*vao)
	for _, vbuff := range vdata {
		vd, ok := vbuff.(*vertexData)
		if ok && vd.rebind {
			gc.bindVertexBuffer(vd)
			vd.rebind = false
		}
	}
	if glerr := gl.GetError(); glerr != gl.NO_ERROR {
		return fmt.Errorf("BindMesh failed to bind vb %X", glerr)
	}
	if fd, ok := fdata.(*faceData); ok {
		if fd.rebind {
			gc.bindFaceBuffer(fd)
			fd.rebind = false
		}
	}
	if glerr := gl.GetError(); glerr != gl.NO_ERROR {
		return fmt.Errorf("BindMesh failed to bind fb %X", glerr)
	}
	return nil
}
Beispiel #3
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.mvp.Set(tag.mvp64.Mult(tag.mvp64, tag.persp))
	gl.UniformMatrix4fv(tag.mvpRef, 1, false, tag.mvp.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, 0)
	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()
	}
}
Beispiel #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)
		}
	}
}
Beispiel #5
0
// BindFrame creates a framebuffer object with an associated texture.
//    http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-14-render-to-texture/
//    http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-16-shadow-mapping/
func (gc *opengl) BindFrame(buf int, fbo, tid, db *uint32) (err error) {
	size := int32(1024)
	gl.GenFramebuffers(1, fbo)
	gl.BindFramebuffer(gl.FRAMEBUFFER, *fbo)

	// Create a texture specifically for the framebuffer.
	gl.GenTextures(1, tid)
	gl.BindTexture(gl.TEXTURE_2D, *tid)
	switch buf {
	case IMAGE_BUFF:
		gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, size, size,
			0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Pointer(nil))
		gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
		gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)

		// Add a depth buffer to mimic the normal framebuffer behaviour for 3D objects.
		gl.GenRenderbuffers(1, db)
		gl.BindRenderbuffer(gl.RENDERBUFFER, *db)
		gl.RenderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT, size, size)
		gl.FramebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, *db)

		// Associate the texture with the framebuffer.
		gl.FramebufferTexture(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, *tid, 0)
		buffType := uint32(gl.COLOR_ATTACHMENT0)
		gl.DrawBuffers(1, &buffType)
	case DEPTH_BUFF:
		gl.TexImage2D(gl.TEXTURE_2D, 0, gl.DEPTH_COMPONENT16, size, size,
			0, gl.DEPTH_COMPONENT, gl.FLOAT, gl.Pointer(nil))
		gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
		gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
		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_COMPARE_FUNC, gl.LEQUAL)
		gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_COMPARE_MODE, gl.COMPARE_REF_TO_TEXTURE)

		// Associate the texture with the framebuffer.
		gl.FramebufferTexture(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, *tid, 0)
		gl.DrawBuffer(gl.NONE)
	default:
		return fmt.Errorf("BindFrame unrecognized buffer type.")
	}

	// Report any problems.
	glerr := gl.CheckFramebufferStatus(gl.FRAMEBUFFER)
	if glerr != gl.FRAMEBUFFER_COMPLETE {
		return fmt.Errorf("BindFrame error %X", glerr)
	}
	if glerr := gl.GetError(); glerr != gl.NO_ERROR {
		err = fmt.Errorf("Failed binding framebuffer %X", glerr)
	}
	gl.BindFramebuffer(gl.FRAMEBUFFER, 0) // clean up by resetting to default framebuffer.
	return err
}
Beispiel #6
0
// Renderer implementation.
// BindShader compiles the shader and makes it available to the GPU.
// It also adds the list of uniforms and vertex layout references to the
// provided maps.
func (gc *opengl) BindShader(vsh, fsh []string, uniforms map[string]int32,
	layouts map[string]uint32) (program uint32, err error) {
	program = gl.CreateProgram()

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

	// initialize the uniform and layout references
	gl.Uniforms(program, uniforms)
	gl.Layouts(program, layouts)
	if glerr := gl.GetError(); glerr != gl.NO_ERROR {
		log.Printf("shader:Bind need to find and fix error %X", glerr)
	}
	return
}