Демосцена.. на FreeBSD
Продолжаю разрывать границы воображения, пердаки и шаблоны. А то народ в ИТ совсем уже отупел от видеокурсов и обленился. Пройдет еще пару лет и считать столибком разучатся.
Кратко для тех кто не знает
Демосцена это было и есть круто. Наверное все топовые игровые движки и все компьютерные спецэффекты были сделаны (и делаются поныне) бывшими сценерами:
4players.de reported that "numerous" demo and intro programmers, artists, and musicians were employed in the games industry by 2007. Video game companies with demoscene members on staff included Digital Illusions, Starbreeze, Ascaron,[43] 49Games, Remedy, Techland, Lionhead Studios,[44] Bugbear, Digital Reality, Guerrilla Games, and Akella.[45]
The Tracker music which is part of Demoscene culture could be found in many Video games of the late 1990s and early 2000s, such as the Unreal, Unreal Tournament, Deus Ex, Crusader: No Remorse, One Must Fall: 2097, Jazz Jackrabbit and Uplink.[46]
Вообщем демосцена это про спецэффекты и преодоление — как впихнуть невпихуемое туда где ему не место, чтобы стало круто и все оху#ли.
Ниже несколько примеров для понимания что это такое.
fr-041: debris. by Farbrausch
Все что вы видите на видео делает «программулина» в 177 килобайт.
Это почти в 10 раз меньше размера 3.5 дюймовой дискеты, если кто-то еще помнит что сие такое.
Исходники тоже уже выложены, если кому вдруг интересно.
Lifeforce by Andromeda Software Development
Это уже большое демо — целых 26 Мегабайт!
Задумайтесь о смысле своей работы, собирая очередной гиговый билд, набитый всяким говном.
У группы еще очень крутой сайт с кучей других красивых демо, если будет мало.
heaven seven by Exceed
И снова 172кб бинарник рисует и поет всю эту красоту.
Craft by lft
Craft is a demo running on its own minimalistic demo platform. The demo platform is based on an ATmega88 microcontroller.
В видео в самом начале показывается как выглядит железка, на которой эта
После выкладывания статьи на ЛОРе, народ подкинул еще пару интересных вещей, которые просто необходимо упомянуть.
Dírojed by Řrřola
echo 'B013CD10C51F380F10276BDBE58A0F0209028FBFFE02483F4BE460FEC875E7C3' | xxd -r -p - dirojed.com dosbox dirojed.com
Hoody by Rgba
4кб бинарник генерирует вот такое:
Это не статичная картинка и не 3D-модель - это алгоритмы.
Вот тут алгоритм повторен в WebGL:
А это детальный пошаговый разбор алгоритма, от самого автора:
Круто, очень.
Вот тут лежит подборка других крутых демо, для дополнительного просмотра.
Даже просто участие в этом движе — однозначный показатель мастерства, уж молчу про призовые места.
Я к сожалению не дорос до демосцены, не мой уровень, поэтому на этом празднике хардкора — лишь зритель.
FreeBSD и демосцена
Как-то решил я вспомнить счастливое детство и полазить по сайтам сценеров — с удивлением обнаружил, что много кто выкладывает релизы демок под FreeBSD.
FreeBSD — мягко говоря не самая подходящая система для занятия оптимизированной графикой, поэтому это своего рода тоже показатель уровня мастерства и духа сцены: «жги так чтоб все ох#ели».
Вообщем ниже расскажу что из этого удалось собрать и запустить.
Тестовая машина — все тот же боевой некроноут Lenovo T440:
Загружен i915kms, xorg настроен через modesetting:
[alex@cruella ~]$ cat /usr/local/etc/X11/xorg.conf.d/20-intel.conf Section "Device" Identifier "Intel Graphics" Driver "modesetting" Option "DRI" "true" EndSection
Все демки по-умолчанию запускаются в полноэкранном режиме, но я запускал в окне (ключ -w) чтобы делать скриншоты.
Planet Hively by Illi Recentes ImperatoreS & Up Rough
Выглядит может и не так круто:
Но как говорится есть один нюанс:
#PLATFORM = os4 # PLATFORM = win32 # PLATFORM = linux # PLATFORM = aros # PLATFORM = aros64 # PLATFORM = ppc-aros # PLATFORM = morphos-cross # PLATFORM = beos # PLATFORM = ppc-beos-cross # PLATFORM = gp2x # PLATFORM = alpha-linux-cross # PLATFORM = ia64-linux-cross # PLATFORM = amd64-linux-cross # PLATFORM = s390-linux-cross # PLATFORM = s390x-linux-cross # PLATFORM = arm-linux-cross # PLATFORM = sparc-linux-cross # PLATFORM = psp # PLATFORM = hppa-linux-cross # PLATFORM = ppc-linux-cross # PLATFORM = m68k-linux-cross # PLATFORM = mips-linux-cross # PLATFORM = mipsel-linux-cross # PLATFORM = sh3-linux-cross # PLATFORM = sh4-linux-cross # PLATFORM = ppc64-linux-cross # PLATFORM = sparc64-linux-cross # PLATFORM = avr32-linux-cross # PLATFORM = bsdi # PLATFORM = qnx6 # PLATFORM = solaris # PLATFORM = skyos # PLATFORM = openserver5 # PLATFORM = openserver6 # PLATFORM = unixware7 # PLATFORM = mint PLATFORM = i386-freebsd7 # PLATFORM = amd64-freebsd7-cross # PLATFORM = sparc64-freebsd7-cross # PLATFORM = ia64-freebsd6-cross # PLATFORM = alpha-freebsd5-cross # PLATFORM = riscos-cross # PLATFORM = hppa-hpux # PLATFORM = ia64-hpux # PLATFORM = zaurus-cross # PLATFORM = syllable # PLATFORM = netbsd # PLATFORM = alpha-netbsd4-cross # PLATFORM = amd64-netbsd4-cross # PLATFORM = hppa-netbsd4-cross # PLATFORM = m68k-netbsd4-cross # PLATFORM = mipseb-netbsd4-cross # PLATFORM = mipsel-netbsd4-cross # PLATFORM = ns32k-netbsd2-cross # PLATFORM = ppc-netbsd4-cross # PLATFORM = sh3eb-netbsd4-cross # PLATFORM = sh3le-netbsd4-cross # PLATFORM = sh5le-netbsd3-cross # PLATFORM = sparc-netbsd4-cross # PLATFORM = sparc64-netbsd4-cross # PLATFORM = vax-netbsd4-cross # PLATFORM = arm-netbsd4-cross # PLATFORM = m68010-netbsd4-cross # PLATFORM = xbox # PLATFORM = i386-openbsd # PLATFORM = alpha-openbsd-cross # PLATFORM = amd64-openbsd-cross # PLATFORM = arm-openbsd-cross # PLATFORM = hppa-openbsd-cross # PLATFORM = ppc-openbsd-cross # PLATFORM = mips64-openbsd-cross # PLATFORM = sh4-openbsd-cross # PLATFORM = sparc64-openbsd-cross # PLATFORM = m68k-openbsd-cross # PLATFORM = sparc-openbsd-cross # PLATFORM = aix # PLATFORM = irix # PLATFORM = irix_marq # PLATFORM = pandora
Вообщем, если вы (как и я) думали, что чего-то понимаете в портировании и многоплатформенности — начинайте бухать с горя искать себе новую работу. Потому что такого я никогда в жизни не видел, не то чтобы уметь сделать.
Вот это же демо запущенное на Raspberry Pi:
Исходники и сборка
Исходники выложили относительно недавно, вот тут. Со сборкой есть ряд проблем.
Во-первых авторы забыли выложить часть ресурсов и при запуске демка будет ругаться. Вам нужно вытащить папку tunes из вот этого pull request и подложить в корень проекта.
Дальше нужно будет в файле makefile раскомментировать строку:
PLATFORM = i386-freebsd7
####### DEFAULT SETTINGS HERE ####### CFLAGS = -Wall -O2 LFLAGS = CC = gcc12 DEBUGLIB = TARGET = planethively FASTMATH = -ffast-math
Написано все на чистом Си, с использованием SDL. Ниже пара интересных приемов, найденных в исходнике.
Быстрое вычисление квадратного корня:
static inline int fastsqrt( int n ) { if( n > 32767 ) return sqrt( n ); return isqrt[n]; }
Генерация белого шума:
void hvl_GenWhiteNoise( int8 *buf, uint32 len ) { uint32 ays; ays = 0x41595321; do { uint16 ax, bx; int8 s; s = ays; if( ays & 0x100 ) { s = 0x80; if( (LONG)(ays & 0xffff) >= 0 ) s = 0x7f; } *buf++ = s; len--; ays = (ays >> 5) | (ays << 27); ays = (ays & 0xffffff00) | ((ays & 0xff) ^ 0x9a); bx = ays; ays = (ays << 2) | (ays >> 30); ax = ays; bx += ax; ax ^= bx; ays = (ays & 0xffff0000) | ax; ays = (ays >> 3) | (ays << 29); } while( len ); }
Chrysler by Fit [web] & Bandwagon [web]
Motorola Inside 2004, 1е место
Исходник лежит вот тут, несмотря на то что архив от 2009го года — все отлично собирается.
Количество поддерживаемых платформ:
Чтоб я так жил, как вы портируете вообщем.
На моей фре это выглядит вот так:
Сборка и исходники
Cобирается через gmake, нужно поправить Makefile, поставив СС=gcc12:
CC = gcc12 CFLAGS = -O2 -ffast-math `sdl-config --cflags` #LDFLAGS = `sdl-config --libs` -lm LDFLAGS = `sdl-config --static-libs` -lm OBJ = data.o kirjaimet2.o kokko.o maf.o main.o mosaic.o pallot.o plasma.o\ ratas.o stripes.o video.o cool_mzx/cool_mzx.a ...
Написано все на чистом Си, также с использованием SDL. Ниже некоторые интересные моменты в исходниках.
Заданная PI-константа для Амиги:
#ifdef AMIGA #define M_PI 3.1415927 #endif
Элегантный способ проверить правильность нескольких вызовов подряд:
int readall(void) { int val=0; val+=readfile("data/tehas2.mod",&musakki); val+=readfile("data/dd.raw",&dd); val+=readfile("data/na_eka.raw",&na_eka); val+=readfile("data/na_toka.raw",&na_toka); val+=readfile("data/onnettomuus.raw",&onnettomuus); val+=readfile("data/paa.raw",&paa); val+=readfile("data/siunaus.raw",&siunaus); val+=readfile("data/ukko.raw",&ukko); val+=readfile("data/ratas.raw",&ratas); val+=readfile("data/kooste.raw",&kooste); val+=readfile("data/chrysler.raw",&chrysler); return(val); }
if(readall()!=0) { printf("Problem loading datas\n"); return(0); }
src=frame[no]*40*200; dst =buffer; for (y=0; y<AH; y++) for (x=0; x<(AW/8); x++) { ip1=bitti_muunnos+video[src]*8; *dst++ = *ip1++; *dst++ = *ip1++; src++; }
Удачи разобраться со ссылочной логикой - именно тот случай когда "без поллитры никак".
Hex Pistols by Fit [web]
Motorola Inside 2005, 1е место, релиз на Амиге да.
Вот так выглядит запуск на фоне исходников демки:
Сборка и исходники
Исходники можно скачать вот тут. Для сборки надо опять заменить CC=gcc на CC=gcc12 в Makefile, все просто.
Снова чистый Си и SDL (в версии не для Амиги).
Чтение RGB цвета и упаковка его в одну переменную с побитовым сдвигом:
/* Background */ if(!strcmp("backcolr",str)) { fscanf(s,"%d%d%d",&r,&g,&b); cgm->back=(r<<16)+(g<<8)+b; }
Faemiyah [web] [demozoo] [glöplog]
Это целая группа, которая стабильно ваяет и выкладывает релизы под FreeBSD. Напрочь е#нутые финские товарищи, зацените сколько исходников.
Yog-Sothoth by Faemiyah
2е место на Assembly, 2013
К сожалению эта демка у меня так нормально и не заработала, что-то тонкое с видео.
Ghosts of Mars by Faemiyah
4е место на Assembly 2015
Картинка с ней как раз в заглавии статьи, выглядит эпично:
Сборка и исходники
Исходники вот тут.
Собирается оно уже по-современному — через cmake:
mkdir build cd build cmake ..
./ghosts_of_mars -w -r 800x600
Тут я указываю оконный режим -w и разрешение -r 800x600
Исходники уже на нескольких языках: C, C++ и специальный скрипт на Python для минимизации.
Графика все также на SDL, но уже используются шейдеры и Boost.
Вообщем все сложнее и серьезнее.
Но проблемы те же — снова кастомный random:
/// More random random. /// /// It's better to discard a few bottom-most bits to achieve better randomness. /// /// \param op Modulator for random. /// \return Random value in range [0, op[. static int irand(int op) { return (dnload_rand() >> 4) % op; }
Отладочные блоки на макросах по хардкору:
#if 1 { const float mul = 65535.0f / largest; for(unsigned ii = 0; (IMAGE_SIDE * IMAGE_SIDE > ii); ++ii) { g_image_data[ii] = static_cast<uint16_t>(65535 - g_image_preprocess[ii] * mul); } } #else { const float mul = 255.0f / largest; for(unsigned ii = 0; (IMAGE_SIDE * IMAGE_SIDE > ii); ++ii) { g_image_data[ii] = 255 - static_cast<uint8_t>(g_image_preprocess[ii] * mul); } } gfx::image_png_save(std::string("lol.png"), IMAGE_SIDE, IMAGE_SIDE, 8, g_image_data); #endif
Что такое #if 1:
Only the first block will be processed -— until someone changes the 1 to a 0. Then the other block will be compiled. This is a convenient way to temporary switch blocks of code in and out while testing different algorithms.
Adarkar Wastes by Faemiyah
Instanssi 2018, 1е место
Вот так выглядит на моей FreeBSD:
Сборка и исходники
Исходники все там же, сборка и запуск аналогичны предыдущей.
Проект снова на C++, SDL и Boost, плюс появилась маленькая вставка на ассемблере — для синтезатора.
Как обычно ниже про интересные места в коде.
Cнова кастомный random-генератор:
/** BSD random var. */ static bsd_u_long bsd_rand_next = 2; int bsd_rand(void) { /* * Compute x = (7^5 * x) mod (2^31 - 1) * without overflowing 31 bits: * (2^31 - 1) = 127773 * (7^5) + 2836 * From "Random number generators: good ones are hard to find", * Park and Miller, Communications of the ACM, vol. 31, no. 10, * October 1988, p. 1195. */ long hi, lo, x; /* Must be in [1, 0x7ffffffe] range at this point. */ hi = (long)(bsd_rand_next / 127773); lo = (long)(bsd_rand_next % 127773); x = 16807 * lo - 2836 * hi; if (x < 0) x += 0x7fffffff; bsd_rand_next = (bsd_u_long)x; /* Transform to [0, 0x7ffffffd] range. */ return (int)(x - 1); } void bsd_srand(bsd_u_int seed) { /* Transform to [1, 0x7ffffffe] range. */ bsd_rand_next = (seed % 0x7ffffffe) + 1; }
Это то что сейчас делает отдельный чип, не то что какой-то код.
Обработка указанного разрешения (-r 800x600 помните?) :
/// Parse resolution from string input. /// /// \param op Resolution string. /// \return Tuple of width and height. boost::tuple<unsigned, unsigned> parse_resolution(const std::string &op) { size_t cx = op.find("x"); if(std::string::npos == cx) { cx = op.rfind("p"); if((std::string::npos == cx) || (0 >= cx)) { std::ostringstream sstr; sstr << "invalid resolution string '" << op << '\''; BOOST_THROW_EXCEPTION(std::runtime_error(sstr.str())); } std::string sh = op.substr(0, cx); unsigned rh = boost::lexical_cast<unsigned>(sh); unsigned rw = (rh * 16) / 9; unsigned rem4 = rw % 4; return boost::make_tuple(rw - rem4, rh); } std::string sw = op.substr(0, cx); std::string sh = op.substr(cx + 1); return boost::make_tuple(boost::lexical_cast<int>(sw), boost::lexical_cast<int>(sh)); }
Препроцессинг (макросы) в шейдерах:
float i_fov = 1.73; //float i_fov = 1.0 / tan(60.0 / 180.0 * PI * 0.5); #if defined(USE_LD) perspective[0][0] = i_fov / (float(screen_size.x) / float(screen_size.y)); #elif (DISPLAY_MODE == -800) || (DISPLAY_MODE == 800) || (DISPLAY_MODE == -1200) || (DISPLAY_MODE == 1200) perspective[0][0] = i_fov / 1.6; #else // Assuming 16/9. perspective[0][0] = i_fov / 1.78; #endif
Демосцена умерла?
Вы наверное заметили что все демки выше достаточно старые, а если покопаться в сети то окажется, что большая часть сайтов по демосцене находятся в архивном состоянии, фестивали уже особо не проводятся и так далее.
Я тоже так думал, а затем нашел прекрасное:
Решил реализовать новую концепцию на БК0011 - рисование картинок под музыку. Надеюсь на продолжение :) Релиз и исходные тексты: https://www.pouet.net/prod.php?which=... Трек: https://zxart.ee/rus/avtory/k/kuvo/ar...
Вот что такое БК0011: