Jul 23

实现3D渲染的桌面宠物

编程心得

今天看到前同事出去开公司搞了一个桌面3D宠物,感觉有点意思,以前就想过桌面版的任天狗online,没有想到已经有人搞起来了,“不是我不明白,是世界变化快”啊,所谓3D渲染的桌面宠物,就是类似office助手那种桌面动画(桌面精灵),其实它也是一个窗口,不同的是,是一个shape会改变的不规则窗口,office助手是2D图形,如果换成3D渲染一只宠物,我就称其“3D渲染的桌面宠物”。

 

先说说2D桌面精灵的实现,在2k的系统以后,有一个非常好用的函数,就是UpdateLayeredWindow,只要每次传递给他一个内容不同的dc,该函数就会根据dc的bitmap和key color,把桌面的shape修改为dc的样子,所以对于2D的桌面精灵就是定时修改dc的内容,然后调用UpdateLayeredWindow就可以了。与简单的2D桌面精灵不同的是,3D渲染对shape的变化率要求比较高(取决于fps),而得到3D渲染的rt则受到硬件特性的限制,我们都知道直接lock back buffer或者rt都是很慢,更不用提将rt变化为dc,所以要解决3D渲染转换可以使用的dc,首先要解决的就是速度问题。

 

解决速度问题,我想到了2种方法,第一就是完全软件渲染,摒弃对硬件的依赖,因为一般桌面精灵(即使是3D)对渲染质量不会太高,完全软件渲染的速度是完全可以接受的,无非是变换和光栅化,网络上也有一些纯软件实现的3D framework;第二种方法就是想办法优化从硬件中访问rt的速度,这也是我努力的方向,毕竟能用现成的技术直接渲染桌面精灵是再好不过了,经过不断尝试,总算解决了问题,步骤如下:

1)创建rt,渲染所有图形到rt;

2)创建offscreen surface,把rt的内容通过GetRenderTargetData函数导入到surface;

3.1) 如果需要同桌面alpha混合,lock surface,创建32bit bitmap,select到mem dc;

3.2) 如果不需要alpha混合(可能会有锯齿,或者不会半透明),直接surface->getdc;

4) 使用上述dc调用UpdateLayeredWindow函数,收工。

 

这种方法在我的8800和7600的卡上,通过测试,其关键的时间消耗可能在步骤2)上,之前我直接lock rt,发现很慢,每次lock获取dc需要200ms,而通过一个offscreen surface转换则几乎没有时间消耗,当然GetRenderTargetData函数的效率我没有办法预估在不同card上的表现,如果在某些卡上效率不理想,则只有考虑方法1)了。

image

这是运行的效果图,由于没有模型动画,用了一个简单旋转三角形表示,原理一样。

点击这里下载例子,修改.jpg为.exe。

update2---------------------------------

很多童鞋留言,邮件询问我source, 这里说明下, 源代码早已丢失, 因为我的一块硬盘坏掉了.

tags:

to "实现3D渲染的桌面宠物"

  1. 求实现3D渲染的桌面宠物 Says:

    看了您实现实现3D渲染的桌面宠物我很欣喜,终于找到了实现它的方法了,本人初学,按你的方法做了还是有点问题,如果您不介意,可以把程序发给我看下吗?
    邮箱 yaowei2008cd@163.com

  2. 不错厉害 Says:

    博主你好,用你的方法做了确实很不错,不过cpu占用却一直非常高,一般都达到50%左右了,请问有办法降低占用吗?

    siney 于 2008-09-29 10:55:08 回复
    你可以考虑限制帧数,毕竟一般桌面宠物游戏,维持在30fps已经足够了
    不错厉害 于 2008-10-04 07:59:57 回复
    我将帧数降低到10帧都会占用40%左右的cpu,还是很高,博主能否再想想办法?
    我电脑是AMD的2核2.11G HZ

  3. webboyvc Says:

    最近我也碰到这个问题,我是新手,能否把您的源码发给我,研究一下,十分感谢。我的
    email:guoshuai418@163.com

  4. xoyojank Says:

    http://www.codeproject.com/KB/WPF/D3DImage.aspx
    在WPF已经可以支持Direct3D了

    siney 于 2008-09-30 16:46:13 回复
    恩,看起来挺强大的,不过貌似仅支持vista?
    xoyojank 于 2008-10-13 15:29:28 回复
    不用, 需要.net3.5sp1, 好像还要打个WindowsXP-KB937106-x86-ENU

  5. linrui Says:

    siney 您好,我们也正研究这种问题,能否将你的代码发给我参考一下。

  6. linrui Says:

    我的邮箱:linrui20011@sina.com

  7. ABXY Says:

    你好,可不可以把源码供我学习一下啊,不胜感激。谢谢。如果可以麻烦发到我邮箱,可以的话交个朋友,谢谢。我的邮箱iwanttoflywithstar@hotmail.com

  8. xuexue Says:

    楼主好,最近对这方面的技术很感兴趣!不知道有没有新的技术出来!
    像D-player跳舞软件有个桌面舞者的小程序就实现了桌面3D显示!不知道那种的技术原理是怎么来的!
    在其他地方看了有关GDI的资料说有实现方法!但是都没有相关技术文章出来!
    不知道楼主有共享的可能不!
    我的邮箱是pilotsyc@163.com,能给份源码吗?

  9. cyuyan Says:

    好文。感谢作者共享心得

  10. Jare Says:

    Siney好,我也对这个技术很感兴趣,能否发一份源码给我?我的邮箱是 s_fantasy@163.com 非常感谢!望不吝赐教!

  11. kk Says:

    楼主 你好!很高兴看到你这篇文章
    能否也给我份源码研究下 发往zhk450861222@qq.com
    太谢谢了!

  12. konga Says:

    Siney好,对你的实现很感兴趣,求代码一份,谢谢konthiga@gmail.com

  13. Anew Says:

    Siney久闻大名了.
    今天看到这篇文章,对你更加崇拜了..
    在下也研究D3D窗口透明很长时间了.用的是SetLayeredWindowAttributes.效率低下.
    想尝试你的方法进行渲染,特来取经.
    能发将源码发送我来研究,万分感谢.
    d9ss@163.com

    不明白 于 2009-07-01 16:13:34 回复
    请问为什么你说 你用的是SetLayeredWindowAttributes.它的效率为什么比UpdateLayeredWindow低下呢?

  14. 吴题 Says:

    能发将源码发送我来研究,万分感谢.
    d9ss@163.com

  15. 吴题 Says:

    能发将源码发送我来研究,万分感谢.

    etimes2001@qq.com

  16. drizzt Says:

    你好,我最近也想研究這種技術,可以請你將源碼寄一份給我研究參考嗎?,非常感謝你。
    drizztc@gmail.com

  17. wbfnnn Says:

    大师,你好,这个问题我已经困扰很久了,能否也发一份代码给我,太感谢了
    wbfnnn@126.com

  18. kawayiboy Says:

    请问能否也发一份代码给我,非常感谢您,tenglu2@qq.com

  19. cloverstudio Says:

    Hello,文章提到的例子我不能运行,
    可以给一份源码嘛,谢谢;

  20. cloverstudio Says:

    我邮箱:cloverstudios@live.cn

    Thanks;

  21. kawayiboy Says:

    你好,我想请问一下UpdateLayeredWindow是在哪里使用呢?是每一次绘制的时候吗?我现在不能把东西抠出来,一直有黑色的背景,请问应该怎么办?谢谢,希望你加我qq讨论这个问题,qq:421810919,谢谢

  22. Bravo Says:

    最近正好在研究这个技术,但是不管怎麽弄都会有黑色的背景,请问源码是否能够给我一份?十分感谢。Email:fish8684@gmail.com

  23. 3DMan Says:

    楼主好,我按你的方法做了。但是达不到你的效果。如果能给一份源码的话,将不胜感激。
    邮箱:381825334@qq.com

    siney 于 2010-05-06 21:37:07 回复
    代码早丢了, 因为有个硬盘曾经罢工了

  24. hainengluo Says:

    太好了找了好久的,终于看到了高人,能给我代码吗?谢谢 977929132@qq.com

  25. track Says:

    CoolAdoreLove

Leave a Reply