raytracer/raycast.frag
2024-05-10 09:06:15 +12:00

114 lines
2.4 KiB
GLSL

#version 460 core
in vec2 pos;
out vec4 color;
layout(location = 0) uniform float aspect_ratio;
layout(location = 1) uniform float sphere_y;
layout(std430, binding = 0) buffer data
{
int ray_count;
};
struct Ray {
vec3 origin;
vec3 direction;
};
struct Sphere {
vec3 center;
float radius;
};
vec3 unit_vector(vec3 v) {
return v / length(v);
}
float length_squared(vec3 v) {
float length = length(v);
return length * length;
}
float hit_sphere(Ray r, Sphere s) {
vec3 oc = s.center - r.origin;
float a = length_squared(r.direction);
float h = dot(r.direction, oc);
float c = length_squared(oc) - s.radius * s.radius;
float discriminant = h * h - a * c;
if(discriminant > 0.0) {
return (h - sqrt(discriminant)) / a;
}
return -1.0;
}
vec3 at(Ray r, float time) {
return r.origin + time * r.direction;
}
vec3 get_normal_color(Ray r, vec3 pos, Sphere s) {
vec3 normal = unit_vector(pos - s.center);
return 0.5 * vec3(normal + vec3(1.0, 1.0, 1.0));
}
Sphere spheres[] = {
Sphere(vec3(0, sphere_y, -1), 0.5),
Sphere(vec3(2, 0, 0), 0.25),
Sphere(vec3(0, -100.5, -1), 100.0)
};
struct HitInfo {
vec3 pos;
bool hit;
int index;
};
HitInfo hit_spheres(Ray r) {
float t_min = 0;
int index;
bool hit = false;
for(int i = 0; i < spheres.length(); i++) {
Sphere s = spheres[i];
float t = hit_sphere(r, s);
if(t > 0.0 && (!hit || t < t_min)) {
t_min = t;
index = i;
hit = true;
}
}
return HitInfo(hit ? at(r, t_min) : vec3(0.0), hit, index);
}
vec3 ray_color(Ray r) {
HitInfo info = hit_spheres(r);
if(info.hit) {
vec3 sun_dir = vec3(10, 10, 10) - info.pos;
Ray sun_ray = Ray(info.pos, sun_dir);
HitInfo sun_hit = hit_spheres(sun_ray);
return get_normal_color(r, info.pos,
spheres[info.index]) -
(sun_hit.hit && sun_hit.index != info.index ? 0.4 : 0.0);
}
vec3 unit_direction = unit_vector(r.direction);
float a = 0.5 * (unit_direction.y + 1.0);
return (1.0 - a) * vec3(1.0, 1.0, 1.0) + a * vec3(0.5, 0.7, 1.0);
}
void main() {
vec3 p = vec3(pos, 0.0);
p.x *= aspect_ratio;
vec3 camera_pos = vec3(0.0, 0.0, 0.0);
camera_pos.z += 1.0;
vec3 ray_dir = p - camera_pos;
Ray r = Ray(camera_pos, ray_dir);
color = vec4(ray_color(r), 1.0);
}