试图在OpenGL中绘制文本,但纹理略有偏移

试图在OpenGL中绘制文本,但纹理略有偏移,opengl,text,Opengl,Text,我正在尝试在OpenGL中绘制文本。我使用一个小型C#程序将0x21到0x7E之间的所有字符绘制成位图。我将其作为纹理加载,并尝试使用它来绘制文本。这似乎有效,但我似乎遇到了一些奇怪的问题。请注意“a”旁边的额外像素和“c”被略微截断的事实。看起来整个事情都有轻微的变化。有人知道我为什么会遇到这个问题吗?我不想使用gltext这样的库,因为我不想依赖libfreetype,因为我只画了几个字符串。以下是我正在使用的代码: static void textDrawChar(char c, int

我正在尝试在OpenGL中绘制文本。我使用一个小型C#程序将0x21到0x7E之间的所有字符绘制成位图。我将其作为纹理加载,并尝试使用它来绘制文本。这似乎有效,但我似乎遇到了一些奇怪的问题。请注意“a”旁边的额外像素和“c”被略微截断的事实。看起来整个事情都有轻微的变化。有人知道我为什么会遇到这个问题吗?我不想使用gltext这样的库,因为我不想依赖libfreetype,因为我只画了几个字符串。以下是我正在使用的代码:

static void textDrawChar(char c, int x, int y)
{
GLfloat vert[8];
GLfloat texcoord[8];

vert[0] = x;                            vert[1] = y;
vert[2] = x;                            vert[3] = y + TEXT_HEIGHT;
vert[4] = x + font_char_width[c-0x21];  vert[5] = y + TEXT_HEIGHT;
vert[6] = x + font_char_width[c-0x21];  vert[7] = y;

texcoord[0] = (float)(font_char_pos[c-0x21])/TOTAL_WIDTH;
texcoord[1] = 1.0f;
texcoord[2] = (float)(font_char_pos[c-0x21])/TOTAL_WIDTH;
texcoord[3] = 0.0f;
texcoord[4] = (float)(font_char_pos[c-0x21] + font_char_width[c-0x21])/TOTAL_WIDTH;
texcoord[5] = 0.0f;
texcoord[6] = (float)(font_char_pos[c-0x21] + font_char_width[c-0x21])/TOTAL_WIDTH;
texcoord[7] = 1.0f;

glBindTexture(GL_TEXTURE_2D, texture);
glVertexPointer(2, GL_FLOAT, 0, vert);
glTexCoordPointer(2, GL_FLOAT, 0, texcoord);
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, indices);
}

void textDraw(void)
{
textDrawChar('a', 300, 300);
textDrawChar('b', 300+font_char_width['a'-0x21], 300);
textDrawChar('c', 300+font_char_width['a'-0x21]+font_char_width['b'-0x21], 300);
}
编辑我在纹理坐标(0,2,4,6)中添加了4,这似乎解决了问题。然而,现在我需要知道这是否会继续有效,或者由于未知的原因可能会中断。这是位图创建代码,以防出现问题

using System;
using System.Drawing;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Collections;

namespace font_to_bmp
{
class Program
{
    static void Main(string[] args)
    {
        Bitmap b = new Bitmap(1715, 36);
        Graphics g = Graphics.FromImage(b);
        g.FillRectangle(new SolidBrush(Color.Transparent), 0, 0, 1715, 36);
        Font f = new Font("Liberation Sans", 24, GraphicsUnit.Point);
        g.PageUnit = GraphicsUnit.Pixel;
        int curx = 0;
        StreamWriter w = new StreamWriter(new FileStream("font_width.h", FileMode.Create, FileAccess.Write, FileShare.Read));
        w.WriteLine("static const int font_char_width[] = {");
        ArrayList hax = new ArrayList();
        for (int i = 0x21; i <= 0x7E; i++)
        {
            char c = (char)i;
            string s = c.ToString();
            SizeF sz = g.MeasureString(s, f);
            StringFormat sf = new StringFormat();
            sf.SetMeasurableCharacterRanges(new CharacterRange[] {new CharacterRange(0,1)});
            Region r = g.MeasureCharacterRanges(s, f, new RectangleF(0, 0, 1000, 1000), sf)[0];
            RectangleF r2 = r.GetBounds(g);
            Console.WriteLine("{0} is {1}x{2}", s, r2.Width, r2.Height);
            int w_int = (int)(Math.Ceiling(r2.Width));
            g.DrawString(s, f, new SolidBrush(Color.Black), curx, 0);
            hax.Add(curx);
            curx += w_int;
            w.WriteLine("\t{0},", w_int);
        }
        Console.WriteLine("Total width {0}", curx);
        w.WriteLine("};");
        w.WriteLine();

        w.WriteLine("static const int font_char_pos[] = {");

        foreach(int z in hax)
        {
            w.WriteLine("\t{0},", z);
        }
        w.WriteLine("};");

        w.Close();
        b.Save("font.png");
    }
}
}
使用系统;
使用系统图;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.IO;
使用系统集合;
命名空间字体\u到\u bmp
{
班级计划
{
静态void Main(字符串[]参数)
{
位图b=新位图(1715,36);
图形g=图形。来自图像(b);
g、 FillRectangle(新的SolidBrush(颜色.透明),0,0,1715,36);
Font f=新字体(“解放号”,24,GraphicsUnit.Point);
g、 PageUnit=GraphicsUnit.Pixel;
int-curx=0;
StreamWriter w=新的StreamWriter(新的文件流(“font_width.h”,FileMode.Create,FileAccess.Write,FileShare.Read));
w、 WriteLine(“static const int font_char_width[]={”);
ArrayList hax=新的ArrayList();

对于(int i=0x21;i而言,精确地在纹理中寻址像素有点棘手。请参阅中给出的答案


这已经被问了好几次了,但我手头没有链接,所以我给出了一个快速而粗略的解释。假设纹理是8像素宽:

 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
 ^   ^   ^   ^   ^   ^   ^   ^   ^
0.0  |   |   |   |   |   |   |  1.0
 |   |   |   |   |   |   |   |   |
0/8 1/8 2/8 3/8 4/8 5/8 6/8 7/8 8/8
数字表示纹理的像素,条形表示纹理的边缘,如果是最近的过滤,则表示像素之间的边界。但是,您希望击中像素的中心。因此,您对纹理坐标感兴趣

(0/8+1/8)/2=1/(2*8)

(1/8+2/8)/2=3/(2*8)

(7/8+8/8)/2=15/(2*8)

或者更一般地,对于N宽纹理中的像素i,适当的纹理坐标为

(2i-1)/(2N)

但是,如果要将纹理与屏幕像素完全对齐,请记住,指定为坐标的不是四边形的像素,而是边缘,根据投影情况,边缘可能与屏幕像素边缘对齐,而不是中心对齐,因此可能需要其他纹理坐标