title: How to create a spherical angular gradient around y-axis using Lua in Filter Forge?
body: <p>I am working on a Spherical Map Script that generates a linear gradient along the y-axis and an angular gradient around the y-axis in the green and red channels, respectively. I have been unable to find any documentation suited to this online, but have experimented using examples in Javascript and C#. The linear gradient has worked out fine, but the angular gradient (one describing a 360 degree arc around the y-axis) continues to elude me.</p>
  <p>My working script is as follows.</p>
  <pre><code>-- 3d sphere 
      -- produces rgb gradudient mapped to a 3d sphere, but not correctly. 
      -- this is basically missing an angle gradient around the y-axis...
  function prepare()
      -- tilt &amp; rotation precalc
      toRad = 180/math.pi
      -- toCir = 360/math.p -- may or may not work for circumference...
  
      radius = get_slider_input(RADIUS)
  
      angle = get_angle_input(ROTATION)/toRad
      cosa = math.cos(angle)
      sina = math.sin(angle)
  
      tilt = get_angle_input(TILT)/toRad
      cosa2 = math.cos(tilt)
      sina2 = math.sin(tilt)
  end;
  
  
  function get_sample(x, y)
      local r, g, b, a = get_sample_map(x, y, SOURCE)
      -- color gradient example
      --  local r = x
      --  local g = y
      --  local b = (x + y) / 2
      --  local a = 1
      -- spherical mapping formulae (polar to cartesian, apparently)
      --  local x = x * math.pi -- * aspect 
      --  local y = y * math.pi
      --  local nx = math.cos(x) * math.sin(y) 
      --  local ny = math.sin(x) * math.sin(y) 
      --  local nz = math.cos(y) 
      -- cartesian to polar (reference)
      --  example 1
      --  r = math.sqrt(((x * x) + (y * y) + (z * z))) 
      --  long = math.acos(x / math.sqrt((x * x) + (y * y))) * (y &lt; 0 ? -1 : 1) 
      --  lat = math.acos(z / radius) * (z &lt; 0 ? -1 : 1) 
      --  example 2
      --      r = math.sqrt((x * x) + (y * y) + (z * z)) 
      --      long = math.acos(x / math.sqrt((x * x) + (y * y))) * (y &lt; 0 ? -1 : 1) 
      --  lat = math.acos(z / r) 
              -- equations cannot accept boolean comparison
              -- boolean syntax may not be valid in lua
     
      -- image generation
      -- shift origin to center and set radius limits
      local px = (x*2.0) - 1.0
      local py = (y*2.0) - 1.0
      px = px/radius
      py = py/radius
      local len = math.sqrt((px*px)+(py*py))
      if len &gt; 1.0 then return 0,0,0,0 end
  
      local z = -math.sqrt(1.0 - ((px*px)+(py*py)))
  
      -- cartesian to polar
          -- r = math.sqrt((x * x) + (y * y) + (z * z))
          -- lat = math.acos(z / r)
          -- long = math.acos(x / math.sqrt((x * x) + (y * y))) * (y &lt; 0) ? -1 : 1) 
  
      -- apply rotaqtion and tilt (order is important)
      local tz = (cosa2 * z) - (sina2 * py) 
      local ty = (sina2 * z) + (cosa2 * py) -- gradient along y-axis is correct
      z = tz 
      py = ty
  
      local tx = (cosa * px) - (sina * z) -- gradient needs to go around y-axis
      local tz = (sina * px) + (cosa * z)
      px = tx
      z = tz
  
          -- r = math.sqrt((x * x) + (y * y) + (z * z)) 
          -- lat = math.acos(z / r) -- invalid z for this; what is correct source?
          -- long = math.acos(x / math.sqrt((x * x) + (y * y))) -- map -1 : 1 needed
          -- long = (sina * px) + (cosa * z) -- ok;  2 full rotations
  
      -- return r, g, b, a
      -- return px,py,z,a 
      return px/2+.5,py/2+.5,z/2+.5,a 
      -- return px/2+.5,px/2+.5,px/2+.5,a 
      -- return long,long,long,a 
      -- return px/2+.5,py/2+.5,long,a 
  end;
  </code></pre>