Попытка нарисовать текст в OpenGL, но текстура немного смещена - PullRequest
1 голос
/ 30 августа 2011

Я пытаюсь нарисовать текст в OpenGL. Я использовал небольшую программу на C #, чтобы нарисовать все символы от 0x21 до 0x7E в растровое изображение. Я загружаю это как текстуру и пытаюсь использовать это для рисования моего текста. Кажется, это работает, но у меня, кажется, есть некоторые странные проблемы. http://i54.tinypic.com/mmd7k8.png Обратите внимание на дополнительный пиксель рядом с '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);
}

РЕДАКТИРОВАТЬ Я добавил 4 к текстурной координате (0,2,4,6), и это, похоже, решило проблему. Однако теперь мне нужно знать, будет ли это продолжать работать или может сломаться по неизвестным причинам. Вот код создания растрового изображения на случай, если проблема может быть там.

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");
    }
}
}

1 Ответ

3 голосов
/ 30 августа 2011

Адресация пикселей точно в текстуре немного сложнее.См. Мой ответ, приведенный в Текстурные координаты OpenGL в пиксельном пространстве


Об этом спрашивали несколько раз, но у меня нет ссылок под рукой, поэтому быстро и грубообъяснение.Допустим, текстура имеет ширину 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)

илив более общем смысле для пикселя i в текстуре шириной N правильная координата текстуры:

(2i - 1) / (2N)

Однако, если вы хотите идеально выровнять текстуру с пикселями экрана,помните, что то, что вы указываете в качестве координат, - это не пиксели квадратора, а ребра, которые в зависимости от проекции могут совмещаться с краями пикселов экрана, а не с центрами, поэтому могут потребоваться другие координаты текстуры.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...