Skip to content

Instantly share code, notes, and snippets.

@0smr
Last active January 4, 2024 05:11
Show Gist options
  • Select an option

  • Save 0smr/20155fecbe8e892afc76cdb708524aae to your computer and use it in GitHub Desktop.

Select an option

Save 0smr/20155fecbe8e892afc76cdb708524aae to your computer and use it in GitHub Desktop.
Sphere of particles fragment shader using raymarching

Sphere of particles

A sphere of particles in the fragment shader using raymarching.

Warning

The sphere is not rendered correctly, and there are glitches in the rendred result. Any suggestions to get rid of those glitches are welcome.

Preview


Sphere of tiny particle
// template: https://www.shadertoy.com/view/WtGXDD
#ifdef GL_ES
precision mediump float;
#endif
#define MAX_STEPS 100
#define MAX_DIST 10.
#define SURF_DIST .001
#define TAU 6.283185
#define PI 3.141592
#define S smoothstep
#define T u_time
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
// Precision-adjusted variations of https://www.shadertoy.com/view/4djSRW
float hash(float p) { p = fract(p * 0.011); p *= p + 7.5; p *= p + p; return fract(p); }
float hash(vec2 p) {vec3 p3 = fract(vec3(p.xyx) * 0.13); p3 += dot(p3, p3.yzx + 3.333); return fract((p3.x + p3.y) * p3.z); }
float noise(vec2 x) {
vec2 i = floor(x);
vec2 f = fract(x);
float a = hash(i);
float b = hash(i + vec2(1.0, 0.0));
float c = hash(i + vec2(0.0, 1.0));
float d = hash(i + vec2(1.0, 1.0));
vec2 u = f * f * (3.0 - 2.0 * f);
return mix(a, b, u.x) + (c - a) * u.y * (1.0 - u.x) + (d - b) * u.x * u.y;
}
mat2 Rot(float a) { float s=sin(a), c = cos(a); return mat2(c, -s, s, c); }
float fold(vec3 p, float n, float arct) {
float section = 6.283185 / n;
return floor(0.5 + arct / section) * section;
}
float GetDist(vec3 p) {
float div = 150.0, radius = 1.0, yid, xzid, size = 1.0/div;
yid = fold(p, div, atan(p.y, p.z));
p.xz *= Rot(sin(40. * yid + T) / 30.0);
xzid = fold(p, div, atan(p.x, p.z));
p.yz *= Rot(xzid / 1.5 + sin(xzid + T / 10.0) / 10.);
xzid = fold(p, div, atan(p.x, p.z)); p.xz *= Rot(xzid);
yid = fold(p, div, atan(p.y, p.z)); p.yz *= Rot(yid);
float noise2d = noise(vec2(yid, xzid) * 5.0 + (T/5.));
radius += 0.02 * sin(xzid * 6.28 + T);
radius -= 0.1 * noise2d;
size *= noise2d;
return length(p - vec3(0, 0, radius)) - size;
}
float RayMarch(vec3 ro, vec3 rd) {
float dO = 0.;
for(int i = 0; i < MAX_STEPS; i++) {
vec3 p = ro + rd * dO;
float dS = GetDist(p);
dO += dS;
if(dO > MAX_DIST || abs(dS) < SURF_DIST) break;
}
return dO;
}
vec3 GetNormal(vec3 p) {
vec2 e = vec2(.001, 0);
vec3 n = GetDist(p) - vec3(GetDist(p-e.xyy), GetDist(p-e.yxy),GetDist(p-e.yyx));
return normalize(n);
}
vec3 GetRayDir(vec2 uv, vec3 p, vec3 l, float z) {
vec3 f = normalize(l-p),
r = normalize(cross(vec3(0,1,0), f)),
u = cross(f,r),
c = f*z,
i = c + uv.x*r + uv.y*u;
return normalize(i);
}
void main() {
vec2 uv = (gl_FragCoord.xy - .5 * u_resolution.xy)/u_resolution.y;
vec2 m = u_mouse.xy/u_resolution.xy;
vec3 ro = vec3(0, 0.2, 3.0); // camera position
vec3 rd = GetRayDir(uv, ro, vec3(0,0.,0), 1.2);
vec3 col = vec3(0);
float d = RayMarch(ro, rd);
if(d<MAX_DIST) {
vec3 p = ro + rd * d;
vec3 n = GetNormal(p);
float dif = dot(n, normalize(vec3(1))) * .5 + .5;
col = vec3(dif) * mix(vec3(0.4, 0.0, 0.0), vec3(0.0, 1.0, 1.0), (length(p) - 0.92) * 20.0);
}
col = pow(col, vec3(.4545)); // gamma correction
gl_FragColor = vec4(col, 1.0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment