forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   Проекты C++ (http://forum.boolean.name/forumdisplay.php?f=56)
-   -   raycasting (http://forum.boolean.name/showthread.php?t=18551)

Samodelkin 20.09.2013 22:13

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)

Arton 20.09.2013 22:55

Ответ: raycasting
 
Цитата:

Сообщение от Samodelkin (Сообщение 267440)
Вобщем если кого заинтересует, можно вернуться к разработке...

Уже жду :)

Samodelkin 22.09.2013 03:19

Ответ: raycasting
 
Обнова: raycasting_2

* Немного поправил код: теперь можно в сурцах задавать больше вариантов разрешения. В архиве есть ЕХЕ с 640х480 и 800х600 (окно и полный экран).
* Добавил код компенсирующий эффект fish eye, свойственный для рейкастинга.
* Немного устранил искажения aspect ratio при некоторых разрешениях, но небольшие всеравно есть. Связано это с тем, что алгоритм был основан на целых числах с фиксированным разрешением 320х240 и значения подобраны таким образом чтобы не происходили округления. Но с другими разрешениями появляются искажения, поэтому я частично перевожу на float (тем более что потом всеравно все это на gpu логично будет перенести).
* Еще всяческие изменения в коде сделал, но он пока по прежнему плохо структурирован.
* Самая медленная часть кода - софтварная выборка текстуры, там надо ускорять сильно, может быть для начала попробовать SSE, хотя я не уверен что вообще системная память хорошо умеет делать выборку как видеопамять.

mr.DIMAS 25.09.2013 10:57

Ответ: raycasting
 
Я чего-то непонимаю? Зачем с собой темплейты таскать такие длинные?

Samodelkin 25.09.2013 16:18

Ответ: raycasting
 
Цитата:

Я чего-то непонимаю? Зачем с собой темплейты таскать такие длинные?
Ты про то что шаблоны большие или сам факт записи нечитабельный? =)
Я предупреждал что код кривой.
Там по сути половина параметров шаблона вообще не нужно. Я их уже сокращаю. Даже если там останется много параметров то класс лучше инициализировать через дескриптор, тогда и читаемость кода лучше будет.
Вобщем буду править.

mr.DIMAS 25.09.2013 23:32

Ответ: raycasting
 
Ясно, а так интересный код. Просто до сих пор не удосужился поглядеть код Wolfenstein'a, а тут как раз рейкаст.

Samodelkin 26.09.2013 00:24

Ответ: raycasting
 
Обновил код - ссылка в первом посте.
Визуально ничего не изменилось, так что добавлять приложение не стал.

Я посмотрел на шаблоны классов FrameBuffer и rc2d и там небыло ни одного параметра типа. Значит классы не такие уж гибкие и шаблоны им особо не нужны. Я заменил шаблоны на дескрипторы. Также добавил кое что из с++11: конструкторы переноса для классов FrameBuffer и rc2d весьма полезны будут, местами синтаксис и формат подправил. Обернул двумерный массив maze в класс Maze, чтобы сократить число аргументов в некоторых методах.

is.SarCasm 26.09.2013 09:35

Ответ: raycasting
 
Мой винрар не распаковывает твои архивы (Неизвестный метод). У меня стоит последняя версия

Samodelkin 26.09.2013 15:43

Ответ: raycasting
 
Цитата:

Мой винрар не распаковывает твои архивы (Неизвестный метод). У меня стоит последняя версия
Это который 5.00 beta чтоли?

WinRAR 4.20 вроде нормально открывает.
Я паковал с помощью PeaZip в стандартном zip формате.
На всякий случай продублировал все в rar ( ссылки в первом посте ).

is.SarCasm 27.09.2013 10:47

Ответ: raycasting
 
Samodelkin, теперь всё отлично, спасибо. Буду следить)

Samodelkin 28.09.2013 17:51

Ответ: 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.

Ссылки все в первом посте.

mr.DIMAS 29.09.2013 03:44

Ответ: raycasting
 
Визуально ничего не изменилось. Скорость рендера возросла.

Среднее значение

maze_2 : 42

maze_4 : 63

Процессор 4 ядра по 3,2 ГГЦ

Редактором не врубился как пользоваться.

Код поглядел. Стал лучше.

Вообще проект у тебя интересный. Слежу.

Samodelkin 30.09.2013 22:35

Ответ: raycasting
 
Неудобно что правка первого поста ограничена 10 днями... Туда удобно было добавлять новый материал чтобы все в одном месте было.

Raycasting прогрессирует!



>>> maze_5.rar <<<

Подправил многопоточность: на моем пк +20 fps прирост.

Добавил текстуры. Вообще они там и так были, но небыло загрузчика для них. Я написал свой для bmp. Свой писал потому что мне нужен был определенный контроль при переводе из DIP в DDB формат, так как есть определенные особенности рендера. Загрузчик пока читает bmp с заголовком в 54 байта (те что стандартные из пеинта вобщем), остальные варианты если нужны будут потом добавлю. Фильтр для текстуры пока nearest, чуть позже попробую bilinear - есть вероятность что в софтваре уже не потянет.

Сделал разрешение 1280х720 и ограниение в 30 fps, чтобы фреймрейт не скакал. Для софварного рендера это очень даже неплохо имхо, тем более что дальше графика еще будет нагружаться.

Сделал чуток плавней управление.

mr.DIMAS 01.10.2013 00:13

Ответ: raycasting
 
Вложений: 1
Скорость рендера стабильная, и практически не зависит от размера текстуры - я уменьшил размер текстуры в 2 раза и FPS все равно 31. Что круто.

Двигаясь вплотную по стенке вызел баг. Второй раз пошел по тому же самому месту - баг не вылез. Скрин в аттаче.

Samodelkin 01.10.2013 20:48

Ответ: raycasting
 
Цитата:

Двигаясь вплотную по стенке вызел баг.
Да у меня тоже самое. Пока добавил костыль - если возникнет баг то на секунду пропадет изображение, но игра не вылетет. Причина же где то в недрах алгоритмов расчета бросания лучей - они иногда странные координаты пересечения со стенами возвращают, возможно последтвия округления и преобразования из одного типа в другой. Сейчас буду целиком на float переводить все расчеты, потому что нет смысла на современных цп делать только целочисленные вычисления.

Кстати странная вещь - в mingw 4.7.2 неработают атрибуты:
Код:

struct A { char a; char b; ... } __attribute__( __aligned( 1 ) );
struct B { char a; char b; ... } __attribute__( __packed__ );

Эти структуры будут по прежнему выравниваться по 4 байта...
Пришлось сделать так:
Код:

#pragma pack( push, 1 )
struct C { char a; char b; ... };
#pragma pack( pop )

Хотя вроде раньше на более старых версиях mingw атрибуты вроде бы работали, я помню ими пользовался когда-то.

Samodelkin 14.10.2013 00:45

Ответ: 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)

Arton 14.10.2013 02:29

Ответ: raycasting
 
Ёпт!
Так и должно быть???



Фтопку такую постобработку!

mr.DIMAS 14.10.2013 16:52

Ответ: raycasting
 
Круто! Походив 5 минут по лабиринту не вылезло ни единого бага, что круто. В качестве постэффекта лучше сделать легкий шум, чем кадровую развертку. Работает всё шустро. Среднее фпс - 55. А текущее иногда проваливается до 47.

Samodelkin 15.10.2013 00:30

Ответ: raycasting
 
Цитата:

Ёпт!
Так и должно быть???
2Arton Может тебе просто графика в старых играх вообще не нравится?

Так или иначе, рейкастинг был сделан для игр своего времени и поэтому я пытаюсь стилизовать картинку так чтобы это выглядело как старый ЭЛТ монитор или телевизор, с низким разрешением.

Попробуй тогда в демке ниже сам понастраивать разные комбо постэффектов.

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 файл.

Arton 15.10.2013 18:09

Ответ: raycasting
 
Цитата:

Сообщение от Samodelkin (Сообщение 268792)
2Arton Может тебе просто графика в старых играх вообще не нравится?

Так или иначе, рейкастинг был сделан для игр своего времени и поэтому я пытаюсь стилизовать картинку так чтобы это выглядело как старый ЭЛТ монитор или телевизор, с низким разрешением.

Попробуй тогда в демке ниже сам понастраивать разные комбо постэффектов.

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 файл.

Причём тут нравится не нравится. Эффект развёртки всё портит! ИМХО

FPS выше 19 не поднимается :(

ЦП хороший - AMD FX-6100, 3,3 ГГц

Последний пример хорошо смотрится, вариант по умолчанию понравился, молодец, продолжай в том же духе :super:

P. S. Обзор мышью будешь делать??

Samodelkin 15.10.2013 18:51

Ответ: raycasting
 
Цитата:

Сообщение от Arton
FPS выше 19 не поднимается

Цитата:

Сообщение от Samodelkin
Сейчас я не занимался их оптимизацией, поэтому данная версия довольно медленная.

Как раз сейчас буду оптимизировать.
Цитата:

Сообщение от Arton
P. S. Обзор мышью будешь делать??

А что она у тебя не работает?

Движение по вертикали чуть позже добавлю - там не все так просто - возможности рейкастинга пока не дают камеру вверх/вниз поварачивать.

Arton 15.10.2013 21:31

Ответ: raycasting
 
Цитата:

Сообщение от Samodelkin (Сообщение 268819)
А что она у тебя не работает?

Движение по вертикали чуть позже добавлю - там не все так просто - возможности рейкастинга пока не дают камеру вверх/вниз поварачивать.

Об этом я и говорил, ещё в первом думе можно было осматриваться мышкой.

Samodelkin 21.10.2013 01:54

Ответ: 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-реализация некоторых стандартных функций. Так что по возможности буду их убирать из кода и обходиться своими.

Цитата:

Управление:
1 - вкл/выкл эффект xray (хаотичные белые точки, не путать с шумом).
2 - вкл/выкл эффект кадровой развертки (его нужно видеть в движении, от скринов толку мало).
3 - переключение функции тумана (ничего|темнота|туман).
4 - вкл/выкл затенение по углам.
5 - вкл/выкл шум.
6 - переключение цветовых фильтров (обычный|черно-белый|сепия).
7 - вкл/выкл билинейную фильтрацию (она вообще какая то плохая, видимо я накосячил где-то в ее логике - не так хорошо семплы смешивает, потом перепроверю).
8 - поставить ограничение в 30fps.
9 - поставить ограничение в 60fps.
0 - неограниченный fps.
Теперь на цифре 6 к тем что уже были добавлен эффект "RGB расслоение", а + и - можно задавать силу эффекта, который в данный момент выбран цифрой 6.
Размытие по краям линзы включено все время.

mr.DIMAS 21.10.2013 09:07

Ответ: raycasting
 
Все работает. Багов не замечено. Возможно ли при рейкастинге сделать мипфильтрацию? А то аж рябит в глазах от выборки пикселей.

ФПС при одном эффекте мыла по краям - среднее 27
ФПС при всех включенных эффектах - 22 ( тоже среднее ).

Samodelkin 21.10.2013 23:03

Ответ: raycasting
 
Цитата:

Сообщение от mr.DIMAS
Возможно ли при рейкастинге сделать мипфильтрацию? А то аж рябит в глазах от выборки пикселей.

На самом деле проблема случайных пикселей (ряби текстур) должна решаться комплексным подходом с помощью MIP-mapping и анизотропной фильтрации. Один только mipmapping не решает проблему с текстурами на поверхностях, которые находятся под острым углом к вектору направления обзора. Потому что на большом расстоянии разрешение подходящей mip текстуры поперек вектора обзора будет на много выше чем вдоль вектора обзора и невозможно будет подобрать оптимальную mip текстуру. Здесь нужна анизотропная фильтрация, которая сначала подбирает нужную mip текстуру поперек вектора направления обзора, а затем делает несколько выборок вдоль и усредняет результат. Но именно анизотропная фильтрация очень требовательна к пропускной способности памяти, что может сильно перегружать RAM, и так загруженную работой с фрейбуферами.

Однако я точно не уверен, поэтому попробовать нужно. Но все же надо подумать и об альтернативных вариантах, может быть есть какие то варианты процедурной обработки или генерации текстур, промежуточные форматы хранения или что то в этом роде, не создающие большой трафик в памяти.

Третий вариант - это просто сделать правильные текстуры, в которых впринципе не будет такого большого контраста текселей. Или например сделать специальную mip фильтрацию (на стадии загрузки или даже сохранения текстуры в редакторе), которая в каждой следующей уменьшеной копии текстуры убирает сильно выделяющиеся по контрасту текселы, в таком случае можно обойтись mip-mapping'ом с обычным nearest (или bilinear) фильтром.

Samodelkin 27.10.2013 01:52

Ответ: 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 уровни в линейной зависимости от расстояния.

mr.DIMAS 27.10.2013 21:45

Ответ: raycasting
 
Среднее ФПС со стандартным набором эффектов - 44.
Со всеми включёнными - 42.
Графон стал лучше. С мипами не так сильно рябит. Но без тумана текстура вообще исчезает вдали - будто мип 1х1.
Работает шустро.

Samodelkin 27.10.2013 22:02

Ответ: raycasting
 
maze_6_12.rar


Цитата:

Но без тумана текстура вообще исчезает вдали - будто мип 1х1.
Поправил.
Вывел более менее оптимальную формулу расчета мип-уровней:
Код:

twoTanAlpha = 2.0f * tan( fieldOfViewInRad / 2.0f );
fbRealWidth = rayLen * twoTanAlpha * factor;
pixSize = fbRealWidth / scrWidth;
texSize = objWidth / texWidth;
lv = ceil( sqrt( pixSize / texSize ) ) - 1.0f;
// rayLen - длина луча.
// scrWidth - ширина экрана в пикселях.
// objWidth - ширина объекта с текстурой (в мировых единицах измерения).
// texWidth - ширина текстуры в текселях.
// fieldOfView - угол обзора в радианах.

Однако всеравно приходится выбирать баланс с помощью коэффициента factor между текстурами которые ложаться на сурфейсы параллельные плоскости экрана и текстурами которые ложаться на сурфейсы под большим углом к плоскости экрана. Другими словами либо видна размытость стен, либо рябь на земле и потолке.

Вот, анизотропную фильтрацию пока сделать вообще не удасться - нехватает данных о положении сурфейса во время процесса выборки текстур. Нужно конвеер рендера расширять. Так что пока всё.

mr.DIMAS 28.10.2013 00:01

Ответ: raycasting
 
Стало намного лучше.

SIMD будешь использовать?

Samodelkin 28.10.2013 01:29

Ответ: raycasting
 
Сейчас я уже с ключом sse компилирую, только толку от него пока мало - нужно правильные циклы писать чтобы автовекторизатор срабатывал. Так что да нужно вручную ассемблировать. Сначала буду матлибу переписывать c simd, а потом рендер. Если я правильно понимаю то в 64 битном режиме доступно 16 xmm регистров, что значительно должно повысить производительность. Но этим я и ограничусь, avx не буду делать, да и железки у меня такой нет. Потом буду смотреть в сторону gpgpu.

Arton 28.10.2013 09:58

Ответ: raycasting
 
Цитата:

Сообщение от Samodelkin (Сообщение 269398)
maze_6_12.rar



Поправил.
Вывел более менее оптимальную формулу расчета мип-уровней:
Код:

twoTanAlpha = 2.0f * tan( fieldOfViewInRad / 2.0f );
fbRealWidth = rayLen * twoTanAlpha * factor;
pixSize = fbRealWidth / scrWidth;
texSize = objWidth / texWidth;
lv = ceil( sqrt( pixSize / texSize ) ) - 1.0f;
// rayLen - длина луча.
// scrWidth - ширина экрана в пикселях.
// objWidth - ширина объекта с текстурой (в мировых единицах измерения).
// texWidth - ширина текстуры в текселях.
// fieldOfView - угол обзора в радианах.

Однако всеравно приходится выбирать баланс с помощью коэффициента factor между текстурами которые ложаться на сурфейсы параллельные плоскости экрана и текстурами которые ложаться на сурфейсы под большим углом к плоскости экрана. Другими словами либо видна размытость стен, либо рябь на земле и потолке.

Вот, анизотропную фильтрацию пока сделать вообще не удасться - нехватает данных о положении сурфейса во время процесса выборки текстур. Нужно конвеер рендера расширять. Так что пока всё.

Классно выглядит! :super:

FPS max. - 15, min. - 13

Стерео эффект пока что не очень, может быть из-за чёрных полосок сверху и снизу экрана, или нечёткости контуров.
Слева экрана, артефактная красная полоса, в стерео очках даёт странный эффект - как будто слева очень узкая, дополнительная камера.

Samodelkin 28.10.2013 17:46

Ответ: raycasting
 
Цитата:

Сообщение от Arton
Стерео эффект пока что не очень

Там его и нет, это все твое воображение.

Однако идея хорошая. Ты имеешь ввиду анаглифные очки? С ними можно попробовать поэкспериментировать. Вообще я сам не очень одобряю эти очки, у них и качество посредственное и пускать два разных цветовых канала в каждый глаз это издевательство. Но в целом опробовать стерео механику в широком смысле слова было бы неплохо для рендера. Как нибудь займусь этим.

Насчет того эффекта что ты принял за стерео - его механика проще: изображение раскладывается на 3 составляющии, красное, зеленое и синие. Затем красное и синие сдвигаются вправо и влево относительно зеленого соотвественно, и немного искажаются по горизонтали, с помощью смещения. Затем 3 составляющии снова соединяются в одно изображение. То что это внешне напоминает стерео - просто совпадение, я и не думал о нем когда делал этот эффект.

Цитата:

Сообщение от Arton
FPS max. - 15, min. - 13

Сей факт меня печалит...
Я пробовал на стареньком ноуте с процем DualCore 2ГГц - там до 20 fps, на i7-930 - 55-60. У тебя нет возможности Linux версию протестировать? И кстати какая у тебя память (сколько каналов, тип и частота)?

maze_6_13.tar.7z (Linux)

Arton 28.10.2013 21:11

Ответ: raycasting
 
Цитата:

Сообщение от Samodelkin (Сообщение 269415)
Там его и нет, это все твое воображение.

Однако идея хорошая. Ты имеешь ввиду анаглифные очки? С ними можно попробовать поэкспериментировать. Вообще я сам не очень одобряю эти очки, у них и качество посредственное и пускать два разных цветовых канала в каждый глаз это издевательство. Но в целом опробовать стерео механику в широком смысле слова было бы неплохо для рендера. Как нибудь займусь этим.

Насчет того эффекта что ты принял за стерео - его механика проще: изображение раскладывается на 3 составляющии, красное, зеленое и синие. Затем красное и синие сдвигаются вправо и влево относительно зеленого соотвественно, и немного искажаются по горизонтали, с помощью смещения. Затем 3 составляющии снова соединяются в одно изображение. То что это внешне напоминает стерео - просто совпадение, я и не думал о нем когда делал этот эффект.

Моё воображение... +_+

А ведь почти получилось :)


Цитата:

Сей факт меня печалит...
Я пробовал на стареньком ноуте с процем DualCore 2ГГц - там до 20 fps, на i7-930 - 55-60. У тебя нет возможности Linux версию протестировать? И кстати какая у тебя память (сколько каналов, тип и частота)?

maze_6_13.tar.7z (Linux)
Вох! Внезапно он у меня есть, убунта в смысле, но протестирую позже, т. к. не знаю\не помню как его включать и что там :-)

DDR 3 - 1333 - 4Гб - одна планка

Samodelkin 28.10.2013 23:26

Ответ: raycasting
 
Цитата:

Сообщение от Arton
Вох! Внезапно он у меня есть, убунта в смысле, но протестирую позже, т. к. не знаю\не помню как его включать и что там

DDR 3 - 1333 - 4Гб - одна планка

Там через менеджер пакетов или центр приложений нужно поставить gcc и g++ компиляторы и sdl 1.2. Это нужно для рантайм библиотек. Для линуха я не комплектую приложения сопутствующими .so файлами - их правильней хранить в специальной отдельной папке. Тест, особенно в окне лучше запускать из командной строки - тогда в нее же будет fps выводиться (консольное окно само не откроется как в windows).

Вполе возможно что медленно так из-за памяти. Так что буду пробовать еще снижать трафик в памяти. Я думаю на памяти надо даже больше сосредоточиться чем на процессоре.

Я кстати не знаю причины почему у тебя одна планка, но это не рационально. Для твоего процессора оптимальная память раза в 3 быстрей должна быть. У тебя же наверняка трехканальная передача данных поддерживается или что-то в этом роде. Еще 2 планки аналогичные поставь.

alko 23.12.2013 12:51

Ответ: raycasting
 
Надеюсь автор топика не будет против, если я продолжу тему по иному рейкаст-двигателю (http://lodev.org/cgtutor/raycasting2.html)
Пробовал заделать пол и потолок градиентом (пикча) прирост производительноти процентов, эдак, на 50...75. Но всё равно отстойно смотрится.
Замена double на float не привнесла абсолютно никаких изменений. Всё такой же адово низкий показатель fps. (при отрисовке текстур пола и потолка на разрешении 1366*768 и частоте проца 2.2 ГГц выдаёт 12 кадров пер секонд)

И ещё, как поменять в этом движке высоту положения камеры ? Там надо отдельно менять какие-то значения в цикле рендера пола, цикле стен и спрайтов.

alko 23.12.2013 13:39

Ответ: raycasting
 
В этом участке я максимум что осилил, так это вынести пару арифметических операций за тело цикла.
Код:

  int dd=h * 128 ;
      int dd1=lineHeight * 128;
      for(int y = drawStart; y < drawEnd; y+=2)
      {
        int d = y * 256 - dd+dd1; //256 and 128 factors to avoid floats
        int texY = ((d * texHeight) / lineHeight) / 256;
        int color = texture[texNum][texWidth * texY + texX];
        if(side == 1) color = (color >> 1) & 8355711;
        buffer[x][y] = color; 
      }


alko 23.12.2013 13:40

Ответ: raycasting
 
Нужно избавиться от умножения. До тела цикла вычислить константу, а затем вычислять d+=const.
то же касается и TexY.
А вообще лучше конечно было бы асм-всавками воспользоваться, но хз, как потом результат вычислений занести из регистров в определённую переменную...

Samodelkin 23.12.2013 18:02

Ответ: raycasting
 
Пока еще не разбирал этот двиг, но некоторые алгоритмы рейкастинга (и в моем движке так тоже было в начале) могут не предусмативать настройку высоты камеры вообще - опять же этими апроксимациями можно сократить кол-во вычислений.

1366х768 и при этом собираешься делать ретро игру под pentium mmx с выборкой без сглаживания и целочисленными вычислениями? Так не выйдет. Определись - либо делаешь всё как в старых играх, в том числе 320х200 (или 240), либо делаешь нормально под современные железо и пользуешься текстурными фильтрами и прочими вещами которые хоть как то облагораживают изображения для более менее высокого разрешения. Иначе будет выглядеть трешево.

Ок, можешь в сюда постить - будет общая тема рейкастинга.

upd:
Максимум что можно сделать это рендерить в буфер 320x240, а затем аппаратно перерисовать в более большой, например 1920х1080, потому что не все мониторы могут растянуть такое низкое разрешение на полный экран, только перерисовывать без сглаживания, либо с каким то дополнительным шейдерным эффектом, как например старые ЭЛТ мониторы - они не могли четко нарисовать пиксель как LCD монитор.

alko 23.12.2013 19:47

Ответ: raycasting
 
Цитата:

Сообщение от Samodelkin (Сообщение 271817)

1366х768 и при этом собираешься делать ретро игру под pentium mmx с выборкой без сглаживания и целочисленными вычислениями?

Та не. То я для примера привёл цифры.
так-то планирую хотя бы на 640*480 ориентироваться. Дело в том, что на 640*480 этот движок тоже адски тормозит.
На моём пне MMX вполне шустро работает виндовый порт Дюка3д eduke32 на разрешении 800*600, на софтверном рендере, разумеется. А там графон огого, и динамические освещения, и разная высота стен, и альфаблендинг текстур, и анимация биллбордов и текстур, та и тайлинг текстур нехилый такой, и наклонные поверхности по всем осям, и ещё много чего.

Та и не только рейкаст, даже полигнональные игры, типа NFS-1 или MDK на софтверном двигателе летают на моем MMX'e. А вот игры с коррекцией перспективы уже малость лажают (тот же quake 1-2, на разрешениях 640*480 проседают по фреймрейту, так как коррекция перспективы довольно ресурсоёмка. Хотя меш моделей *.md1 *.md2 с искажённым наложением текстур)... Но это уже малость оффтоп.

alko 23.12.2013 19:51

Ответ: raycasting
 
Вот сейчас интересует, как же запилить ассемблерную вставку в коде-блоксе (mingw gcc win32).
Чтоб произвести арифметические вычисления, и результат из регистра поместить в какую-либо переменную.

Samodelkin 23.12.2013 20:40

Ответ: raycasting
 
В gcc inline assembler есть два наречия at&t и intel - intel признано более удобным, но можешь по любому писать.

howto для at&t

Для intel все тоже самое только нужно ".intel_syntax;" добавить первой строкой ну и соответсвенно на другом наречии дальше писать, например как тут.

Здесь можно смотреть сами инструкции. Необязательно читать всё - тебе надо 5.5, а также часть 9 про mmx, части 10 и 11 про sse и sse2, ну и дальше если тебе нужно больше расширений.

Однако многие предпочитают интринсики ассемблерным вставкам, они чуть медленей, но всеравно в разы быстрей чем без них, но я их не использовал, так что пусть ктонибудь другой ответит кто знает.

alko 26.12.2013 17:47

Ответ: raycasting
 
За счёт побитного скролла fps увеличился с 50-ти до 62-ух (это если стенку в вплотную разглядывать... При разглядывании спрайтов fps почти вдвое меньше становится)
Код:

    int d1=lineHeight * 128;
      int d2=h * 128;
      for(int y = drawStart; y < drawEnd; y++)
      {
        int d = y *256 - d2 + d1;  //256 and 128 factors to avoid floats
        int texY = ((d * texHeight) / lineHeight) >>8;
        Uint32 color =texture[texNum][texWidth * texY + texX];
        if(side == 1) color = (color >> 1) & 8355711;
        buffer[x][y] = color;
            }

Если " у*256 " заменить на " y<<8 " - там происходит сатана с текстурами.

Samodelkin 26.12.2013 23:00

Ответ: raycasting
 
Код:

int d = ( y  << 8 )  - d2 + d1;
В скобки обводил? У сдвига приоритет ниже чем у сложения/вычитания.

alko 28.12.2013 00:09

Ответ: raycasting
 
Есть идеи, как в том сорсе осуществить поворот стен хотя бы кратный 45-ти градусам ?
В смысле не строго север\юг\запад\восток, а хотя бы так, как в zero tolerance на мегадрайве.

Samodelkin 28.12.2013 01:25

Ответ: raycasting
 
В данном подходе никаких проблем нет. Главное нужно понимать что задачу можно разделить на две составляющие - первая нахождение пересечения луча со стеной в 2д, вторая уже на основе полученной длины луча мы строим слайс с учетом высоты стены. Поэтому в первой составляющей мы можем рассчитать стену как угодно, а для второй аргументами будут являться длина луча и высота стены. Так что считать только прямоугольные стены совсем не обязательно. Например мы можем рисовать произвольной кривизны линии изображающие стены и если у нас будет алгоритм, который сможет найти пересечения луча и этих линий то мы найдем длину луча, которую и передадим во вторую составляющую алгоритма. Однако не стоит забывать что в играх кроме графики есть и физика, и например рассчитывать коллизии игрока со стенами произвольной кривизны будет сложно. Я думаю самым оптимальным выбором будут стены составленные из отрезков, которые могут находиться под произвольным углом (а не только 45 градусов). Таким образом задача сводится к нахождению пересечения луча и отрезка.

Вроде когда я смотрел коды того движка, там карта задавалась прямо в коде в виде двумерного массива. С таким форматом ничего не выйдет - нужно разработать другой формат, который хранит данные о карте в форме отрезков. Возможно для удобства потребуется редактор таких карт.

alko 28.12.2013 03:08

Ответ: raycasting
 
Цитата:

Сообщение от Samodelkin (Сообщение 271989)
С таким форматом ничего не выйдет - нужно разработать другой формат, который хранит данные о карте в форме отрезков. Возможно для удобства потребуется редактор таких карт.

в zero tolerance тоже 2д-массив карты, просто каждый элемент массива может принимать значения от 00 до FF... но кривизна не произвольная.




Samodelkin 28.12.2013 18:37

Ответ: raycasting
 
Я думал над таким решением и мне кажется оно будет со временем усложнять код, ведь здесь используется ветвление - на каждый случай есть своя реализация как его обсчитать. И чем больше будет вариантов стен и их углов (а также еще и текстур или еще чего-то) - тем более запутанный будет становиться код.

Поэтому я считаю что нужно использовать обобщенный алгоритм пересечения луча и отрезков как я предложил выше.

Конечно ты можешь хранить карту в таком массиве, а перед расчетом лучей преобразовать ее в отрезки, но зачем лишние конвертации если можно сразу хранить и редактировать в отрезках.

Если ты уверен на 100%, что кроме стен под углом 45 тебе ничего не понадобиться, то можешь остановиться на этом варианте.

В любом случае тебе придется делать редактор, потому что править такой массив данных прямо в коде весьма утомительно.

alko 28.12.2013 22:41

Ответ: raycasting
 
Цитата:

Если ты уверен на 100%, что кроме стен под углом 45 тебе ничего не понадобиться, то можешь остановиться на этом варианте.
Да, уверен.

Цитата:

В любом случае тебе придется делать редактор, потому что править такой массив данных прямо в коде весьма утомительно.
Сделать такой редактор не проблема... Но нужно спрва разобраться с этим движком. Пол и потолок всё-таки пришлось убрать. Ещё сделаю где-то на 1/4 экрана интерфейс, заодно меньше пикселей придётся обновлять на экране.

Щас не могу разобраться, как изменить точку схода перспективы, то есть поставить камеру выше. В процедуре рисования спрайтов это задаётся отдельным дефайном, а как быть со стенками не знаю.

alko 29.12.2013 00:55

Ответ: raycasting
 
Samodelkin, видал в твоём проЭкте сделана фишка "затенение в глубину" (или туман, если инверсия)

Как сделать это в том движке, на который я глаз положил ?
Там в зависимости от переменной drawStart нужно произвести операцию тонирования со столбцом пикселей текстуры.

Samodelkin 29.12.2013 03:05

Ответ: raycasting
 
К сожалению всё руки не доходят посмотреть тот движок, хотя я заметил там несколько классных фич которые надо бы перенять.

Вот мой код:
Код:

/*
================================================================================
rc2d::FogCompute
================================================================================
*/
auto rc::rc2d::FogCompute( Pyramid::Vector3f& outColor, const Pyramid::Vector3f& inColor, float rayLen ) const noexcept ->void {
    if ( rayLen > desc.fogMaxClamp ) {
        rayLen = desc.fogMaxClamp;
    } else if ( rayLen < desc.fogMinClamp ) {
        rayLen = desc.fogMinClamp;
    }
    float fogValue = ( rayLen - desc.fogMinClamp ) / ( desc.fogMaxClamp - desc.fogMinClamp );
    fogValue *= desc.fogFactor;
    outColor = inColor + ( desc.fogColor * fogValue );
    outColor.Saturate();
}

Сразу замечу что представление цвета я храню в 3д векторе типа float и уже непосредственно при записи в пиксел я конвертирую в uint32. В твоём случае (для возможности игры на mmx и более старых машинах) так лучше не делать.

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.

alko 29.12.2013 13:29

Ответ: raycasting
 
:shit: всё очень печально :shit:
Запускал только-что на пентиуме вариант без пола и потолка - 4 кадра в секунду (если в обзор попадает спрайт - 3 кадра)
Комп как бы намекает, что это всё плохая затея.

Samodelkin 29.12.2013 17:26

Ответ: raycasting
 
Цитата:

Сообщение от alko (Сообщение 272017)
:shit: всё очень печально :shit:
Запускал только-что на пентиуме вариант без пола и потолка - 4 кадра в секунду (если в обзор попадает спрайт - 3 кадра)
Комп как бы намекает, что это всё плохая затея.

Ну как я уже выше написал мой код расчитан на новое железо и хорошую графику :)

Попробуй вот так (код я не проверял и не компилировал):
Код:

uint32_t fog( const uint32_t inColor, const uint32_t rayLen, const uint8_t factor ) {
        uint16_t color[ 3 ];
        color[ 0 ] = ( char )( inColor >> 8 );
        color[ 1 ] = ( char )( inColor >> 16 );
        color[ 2 ] = ( char )( inColor >> 24 );

        if ( rayLen < ( 256 << factor ) - 256 ) {
                color[ 0 ] += ( rayLen >> factor );
                color[ 1 ] += ( rayLen >> factor );
                color[ 2 ] += ( rayLen >> factor );
                if ( color[ 0 ] >= 256 ) color[ 0 ] = 255;
                if ( color[ 1 ] >= 256 ) color[ 1 ] = 255;
                if ( color[ 2 ] >= 256 ) color[ 2 ] = 255;
                uint32_t outColor = 0;
                outColor |= ( ( ( char )color[ 0 ] ) >> 8 );
                outColor |= ( ( ( char )color[ 1 ] ) >> 16 );
                outColor |= ( ( ( char )color[ 2 ] ) >> 24 );
                return outColor;
        } else {
                return 0xffffff00;
        }
}

factor сначала задавай 0, а потом 1 и выше до 7 включительно.

Тут главное не напутать с форматом цвета. Например согласно little endian 4 байтное число 0xaabbccdd на самом деле записывается в память в обратном порядке - ddccbbaa. Таким образом при преобразовании типа, например в 2 байтное число оно превратится в ddcc, то есть 0xccdd если в нормальном представлении. Так что я код написал что у тебя в памяти идет ARGB в таком порядке, то есть в 4 байтном числе это 0xBGRA. Однако операторы сдвига как раз работают с числами в нормальном представлении, то есть для числа 0xaabbccdd если применить >> 24 то будет ожидаемое aa, а не какое то значине справа от числа, так что я просто написал чтобы было понятно как работает внутри :crazy:

Да кстати расширение mmx (а также sse в более новых машинах) может работать с упакованными значениями - и видимо они здесь как раз кстати подойдут, но я пока сам так еще не делал.

alko 29.12.2013 19:34

Ответ: raycasting
 
Цитата:

Сообщение от alko (Сообщение 272017)
Запускал только-что на пентиуме вариант без пола и потолка - 4 кадра в секунду (если в обзор попадает спрайт - 3 кадра).

Это даже без тонирования в глубину.

alko 29.12.2013 20:07

Ответ: raycasting
 
Дело не в рейкастинге... Дело в самом quickCG.
Попробовал написать элементарное Хыллоу Ворлд, где будет закрашиваться экран и выводится отмасштабированный в два раза спрайт. И таки шо ви думаете? Эта хрень рисуется тоже 4 кадра пер секонд. (на пентиуме, разумеется... На моём ноуте 150 кадров в секунду)

Код:

#ifdef __cplusplus
    #include <cstdlib>
#else
    #include <stdlib.h>
#endif

#include <SDL.h>

#include <cmath>
#include <string>
#include <vector>
#include <iostream>

#include "quickcg.h"
using namespace QuickCG;

#define screenWidth 800
#define screenHeight 600

struct Sprite
{
  float x;
  float y;
  int texture;
};

Sprite sprite[50];

int main(int argc, char *argv[])
{
    double time = 0;
  double oldTime = 0;
    std::vector<Uint32> texture[11];
    unsigned long tw, th;
    Uint32 buffer[screenWidth][screenHeight];
    loadImage(texture[0], tw, th, "rc/gg1.png");

    screen(800, 600, 1, "Metallix zone");

    while(!done())
    {
        int i=0;
  for(int xx=0;xx<800;xx++)
  for(int yy=0;yy<600;yy++)
  buffer[xx][yy]= 0x0f00f0;
        int x=rand()%500,y=rand()%100;
        for(int xx=0;xx<128;xx++){

        for(int yy=0;yy<64;yy++){
        Uint32 color = texture[0][i];
        i++;

        if(color!=0xffffffff)for(int i=0; i<2 ; i++)
        for(int k=0; k<2 ; k++)
        buffer[yy*2+i+x][xx*2+k+y]=color<<8;}
        }
        drawBuffer(buffer[0]);

              oldTime = time;
    time = getTicks();
    double frameTime = (time - oldTime) / 1000.0;
    print(1.0 / frameTime);
        redraw();
    }
}


alko 29.12.2013 20:18

Ответ: raycasting
 
И тут дело даже не в выборке пикселей из png-картинки.
Тут дело в выводе пикселя, каким бы он ни был.
Там даже обычное заполнение сплошным цветом - 4-5 кадров в секунду.

Samodelkin 29.12.2013 22:45

Ответ: raycasting
 
В топку этот quickCG значит. Зачем он нужен? Я у себя рендер делал целиком сам, затем готовый фрейм с помощью SDL 1.2 выводил на экран. Еще лучше заюзать OpenGL или D3D напрямую, даже если не использовать аппаратные плюшки, я просто не в курсе как делали во времена MMX, возможно напрямую VGA юзали. Через чего кстати видеокарта подключена на твоем компе? Может там шина PCI или AGP старая и медленная и менять пиксели из системы очень медленно? Либо алгоритм не самый лучший, например при программировании VGA напрямую есть режим отображения видеопамяти на системную - я так делал когда пробовал написать бутлоадер с графическим интерфейсом через графику BIOS.

Тут тебе видимо тоже рекомендуют на шейдеры перенести :)

Короче просто попробуй сделать хело ворлд вместе с SDL и посмотреть как на нем будет. Если медленно тогда придется искать другие способы взаимодействия с видеокартой.

alko 29.12.2013 23:21

Ответ: raycasting
 
Цитата:

Через чего кстати видеокарта подключена на твоем компе? Может там шина PCI или AGP старая и медленная и менять пиксели из системы очень медленно?
Видяха PCI ati Rage II. Из api поддерживается только DX 5.0 , и то - для галочки. Tomb Raider на софтверном рендеринге ЦП и то быстрее рисует, нежели та видяха на DX. Она очень медленно текстурирует. А если кубик без текстур вращать - то она быстрее это делает, чем проц.

Цитата:

Тут тебе видимо тоже рекомендуют на шейдеры перенести
Ага. Всех уже задолбал этим рейкастингом.

А какие есть ещё API помимо SDL, чтоб шустро выводить пиксель на экран при помощи ЦП ?

Цитата:

Короче просто попробуй сделать хело ворлд вместе с SDL
quickCG - это набор функций, которые юзают непосредственно SDL. Только якобы быстрее... А на деле - эххх....
http://lodev.org/cgtutor/quickcg.html

Samodelkin 30.12.2013 02:29

Ответ: raycasting
 
Подожди, тут нужно структурировать:

SDL является прослойкой между приложением и directx для windows или xlib|opengl для linux. Поэтому в твоем случае directx юзается всеравно. quickcg получается еще одной надстройкой над sdl, и если даже он использует sdl каким то хитрым способом, то это в любом случае медленнее чем dx. поэтому если у тебя на видеокарте медленный dx то у тебя sdl быстрей не будет.

Теперь о софтварном рендере. Монитор у тебя всеравно подключен к видеокарте и она в любом случае принимает участие в формировании изображения. Видеокарта соеденина с матплатой посредством agp, pci или pci-express (что там на mmx было?) и это обычно является самым узким местом. Преимущество аппаратного ускорения в том что все текстуры, вершинные буферы и прочая инфа один раз загружается в видеопамять (если не считать изменений и синхронизаций) и затем кадры формируются уже внутри видяхи не затрагивая шину разъема. В случае софтварного рендера у тебя кадр формируется в раме, и значит тебе нужно каждый раз новый кадр переправлять по разъему чтобы видяха его вывела на экран. вот. тут все решает размер этого кадра, то есть его разрешение, глубина цвета и прочие атрибуты.

Если же ты будешь прогать через vga напрямую то тебе даже не нужны ни ось, ни всякие gapi, то есть никакого оверхеда, а так как тебе нужно только копировать кадры из рамы в видяху, минимальных возможностей vga должно быть достаточно. Но там все через асм. И вобщем судя по твоим отчетам о скорости dx на старых компах, я еще больше убеждаюсь что игры тогда программировали именно так - напрямую, без юзания gapi.

alko 30.12.2013 13:47

Ответ: raycasting
 
Даже не знаю где бы инфу черпануть по перебросу содержимого системного ОЗУ в видео-память на асме. + инициализировать граф. режим надо.
На моём излюбленном спектруме это делалось 5-тью 6-тью инструкциями... IBM-PC куда сложнее в этом плане, при том что большинство инструкций - целые макрокоманды.

Более того, прежде чем перебрасывать содержимое оперы, надо как-то ещё туда и записать само изображение... Быть может SDL даже в буфер медленно записывает.

Хотя не. Кое-что нашёл по VGA-CGA-EGA. Читану на досуге.
http://www.codenet.ru/cat/Applicatio...ESA-Standarts/

Samodelkin 30.12.2013 21:55

Ответ: raycasting
 
В режиме VGA ничего перебрасывать не надо, точней там идет отображение адресного пространства, ты пишешь в определенные адреса как в обычное ОЗУ, а система сама перегоняет это в видеопамять.

Ты видимо неправильно SDL использовал. Нужно создать фрейм буфер в ОЗУ через обычный malloc например и обращаться к нему как к двумерному массиву:
Код:

uint32_t* buffer = ( uint32_t* )malloc( 320 * 240 * sizeof( uint32_t ) );
buffer[ 100 ][ 200 ] = 0xaabbccdd; // обращение как в 2д массиву (порядок: высота, ширина)
*( buffer + 100 * 320 + 201 ) = 0xaabbccdd; // обращение посредством адресной арифметики (тоже самое по сути)

И затем достаточно сделать только ОДИН вызов SDL чтобы он весь буфер скопировал в видеопамять и вывел на экран. Если ты будешь вызывать каждый раз чтобы записать по одному пикселу то конечно всё будет очень медленно.

Вот я у себя целый класс FrameBuffer сделал чтобы работать с фреймами внутри ОЗУ.

ЗЫ: Размеры массивов в С++ ограничены, поэтому именно через malloc / free лучше с буферами работать.

alko 31.12.2013 00:59

Ответ: raycasting
 
Цитата:

Нужно создать фрейм буфер в ОЗУ через обычный malloc например и обращаться к нему как к двумерному массиву:
В приведенном мною коде это есть.
Код:

Uint32 buffer[screenWidth][screenHeight];
Цитата:

затем достаточно сделать только ОДИН вызов SDL чтобы он весь буфер скопировал в видеопамять и вывел на экран.
Так опять же, это делает функция :
Код:

drawBuffer(buffer[0]);
Я в курсе, что после каждой записи пикселя в ОЗУ глупо выплёскивать всё это на экран, не дождавшись завершения обновления всей картинки.

alko 31.12.2013 01:11

Ответ: raycasting
 
Вложений: 1
"чистый" SDL , без quickCG тоже медленно рисует вроде бы.
Вот я когда-то давно клепал на чистом SDL движок (с рейкастингом он правда никак не связан, но рисует всё попиксельно). На пентиуме тоже дико лагает. На гигагерцах вполне нормально идёт.
Правда в этом моём движке проц шибко много ненужных вещей делает. Например , если спрайт находится за спрайтом, то невидимые зрителю пиксели он всё равно рисует.

Samodelkin 31.12.2013 01:27

Ответ: raycasting
 
Работает, немного глючит курсор когда ездит снизу, справа - он попадает в область где не очищается буфер. Также если уехать сильно влево/вправо то глючить начинает бекграунд. Также нету синхронизации по времени? Все спрайты я проезжаю за 2 сек.

alko 31.12.2013 11:16

Ответ: raycasting
 
Цитата:

Также нету синхронизации по времени? Все спрайты я проезжаю за 2 сек.
Пытался высчитывать дэльта-тайм между фреймами. Но он всё равно криво считается.

Цитата:

немного глючит курсор когда ездит снизу, справа - он попадает в область где не очищается буфер. Также если уехать сильно влево/вправо то глючить начинает бекграунд.
Знаю... То я так, эксперементировал с масштабированием спрайтов когда-то.


Часовой пояс GMT +4, время: 14:31.

vBulletin® Version 3.6.5.
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Перевод: zCarot