Рендеринг трехмерных сцен на языке программирования C

Можете ли вы поверить, что вот этот код...


#include // card > aek.ppm
#include
#include
typedef int i;typedef float f;struct v{
f x,y,z;v operator+(v r){return v(x+r.x
,y+r.y,z+r.z);}v operator*(f r){return
v(x*r,y*r,z*r);}f operator%(v r){return
x*r.x+y*r.y+z*r.z;}v(){}v operator^(v r
){return v(y*r.z-z*r.y,z*r.x-x*r.z,x*r.
y-y*r.x);}v(f a,f b,f c){x=a;y=b;z=c;}v
operator!(){return*this*(1/sqrt(*this%*
this));}};i G[]={247570,280596,280600,
249748,18578,18577,231184,16,16};f R(){
return(f)rand()/RAND_MAX;}i T(v o,v d,f
&t,v&n){t=1e9;i m=0;f p=-o.z/d.z;if(.01
0
){f s=-b-sqrt(q);if(s.01)t=s,n=!(
p+d*t),m=2;}}return m;}v S(v o,v d){f t
;v n;i m=T(o,d,t,n);if(!m)return v(.7,
.6,1)*pow(1-d.z,4);v h=o+d*t,l=!(v(9+R(
),9+R(),16)+h*-1),r=d+n*(n%d*-2);f b=l%
n;if(b<0||T(h,l,t,n))b=0;f p=pow(l%r*(b
>0),99);if(m&1){h=h*.2;return((i)(ceil(
h.x)+ceil(h.y))&1?v(3,1,1):v(3,3,3))*(b
*.2+.1);}return v(p,p,p)+S(h,r)*.5;}i
main(){printf("P6 512 512 255 ");v g=!v
(-6,-16,0),a=!(v(0,0,1)^g)*.002,b=!(g^a
)*.002,c=(a+b)*-256+g;for(i y=512;y--;)
for(i x=512;x--;){v p(13,13,13);for(i r
=64;r--;){v t=a*(R()-.5)*99+b*(R()-.5)*
99;p=S(v(17,16,8)+t,!(t*-1+(a*(R()+x)+b
*(y+R())+c)*16))*3.5+p;}printf("%c%c%c"
,(i)p.x,(i)p.y,(i)p.z);}}

... генерирует с нуля вот эту картинку?

Чудо-картинка

Строится трехмерная сцена и обсчитывается по алгоритму Raytracer. Точно такой же используется в Blender или в 3D Max. Обратите внимание, программа не использует ни единой графической библиотеки или внешней зависимости. Чудеса? А то!

Как скомпилировать и запустить?


c++ -O3 -o card card.cpp
./card > card.ppm

А как оно вообще работает?

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

field_vote: 
Ваша оценка: Нет Средняя: 5 (2 оценки)

С ностальгией вспоминаю те времена, когда бережно относились к каждому байту. Тогда делали упор на оптимизацию, алгоритмы и математику. Сейчас любой дебил может зайти в магазин, купить комп с 16 гигами ОЗУ и на говноязыке из Пэхапэ-плеяды сваять то, что раньше помещалось в 3 строки кода. ;)

Исходная сцена обсчитывается где-то за 10 секунд (на одном ядре i7). Поднял разрешение с 512x512 до 4096x4096 и уже ждать пришлось где-то минут 5. PPM на выходе 50 Мб. :)

Raytracer

> -O3
Мсье, вы наверное хотели сказать -Os ?

Нет, я хотел сказать именно то, что и сказал — -O3. Программа сильно грузит процессор вычислениями и оптимизация требуется по скорости, а не по размеру бинарника. Можно, конечно, и без -O3, но тогда ждать окончание рендеринга придется 2-3 раза дольше.

Комментировать

Filtered HTML

  • Use [fn]...[/fn] (or <fn>...</fn>) to insert automatically numbered footnotes.
  • Доступны HTML теги: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <blockquote> <strike> <code> <h2> <h3> <h4> <h5> <del> <img>
  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Строки и параграфы переносятся автоматически.

Plain text

  • HTML-теги не обрабатываются и показываются как обычный текст
  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Строки и параграфы переносятся автоматически.