使用OpenGL渲染Truetype字体

时间:2015-12-24 17:09:34

标签: opengl go

我现在开始学习OpenGL,使用 Go编程语言(我在Windows机器上无法使用C / C ++),到目前为止我已经设法显示屏幕中的一些旋转立方体,纹理主要是复制和粘贴教程中的代码。不过,我已经学到了很多东西,但我不能用我自己编写的代码在屏幕上看到一些文字。我查了许多教程和问题,但似乎没有任何工作,我怀疑顶点有问题,因为我很确定纹理坐标是正确的,仍然没有任何东西出现在屏幕上。这是代码:

package game

import (
  "fmt"
  "io/ioutil"
  "image"
  "image/draw"
  "github.com/go-gl/gl/v3.3-core/gl"
  mgl "github.com/go-gl/mathgl/mgl32"
  "github.com/golang/freetype/truetype"
  "golang.org/x/image/font"
  "golang.org/x/image/math/fixed"
)

type GameFont struct {
  loaded bool
  vao uint32
  vbo VBOData
  pix float32
  Texture *Texture
  Shader ShaderProgram
}


// Load a TrueType font from a file and generate a texture 
// with all important characters.
func (f *GameFont) Load(path string, pix float32) {
  contents, err := ioutil.ReadFile(path)
  if err != nil {
    fmt.Println("Could not read font file: " + path)
    panic(err)
  }
  fontFace, err := truetype.Parse(contents)
  if err != nil {
    fmt.Println("Could not parse font file: " + path)
    panic(err)
  }

  // Create a texture for the characters
  // Find the next power of 2 for the texture size
  size := nextP2(int(pix * 16))
  fg, bg := image.White, image.Black
  rgba := image.NewRGBA(image.Rect(0, 0, size, size))

  draw.Draw(rgba, rgba.Bounds(), bg, image.ZP, draw.Src)
  d := &font.Drawer{
    Dst: rgba,
    Src: fg,
    Face: truetype.NewFace(fontFace, &truetype.Options{
      Size: float64(pix),
      DPI: 72,
      Hinting: font.HintingNone,
    }),
  }

  // Some GL preps
  gl.GenVertexArrays(1, &f.vao)
  gl.BindVertexArray(f.vao)
  f.vbo.Create()
  f.vbo.Bind()

  f.Shader = newShaderProgram("data/shaders/font.vert", "data/shaders/font.frag")
  f.Shader.Use()
  f.Shader.SetUniform("tex", 0)

  // Create vertex data (and coordinates in the texture) for each character
  // All characters below 32 are useless
  for i := 32; i < 128; i++ {
    c := string(rune(i))
    x, y := i % 16, i / 16

    // Draw the character on the texture
    d.Dot = fixed.P(x * int(pix), y * int(pix))
    d.DrawString(c)

    // Vertices
    quads := []float32{
      0,    0,
      0,    pix,
      pix,  0,
      pix,  pix,
    }

    norm := func(n int) float32 {
      return float32(n) / 16.0
    }

    // Texture coordinates (normalized)
    texQuads := []float32{
      norm(x),      1.0 - norm(y + 1),
      norm(x),      1.0 - norm(y),
      norm(x + 1),  1.0 - norm(y + 1),
      norm(x + 1),  1.0 - norm(y),
    }

    for v := 0; v < 8; v += 2 {
      vQuads, vTexQuads := quads[v:(v+2)], texQuads[v:(v+2)]

      // Data is like (X, Y, U, V)
      f.vbo.AppendData(vQuads, 2)
      f.vbo.AppendData(vTexQuads, 2)
    }
  }

  // Upload data to GPU and we're done
  f.Texture = newTextureFromRGBA(rgba)
  f.Texture.Bind()
  f.Texture.SetGLParam(gl.TEXTURE_MIN_FILTER, gl.LINEAR)
  f.Texture.SetGLParam(gl.TEXTURE_MAG_FILTER, gl.LINEAR)
  f.Texture.Upload()

  f.vbo.UploadData(gl.STATIC_DRAW)

  gl.EnableVertexAttribArray(0)
  gl.VertexAttribPointer(0, 2, gl.FLOAT, false, 4*4, gl.PtrOffset(0))
  gl.EnableVertexAttribArray(1)
  gl.VertexAttribPointer(1, 2, gl.FLOAT, false, 4*4, gl.PtrOffset(2*4))

  f.loaded = true
}

// Render a text using the font
func (f *GameFont) Render(text string, x, y int, pix float32, color mgl.Vec4) {
  if !f.loaded {
    return
  }

  gl.Disable(gl.DEPTH_TEST)
  gl.Enable(gl.BLEND)
  gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
  gl.BindVertexArray(f.vao)

  f.Shader.Use()
  f.Shader.SetUniform("projection", mgl.Ortho2D(0, _screen.Width, 0, _screen.Height))
  f.Shader.SetUniform("color", color)

  f.Texture.Bind()

  scale := pix / f.pix
  for i := 0; i < len(text); i++ {
    index := rune(text[i])
    model := mgl.Ident4().Mul4(mgl.Scale3D(scale, scale, 0))
    model = model.Add(mgl.Translate3D(float32(x) + float32(i) * pix, float32(y), 0))
    f.Shader.SetUniform("model", model)
    gl.DrawArrays(gl.TRIANGLE_STRIP, (32-index)*4, 4)
  }

  gl.Enable(gl.DEPTH_TEST)
  gl.Disable(gl.BLEND)
}

这是着色器:

顶点着色器

#version 330
uniform mat4 projection;
uniform mat4 model;

layout (location = 0) in vec2 vert;
layout (location = 1) in vec2 vertTexCoord;

out vec2 fragTexCoord;

void main() {
  fragTexCoord = vertTexCoord;
  gl_Position = projection * model * vec4(vert, 0, 1);
}

片段着色器

#version 330

uniform sampler2D tex;
uniform vec4 color;

in vec2 fragTexCoord;
out vec4 outputColor;

void main() {
  outputColor = color * texture(tex, fragTexCoord);
}

GameFont结构的每个“组件”都正常工作(我将它们与旋转的立方体一起使用),因此每个函数都调用GL对应的一个。

纹理正在正确绘制,我已将其保存到磁盘,它看起来像这样:

enter image description here

然而,屏幕上没有文字。

0 个答案:

没有答案