使用OpenGL渲染Truetype字体

使用OpenGL渲染Truetype字体,opengl,go,Opengl,Go,我现在开始学习OpenGL,使用Go编程语言(我只是无法在我的Windows机器上使用C/C++),到目前为止,我已经设法在屏幕上显示一些旋转立方体,纹理主要是复制和粘贴教程中的代码。虽然我学到了很多,但我就是无法用我自己编写的代码在屏幕上显示一些文本。我查阅了许多教程和问题,但似乎没有任何效果,我怀疑顶点有问题,因为我非常确定纹理坐标是正确的,但屏幕上仍然没有显示任何内容。代码如下: package game import ( "fmt" "io/ioutil" "image"

我现在开始学习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

此外,纹理绘制正确,我已将其保存到磁盘,看起来如下所示:


屏幕上仍然没有文本。

你看了吗?我现在正在做同样的事情,同样的语言。@sixFingers是的,我实际上使用了“抽屉”的例子。无论如何,问题出在我的渲染代码中,我已经能够解决它了。它正在工作,如果你需要帮助,请告诉我。很高兴听到你解决了它。我也是。最后,我使用了一个带有相应UV的三角形列表。对整个文本框进行一次绘制。