Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- struct Ray {
- vec3 origin;
- vec3 dir;
- };
- struct Light {
- vec3 pos;
- };
- struct Camera {
- vec3 pos;
- Ray ray;
- float rayDivergence;
- };
- struct Sphere {
- vec3 center;
- float radius;
- };
- struct Plane {
- float yCoord;
- };
- float unionOp(float d0, float d1) {
- return min(d0, d1);
- }
- float distToSphere(in Ray r, in Sphere s) {
- float d = distance(r.origin, s.center);
- return d - s.radius;
- }
- float distToPlane(in Ray r, in Plane p) {
- return r.origin.y - p.yCoord;
- }
- vec2 distToScene(in Ray r) {
- Plane p = Plane(0.0);
- float d2p = distToPlane(r, p);
- Sphere s = Sphere(vec3(0.0, 6.0, 0.0), 6.0);
- float d2s = distToSphere(r, s);
- float dist = unionOp(d2s, d2p);
- float o = 0.0; // 0 means plane is closer
- if (d2p > d2s) {
- o = 1.0; // 1 means sphere is closer
- }
- vec2 obj = vec2(dist, o);
- return obj;
- }
- vec3 getNormal(in Ray ray) {
- vec2 eps = vec2(0.001, 0.0);
- vec3 n = vec3(distToScene(Ray(ray.origin + eps.xyy, ray.dir)).x -
- distToScene(Ray(ray.origin - eps.xyy, ray.dir)).x,
- distToScene(Ray(ray.origin + eps.yxy, ray.dir)).x -
- distToScene(Ray(ray.origin - eps.yxy, ray.dir)).x,
- distToScene(Ray(ray.origin + eps.yyx, ray.dir)).x -
- distToScene(Ray(ray.origin - eps.yyx, ray.dir)).x);
- return normalize(n);
- }
- float ao(in vec3 pos, in vec3 n) {
- float eps = 0.01;
- pos += n * eps * 2.0;
- float occlusion = 0.0;
- for (float i=1.0; i<10.0; i++) {
- float dist = distToScene(Ray(pos, vec3(0))).x;
- float coneWidth = 2.0 * eps;
- float occlusionAmount = max(coneWidth - dist, 0.0);
- float occlusionFactor = occlusionAmount / coneWidth;
- occlusionFactor *= 1.0 - (i / 10.0);
- occlusion = max(occlusion, occlusionFactor);
- eps *= 2.0;
- pos += n * eps;
- }
- return max(0.0, 1.0 - occlusion);
- }
- Camera setupCam(in vec3 pos, in vec3 target, in float fov, in vec2 uv) {
- uv *= fov;
- vec3 cw = normalize (target - pos);
- vec3 cp = vec3 (0.0, 1.0, 0.0);
- vec3 cu = normalize(cross(cw, cp));
- vec3 cv = normalize(cross(cu, cw));
- vec3 dir = normalize (uv.x * cu + uv.y * cv + 0.5 * cw);
- Ray ray = Ray(pos, dir);
- Camera cam = Camera(pos, ray, fov / iResolution.x);
- return cam;
- }
- void reflectRay(inout Camera cam, vec3 n, float eps) {
- cam.ray.origin += n * eps;
- cam.ray.dir = reflect(cam.ray.dir, n);
- }
- vec3 refractRay(float object) {
- vec3 rayColor = vec3(1.0);
- if (object == 1.0) {}
- else if (object == 0.0) {}
- return rayColor;
- }
- void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
- vec2 uv = fragCoord.xy / iResolution.xy;
- uv = uv * 2.0 - 1.0;
- uv.y *= iResolution.y / iResolution.x;
- // Lets have the camera moving so we can see what's happening
- vec3 camPos = vec3(sin(iTime)*15., sin(iTime)*5.+7., cos(iTime)*15.);
- Camera cam = setupCam(camPos, vec3(0.0), 1.25, uv);
- vec3 col = vec3(1.);
- bool hit = false;
- float eps = 0.01;
- float object;
- bool inside = false;
- for (int i=0; i<300; i++) {
- vec2 obj = distToScene(cam.ray);
- float dist = obj.x * (inside ? -1. : 1.);
- float o = obj.y;
- if (dist < eps) {
- vec3 normal = getNormal(cam.ray) * (inside ? -1. : 1.);
- if (object == 0.0) {
- // AO on glass doesn't work, so we do AO on the floor only
- // Note: if ray hits floor and bounces out into the sky, then
- // doing AO at the end means adding AO to the sky! Has to be done here.
- float o = ao(cam.ray.origin, normal);
- col *= o;
- // Do the colour stuff
- vec2 pos = cam.ray.origin.xz;
- pos *= 0.1;
- pos = floor(mod(pos, 2.0));
- float check = mod(pos.x + pos.y, 2.0);
- col *= check * 0.6 + 0.2;
- // reflect the ray
- reflectRay(cam, normal, eps);
- } else if (object == 1.0) {
- // Don't forget to switch in/out when we hit the glass!
- inside = !inside;
- float ior = inside ? 1.0 / 1.5 : 1.5;
- cam.ray.origin -= normal * eps * 2.0;
- cam.ray.dir = refract(cam.ray.dir, normal, ior);
- }
- // We don't hit now, since the ray is either reflected or refracted!
- // hit = true;
- }
- if (o == 1.0) { object = 1.0; } else { object = 0.0; }
- cam.ray.origin += cam.ray.dir * dist;
- eps += cam.rayDivergence * dist;
- }
- // Because we ignore the 'hit' value, the ray always ends up the sky:
- col.rgb *= mix(vec3(.8 ,.8, .4), vec3(.4, .4, 1.), cam.ray.dir.y);
- fragColor.rgb = col;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement