Esempio n. 1
5
func main() {
	// Initialize GLFW for window management
	glfw.SetErrorCallback(glfwErrorCallback)
	if !glfw.Init() {
		panic("failed to initialize glfw")
	}
	defer glfw.Terminate()

	glfw.WindowHint(glfw.Resizable, glfw.False)
	glfw.WindowHint(glfw.ContextVersionMajor, 3)
	glfw.WindowHint(glfw.ContextVersionMinor, 3)
	glfw.WindowHint(glfw.OpenglForwardCompatible, glfw.True)    // Necessary for OS X
	glfw.WindowHint(glfw.OpenglProfile, glfw.OpenglCoreProfile) // Necessary for OS X
	glfw.WindowHint(glfw.OpenglDebugContext, glfw.True)
	window, err := glfw.CreateWindow(WindowWidth, WindowHeight, "Cube", nil, nil)
	if err != nil {
		panic(err)
	}
	window.MakeContextCurrent()

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

	// Note that it is possible to use GL functions spanning multiple versions
	if err := gl4.Init(); err != nil {
		fmt.Printf("Could not initialize GL 4.4 (non-fatal)")
	}

	if gl.ARB_debug_output {
		gl.Enable(gl.DEBUG_OUTPUT_SYNCHRONOUS_ARB)
		gl.DebugMessageCallbackARB(gl.DebugProc(glDebugCallback), gl.Ptr(nil))
		// Trigger an error to demonstrate debug output
		gl.Enable(gl.CONTEXT_FLAGS)
	}

	version := gl.GoStr(gl.GetString(gl.VERSION))
	fmt.Println("OpenGL version", version)

	// Configure the vertex and fragment shaders
	program, err := newProgram(vertexShader, fragmentShader)
	if err != nil {
		panic(err)
	}
	gl.UseProgram(program)

	projection := mgl32.Perspective(70.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])

	textureUniform := gl.GetUniformLocation(program, gl.Str("tex\x00"))
	gl.Uniform1i(textureUniform, 0)

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

	// Load the texture
	texture, err := newTexture("square.png")
	if err != nil {
		panic(err)
	}

	// Configure the vertex data
	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(cubeVertices)*4, gl.Ptr(cubeVertices), gl.STATIC_DRAW)

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

	texCoordAttrib := uint32(gl.GetAttribLocation(program, gl.Str("vertTexCoord\x00")))
	gl.EnableVertexAttribArray(texCoordAttrib)
	gl.VertexAttribPointer(texCoordAttrib, 2, gl.FLOAT, false, 5*4, gl.PtrOffset(3*4))

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

	angle := 0.0
	previousTime := glfw.GetTime()

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

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

		angle += elapsed
		model = mgl32.HomogRotate3D(float32(angle), mgl32.Vec3{0, 1, 0})

		// Render
		gl.UseProgram(program)
		gl.UniformMatrix4fv(modelUniform, 1, false, &model[0])

		gl.BindVertexArray(vao)

		gl.ActiveTexture(gl.TEXTURE0)
		gl.BindTexture(gl.TEXTURE_2D, texture)

		gl.DrawArrays(gl.TRIANGLES, 0, 6*2*3)

		// Maintenance
		window.SwapBuffers()
		glfw.PollEvents()
	}
}
Esempio n. 2
0
func newTexture(file string) (uint32, error) {
	imgFile, err := os.Open(file)
	if err != nil {
		return 0, err
	}
	img, _, err := image.Decode(imgFile)
	if err != nil {
		return 0, err
	}

	rgba := image.NewRGBA(img.Bounds())
	if rgba.Stride != rgba.Rect.Size().X*4 {
		return 0, fmt.Errorf("unsupported stride")
	}
	draw.Draw(rgba, rgba.Bounds(), img, image.Point{0, 0}, draw.Src)

	var texture uint32
	gl.GenTextures(1, &texture)
	gl.ActiveTexture(gl.TEXTURE0)
	gl.BindTexture(gl.TEXTURE_2D, texture)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_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.TexImage2D(
		gl.TEXTURE_2D,
		0,
		gl.RGBA,
		int32(rgba.Rect.Size().X),
		int32(rgba.Rect.Size().Y),
		0,
		gl.RGBA,
		gl.UNSIGNED_BYTE,
		gl.Ptr(rgba.Pix))

	return texture, nil
}
Esempio n. 3
0
File: text.go Progetto: mik3cap/glop
// 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
}
Esempio n. 4
0
File: text.go Progetto: mik3cap/glop
// LoadDictionary reads a gobbed Dictionary object from r, registers its atlas texture with opengl,
// and returns a Dictionary that is ready to render text.
func LoadDictionary(r io.Reader) (*Dictionary, error) {
	errChan := make(chan error)
	initOnce.Do(func() {
		render.Queue(func() {
			// errChan <- render.RegisterShader("glop.font", []byte(font_vertex_shader), []byte(font_fragment_shader))
			errChan <- render.RegisterShader("glop.font", []byte(font_vshader), []byte(font_fshader))
		})
	})
	err := <-errChan
	if err != nil {
		return nil, err
	}

	var dict Dictionary
	dec := gob.NewDecoder(r)
	err = dec.Decode(&dict)
	if err != nil {
		return nil, err
	}

	render.Queue(func() {
		// Create the gl texture for the atlas
		gl.GenTextures(1, &dict.atlas.texture)
		glerr := gl.GetError()
		if glerr != 0 {
			errChan <- fmt.Errorf("Gl Error on gl.GenTextures: %v", glerr)
			return
		}

		// Send the atlas to opengl
		gl.BindTexture(gl.TEXTURE_2D, dict.atlas.texture)
		gl.PixelStorei(gl.UNPACK_ALIGNMENT, 1)
		gl.TexImage2D(
			gl.TEXTURE_2D,
			0,
			gl.RED,
			dict.Dx,
			dict.Dy,
			0,
			gl.RED,
			gl.UNSIGNED_BYTE,
			gl.Ptr(&dict.Pix[0]))
		glerr = gl.GetError()
		if glerr != 0 {
			errChan <- fmt.Errorf("Gl Error on creating texture: %v", glerr)
			return
		}

		// Create the atlas sampler and set the parameters we want for it
		gl.GenSamplers(1, &dict.atlas.sampler)
		gl.SamplerParameteri(dict.atlas.sampler, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
		gl.SamplerParameteri(dict.atlas.sampler, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
		gl.SamplerParameteri(dict.atlas.sampler, gl.TEXTURE_WRAP_S, gl.REPEAT)
		gl.SamplerParameteri(dict.atlas.sampler, gl.TEXTURE_WRAP_T, gl.REPEAT)
		glerr = gl.GetError()
		if glerr != 0 {
			errChan <- fmt.Errorf("Gl Error on creating sampler: %v", glerr)
			return
		}
		errChan <- nil
	})

	err = <-errChan
	if err != nil {
		return nil, err
	}

	return &dict, nil
}