如何从许多纹理的一部分(C ++,SDL 2)创建一个位图?

How to create one bitmap from parts of many textures (C++, SDL 2)?

我有* .png文件,我想从纹理中获取不同的8x8 px零件并将其放置在位图上(我想,但也许不是),像这样:

Image.

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

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

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


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

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

然后,完成后,将该表面转换为SDL_Texture并进行渲染?

您将避免所有SDL_UpdateTexture()调用。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  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;
  };

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

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

BlitToSurface()看起来像这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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转换为SDL_Texture并将其blit。


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

1
2
3
4
5
SDL_SetRenderTarget(renderer, target_texture);
SDL_RenderCopy(renderer, texture1, ...);
SDL_RenderCopy(renderer, texture2, ...);
...
SDL_SetRenderTarget(renderer, NULL);

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


感谢所有参与的人,但我们与朋友们解决了这个问题。因此,这是一个示例(源代码太大且在这里不必要,我仅描述主要思想):

1
2
3
4
5
6
7
8
9
10
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);