Advertisement
Guest User

RaymarchedHyperboloid.glsl

a guest
Sep 21st, 2019
290
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // raymarched hyperboloid
  2. //boilerplate
  3. //#ifdef GL_ES
  4. precision highp float;
  5. //#endif
  6.  
  7. uniform float time;
  8. uniform vec2 mouse;
  9. uniform vec4 color;
  10. uniform vec2 resolution;
  11.  
  12. float scale = 3.3333;// .5*exp(1./max(.00125,color.r));
  13. vec3 iResolution = vec3(resolution.xy * scale * .5, 1.);
  14. float iTime = time;
  15. vec4 iDate = vec4(color.r, iTime*.125, iTime*.5, iTime);
  16. vec4 iMouse=vec4(mouse*iResolution.xy,1.,1.);
  17.  
  18. float sphererad = 10.0;
  19.  
  20. //Blakes graphing calculator - test ver
  21. float sdfOfBound(vec3, vec3, vec3);
  22. float sgn(float);
  23. float LineHeight(float, vec2, float);
  24. vec2 intersectionOfTwoLines(vec2, float, vec2, float);
  25.  
  26. // So the idea of this shader is to raymarch some function given some information about it.
  27. // The relevant information consists of 3 functions, along with some bounds.
  28. // The three functions below define the function we are going to raymarch. df is the first
  29. // derivative of f, and ddf is the second derivative of f. Along with that, some bounds need to
  30. // be defined as well, but we'll get to that.
  31.  
  32.  
  33. //////// HACKS!!!!!
  34. float yscale=.7; // underestimate f(x) by this factor and scale point to counteract.
  35. float ddffactor=40.; // overestimate ddf/dx by this factor (why?!)
  36.  
  37. float f(float x)
  38. {
  39.     // return the function when fed an x value
  40.     // given the roots of the cubic, calculate the function of x
  41.     return yscale*sqrt(1.+x*x);
  42. }
  43.  
  44. float ff(float x)
  45. {
  46.     // return the function when fed an x value
  47.     // given the roots of the cubic, calculate the function of x
  48.     return sqrt(1.+x*x);
  49. }
  50. float df(float x)
  51. {
  52.     // return the derivative of the function when fed an x value
  53.     // given the roots of the cubic, calculate the derivative of x
  54.     return (2.)*x/ff(x);
  55. }
  56. float ddf(float x)
  57. {
  58.     return (ff(x)*2.-2.*x*(ddffactor)*x/ff(x))/(1.+x*x);
  59. }
  60. vec3 GetBoundary(int i, vec3 pt)
  61. {
  62.    
  63.     float ex0 = -1000.0;
  64.     float ex1 = -1000.;//-120000.;//-2.5/2./fscale;//3.1415926;
  65.     float ex2 = 1000.;//2.5/2./fscale;//3.1415926;
  66.     float ex3 = 1000.0;
  67.        
  68.     float i0 = -1000.0;
  69.     float i1 = pt.z>0.?1./30.:-1./30.;
  70.     float i2 = 1000.0;
  71.    
  72.     if (i == 0)
  73.     {
  74.         return vec3(ex0, i0, ex1);
  75.     }
  76.     if (i == 1)
  77.     {
  78.         return vec3(ex1, i1, ex2);
  79.     }
  80.     if (i == 2)
  81.     {
  82.         return vec3(ex2, i2, ex3);
  83.     }
  84.     return vec3(0.0,0.0,0.0);
  85. }
  86.  
  87. float sdfFunction(vec3 Point, vec3 Center)
  88. {
  89.     // The number of extrema (not counting infinities
  90.     const int EXTREMA_COUNT = 2;
  91.         vec3 pnt = Point - Center;
  92.     //pnt.xz = mod(pnt.xz + vec2(2.0), vec2(4.0))-vec2(2.0);
  93.     float h = length(pnt.xz);
  94.     h = h * sgn(pnt.x)*sgn(pnt.z);
  95.         Point = vec3(0.,yscale*pnt.y, h) + Center;
  96. vec3 invPoint = vec3(0.,-yscale*pnt.y, h) + Center;
  97.     float d = 100000.0;        
  98.     for (int i = 0; i < EXTREMA_COUNT + 1; i++)
  99.     {
  100.         d = min(d, min(sdfOfBound(Point, Center, GetBoundary(i,Point)), sdfOfBound(invPoint, Center, GetBoundary(i,invPoint))));
  101.     }
  102.     return d;
  103. }
  104.  
  105. ///////////////////////
  106.  
  107. // End of user input //
  108.  
  109. ///////////////////////
  110.  
  111. float sdfOfBound(vec3 Point, vec3 Center, vec3 Keys)
  112. {
  113.     vec3 pnt = Point - Center;
  114.     //pnt.xz = mod(pnt.xz + vec2(1.0), vec2(2.0))-vec2(1.0);
  115.     float h = pnt.z;//length(pnt.x);//pnt.x + pnt.z; //max(abs(pnt.x),abs(pnt.z));
  116.     //h = h * sgn(pnt.x)*sgn(pnt.z);
  117.     float k = pnt.y;
  118.  
  119.     float a = Keys.x;
  120.     float b = Keys.z;
  121.     float I = Keys.y;
  122.  
  123.     vec2 P_temp = vec2(h, k);    
  124.     h = clamp(h, a, b);
  125.     vec2 P = vec2(h,k);
  126.  
  127.     bool tangent_method = sgn(f(h) - k) == sgn(ddf(h));
  128.    
  129.     float tan_at_I = df(I);
  130.     float nor_at_I = -1.0 / tan_at_I;
  131.     vec2 pnt_at_I = vec2(I, f(I));
  132.     float line_height = LineHeight(nor_at_I, pnt_at_I, h);
  133.     bool chord_method = (k*ddf(h) < line_height*ddf(h)) && !tangent_method;
  134.     bool clamped_tangent = !chord_method && !tangent_method;
  135.      
  136.     float ct_slope = tan_at_I;
  137.     vec2 ct_pnt = pnt_at_I;    
  138.    
  139.     float t_slope = df(h);
  140.     vec2 t_pnt = vec2(h, f(h));  
  141.    
  142.     float ch_samp_d = abs(f(h) - k) * sgn(df(h)) * sgn(ddf(h));      
  143.     if (P_temp.x < a || P_temp.x > b)
  144.     {
  145.          ch_samp_d = abs(f(h) - k) * -sgn(P_temp.x-h);  
  146.     }
  147.     float ch_raw_Q = h + ch_samp_d;      
  148.     float ch_clamped_Q = clamp(ch_raw_Q, min(I, ch_raw_Q), max(I, ch_raw_Q));  
  149.     vec2 ch_P = vec2(h, f(h));
  150.     vec2 ch_Q = vec2(ch_clamped_Q, f(ch_clamped_Q));    
  151.     float ch_slope = (ch_P.y - ch_Q.y) / (ch_P.x - ch_Q.x);
  152.     vec2 ch_pnt = ch_P;
  153.     vec2 ct_closest = intersectionOfTwoLines(ct_pnt, ct_slope, P, -1.0 / ct_slope);
  154.     vec2 t_closest = intersectionOfTwoLines(t_pnt, t_slope, P, -1.0 / t_slope);
  155.     vec2 ch_closest = intersectionOfTwoLines(ch_pnt, ch_slope, P, -1.0 / ch_slope);
  156.  
  157.     float ct_dist = distance(ct_closest, P);
  158.     float t_dist = distance(t_closest, P);
  159.     float ch_dist = distance(ch_closest, P);
  160.    
  161.     float d = -1.0;
  162.     if (clamped_tangent){ d = ct_dist;}
  163.     if (tangent_method) { d = t_dist; }
  164.     if (chord_method)   { d = ch_dist;}
  165.    
  166.    float dx = d;
  167.     d = max(d , -(P_temp.x - a));
  168.     d = max(d , (P_temp.x - b));
  169.     //if (f(h) > k)         { d *= -1.0;  }
  170.     return dx > 0. ? d: dx;//max(dx,-1111111.);
  171. }
  172.  
  173.  
  174. // Convert degrees to radians
  175. float Radians(float deg)
  176. {
  177.     return deg / 360.0 * 2.0 * 3.14159;
  178. }
  179.  
  180. // Write a float4 function for some of the HLSL Code conversion
  181. vec4 float4(float x, float y, float z, float w)
  182. {
  183.     return vec4(x,y,z,w);  
  184. }
  185.  
  186. // Write a float3 function for the same purpose
  187. vec3 float3(float x, float y, float z)
  188. {
  189.     return vec3(x,y,z);  
  190. }
  191.  
  192. // and a float2 function as well
  193. vec2 float2(float x, float y)
  194. {
  195.     return vec2(x, y);  
  196. }
  197.  
  198. // A method for intersecting two lines in R-two.
  199. vec2 intersectionOfTwoLines(vec2 A, float sa, vec2 B, float sb)
  200. {
  201.     float buffer = (sa*A.x - A.y - sb * B.x + B.y) / (sa - sb);
  202.     vec2 intersection = float2(buffer, sa*(buffer - A.x) + A.y);
  203.     return intersection;
  204. }
  205.  
  206. // Exact SDF for a sphere
  207. float dSphere(vec3 pos, vec3 center, float radius)
  208. {
  209.     // find the distance to the center
  210.     vec3 v = pos - center;
  211.    
  212.     // return that, minus the radius
  213.     return length(v) - radius;
  214. }
  215.  
  216. // Exact intersection of a sphere. Resolves a quatratic equation. Returns the
  217. // min distance, max distance, and discriminant to determine if the intersections
  218. // actually exist.
  219. vec3 intersections_of_sphere(vec3 pos_vector, vec3 dir_vector, float sphere_radius)
  220. {
  221.     // Derivation for formula:
  222.     //      Let the ray be represented as a point P plus a scalar multiple t of the direction vector v,
  223.     //      The ray can then be expressed as P + vt
  224.     //
  225.     //      The point of intersection I = (x, y, z) must be expressed as this, but must also be some distance r
  226.     //      from the center of the sphere, thus x*x + y*y + z*z = r*r, or in vector notation, I*I = r*r
  227.     //
  228.     //      It therefore follows that (P + vt)*(P + vt) = r*r, or when expanded and rearranged,
  229.     //      (v*v)t^2 + (2P*v)t + (P*P - r*r) = 0. For this we will use the quadratic equation for the points of
  230.     //      intersection
  231.  
  232.     // a, b, and c correspond to the second, first, and zeroth order terms of t, the parameter we are trying to solve for.
  233.     float a = dot(dir_vector, dir_vector);
  234.     float b = 2.0 * dot(pos_vector, dir_vector);
  235.     float c = dot(pos_vector, pos_vector) - sphere_radius * sphere_radius;
  236.  
  237.     // to avoid imaginary number, we will find the absolute value of the discriminant.
  238.     float discriminant = b * b - 4.0 * a*c;
  239.     float abs_discriminant = abs(discriminant);
  240.     float min_dist = (-b - sqrt(abs_discriminant)) / (2.0 * a);
  241.     float max_dist = (-b + sqrt(abs_discriminant)) / (2.0 * a);
  242.  
  243.     // return the two intersections, along with the discriminant to determine if
  244.     // the intersections actually exist.
  245.     return float3(min_dist, max_dist, discriminant);
  246.  
  247. }
  248.  
  249. float sgn(float x)
  250. {
  251.     if (x < 0.0)
  252.     {
  253.         return -1.0;
  254.     }
  255.     return 1.0;
  256. }
  257.  
  258. float LineHeight(float slope, vec2 point, float x)
  259. {
  260.     return slope*(x - point.x) + point.y;  
  261. }
  262.  
  263. // Distance estimation for the scene
  264. float DE(vec3 p, vec3 c)
  265. {
  266.     // Raymarch a bounding sphere
  267.     float sphere = dSphere(p, c, sphererad);
  268.    
  269.     // Raymarch generic sdf for a function
  270.     float function = sdfFunction(p,c);
  271.    
  272.     // cut out the bounding sphere
  273.     float d = max(sphere, function);
  274.  
  275.     // return the distance
  276.     return d;
  277. }
  278.  
  279. void mainImage( out vec4 fragColor, in vec2 fragCoord )
  280. {
  281.     // Define the iterations for the marcher.
  282.     const int ITERATIONS = 60;
  283.    
  284.     // Define the roation speed. Set to 0 to disable
  285.     const float ROTATION_SPEED = 0.2;
  286.    
  287.     // Define the start angle for the rotation (in degrees)
  288.     const float START_ANGLE = 0.0;
  289.    
  290.     // Define the orbit radius
  291.     const float ORBIT_RADIUS = 16.0;
  292.    
  293.     // Define the epsilon value for closeness to be considered a hit
  294.     const float EPSILON = 0.001;
  295.    
  296.     const bool HIDE_BACKGROUND = false;
  297.    
  298.    
  299.    
  300.     // Define the center of the julia set
  301.     vec3 sdf_center = vec3(0.0, 0.0, 0.0);
  302.  
  303.     // Calculate the starting angles for the orbit
  304.     float theta = iTime * ROTATION_SPEED;
  305.     float phi = Radians(START_ANGLE);
  306.    
  307.     // Take some mouse input
  308.     vec4 mouse = iMouse / iResolution.xyxx;
  309.    
  310.     // If the mouse is being held down
  311.     //if (mouse.z > 0.0)
  312.     {
  313.         // convert the mouse input to angles
  314.         theta = mouse.x * 2.0 * 3.14159;
  315.         phi = (mouse.y - 0.5) * 1.0 * 3.14159;
  316.     }
  317.    
  318.     // Define an orbital path based on time
  319.     vec3 orbit = vec3(cos(theta)*cos(phi), sin(phi), sin(theta)*cos(phi));
  320.    
  321.     // Cacluate the normal of the path. Since its a circle, it will just
  322.     // be back down into the center
  323.     vec3 normal = -normalize(orbit);
  324.    
  325.     // Calculate the tangent of the path
  326.     // A circle consists of <cost, sint>, which when differentiated yields
  327.     // <-sint, cost>. since z is already sint, and x is already cost, the equation
  328.     // is as follows.
  329.     vec3 tangent = normalize(vec3(-normal.z, 0.0, normal.x));
  330.    
  331.     // Calculate the UV coordinates
  332.     vec2 uv = fragCoord/iResolution.xy;
  333.    
  334.     // Convert the UV coordinates to a range between -1 and 1
  335.     vec2 range = uv*2.0 - vec2(1.0,1.0);
  336.    
  337.     //// Define the Camera position
  338.     //vec3 cam_pos = vec3(0,0,-2);
  339.    
  340.     //// Define the forward, up, and right vectors (needs rework)
  341.     //vec3 forward = normalize(vec3(0,0,1));
  342.     //vec3 up = normalize(vec3(0,1,0));
  343.     //vec3 right = normalize(vec3(1,0,0));
  344.    
  345.     // Define the Camera position
  346.     vec3 cam_pos = orbit*ORBIT_RADIUS;
  347.    
  348.     // Define the forward, up, and right vectors (needs rework)
  349.     vec3 forward = normal;
  350.     vec3 up = normalize(cross(normal, tangent));
  351.     vec3 right = tangent;
  352.        
  353.     // Calculate the aspect ratio of the screen
  354.     float aspect = float(iResolution.y) / float(iResolution.x);
  355.    
  356.     // Calculate the ray as a normalized combination of the forward, right, and up vectors.
  357.     // Note that the purely forward + horizonal combination yield vectors 45 degrees outward
  358.     // for a 90 degree field of view. This may be updated with a fov option
  359.     vec3 ray = normalize(forward + range.x*right + range.y*up*aspect);
  360.    
  361.     // Initialize the ray marched point p
  362.     vec3 p = cam_pos;
  363.  
  364.  
  365.     // Initialize the distance
  366.     float dist = 1.0;
  367.    
  368.     // Calculate the exact distance from a sphere of radius 2 using a raytracing function
  369.     vec3 init_distance = intersections_of_sphere(p - sdf_center, ray, sphererad);
  370.    
  371.     // If we are outside a bubble around the raymarched fractal
  372.     if (init_distance.z > 0.0)
  373.     {
  374.         // Step onto the sphere so we start off a bit closer.
  375.         p += ray * clamp(init_distance.x, 0.0, init_distance.x);
  376.     }
  377.  
  378.     // declare a dummy variable to store the number of iterations into.
  379.     // I'm doing it this way because on my phone it didnt let me use an
  380.     // already declared variable as the loop iterator.
  381.     int j;
  382.    
  383.     float min_dist = 1.0;
  384.     // Begin the raymarch
  385.     for (int i = 0; i < ITERATIONS; i++)
  386.     {
  387.         // Estimate the distance to the julia set
  388.         dist = DE(p, sdf_center);
  389.        
  390.         min_dist = min(dist, min_dist);
  391.        
  392.         // Move forward that distance
  393.         p += ray*dist;
  394.        
  395.         // Record the number of iterations we are on
  396.         j = i;
  397.        
  398.         // If we hit the julia set, or get too far away form it
  399.         if (dist < EPSILON || dot(p - sdf_center, p-sdf_center) > sphererad * sphererad + 0.1)
  400.         {
  401.             // Break the loop.
  402.             break;  
  403.         }
  404.        
  405.     }
  406.    
  407.         // determine if we hit the fractal or not
  408.     float hit = step(dist, EPSILON);
  409.    
  410.    
  411.     // calculate the brightness based on iterations used
  412.     float di = (1.0 - (float(j) + (dist / EPSILON)*hit) / float(ITERATIONS));
  413.     float glow = 1.0 - (min_dist / 1.0);
  414.    
  415.     //di = (di * hit) + (glow*(1.0-hit));
  416.     if (HIDE_BACKGROUND)
  417.     {
  418.         di *= hit;
  419.     }
  420.  
  421.    
  422.    
  423.    
  424.     // define some phase angle
  425.     float psi = Radians(70.0);
  426.    
  427.     // Time varying pixel color (included in default shadertoy project)
  428.     //vec3 col = 0.8 + 0.2*cos(iTime*0.5+uv.xyx+vec3(0,2,4) + psi*hit);
  429.    
  430.     // Boring old white instead of the above commented code. Will tweak rendering later
  431.     vec3 col = vec3(1.0,1.0,1.0);
  432.    
  433.    
  434.     // Output to screen. Modifiy the color with the brightness calculated as di.
  435.     fragColor = vec4(col*di,1.0);
  436. }
  437.  
  438. void main( void ) {
  439.     gl_FragColor = vec4(0.,10.,0.,0.);
  440.     vec2 zoomedCoord = (color.gb - .5) * .125 * iResolution.y - (mouse.xy-vec2(.5,.5)) * iResolution.xy + gl_FragCoord.xy - resolution*.5;
  441. zoomedCoord = gl_FragCoord.xy + resolution*.33;
  442.     mainImage( gl_FragColor, zoomedCoord.xy );
  443. }
  444. // P.S. vrchat is blessed. ~Ly
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement