Advertisement
Yevano

Fragment Shader API

Sep 10th, 2015
405
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 16.67 KB | None | 0 0
  1. -- Rev 2
  2.  
  3. local sin   = math.sin
  4. local cos   = math.cos
  5. local tan   = math.tan
  6. local abs   = math.abs
  7. local min   = math.min
  8. local max   = math.max
  9. local floor = math.floor
  10. local sqrt  = math.sqrt
  11. local clock = os.clock
  12.  
  13. local term_setCursorPos = term.setCursorPos
  14. local term_blit         = term.blit
  15. local table_concat      = table.concat
  16.  
  17. local STRATEGY_FULL_CELL = 0
  18. local STRATEGY_HEX_CELL = 1
  19. local STRATEGY_TWO_CELL = 2
  20.  
  21. local function vec2(x, y)
  22.     return { x = x, y = y }
  23. end
  24.  
  25. local function vec3(x, y, z)
  26.     return { x = x, y = y, z = z }
  27. end
  28.  
  29. local function vec4(x, y, z, w)
  30.     return { x = x, y = y, z = z, w = w }
  31. end
  32.  
  33. local function length2(v)
  34.     return (v.x^2 + v.y^2)^0.5
  35. end
  36.  
  37. local function length3(v)
  38.     return (v.x^2 + v.y^2 + v.z^2)^0.5
  39. end
  40.  
  41. local function length4(v)
  42.     return (v.x^2 + v.y^2 + v.z^2 + v.w^2)^0.5
  43. end
  44.  
  45. local function normalize2(v)
  46.     return div2s(v, length2(v))
  47. end
  48.  
  49. local function normalize3(v)
  50.     return div3s(v, length3(v))
  51. end
  52.  
  53. local function normalize4(v)
  54.     return div4s(v, length4(v))
  55. end
  56.  
  57. local function distance2(v1, v2)
  58.     return ((v1.x - v2.x)^2 + (v1.y - v2.y)^2)^0.5
  59. end
  60.  
  61. local function distance3(v1, v2)
  62.     return ((v1.x - v2.x)^2 + (v1.y - v2.y)^2 + (v1.z - v2.z)^2)^0.5
  63. end
  64.  
  65. local function distance4(v1, v2)
  66.     return ((v1.x - v2.x)^2 + (v1.y - v2.y)^2 + (v1.z - v2.z)^2 + (v1.w - v2.w)^2)^0.5
  67. end
  68.  
  69. local function dot2(v1, v2)
  70.     return v1.x*v2.x + v1.y*v2.y
  71. end
  72.  
  73. local function dot3(v1, v2)
  74.     return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z
  75. end
  76.  
  77. local function dot4(v1, v2)
  78.     return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z + v1.w*v2.w
  79. end
  80.  
  81. local function add2(v1, v2)
  82.     return vec2(v1.x+v2.x, v1.y+v2.y)
  83. end
  84.  
  85. local function add3(v1, v2)
  86.     return vec3(v1.x+v2.x, v1.y+v2.y, v1.z+v2.z)
  87. end
  88.  
  89. local function add4(v1, v2)
  90.     return vec4(v1.x+v2.x, v1.y+v2.y, v1.z+v2.z, v1.w+v2.w)
  91. end
  92.  
  93. local function sub2(v1, v2)
  94.     return vec2(v1.x-v2.x, v1.y-v2.y)
  95. end
  96.  
  97. local function sub3(v1, v2)
  98.     return vec3(v1.x-v2.x, v1.y-v2.y, v1.z-v2.z)
  99. end
  100.  
  101. local function sub4(v1, v2)
  102.     return vec4(v1.x-v2.x, v1.y-v2.y, v1.z-v2.z, v1.w-v2.w)
  103. end
  104.  
  105. local function mul2(v1, v2)
  106.     return vec2(v1.x*v2.x, v1.y*v2.y)
  107. end
  108.  
  109. local function mul3(v1, v2)
  110.     return vec3(v1.x*v2.x, v1.y*v2.y, v1.z*v2.z)
  111. end
  112.  
  113. local function mul4(v1, v2)
  114.     return vec4(v1.x*v2.x, v1.y*v2.y, v1.z*v2.z, v1.w*v2.w)
  115. end
  116.  
  117. local function div2(v1, v2)
  118.     return vec2(v1.x/v2.x, v1.y/v2.y)
  119. end
  120.  
  121. local function div3(v1, v2)
  122.     return vec3(v1.x/v2.x, v1.y/v2.y, v1.z/v2.z)
  123. end
  124.  
  125. local function div4(v1, v2)
  126.     return vec4(v1.x/v2.x, v1.y/v2.y, v1.z/v2.z, v1.w/v2.w)
  127. end
  128.  
  129. local function add2s(v1, n)
  130.     return vec2(v1.x+n, v1.y+n)
  131. end
  132.  
  133. local function add3s(v1, n)
  134.     return vec3(v1.x+n, v1.y+n, v1.z+n)
  135. end
  136.  
  137. local function add4s(v1, n)
  138.     return vec4(v1.x+n, v1.y+n, v1.z+n, v1.w+n)
  139. end
  140.  
  141. local function sub2s(v1, n)
  142.     return vec2(v1.x-n, v1.y-n)
  143. end
  144.  
  145. local function sub3s(v1, n)
  146.     return vec3(v1.x-n, v1.y-n, v1.z-n)
  147. end
  148.  
  149. local function sub4s(v1, n)
  150.     return vec4(v1.x-n, v1.y-n, v1.z-n, v1.w-n)
  151. end
  152.  
  153. local function mul2s(v1, n)
  154.     return vec2(v1.x*n, v1.y*n)
  155. end
  156.  
  157. local function mul3s(v1, n)
  158.     return vec3(v1.x*n, v1.y*n, v1.z*n)
  159. end
  160.  
  161. local function mul4s(v1, n)
  162.     return vec4(v1.x*n, v1.y*n, v1.z*n, v1.w*n)
  163. end
  164.  
  165. local function div2s(v1, n)
  166.     return vec2(v1.x/n, v1.y/n)
  167. end
  168.  
  169. local function div3s(v1, n)
  170.     return vec3(v1.x/n, v1.y/n, v1.z/n)
  171. end
  172.  
  173. local function div4s(v1, n)
  174.     return vec4(v1.x/n, v1.y/n, v1.z/n, v1.w/n)
  175. end
  176.  
  177. local function mat2mulvec2(m, v)
  178.     return vec2(m[1] * v.x + m[2] * v.y,
  179.                 m[3] * v.x + m[4] * v.y)
  180. end
  181.  
  182. local function mat3mulvec3(m, v)
  183.     return vec3(m[1] * v.x + m[2] * v.y + m[3] * v.z,
  184.                 m[4] * v.x + m[5] * v.y + m[6] * v.z,
  185.                 m[7] * v.x + m[8] * v.y + m[9] * v.z)
  186. end
  187.  
  188. local function getRotMat2(a)
  189.     return { cos(a), -sin(a), sin(a), cos(a) }
  190. end
  191.  
  192. local function getRotMat3x(a)
  193.     return {    1,          0,          0,
  194.                 0,          cos(a),     -sin(a),
  195.                 0,          sin(a),     cos(a)  }
  196. end
  197.  
  198. local function getRotMat3y(a)
  199.     return {    cos(a),     0,          sin(a),
  200.                 0,          1,          0,
  201.                 -sin(a),    0,          cos(a)  }
  202. end
  203.  
  204. local function getRotMat3z(a)
  205.     return {    cos(a),     -sin(a),    0,
  206.                 sin(a),     cos(a),     0,
  207.                 0,          0,          1       }
  208. end
  209.  
  210. local function fract(n)
  211.     return n - floor(n)
  212. end
  213.  
  214. local function mix(x, y, a)
  215.     return x * (1 - a) + y * a
  216. end
  217.  
  218. local function clamp(a, s, l)
  219.     return a < s and s or a > l and l or a
  220. end
  221.  
  222. local function smoothstep(edge0, edge1, x)
  223.     local t = clamp((x - edge0) / (edge1 - edge0), 0, 1)
  224.     return t * t * (3 - 2 * t)
  225. end
  226.  
  227. local function lab2xyz(lab)
  228.     local y = (lab.x + 16.0) / 116.0
  229.     local y3 = y^3.0
  230.     local x = (lab.y / 500.0) + y
  231.     local x3 = x^3.0
  232.     local z = y - (lab.z / 200.0)
  233.     local z3 = z^3.0
  234.  
  235.     if y3 > 0.008856 then
  236.         y = y3
  237.     else
  238.         y = (y - (16.0 / 116.0)) / 7.787
  239.     end
  240.     if x3 > 0.008856 then
  241.         x = x3
  242.     else
  243.         x = (x - (16.0 / 116.0)) / 7.787
  244.     end
  245.  
  246.     if z3 > 0.008856 then
  247.         z = z3
  248.     else
  249.         z = (z - (16.0 / 116.0)) / 7.787
  250.     end
  251.  
  252.     return vec3(x * 95.0429, y * 100.0, z * 108.8900)
  253. end
  254.  
  255. local Mi =  {{ 3.2406, -1.5372, -0.4986},
  256.              {-0.9689,  1.8758,  0.0415},
  257.              { 0.0557, -0.2040,  1.0570}}
  258.  
  259. local function xyz2rgb(xyz)
  260.     local x = xyz.x / 100.0
  261.     local y = xyz.y / 100.0
  262.     local z = xyz.z / 100.0
  263.  
  264.     local r = (x * Mi[1][1]) + (y * Mi[1][2]) + (z * Mi[1][3])
  265.     local g = (x * Mi[2][1]) + (y * Mi[2][2]) + (z * Mi[2][3])
  266.     local b = (x * Mi[3][1]) + (y * Mi[3][2]) + (z * Mi[3][3])
  267.  
  268.     -- assume sRGB
  269.     if r > 0.0031308 then
  270.         r = ((1.055 * r^(1.0 / 2.4)) - 0.055)
  271.     else
  272.         r = (r * 12.92)
  273.     end
  274.     if g > 0.0031308 then
  275.         g = ((1.055 * g^(1.0 / 2.4)) - 0.055)
  276.     else
  277.         g = (g * 12.92)
  278.     end
  279.     if b > 0.0031308 then
  280.         b = ((1.055 * b^(1.0 / 2.4)) - 0.055)
  281.     else
  282.         b = (b * 12.92)
  283.     end
  284.  
  285.     r = (r < 0) and 0 or r
  286.     g = (g < 0) and 0 or g
  287.     b = (b < 0) and 0 or b
  288.  
  289.     return vec3(r, g, b)
  290. end
  291.  
  292. local function lab2rgb(lab)
  293.     return xyz2rgb(lab2xyz(lab))
  294. end
  295.  
  296. local function rgb2lab(color)
  297.     -- Original code: http://www.brucelindbloom.com
  298.     -- Ported to Lua by Yevano.
  299.     local r, g, b = color.x, color.y, color.z
  300.     local X, Y, Z, fx, fy, fz, xr, yr, z
  301.     local Ls, as, bs
  302.     local eps = 216 / 24389
  303.     local k = 24389 / 27
  304.  
  305.     local Xr = 0.964221  -- reference white D50
  306.     local Yr = 1
  307.     local Zr = 0.825211
  308.  
  309.     -- assuming sRGB (D65)
  310.     if r <= 0.04045 then
  311.         r = r / 12
  312.     else
  313.         r = ((r + 0.055) / 1.055)^2.4
  314.     end
  315.  
  316.     if g <= 0.04045 then
  317.         g = g / 12
  318.     else
  319.         g = ((g + 0.055) / 1.055)^2.4
  320.     end
  321.  
  322.     if b <= 0.04045 then
  323.         b = b / 12
  324.     else
  325.         b = ((b + 0.055) / 1.055)^2.4
  326.     end
  327.  
  328.     X = 0.436052025 * r + 0.385081593 * g + 0.143087414 * b
  329.     Y = 0.222491598 * r + 0.71688606 * g + 0.060621486 * b
  330.     Z = 0.013929122 * r + 0.097097002 * g + 0.71418547 * b
  331.  
  332.     -- XYZ to Lab
  333.     xr = X / Xr
  334.     yr = Y / Yr
  335.     zr = Z / Zr
  336.  
  337.     if xr > eps then
  338.         fx = xr^(1 / 3)
  339.     else
  340.         fx = ((k * xr + 16.) / 116.)
  341.     end
  342.  
  343.     if yr > eps then
  344.         fy = yr^(1 / 3)
  345.     else
  346.         fy = ((k * yr + 16.) / 116.)
  347.     end
  348.  
  349.     if zr > eps then
  350.         fz = zr^(1 / 3)
  351.     else
  352.         fz = ((k * zr + 16.) / 116)
  353.     end
  354.  
  355.     Ls = (116 * fy) - 16
  356.     as = 500 * (fx - fy)
  357.     bs = 200 * (fy - fz)
  358.  
  359.     return vec3(2.55 * Ls + .5, as + .5, bs + .5)
  360. end
  361.  
  362. local function colorDistance(c1, c2)
  363.     local lab1 = rgb2lab(c1)
  364.     local lab2 = rgb2lab(c2)
  365.     return distance3(lab1, lab2)
  366. end
  367.  
  368. local function createPalette(indexTable, redPal, greenPal, bluePal, ldFunc)
  369.     ldFunc = ldFunc or function() return 0.1 end
  370.     local colorTable = { }
  371.     local pal = {
  372.         indexTable = indexTable,
  373.         colorTable = colorTable,
  374.         redPal = redPal,
  375.         greenPal = greenPal,
  376.         bluePal = bluePal
  377.     }
  378.     local s = os.clock()
  379.     for r = 0, redPal - 1 do
  380.         colorTable[r] = { }
  381.         for g = 0, greenPal - 1 do
  382.             colorTable[r][g] = { }
  383.             for b = 0, bluePal - 1 do
  384.                 local minDist = 9999
  385.                 local entry
  386.                 for i = 1, #indexTable do
  387.                     local dist = colorDistance(vec3(r/(redPal-1), g/(greenPal-1), b/(bluePal-1)), indexTable[i])
  388.                     if dist < minDist then
  389.                         minDist = dist
  390.                         entry = i
  391.                     end
  392.                 end
  393.                 colorTable[r][g][b] = entry
  394.             end
  395.         end
  396.         if os.clock() - s > ldFunc((r*greenPal*bluePal)/(redPal*greenPal*bluePal)) then
  397.             sleep(0)
  398.             s = os.clock()
  399.         end
  400.     end
  401.     return pal
  402. end
  403.  
  404. local function paletteConvert(palette, color)
  405.     local x = color.x < 0 and 0 or color.x > 1 and 1 or color.x
  406.     local y = color.y < 0 and 0 or color.y > 1 and 1 or color.y
  407.     local z = color.z < 0 and 0 or color.z > 1 and 1 or color.z
  408.     local r = floor(x * palette.redPal)
  409.     local g = floor(y * palette.greenPal)
  410.     local b = floor(z * palette.bluePal)
  411.     if r == palette.redPal then r = r - 1 end
  412.     if g == palette.greenPal then g = g - 1 end
  413.     if b == palette.bluePal then b = b - 1 end
  414.     local i = palette.colorTable[r][g][b]
  415.     return i
  416. end
  417.  
  418. local function createShaderProgram()
  419.     local prog = {
  420.         shaders = { }
  421.     }
  422.     return prog
  423. end
  424.  
  425. local function addShader(program, shader)
  426.     program.shaders[#program.shaders + 1] = shader
  427. end
  428.  
  429. local function applyShaderProgram(program, frameBuffer)
  430.     local pixelData = frameBuffer.pixelData
  431.     local w = frameBuffer.size.x
  432.     local h = frameBuffer.size.y
  433.     for i = 1, #program.shaders do
  434.         local shaderFunc = program.shaders[i].shaderFunc
  435.         local inputs = program.shaders[i].inputs
  436.         for x = 1, w do
  437.             for y = 1, h do
  438.                 pixelData[x + (y - 1) * w] = shaderFunc(vec4(pixelData[x + (y - 1) * w]), vec2((x - 1), (h - y + 1)*3/2), inputs)
  439.             end
  440.         end
  441.     end
  442. end
  443.  
  444. local function createShader(shaderFunc)
  445.     local shader = {
  446.         shaderFunc = shaderFunc,
  447.         inputs = { }
  448.     }
  449.     return shader
  450. end
  451.  
  452. local function setShaderInput(shader, i, v)
  453.     shader.inputs[i] = v
  454. end
  455.  
  456. local function createFrameBuffer(palette, charTable, size, renderStrategy, blit, scp)
  457.     renderStrategy = renderStrategy or STRATEGY_FULL_CELL
  458.     if renderStrategy == STRATEGY_HEX_CELL and (size.x % 2 ~= 0 or size.y % 3 ~= 0) then
  459.         error("Frame Buffer using STRATEGY_HEX_CELL must have width multiple of 2 and height multiple of 3.")
  460.     end
  461.     if renderStrategy == STRATEGY_TWO_CELL then
  462.         error("STRATEGY_TWO_CELL not yet implemented.")
  463.     end
  464.     local pixelData = { }
  465.     local buf = {
  466.         palette = palette,
  467.         charTable = charTable,
  468.         size = size,
  469.         pixelData = pixelData,
  470.         renderStrategy = renderStrategy,
  471.         blit = blit or term_blit,
  472.         scp = scp or term_setCursorPos
  473.     }
  474.     for i = 1, size.x * size.y do
  475.         pixelData[i] = vec4(0, 0, 0, 0)
  476.     end
  477.     return buf
  478. end
  479.  
  480. -- Thanks for writing this useful function, oli414.
  481. local function getDrawingCharacter(topLeft, topRight, left, right, bottomLeft, bottomRight)
  482.     local data = 128
  483.     if not bottomRight then
  484.         data = data + (topLeft and 1 or 0)
  485.         data = data + (topRight and 2 or 0)
  486.         data = data + (left and 4 or 0)
  487.         data = data + (right and 8 or 0)
  488.         data = data + (bottomLeft and 16 or 0)
  489.     else
  490.         data = data + (topLeft and 0 or 1)
  491.         data = data + (topRight and 0 or 2)
  492.         data = data + (left and 0 or 4)
  493.         data = data + (right and 0 or 8)
  494.         data = data + (bottomLeft and 0 or 16)
  495.     end
  496.     return string.char(data), bottomRight
  497. end
  498.  
  499. local function drawFrameBuffer(buf, pos)
  500.     local w, h = buf.size.x, buf.size.y
  501.     local x, y = pos.x, pos.y
  502.     local pixelData = buf.pixelData
  503.     local palette = buf.palette
  504.     local charTable = buf.charTable
  505.     local blit = buf.blit
  506.     local scp = buf.scp
  507.     if buf.renderStrategy == STRATEGY_FULL_CELL then
  508.         for i = y, y + h - 1 do
  509.             local s = { }
  510.             local b = { }
  511.             local f = { }
  512.             for j = (i-1)*w + 1, i*w do
  513.                 local colIdx = paletteConvert(palette, pixelData[j])
  514.                 local charEntry = charTable[colIdx]
  515.                 s[#s + 1] = charEntry[1]
  516.                 b[#b + 1] = charEntry[2]
  517.                 f[#f + 1] = charEntry[3]
  518.             end
  519.             scp(x, i)
  520.             blit(table_concat(s), table_concat(f), table_concat(b))
  521.         end
  522.     elseif buf.renderStrategy == STRATEGY_HEX_CELL then
  523.         for sy = 0, h-1, 3 do
  524.             local s = { }
  525.             local b = { }
  526.             local f = { }
  527.             for sx = 0, w-1, 2 do
  528.                 local uniqueColors = { }
  529.                 local colorCounts = { }
  530.                 local convColors = { }
  531.                 for j = 0, 2 do
  532.                     for i = 0, 1 do
  533.                         local col = charTable[paletteConvert(palette, pixelData[sx+i + (sy+j) * w + 1])][2]
  534.                         convColors[#convColors + 1] = col
  535.                         if colorCounts[col] then
  536.                             colorCounts[col] = colorCounts[col] + 1
  537.                         else
  538.                             colorCounts[col] = 1
  539.                             uniqueColors[#uniqueColors + 1] = col
  540.                         end
  541.                     end
  542.                 end
  543.                 table.sort(uniqueColors, function(a, b) return colorCounts[a] > colorCounts[b] end)
  544.                 local c0 = uniqueColors[1]
  545.                 local c1 = uniqueColors[2] or c0
  546.                 local char, inv = getDrawingCharacter(
  547.                     convColors[1] ~= c1,
  548.                     convColors[2] ~= c1,
  549.                     convColors[3] ~= c1,
  550.                     convColors[4] ~= c1,
  551.                     convColors[5] ~= c1,
  552.                     convColors[6] ~= c1)
  553.                 s[#s + 1] = char
  554.                 if inv then
  555.                     b[#b + 1] = c0
  556.                     f[#f + 1] = c1
  557.                 else
  558.                     b[#b + 1] = c1
  559.                     f[#f + 1] = c0
  560.                 end
  561.             end
  562.             scp(x, y + sy/3)
  563.             blit(table_concat(s), table_concat(f), table_concat(b))
  564.         end
  565.     elseif buf.renderStrategy == STRATEGY_TWO_CELL then
  566.         error("STRATEGY_TWO_CELL not yet implemented.")
  567.     end
  568. end
  569.  
  570. local function getUnstretchedResolution(buf)
  571.     return vec2(buf.size.x, buf.size.y * 3/2)
  572. end
  573.  
  574. local function clearFrameBuffer(buf, color)
  575.     local pixelData = buf.pixelData
  576.     for i = 1, #pixelData do
  577.         pixelData[i] = color
  578.     end
  579. end
  580.  
  581. local g = getfenv()
  582. g.STRATEGY_FULL_CELL = STRATEGY_FULL_CELL
  583. g.STRATEGY_HEX_CELL = STRATEGY_HEX_CELL
  584. g.STRATEGY_TWO_CELL = STRATEGY_TWO_CELL
  585. g.vec2 = vec2
  586. g.vec3 = vec3
  587. g.vec4 = vec4
  588. g.length2 = length2
  589. g.length3 = length3
  590. g.length4 = length4
  591. g.normalize2 = normalize2
  592. g.normalize3 = normalize3
  593. g.normalize4 = normalize4
  594. g.distance2 = distance2
  595. g.distance3 = distance3
  596. g.distance4 = distance4
  597. g.dot2 = dot2
  598. g.dot3 = dot3
  599. g.dot4 = dot4
  600. g.add2 = add2
  601. g.add3 = add3
  602. g.add4 = add4
  603. g.sub2 = sub2
  604. g.sub3 = sub3
  605. g.sub4 = sub4
  606. g.mul2 = mul2
  607. g.mul3 = mul3
  608. g.mul4 = mul4
  609. g.div2 = div2
  610. g.div3 = div3
  611. g.div4 = div4
  612. g.add2s = add2s
  613. g.add3s = add3s
  614. g.add4s = add4s
  615. g.sub2s = sub2s
  616. g.sub3s = sub3s
  617. g.sub4s = sub4s
  618. g.mul2s = mul2s
  619. g.mul3s = mul3s
  620. g.mul4s = mul4s
  621. g.div2s = div2s
  622. g.div3s = div3s
  623. g.div4s = div4s
  624. g.mat2mulvec2 = mat2mulvec2
  625. g.mat3mulvec3 = mat3mulvec3
  626. g.getRotMat2 = getRotMat2
  627. g.getRotMat3x = getRotMat3x
  628. g.getRotMat3y = getRotMat3y
  629. g.getRotMat3z = getRotMat3z
  630. g.fract = fract
  631. g.mix = mix
  632. g.clamp = clamp
  633. g.smoothstep = smoothstep
  634. g.lab2xyz = lab2xyz
  635. g.xyz2rgb = xyz2rgb
  636. g.lab2rgb = lab2rgb
  637. g.rgb2lab = rgb2lab
  638. g.colorDistance = colorDistance
  639. g.createPalette = createPalette
  640. g.paletteConvert = paletteConvert
  641. g.createShaderProgram = createShaderProgram
  642. g.addShader = addShader
  643. g.applyShaderProgram = applyShaderProgram
  644. g.createShader = createShader
  645. g.setShaderInput = setShaderInput
  646. g.createFrameBuffer = createFrameBuffer
  647. g.drawFrameBuffer = drawFrameBuffer
  648. g.getUnstretchedResolution = getUnstretchedResolution
  649. g.clearFrameBuffer = clearFrameBuffer
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement