C# 或 C++游戏:许多 16 色图像加载到 RAM 中。有效的解决方案?

发布于 2024-10-10 05:30:54 字数 844 浏览 0 评论 0原文

我正处于创建一款格斗游戏的规划阶段,不确定如何处理与内存相关的问题。

背景信息:
- 仍在争论是使用 C# (XNA) 还是 C++。在我们探索如何用两种语言解决这个问题之前,我们不想承诺任何一种。
- 如果可能的话,使用最大 256MB RAM 会很棒。
- 一次会出现两个角色,并且这些角色只能在战斗之间更换。战斗之间有时间加载/释放内存,但游戏在战斗期间需要以每秒 60 帧的恒定速度运行。每帧16.67ms
- 每个角色的图像总数只有几百张。每个图像大约为 200x400 像素。在任何给定时刻只会显示每个角色的一张图像。

根据我的计算,未压缩时每张图像大约需要 300kb;整个字符超过 100MB。鉴于某些其他资源也需要内存,这太接近 256MB 限制了。

因为每个图像总共可以用 16 种颜色来制作。理论上,如果我能利用这一点,我应该能够使用 1/8 的空间。我环顾四周,但没有找到任何对调色板图像的本机支持。 (使用更少的位存储每个像素,每个像素映射到 32 位 RGBa 颜色)

我们尝试使用 DXT 压缩,但是,压缩伪影非常明显。

我正在考虑制作自己的文件格式,每像素 4 位(以及一些额外的调色板信息),在战斗前将这种新格式的所有图像加载到 RAM 中,然后在绘制任何特定图像时,仅将该图像解压缩为原始图像所以它可以正确渲染。我不知道每帧执行如此多的赋值操作(每个字符约 200x400 = 160k)是否现实。对我来说这听起来很老套。

有人对我的解决方案听起来是否合理以及是否有更好的解决方案有建议吗?

非常感谢!

(我还尝试使用只有 1 个通道的图像,然后使用着色器执行一系列 if 语句,将各种值转换为其他颜色。不幸的是,着色器的代码行太多。它也相当 hacky并且不能很好地扩展。)

I am in the planning stages of creating a fighting game and am unsure how to handle one issue relating to memory.

Background info:
- Still debating whether to use C# (XNA) or C++. We do not want to commit to either until we have explored how to solve this problem in both languages.
- Using a max of 256MB RAM would be great if possible.
- Two characters will be present at a time, and these characters can only change between battles. There is time to load/free memory between battles, but the game needs to run at a constant 60 drawn frames per second during combat. Each frame is 16.67ms
- The total number of images per character is in the low hundreds. Each image is roughly 200x400 pixels. Only one image from each character will be displayed at any given moment.

Uncompressed, each image takes roughly 300kb from my calculations; upwards of 100MB for a whole character. This is pushing too close to the 256MB limit given that memory will be needed for some other resources as well.

Since each image can be made with a total of 16 colors. Theoretically I should be able to use 1/8th the space if I can take advantage of this. I've looked around but haven't found any word of native support for paletted images. (Storing each pixel using fewer bits that each map to a 32-bit RGBa color)

We tried using DXT compression, however, the compression artifacts are quite noticeable.

I was considering making my own file format with 4 bits per pixel (and some extra palette info), loading all the images of this new format into RAM before battle, and then when drawing any specific image, decompress only that image into a raw image so it can be rendered properly. I don't know if it's realistic to perform so many assignment operations (appx 200x400 for each character = 160k) each frame. It sounds very hacky to me.

Does anyone have advice on whether my solution sounds reasonable, and if there is perhaps a better one available?

Thanks so much!

(I also attempted to use an image with only 1 channel, then use a shader to perform a series of if statements to translate various values into other colors. Unfortunately, there were too many lines of code for the shader. It is also rather hacky and does not scale well.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

唱一曲作罢 2024-10-17 05:30:54

请改用 S3 纹理压缩(又名 DXTn)。 S3TC 允许您以 4 位/像素或 8 位/像素存储纹理,并且显卡本身支持它。您不必担心动态解压缩它,因为显卡会这样做。

DirectX 在 C++ 和 C# 中对 S3TC 都有很好的支持。

Use S3 Texture Compression (aka DXTn) instead. S3TC lets you store textures at 4 bits/pixel or 8 bits/pixel, and it's supported natively by graphics cards. You don't have to worry about decompressing it on the fly, since the graphics card does that.

DirectX has very good support for S3TC, in both C++ and C#.

他不在意 2024-10-17 05:30:54

如果您想以 Xbox 360 为目标并且没有合适的(成熟的)开发套件,那么 C# 是您唯一的选择。当开始使用 XNA 时,XNA 肯定会让您的工作变得更加轻松,特别是如果您现在只做 2D(并且可以处理许多您现在不需要担心的其他事情)。

至于内存限制问题,建议解决:

  • 使用1555纹理格式将大小减半
    (虽然你只有 1 位
    alpha)
  • 不同的图像有任何共同的部分吗?您可以使用许多较小的图块而不是一个大的图块(即 2x4 或更大的网格)来渲染角色吗?最有可能的是,你会在角落里有很多空白空间,可以在大多数图像之间共享,这将产生良好的保存效果(我刚刚发现有人已经通过 spritesheets 提到过这一点 - 尽管这应该是一个无损的保存选项记忆)。
  • 您提到已经尝试伪造托盘纹理。您可以拥有一个包含调色板颜色的第二个纹理,而不是 IF 语句,并使用从第一个纹理获得的值作为纹理坐标,通过像素着色器查找第二个纹理(第二个纹理只是一个一维纹理) 32 位颜色值的纹理)。
  • 考虑到现代处理器的强大功能以及您当时所做的其他事情,您可能有足够的备用资源来将两个角色的动态帧解压缩为准备渲染的纹理(尤其是多核)。不过,您至少需要对纹理进行双缓冲,以阻止 CPU 阻塞等待 GPU 完成使用前一帧中的纹理。

您还可以结合其中一些选项来节省更多。

If you want to target the XBox 360 and don't have a proper (full blown) devkit, then C# is your only option. When starting out XNA certainly makes doing things a lot easier for you, especially if you're just doing 2D for now (and takes care of a lot of other things you don't need to worry about right now).

As for the memory constraints issue, suggestions to get it down:

  • Use the 1555 texture format to halve the size
    (although you'll only have 1 bit of
    alpha)
  • Do the different images have any common sections? Could you render the character using a number of smaller tiles rather than one large one (i.e. a grid of 2x4 or more). Most likely you'll have a lot of empty space in the corners that could be shared between most images and this will yield a good saving (I've just spotted someone already mentioned this via spritesheets - although this should be a lossless option to save memory).
  • You mention already trying to fake palletised textures. Instead of IF statements, you could have a 2nd texture that contains the palette colours and use the value you get from the first texture as a texture co-ordinate to lookup into the 2nd texture via a pixel shader (the 2nd texture is just a 1D texture of 32-bit colour values).
  • Given the power of modern processors and depending on what else your doing at the time, you may well have enough spare resources to decompress frames on the fly for the two characters into textures ready for rendering (especially with multi-core). You'll need to at least double-buffer the textures to stop the CPU blocking waiting for the GPU to finish using them from the previous frame though.

You could also combine some of these options to save more.

后eg是否自 2024-10-17 05:30:54

我认为将图像放入精灵表中是最好的选择。这可以让您在因压缩而丢失图像数据和内存成本之间取得最佳平衡。

我将从 C# 和 XNA 框架开始,因为它对内置精灵处理器有很好的支持,并且内容管道可以在编译时自动将单个图像转换为完整的精灵表。 Microsoft 在此处提供了一个演示此功能的示例项目: http://create.msdn .com/en-US/education/catalog/sample/sprite_sheet

I think putting your images into a spritesheet is your best option. This gives you the best balance between losing your image data to compression, and memory cost.

I would start with C# and the XNA framework as there is excellent support for a built in sprite processor and the content pipeline can automatically convert individual images into a complete spritesheet at compile time. Microsoft provides a sample project demonstrating this functionality here: http://create.msdn.com/en-US/education/catalog/sample/sprite_sheet

猫烠⑼条掵仅有一顆心 2024-10-17 05:30:54

您可以使用霍夫曼编码树来存储在内存中压缩的数据(因为正如您所说,它压缩得很好);然后实时提取/加载。您还可以使用其他压缩数据结构。

You could use a Huffman Encoding Tree to store the data compressed in the memory (since, as you say, it compresses well); then extract/load in real-time. There are other compressed data structures as well that you could use.

燃情 2024-10-17 05:30:54

您可能需要查看 xnaMUGEN。格斗游戏引擎可以用 C# 轻松完成。

You may want to look at xnaMUGEN. A fighting game engine is something which can easily be done in C#.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文