0

我有 *.png 文件,我想从纹理中获取不同的 8x8 px 部分并将它们放在位图上(我猜是 SDL_Surface,但也许不是),就像这样:

图片。

现在我在没有位图的情况下渲染它,即我调用每个纹理并直接在屏幕上每一帧绘制部分,它太慢了。我想我需要加载每个 *.png 来分隔位图并使用它们传递视频内存,然后只调用一个大位图,但也许我错了。我需要最快的方法,我需要这样的代码(SDL 2,而不是 SDL 1.3)。另外,也许我需要在这里使用清晰的 OpenGL?

更新:
或者我可能需要以某种方式将 *.png 加载到 int 数组中并像通常的数字一样使用它们并将它们放置到一个大 int 数组中,然后将其转换为 SDL_Surface/SDL_Texture?这似乎是最好的方法,但是如何写呢?

更新2:
每个块中像素的颜色与图片中呈现的颜色不同,它们也可以是透明的。图片只是一个例子。

4

3 回答 3

1

好吧,当我问到“纯色”时,我的意思是-“在您从中复制的 .png 中的 8x8 像素区域中,所有 64 像素是否具有相同的 RGB 值?” 它在您的图表中看起来是这样的,那么这个怎么样:

如何创建一个, 并使用从原始 .png 读取的值直接绘制其成员SDL_Surface指向的内存的 8x8 像素区域。pixelsSDL_Surface

然后当你完成后,将该表面转换为一个SDL_Texture并渲染

你会避免所有的SDL_UpdateTexture()电话。

无论如何,这里有一些示例代码。假设您创建了一个名为EightByEight.

  class EightByEight
  {
    public:
      EightByEight( SDL_Surface * pDest, Uint8 r, Uint8 g, Uint8 b):
          m_pSurface(pDest),
          m_red(r),
          m_green(g),
          m_blue(b){}

      void BlitToSurface( int column, int row );

    private:
      SDL_Surface * m_pSurface;
      Uint8 m_red;
      Uint8 m_green;
      Uint8 m_blue;
  };

EightByEight您可以通过传递一个指向 an 的指针SDL_Surface以及红色、绿色和蓝色的一些值来构造一个类型的对象。此 RGB 对应于从您当前正在读取的 .png 的特定 8x8 像素区域获取的 RGB 值。SDL_Surface您将使用此 RGB 值绘制像素的特定 8x8 像素区域。

因此,现在当您想要绘制 的区域时SDL_Surface,您可以使用该函数BlitToSurface()并传入列和行值。例如,如果您将其划分SDL_Surface为 8x8 像素的正方形,BlitToSurface(3,5) 表示使用我在构造时设置的 RGB 值在第 4 列和第 5 行绘制正方形。

BlitToSurface()看起来像这样:

void EightByEight::BlitToSurface(int column, int row)
{
  Uint32 * pixel = (Uint32*)m_pSurface->pixels+(row*(m_pSurface->pitch/4))+column;

  // now pixel is pointing to the first pixel in the correct 8x8 pixel square 
  // of the Surface's pixel memory. Now you need to paint a 8 rows of 8 pixels, 
  // but be careful - you need to add m_pSurface->pitch - 8 each time 

  for(int y = 0; y < 8; y++)
  {
      // paint a row
      for(int i = 0; i < 8; i++)
      {
        *pixel++ = SDL_MapRGB(m_pSurface->format, m_red, m_green, m_blue);
      }

      // advance pixel pointer by pitch-8, to get the next "row".
      pixel += (m_pSurface->pitch - 8);
   }
}

我相信您可以通过预先计算构建时的 RGB 值来进一步加快速度。或者,如果您正在从纹理中读取像素,您可能会省去 SDL_MapRGB()(但它只是在 Surface 与 .png 具有不同像素格式的情况下存在)。

memcpy可能比对 RGB 值的 8 个单独分配要快 - 但我只想演示该技术。你可以做实验。

因此,EightByEight您创建的所有对象都指向同一个SDL_Surface.

然后,当你完成后,你只需将其转换SDL_Surface为 anSDL_Texture并 blit 即可。

于 2013-11-15T12:32:16.607 回答
1

感谢所有参与的人,但我们和朋友一起解决了这个问题。所以这里是一个例子(源代码太大,这里没必要,我只描述主要思想):

int pitch, *pixels;
SDL_Texture *texture;
...
if (!SDL_LockTexture(texture, 0, (void **)&pixels, &pitch))
{
    for (/*Conditions*/)
        memcpy(/*Params*/);
    SDL_UnlockTexture(texture);
}
SDL_RenderCopy(renderer, texture, 0, 0);
于 2013-11-27T23:57:36.493 回答
1

假设您已经将位图加载为 SDL_Texture(s),则通过SDL_SetRenderTarget将它们组合成不同的纹理。

SDL_SetRenderTarget(renderer, target_texture);
SDL_RenderCopy(renderer, texture1, ...);
SDL_RenderCopy(renderer, texture2, ...);
...
SDL_SetRenderTarget(renderer, NULL);

您在设置渲染目标和重置它(通过使用 NULL 纹理参数调用 SDL_SetRenderTarget)之间执行的每个渲染操作都将渲染到指定的纹理。然后,您可以像使用任何其他纹理一样使用此纹理。

于 2013-11-06T16:42:58.090 回答