perovskite_client 0.3.2

Multiplayer voxel game written in Rust - Game client
#version 460
#extension GL_ARB_shading_language_include : enable
#include "color_mapping.glsl"

layout(location = 0) in vec2 uv_texcoord;
layout(location = 1) flat in float brightness;
layout(location = 2) flat in vec3 global_brightness;
layout(location = 3) flat in vec3 world_normal;
layout(location = 4) in vec3 world_pos;
layout(location = 5) flat in vec3 world_tangent;
layout(location = 6) flat in uint texture_flags;

layout(set = 0, binding = 0) uniform sampler2D diffuse_tex;
#ifdef ENABLE_BASIC_COLOR
// No specular, discard if SPARSE
layout(location = 0) out vec4 f_color;
layout(set = 0, binding = 1) uniform sampler2D emissive_tex;
#endif

#ifdef ENABLE_UNIFIED_SPECULAR
// Unified specular, never discard
layout(location = 0) out vec4 f_color;
layout(location = 1) out vec4 spec_strength;
layout(location = 2) out uvec4 spec_dir;

layout(set = 0, binding = 1) uniform sampler2D emissive_tex;
layout(set = 0, binding = 2) uniform sampler2D specular_tex;
layout(set = 0, binding = 3) uniform sampler2D normal_tex;
#endif

#ifdef ENABLE_SPECULAR_ONLY
// Specular only, discard zero specular
layout(location = 0) out vec4 spec_strength;
layout(location = 1) out uvec4 spec_dir;

layout(set = 0, binding = 1) uniform sampler2D specular_tex;
layout(set = 0, binding = 2) uniform sampler2D normal_tex;
#endif

layout(constant_id = 0) const bool SPARSE = true;
layout(constant_id = 1) const bool DEBUG_INVERT_RASTER_TRANSPARENT = true;

float random(vec2 st, float f) {
  return fract(sin(dot(st.xy + vec2(32.2, 17.3), vec2(12.9898, 78.233))) * f);
}

void main() {

  vec2 tile_control = fract(1.0 * uv_texcoord * textureSize(diffuse_tex, 0));
  vec4 diffuse = texture(diffuse_tex, uv_texcoord);
  bool wall_tiles =
      (texture_flags & 0x100) != 0 && length(world_pos) < 16 &&
      (tile_control.x < 0.03125 || tile_control.x > 1.0 - 0.03125 ||
       tile_control.y < 0.03125 || tile_control.y > 1.0 - 0.03125);
  if (wall_tiles) {
    diffuse = vec4(0.1, 0.1, 0.1, diffuse.a);
  }

  if ((texture_flags & 0x400) == 0x400) {
    uvec2 texel = uvec2(4.0 * uv_texcoord * textureSize(diffuse_tex, 0));
    float cutoff = (texture_flags & 0xFF) / 255.0;
    float rng = random(texel, 4096);
    vec3 desaturated_color =
        vec3(0.8, 0.8, 0.8) * (diffuse.r + diffuse.g + diffuse.b) / 3.0 +
        0.2 * diffuse.rgb;
    if (rng < cutoff) {
      diffuse.rgb = desaturated_color;
    }
  }
#if defined(ENABLE_BASIC_COLOR) || defined(ENABLE_UNIFIED_SPECULAR)
  vec4 emissive = texture(emissive_tex, uv_texcoord);
  if (wall_tiles) {
    emissive = vec4(0.0, 0.0, 0.0, 1.0);
  }

  f_color = combine_colors(diffuse, emissive, world_normal, world_pos,
                           brightness, global_brightness);

  if (DEBUG_INVERT_RASTER_TRANSPARENT) {
    f_color.rgb = 1.0 - f_color.rgb;
  }

#ifdef ENABLE_BASIC_COLOR
  if (SPARSE) {
    if (f_color.a < 0.5) {
      discard;
    } else {
      f_color.a = 1.0;
    }
  }
#endif // ENABLE_BASIC_COLOR
#endif // defined(ENABLE_BASIC_COLOR) || defined(ENABLE_UNIFIED_SPECULAR)

#if defined(ENABLE_SPECULAR_ONLY) || defined(ENABLE_UNIFIED_SPECULAR)
  spec_dir = uvec4(0);
  vec4 specular = texture(specular_tex, uv_texcoord);
  // Weather shader effects are being shelved; it's hard to get a generally
  // correct effect for all materials.
  //
  // if ((texture_flags & 4) == 4) {
  //   // if the surface is wet, make it slightly shiny.
  //   specular.rgb = max(specular.rgb, vec3(0.25, 0.25, 0.25));
  // }

  if (specular.rgb != vec3(0) && !wall_tiles) {
    vec2 normal_map = (texture(normal_tex, uv_texcoord).xy - 0.5) * 1.414;

    float rt_len = (length(world_pos) - 0.05) / 32.0;
    vec3 incident = normalize(world_pos);
    vec3 world_bitangent = cross(world_normal, world_tangent);

    float imputed_normal = sqrt(1 - min(dot(normal_map, normal_map), 1));
    vec3 mul = vec3(imputed_normal, normal_map.yx);

    mat3 ntb = mat3(world_normal, world_tangent, world_bitangent);

    vec3 mapped_normal = ntb * mul;

    vec3 reflection = reflect(incident, mapped_normal);

    float cos_theta = dot(world_normal, reflection);
    float fresnel = min((0.02 + 0.98 * pow(1 - cos_theta, 5)), 1.0);
    spec_strength = vec4(mix(fresnel, 1.0, diffuse.a) * specular.rgb, 1.0);
    reflection.y = -reflection.y;
    spec_dir = uvec4(floatBitsToUint(rt_len * reflection), 0xffffffff);
  } else {
#ifdef ENABLE_SPECULAR_ONLY
    // Do not discard on unified (solid/translucent) materials
    discard;
#endif // ENABLE_SPECULAR_ONLY
  }
#endif // defined(ENABLE_SPECULAR_ONLY) || defined(ENABLE_UNIFIED_SPECULAR)
}