Конференция "Игры" » Загрузка текстуры в ручную. DirectX. [Delphi]
 
  • !!! (19.05.11 13:32) [20]
    Когда-то использовал следующую функцию загрузки bmpшек на поверхность directx7 ...
    у меня тоже не получалось правильно загрузить, но на этом форуме помогли.

    // ================================================================================ ====
    // структура для хранения спрайта
    typedef struct
    {
    int xsize;
    int ysize;

    LPDIRECTDRAWSURFACE7 Surf;
    }
    spriteTag;

    // ================================================================================ ====
    // Загружает спрайт из архива
    spriteTag* Pak_LoadSprite (packfile_t *pf, char *filename, int r, int g, int b)
    {
    char *buf_data;   // Буфер данных

      // Грузим данные в буффер, используя функцию из библиотеки
      /*
    unpak.c   Copyright (C) 1998-2000 Vitaly Ovtchinnikov
             and Damir Sagidullin         */

    int filesize = PackFileGet (pf, filename, &buf_data);

    if (!filesize || !(*buf_data))  // Если ничего не загрузилось
    {
     free (buf_data);
     return NULL;
    }


    // Копируем заголовок
    BITMAPFILEHEADER bmpHEAD;
    memcpy (&bmpHEAD, buf_data, sizeof(bmpHEAD));

    // Проверяем, действительно ли это БМП файл
    char *bmpType = (char*)
    &bmpHEAD.bfType;

    if (*bmpType != 'B' || *++bmpType != 'M')  // Если нет
    {
     free (buf_data);
     return NULL;
    }


    // Копируем второй - информацинный заголовок
    BITMAPINFOHEADER bmpINFO;
    memcpy (&bmpINFO, buf_data + sizeof(bmpHEAD), sizeof(bmpINFO));

    if (bmpINFO.biCompression != BI_RGB) // Не сжатое ли изображение
    {
     free (buf_data);
     return NULL;
    }


    // Устраивают ли нас пиксели
    if (bmpINFO.biBitCount != 24)
    {
     free (buf_data);
     return NULL;
    }


    // Выделяем место под спрайт
    spriteTag *newSprite = new spriteTag;

    // Если не удалось выделеть место
    if (!newSprite)
    {
     free (buf_data);
     return NULL;
    }


    // сохраним в спрайте размеры картинки
    newSprite->xsize = bmpINFO.biWidth;
    newSprite->ysize = bmpINFO.biHeight;

    // Создаем поверхность
    if (DirectDraw7_CreateSurface (&(newSprite->Surf), newSprite->xsize, newSprite->ysize))
    {
     free (buf_data);
     delete newSprite;
     return NULL;
    }


    // Установим прозрачный цвет для поверхности
    DirectDraw7_SetColorKey (newSprite->Surf, r, g, b);

    // Вычисляем размер изображения, если нужно
    int ImageSize = bmpINFO.biSizeImage;
    if (!ImageSize)
     ImageSize = ((bmpINFO.biWidth*(bmpINFO.biBitCount/8)+3 & ~3)*bmpINFO.biHeight);

    // Теперь займемся копированием точек на поверхность
    BYTE *bmpbuf = (BYTE*)
    (buf_data + sizeof(bmpHEAD) + bmpINFO.biSize);

    DDSURFACEDESC2 desc;
    ZeroMemory (&desc, sizeof (desc));
    desc.dwSize = sizeof (desc);

    // Залочим поверхность чтобы с ней можно было работать
    HRESULT res = newSprite->Surf->Lock( 0, &desc, DDLOCK_WAIT | DDLOCK_WRITEONLY, 0 );

    // Если не получилось, то на выход
    if (res != DD_OK)
    {
     free (buf_data);
     delete newSprite;
     return false;
    }


    int BytesRequired = bmpINFO.biWidth * 3;
    int BytesGiven = (BytesRequired + 3) & ~3;
    BYTE *surfBits = (BYTE*)desc.lpSurface;
    BYTE *imageBits = (BYTE*)(&bmpbuf[(bmpINFO.biHeight-1)*BytesGiven]);

    for (int i=0; i<bmpINFO.biHeight; i++)
    {
     WORD *pixptr = (WORD*)surfBits;
     RGBTRIPLE *triple = (RGBTRIPLE*)imageBits;

     for (int p=0; p<bmpINFO.biWidth; p++)
     {
      BYTE rf = triple->rgbtRed >> 3;
      BYTE gf = triple->rgbtGreen >> 2;
      BYTE bf = triple->rgbtBlue >> 3;

      *pixptr = (WORD)(bf | (gf << 5) | (rf << 11));
      triple++;
      pixptr++;
     }

     surfBits += desc.lPitch;
     imageBits -= BytesGiven;
    }

    // Разлочим поверхность
    newSprite->Surf->Unlock (NULL);

      // вернем готовый спрайт
    return newSprite;
    }

  • eXAAAXe (20.05.11 11:49) [21]

    > CrytoGen   (18.05.11 21:20) [18]


    Выравнял по 4 байта, для не кратных 2-ке, всё осталось также как на картинке.

    > Попробуйте так. И поищите ответ сами, что ли :)

    У меня плохо гуглится. :)

    >Sapersky   (19.05.11 00:43) [19]

    Спасибо.

    >!!!   (19.05.11 13:32) [20]

    Посмотрел код, вроде тоже самое: выравнивание, RGB-структура.
  • CrytoGen (20.05.11 12:37) [22]
    Для всех надо выравнивать.

         For Y:= H - 1 downto 0 do
         begin
           P:= Pointer(Integer(pScr)+((Y*3+3)*W div 4)*4);//выровняли по 4 байта
           For X:= 0 to W - 1 do
           with P^ do
           begin
             PDWORD(DWORD(LRect.pBits) + Y * LRect.Pitch + X * 4)^:= D3DCOLOR_XRGB(B, G, R);
             Inc(P);
           end;
         end;


    Ну так попробуйте. И вообще если у вас проблемы отладить такую вещь, то используйте более стандартные подходы. Если бы взяли TBitmap.Scanline, вообще такой проблемы не было бы.
  • CrytoGen (20.05.11 13:23) [23]
    Лучше конечно такие вещи с дельфёй проверять.
        For Y:= H - 1 downto 0 do
        begin
          P:= Pointer(Integer(pScr)+((Y*3+3) div 4)*4*W);//выровняли по 4 байта
          For X:= 0 to W - 1 do
          with P^ do
          begin
            PDWORD(DWORD(LRect.pBits) + Y * LRect.Pitch + X * 4)^:= D3DCOLOR_XRGB(B, G, R);
            Inc(P);
          end;
        end;

  • eXAAAXe (20.05.11 16:11) [24]

    > CrytoGen  


    > Sapersky  


    Большое спасибо, что терпели меня. =)
    Сделал как в ScanLine у TBitmap.
 
Конференция "Игры" » Загрузка текстуры в ручную. DirectX. [Delphi]
Есть новые Нет новых   [118574   +16][b:0][p:0.004]