![]() |
raycasting
Давно пробовал делать рейкастинг как в wolf3d, ну и посмотреть, можно ли как нибудь развить эту тему, но потом как то забросил.
Решил выложить, может кому интересно будет, хотя похожих тем немало есть в инете. В архиве демка и сурцы (ссылка ниже). Раз это рейкастинг, то весь рендер софтварный, а sdl используется только чтобы готовое изображение вывести на экран (ну еще управление в демке через него). Написано на С++03, писал давно - С++11 еще небыло... ну и в целом коды там кривые... Если изменить несколько параметров, можно под линух собрать. Вобщем если кого заинтересует, можно вернуться к разработке, переписать коды нормально и т. п. maze.zip | maze.rar (20.09.13) maze_2.zip | maze_2.rar (22.09.13) maze_3.zip | maze_3.rar (25.09.13, без бинарников) maze_4.rar (28.09.13) |
Ответ: raycasting
Цитата:
|
Ответ: raycasting
Обнова: raycasting_2
* Немного поправил код: теперь можно в сурцах задавать больше вариантов разрешения. В архиве есть ЕХЕ с 640х480 и 800х600 (окно и полный экран). * Добавил код компенсирующий эффект fish eye, свойственный для рейкастинга. * Немного устранил искажения aspect ratio при некоторых разрешениях, но небольшие всеравно есть. Связано это с тем, что алгоритм был основан на целых числах с фиксированным разрешением 320х240 и значения подобраны таким образом чтобы не происходили округления. Но с другими разрешениями появляются искажения, поэтому я частично перевожу на float (тем более что потом всеравно все это на gpu логично будет перенести). * Еще всяческие изменения в коде сделал, но он пока по прежнему плохо структурирован. * Самая медленная часть кода - софтварная выборка текстуры, там надо ускорять сильно, может быть для начала попробовать SSE, хотя я не уверен что вообще системная память хорошо умеет делать выборку как видеопамять. |
Ответ: raycasting
Я чего-то непонимаю? Зачем с собой темплейты таскать такие длинные?
|
Ответ: raycasting
Цитата:
Я предупреждал что код кривой. Там по сути половина параметров шаблона вообще не нужно. Я их уже сокращаю. Даже если там останется много параметров то класс лучше инициализировать через дескриптор, тогда и читаемость кода лучше будет. Вобщем буду править. |
Ответ: raycasting
Ясно, а так интересный код. Просто до сих пор не удосужился поглядеть код Wolfenstein'a, а тут как раз рейкаст.
|
Ответ: raycasting
Обновил код - ссылка в первом посте.
Визуально ничего не изменилось, так что добавлять приложение не стал. Я посмотрел на шаблоны классов FrameBuffer и rc2d и там небыло ни одного параметра типа. Значит классы не такие уж гибкие и шаблоны им особо не нужны. Я заменил шаблоны на дескрипторы. Также добавил кое что из с++11: конструкторы переноса для классов FrameBuffer и rc2d весьма полезны будут, местами синтаксис и формат подправил. Обернул двумерный массив maze в класс Maze, чтобы сократить число аргументов в некоторых методах. |
Ответ: raycasting
Мой винрар не распаковывает твои архивы (Неизвестный метод). У меня стоит последняя версия
|
Ответ: raycasting
Цитата:
WinRAR 4.20 вроде нормально открывает. Я паковал с помощью PeaZip в стандартном zip формате. На всякий случай продублировал все в rar ( ссылки в первом посте ). |
Ответ: raycasting
Samodelkin, теперь всё отлично, спасибо. Буду следить)
|
Ответ: raycasting
Добавил редактор (скорей это чит) - теперь можно добавлять/удалять блоки (из которых состоят стены) прямо из игры.
Если смотреть на карту сверху: U - верхний левый; I - верхний; O - верхний правый; L - справа; > - нижний правый; < - нижний; M - нижний левый; J - слева; Угол поворота самой камеры никак не влияет на это. Перенес управление со стрелок на WSAD. Чуть попозже может быть добавлю мышь и стрейфы. Карту вынес в отдельный класс (maze.hpp, maze.cpp). Сделал каркас класса Player, но пока еще не заполнил его кодом. Убрал переопределия целочисленных типов - они там не нужны. Теперь в коде стандартные типы из cstdint. Добавил многопоточность. Она работает на уровне кастинга лучей (тест на пересечение с объектами) и на уровне заполнения фреймбуфера (софтварного), буфер делится на области, с каждой работает отдельный поток. В C++11 есть удобный класс std::thread, но в mingw 4.7.2 он не работает (в mingw вообще я смотрю много проблем). Boost решил не использовать - он слишком большой для такого маленького проекта (нарушается равновесие дзен). Поэтому воспользовался WinAPI CreateThread: там всего около 20 строчек кода, которые можно макросами обвести для компиляции в другой ос, и использовать уже там например std::thread. Ссылки все в первом посте. |
Ответ: raycasting
Визуально ничего не изменилось. Скорость рендера возросла.
Среднее значение maze_2 : 42 maze_4 : 63 Процессор 4 ядра по 3,2 ГГЦ Редактором не врубился как пользоваться. Код поглядел. Стал лучше. Вообще проект у тебя интересный. Слежу. |
Ответ: raycasting
Неудобно что правка первого поста ограничена 10 днями... Туда удобно было добавлять новый материал чтобы все в одном месте было.
Raycasting прогрессирует! ![]() >>> maze_5.rar <<< Подправил многопоточность: на моем пк +20 fps прирост. Добавил текстуры. Вообще они там и так были, но небыло загрузчика для них. Я написал свой для bmp. Свой писал потому что мне нужен был определенный контроль при переводе из DIP в DDB формат, так как есть определенные особенности рендера. Загрузчик пока читает bmp с заголовком в 54 байта (те что стандартные из пеинта вобщем), остальные варианты если нужны будут потом добавлю. Фильтр для текстуры пока nearest, чуть позже попробую bilinear - есть вероятность что в софтваре уже не потянет. Сделал разрешение 1280х720 и ограниение в 30 fps, чтобы фреймрейт не скакал. Для софварного рендера это очень даже неплохо имхо, тем более что дальше графика еще будет нагружаться. Сделал чуток плавней управление. |
Ответ: raycasting
Вложений: 1
Скорость рендера стабильная, и практически не зависит от размера текстуры - я уменьшил размер текстуры в 2 раза и FPS все равно 31. Что круто.
Двигаясь вплотную по стенке вызел баг. Второй раз пошел по тому же самому месту - баг не вылез. Скрин в аттаче. |
Ответ: raycasting
Цитата:
Кстати странная вещь - в mingw 4.7.2 неработают атрибуты: Код:
struct A { char a; char b; ... } __attribute__( __aligned( 1 ) ); Пришлось сделать так: Код:
#pragma pack( push, 1 ) |
Ответ: raycasting
Цитата:
Переписал все вычисления на float (раньше были целочисленные, как и следует wolf3d подобным играм). Тем самым образом исчезли артефакты связанные с неточной выборкой текстур и расчетом геометрией на близком расстоянии (тем более что разрешение выше чем в wolf3d и целочисленные косяки стали более заметны). Убрал предрасчетные тригонометрические таблицы (опять же по причине достаточной производительности), кое где в критических местах работает кеширование. Добавил функцию расчета тумана. Вообще она универсальная, и можно делать не только туман, а вообще любой эффект, у которого есть линейная зависимость от расстояния (например в демке я сделал погружение дальних объектов в темноту). Добавил AABB и сделал небольшую механику на них. Теперь все объекты коллиzятся через AABB (раньше был примитивный рассчет на окружностях). Например у перса появилась инерция, а при соударении со стенами (перса =)) гасится импульс только вдоль нормали к стене. Таким образом позже будет легко добавить отскоки и прыжки. Также AABB можно тестировать на пересечение с отрезками и лучами, что тоже будет полезно. Тестирование пересечений есть двух типов: первое просто проверяет на пересечение двух AABB, второе перемещает AABB по всей тестируемой траектории движения с заданным шагом. Тем самым быстрые мелкие объекты не будут проскакивать через другие мелкие объекты. Хорошей оптимизации для обсчета всех AABB наподобие деревьев пока нет, но я сделал предварительный расчет расстояния, если оно больше чем может преодолеть объект то тестирование прерывается. Вобщем у меня на карте около 1000 AABB, обсчитывается на одном ядре и никакого падения производительности незаметно. В связи с описанным выше, у перса появилась улучшенная механика движения, добавил управление мышью (можно и стрелками), стрейф (WSAD). Однако еще далеко не все сделано. Кстати к вопросу почему я не использую готовые физические движки. Я думаю попробовать сделать оригинальную механику из какой-нибудь игры вроде doom или quake. Вообще у меня есть написаный ранее модуль для другого движка с physx, но вот пока я думаю он не нужен... Да самое заметное это то, что появился пол и потолок. Незнаю точно как делали в doom 1, но я уже делал нечто среднее между кастингом и трейсингом, потому как пол и потолок обрабатываются попиксельно (что то наподобие как делают в пиксельных шейдерах, только конечно с меньшим количеством кода). Сейчас используется nearest фильтр при выборке из текстуры и он создает очень "шумное" изображение. Я пробовал делать билинейную фильтрацию, но она скорей нужна в случае когда текстура с низким разрешением растягивается на экран большого разрешения, а в случае с этим проектом нужно как раз наоборот. Анизотропные фильтры уже не потянет софтварный рендер, поэтому я решил пока оставить так, и может быть потом сделаю сглаживание всего изображения как пост-процесс эффект и этого будет достаточно. Кстати разрешение я снизил до 640х320, но поднял fps до 60 (ну может у кого и меньше будет). Добавил пару пост-процесс эффектов. В сумме с низким разрешением изображение получилось в таком трешевом киберпанковском стиле =). Но в целом оптимизировать еще есть куда, я думаю раза в 3-4 можно ускорить - simd и лучшее распределение по потокам. Раз это рейкастинг, то сложность сцены почти не повлияет на произоводительность, так что на загруженных сценах сильно медленней не должно быть. И теперь проект также работает на Linux. maze_6_4.rar (Windows) maze_6_5.tar.7z (Linux) |
Ответ: raycasting
Ёпт!
Так и должно быть??? ![]() Фтопку такую постобработку! |
Ответ: raycasting
Круто! Походив 5 минут по лабиринту не вылезло ни единого бага, что круто. В качестве постэффекта лучше сделать легкий шум, чем кадровую развертку. Работает всё шустро. Среднее фпс - 55. А текущее иногда проваливается до 47.
|
Ответ: raycasting
Цитата:
Так или иначе, рейкастинг был сделан для игр своего времени и поэтому я пытаюсь стилизовать картинку так чтобы это выглядело как старый ЭЛТ монитор или телевизор, с низким разрешением. Попробуй тогда в демке ниже сам понастраивать разные комбо постэффектов. maze_6_6.rar (Windows) maze_6_7.tar.7z (Linux) Добавил несколько пост эффектов и возможность их включать/выключать (можно комбинировать). Сейчас я не занимался их оптимизацией, поэтому данная версия довольно медленная. Управление: 1 - вкл/выкл эффект xray (хаотичные белые точки, не путать с шумом). 2 - вкл/выкл эффект кадровой развертки (его нужно видеть в движении, от скринов толку мало). 3 - переключение функции тумана (ничего|темнота|туман). 4 - вкл/выкл затенение по углам. 5 - вкл/выкл шум. 6 - переключение цветовых фильтров (обычный|черно-белый|сепия). 7 - вкл/выкл билинейную фильтрацию (она вообще какая то плохая, видимо я накосячил где-то в ее логике - не так хорошо семплы смешивает, потом перепроверю). 8 - поставить ограничение в 30fps. 9 - поставить ограничение в 60fps. 0 - неограниченный fps. Ну конечно настроек у каждого эффекта больше, но клавиш не хватит - потом вынесу все в cfg файл. |
Ответ: raycasting
Цитата:
FPS выше 19 не поднимается :( ЦП хороший - AMD FX-6100, 3,3 ГГц Последний пример хорошо смотрится, вариант по умолчанию понравился, молодец, продолжай в том же духе :super: P. S. Обзор мышью будешь делать?? |
Ответ: raycasting
Цитата:
Цитата:
Цитата:
Движение по вертикали чуть позже добавлю - там не все так просто - возможности рейкастинга пока не дают камеру вверх/вниз поварачивать. |
Ответ: raycasting
Цитата:
|
Ответ: raycasting
:winlogo: maze_6_9.rar :luxlogo: maze_6_10.tar.7z Сделал несколько экспериментов с фреймбуферами. Изначально был фреймбуфер, который хранил пикселы формата A8R8G8B8, но записывал их столбцами, а не строками, так как я предположил что это будет лучше, потому что рейкастинг именно так рисует пикселы. Однако на стадии рейкастинга особого прироста это не давало, а вот для постпроцесс эффектов это было неудобно - когда надо было копировать группу пикселей, memcpy это делает быстрей чем копирование по одному в цикле. И я сделал построковый фреймбуфер, а тот старый удалил вообще. Также, в постпроцесс эффектах довольно часто приходится конвертировать из A8R8G8B8 в R32fG32fB32f формат, и чтобы сэкономить на этих операциях с добавил такой формат фреймбуфера, и такой же сделал для текстур. Однако в данном случае увеличивается их размер и в среднем получается что они работают примерно с одинаковой скоростью, так что я оставил оба варианта на всякий случай. Исправил несколько багов с BMP загрузчиком. Я не внимательно читал вики, а там было сказано что расположение строк пикселей в BMP находится в обратном порядке, что я не учел, и все изображения раньше приходилось в рендере еще раз переворачивать. Добавил новые эффекты: "RGB расслоение", раздельное горизонтальное и вертикальное размытие по Гауссу с выборкой из 5 соседних пикселей, на основе размытия сделал эффект расфокусировки линзы объектива по краям экрана (как в игре Limbo). Большинство эффектов распараллелены. Оптимизация проводилась за счет кеширования и предварительного расчета маски актуальных пикселей, другими словами заранее определялись пикселы которые нужно изменить и только они и меняются, избегая обращения к другим пикселям (RAM позволяет все это делать без каких либо пинг-понгов на квадах, как это было на шейдерах). Однако еще есть много места для оптимизации. В общем с учетом добавления новых (довольно тяжелых) эффектов fps удалось поднять до 30 (i7 930, на Linux). Однако, не хотелось бы никого обижать :), но на Windows MinGW примерно тот же код, с теме же ключами, компилируется на 30-40% более медленным! Особенно проблемы доставляет mingw-реализация некоторых стандартных функций. Так что по возможности буду их убирать из кода и обходиться своими. Цитата:
Размытие по краям линзы включено все время. |
Ответ: raycasting
Все работает. Багов не замечено. Возможно ли при рейкастинге сделать мипфильтрацию? А то аж рябит в глазах от выборки пикселей.
ФПС при одном эффекте мыла по краям - среднее 27 ФПС при всех включенных эффектах - 22 ( тоже среднее ). |
Ответ: raycasting
Цитата:
Однако я точно не уверен, поэтому попробовать нужно. Но все же надо подумать и об альтернативных вариантах, может быть есть какие то варианты процедурной обработки или генерации текстур, промежуточные форматы хранения или что то в этом роде, не создающие большой трафик в памяти. Третий вариант - это просто сделать правильные текстуры, в которых впринципе не будет такого большого контраста текселей. Или например сделать специальную mip фильтрацию (на стадии загрузки или даже сохранения текстуры в редакторе), которая в каждой следующей уменьшеной копии текстуры убирает сильно выделяющиеся по контрасту текселы, в таком случае можно обойтись mip-mapping'ом с обычным nearest (или bilinear) фильтром. |
Ответ: raycasting
maze_6_11.rar
Тестировал оба формата (A8R8G8B8 и R32fG32fB32f) на скорость - они показывают практически одинаковые результаты, разница в районе 2-3%, что совсем несущественно. Так как float формат занимает в 3 раза больше места, то он менее перспективен и я его удалил (это касается фреймбуферов, текстур и буферов эффектов). Так что теперь рендер будет работать только с A8R8G8B8. Попробовал разные способы автооптимизацию (автовекторизацию, выбор целевой архитектуры, настройку математики и прочие опции компилятора), в среднем удалось ускорить в 2,5 раза, это поверх опции -O3 (я на gcc собираю), что весьма неплохо... Но там еще есть над чем поработать, так что в следующий раз подробности расскажу =). Также оптимизировал локальность размещения данных в памяти, чтобы было меньше кеш промахов, но тут имхо для лучшего результата нужно свой аллокатор делать. За счет небольшой прибавки скорости, я восстановил качество некоторых пост эффектов, которое раньше было урезано. Исправил баг в коде билинейного фильтра. Теперь понятно почему он раньше так плохо выглядел. Сейчас все сглаживается как и положено - можно в упор подойти к стене и понажимать 7 (включение/выключение билинейной фильтрации). Частично реализовал систему mipmaping'а. Значит я написал класс-контейнер который содержит внутри себя классы текстур, каждая текстура имеет свой размер, соответственно mipmap уровню. Генерация уровней происходит после загрузки текстуры, в качестве фильтра для генерации уменьшенных копий используется усреднение значений 4 соседних текселей (ну вобщем ничего особенного). Во время выборки уровень определяется на основе расстояние (то есть для рейкастинга у нас известна длина луча, никаких z-buffer'ов тут нет). Однако на данный момент я сделал линейную зависимость, что неправильно - дальние текстуры будут быстро понижаться в уровне. Нужен более сложный алгоритм, который кроме расстояния, будет учитывать разрешение текстуры, угол обзора FOV, а также угол наклона поверхности к вектору обзора. Скорей всего все это я попробую учесть в реализации анизотропной фильтрации. То что касается этой демки: 7 - включить/выключить билинейный фильтр, 8 - включить/выключить mipmapping, 3 - как и раньше перключение темноты/тумана/без_тумана - если его отключить то будет видно далеко и как меняются mipmap уровни в линейной зависимости от расстояния. |
Ответ: raycasting
Среднее ФПС со стандартным набором эффектов - 44.
Со всеми включёнными - 42. Графон стал лучше. С мипами не так сильно рябит. Но без тумана текстура вообще исчезает вдали - будто мип 1х1. Работает шустро. |
Ответ: raycasting
maze_6_12.rar
Цитата:
Вывел более менее оптимальную формулу расчета мип-уровней: Код:
twoTanAlpha = 2.0f * tan( fieldOfViewInRad / 2.0f ); Вот, анизотропную фильтрацию пока сделать вообще не удасться - нехватает данных о положении сурфейса во время процесса выборки текстур. Нужно конвеер рендера расширять. Так что пока всё. |
Ответ: raycasting
Стало намного лучше.
SIMD будешь использовать? |
Ответ: raycasting
Сейчас я уже с ключом sse компилирую, только толку от него пока мало - нужно правильные циклы писать чтобы автовекторизатор срабатывал. Так что да нужно вручную ассемблировать. Сначала буду матлибу переписывать c simd, а потом рендер. Если я правильно понимаю то в 64 битном режиме доступно 16 xmm регистров, что значительно должно повысить производительность. Но этим я и ограничусь, avx не буду делать, да и железки у меня такой нет. Потом буду смотреть в сторону gpgpu.
|
Ответ: raycasting
Цитата:
FPS max. - 15, min. - 13 Стерео эффект пока что не очень, может быть из-за чёрных полосок сверху и снизу экрана, или нечёткости контуров. Слева экрана, артефактная красная полоса, в стерео очках даёт странный эффект - как будто слева очень узкая, дополнительная камера. |
Ответ: raycasting
Цитата:
Однако идея хорошая. Ты имеешь ввиду анаглифные очки? С ними можно попробовать поэкспериментировать. Вообще я сам не очень одобряю эти очки, у них и качество посредственное и пускать два разных цветовых канала в каждый глаз это издевательство. Но в целом опробовать стерео механику в широком смысле слова было бы неплохо для рендера. Как нибудь займусь этим. Насчет того эффекта что ты принял за стерео - его механика проще: изображение раскладывается на 3 составляющии, красное, зеленое и синие. Затем красное и синие сдвигаются вправо и влево относительно зеленого соотвественно, и немного искажаются по горизонтали, с помощью смещения. Затем 3 составляющии снова соединяются в одно изображение. То что это внешне напоминает стерео - просто совпадение, я и не думал о нем когда делал этот эффект. Цитата:
Я пробовал на стареньком ноуте с процем DualCore 2ГГц - там до 20 fps, на i7-930 - 55-60. У тебя нет возможности Linux версию протестировать? И кстати какая у тебя память (сколько каналов, тип и частота)? maze_6_13.tar.7z (Linux) |
Ответ: raycasting
Цитата:
А ведь почти получилось :) Цитата:
DDR 3 - 1333 - 4Гб - одна планка |
Ответ: raycasting
Цитата:
Вполе возможно что медленно так из-за памяти. Так что буду пробовать еще снижать трафик в памяти. Я думаю на памяти надо даже больше сосредоточиться чем на процессоре. Я кстати не знаю причины почему у тебя одна планка, но это не рационально. Для твоего процессора оптимальная память раза в 3 быстрей должна быть. У тебя же наверняка трехканальная передача данных поддерживается или что-то в этом роде. Еще 2 планки аналогичные поставь. |
Ответ: raycasting
Надеюсь автор топика не будет против, если я продолжу тему по иному рейкаст-двигателю (http://lodev.org/cgtutor/raycasting2.html)
Пробовал заделать пол и потолок градиентом (пикча) прирост производительноти процентов, эдак, на 50...75. Но всё равно отстойно смотрится. Замена double на float не привнесла абсолютно никаких изменений. Всё такой же адово низкий показатель fps. (при отрисовке текстур пола и потолка на разрешении 1366*768 и частоте проца 2.2 ГГц выдаёт 12 кадров пер секонд) И ещё, как поменять в этом движке высоту положения камеры ? Там надо отдельно менять какие-то значения в цикле рендера пола, цикле стен и спрайтов. |
Ответ: raycasting
В этом участке я максимум что осилил, так это вынести пару арифметических операций за тело цикла.
Код:
int dd=h * 128 ; |
Ответ: raycasting
Нужно избавиться от умножения. До тела цикла вычислить константу, а затем вычислять d+=const.
то же касается и TexY. А вообще лучше конечно было бы асм-всавками воспользоваться, но хз, как потом результат вычислений занести из регистров в определённую переменную... |
Ответ: raycasting
Пока еще не разбирал этот двиг, но некоторые алгоритмы рейкастинга (и в моем движке так тоже было в начале) могут не предусмативать настройку высоты камеры вообще - опять же этими апроксимациями можно сократить кол-во вычислений.
1366х768 и при этом собираешься делать ретро игру под pentium mmx с выборкой без сглаживания и целочисленными вычислениями? Так не выйдет. Определись - либо делаешь всё как в старых играх, в том числе 320х200 (или 240), либо делаешь нормально под современные железо и пользуешься текстурными фильтрами и прочими вещами которые хоть как то облагораживают изображения для более менее высокого разрешения. Иначе будет выглядеть трешево. Ок, можешь в сюда постить - будет общая тема рейкастинга. upd: Максимум что можно сделать это рендерить в буфер 320x240, а затем аппаратно перерисовать в более большой, например 1920х1080, потому что не все мониторы могут растянуть такое низкое разрешение на полный экран, только перерисовывать без сглаживания, либо с каким то дополнительным шейдерным эффектом, как например старые ЭЛТ мониторы - они не могли четко нарисовать пиксель как LCD монитор. |
Ответ: raycasting
Цитата:
так-то планирую хотя бы на 640*480 ориентироваться. Дело в том, что на 640*480 этот движок тоже адски тормозит. На моём пне MMX вполне шустро работает виндовый порт Дюка3д eduke32 на разрешении 800*600, на софтверном рендере, разумеется. А там графон огого, и динамические освещения, и разная высота стен, и альфаблендинг текстур, и анимация биллбордов и текстур, та и тайлинг текстур нехилый такой, и наклонные поверхности по всем осям, и ещё много чего. Та и не только рейкаст, даже полигнональные игры, типа NFS-1 или MDK на софтверном двигателе летают на моем MMX'e. А вот игры с коррекцией перспективы уже малость лажают (тот же quake 1-2, на разрешениях 640*480 проседают по фреймрейту, так как коррекция перспективы довольно ресурсоёмка. Хотя меш моделей *.md1 *.md2 с искажённым наложением текстур)... Но это уже малость оффтоп. |
Ответ: raycasting
Вот сейчас интересует, как же запилить ассемблерную вставку в коде-блоксе (mingw gcc win32).
Чтоб произвести арифметические вычисления, и результат из регистра поместить в какую-либо переменную. |
Ответ: raycasting
В gcc inline assembler есть два наречия at&t и intel - intel признано более удобным, но можешь по любому писать.
howto для at&t Для intel все тоже самое только нужно ".intel_syntax;" добавить первой строкой ну и соответсвенно на другом наречии дальше писать, например как тут. Здесь можно смотреть сами инструкции. Необязательно читать всё - тебе надо 5.5, а также часть 9 про mmx, части 10 и 11 про sse и sse2, ну и дальше если тебе нужно больше расширений. Однако многие предпочитают интринсики ассемблерным вставкам, они чуть медленей, но всеравно в разы быстрей чем без них, но я их не использовал, так что пусть ктонибудь другой ответит кто знает. |
Ответ: raycasting
За счёт побитного скролла fps увеличился с 50-ти до 62-ух (это если стенку в вплотную разглядывать... При разглядывании спрайтов fps почти вдвое меньше становится)
Код:
int d1=lineHeight * 128; |
Ответ: raycasting
Код:
int d = ( y << 8 ) - d2 + d1; |
Ответ: raycasting
Есть идеи, как в том сорсе осуществить поворот стен хотя бы кратный 45-ти градусам ?
В смысле не строго север\юг\запад\восток, а хотя бы так, как в zero tolerance на мегадрайве. |
Ответ: raycasting
В данном подходе никаких проблем нет. Главное нужно понимать что задачу можно разделить на две составляющие - первая нахождение пересечения луча со стеной в 2д, вторая уже на основе полученной длины луча мы строим слайс с учетом высоты стены. Поэтому в первой составляющей мы можем рассчитать стену как угодно, а для второй аргументами будут являться длина луча и высота стены. Так что считать только прямоугольные стены совсем не обязательно. Например мы можем рисовать произвольной кривизны линии изображающие стены и если у нас будет алгоритм, который сможет найти пересечения луча и этих линий то мы найдем длину луча, которую и передадим во вторую составляющую алгоритма. Однако не стоит забывать что в играх кроме графики есть и физика, и например рассчитывать коллизии игрока со стенами произвольной кривизны будет сложно. Я думаю самым оптимальным выбором будут стены составленные из отрезков, которые могут находиться под произвольным углом (а не только 45 градусов). Таким образом задача сводится к нахождению пересечения луча и отрезка.
Вроде когда я смотрел коды того движка, там карта задавалась прямо в коде в виде двумерного массива. С таким форматом ничего не выйдет - нужно разработать другой формат, который хранит данные о карте в форме отрезков. Возможно для удобства потребуется редактор таких карт. |
Ответ: raycasting
Цитата:
![]() ![]() |
Ответ: raycasting
Я думал над таким решением и мне кажется оно будет со временем усложнять код, ведь здесь используется ветвление - на каждый случай есть своя реализация как его обсчитать. И чем больше будет вариантов стен и их углов (а также еще и текстур или еще чего-то) - тем более запутанный будет становиться код.
Поэтому я считаю что нужно использовать обобщенный алгоритм пересечения луча и отрезков как я предложил выше. Конечно ты можешь хранить карту в таком массиве, а перед расчетом лучей преобразовать ее в отрезки, но зачем лишние конвертации если можно сразу хранить и редактировать в отрезках. Если ты уверен на 100%, что кроме стен под углом 45 тебе ничего не понадобиться, то можешь остановиться на этом варианте. В любом случае тебе придется делать редактор, потому что править такой массив данных прямо в коде весьма утомительно. |
Ответ: raycasting
Цитата:
Цитата:
Щас не могу разобраться, как изменить точку схода перспективы, то есть поставить камеру выше. В процедуре рисования спрайтов это задаётся отдельным дефайном, а как быть со стенками не знаю. |
Ответ: raycasting
Samodelkin, видал в твоём проЭкте сделана фишка "затенение в глубину" (или туман, если инверсия)
Как сделать это в том движке, на который я глаз положил ? Там в зависимости от переменной drawStart нужно произвести операцию тонирования со столбцом пикселей текстуры. |
Ответ: raycasting
К сожалению всё руки не доходят посмотреть тот движок, хотя я заметил там несколько классных фич которые надо бы перенять.
Вот мой код: Код:
/* outColor - результирующий цвет. inColor - исходный цвет. rayLen - длина луча до стены (или пола/потолка). Первая часть функции это условия чтобы регулировать на каком расстоянии туман начинается и на каком он достигает своего максимального значения ( desc.fogMinClamp и desc.fogMaxClamp соответственно ). Между этими значениями происходит линейная интерполяция, которая осуществляется в следующей строке кода и записывается в fogValue. Результат будет в диапазоне 0.0f - 1.0f. Затем идет домножение на desc.fogFactor чтобы нормализованное значение изменить таким образом в соответствии с решением задуманным дизайнером. Дальше мы умножаем на desc.fogColor чтобы задать цвет туману и прибавляем результат цвета к исходному inColor цвету пиксела. Затем функция Saturate просто обрезает (не нормализует) значения вектора в диапазон [0.0f; 1.0f] - это аналогично функции saturate или clamp( x, 0.0f, 1.0f ) из HLSL. |
Ответ: raycasting
:shit: всё очень печально :shit:
Запускал только-что на пентиуме вариант без пола и потолка - 4 кадра в секунду (если в обзор попадает спрайт - 3 кадра) Комп как бы намекает, что это всё плохая затея. |
Ответ: raycasting
Цитата:
Попробуй вот так (код я не проверял и не компилировал): Код:
uint32_t fog( const uint32_t inColor, const uint32_t rayLen, const uint8_t factor ) { Тут главное не напутать с форматом цвета. Например согласно little endian 4 байтное число 0xaabbccdd на самом деле записывается в память в обратном порядке - ddccbbaa. Таким образом при преобразовании типа, например в 2 байтное число оно превратится в ddcc, то есть 0xccdd если в нормальном представлении. Так что я код написал что у тебя в памяти идет ARGB в таком порядке, то есть в 4 байтном числе это 0xBGRA. Однако операторы сдвига как раз работают с числами в нормальном представлении, то есть для числа 0xaabbccdd если применить >> 24 то будет ожидаемое aa, а не какое то значине справа от числа, так что я просто написал чтобы было понятно как работает внутри :crazy: Да кстати расширение mmx (а также sse в более новых машинах) может работать с упакованными значениями - и видимо они здесь как раз кстати подойдут, но я пока сам так еще не делал. |
Ответ: raycasting
Цитата:
|
Ответ: raycasting
Дело не в рейкастинге... Дело в самом quickCG.
Попробовал написать элементарное Хыллоу Ворлд, где будет закрашиваться экран и выводится отмасштабированный в два раза спрайт. И таки шо ви думаете? Эта хрень рисуется тоже 4 кадра пер секонд. (на пентиуме, разумеется... На моём ноуте 150 кадров в секунду) Код:
#ifdef __cplusplus |
Ответ: raycasting
И тут дело даже не в выборке пикселей из png-картинки.
Тут дело в выводе пикселя, каким бы он ни был. Там даже обычное заполнение сплошным цветом - 4-5 кадров в секунду. |
Ответ: raycasting
В топку этот quickCG значит. Зачем он нужен? Я у себя рендер делал целиком сам, затем готовый фрейм с помощью SDL 1.2 выводил на экран. Еще лучше заюзать OpenGL или D3D напрямую, даже если не использовать аппаратные плюшки, я просто не в курсе как делали во времена MMX, возможно напрямую VGA юзали. Через чего кстати видеокарта подключена на твоем компе? Может там шина PCI или AGP старая и медленная и менять пиксели из системы очень медленно? Либо алгоритм не самый лучший, например при программировании VGA напрямую есть режим отображения видеопамяти на системную - я так делал когда пробовал написать бутлоадер с графическим интерфейсом через графику BIOS.
Тут тебе видимо тоже рекомендуют на шейдеры перенести :) Короче просто попробуй сделать хело ворлд вместе с SDL и посмотреть как на нем будет. Если медленно тогда придется искать другие способы взаимодействия с видеокартой. |
Ответ: raycasting
Цитата:
Цитата:
А какие есть ещё API помимо SDL, чтоб шустро выводить пиксель на экран при помощи ЦП ? Цитата:
http://lodev.org/cgtutor/quickcg.html |
Ответ: raycasting
Подожди, тут нужно структурировать:
SDL является прослойкой между приложением и directx для windows или xlib|opengl для linux. Поэтому в твоем случае directx юзается всеравно. quickcg получается еще одной надстройкой над sdl, и если даже он использует sdl каким то хитрым способом, то это в любом случае медленнее чем dx. поэтому если у тебя на видеокарте медленный dx то у тебя sdl быстрей не будет. Теперь о софтварном рендере. Монитор у тебя всеравно подключен к видеокарте и она в любом случае принимает участие в формировании изображения. Видеокарта соеденина с матплатой посредством agp, pci или pci-express (что там на mmx было?) и это обычно является самым узким местом. Преимущество аппаратного ускорения в том что все текстуры, вершинные буферы и прочая инфа один раз загружается в видеопамять (если не считать изменений и синхронизаций) и затем кадры формируются уже внутри видяхи не затрагивая шину разъема. В случае софтварного рендера у тебя кадр формируется в раме, и значит тебе нужно каждый раз новый кадр переправлять по разъему чтобы видяха его вывела на экран. вот. тут все решает размер этого кадра, то есть его разрешение, глубина цвета и прочие атрибуты. Если же ты будешь прогать через vga напрямую то тебе даже не нужны ни ось, ни всякие gapi, то есть никакого оверхеда, а так как тебе нужно только копировать кадры из рамы в видяху, минимальных возможностей vga должно быть достаточно. Но там все через асм. И вобщем судя по твоим отчетам о скорости dx на старых компах, я еще больше убеждаюсь что игры тогда программировали именно так - напрямую, без юзания gapi. |
Ответ: raycasting
Даже не знаю где бы инфу черпануть по перебросу содержимого системного ОЗУ в видео-память на асме. + инициализировать граф. режим надо.
На моём излюбленном спектруме это делалось 5-тью 6-тью инструкциями... IBM-PC куда сложнее в этом плане, при том что большинство инструкций - целые макрокоманды. Более того, прежде чем перебрасывать содержимое оперы, надо как-то ещё туда и записать само изображение... Быть может SDL даже в буфер медленно записывает. Хотя не. Кое-что нашёл по VGA-CGA-EGA. Читану на досуге. http://www.codenet.ru/cat/Applicatio...ESA-Standarts/ |
Ответ: raycasting
В режиме VGA ничего перебрасывать не надо, точней там идет отображение адресного пространства, ты пишешь в определенные адреса как в обычное ОЗУ, а система сама перегоняет это в видеопамять.
Ты видимо неправильно SDL использовал. Нужно создать фрейм буфер в ОЗУ через обычный malloc например и обращаться к нему как к двумерному массиву: Код:
uint32_t* buffer = ( uint32_t* )malloc( 320 * 240 * sizeof( uint32_t ) ); Вот я у себя целый класс FrameBuffer сделал чтобы работать с фреймами внутри ОЗУ. ЗЫ: Размеры массивов в С++ ограничены, поэтому именно через malloc / free лучше с буферами работать. |
Ответ: raycasting
Цитата:
Код:
Uint32 buffer[screenWidth][screenHeight]; Цитата:
Код:
drawBuffer(buffer[0]); |
Ответ: raycasting
Вложений: 1
"чистый" SDL , без quickCG тоже медленно рисует вроде бы.
Вот я когда-то давно клепал на чистом SDL движок (с рейкастингом он правда никак не связан, но рисует всё попиксельно). На пентиуме тоже дико лагает. На гигагерцах вполне нормально идёт. Правда в этом моём движке проц шибко много ненужных вещей делает. Например , если спрайт находится за спрайтом, то невидимые зрителю пиксели он всё равно рисует. |
Ответ: raycasting
Работает, немного глючит курсор когда ездит снизу, справа - он попадает в область где не очищается буфер. Также если уехать сильно влево/вправо то глючить начинает бекграунд. Также нету синхронизации по времени? Все спрайты я проезжаю за 2 сек.
|
Ответ: raycasting
Цитата:
Цитата:
|
Часовой пояс GMT +4, время: 14:31. |
vBulletin® Version 3.6.5.
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Перевод: zCarot