已经很久没来这里记录东西了,在写了地下的lod后,dx的学习也是断断续续的,那之后给地形加上了贴图,弄了段时间的shader,之后地形就放下了,之后开始弄了水的渲染。在弄水的渲染也是碰到了很多的问题但是都太懒了都没记录下什么,等有时间一定要补上。这段时间在弄freetype。主要是通过freetype把字体渲染到纹理上,然后通过纹理贴图把字显示出来。
整体思路是这样的:对字符串中每个字进行处理,看该字是否已经渲染到在纹理中了,如果有则取得相应的信息进行渲染到目标上,如果没则把这个字渲染到纹理,然后进行渲染处理。
freetype的介绍就不说了,网上很多资料,并且我对它的所有认识都是从网上来的,也感谢一些前辈留下他们的学习的心得。在这个过程中碰到一些问题记录一下。其中包括freetype自身 和 dx,并且发现 《Introduction To 3D Game Programming With DirectX 9.0》源码有个地方有点问题。
Freetyep怎么说呢,我也是在开始接触时不知道是啥玩意,然后看一些介绍的文章和官方的文档对其有了一定的了解后,就开始弄了。
要注意的
1、freetype的一些规约 一些参数的定义,看文档是很重要的 如:点的定义等,为什么一些参数要乘以64,一些要除以64。
2、freetype的bitmap的 bitmap.pixel_mode。当在 FT_Render_Glyph函数中设置 FT_RENDER_MODE_NORMAL,根据是中英文或是字体大小的影响都有可能
pixel_mode 为FT_PIXEL_MODE_MONO 或 FT_PIXEL_MODE_GRAY。
如何把freetype生成的bitmpa的数据写到dx纹理下呢
1、创建纹理。
创建一个格式为 D3DFMT_A8L8 的纹理,8位alpha值,8位RGB颜色值。
在填充时没注意又碰到点问题如下面两段代码:
D3DLOCKED_RECT lockedRect;
m_pTexture
->
LockRect(
0
,
&
lockedRect,
0
,
0
);
unsigned
char
*
DesData
=
(unsigned
char
*
) lockedRect.pBits;
for
(
int
i
=
0
; i
<
m_nTexHeight ; i
++
)
{
for
(
int
j
=
0
; j
<
m_nTexWidth ; j
++
)
{
int
index
=
i
*
lockedRect.Pitch
/
2
+
j;
DesData[
2
*
index]
=
0x00
;
DesData[
2
*
index
+
1
]
=
0xff
;
}
}
m_pTexture
->
UnlockRect(
0
);
D3DLOCKED_RECT lockedRect;
m_pTexture
->
LockRect(
0
,
&
lockedRect,
0
,
0
);
unsigned
short
*
DesData
=
(unsigned
short
*
) lockedRect.pBits;
for
(
int
i
=
0
; i
<
m_nTexHeight ; i
++
)
{
for (int j = 0 ; j < m_nTexWidth ; j++)
{
int index = i * lockedRect.Pitch / 2 + j;
DesData[index] = 0x00ff;
}
}
m_pTexture
->
UnlockRect(
0
);
这两段代码由于对一个像素的不同复值也让我调试了很久,我们的机器是小端 所以两个unsigned char 转化为一个unsigned short 时要反过来才正确。
2 在慢慢地一点点的模仿网上的一些代码后终于可以把字体写入到纹理了。后面是怎样通过这个纹理把字体渲染到2D的平面上。一开始是用直接ID3DXSprite 把整个字体纹理渲染出了,以用于检查是否正确写入到了纹理中。但在渲染字体时,我没选择用它,我是用了D3DFVF_XYZRHW来渲染,每个字有4个顶点,两个3角形,6个索引组成的
我的顶点结构如下:
struct
UIRHWVertex
{
float mx, my, mz, mrhw;
float mu, mv;
DWORD mcolor;
static const DWORD FVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1 ;
}
;
这下子悲剧了,我检查了很久很久都显示不了,为什么贴图显示不都是显示黑的。
在快要崩溃的时候无意中换了下颜色和 vu的声明顺序为:
struct
UIRHWVertex
{
float mx, my, mz, mrhw;
DWORD mcolor;
float mu, mv;
static const DWORD FVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1 ;
}
;
这样就正确了。真是郁闷到点了。也不知为什么?!
该看到字体了,写了UIWord,UIRender,UIEditBox类,就等着看先效果了,但是郁闷的来了无论怎样,字体都不清晰或是烂了的感觉,但是检查写在纹理的字体都是完好的。
模糊
真是郁闷了很多天但是为什么会这样呢,查了很多原因,贴图与距形的大小是否一致,是否有偏移,是否是贴图的大小不是2的幂 等等都一样的排除了。最后弄了个简单的程序能清晰显示图片的来一一比终于发现问题了。
我在开始学习dx是看《Introduction To 3D Game Programming With DirectX 9.0》的。所以很多代码我就直接用了它源码的框架来用,在d3dUtility.cpp文件中创建设备是这样的
D3DPRESENT_PARAMETERS d3dpp;
d3dpp.BackBufferWidth
=
width;
d3dpp.BackBufferHeight
=
height;
d3dpp.BackBufferFormat
=
D3DFMT_A8R8G8B8;
d3dpp.BackBufferCount
=
1
;
d3dpp.MultiSampleType
=
D3DMULTISAMPLE_NONE;
d3dpp.MultiSampleQuality
=
0
;
d3dpp.SwapEffect
=
D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow
=
hwnd;
d3dpp.Windowed
=
windowed;
d3dpp.EnableAutoDepthStencil
=
true
;
d3dpp.AutoDepthStencilFormat
=
D3DFMT_D24S8;
d3dpp.Flags
=
0
;
d3dpp.FullScreen_RefreshRateInHz
=
D3DPRESENT_RATE_DEFAULT;
d3dpp.PresentationInterval
=
D3DPRESENT_INTERVAL_IMMEDIATE;
//
Step 4: Create the device.
hr
=
d3d9
->
CreateDevice(
D3DADAPTER_DEFAULT,
//
primary adapter
deviceType,
//
device type
hwnd,
//
window associated with device
vp,
//
vertex processing
&
d3dpp,
//
present parameters
device);
//
return created device
其中的
d3dpp.BackBufferWidth = width;
d3dpp.BackBufferHeight = height;
是问题,其中width和height是传入的参数,是用于创建窗口的大小的参数
但这个是窗口的大小并不是渲染的窗口的大小
所以要用
RECT rect;
GetClientRect(hwnd,&rect);
获取到大小后再设置backbuffer的大小为:
d3dpp.BackBufferWidth = rect.right - rect.left;
d3dpp.BackBufferHeight = rect.bottom - rect.top;
这样才正确的显示了: