/ chmod777_includes / shaders / ray_march.glsl
ray_march.glsl
  1  layout (local_size_x=1, local_size_y=1, local_size_z=1) in;
  2  layout(rgba32f, binding = 0) uniform image2D imgOutput;
  3  
  4  // file: raymarch.glsl
  5  // author: chmod777
  6  // license: GNU AGPL v3
  7  
  8  layout(std140, binding = 5) buffer Spheres {
  9  	vec4 pallet_a;
 10  	vec4 pallet_b;
 11  	vec4 pallet_c;
 12  	vec4 pallet_d;
 13  	vec4 sp_pos[SPHERE_COUNT];
 14  	vec4 sp_speed[SPHERE_COUNT];
 15  	float sp_radius[SPHERE_COUNT]; // alignment [float, pad, pad, pad]
 16  };
 17  
 18  layout(std430, binding = 7) buffer Camera {
 19  	vec4 cam_pos;
 20  	vec4 cam_front;
 21  	vec4 cam_xAxis;
 22  	vec4 cam_yAxis;
 23  	float cam_fov;
 24  };
 25  uniform float time;
 26  
 27  // Resources
 28  // https://iquilezles.org/articles/palettes/
 29  vec4 palette_impl(float t, vec4 a, vec4 b, vec4 c, vec4 d) {
 30  	// return a + b*cos( 6.28312 * (c*t+d) )
 31  	return fma(b, cos(6.28312 * fma(c, vec4(t), d)), a);
 32  }
 33  vec4 palette(float t) {
 34  	return palette_impl(t, pallet_a, pallet_b, pallet_c, pallet_d);
 35  }
 36  
 37  struct Sphere {
 38  	vec3 pos;     // 4
 39  	float radius; // 8
 40  };
 41  Sphere localSpheres[SPHERE_COUNT];
 42  
 43  struct RayHit {
 44  	float dist;
 45  	int id;
 46  	vec3 normal;
 47  };
 48  
 49  float op_union(float a, float b) {
 50  	return (a < b) ? a : b;
 51  }
 52  float op_smooth_union(float a, float b, float k) {
 53  	float diff = a - b;
 54  	float h_raw = fma(diff/k, 0.5, 0.5);
 55  	float h = clamp(h_raw, 0.0, 1.0);
 56  	float d = fma(-k, h*(1.0 - h), mix(a, b, h));
 57  	return d;
 58  }
 59  
 60  float signDistanceSphere(vec3 point, Sphere sphere) {
 61  	return length(point - sphere.pos) - sphere.radius;
 62  }
 63  
 64  float sdf(vec3 point) {
 65  	float a = signDistanceSphere(point, localSpheres[0]);
 66  	for (int i = 1; i < SPHERE_COUNT; i++) {
 67  		float b = signDistanceSphere(point, localSpheres[i]);
 68  		a = op_smooth_union(a, b, float(SMOOTHING_FACTOR));
 69  	}
 70  	return a;
 71  }
 72  
 73  vec3 normal(vec3 p) {
 74  	vec2 e = vec2(0.0001, 0.0);
 75  	float d = sdf(p);
 76  	vec3 n = d - vec3(
 77  		sdf(p - e.xyy),
 78  		sdf(p - e.yxy),
 79  		sdf(p - e.yyx)
 80  	);
 81  	return normalize(n);
 82  }
 83  RayHit rayMarch(vec3 origin, vec3 dir) {
 84  	RayHit dummy = RayHit(-1.0, -1, vec3(0.0, 1.0, 0.0));
 85  	float t = 0.0;
 86  	for (int i = 0; i < MAX_STEPS; i++) {
 87  		vec3 p = fma(dir, vec3(t), origin);
 88  		float res = sdf(p);
 89  		if (res < (MIN_DISTANCE))
 90  			return RayHit(t, 0, normal(p));
 91  		if (res > MAX_DISTANCE)
 92  			return dummy;
 93  		t += res;
 94  	}
 95  
 96  	return dummy;
 97  }
 98  float map(float value, float min1, float max1, float min2, float max2) {
 99  	return min2 + (value - min1) * (max2 - min2) / (max1 - min1);
100  }
101  
102  void main() {
103  	ivec2 pixelCoord = ivec2(gl_GlobalInvocationID.xy);
104  
105  	vec2 pixelCoordF = vec2(pixelCoord);
106  	vec2 dims = vec2(float(WIDTH), float(HEIGHT));
107  	vec2 uv = pixelCoordF / dims * 2.0;
108  	uv.x = uv.x - 1.0;
109  	uv.y = 1.0 - uv.y;
110  
111  	vec3 origin = cam_pos.xyz;
112  	vec3 dir = normalize(
113  		fma(vec3(cam_xAxis), vec3(uv.x),
114  			fma(vec3(cam_yAxis), vec3(uv.y),
115  				vec3(cam_front) * radians(cam_fov)
116  			)
117  		)
118  	);
119  
120  	float t = time * TIMESCALE;
121  	for (int i = 0; i < SPHERE_COUNT; i++) {
122  		Sphere sp = Sphere(
123  			fma(sin(sp_speed[i].xyz * t), vec3(MOVESCALE), sp_pos[i].xyz),
124  			sp_radius[i]
125  		);
126  		localSpheres[i] = sp;
127  	}
128  
129  	vec4 pixel = vec4(0.0);
130  
131  	RayHit hit = rayMarch(origin, dir);
132  	if (hit.dist != -1.0) {
133  		pixel = vec4(hit.normal, 1.0);
134  		float t = dot(hit.normal, dir)
135  			+ time * TIMESCALE * 0.05;
136  		float a = 1.0; // map(hit.dist, 4.0, 12.0, 1.0, 0.5);
137  		pixel = vec4(palette(t).xyz, a);
138  	}
139  
140  	imageStore(imgOutput, pixelCoord, pixel);
141  }