topameng's profileQuake3 启示录PhotosBlogListsMore Tools Help

Blog


    February 26

    FreeType字体显示模糊

    我设置的是让左上角做为原点(0,0), 用正交投影来实现的2D显示, 同样的2d 引擎HGE也这样做的。但我用FreeType实现的文字比起HGE模糊暗上一些。打印出来的点阵都是相同的,开始还以为 alphablend 哪里弄错了。偶然才发现是设置投影矩阵的影响。HGE 做法:
    void HGE_Impl::_SetProjectionMatrix(int width, int height)
    {
    D3DXMATRIX tmp;
    D3DXMatrixScaling(&matProj, 1.0f, -1.0f, 1.0f);
    D3DXMatrixTranslation(&tmp, -0.5f, height+0.5f, 0.0f);
    D3DXMatrixMultiply(&matProj, &matProj, &tmp);
    D3DXMatrixOrthoOffCenterLH(&tmp, 0, (float)width, 0, (float)height, 0.0f, 1.0f);
    D3DXMatrixMultiply(&matProj, &matProj, &tmp);
    }
    而我只调用了:
    D3DXMatrixOrthoOffCenterLH(&m_matProj,0,(float)width,(float)height,0,0.0f,1.0f);
    d3dOK( m_pDevice9->SetTransform(D3DTS_PROJECTION, &m_matProj) );
    作用是相同的:把左上角作为原点,不同的是 HGE 相当于(-1,-1)作为了原点往左上移动了一个像素
    结果如下:
    freetype
     freetype1
    奇怪的问题。
    我也同样向左上移动:字体显示就亮了些,特别是对于笔画粗的文字,也都细了。
    D3DXMATRIX tmp;
    D3DXMatrixOrthoOffCenterLH(&m_matProj,0,(float)m_iWidth,(float)m_iHeight,0,0.0f,1.0f);
    D3DXMatrixTranslation(&tmp, -0.5f, -0.5f, 0.0f);
    D3DXMatrixMultiply(&m_matProj, &tmp, &m_matProj);
    不知道原因,如果有高手明白请不吝赐教。

    重新编译了FreeType ,打开了freetype 对bytecode interpreter 的支持。修改ftoption.h
    即使用字体本身的HINTING来读取小字体
    #define TT_CONFIG_OPTION_BYTECODE_INTERPRETER
    屏蔽了
    /*#define TT_CONFIG_OPTION_UNPATENTED_HINTING*/

    打开了对液晶显示器的支持
    #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING

    上面的图显示的英文要比汉字暗一些。设置纹理操作为modulate2x
    m_pDevice9->SetTextureStageState( 0,D3DTSS_ALPHAOP,D3DTOP_MODULATE2X );
    提高alpha值。结果:
    finial 

    终于找到了原因,其实跟正交投影没有一点关系。主要是纹理滤波的问题,浪费了大量时间,不过也得到了不少,
    1 如FreeType  使用字体文件bytecode interpreter (版权归字体创建者所有),来显示小的文字
    2 对于正交投影的理解。经过正交矩阵相乘最终的点映射到2维坐标(-1,-1) 和(1,1)之间。中心点为(0,0)
    当正交矩阵移动0.5,其实相当于坐标系内物体移动了1个像素,因为被正交坐标系(0,0)分成了2个部分。而这个偏移导致字体不在模糊是因为把变换的点,再映射到视口的时候产生了0.5像素大小,如300.5, 这样的0.5被舍弃,字体大小略有变化,这个变化也影响了纹理滤波,所以显示文字时设置滤波最好是: 系统默认D3DTEXF_NONE或者D3DTEXF_POINT,不过字体大的时候相对影响不明显,到是可以用来加粗字体(不推荐)
    //缩小滤波
    m_pDevice9->SetSamplerState( i,D3DSAMP_MINFILTER,D3DTEXF_POINT) ;
    //放大滤波
    m_pDevice9->SetSamplerState( i,D3DSAMP_MAGFILTER,D3DTEXF_POINT);
    //mipmap 选择
    m_pDevice9->SetSamplerState( i,D3DSAMP_MIPFILTER,D3DTEXF_LINEAR);

    找到了实现文字粗体的函数:

    if(!FT_Load_Glyph(m_FTFace,idx,FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP))
    {
        FT_GlyphSlot glyph = m_FTFace->glyph;

        if (glyph->format == ft_glyph_format_outline)
        {

            if(m_bShadow)
            {
                //加粗文字
                FT_Outline_Embolden( &(glyph->outline), 260 );
            }
            if (!FT_Render_Glyph( glyph, m_bAntiAliased ?  FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO))
            {
              //更新到纹理中
            }
        }

    }

    //用粗体文字做底纹实现类似魔兽任务tips的文字
     wow

    February 21

    stlport 标准库内存泄漏

    使用stlport vector 居然发现了内存泄漏.
    STLport现在的做法是会特意泄漏内存的,如果你检测到内存泄漏,经过讨论,STLport采用了特意不回收收集的小块内存,而借助现代操作系统的自动回收能力(应用程序退出时会收回分配给进程的内存)的做法,以减少内存印记、获得较好的再分配能力和性能。具体的详细解释,可以读源码,上STLport的交流论坛,或者看《STL源码剖析》——里面有关于SGI内存适配器(也是STLport所采用的)的解析。
    尽管泄漏一次不算什么内存泄漏,但当程序过大时候,可能内存泄漏数据多了起来会影响调试.也可以避免这种情况如 含有 int 的 vector  resize 到 64 即可避免因小块内存而出现的内存泄漏,内存泄漏的一些调试方法可以使用vld 也可以用ms的调试函数. 可以参考前面的使用VLD检测内存泄露:
     http://topameng.spaces.live.com/blog/cns!F962D4854A8233D!341.entry