ПрограммированиеФорумГрафика

Из текстуры в Bitmap и обратно, DirectX 9 (2 стр)

Страницы: 1 2 3 Следующая »
#15
13:42, 18 апр 2016

Mira
> GetRenderTargetData кароч. Смотри msdn :)
Он с сурфейсами работает.
Наткнулся на интересную функцию

 D3DXSaveTextureToFileInMemory

Она должна сохранять текстуру в памяти в формате файла.
Создаю

Buffer: ID3DXBUFFER;

Выделяю память с запасом.

D3DXCreateBuffer(32*800*600*4,buffer);
D3DXSaveTextureToFileInMemory(buffer, D3DXIFF_BMP, RenderTexture,0);

Работает... Но как мне БМП из ID3DXBUFFER достать??

#16
13:47, 18 апр 2016

Ramm
Getrendertargetdata для твоего случая пойдёт. Из текстуры сурфейс кстати можно взять.

А если ниженаписаная функция возвращает норм буфер то залочь его и считай память.
Поидее там должно быть уже с bitmap хеадерами а не просто набор пикселей.
У буфера там полтора метода , не запутаешся. Залочить и получить содержимое , узнать размер содержимого, разлочить

#17
13:50, 18 апр 2016

Буфер поидне не надо создавать там разве не out параметр?
Ну и ты там в 32 раза больше памяти чем надо выделил:)

#18
14:11, 18 апр 2016

Mira
> возвращает норм буфер то залочь его и считай память.
Залочить буфер? Как? У него 5 методов.
Mira
> Поидее там должно быть уже с bitmap хеадерами а не просто набор пикселей.
Вооооот.
И как достать то из него?

#19
14:33, 18 апр 2016

Даже лочить не надо.
Getbufferpointer() указатель на начало памяти .
Getbuffersize размер буфера

Че в 3 соснах не можешь)

#20
14:51, 18 апр 2016

Mira
> Че в 3 соснах не можешь)
Mira
> Getbufferpointer() указатель на начало памяти .
Указатель) А для создания hbitmap нужен хендл...
Хз, у меня голова уже квадратная.

#21
15:03, 18 апр 2016

Ramm
Hbitmap это и есть хэндл. Ты че хочешь в итоге то получить ?

#22
15:39, 18 апр 2016

Ramm
Я так понял, ты всё мучаешься с выбором объекта мышкой на экране, вот я написал пример на VB6, это достаточно близко к Дельфи, тоже объекты передаются ссылками, методы пишутся через точку:
https://yadi.sk/d/HUm9GgxEr6BMA
Посмотри как работает EXE, открой файл RenderTarget2.frm блокнотом, там весь нужный тебе код.

#23
16:26, 18 апр 2016

Mira
> Hbitmap это и есть хэндл. Ты че хочешь в итоге то получить ?
Хочу HBiTMAP) А имею указатель на буфер, в котором лежит *.bmp в хз каком виде.
Mikle
> вот я написал пример на VB6, это достаточно близко к Дельфи
С++ ближе)

RenderTexture: IDirect3DTexture9;
    RenderSurface: IDirect3DSurface9;
    BackBuffer: IDirect3DSurface9;

Я справился с рендером в текстуру, т.е. перед рендером однократно делаю так:

  D3DXCreateTexture(DeviceDX, ScreenX, ScreenY, 0, D3DUSAGE_RENDERTARGET,
  D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, RenderTexture);
  RenderTexture.GetSurfaceLevel(0, RenderSurface);
  Devicedx.GetRenderTarget(0, BackBuffer);

Если надо рендерить в текстуру, то делаю так:

DeviceDX.SetRenderTarget(0, RenderSurface);

И чтобы увидеть результат:

D3DXSaveTextureToFile('scene.png', D3DXIFF_PNG, RenderTexture, nil);

Пнг выводится. Все норм. Я эту текстуру конвертировать не могу, и заблочить ее у меня почему-то не выходит.

#24
16:34, 18 апр 2016

Ramm
> заблочить ее у меня почему-то не выходит.
Так я дал пример, где используется GetRenderTargetData, дальше без проблем лочится и копируется в массив в памяти, не нужно никаких файлов, даже в памяти, это всё равно медленно, не нужно даже битмапов, просто - из сюрфейса в массив.

#25
18:35, 18 апр 2016

Ramm
> И чтобы увидеть результат:
> D3DXSaveTextureToFile('scene.png', D3DXIFF_PNG, RenderTexture, nil);
это все очень медленно

Ramm
> D3DXSaveTextureToFileInMemory
значит это тебе не надо, возвращаемя снова к GetRenderTargetData

допустим ты разобрался с этой функций (если нет смотри пример Микла) и получил Pointer с пикселями из своей текстуры
дальше юзаешь CreateDIBSection , передаешь туда массив и корректно заполняешь заголовок.

PROFIT - юзаеш полученный хендл как HBITMAP

#26
8:27, 19 апр 2016

Mira
> возвращаемя снова к GetRenderTargetData
Хорошо
Приведу код инициализации, убрал все лишнее, убрал деструктор, лишние методы, оставил только суть:

unit INITDX;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs,  Math,  Direct3D9,  D3DX9,  CAMERADX;

type
  INITDX9 = class
    constructor Create(f:TForm; R, G, B: cardinal); //рабочая форма и цвет заливки заднего буфера
  private
    { Private declarations }
    Form: TForm;        //форма, на которой используем dx

    //цвет очистки
    ColorClearR,ColorClearG,ColorClearB:Cardinal;

    RenderTexture: IDirect3DTexture9;
    RenderSurface: IDirect3DSurface9;
    BackBuffer:    IDirect3DSurface9;
    TSurf:         IDirect3DSurface9;
    DrawOnTextureFLAG:boolean;

    procedure SaveTextureToBITMAP;
  public
    MainDirect:IDirect3D9;//главный объект с интерфейсом IDirect3D9
    DeviceDX:IDirect3DDevice9;//объект устройства IDirect3DDevice9

    Camera:TCAMERA;

    ScreenX,ScreenY:integer;//разрешение экрана
    procedure Draw;  //вывод заднего буфера
    procedure DrawOnTexture(FLAG:BOOLEAN);//осуществлять ли вывод в текстуру
    procedure Clear; //очистка (заливка) заднего буфера, очистка z-буфера
  end;



implementation



procedure INITDX9.Clear;
begin
  //очистка, как буфера кадра, так и буфера глубины
  DeviceDX.Clear(0, NIL, D3DCLEAR_TARGET or D3DCLEAR_ZBUFFER, //or D3DCLEAR_STENCIL,
  D3DCOLOR_XRGB(ColorClearR, ColorClearG, ColorClearB), 1, 0);
end;

constructor INITDX9.Create(f: TForm; R, G, B: cardinal);
var
  DisplayInfo:TD3DDisplayMode;
  Parameters:TD3DPresentParameters;
  d3dViewport1: TD3DViewport9;
begin
  Form:=f;
  ScreenX:=form.ClientWidth;
  ScreenY:=form.ClientHeight;

  DrawOnTextureFLAG:=false;

  //создаем обект с интерфейсом IDirect3D9
  MainDirect:=Direct3DCreate9(D3D_SDK_VERSION);
  //получаем установки текущего режима адаптера
  MainDirect.GetAdapterDisplayMode(D3DADAPTER_DEFAULT,DisplayInfo);
  //задаем пареметры усройства
  ZeroMemory(@Parameters,SizeOf(Parameters));
  //использовать оконный режим да\нет
  Parameters.Windowed:=true;
  //режим переключения между буферами
  Parameters.SwapEffect:=D3DSWAPEFFECT_DISCARD;
  //формат буфера не определен
  Parameters.BackBufferFormat:=DisplayInfo.Format;
  
  Parameters.EnableAutoDepthStencil := TRUE;
  //   формат буфера глубины
  Parameters.AutoDepthStencilFormat := D3DFMT_D16;
  //создаем объект устройства
  MainDirect.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, Form.Handle,
    D3DCREATE_SOFTWARE_VERTEXPROCESSING, @Parameters, DeviceDX);


  // Включаем поддержку Z-буфера устройством
  DeviceDX.SetRenderState(D3DRS_ZENABLE, 1);   //D3DZB_TRUE
  // Отключаем освещение сцены
  DeviceDX.SetRenderState(D3DRS_LIGHTING, 0);

    //получаем параметры окна вывода
  //DeviceDX.GetViewport(d3dViewport1);

  ColorClearR:=R;
  ColorClearG:=G;
  ColorClearB:=B;
///////////////////////////////////////////////////////////////////////////////////////////////
  D3DXCreateTexture(DeviceDX, ScreenX, ScreenY, 0, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, RenderTexture);
  RenderTexture.GetSurfaceLevel(0,RenderSurface);
  DeviceDX.CreateOffscreenPlainSurface(800, 600, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, TSurf, nil);

  Devicedx.GetRenderTarget(0, BackBuffer);
///////////////////////////////////////////////////////////////////////////////////////////////
  Clear; //очистка устройства

  Camera:=TCAMERA.Create(DeviceDX,Form);
end;

procedure INITDX9.Draw;//непосредственный вывод, либо в файл, либо задний буфер становится видимым
begin
  if DrawOnTextureFLAG then
  begin
    D3DXSaveTextureToFile('scene.png', D3DXIFF_PNG, RenderTexture, nil);
    SaveTextureToBITMAP;
  end
  else
  begin
    DeviceDX.Present(NIL,NIL,0,NIL);
  end;
end;

procedure INITDX9.DrawOnTexture(FLAG: BOOLEAN);
begin
  DrawOnTextureFLAG:=FLAG;      //если да, то рендерить будем в текстуру
  if FLAG then
  begin
    DeviceDX.SetRenderTarget(0, RenderSurface);//рендерить будем в сурфейс
  end
  else
  begin
    DeviceDX.SetRenderTarget(0, BackBuffer);//рендерить будем в задний буфер
  end;
end;

procedure INITDX9.SaveTextureToBITMAP;
var
bmp: hbitmap;
desc: D3DSURFACE_DESC;
lr: D3DLOCKED_RECT;
BmpVCL: TBitmap;
begin
  DeviceDX.GetRenderTargetData(RenderSurface,TSurf);

  TSurf.GetDesc(desc);
  TSurf.LockRect(lr,0,0);
  form.Caption:=inttostr(lr.Pitch);

  //BmpVCL := TBitmap.Create();
  //BmpVCL.Handle := bmp;
  //BmpVCL.SaveToFile('aaa666.bmp');
end;

end.

Pitch теперь равен 3200, а при повторной отрисовке - более 1.5 млн.
Где-то TSurf надо чистить... Если сделать его локальным (определить в SaveTextureToBITMAP), то Pitch всегда 3200.
Я правильно понимаю, что нужно вообще отказаться от текстур, обойтись одними поверхностями (IDirect3DSurface9)?
Mikle

If tSurf.GetData(VarPtr(R), 800& * 600 * 4, VarPtr(Ar(0, 0))) Then//Что это такое?
      Caption = Ar(Mx Mod 800, My Mod 600) And &HFFFFFF
    End If

У IDirect3DSurface9 у меня нет такого метода, есть GetPrivateData(TGUID, Pointer, Integer)

#27
8:40, 19 апр 2016

Ramm
Все верно.
Размер скрина 800 * sizeof(integer) размер пикселя = 3200
Теперь халява, сделать картинку из массива пикселей.
Юзаешь createcompatibledc или сторонний компонент умеющий быстрый доступ к пикселям.
Лично я юзал FastDIB

#28
8:59, 19 апр 2016

Ramm
> У IDirect3DSurface9 у меня нет такого метода
Да, забыл сразу написать, GetData() - это макрос, состоит из LockRect(), memcpy() и UnlockRect(), возвращает True, если LockRect() вернул D3D_OK. Всё остальное - стандартные D3D9 методы.

#29
10:00, 19 апр 2016

Mira
Mikle
аааааааааааааааАААААААААААААЗАРАБОТАЛО!!!!!!!!!!111111111111111111111111
Спасибо огромное!

procedure INITDX9.SaveTextureToBITMAP;
var
bmp: hbitmap;
desc: D3DSURFACE_DESC;
lr: D3DLOCKED_RECT;
BmpVCL: TBitmap;
TSurf: IDirect3DSurface9;
begin
  DeviceDX.CreateOffscreenPlainSurface(800, 600, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, TSurf, nil);
  DeviceDX.GetRenderTargetData(RenderSurface,TSurf);
  TSurf.GetDesc(desc);
  TSurf.LockRect(lr,0,0);
  form.Caption:=inttostr(lr.Pitch);

  bmp := CreateCompatibleBitmap(GetDC(0), desc.Width, desc.Height);
  SetBitmapBits(bmp,lr.Pitch*desc.Height,lr.pBits);
  TSurf.UnlockRect;

  BmpVCL:= TBitmap.Create();
  BmpVCL.Handle:=bmp;
  BmpVCL.SaveToFile('aaa666.bmp');
end;

Главное - это вот это:

  DeviceDX.CreateOffscreenPlainSurface(800, 600, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, TSurf, nil);
  DeviceDX.GetRenderTargetData(RenderSurface,TSurf);

Единственное... Я правильно понял, что вообще без текстуры нельзя обойтись?

  D3DXCreateTexture(DeviceDX, ScreenX, ScreenY, 0, D3DUSAGE_RENDERTARGET,
  D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, RenderTexture);
  RenderTexture.GetSurfaceLevel(0,RenderSurface);

  Devicedx.GetRenderTarget(0, BackBuffer);

Т.е. без вот этого никак?

Страницы: 1 2 3 Следующая »
ПрограммированиеФорумГрафика

Тема в архиве.