![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Проблема с 32 битами на DirectX JEDI, IDirectDraw7 [D7, WinXP]
d10 © (2004-07-31 01:22:00)Я делаю вывод графики средствами DirectX JEDI. Использую IDirectDraw7. Делаю около 500 фаст блиттингов маленькой (64*32 пикселя) поверхности на заднюю, потом флит задней на переднюю. Если использую 32бита все жутко тормозит, FPS<1 на глаз, при 8 битах FPS>50 на глаз. Это так и должно быть или я чтото делаю не так? И как можно ускорить вывод 32 бит?
вот методы иницилизации и вывода графики:
constructor TGraph.Create;
var hRet:HRESULT;
ddsd:TDDSurfaceDesc2;//вспомогательная переменная для создания поверхностей
ddscaps:TDDSCaps2;//вспомогательная переменная для приаттачивания поверхностей
begin
inherited create;//конструктор родителя
screen.x:=1024;screen.y:=768;screen.bit:=8;
//обнуляем все
FDDSBack:=nil;FDDSGround:=nil;FDDSHero:=nil;FDDSPrimary:=nil; FDD:=nil;
//создание главного обьекта ДД
hRet := DirectDrawCreateEx (nil, FDD, IDirectDraw7, nil);
if hRet <> DD_OK then begin ErrorOut(hRet, 'DirectDrawCreateEx');Exit;end;
//задание уровня кооперации
hRet := FDD.SetCooperativeLevel(Form1.Handle, DDSCL_FULLSCREEN + DDSCL_EXCLUSIVE);
if hRet <> DD_OK then begin ErrorOut(hRet, 'SetCooperativeLevel');Exit;end;
//установка режима дисплея
hRet := FDD.SetDisplayMode (screen.x,screen.y,screen.bit, 0, 0);
if hRet <> DD_OK then begin ErrorOut(hRet, 'SetDisplayMode');Exit;end;
//создание главной поверхности
FillChar (ddsd, SizeOf(ddsd), 0);
ddsd.dwSize:=SizeOf(ddsd);
ddsd.dwFlags:=DDSD_CAPS or DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps:=DDSCAPS_PRIMARYSURFACE or DDSCAPS_FLIP or DDSCAPS_COMPLEX;
ddsd.dwBackBufferCount := 1;
hRet := FDD.CreateSurface(ddsd, FDDSPrimary, nil);
if hRet <> DD_OK then begin ErrorOut(hRet, 'Create Primary Surface');Exit;end;
//приаттачиваем заднюю поверхность
FillChar(ddscaps, SizeOf(ddscaps), 0);
ddscaps.dwCaps := DDSCAPS_BACKBUFFER;
hRet := FDDSPrimary.GetAttachedSurface(ddscaps, FDDSBack);
if hRet <> DD_OK then begin ErrorOut(hRet, 'GetAttachedSurface');Exit;end;
//создание поверхности для поверхности карты
FDDSGround := DDLoadBitmap(FDD, 'bmps/ground.bmp', 0, 0);
if FDDSGround = nil then begin ErrorOut(hRet, 'DDLoadBitmap1');Exit;end;
//создание поверхности для героя
FDDSHero := DDLoadBitmap(FDD, 'bmps/goblin.bmp', 0, 0);
if FDDSHero = nil then begin ErrorOut(hRet, 'DDLoadBitmap2');Exit;end;
// Задаем цветовой ключ для поверхности
hRet:=DDSetColorKey(FDDSGround,clWhite);if Failed (hRet)then ErrorOut(hRet,'DDSetColorKey');
// Задаем цветовой ключ для героя
hRet:=DDSetColorKey(FDDSHero,0);if Failed (hRet)then ErrorOut(hRet,'DDSetColorKey');
end;
Procedure TGraph.Draw;
const rad=25;
var hRet:HRESULT;
x,y:integer;//координаты текущей клетки
xs,ys:integer;//экранные координаты
Center:TPointI;//
ddbltfx:TDDBLTFX;
rect:TRect;
begin
if not activ then exit;
//закрашиваем задник белым цветом
FillChar (ddbltfx, SizeOf(ddbltfx),0);
ddbltfx.dwSize:=SizeOf (ddbltfx);
ddbltfx.dwFillColor:=clWhite; //Цвет заполнения - белый
hRet:=FDDSBack.Blt(nil, nil, nil, DDBLT_COLORFILL or DDBLT_WAIT, @ddbltfx);
SetRect(rect,0,0,64,32);
Center:=World.MyHero^.PosC;
//просматриваем карту в определенном радиусе
for x:=center.x-rad to center.x+rad do
for y:=center.y-rad to center.y+rad do
begin
Application.ProcessMessages;//обрабатываем сообщения
//проверка чтоб не выйти за пределы мапы
if (x<0)or(y<0)or(x>length(World.Map)-1)or(y>length(World.Map)-1) then continue;
//расчет экранных координат верхнего левого угла текущей клетки
xs:=trunc(screen.x/2)-32+32*((x-center.x)-(y-center.y));
ys:=trunc(screen.y/2)-16+16*((x-center.x)+(y-center.y));
//проверка входитли клетка в экран...
if (xs<-32)or(xs>screen.x-32)or(ys<-32)or(ys>screen.y-32) then continue;
//блитинг
hRet := FDDSBack.BltFast (xs,ys,FDDSGround,@rect, DDBLTFAST_WAIT or DDBLTFAST_SRCCOLORKEY);
if hRet = DDERR_SURFACELOST then begin if Failed (RestoreAll) then Exit;end;
end;
//флит на основную поверхность
hRet := FDDSPrimary.Flip(nil, DDFLIP_WAIT);
if hRet = DDERR_SURFACELOST then if Failed (RestoreAll) then Exit;
end;
вообще это код моей игрушки - РПГ.
Всем спасибо за помощь.
cyborg (2004-08-04 12:59:00) [1]значит так, начнём с того, что проверим стоят ли нормально дрова к видео, Детонатор стоит? Пуск-выполнить-dxdiag смотрим включены ли режимы ускорения, можешь понажимть кнопки теста, всё ли работает. Дальше смотри настройки видео в дровах. Если всё нормально, создавай минимальное приложение, которое очищает экран и делает флипинг, выводи ФПС, всё в цикле с максимальной скоростью при отключённой видеосинхронизацией, должно быть от нескольких сотен, до нескольких тысяч ФПС, если тут тормозит, то смотрим код инициализации, всё ли как положено? Если всё нормально и тормозит, то возвращаемся к дровам. Если летает идём дальше, выводи несколько сотен спрайтов рендомно, просто инициализируй ректангл и выводи один и тот же спрайт, если тут тормозит, то это значит либо не используется хардвар или всё сидит в оперативке, разбирайся почему так, либо просто спрайтов слишком много выводишь.
d10 (2004-08-04 12:18:00) [2]2cyborg
pohoje delo bilo ne v + DDSCAPS_VIDEOMEMORY. Raznici v skorosti ya ne zametil na glaz, navermo po defoltu v videomemory sozdayotsya poverhnost'. Kstati na 16 bit FPS<2 toje. Mojet oshibka v drugom?
d10 (2004-08-02 19:14:00) [3]спасибо, щас попробую
cyborg (2004-07-31 20:33:00) [4]допиши в функции, если уж её используешь, DDLoadBitmap в модуле ddutil где
... := DDSCAPS_OFFSCREENPLAIN;
замени на
... := DDSCAPS_OFFSCREENPLAIN or DDSCAPS_VIDEOMEMORY;
только учти, что когда видеопамяти не хватит, поверхность не создастся.
когда видеопамяти не хватает, возвращается ошибка DDERR_OUTOFVIDEOMEMORY, тогда пробуй грузить в оперативку, флаг DDSCAPS_SYSTEMMEMORY
d10 (2004-07-31 13:51:00) [5]Dmk, спасибо за совет конечно, но проблему это не решит. Сначала я вообще без этой строки делал, если программа висла то только ресетом выйти можно было, теперь просто альт+табом.
Да кстати, видео у меня Geforce4MX 440 128mb.
Dmk (2004-07-31 12:30:00) [6]>Application.ProcessMessages;//обрабатываем сообщения
Не делай это в Y цикле. Вынеси например, в X цикл, или
сделай счетчик и на каждые 20 - 50 спрайтов делай
ProcessMessages;
If (Counter mod 50) = 0 then ProcessMessages;