Advertisement
Yevano

Distance Field Renderer

May 19th, 2015
554
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 4.55 KB | None | 0 0
  1. local sin   = math.sin
  2. local cos   = math.cos
  3. local tan   = math.tan
  4. local abs   = math.abs
  5. local min   = math.min
  6. local max   = math.max
  7. local floor = math.floor
  8. local sqrt  = math.sqrt
  9. local clock = os.clock
  10.  
  11. -- Threshold values for RGB to RGBI conversion.
  12. R_THRESHOLD = 0.5
  13. G_THRESHOLD = 0.5
  14. B_THRESHOLD = 0.5
  15. I_THRESHOLD = 0.5
  16.  
  17. -- Conversion of 4-bit RGBI to CC colors.
  18. local palette = {
  19.     colors.black,
  20.     colors.gray,
  21.     colors.blue,
  22.     colors.blue,
  23.     colors.green,
  24.     colors.lime,
  25.     colors.cyan,
  26.     colors.lightBlue,
  27.     colors.red,
  28.     colors.red,
  29.     colors.purple,
  30.     colors.magenta,
  31.     colors.brown,
  32.     colors.yellow,
  33.     colors.lightGray,
  34.     colors.white,
  35. }
  36.  
  37. local function clamp(a, m, n)
  38.     return (a > n) and n or (a < m and m or a)
  39. end
  40.  
  41. -- Convert RGB to 4-bit RGBI index.
  42. local function rgbtorgbi(r, g, b)
  43.     r = clamp(r, 0, 1)
  44.     g = clamp(g, 0, 1)
  45.     b = clamp(b, 0, 1)
  46.     local R = r > R_THRESHOLD and 1 or 0
  47.     local G = g > G_THRESHOLD and 1 or 0
  48.     local B = b > B_THRESHOLD and 1 or 0
  49.     local I = (r + g + b)/3 > I_THRESHOLD and 1 or 0
  50.     return R * 8 + G * 4 + B * 2 + I
  51. end
  52.  
  53. --[[ Vector functions ]]--
  54.  
  55. local function length2(x, y)
  56.     return sqrt(x*x + y*y)
  57. end
  58.  
  59. local function length3(x, y, z)
  60.     return sqrt(x*x + y*y + z*z)
  61. end
  62.  
  63. local function normalize3(x, y, z)
  64.     local len = length3(x, y, z)
  65.     return x/len, y/len, z/len
  66. end
  67.  
  68. local function vec3add(x, y, z, a, b, c)
  69.     return x + a, y + b, z + c
  70. end
  71.  
  72. local function vec3sub(x, y, z, a, b, c)
  73.     return x - a, y - b, z - c
  74. end
  75.  
  76. local function vec3mulscalar(x, y, z, a)
  77.     return x * a, y * a, z * a
  78. end
  79.  
  80. local function vec3abs(x, y, z)
  81.     return abs(x), abs(y), abs(z)
  82. end
  83.  
  84. --[[ Matrix functions ]]
  85.  
  86. local function mat2mulvec2(m, x, y)
  87.     return  m[1] * x + m[2] * y,
  88.             m[3] * x + m[4] * y
  89. end
  90.  
  91. local function mat3mulvec3(m, x, y, z)
  92.     return  m[1] * x + m[2] * y + m[3] * z,
  93.             m[4] * x + m[5] * y + m[6] * z,
  94.             m[7] * x + m[8] * y + m[9] * z
  95. end
  96.  
  97. local function getRotMat2(a)
  98.     return { cos(a), -sin(a), sin(a), cos(a) }
  99. end
  100.  
  101. local function getRotMat3x(a)
  102.     return {    1,          0,          0,
  103.                 0,          cos(a),     -sin(a),
  104.                 0,          sin(a),     cos(a)  }
  105. end
  106.  
  107. local function getRotMat3y(a)
  108.     return {    cos(a),     0,          sin(a),
  109.                 0,          1,          0,
  110.                 -sin(a),    0,          cos(a)  }
  111. end
  112.  
  113. local function getRotMat3z(a)
  114.     return {    cos(a),     -sin(a),    0,
  115.                 sin(a),     cos(a),     0,
  116.                 0,          0,          1       }
  117. end
  118.  
  119. local w, h = term.getSize()
  120.  
  121. --[[ Distance functions ]]--
  122.  
  123. local function sphere(x, y, z, r)
  124.     return length3(x, y, z) - r, 0, 1, 0
  125. end
  126.  
  127. local function box(x, y, z, a, b, c)
  128.     return max(max(abs(x) - a, abs(y) - b), abs(z) - c), 1, 0, 0
  129. end
  130.  
  131. -- Place all the models.
  132. local function map(x, y, z)
  133.     local d1, r1, g1, b1 = sphere(x, y, z, 1)
  134.     local d2, r2, g2, b2 = box(x, y, z, 0.8, 0.8, 0.8)
  135.     local d
  136.     if d1 < d2 then
  137.         return d1, r1, g1, b1
  138.     end
  139.     return d2, r2, g2, b2
  140. end
  141.  
  142. local EPSILON = 0.001
  143. local MAX_DIST = 10
  144.  
  145. local function pixel(x, y)
  146.     -- Fix stretching.
  147.     local u, v = x/w, y/h
  148.     u = u * w/h*2/3
  149.     u = u - w/h*2/3/2
  150.     v = v - 0.5
  151.  
  152.     -- Rotation
  153.     local rox, roy, roz = mat3mulvec3(getRotMat3y(clock()), 0, 0, -3)
  154.     rox, roy, roz = mat3mulvec3(getRotMat3z(clock()), rox, roy, roz)
  155.     rox, roy, roz = mat3mulvec3(getRotMat3x(clock()), rox, roy, roz)
  156.    
  157.     local rdx, rdy, rdz = normalize3(u, v, 1)
  158.     rdx, rdy, rdz = mat3mulvec3(getRotMat3y(clock()), rdx, rdy, rdz)
  159.     rdx, rdy, rdz = mat3mulvec3(getRotMat3z(clock()), rdx, rdy, rdz)
  160.     rdx, rdy, rdz = mat3mulvec3(getRotMat3x(clock()), rdx, rdy, rdz)
  161.  
  162.     -- Raymarching
  163.     local l = 0
  164.     for i = 1, 100 do
  165.         local rx, ry, rz = vec3add(rox, roy, roz, vec3mulscalar(rdx, rdy, rdz, l))
  166.         local d, r, g, b = map(rx, ry, rz)
  167.  
  168.         if d <= EPSILON then
  169.             return r, g, b
  170.         end
  171.  
  172.         if l > MAX_DIST then
  173.             return 0, 0, 0
  174.         end
  175.  
  176.         l = l + d
  177.     end
  178.  
  179.     return 0, 0, 0
  180. end
  181.  
  182. term.clear()
  183.  
  184. local scp = term.setCursorPos
  185. local sbc = term.setBackgroundColor
  186. local tw  = term.write
  187.  
  188. -- Draw the pixels.
  189. while true do
  190.     for i = 1, w do
  191.         for j = 1, h do
  192.             scp(i, j)
  193.             sbc(palette[rgbtorgbi(pixel(i - 1, j - 1)) + 1])
  194.             tw(" ")
  195.         end
  196.     end
  197.     sleep(0)
  198. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement