114 lines
2.4 KiB
GLSL
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);
|
||
|
}
|