使用 Direct3D 进行高级文本渲染
先描述一下我的任务的“战场”:
- 超过1M用户的多房间音视频聊天;
- 自定义 Direct3D 渲染器;
我需要实现的是 TextOverVideo 功能。文本本身通过网络传输,并使用 Direct3D 渲染器在接收方进行渲染。 AFAIK,它通常用于游戏开发中,用字母/数字创建自己的纹理并绘制该项目。因为我们的应用程序必须支持多种语言,所以我们应该使用一个标准。这就是为什么我一直在使用 ID3DXFont 界面,但我发现了一些不满意的限制。
我面临的是缺乏可扩展性。例如,如果用户正在调整视频窗口的大小,我必须在他这样做时使用新的 D3DXFONT_DESC 重新创建 D3DXFont。我认为这是不可接受的。 这就是为什么我看到的唯一解决方案(由于我的技能)是以某种方式将文本渲染为纹理,从而通过缩放、平移等绘制精灵。
所以,我不确定我是否进入了正确的方向。请提供建议、经验、文献、资料来源......
Let me describe the "battlefield" of my task:
- Multi-room audio/video chat with more than 1M users;
- Custom Direct3D renderer;
What I need to implement is a TextOverVideo feature. The Text itself goes via network and is to be rendered on the recipient side with Direct3D renderer. AFAIK, it is commonly used in game development to create your own texture with letters/numbers and draw this items. Because our application must support many languages, we ought to use a standard. That's why I've been working with ID3DXFont interface but I've found out some unsatisfied limitations.
What I've faced is a lack of scalability. E.g. if user is resizing video window I have to RE-create D3DXFont with new D3DXFONT_DESC while he's doing that. I think it is unacceptable.
That is why the ONLY solution I see (due to my skills) is somehow render the text to a texture and therefore draw sprite with scaling, translation etc.
So, I'm not sure if I go into the correct direction. Please help with advice, experience, literature, sources...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
你的问题有点不清楚。据我了解,您需要易于缩放的字体。
据我所知,这是字体的标准行为 - 即使对于系统字体也是如此。它们不应该容易扩展。
可能的解决方案:
我会忘记它。只要用户对整体性能感到满意,改进字体渲染例程(因此他们的行为看起来对您来说很好)就不值得付出努力。
--编辑--
关于 ID3DXRenderTarget。
即使您使用 ID3DXRenderTarget,您也需要 ID3DXFont。即,您使用 ID3DXFont 将文本渲染到纹理上,然后使用纹理将文本传输到屏幕上。
因为您说过性能至关重要,所以您可以延迟创建新的 ID3DXFont,直到用户停止调整视频大小。即,当用户开始调整视频大小时,您使用旧字体,但使用纹理对其进行升级。当然会有过滤。一旦用户停止调整大小,您就有时间创建新字体。您可能可以在单独的线程中执行此操作,但我不确定。或者您可以简单地始终以与视频相同的分辨率渲染文本。这样您就不必担心调整它的大小(它仍然会与视频一起被过滤)。一些视频播放器以这种方式工作。
关于 ID3DXFont 的更多信息。 ID3DXFont 有一个问题 - 在需要大量文本的情况下它很慢(但你仍然需要它,因为它支持 unicode,并且编写带有 unicode 支持的纹理字体是痛苦的)。上次我使用它时,我通过在纹理中缓存常用字符串来优化一些东西。即,在行中绘制超过 3 帧的任何字符串都会渲染到 D3DFMT_A8R8G8B8 纹理/渲染目标上,然后我一直从纹理复制该字符串,而不是使用 ID3DXFont。暂时未渲染的字符串已从纹理中删除。这给了我们很大的推动。然而,这个解决方案很棘手——监视纹理中的空白空间、删除未使用的字符串以及对纹理进行碎片整理并不是微不足道的(没有什么特别复杂的,但很容易犯错误)。除非您的屏幕实际上被文本覆盖,否则您不需要如此复杂的系统。
Your question is a bit unclear. As I understand it, you want easily scalable font.
As far as I know, this is standard behavior for fonts - even for system fonts. They aren't supposed to be easily scalable.
Possible solutions:
I'd forget about it. As long as user is happy about overall performance, improving font rendering routines (so their behavior looks nice to you) is not worth the effort.
--EDIT--
About ID3DXRenderTarget.
EVen if you use ID3DXRenderTarget, you'll need ID3DXFont. I.e. you use ID3DXFont to render text onto texture, and then use texture to blit text onto screen.
Because you said that performance is critical, you can delay creation of new ID3DXFont until user stops resizing video. I.e. When user starts resizing video, you use old font, but upscale it using texture. There will be filtering, of course. Once user stops resizing, you create new font when you have time. you probably can do that in separate thread, but I'm not sure about it. OR you could simply always render text in the same resolution as video. This way you won't have to worry about resizing it (it still will be filtered - along with the video). Some video players work this way.
Few more things about ID3DXFont. There is one problem with ID3DXFont - it is slow in situations where you need a lot of text (but you still need it, because it supports unicode, and writing texturefont with unicode support is pain). Last time I worked with it I optimized things by caching commonly used strings in the textures. I.e. any string that was drawn more than 3 frames in the row were rendered onto D3DFMT_A8R8G8B8 texture/render target, and then I've been copying that string from texture instead of using ID3DXFont. Strings that weren't rendered for a while, were removed from texture. That gave some serious boost. This solution, however is tricky - monitoring empty space in the texture, removing unused strings, and defragmenting the texture isn't exactly trivial (there is nothing exceptionally complicated, but it is easy to make a mistake). You won't need such complicated system unless your screen is literally covered by text.
ID3DXFont 字体是扁平的,始终与屏幕平行。 D3DXCreateText 是可以缩放和旋转的网格。
纹理字体模糊,看起来不太清晰。不适合使用大量小文本的应用程序。
我正在编写一个应用程序,可以创建 500 个文本网格,每个网格平均有 3,000-5,000 个顶点。文本网格创建一次后就是静态的。我在 GeForce 8800 上获得 700 fps。
ID3DXFont fonts are flat, always parallel to the screen. D3DXCreateText are meshes that can be scaled and rotated.
Texture fonts are fuzzy and don't look very clear. Not good for an app that uses lots of small text.
I am writing an app that can create 500 text meshes, each mesh averaging 3,000-5,000 vertices. The text meshes are created once, then are static. I get 700 fps on a GeForce 8800.