Public
Edited
Nov 27, 2024
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
// viewof
module = wgsl`

struct Vertex {
@builtin(vertex_index)
vertex_index : u32,
};

struct Point {
@builtin(position)
position: vec4f,
};

struct Uniforms {
time: f32,
frame: u32,
resolution: vec4f,
view: mat4x4f,
};

struct Pointers {
count: u32,
positions: array<vec4f, 10>,
}

struct Ray {
origin: vec3f,
// assume direction is normalized
direction: vec3f,
};


@group(0) @binding(0) var<uniform> uniforms: Uniforms;

@group(1) @binding(0) var<uniform> pointers: Pointers;

const bin = vec4f(-1,3,0,1);

const points = array(
Point(
bin.xxzw,
),
Point(
bin.xyzw,
),
Point(
bin.yxzw,
),
);

const spheres = array(
// cube
bin.xxxw,
bin.xxww,
bin.xwxw,
bin.xwww,
bin.wxxw,
bin.wxww,
bin.wwxw,
bin.wwww,
// octahedron
bin.zzww,
bin.zzxw,
bin.zwzw,
bin.zxzw,
bin.wzzw,
bin.xzzw,
);


fn set_xyz(point: ptr<function, vec4f>, value: vec3f) {
*point = vec4(value, (*point).w);
}

fn ray_point(ray: Ray, t: f32) -> vec3f {
return ray.origin + t * ray.direction;
}

// apply projective transform
// in affine space
fn rotate(point: vec3f, transform: mat4x4f) -> vec3f {
let q = transform * vec4(point, 1);
return q.xyz / q.w;
}

// apply projective function
// in tangent space
fn rotate_direction(direction: vec3f, transform: mat4x4f) -> vec3f {
let q = transform * vec4(direction, 0);
return q.xyz;
}

fn rotate_ray(ray: Ray, transform: mat4x4f) -> Ray {
return Ray(
rotate(ray.origin, transform),
rotate_direction(ray.direction, transform)
);
}

fn rotate_ray_ref(ray: ptr<function, Ray>, transform: mat4x4f) {
(*ray).origin = rotate((*ray).origin, transform);
(*ray).direction = rotate((*ray).direction, transform);
}

fn sphere(color: ptr<function, vec4f>, ray: Ray, center: vec3f, r: f32) {
let offset = center - ray.origin;
let t_closest = dot(offset, ray.direction);
let closest = ray_point(ray, t_closest);
let d = distance(closest, center);
if (d > r) {
return;
}
let dt = sqrt(r*r - d*d);
var t = t_closest - dt;
if (t < 0.01) {
t = t_closest + dt;
if (t < 0.01) {
return;
}
}
var z = (*color).w - 1;
if (z == 0) {
z = 100.0;
}
if (t > z) {
return;
}
(*color).w = t + 1;

let intersection = ray_point(ray, t);
let normal = (intersection - center) / r;
set_xyz(color, .8*(.5 + .5*normal));
*color += vec4(
vec3(.2 * fract(1.5*intersection)),
0);
var fresnel = length(cross(normal, ray.direction));
fresnel=saturate(exp(fresnel - 3.));
//set_xyz(color, mix(color.xyz, vec3(1), fresnel);
}

fn rescale(pixels: vec2f) -> vec2f {
return 2
* (pixels - uniforms.resolution.xy / 2)
/ uniforms.resolution.z;
}


@vertex fn vertex(
vert: Vertex,
) -> Point {
return points[vert.vertex_index];
}

@fragment fn fragment(point: Point) -> @location(0) vec4f {
_ = uniforms;
_ = pointers;
var pos = rescale(point.position.xy);
pos *= 1.25;
var d = length(pos);
d = smoothstep(1.1, 1.2, d) *exp(-d);
var color: vec4f = vec2(d, 1.0).xxxy;
let origin = vec3(pos, -5);
var ray = Ray(
origin,
// ortographic
//vec3(0,0,1),
normalize(origin + vec3(0,0,10))
);
rotate_ray_ref(&ray, uniforms.view);
sphere(&color, ray, vec3(0.0), 1.0);
for (var i = 0u; i < 8u + 6u; i++) {
let s = spheres[i];
sphere(&color, ray, s.xyz, s.w / 10);
}

for (var i = 0u; i < pointers.count; i++) {
let pointer = pointers.positions[i];
var d = 0.03 * length(
(point.position.xy
- pointer.xy)
/ vec2(pointer.zw)
);
color = mix(
color,
vec4(1.0),
exp(-d)
);
}
return color;
}

`.value
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more