powered by simpleCommunicator - 2.0.36     © 2025 Programmizd 02
Форумы / Delphi [игнор отключен] [закрыт для гостей] / DirectX. Отрисовка битмапов
7 сообщений из 7, страница 1 из 1
DirectX. Отрисовка битмапов
    #40117290
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Достался мне в наследство код, который должен рисовать битмапы в окне. Проблема в том, что он работает через пень-колоду. Может отрисовать все, может только угол битмапа, а может оставить пустое окно. В DirectX я ноль. Может, кто тыкнет носом в ошибку?
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
FD3DDevice: IDirect3DDevice9;
MapID3DSurface: IDirect3DSurface9;

procedure DoPaint;
var
  LDC: HDC;
  LDIB: TFastDIB;
  LInfo: Trs16bitPicture;
begin
  FD3DDevice.Clear(0, nil, D3DCLEAR_TARGET,
        D3DCOLOR_XRGB(255, 255, 255), 0.0, 0);
  MapID3DSurface.GetDC(LDC);
  try
    LDIB := GetDIBForeground;
    // В конкретном тесте LDIB.Bpp = 8
    if LDIB.Bpp = 8 then
      StretchDIBits(
        LDC,
        0, 0, VisRect.mrWidth, VisRect.mrHeight,  // VisRect совпадает с размерами LDIB
        0, 0, LDIB.Width, LDIB.Height,
        LDIB.Bits,
        PBitmapInfo(@LDIB.BitMapInfo)^, 0, SRCCOPY)
    else if LDIB.Bpp = 16 then begin
      LInfo.dsBmih := LDIB.BitMapInfo.bmiHeader;
      LInfo.dsBitfields[0] := $F800;
      LInfo.dsBitfields[1] := $07E0;
      LInfo.dsBitfields[2] := $001F;
      StretchDIBits(
        LDC,
        0, 0, VisRect.mrWidth, VisRect.mrHeight,
        0, 0, LDIB.Width, LDIB.Height,
        LDIB.Bits,
        PBitmapInfo(@LInfo)^, 0, SRCCOPY);
    end;
  finally
    MapID3DSurface.ReleaseDC(LDC);
  end;
  with FD3DDevice do
  begin
    BeginScene;
    SetRenderState(D3DRS_ALPHABLENDENABLE, DWORD(True));
    // включить рисование задних сторон треугольника
    SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
    DrawMapObject(Owner.VisRect.mrX, Owner.VisRect.mrY);
    SetRenderState(D3DRS_ALPHABLENDENABLE, DWORD(false));
    EndScene;
  end;
  FD3DDevice.Present(nil, nil, 0, nil);
end;


При этом если я сохраняю этот битмап в файл
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
LBmp := TBitmap.Create;
try
  LBmp.SetSize(LDIB.Width, LDIB.Height);
  StretchDIBits(
    LBmp.Canvas.Handle,
    0, 0, Owner.VisRect.mrWidth, Owner.VisRect.mrHeight,
    0, 0, LDIB.Width, LDIB.Height,
    LDIB.Bits,
    PBitmapInfo(@LDIB.BitMapInfo)^, 0, SRCCOPY
  );
  LBmp.SaveToFile('save.bmp');
finally
    LBmp.Free;
end;

По симптомам очень похоже на гонку потоков. Но вроде доступа из разных потоков быть не должно, а DoPaint точно вызывается только в главном потоке. Или DirectX не видит то, что область изменилась.

С уважением, Vasilisk
...
Рейтинг: 0 / 0
DirectX. Отрисовка битмапов
    #40117415
Sapersky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Надо смотреть, что делается в DrawMapObject, как получен MapID3DSurface.
В целом странный код. DirectX используется только для вывода битмапа с альфа-блендингом?
...
Рейтинг: 0 / 0
DirectX. Отрисовка битмапов
    #40117467
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sapersky
Надо смотреть, что делается в DrawMapObject
Идет отрисовка дополнительных объектов
Sapersky
как получен MapID3DSurface.
Код: pascal
1.
FD3DDevice.GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, MapID3DSurface);


Sapersky
DirectX используется только для вывода битмапа с альфа-блендингом?
Нет. Это только рисование подложки. А потом сверху рисуются объекты.

Я все больше слоняюсь к мысли, что
_Vasilisk_
DirectX не видит то, что область изменилась.
Потому что если окно свернуть, а потом развернуть - то все отрисовывается. Этой же процедурой. Только тогда она вызывается из WM_PAINT. А когда барахлит - я ее вызываю сам
...
Рейтинг: 0 / 0
DirectX. Отрисовка битмапов
    #40117508
Sapersky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Это довольно экзотическая смесь DirectX и GDI. Бэкбуфер очищается через DirectX, потом в него пихается картинка через GDI, потом опять рисование через DirectX. Мои соболезнования писателям видеодрайверов...
Если проблема точно не в параметрах VisRect.mrWidth, VisRect.mrHeight - попробуй убрать очистку (FD3DDevice.Clear). Она и не нужна по идее, если битмап занимает всё окно.
При неправильном рисовании - всё остальное кроме подложки рисуется?
...
Рейтинг: 0 / 0
DirectX. Отрисовка битмапов
    #40117524
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sapersky
попробуй убрать очистку (FD3DDevice.Clear).
Ничего не поменялось
Sapersky
При неправильном рисовании - всё остальное кроме подложки рисуется?
Нет. Ничего не рисуется.
Sapersky
Если проблема точно не в параметрах VisRect.mrWidth, VisRect.mrHeight
Добавил перед отрисовкой проверку
Код: pascal
1.
2.
Assert((LDIB.Height > 0) and (LDIB.Width > 0));
Assert((LDIB.Height = VisRect.mrHeight) and (LDIB.Width = VisRect.mrWidth));

Также все вызовы обернул в OleCheck, а вызов StretchDIBits в Win32Check - ничего не изменилось.

Причем те места, где ничего не рисуется отображается не белым фоном, а clBtnFace

Sapersky
Бэкбуфер очищается через DirectX, потом в него пихается картинка через GDI, потом опять рисование через DirectX
Как запихнуть картинку через DirectX?
...
Рейтинг: 0 / 0
DirectX. Отрисовка битмапов
    #40117609
Sapersky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
_Vasilisk_
Причем те места, где ничего не рисуется отображается не белым фоном, а clBtnFace
Тогда наверное проблема на этапе копирования бэкбуфера на экран (FD3DDevice.Present). DirectX привязывается к хэндлу окна, который задаётся на этапе инициализации, может там окна пересоздаются и он меняется? Или какой-то компонент лежит поверх.
Попробуй указать конкретный хэндл в 3-м параметре Present. Или можно попробовать InvalidateRect на окно.
...
Рейтинг: 0 / 0
DirectX. Отрисовка битмапов
    #40117671
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sapersky
Тогда наверное проблема на этапе копирования бэкбуфера на экран (FD3DDevice.Present).
Нашел проблему. Проблема была в обработке WM_PAINT.

Было
Код: pascal
1.
2.
3.
4.
5.
procedure WMPaint(var AMessage: TWMPaint);
begin
  DoPaint;
  inherited;
end;

стало
Код: pascal
1.
2.
3.
4.
5.
procedure WMPaint(var AMessage: TWMPaint);
begin
  inherited;
  DoPaint;
end;


clBtnFace навел на мысль
...
Рейтинг: 0 / 0
7 сообщений из 7, страница 1 из 1
Форумы / Delphi [игнор отключен] [закрыт для гостей] / DirectX. Отрисовка битмапов
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]