Advertisement
Guest User

Pico-8 Winter Forest Renderer

a guest
May 19th, 2019
357
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 4.59 KB | None | 0 0
  1. p={}
  2. depth={}
  3. pos={}
  4.  
  5. groundy=-6
  6.  
  7. function getindex(x,y)
  8.     x=flr(x)
  9.     y=flr(y)
  10.  
  11.     if (x%128!=x or y%128!=y) return nil
  12.    
  13.     return x*128+y
  14. end
  15.  
  16. function rnddir(ground)
  17.     local a=rnd()
  18.     local y=rnd(2)-1
  19.     local r=sqrt(1-y*y)
  20.     local x=cos(a)*r
  21.     local z=sin(a)*r
  22.     if ground then
  23.         y=abs(y)
  24.     else
  25.         z=-abs(z)
  26.     end
  27.     return x,y,z
  28. end
  29.  
  30. function worldtoscr(x,y,z)
  31.     local persp=60/z
  32.    
  33.     local u=64+x*persp
  34.     local v=64-y*persp
  35.     return u,v,persp
  36. end
  37.  
  38. function scrtoworld(u,v)
  39.     local y=groundy
  40.     local persp=(64-v)/y
  41.    
  42.     local x=(u-64)/persp
  43.     local z=60/persp
  44.     return x,y,z,persp
  45. end
  46.  
  47. dirsx={1,-1,0,0}
  48. dirsy={0,0,1,-1}
  49.  
  50. function outline(u,v)
  51.     local index=getindex(u,v)
  52.     local dist=depth[index]
  53.  
  54.     for i=1,#dirsx do
  55.         local u2=u+dirsx[i]
  56.         local v2=v+dirsy[i]
  57.         local index2=getindex(u2,v2)
  58.         if index2 then
  59.             local dist2=depth[index2]
  60.             if dist2 then
  61.                 if dist2>dist*1.1+sqrt(dist)*.5 then
  62.                     return true
  63.                 end
  64.             else
  65.                 return true
  66.             end
  67.         end
  68.     end
  69.    
  70.     return false
  71. end
  72.  
  73. function ssao(point,dist)
  74.     local x=point[1]
  75.     local y=point[2]
  76.     local z=point[3]
  77.     local ground = (y==groundy)
  78.     local hits=0
  79.     local totalweight=0
  80.     local raycount=60
  81.     local raysamples=4
  82.     local _,__,persp=worldtoscr(x,y,z)
  83.     local raylen=4/persp
  84.     for i=1,raycount do
  85.         local dx,dy,dz=rnddir(ground)
  86.         local rayhits=0
  87.         local weight=1
  88.         for j=1,raysamples do
  89.             local d=j/raysamples*raylen
  90.             local u,v=worldtoscr(x+dx*d,y+dy*d,z+dz*d)
  91.             local index=getindex(u,v)
  92.             if index then
  93.                 local otherdepth=depth[index]
  94.                 if otherdepth and otherdepth<dist then
  95.                     rayhits+=1/raysamples
  96.                 end
  97.             else
  98.                 if rayhits==0 then
  99.                     break
  100.                 end
  101.             end
  102.         end
  103.         hits+=rayhits*rayhits*weight
  104.         totalweight+=weight
  105.     end
  106.    
  107.     return 1-(hits/totalweight)^2
  108. end
  109.  
  110. function drawpoint(x,y,z,u,v)
  111.     if not u then
  112.         u,v=worldtoscr(x,y,z)
  113.     end
  114.    
  115.     index=getindex(u,v)
  116.     if index then
  117.      dist=z
  118.      if not depth[index] or dist<depth[index] then
  119.             col=sqrt(dist/50)*15
  120.             pset(u,v,col)
  121.             depth[index]=dist
  122.             if pos[index] then
  123.                 pos[index][1]=x
  124.                 pos[index][2]=y
  125.                 pos[index][3]=z
  126.             else
  127.                 pos[index]={x,y,z}
  128.             end
  129.         end
  130.     end
  131. end
  132.  
  133. function drawleaf(lx,ly,lz,count,jit)
  134.     for j=1,count do
  135.         x=lx+rnd(jit)-jit/2
  136.         y=ly+rnd(jit)-jit/2
  137.         z=lz+rnd(jit)-jit/2
  138.        
  139.         drawpoint(x,y,z)
  140.     end
  141. end
  142.  
  143. function maketree(tx,tz)
  144.     local height=rnd(6)+6
  145.     for i=0,100 do
  146.         t=i/100
  147.         l=3*(1-t^2)
  148.         a=i*.618+.1
  149.         dx=cos(a)
  150.         dz=sin(a)
  151.         for j=0,l,.1 do
  152.             t2=j/l
  153.             x=dx*j+tx
  154.             y=groundy+t*height-j/2
  155.             z=dz*j+tz
  156.             drawleaf(x,y,z+8,8,.3)
  157.         end
  158.     end
  159. end
  160.  
  161. function makeplant(x,z)
  162.     local h=rnd(2)
  163.     for i=0,h,.1 do
  164.         for j=1,1 do
  165.             drawpoint(x+rnd(.2)-.1,
  166.                       groundy+i,
  167.                       z+rnd(.2)-.1)
  168.         end
  169.     end
  170. end
  171.  
  172. function makemountain(x,z,h)
  173.     local u,v,persp=worldtoscr(x,groundy,z)
  174.     local wheight=h/persp
  175.     local y=groundy+wheight
  176.     local u2,v2=worldtoscr(x,y,z)
  177.     local sheight=v-v2
  178.     for i=0,sheight,.2 do
  179.         local t=i/sheight
  180.         local radius=t*wheight
  181.         for a=0,.5,.1/radius do
  182.             local dx=cos(a)*radius
  183.             local dz=sin(a)*radius
  184.             local wave=sin(a*12+t*4)*2/persp
  185.             drawpoint(x+dx,y-wheight*t+wave-rnd(6)/persp,z+dz)
  186.         end
  187.     end
  188.    
  189. end
  190.  
  191. function makecloud(x,y,z,screenw)
  192.     local u,v,persp=worldtoscr(x,y,z)
  193.     local w=screenw/persp
  194.     for i=1,80 do
  195.         drawleaf(x+rnd(w)-w/2,
  196.                  y+rnd(w/8)-w/16,
  197.                  z+rnd(w/8)-w/16,
  198.                  80,
  199.                  w/20)
  200.     end
  201. end
  202.  
  203. cls(13)
  204.  
  205. for u=0,127 do
  206.     for v=65,127 do
  207.         index=getindex(u,v)
  208.         x,y,z=scrtoworld(u,v)
  209.         drawpoint(x,y,z,u,v)
  210.     end
  211. end
  212.  
  213.  
  214. srand(3)
  215. nextseed=rnd(-1)
  216. for i=1,8 do
  217.     makemountain(rnd(400)-200,
  218.                  200+i*30,
  219.                  15+rnd(30))
  220.     srand(nextseed)
  221.     nextseed=rnd(-1)
  222. end
  223.  
  224. srand(0)
  225. nextseed=rnd(-1)
  226. for i=1,20 do
  227.     makecloud(rnd(1000)-500,
  228.               350+rnd(100),
  229.               500+rnd(200),
  230.               rnd(60)+30)
  231.     srand(nextseed)
  232.     nextseed=rnd(-1)
  233. end
  234.  
  235. srand(0)
  236. nextseed=rnd(-1)
  237. for j=0,4 do
  238.     for i=-1-j,1+j do
  239.         maketree((i+rnd()-.5)*7,
  240.                  (j+rnd()-.5)*6)
  241.         srand(nextseed)
  242.         nextseed=rnd(-1)
  243.     end
  244. end
  245.  
  246. srand(0)
  247. nextseed=rnd(-1)
  248. for i=1,100 do
  249.     local px=rnd(20)-10
  250.     local pz=rnd(12)+3
  251.     for j=1,5+rnd(10) do
  252.         makeplant(px+rnd(2)-1,
  253.                   pz+rnd(1)-.5)
  254.     end
  255.     srand(nextseed)
  256.     nextseed=rnd(-1)
  257. end
  258.  
  259. for u=0,127 do
  260.     for v=0,127 do
  261.         index=getindex(u,v)
  262.         dist=depth[index]
  263.         if dist then
  264.             light=ssao(pos[index],dist)
  265.             //light+=(.5-light)*mid(dist/1200,0,1)
  266.             local col=5+light*2.5
  267.             if outline(u,v) then
  268.                 //col=1+flr(light*1.2)*4
  269.                 col=5
  270.             end
  271.             pset(u,v,col)
  272.         end
  273.     end
  274. end
  275.  
  276. function _update()
  277. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement