fontsize:
result:
--------------------------------------------------------------------------- | |
-- vector | |
local vector = (function() | |
local mt = {} | |
mt.__index = mt | |
local vector | |
vector = function(x, y, z) | |
if type(x) == 'table' then | |
return setmetatable(x, mt) | |
end | |
x = x or 0 | |
y = y or x | |
z = z or y | |
return vector{x, y, z} | |
end | |
local map = function(f, a, b) | |
a = vector(a) | |
b = vector(b) | |
return vector{ f(a[1], b[1]), f(a[2], b[2]), f(a[3], b[3]) } | |
end | |
local sqrt = math.sqrt | |
mt.__add = function(a, b) return map(function(x, y) return x+y end, a, b) end | |
mt.__sub = function(a, b) return map(function(x, y) return x-y end, a, b) end | |
mt.__mul = function(a, b) return map(function(x, y) return x*y end, a, b) end | |
mt.__div = function(a, b) return map(function(x, y) return x/y end, a, b) end | |
mt.__neg = function(a ) return map(function(x ) return -x end, a ) end | |
mt.__concat = function(a, b) return a[1]*b[1] + a[2]*b[2] + a[3]*b[3] end | |
mt.__len = function(a) return sqrt(a .. a) end | |
mt.norm = function(a) return a / #a end | |
return vector | |
end)() | |
--------------------------------------------------------------------------- | |
-- distance field renderer | |
local renderer = (function(max_step, max_radius) | |
local lerp = function(x, xf, xt, df, dt) | |
if x < xf then return df end | |
if x > xt then return dt end | |
return (x-xf) / (xt-xf) * (dt-df) + df | |
end | |
local raymarch = function(est, origin, dir) | |
local dist = 0 | |
for i=1,max_step do | |
local d = est(dir * dist + origin) | |
if d < 1e-5 then return lerp(i, 1, max_step, 0, 1) end | |
dist = dist + d | |
if dist > max_radius then break end | |
end | |
end | |
local rad, cos, sin, pow = math.rad, math.cos, math.sin, math.pow | |
local write = io.write | |
local aa = function(x) | |
local grays = [==[ .'`^",:;Il!i><~+_-?][}{1)(|\/tfjrxnuvczXYUJCLQ0OZmwqpdbkhao*#MW&8%B@$]==] | |
x = math.floor(lerp(x, 0, 1, 1, grays:len())) | |
return grays:sub(x, x) | |
end | |
return function(estimator, size, fov, eye) | |
for y=1,size.h do | |
for x=1,size.w do | |
local cx = rad( lerp(x, 1, size.w, -fov.x/2, fov.x/2)) | |
local cy = rad(-lerp(y, 1, size.h, -fov.y/2, fov.y/2)) | |
local dir = vector(cos(cy)*sin(cx), sin(cy), -cos(cy)*cos(cx)) | |
local x = raymarch(estimator, vector(eye), dir) | |
if x then x = pow(1-x, 10) else x = 0 end | |
write(aa(x)) | |
end | |
write '\n' | |
end | |
end | |
end)(100, 50) | |
--------------------------------------------------------------------------- | |
-- main | |
local estimator = (function() | |
local s2p = vector(2, 0, 0) | |
local min, max = math.min, math.max | |
return function(p) | |
local ns1 = 1 - #p | |
local s2 = #(p-s2p) - 2 | |
local p = p[2] + 1 | |
return max(min(s2, p), ns1) | |
end | |
end)() | |
local scale=1.4 | |
renderer(estimator, {w=60*1.7*scale, h=30*scale}, {x=160, y=90}, {-0.5, 0, 2}) |
--------------------------------------------------------------------------- | |
-- vector | |
local vector = (function() | |
local mt = {} | |
mt.__index = mt | |
local vector | |
vector = function(x, y, z) | |
if type(x) == 'table' then | |
return setmetatable(x, mt) | |
end | |
x = x or 0 | |
y = y or x | |
z = z or y | |
return vector{x, y, z} | |
end | |
local map = function(f, a, b) | |
a = vector(a) | |
b = vector(b) | |
return vector{ f(a[1], b[1]), f(a[2], b[2]), f(a[3], b[3]) } | |
end | |
local sqrt = math.sqrt | |
mt.__add = function(a, b) return map(function(x, y) return x+y end, a, b) end | |
mt.__sub = function(a, b) return map(function(x, y) return x-y end, a, b) end | |
mt.__mul = function(a, b) return map(function(x, y) return x*y end, a, b) end | |
mt.__div = function(a, b) return map(function(x, y) return x/y end, a, b) end | |
mt.__neg = function(a ) return map(function(x ) return -x end, a ) end | |
mt.__concat = function(a, b) return a[1]*b[1] + a[2]*b[2] + a[3]*b[3] end | |
mt.__len = function(a) return sqrt(a .. a) end | |
mt.norm = function(a) return a / #a end | |
return vector | |
end)() | |
--------------------------------------------------------------------------- | |
-- distance field renderer | |
local renderer = (function(max_step, max_radius) | |
local lerp = function(x, xf, xt, df, dt) | |
if x < xf then return df end | |
if x > xt then return dt end | |
return (x-xf) / (xt-xf) * (dt-df) + df | |
end | |
local raymarch = function(est, origin, dir) | |
local dist = 0 | |
for i=1,max_step do | |
local d = est(dir * dist + origin) | |
if d < 1e-5 then return lerp(i, 1, max_step, 0, 1) end | |
dist = dist + d | |
if dist > max_radius then break end | |
end | |
end | |
local rad, cos, sin, pow, floor = math.rad, math.cos, math.sin, math.pow, math.floor | |
local fmt = string.format | |
local write = io.write | |
local aa = function(x) | |
return fmt("\x1b[48;5;%dm \x1b[0m", floor(lerp(x, 0, 1, 232, 255))) | |
end | |
return function(estimator, size, fov, eye) | |
for y=1,size.h do | |
for x=1,size.w do | |
local cx = rad( lerp(x, 1, size.w, -fov.x/2, fov.x/2)) | |
local cy = rad(-lerp(y, 1, size.h, -fov.y/2, fov.y/2)) | |
local dir = vector(cos(cy)*sin(cx), sin(cy), -cos(cy)*cos(cx)) | |
local x = raymarch(estimator, vector(eye), dir) | |
if x then x = pow(1-x, 10) else x = 0 end | |
write(aa(x)) | |
end | |
write '\n' | |
end | |
end | |
end)(100, 50) | |
--------------------------------------------------------------------------- | |
-- main | |
local estimator = (function() | |
local s2p = vector(2, 0, 0) | |
local min, max = math.min, math.max | |
return function(p) | |
local ns1 = 1 - #p | |
local s2 = #(p-s2p) - 2 | |
local p = p[2] + 1 | |
return max(min(s2, p), ns1) | |
end | |
end)() | |
local scale=1.4 | |
renderer(estimator, {w=60*1.7*scale, h=30*scale}, {x=160, y=90}, {-0.5, 0, 2}) |
...'''`````''''.. | |
.'`^^",::;;;IIII;;;::,"^^`'. | |
.'^",;;Il!!!>>>>>>>>>>>>!!llI;:,"^'. | |
.`^,:Il!!>~~~++++--------++++~~>>!!lI:"^'. | |
'^":Il!>~~++---[[[[[[[[[[[[[[[[---++~~>!lI:"`. | |
`''. !>~~+--[[[{{{{{(((((((((({{{{{[[[--+~~>!I:"`. | |
;:,"^`'. --[[{{{((((((//////////((((({{{[[[-++~>!I:^ | |
>!!llI;:"^'. [{{((((//////rrrrrrrr//////(((({{[[-++~!l; | |
~~~>>!lI;:"^' (((////rrrrrrrrrrrrrrrrrr////((({{[[-+~>! | |
---++~~>!lI;,^'(///rrrrruuuuuuuuuuuuuurrrrr///((({{[-+~> | |
[[[[---++~>!lI:^'/rrrruuuuuuuuYYYYuuuuuuuurrrr///(({{[-+~ | |
{{{{[[[--+~>!lI:^rrruuuuuYYYYYYYYYYYYYYuuuuurrrr//(({{[-+ | |
(((({{[[[-+~~!l;,'uuuuuYYYYYYYYYYYYYYYYYYuuuuurrr//(({{[- | |
///(((({{[[-+~>!I:^uuuYYYYYYLLLLLLLLLLYYYYYYuuuurrr//(({[[ | |
r////((({{[--+~>l;"uuYYYYYLLLLLLLLLLLLLLYYYYYuuurrr//(({{[ | |
rrrr//((({[[-+~>!I,uYYYYYLLLLLmmmmmLLLLLLYYYYuuuurrr//(({[ | |
uurr///(({{[-++>!I,uYYYYLLLLLmmmmmmmmLLLLYYYYYuuurrr//(({[ | |
uurr///(({{[-++>!I,uYYYYLLLLLmmmmmmmmLLLLYYYYYuuurrr//(({[ | |
rrrr//((({[[-+~>!I,uYYYYYLLLLLmmmmmLLLLLLYYYYuuuurrr//(({[ | |
r////((({{[--+~>l;"uuYYYYYLLLLLLLLLLLLLLYYYYYuuurrr//(({{[ | |
///(((({{[[-+~>!I:^uuuYYYYYYLLLLLLLLLLYYYYYYuuuurrr//(({[[ | |
(((({{[[[-+~~!l;,'uuuuuYYYYYYYYYYYYYYYYYYuuuuurrr//(({{[- | |
{{{{[[[--+~>!lI:^rrruuuuuYYYYYYYYYYYYYYuuuuurrrr//(({{[-+ | |
[[[[---++~>!lI:^'/rrrruuuuuuuuYYYYuuuuuuuurrrr///(({{[-+~ | |
---++~~>!lI;,^'(///rrrrruuuuuuuuuuuuuurrrrr///((({{[-+~> | |
..................................................................................... ~~~>>!lI;:"^' (((////rrrrrrrrrrrrrrrrrr////((({{[[-+~>! | |
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''.>!!llI;:"^'. [{{((((//////rrrrrrrr//////(((({{[[-++~!l; | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^``` ;:,"^`'. --[[{{{((((((//////////((((({{{[[[-++~>!I:^ | |
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,""^``''. !>~~+--[[[{{{{{(((((((((({{{{{[[[--+~~>!I:"`. | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::^ '^":Il!>~~++---[[[[[[[[[[[[[[[[---++~~>!lI:"`. " | |
llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllII.`^,:Il!!>~~~++++--------++++~~>>!!lI:"^'.IIll | |
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!:",;;Il!!!>>>>>>>>>>>>!!llI;:,"l!!!!!!!!! | |
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>;;;IIII;;;>>>>>>>>>>>>>>>>>>>> | |
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | |
---------------------------------------------------------------------------------------------------------------------------------------------- | |
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[ | |
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[ | |
{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ |