Конференция "Игры" » Как вывести результат рендера OpenGL на поверхность DirectX [Delphi, Windows]
 
  • Дмитрий Белькевич (13.11.10 18:46) [0]
    Возможно ли это?
  • CrytoGen (13.11.10 19:16) [1]
    Я думаю быстро только если через CUDA :) Медленно можно и без CUDA
  • Дмитрий Белькевич (13.11.10 23:57) [2]
    Как медленно?
  • Дмитрий Белькевич (14.11.10 00:14) [3]
    В смысле - как сделать медленно? Через временный dib, я так понимаю? То есть - придётся гонять картинки через обычную память? Некошерно, конечно.
  • CrytoGen (14.11.10 10:11) [4]
    Да. Можно рендерить в текстуру, затем читать эту текстуру и использовать её.
    Код для рендеринга в текстуру могу дать.
  • Дмитрий Белькевич (14.11.10 13:28) [5]

    > Код для рендеринга в текстуру могу дать.


    Было бы неплохо. Как я понимаю, текстура уже может в видеопамяти лежать.
  • CrytoGen (14.11.10 19:46) [6]
    Для себя я написал вот такой модуль, комментарии не люблю, но думаю вы разберётесь.
    unit FrameBufferUnit;

    interface

    uses
     Windows, SysUtils, Graphics, GL, GLu, GLext;

    type
     TFrameBuffer = class
     private
       width   : Integer;
       height  : Integer;
       frameb  : GLuint;
       depthb  : GLuint;
       texture : GLuint;
       ftex    : boolean;
     public
       constructor Create(const nWidth,nHeight:Integer;ctexture:Integer = 0 );
       destructor Destroy;override;
       procedure BindFrameBuffer;
       procedure UnbindFrameBuffer;
       function GetBitmap:TBitmap;
       procedure AttachTexture;
       procedure DettachTexture;    
     end;

    implementation

    { TFrameBuffer }

    type
     TRGBLine = array [0..1023] of TRGBTriple;
     PRGBLine = ^TRGBLine;

    procedure TFrameBuffer.AttachTexture;
    begin
    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,GL_COLOR_ATTACHMENT0_EXT,GL_TEXTURE _2D,texture,0);
    end;

    procedure TFrameBuffer.BindFrameBuffer;
    begin
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,frameb);
    end;

    constructor TFrameBuffer.Create(const nWidth, nHeight: Integer;ctexture:Integer);
    var
     res   : Integer;
     ww,hh : Integer;
    begin
    Width:=nWidth;
    Height:=nHeight;
    { ww:=1;
    while ww<Width do
     ww:=ww*2;
    hh:=1;
    while hh<Height do
     hh:=hh*2;}

    ww:=Width;
    hh:=Height;
    ftex:=ctexture<>0;
    if ftex then
     texture:=ctexture
    else
     glGenTextures(1,@texture);
    glBindTexture(GL_TEXTURE_2D,texture);
    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR_MIPMAP_LINEAR);
    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
    glTexParameterf(GL_TEXTURE_2D,GL_GENERATE_MIPMAP,0);
    glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,ww,hh,0,GL_RGBA,GL_UNSIGNED_BYTE,nil);
    glBindTexture(GL_Texture_2D,0);
    glGenFramebuffersEXT(1,@frameb);
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,frameb);
    glGenRenderbuffersEXT(1,@depthb);
    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT,depthb);
    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,GL_DEPTH_COMPONENT,width,height);
    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT,0);
    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,GL_COLOR_ATTACHMENT0_EXT,GL_TEXTURE _2D,texture,0);
    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,GL_DEPTH_ATTACHMENT_EXT,GL_RENDE RBUFFER_EXT,depthb);
    res:=glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
    if res<>GL_FRAMEBUFFER_COMPLETE_EXT then
     raise Exception.Create('frame buffer error');
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,0);
    end;

    destructor TFrameBuffer.Destroy;
    begin
    DettachTexture;
    glDeleteFramebuffersEXT(1,@frameb);
    glDeleteRenderbuffersEXT(1,@depthb);
    if not ftex then
     glDeleteTextures(1,@texture);
    inherited;
    end;

    procedure TFrameBuffer.DettachTexture;
    begin
    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,GL_COLOR_ATTACHMENT0_EXT,GL_TEXTURE _2D,0,0);
    end;

    function TFrameBuffer.GetBitmap: TBitmap;
    var
     buf : Pointer;
     l   : PRGBLine;
     b   : ^TRGBTriple;
     i,j : Integer;
     h,w : Integer;
    function PtrAllign(APointer:Pointer; bytes: cardinal):Pointer;
    begin
     Result := Ptr(cardinal(APointer) + (bytes-cardinal(APointer) mod bytes) mod bytes);
    end;
    begin
    w:=width;
    h:=height;
    result:=TBitmap.Create;
    result.PixelFormat:=pf24bit;
    result.Width:=w;
    result.Height:=h;
    GetMem(buf,w*h*3);
    glBindTexture(GL_TEXTURE_2D,texture);
    ZeroMemory(buf,w*h*3);
    glGetTexImage(GL_TEXTURE_2D,0,GL_RGB,GL_UNSIGNED_BYTE,buf);
    glBindTexture(GL_TEXTURE_2D,0);
    b:=buf;
    for i:=h-1 downto 0 do
    begin
      l:=result.ScanLine[i];
      for j:=0 to w-1 do
      begin
        l[j].rgbtBlue:=b.rgbtRed;
        l[j].rgbtGreen:=b.rgbtGreen;
        l[j].rgbtRed:=b.rgbtBlue;
        Inc(b);
      end;
      b:=PtrAllign(b,4);
    end;
    FreeMemory(buf);
    end;

    procedure TFrameBuffer.UnbindFrameBuffer;
    begin
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,0);
    end;

    end.

  • Дмитрий Белькевич (15.11.10 00:28) [7]
    Большое спасибо, будем разбираться.
  • Piroxyline © (21.01.11 16:13) [8]
    Вот кусок кода попроще, но на си:
    int y;
    int w = m_ScreenWidth;
    int h = m_ScreenHeight;
    unsigned char *pPixelData = (unsigned char *)mem_alloc(w*(h+1)*3, 1);
    unsigned char *pTempRow = pPixelData+w*h*3;
    GLint Alignment;
    glGetIntegerv(GL_PACK_ALIGNMENT, &Alignment);
    glPixelStorei(GL_PACK_ALIGNMENT, 1);
    glReadPixels(0,0, w, h, GL_RGB, GL_UNSIGNED_BYTE, pPixelData);
    glPixelStorei(GL_PACK_ALIGNMENT, Alignment);

    // flip the pixel because opengl works from bottom left corner
    for(y = 0; y < h/2; y++)
    {
     mem_copy(pTempRow, pPixelData+y*w*3, w*3);
     mem_copy(pPixelData+y*w*3, pPixelData+(h-y-1)*w*3, w*3);
     mem_copy(pPixelData+(h-y-1)*w*3, pTempRow,w*3);
    }


    Плюс вот здесь есть нечто похожее: http://pda.delphimaster.net/?id=1193408072&n=9
    Но как постоянно обновлять текстуру в DirectX - понятия не имею =(
  • CrytoGen (22.01.11 00:09) [9]
    извиняюсь хрень. если учесть, что opengl имеет проблемы с рендерингом на невидимых окнах.
  • Студент (09.02.11 01:34) [10]
    Я извиняюсь... А "рендерить в текстуру" и "рендерить в битмап" - это одно и то же?
    И что-то нет модулей GL/GLu/GLext в Делфи7...
  • CrytoGen (09.02.11 07:01) [11]
    Рендерить в текстуру и в битмап это разные вещи.
    Рендер в битмап обычно выполняется software, при это могут вылезать некоторые странные вещи :) типа неработоспособности шейдеров, ограничений на размеры текстур и др.

    GL,GLu, GLext в поставке Delphi нет. Лично я для этих целей использовал dot, но в настоящий момент домашняя страница dot не доступна.
  • Студент (10.02.11 16:03) [12]
    А рендер в текстуру всегда аппаратный? То есть в большинстве случаев быстрее и корректнее делать рендер в текстуру, а уже из неё как-то вытаскивать, чем рендерить в битмап?

    По поводу "странные вещи"... Пытался как-то что-то сотворить из примеров в теме "рендерить в битмап" (ссылка в посте [8]) - так там они у меня кажется были... Причём на разных компах разные... %)
  • CrytoGen (10.02.11 17:50) [13]
    Рендер в текстуру, как и обычный "рендер на экран" может быть не только аппаратным, но в большинстве случаев конечно же будет аппаратным. Вообще рендер в текстуру предназначен для других вещей, но и для вытаскивания из видеокарты подходит неплохо.
  • Студент (10.02.11 18:03) [14]
    Я знаю что для других вещей, немного читал про них где-то...)
    Просто мне нужно было нечто именно для "вытаскивания"...))

    Спасибо, будем пробовать...)
 
Конференция "Игры" » Как вывести результат рендера OpenGL на поверхность DirectX [Delphi, Windows]
Есть новые Нет новых   [134427   +37][b:0][p:0.003]