-
Возможно ли это?
-
Я думаю быстро только если через CUDA :) Медленно можно и без CUDA
-
Как медленно?
-
В смысле - как сделать медленно? Через временный dib, я так понимаю? То есть - придётся гонять картинки через обычную память? Некошерно, конечно.
-
Да. Можно рендерить в текстуру, затем читать эту текстуру и использовать её. Код для рендеринга в текстуру могу дать.
-
> Код для рендеринга в текстуру могу дать.
Было бы неплохо. Как я понимаю, текстура уже может в видеопамяти лежать.
-
Для себя я написал вот такой модуль, комментарии не люблю, но думаю вы разберётесь. 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
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:=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.
-
Большое спасибо, будем разбираться.
-
Вот кусок кода попроще, но на си: 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);
for(y = 0; y < h/2; y++)
Плюс вот здесь есть нечто похожее: http://pda.delphimaster.net/?id=1193408072&n=9Но как постоянно обновлять текстуру в DirectX - понятия не имею =(
-
извиняюсь хрень. если учесть, что opengl имеет проблемы с рендерингом на невидимых окнах.
-
Я извиняюсь... А "рендерить в текстуру" и "рендерить в битмап" - это одно и то же? И что-то нет модулей GL/GLu/GLext в Делфи7...
-
Рендерить в текстуру и в битмап это разные вещи. Рендер в битмап обычно выполняется software, при это могут вылезать некоторые странные вещи :) типа неработоспособности шейдеров, ограничений на размеры текстур и др.
GL,GLu, GLext в поставке Delphi нет. Лично я для этих целей использовал dot, но в настоящий момент домашняя страница dot не доступна.
-
А рендер в текстуру всегда аппаратный? То есть в большинстве случаев быстрее и корректнее делать рендер в текстуру, а уже из неё как-то вытаскивать, чем рендерить в битмап?
По поводу "странные вещи"... Пытался как-то что-то сотворить из примеров в теме "рендерить в битмап" (ссылка в посте [8]) - так там они у меня кажется были... Причём на разных компах разные... %)
-
Рендер в текстуру, как и обычный "рендер на экран" может быть не только аппаратным, но в большинстве случаев конечно же будет аппаратным. Вообще рендер в текстуру предназначен для других вещей, но и для вытаскивания из видеокарты подходит неплохо.
-
Я знаю что для других вещей, немного читал про них где-то...) Просто мне нужно было нечто именно для "вытаскивания"...))
Спасибо, будем пробовать...)
|