perovskite_client 0.3.2

Multiplayer voxel game written in Rust - Game client
#version 460
#extension GL_ARB_shading_language_include : enable

#define SKIP_MASK 4u
#include "raytracer_frag_common.glsl"

layout(input_attachment_index = 0, set = 1,
       binding = 3) uniform subpassInput f_depth_in;
layout(location = 0) out vec4 f_color;
layout(location = 1) out vec4 deferred_specular_strength;
layout(location = 2) out uvec4 deferred_specular_ray_dir;

void main() {
  deferred_specular_strength = vec4(0);
  deferred_specular_ray_dir = uvec4(0);

  if (RAYTRACE_DEBUG) {
    vec2 pix3 = gl_FragCoord.xy / (16.0 * SUPERSAMPLING);
    int ix3 = int(pix3.x);
    int iy3 = int(pix3.y);

    if (iy3 == 1) {
      if (ix3 <= 160 && ix3 >= 1) {
        int idx = ix3 - 1;
        int idx0 = idx >> 5;
        uint dbg_data;
        if (idx0 == 0) {
          dbg_data = n_minus_one;
        }
        if (idx0 == 1) {
          dbg_data = mxc;
        }
        if (idx0 == 2) {
          dbg_data = k.x;
        }
        if (idx0 == 3) {
          dbg_data = k.y;
        }
        if (idx0 == 4) {
          dbg_data = k.z;
        }
        uint idx1 = uint(idx & 31);
        uint bit = dbg_data & (1u << idx1);
        if (bit != 0) {
          f_color = vec4(1.0, 0.0, 0.0, 1.0);
          return;
        } else {
          f_color = vec4(0.0, 0.0, 0.0, 1.0);
          return;
        }
      }
    }
    if (iy3 == 2) {
      if (ix3 <= 160 && ix3 >= 1) {
        int idx = ix3 - 1;
        int idx0 = idx >> 5;
        if (idx0 == 0) {
          f_color = vec4(1.0, 0.0, 0.0, 1.0);
          return;
        } else if (idx0 == 1) {
          f_color = vec4(1.0, 1.0, 0.0, 1.0);
          return;
        } else if (idx0 == 2) {
          f_color = vec4(0.0, 1.0, 0.0, 1.0);
          return;
        } else if (idx0 == 3) {
          f_color = vec4(0.0, 0.0, 1.0, 1.0);
          return;
        } else if (idx0 == 4) {
          f_color = vec4(1.0, 1.0, 0.0, 1.0);
          return;
        }
      }
    }

    if (iy3 == 3) {
      if (ix3 <= 160 && ix3 >= 1) {
        int idx = ix3 - 1;
        if ((idx % 2) == 0) {
          f_color = vec4(0.2, 1.0, 0.4, 1.0);
          return;
        } else {
          f_color = vec4(1.0, 1.0, 0.0, 1.0);
          return;
        }
      }
    }
    vec2 pix_fine = gl_FragCoord.xy / (2 * SUPERSAMPLING);
    int ixp = int(pix_fine.x);
    int iyp = int(pix_fine.y) - 64;
    uint rows = (n_minus_one + 1) / 1024;
    if (iyp >= 0 && iyp < rows) {
      if (ixp < 1024) {
        uint slot = iyp * 1024 + ixp;
        uint slot_base = slot * 4;

        if ((chunks[slot_base] & 1) == 0) {
          f_color = vec4(0, 0, 0, 1);
          return;
        }
        uvec3 putative = uvec3(chunks[slot_base + 1], chunks[slot_base + 2],
                               chunks[slot_base + 3]);
        uvec3 products = putative * k;
        uint sum = products.x + products.y + products.z;
        uint try_slot = (sum % 1610612741) & n_minus_one;
        if (try_slot == slot) {
          f_color = vec4(0, 1, 0, 1);
          return;
        } else {
          f_color = vec4(1, 1, 0, 1);
          return;
        }
      }
    }
  } // if (RAYTRACE_DEBUG)

  f_color = vec4(0);
  vec3 facedir_world = normalize(facedir_world_in);
  float prev_depth = subpassLoad(f_depth_in).r;

  // There are some fixups done between the raster and raytrace pipelines:
  // All raster geometry, as well as non-rendering calcs, assume that blocks
  // have their *centers* at integer coordinates. However, we have the *edges*
  // as integer-aligned in this code. Note that this shader works in world
  // space, with Y up throughout. The Y axis orientation has been flipped in the
  // calculation of facedir_world.
  vec2 t_min_max = t_range(fine_pos, facedir_world);

  if (t_min_max.x > t_min_max.y) {
    return;
  }

  vec3 g0 = fine_pos + (t_min_max.x * facedir_world);
  vec3 g1 = fine_pos + (t_min_max.y * facedir_world);

  float strongest_specular = 0;
  uint prev_block = initial_block_id;
  for (int i = 0; i < 5; i++) {
    HitInfo info = {
        ivec3(0), vec3(0), vec3(0), prev_block, 0,
    };

    if (!traverse_space(g0, g1, info)) {
      return;
    }
    // traverse_space will put valid data into info iff it returns true
    prev_block = info.block_id;
    uint info_flags = cube_info[prev_block >> 12].flags;
    vec3 hit_pos = (vec3(info.hit_block) + info.start_cc) / 32.0;
    vec4 rpos = vec4((hit_pos - fine_pos) * 32.0, 1.0) * vec4(1, -1, 1, 1);
    vec4 transformed = forward_vp_matrix * rpos;
    if (clamp(transformed.z / transformed.w, 0, 1) > prev_depth) {
      return;
    }

    // skip fallback blocks
    if (info_flags != 0) {
      if ((info_flags & 4u) != 4) {
        SampleResult result = sample_simple(info, prev_block >> 12, SPECULAR);
        float alpha_contrib = (1 - f_color.a) * result.diffuse.a;
        f_color.rgb += alpha_contrib * result.diffuse.rgb;
        f_color.a += alpha_contrib;

        if (SPECULAR) {
          if (length(result.specular.rgb) > 0.01) {
            vec3 new_dir;
            vec3 normal = decode_normal(info.face_light & 7u);
            if (FUZZY_SHADOWS) {
              vec3 tangent = normalize(cross(facedir_world, normal));
              vec3 bitangent = cross(normal, tangent);
              mat3 ntb = mat3(normal, tangent, bitangent);
              vec3 mul =
                  vec3(0, 0.03 * (random(hit_pos.xz, 43758.5453123) - 0.5),
                       0.01 * random(hit_pos.xz, 43758.5453123));

              new_dir = facedir_world * face_reflectors[info.face_light & 7u] +
                        (ntb * mul);
            } else {
              new_dir = facedir_world * face_reflectors[info.face_light & 7u];
            }
            float cos_theta = dot(normal, new_dir);
            float fresnel = min((0.02 + 0.98 * pow(1 - cos_theta, 5)), 1.0);
            vec3 final_mix =
                mix(fresnel, 1.0, result.diffuse.a) * result.specular.rgb;
            if (length(final_mix) >= strongest_specular) {
              deferred_specular_strength = vec4(final_mix, 1.0);
              new_dir = normalize(new_dir) * length(hit_pos - fine_pos);
              deferred_specular_ray_dir =
                  uvec4(floatBitsToUint(new_dir), info.block_id);
              strongest_specular = length(final_mix);
            }
          }
        }

        if (f_color.a > 0.99) {
          break;
        }
      }
    }
    info.start_cc = mix(info.start_cc, info.end_cc, 0.5);
    g0 = (vec3(info.hit_block) + info.start_cc) / 32.0;
  }
}