最近在写一个template与析构函数有关的东西,碰到了一个比较自己不怎么能理解的问题。我写了如下两个模板函数
1 template< typename T, typename Alloc>
2 T* air_new_t()
3 {
4 return new ( Alloc::allocBytes( sizeof( T ) )) T;
5 }
6
7 template< typename T, typename Alloc>
8 void air_delete_t(T* ptrBase)
9 {
10 if (ptrBase)
11 {
12 ptrBase->~T();
13 Alloc::deallocBytes( ( void* ) ptrBase );
14 }
15 }
然后在main函数中这使用这两个模板函数
1 int* ptr = air_new_t<int, CMemoryNedAlloc>();
2 *ptr = 10;
3 cout<<*ptr<<endl;
4 air_delete_t<int, CMemoryNedAlloc>(ptr);
以我的理解这应该是要编译错误的,因为ptr ->~int();在vs上是明显不行的。但是奇怪的是程序正常的运行了,当是基本类型时
ptrBase->~T()语句会跳过,如果是自己定义的类型则会调用ptrBase->~T()。可以肯定的是模板函数会对基本类型的虚构函数进行特殊的处理,但是如何处理,是以何种规则处理呢?这些我都不明白,问了其他人,和网上查了些但还是太明白,这里也提到了相关的东西,但是我还是不太明白。模板函数不能特化,这样也正好达到了我的目的,原本还想这用特化来处理基本类型呢。不过虽然可以达到目的,到时其中的规则和原因不太明,心里也是没啥底。应该c++的文档里有提及,但是还没怎么查过文档呢,这个东西找起来可能要花些时间,特此记录一下,等找到说明再补上。
posted @
2011-07-21 22:45 木华 阅读(945) |
评论 (0) |
编辑 收藏
之前对虚函数也就是知道有所谓的虚函数表,以及虚函数的用法。但是对于一个类的sizeof是否包含虚函数呢,这些也并不了解。由于最近在弄内存分配,想到虚函数与sizeof,不知道sizeof是否包含了续表 所以今天查了下,看了下这里,讲的很清晰。我也写了断代码测试了一下:
1 class BaseA{
2 private:
3 int x;
4 int y;
5 public:
6 virtual void who()
7 {
8 cout<<"i am BaseA"<<endl;
9 }
10
11 };
12
13 class BaseB
14 {
15 public:
16 virtual void who()
17 {
18 cout<<"i am Base B"<<endl;
19 }
20 private:
21 int x;
22 int y;
23 };
24
25 class DeriveA : public BaseA
26 {
27 public:
28 virtual void who()
29 {
30 cout<<"i am DerivaA"<<endl;
31 }
32 virtual void ownFun()
33 {
34
35 }
36 };
37
38 class DerivAB :public BaseA,public BaseB
39 {
40 public:
41 virtual void ownFun();
42 virtual void who()
43 {
44 cout<<"i am DerivaAB"<<endl;
45 }
46 };
47
48 int main()
49 {
50
51 cout<<"sizeof BaseA: "<<sizeof(BaseA)<<endl;
52 cout<<"sizeof BaseB: "<<sizeof(BaseB)<<endl;
53 cout<<"sizeof DerivA: "<<sizeof(DeriveA)<<endl;
54 cout<<"sizeof DerivAB: "<<sizeof(DerivAB)<<endl;
55 }
输出的结果也是预想中的
sizeof BaseA: 12
sizeof BaseB: 12
sizeof DerivA: 12
sizeof DerivAB: 24
请按任意键继续. . .
BaseA与BaseB中x,y占8 加上虚表就是12了。
而DerivAB多继承AB,所以有BaseA 与BaseB的x,y,数据 以及两个虚表的指针所以是24了。这样看来一个类有多少个虚表也是要看是否有多个继承以及基类里是否也有虚表。sizeof居然包含了虚表的指针,那想必用placement new对于包含虚函数的类也是有用的吧。经过测试,是可以的。c++还有太多的东西不清楚起内部是如何操作的呀。继续一步学习
posted @
2011-07-19 23:10 木华 阅读(1129) |
评论 (0) |
编辑 收藏
这段时间都在弄PostProcess,到现在为止,我对我的设计都不满意。但是也需要做个了结,先实现一些基本的功能。到以后慢慢有了经验了,或是看到了别人比较好的设计方法时再会过头来弄吧。
我对PostProcess也是从0开始的,最先是网上查看一些资料和看sdk中的那postprocess的例子。说白了,postprocess很简单,就是在最后把场景渲染到一种贴图,然后通过pixel shader对这个贴图进行各种处理已达到想要的效果,然后把贴图以2D的方式渲染出来。整个过程都是很简单的。但是要把postprocess的框架设计的好我觉得是很困难的。框架的好与劣以我暂时的浅薄的看法就是框架不需要为增加一种postprocess效果而改动太大。但是这个问题纠结了我很久。
我最初的想法是类似模仿sdk中的例子,通过归纳总结出postprocess操作的shader需要些什么数据,然后把数据都传入进去,不管是否需要,比如有些shader需要渲染窗口的backbuffersize的大小用于把像素点大小转化为纹理大小(blur操作),有些shader需要原始场景贴图合并操作,把后处理的tex与原始场景累加(combine操作)。甚至有些c++的代码需要知道shader里面的数据,比如把贴图放大或缩小操作。这种,把所有都归纳出来的话碰到有两个问题:1、归纳无法完善,现在我们能确定的也只是所有后处理的shader需要上一次后处理的结果的tex作为输入源。然后各种不同的shader就有不同需求了,有的只是需要上一次的postprocess结果,有的是需要原始场景贴图,backbuffer的大小,有点还要给外部c++代码提供参数,放大或缩小贴图。2、由于我使用的是直接的shader而不是effect,所以当一个shader里的量没被使用到时GetConstantByName 和GetConstantDesc是不成功的,因为没使用的变量会被编译器优化掉。
想了很久都卡在这了,但是总不至于每个postprocess都单独的写一份c++的代码去对待吧。最后我也没想出好的什么办法,一个不是办法的办法:封装一个SinglePostProcess类,其代表一个后处理,它带有两个产生列表。一个是提供信息给c++代码使用,一个是提供信息告诉我们shader需要一些什么样的参数设置。然后在pp的框架中就分别根据这两个列表来进行一些设置。这样的缺点就是shader的编写和一些参数的名字是要有规则的,在创建一个SinglePostProcess时需要填写这两个参数列表。
实现的效果:
没经过postprocess处理的截图:
通过了后处理的(bloom处理)截图:
实现一种效果往往需要多个后处理才能达到,所以我觉得一个好的后处理框架的设计很重要。
后处理就先到次吧,以后想到或发现有更好的设计再弄。接下来还要很多东西要学习····慢慢走吧····
posted @
2011-04-28 22:58 木华 阅读(2550) |
评论 (0) |
编辑 收藏
这几天在弄后处理,看了下网上和skd在的介绍后,大概框架原理是明白了,但是在实现的过程中还是遇到了一些问题这些问题。这些问题会在之后慢慢记录下来。
问题1:交换两个 IDirect3DTexture9*变量,原本在处理多个效果时,我的想法是方法交替地用两个textuere,所以有下面一段代码
1 IDirect3DTexture9* pTex;
2 pTex = m_pSoureTex;
3 m_pSoureTex = m_pTargetTex
4 m_pTargetTex = pTex;
但是上面代码并没有真正交换到,都变成了m_pSoureTex的内容,我觉得很奇怪,我觉得这样可以交换m_pTargetTex 和 m_pSoureTex指向的对象呀。设置断点调试的结果是:
很明显虽然m_pTargetTex 和 m_pSoureTex 的地址变了,但是其真正的内容是没相同的。这个问题我并不太清楚,网上也没找到答案,我想着与com有关吧,一般人都不会写出这样的代码吧,来交换两个texue的吧,这应该也算是对dx的不够了解和写代码不好的一个原因吧。但是以后要有时间真的要找找是什么原因才行。对应这个问题参考了sdk例子中的写法。其中例子中用了CRenderTargetChain,其技巧就是把两个变量存在一个数组中,通过改变下标返回想要的IDirect3DTexture9*这个方法不错,也值得借鉴。
问题2:发现在公司的机器上程序能正确运行,但是我自己的笔记本上就出问题了,texture的大小不对。我创建贴图用的代码是这样的
D3DXCreateTexture(
gDevice,
surfaceDesc.Width,
surfaceDesc.Height,
surfaceDesc.Usage,
D3DUSAGE_RENDERTARGET,
surfaceDesc.Format,
D3DPOOL_DEFAULT,
&g_pSoureTex
);
我通过获取到g_pSoureTex的D3DSURFACE_DESC发现 它的长和宽居然不是我指定的长和宽 都变成了2的幂的大小了,网上查了下 原来是 D3DXCreateTexture;
函数经过了优化处理,把贴图的大小改变了。所以我用IDirect3DDevice9::CreateTexture函数就没问题了。但是在公司也是用D3DXCreateTexture函数但没有把长宽优化到2的幂,难道这和显卡有关了!?
posted @
2011-03-23 22:35 木华 阅读(457) |
评论 (0) |
编辑 收藏
已经很久没来这里记录东西了,在写了地下的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;
这样才正确的显示了:
posted @
2011-03-11 23:34 木华 阅读(14888) |
评论 (3) |
编辑 收藏