Гость
Форумы / Delphi [игнор отключен] [закрыт для гостей] / DirectX. Отрисовка битмапов / 7 сообщений из 7, страница 1 из 1
03.12.2021, 23:36
    #40117290
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DirectX. Отрисовка битмапов
Достался мне в наследство код, который должен рисовать битмапы в окне. Проблема в том, что он работает через пень-колоду. Может отрисовать все, может только угол битмапа, а может оставить пустое окно. В 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
05.12.2021, 03:27
    #40117415
Sapersky
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DirectX. Отрисовка битмапов
Надо смотреть, что делается в DrawMapObject, как получен MapID3DSurface.
В целом странный код. DirectX используется только для вывода битмапа с альфа-блендингом?
...
Рейтинг: 0 / 0
05.12.2021, 16:16
    #40117467
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DirectX. Отрисовка битмапов
Sapersky
Надо смотреть, что делается в DrawMapObject
Идет отрисовка дополнительных объектов
Sapersky
как получен MapID3DSurface.
Код: pascal
1.
FD3DDevice.GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, MapID3DSurface);


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

Я все больше слоняюсь к мысли, что
_Vasilisk_
DirectX не видит то, что область изменилась.
Потому что если окно свернуть, а потом развернуть - то все отрисовывается. Этой же процедурой. Только тогда она вызывается из WM_PAINT. А когда барахлит - я ее вызываю сам
...
Рейтинг: 0 / 0
05.12.2021, 18:59
    #40117508
Sapersky
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DirectX. Отрисовка битмапов
Это довольно экзотическая смесь DirectX и GDI. Бэкбуфер очищается через DirectX, потом в него пихается картинка через GDI, потом опять рисование через DirectX. Мои соболезнования писателям видеодрайверов...
Если проблема точно не в параметрах VisRect.mrWidth, VisRect.mrHeight - попробуй убрать очистку (FD3DDevice.Clear). Она и не нужна по идее, если битмап занимает всё окно.
При неправильном рисовании - всё остальное кроме подложки рисуется?
...
Рейтинг: 0 / 0
05.12.2021, 19:28
    #40117524
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DirectX. Отрисовка битмапов
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
06.12.2021, 00:12
    #40117609
Sapersky
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DirectX. Отрисовка битмапов
_Vasilisk_
Причем те места, где ничего не рисуется отображается не белым фоном, а clBtnFace
Тогда наверное проблема на этапе копирования бэкбуфера на экран (FD3DDevice.Present). DirectX привязывается к хэндлу окна, который задаётся на этапе инициализации, может там окна пересоздаются и он меняется? Или какой-то компонент лежит поверх.
Попробуй указать конкретный хэндл в 3-м параметре Present. Или можно попробовать InvalidateRect на окно.
...
Рейтинг: 0 / 0
06.12.2021, 10:44
    #40117671
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DirectX. Отрисовка битмапов
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
Форумы / Delphi [игнор отключен] [закрыт для гостей] / DirectX. Отрисовка битмапов / 7 сообщений из 7, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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