Форум: "Игры";
Текущий архив: 2004.07.25;
Скачать: [xml.tar.bz2];
ВнизВращение спрайта ... Найти похожие ветки
← →
Sp@wN © (2003-09-14 15:21) [0]Есть ли в DirectDraw процедура для аппаратного вращения изображения на IDirectDrawSurface? А то я полазил и в самой бибилиотеке и по форумам различным, не нашёл :( Неужели все так плохо и надо софтверно это все делать?
← →
cyborg © (2003-09-14 16:55) [1]Есть, смотря что твоя карточка поддерживает. На моей видеокарточке только на 90 градусов крутится и зеркальное отображение есть.
← →
Sp@wN © (2003-09-14 17:19) [2]Видеокарта у меня ГыФорс2МХ. А начиная с какой поддерживается вращение? А то напишешь с такой аппаратной поддержкой, а работать будет только на Радеон 9800 про :)) И как называется процедурка?
← →
cyborg © (2003-09-14 19:58) [3]Процедурка называется Blt.
В модуле DirectDraw найди DIRECTDRAWSURFACE BLT FX FLAGS, там флаги вывода.
← →
Sp@wN © (2003-09-14 21:20) [4]Ну что могу сказать ... вот что выдает blt с флагом DDBLT_ROTATIONANGLE:
Operation could not be carried out because there is no rotation hardware present or available.
И как же быть, все таки софтверно делать? Но это же нереально по скорости, например, 30 спрайтов на экране и каждый надо повернуть ... ууужас! Лююююди, которые уже давно написали свою первую игру, вы как делали??
← →
cyborg © (2003-09-14 21:46) [5]Повороты делаются в начале загрузки программы, во время работы выводятся уже повёрнутые спрайты.
← →
NailMan © (2003-09-15 09:49) [6]Было не раз сказано что для полноценны 2Д игр/приложений следует юзать не DirectDraw, а Direct3D с его аппаратными возможностями поворота всего чего угодно, альфа блендинга и т.д. и т.п.
Если все таки ты хочешь писать именно на DDRaw, то придется писать софтварные функции поворота изображений.
Смирись. DDraw - умер уже давно.
← →
Sp@wN © (2003-09-15 10:44) [7]Если заранее все вертеть, то будет долго программа загружатся, но это ладно, главное, что надо очень много памяти, чтобы хранить каждый спрайт повернутый. Скажем на каждые 90 градусов надо 10 фрэймов с разворотом (для плавности), тогда в 40 раз надо больше памяти на каждый спрайт ...
Ех ... спасибо что ламеру отвечали, посмотрю Direct3D. Хотя непонимаю такой фишки: если вращение не поддерживается в ДиректДроу моей видеокартой, с какой стати оно будет поддерживатся в Direct3D?
← →
MeF88 © (2003-09-15 10:52) [8]Дык ты себе представляешь 3д мир, где поворачиваться можно тока на 90 градусов. А вообще DirectDraw тока переносит пиксели от-туда сюда, а Direct3D поворачивает не само изображение, а лишь поворачивает полигон с ним. Так что получается, что D3D - продвинутый вариант DirectDraw.
← →
Sp@wN © (2003-09-15 11:16) [9]Тогда вопрос вдогонку ;)
А они совместимы DirectDraw и Direct3D? Если у меня спрайт на поверхности DDraw, то я смогу его развернуть средствами D3D? И, если да, хорошо ли будет, что у меня в программе присутствуют объекты и DD и D3D?
А то не хотелось бы мне переписывать все под D3D, хотя я и не далеко ушел, но все же.
← →
pasha_676 © (2003-09-15 12:02) [10]
> А они совместимы DirectDraw и Direct3D
ЭЭЭЭЭ.... Как то вопрос некоректно поставлен.
Решение проблеммы под 2D - самое поверхостное, уже предложили. При загружке программы расчитываешь повернутые спрайты (их поворачиваешь по матрице поворота) и помещаешь в буферные ресурсы.
Или же в любом соответствующем граф редакторе поворачиваещь сразу и помещаещь в доступные ресурсы в игре (как угодно хоть в bmp файло). Потом их выводишь в нужном порядке. Т.к. тебе в игре врядли потребуется больше 16 вариантов поворота (а то и 8), то способ вполне имеет право на жизнь (например применяется в Диабло1 и 2).
← →
NailMan © (2003-09-15 13:55) [11]Смирись и с тем что тебе все равно придется переписывать ядро и возможно не раз. Всегда будет новая идея, реализация которой потребует переписывания всего заново. Поэтому не мучайся и переписывай под Д3Д - будет проще.
Что касаемо совмесимости - х.з. вроде как да, но раз уж переписывать, то переписывать основательно и избавляться от DDraw-овских корней.
← →
Sapersky © (2003-09-15 17:36) [12]Что касаемо совмесимости - х.з. вроде как да, но раз уж переписывать, то переписывать основательно и избавляться от DDraw-овских корней.
Вырвем с корнем этот злостный сорняк! :)
Круто, в общем. Но мне вот что-то от крутизны этой не радостно, потому как пишу это с Trident3D 4 mb (это самое "3D" работает с такой же скоростью, что и программная эмуляция, проверял :))
В общем, своё мнение я не раз уже излагал - DirectDraw + Direct3D7. Совместимость - самая что ни на есть. Минимальный кусок кода для добавления поддержки D3D в DDraw - 60 строк (получается аналог D3DXSprite из DX8). Хотя для того, чтобы работало более-менее быстро, нужно написать побольше, но в целом ничего нерешаемого.
Конечно, задействовать все возможности GeForceFX будет нельзя. Но оно вам надо в данном случае?
← →
NailMan © (2003-09-15 18:26) [13]Sapersky ©
Да тяжело бойцам невидимого фронта :-)
С трайдентом то.
Вобщем если уж писать что-то хорошее на 2Д, то ориентиром выбирать карты не ниже TNT-TNT2, а лучше GF2 и от этого плясать.
В общем случае для вижуал эффектов в 2Д можно и шейдеры прикрутить - типа супер-пупер 2Д получится.
← →
Sapersky © (2003-09-16 10:24) [14]Да тяжело бойцам невидимого фронта :-)
Вообще-то, я малость недоговорил для пущего драматического эффекта :) Писал с работы, а дома у меня GeForce2MX :)
Вобщем если уж писать что-то хорошее на 2Д, то ориентиром выбирать карты не ниже TNT-TNT2, а лучше GF2 и от этого плясать.
Ну ладно, не будем учитывать офисные компьютеры. Но существует довольно много ноутбуков со старыми видеокартами, например, Rage 3D. Это тоже ускоритель, хотя и слабее TNT. WarCraft 3 на нём хоть со скрипом, но идёт (!!!). А тут - 2D-графика и GF2...
В общем, я считаю так: если вы заведомо уступаете по качеству лучшим образцам, надо иметь какую-то фичу, чтобы это скомпенсировать. Низкие системные требования, например.
Хотя, как выяснилось, бывают смешные случаи (злосчастные "колобки"), когда в результате ориентации на DDraw и софт производительность обратно пропорциональна мощности компа. Но там, видимо, алгоритмы сильно кривые (пусть автор не обижается, он сам напросился), куча блокировок поверхностей на кадр и т.д.
← →
Sp@wN © (2003-09-16 14:20) [15]NailMan ©
> Вобщем если уж писать что-то хорошее на 2Д, то ориентиром выбирать карты не ниже TNT-TNT2, а лучше GF2 и от этого плясать.
Полностью согласен, и даже не по причинам которые там дальше приведены, а потому что сейчас на 80% компов стоит этот GeForce2MX (да не помянуть его в суе). Вообще встретить компьютер с видеокартой более худшей, оооооочень проблематично.
NailMan ©
> Что касаемо совмесимости - х.з. вроде как да.
Sapersky ©
> Минимальный кусок кода для добавления поддержки D3D в DDraw - 60 строк (получается аналог D3DXSprite из DX8). Хотя для того, чтобы работало более-менее быстро, нужно написать побольше, но в целом ничего нерешаемого.
Как бы я сделал поддержку вращения спрайта из DDraw с помощью D3D. Ввел бы дополнительный класс, который бы полностью отвечал за D3D, т.е. в его Create бы создавались все объекты Device, Buffer, Texture ... У этого объекта несколько процедур: Вращение, Альфа-Блендинг ... которым в качестве параметров передаются исходная поверхность и поверхность, куда нужно поместить результат (+ куча TRect).
Вот отсюда возникают проблемы:
- Как перекинуть DirectDrawSurface в Texture (или это вообще одно и то же?). У меня есть книжка DirectX в проектах Delphi (думаю все ее знают), так вот там автор, когда загружает текстуру, сначала загружает ее из файла в BitMap, а затем в цикле по пикселям перекидывает ее в Текстуру. Если делать так же с DirectDrawSurface -> Texture, то все выгоды 3Д теряются.
- Разворот текстуры происходит разворотом координат рамки, на которую она натянута (физического разворота массива пикселей не происходит???), как быть.
- + куча технических трудностей, которые я сейчас не вижу.
> Но раз уж переписывать, то переписывать основательно и избавляться от DDraw-овских корней.
Вот исходя из моего предыдущего пункта, похоже что так :(
pasha_676 ©
> Или же в любом соответствующем граф редакторе поворачиваещь сразу и помещаещь в доступные ресурсы в игре (как угодно хоть в bmp файло). Потом их выводишь в нужном порядке. Т.к. тебе в игре врядли потребуется больше 16 вариантов поворота (а то и 8), то способ вполне имеет право на жизнь (например применяется в Диабло1 и 2).
Из просмотра чужих игр я понял, что большую роль (если не главную) играет плавность и динамика. Если изображение перескакивает (8 вариантов поворота), то это вызывает раздражение уже через 5 минут. Поэтому, будь моя воля, я бы через 1 градус поворачивал.
← →
JAGO (2003-09-16 14:24) [16]Вобщем переписываю под Direct3D.
← →
MeF88 © (2003-09-16 14:57) [17]А уменя стоит 32Мб ATI Rage Fury Pro 128 XPERT 2000 + Video In/Out Theatre =) И ничего Warcraft3 прет, как миленький, тока я все равно в СтарКрафт по модему играть больше люблю.
Основной её недостаток: нет пиксельных шейдеров, из-за этого скоро пойду за Radeon 9200, а лучше 9500. (О 256Мб 9800 Pro можно тока мечатать...)
Насчет излишней плавности в играх - тоже часто достает, хотя если её правильно реализовать, то будет неплохо.
P.S. ATi рулит... ;-)
← →
Sapersky © (2003-09-17 00:58) [18]У этого объекта несколько процедур: Вращение, Альфа-Блендинг ... которым в качестве параметров передаются исходная поверхность и поверхность, куда нужно поместить результат (+ куча TRect).
C D3D проще сразу выводить на экран (хотя можно и в текстуру). Вращение, блендинг и прочее не являются отдельными фичами, а делаются видеокартой при выводе (на то оно и аппаратное ускорение), если задать соответствующие исходные данные и состояния девайса. Т.е. для 3D-ускорителя вообще нет понятия "повёрнутый/не повёрнутый" - на то он и 3D. С блендингом, в общем, тоже, хотя здесь уже идёт определённая нагрузка, особенно на видеопамять, так что если много чего сблендить - можно и GeForce затормозить :)
Как перекинуть DirectDrawSurface в Texture (или это вообще одно и то же?).
В D3D7 это та же самая поверхность, только созданная со специальным флагом и имеющая размеры = степеням двойки. В D3D8 и далее - отдельный интерфейс, но по сути - опять-таки поверхность, хотя Blt с ней сделать нельзя (можно Lock - см. эту самую книжку).
Как перекидывать - особой разницы нет, хоть по пикселям, хоть GetDC/BitBlt(D3D7), хоть функциями D3DX/D3DXSprite(DX8). Это же делается один раз, в самом начале.
← →
pasha_676 © (2003-09-17 09:46) [19]
> Если изображение перескакивает (8 вариантов поворота), то
> это вызывает раздражение уже через 5 минут.
Тут очень трудно спорить. Т.к. зависит не только от программиста, но и от художника-дизайнера. Извини, опять ссылаюсь на Дяблу - но там 8 направлений и ощущение плавности не потеряно. Правда это опять же за слуга больше художников.
Сделано (имхо)посредством анимации. Т.е. существует 8 направлений, но повороты из одного направление в соседнии - это анимационный спрайт. Очень качественно получается.
← →
Sp@wN © (2003-09-17 22:40) [20]C Direct3D возникают такие проблемы ...
1. Если в DDraw для создания анимированного спрайта я мог все фрэймы загнать на одну поверхность, а потом выбирать нужный и копировать его на первичную поверхность, то как такую фишку сделать в D3D? Тут есть текстура которая может быть полностью выведена вся сразу (я только начал изучать D3D, так что может есть способы?). То есть для каждого фрэйма мне нужно создать по текстуре??
2. Проблема с одновременной отрисовкой этих текстур. Если есть 30 текстур (30 спрайтов тобишь) и в текущем кадре их все надо вывести, то для каждой надо установить активность(SetTexture), потом вызвать метод DrawPrimitive. Т.е, даже если придумать как заполнить буфер вершин не по 4 для каждого спрайта, а последовательно, с тем чтобы затем одним вызовом DrawPrimitive (D3DPT_TRIANGELESTRIP, 0, 4*NumberOfSprite)все вывести, этого сделать не удастся из-за текстур. Как это скажется на производительности? И какие есть способы исправить положение?
← →
NailMan © (2003-09-18 10:42) [21]1. почитай про dirtyrect или около того в интерфейсе IDirect3DTexture, да и в самом IDirect3DDevice тоже.
Вроде как можно переключить текущую рамку в текстуре, с которой будет идти ее рендер, на новые координаты.
2. Да тебе придется делать 30 вызовов draw с новой текстурой, но!
Я у себя сделал так(правда для 3Д игры, но принцип тот же):
- Все текстуры грузятся в массивarray[0..xxx] of IDirect3DTexture8
, параллельно ему есть массивarray[0..xxx] of string[64]
куда я при загрузке я записываю имя текстуры.
- При создании объекта(у тебя спрайта) первым делом смотрим, а загружена ли в массив такая текстура? просто перебираем массив и сравниваем имя нужной текстуры с строками в массиве имен. Если нашлась, выдаем спрайту индекс найденой текстуры, если не нашлось, то грузим ее в массив и возвращаем индекс.
- заводим переменную LastTextureIndex и при рендере спрайта смотрим, а равен ли индекс текстуры спрайта LastTextureIndex-у? если равен то просто рендерим, если не равен, то устанавливаем текстуру(элемент массива текстур по индексу, который хранится в спрайте) и если она анимированная, то и соответсвующий текущий рект. Таким образом спрайты с одинаковым индексом текстуры лишних SetTexture делать не будут.
Естественно тебе придется сделать сортировку по индексу текстуры, дабы этот метод работал эффективно.
← →
Sapersky © (2003-09-18 13:16) [22]А теперь моё, как обычно слегка противоположное :)
Просто уже написал в offline, обидно выкидывать :)
Если в DDraw для создания анимированного спрайта я мог все фрэймы загнать на одну поверхность, а потом выбирать нужный и копировать его на первичную поверхность, то как такую фишку сделать в D3D?
Точно так же, только с учётом специфических размеров текстур - степени двойки, желательно квадратная, желательно не более 256*256, хотя если рассчитывать на GF - можно больше, но в разумных пределах (вообще макс. размер для GF 4096*4096, но большие сильно тормозят).
Выбирать нужный - заданием текстурных координат, см. книжку.
Проблема с одновременной отрисовкой этих текстур. Если есть 30 текстур (30 спрайтов тобишь) и в текущем кадре их все надо вывести, то для каждой надо установить активность(SetTexture), потом вызвать метод DrawPrimitive.
Во-первых, см. ранее (текстур будет меньше), во-вторых, да, желательно группировать по текстурам.
Т.е, даже если придумать как заполнить буфер вершин не по 4 для каждого спрайта, а последовательно, с тем чтобы затем одним вызовом DrawPrimitive (D3DPT_TRIANGELESTRIP, 0, 4*NumberOfSprite)
Не triangle strip, а indexed triangle list. К сожалению, не см. книжку - там этого нет. В DX SDK должно быть... Пример со спрайтами (DX7, разумеется :)):
http://delphigfx.mastak.ru/samples/samp70.rar
См. TSpriteBuffer. Группировки там, правда, нет, текстура устанавливается на весь буфер одна.
← →
Sp@wN © (2003-09-21 10:40) [23]http://delphigfx.mastak.ru/samples/samp70.rar
См. TSpriteBuffer. Группировки там, правда, нет, текстура устанавливается на весь буфер одна.
Посмотрел, от обилия кода у меня перегрузка началась :-) Подумаю чтобы что то такое использовать, надо ещё будет поизучать (книжку для начала, понять что написано хотя бы :)). У меня нет к сожалению библиотеке FastDIB, не получилось посмотреть результат ТО!
Ну и вопрос такой: можно отрисовать текстуру в координатах экрана? ТО есть с такими флагами - D3DFVF_VERTEX = D3DFVF_XYZRHW or D3DFVF_TEX1; У меня получается квадрат Малевича, текстуры нет. И если да, то координаты текстуры будут все равно 0..1?
← →
NailMan © (2003-09-22 09:31) [24]Только так и ресуют:
tVertex = packed record
XYZ : TD3DVector;
RHW : Single;
U,V : Single;
end;
var vert:^TVertex;
Далее заполняешь нужный тебе рект
//1 triangle
vert^.X:=Left;
vert^.Y:=Bottom;
Vert^.Z:=0;
Vert^.RHW:=1;
Vert^.UV:=d3dxvector2(0.08,0.92);//01
inc(vert);
vert^.X:=Left;
vert^.Y:=Top;
Vert^.Z:=0;
Vert^.RHW:=1;
Vert^.UV:=d3dxvector2(0.08,0.08);//00
inc(vert);
vert^.X:=Right;
vert^.Y:=Bottom;
Vert^.RHW:=1;
Vert^.Z:=0;
Vert^.UV:=d3dxvector2(0.92,0.92);//11
inc(vert);
vert^.X:=Right;
vert^.Y:=Top;
Vert^.Z:=0;
Vert^.RHW:=1;
Vert^.UV:=d3dxvector2(0.92,0.08);//10
inc(vert);
И отрисовывать его надо TRIANGLESTRIP
← →
Sapersky © (2003-09-22 09:46) [25]от обилия кода у меня перегрузка началась
Да, пример малость запутанный, извиняюсь :) Поэтому см. только SpriteBuffer - его при желании можно приспособить к своему движку, не особо вникая во всё остальное (и даже не имея FastLIB). Хотя придётся повозиться, выдирая из разных мест используемые им типы и процедуры :)
можно отрисовать текстуру в координатах экрана? ТО есть с такими флагами - D3DFVF_VERTEX = D3DFVF_XYZRHW or D3DFVF_TEX1; У меня получается квадрат Малевича, текстуры нет
Вот-вот, сам в своё время столкнулся. Поэтому и перешёл на мировые координаты (см. TransformQuad в graph_utils). Но вот недавно нашёл пример, там рассчитывается эта самая RHW (опробовать не успел ещё):
http://www.mvps.org/directx/articles/blit3d.htm
← →
Sp@wN © (2003-09-26 12:41) [26]Все таки сделал в мировых координатах. Но! Я че то не понимаю как сделать следующее: у меня спрайт квадратный, я его вращаю, при этом его жутко колбасит, то есть при повороте на 90 градусов, он жутко растягивается (вероятно потому, что 800*600 разрешение), как от этого избавится?
← →
NailMan © (2003-09-26 13:04) [27]А градусы в радианы конвертишь?
← →
Sapersky © (2003-09-26 15:43) [28]Если сделано по такому же принципу, что и в TransformQuad, то там vpHDims - это половина размера окна (экрана), Scale - размер спрайта, вроде, в пикселях; Rot - угол в радианах.
Хотя судя по симптомам... если растягивается всё время и "в бесконечность" - тут либо с количеством (порядком) вершин проблемы, либо индексы сбились (если они используются).
← →
Sp@wN © (2003-09-26 18:04) [29]NailMan ©
> А градусы в радианы конвертишь?
Да. И вершины (4 вершины квадрата) вычисляются одновременно, по одной и той же формуле, так что не должно быть в этом пролемы.
Sapersky ©
> Если сделано по такому же принципу, что и в TransformQuad ...
Формула для вычисления смещений от центра поворота та же:
NewX:=OldX*CosA - OldY*SinA + Centre.X;
NewY:=OldX*SinA + OldY*CosA + Centre.Y;
Я долго над ней тормозил (с математикой совсем не в ладах :)), но вывел, а потом у тебя посмотрел.
А в остальном можно поподробнее, что за переменные и что вычисляется?
procedure TransformQuad(QPos : TRealPoint; vpHDims : TShortPoint; Rot, ScaleX, ScaleY : Single;
color : DWord; Const TCoords : TTexCoordSet;
Var vq : TVertexQuad);
Var
n : Integer;
xv, yv : Single;
sina, cosa : Extended;
begin
SinCos(Rot,sina,cosa);
For n:=0 to 3 do With vq[n] do begin
pos.x:=DefaultCoords[n].x - 0.5;
pos.y:=DefaultCoords[n].y - 0.5;
xv:=pos.x*CosA - pos.y*SinA;
yv:=pos.x*SinA + pos.y*CosA;
pos.x:=(xv / vpHDims.x * ScaleX) - 1 + (QPos.x / vpHDims.x);
pos.y:=2 - ((yv / vpHDims.y * ScaleY) + 1 + (QPos.y / vpHDims.y));
z:=0; c:=color;
tc:=TCoords[n];
end;
Вот она процедура. Что за ДефаултКоорд (я так понимаю - это старое положение точки), и что вычисляется после xv, yv?
Sapersky ©
> Хотя судя по симптомам... если растягивается всё время и "в бесконечность" ...
Нет, в бесконечность не растягивается, он все время возвращается на исходную позицию, и круг за кругом повторяются координаты все.
Причем изначально квадрат и выглядит как квадрат (угол поворота 0 радиан, если угодно), только при повороте растягивается.
← →
Sp@wN © (2003-09-26 23:39) [30]Сделал, теперь всё ок. Стал вращать координаты экрана, а затем уже перевожу в мировые, а раньше делал все в мировых.
Еще такой вопросец. Как наиболее эффективно загрузить картинку из файла на текстуру. Я пока делаю это в цикле по каждому пикселю.
← →
Sapersky © (2003-09-27 10:45) [31]Стал вращать координаты экрана, а затем уже перевожу в мировые, а раньше делал все в мировых.
Ну да, я это и имел в виду. Изначально всё задавать в мировых неудобно. Строчки в TransformQuad:
pos.x:=(xv / vpHDims.x * ScaleX) - 1 + (QPos.x / vpHDims.x);
pos.y:=2 - ((yv / vpHDims.y * ScaleY) + 1 + (QPos.y / vpHDims.y));
- как раз и есть перевод в мировые координаты. Вывел экспериментально, рассчитано на матрицы D3D по умолчанию (т.е. ничего менять не надо). О значении параметров я уже писал в предыдущем посте.
DefaultCoords - это константы, задающие квадрат для triangle strip:
DefaultCoords : TTexCoordSet =
((x: 0; y: 0), (x: 0; y: 1), (x: 1; y: 0), (x: 1; y: 1));
Вычитаем 0,5 - чтобы поместить квадрат в центр координат. Ещё он используется для задания текстурных координат. Хотя в TransformQuad и передаются TCoords, но обычно они равны как раз DefaultCoords.
Как наиболее эффективно загрузить картинку из файла на текстуру. Я пока делаю это в цикле по каждому пикселю
Я уже писал ранее:
Как перекидывать - особой разницы нет, хоть по пикселям, хоть GetDC/BitBlt(D3D7), хоть функциями D3DX/D3DXSprite(DX8). Это же делается один раз, в самом начале.
Для D3D7 оба метода должны быть в graph_files (DrawFDIBtoSurf, DrawFDIBtoSurfEx). По опыту могу сказать - по пикселям надёжнее, GetDC/BitBlt иногда (редко, но всё же) не работает.
Для D3D8 - D3DXCreateTextureFromFile вроде оно называется. Если не хочется использовать D3DX - опять же по пикселям.
← →
Sp@wN © (2003-09-27 19:59) [32]Всем спасибо! Со спрайтом все.
← →
Kid (2004-02-25 08:42) [33]Необходим алгоритм преобразования TriangleList в TriangleStrip
← →
GrayFace © (2004-04-11 07:30) [34]Перекидывать Bitmap в Texture главное не через Canvas.Pixels.
Sapersky, кинь, пожалуйста, пример D3D в DDraw мне на мыло.
Страницы: 1 вся ветка
Форум: "Игры";
Текущий архив: 2004.07.25;
Скачать: [xml.tar.bz2];
Память: 0.58 MB
Время: 0.052 c