Конференция "Игры" » Загрузка текстуры в ручную. DirectX. [Delphi]
 
  • eXAAAXe (16.05.11 10:45) [0]
    Привет.
    Написал загрузку бмп. (Только 24 и 32 битных)
    1) Но как залить им текстуру не понимаю.
    2) Почему Device.FDevice.CreateTexture возвращает ИнвалидКал.

    function LoadTexture(const FileName: string; var W, H: LongWord; var Data: Pointer; var Format: TD3DFormat): boolean;
    var
     Bpp: LongWord;
    begin
     Result:= LoadBmp(FileName, W, H, Bpp, Data);

     If Result then
     Case Bpp of
       24: Format:= D3DFMT_R8G8B8;
       32: Format:= D3DFMT_X8B8G8R8;
     end;
    end;

    function TTexture.Load(const FileName: string): boolean;
    var
     W, H  : LongWord;
     Format: TD3DFormat;
     pScr  : Pointer;
     LRect : TD3DLockedRect;
    begin
     Result:= False;

     If LoadTexture(FileName, W, H, pScr, Format) then
     begin
       If Check(Device.FDevice.CreateTexture(W, H, 0, 0, Format, D3DPOOL_MANAGED, FHandle, nil)) then
       begin
         If Check(FHandle.LockRect(0, LRect, nil, D3DLOCK_DISCARD)) then
         try
           // ?

         finally
           Result:= UnLock;
         end;
       end;

     end;
    end;

  • CrytoGen (16.05.11 10:46) [1]
    (Width,Height,1,0,D3DFMT_A8R8G8B8,D3DPOOL_MANAGED,d3dt,nil))
  • eXAAAXe (16.05.11 18:06) [2]
    Спасибо. Инвалид калл исчез.
    Картинка (бмп24) загрузилась, но изображение серое и раздробленное.
    Ещё формат D3DFMT_R8G8B8 для бмп24 должен был подойти, но нет.
    Почему?


    If Check(FHandle.LockRect(0, LRect, nil, D3DLOCK_DISCARD)) then
    try
     Move(pScr^, LRect.pBits^, W * H * 3);
    finally
     Result:= UnLock;
    end;

  • CrytoGen (16.05.11 19:11) [3]
    Учтите LRect.pitch и чО в bmp выравнивание есть, точно не помню какое.
  • eXAAAXe (16.05.11 22:01) [4]
    Да, точно.
    Решил для начала залить текстуру нужным цветом.
    На выходе получаю один мусор в текстуре.


    For y:= 0 to H - 1 do
      For x:= 0 to W - 1 do
      begin
         PDWORD(DWORD(LRect.pBits) + (Y * DWORD(LRect.Pitch)) + (X * 4))^:= D3DCOLOR_XRGB(255, 0, 0);
         Inc(PDWORD(LRect.pBits)^);
      end;

  • CrytoGen (16.05.11 22:10) [5]
    бред же написали :)
  • CrytoGen (16.05.11 22:10) [6]
    чтобы незапутаться попробуйте тупо FillChar
  • CrytoGen (16.05.11 22:23) [7]
    D3DFMT_R8G8B8 - Трёх байтовая структура, смещение по строкам у вас дважды получается и оба раза не верно.
  • eXAAAXe (17.05.11 09:29) [8]
    Сделал вот так, работает:


    function TTexture.Load(const FileName: string; Custom: boolean = False): boolean;
    var
     X, Y  : LongWord;
     W, H  : LongWord;
     P     : PRGB;
     pScr  : Pointer;
     LRect : TD3DLockedRect;
     Format: TD3DFormat;
    begin
     If Custom then
     begin
       Result:= False;

       // Инфо: Bmp. (BGR, FlipH)
       If LoadTexture(FileName, W, H, pScr, Format) then
       try
         If not DXCheck(Device.FDevice.CreateTexture(W, H, 0, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, FHandle, nil)) then Exit;

         If DXCheck(FHandle.LockRect(0, LRect, nil, 0)) then
         try
           P:= pScr;
           For Y:= H - 1 downto 0 do
             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;
         finally
           Result:= DXCheck(FHandle.UnlockRect(0));
         end;
       finally
         FreeMem(pScr);
       end;
     end else
       Result:= DXCheck(D3DXCreateTextureFromFile(Device.GetHandle, XPChar(FileName), FHandle));
    end;



    Но есть вопросы:

    1) Текстуры обязательно должны быть кратны 2-ке?
    2) Работает только при D3DPOOL_MANAGED.
    3) Перенос пикселей в 2-х циклах да и ещё с D3DCOLOR_XRGB - жирёт время.
       Как-то не оптимально получилось.

    Заранее благодарен. :)
  • CrytoGen (17.05.11 10:26) [9]
    1) вроде не обязательно
    2) почитайте, сейчас на вскидку не подскажу
    3) а вы часто текстуры загружаете? если нет, то какая разница - надёжность важнее


            with P^ do
            begin
              PDWORD(DWORD(LRect.pBits) + Y * LRect.Pitch + X * 4)^:= D3DCOLOR_XRGB(B, G, R);
              Inc(P);
            end;


    чО за P?

    посмотрите типы RGBQuad и RGBTriple. чтобы не заморачиваться с альфой воспользуйтесь трёх байтной структурой.
  • Sapersky (17.05.11 11:41) [10]
    1) Современные карты поддерживают некратные, но с ограничениями (мип-мэппинг с ними не работает и ещё что-то). Для 2D можно использовать, для 3D лучше не.
    2) Да, так и было задумано MS'ом. К POOL_DEFAULT доступа через Lock нет.
    3) Ничего там особенно не "жирёт". Инициализация DX больше времени займёт, чем загрузка текстур. Но если так уж хочется максимально "вылизать", убирай вызов функции, вычисление DWORD(LRect.pBits) + Y * LRect.Pitch на каждом шаге по X (оно же одинаковое остаётся).
  • eXAAAXe (17.05.11 14:40) [11]
    > CrytoGen   (17.05.11 10:26) [9]

    > чО за P?



    type
     PRGB = ^TRGB;
     TRGB = record
       R, G, B: byte;
     end;



    > Sapersky   (17.05.11 11:41) [10]
    > 1) Современные карты поддерживают некратные, но с ограничениями
    > (мип-мэппинг с ними не работает и ещё что-то). Для 2D можно использовать, для 3D лучше не.

    Проверил капсы.
    Оказывается моя видеокарта не поддерживает такие текстуры.

    Всем спасибо. :)
  • eXAAAXe (18.05.11 14:31) [12]
    Проверил на другом аппарате.
    Текстуры не кратные 2-ке - поддерживаются.
    Решил загрузить текстуру 50x50 бмп, 24 бит.
    Картинка получилась такая:
    http://imglink.ru/show-image.php?id=b844ba551e10c15c664aab989915ec68

    В чём дело?
  • CrytoGen (18.05.11 14:50) [13]
    у bmp выравнивание по 4 байта в строках
  • eXAAAXe (18.05.11 17:11) [14]

    > CrytoGen   (18.05.11 14:50) [13]


    А как тогда сделать?
    Поменял так, но получается мусор:


    type
    PRGBA = ^TRGBA;
    TRGBA = record
      R, G, B, A: byte;
    end;




    Или Вы о чем?
  • CrytoGen (18.05.11 19:10) [15]
         
          For Y:= H - 1 downto 0 do
          begin
            P:= Pointer(Integer(pScr)+((Y*W*3+3) 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;


    у вас получаются данные из битмапа без разрыва, а они на каждой новой строке должны быть выровнены по 4-м байтам.
  • CrytoGen (18.05.11 19:11) [16]
    Правда с Pointer'ами и Interger'ами так лучше не делать, а переписать с промежуточным PByte
  • eXAAAXe (18.05.11 20:24) [17]
    Для кратных 2-ке нормально, а для остальных нет.
  • CrytoGen (18.05.11 21:20) [18]

         For Y:= H - 1 downto 0 do
         begin
           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;
           P:= Pointer(((Integer(P)+3) div 4)*4);//выровняли по 4 байта
         end;


    Попробуйте так. И поищите ответ сами, что ли :)
  • Sapersky (19.05.11 00:43) [19]
    Проще говоря, у битмапов как и у текстур есть Pitch, который не обязательно равен Width * BytesPerPixel. Посчитать его можно функцией BytesPerScanline из Graphics.pas.
 
Конференция "Игры" » Загрузка текстуры в ручную. DirectX. [Delphi]
Есть новые Нет новых   [118622   +8][b:0][p:0.003]