首页 文章

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

提问于
浏览
0

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

Image.

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

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

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

3 回答

  • 0

    假设您已经将您的位图加载为SDL_Texture,将它们组合成不同的纹理是通过SDL_SetRenderTarget完成的 .

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

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

  • 1

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

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

    然后当你完成后,将该表面转换为 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;
      };
    

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

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

    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 转换为 SDL_Texture 并将其搞定 .

  • 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);
    

相关问题