从freetype上传到opengl的字形被拉伸

时间:2015-02-09 18:26:30

标签: c opengl rust freetype

我试图使用子像素渲染渲染freetype中的一些文本。当我渲染大尺寸的文本时,结果看起来足够,只有一些颜色条纹,我认为这是预期的。然而,随着我减小尺寸,结果变得越来越模糊,并且变得略微伸展。这些是绘图的结果" Hello"作为像素大小13,18和100。

Three examples of the problem 正如您所看到的,除了轻微的模糊和彩色条纹外,像素大小100相当清晰。像素大小18仍然可读,虽然丑陋。然而,像素大小13是如此扭曲,只有知道它的人应该是一个单词可以识别它。

这就是我从freetype获取位图的方法:

let bitmap_glyph = glyph.to_bitmap(freetype::render_mode::RenderMode::Lcd, None).unwrap();
let bitmap = bitmap_glyph.bitmap();
let texture = Texture::from_freetype_bitmap(bitmap);

这是我目前用于生成纹理的代码:

pub fn from_freetype_bitmap(bitmap: freetype::Bitmap) -> Texture {
    let width = bitmap.width();
    let height = bitmap.rows();

    let mut texture = 0;
    unsafe {
        gl::GenTextures(1, &mut texture);
        assert!(texture != 0);
        gl::BindTexture(gl::TEXTURE_2D, texture);
        gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as i32);
        gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR as i32);
        gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as i32);
        gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as i32);
        gl::PixelStorei(gl::UNPACK_ALIGNMENT, 1);

        let data = bitmap.buffer();
        let pitch = bitmap.pitch();
        let dataWidth = width / 3;

        let mut finalData = Vec::<u8>::new();
        for i in 0..height {
            for j in 0..dataWidth {
                finalData.push(data[(i * pitch + (j * 3) + 0) as usize]);
                finalData.push(data[(i * pitch + (j * 3) + 1) as usize]);
                finalData.push(data[(i * pitch + (j * 3) + 2) as usize]);
                finalData.push(0xff);
            }
        }

        gl::TexImage2D(
            gl::TEXTURE_2D,
            0,
            gl::RGBA as GLint,
            dataWidth, height,
            0, 
            gl::RGBA,
            gl::UNSIGNED_BYTE,
            mem::transmute(finalData.as_ptr())
        );
    }

    let mut mesh = Mesh::new();

    mesh.add_vertex(0.0, 0.0); mesh.add_vertex(0.0, 0.0);
    mesh.add_vertex(width as f32, 0.0); mesh.add_vertex(1.0, 0.0);
    mesh.add_vertex(width as f32, height as f32); mesh.add_vertex(1.0, 1.0);
    mesh.add_vertex(0.0, height as f32); mesh.add_vertex(0.0, 1.0);

    return Texture {
        mesh: mesh, 
        texture: texture
    }
}

然后使用正交矩阵渲染这些纹理,其中原点位于左上角,并缩放到窗口的尺寸。因此,我相信在渲染时不应该进行上采样或下采样。这些是我目前使用的着色器:

// VS
#version 120
uniform vec3 tint;
uniform mat3 matrix;

attribute vec2 position;
attribute vec2 texCoords;

varying vec2 texFrag;

void main() {
    texFrag = texCoords;
    gl_Position = vec4(matrix * vec3(position, 1.0), 1.0);
}

// FS
#version 120

uniform vec3 tint;
uniform mat3 matrix;
uniform sampler2D texSample;

varying vec2 texFrag;

void main() {
    vec4 color = texture(texSample, texFrag);
    if(color.rgb == vec3(0.0, 0.0, 0.0)) {
        color.a = 0.0;
    }
    gl_FragColor = color * vec4(tint, 1.0);
}

我相信我的问题可能与我将纹理转换为RGBA的方式有关。如果我使用位图而不进行此转换(也就是使用RGB而不使用finalData缓冲区),结果是数据错误地对齐。更改解压缩对齐并不能解决该特定错误。这使得直接从freetype使用数据变得不可行。

如果相关,我使用的语言是生锈的,库是gl-rsfreetype-rs。我在Windows上,我使用的freetype是在启用子像素渲染的情况下编译的。我将如何解决这个问题,还有其他一些我应该注意的问题,因为我会继续努力让它发挥作用吗?

0 个答案:

没有答案