rusting_engine 2.7.0

Vulkan 3D game engine with GPU-accelerated physics for massive physics-heavy scenes
#version 450
layout(location = 0) in vec3 position;
layout(location = 1) in vec3 normal;
layout(location = 2) in vec2 uv;
layout(location = 3) in vec4 tangent;
layout(location = 5) in vec4 color;
// Per-vertex data: bits 0-15 a block id, bits 16-22 RUSTING_FLAG_* flags.
layout(location = 6) in uint data;
layout(location = 0) out vec3 v_normal;
layout(push_constant) uniform Camera {
    mat4 view_projection;
    vec4 eye;
    vec4 ambient;
    vec4 ground_ambient;
    uvec4 light_info;
} camera;
struct PhysicsState {
    mat4 model;
    vec4 velocity;
    vec4 angular_velocity;
    vec4 properties;
    vec4 custom_values;
    uvec4 metadata;
};
layout(set = 0, binding = 0) readonly buffer PhysicsStates {
    PhysicsState data[];
} physics_states;
struct RenderInstance {
    mat4 model;
    mat3x4 normal;
    vec4 color;
    vec4 emissive;
    vec4 surface;
    uvec4 physics;
    vec4 transmission;
    vec4 uv_transform;
    vec4 splat_scale;
    vec4 water;
};
layout(set = 0, binding = 1) readonly buffer RenderInstances {
    RenderInstance data[];
} render_instances;
layout(location = 1) out vec4 v_color;
layout(location = 2) out vec3 v_world_position;
layout(location = 3) flat out uvec3 v_alpha;
layout(location = 4) out vec2 v_uv;
layout(location = 5) out vec4 v_tangent;
layout(location = 6) flat out vec4 v_emissive;
layout(location = 7) flat out vec4 v_surface;
layout(location = 8) flat out vec4 v_transmission;
layout(location = 9) flat out vec4 v_splat_scale;
layout(location = 10) flat out vec3 v_tint;
layout(location = 11) flat out vec4 v_water;
layout(location = 12) out float v_crest;
layout(location = 13) flat out uint v_data;
// Index into render_instances from the per-frame visible list.
layout(location = 4) in uint instance_index;
// Wind sway: `Foliage` copies and swaying materials carry their lean per
// unit of wind in normal[0].w, a gust frequency in normal[1].w and a bend
// height in normal[2].w, and bend by the force fields at their base, as
// `lean_matrix` on the CPU did.
#define NO_BODY_SHAPES
#include <physics_shapes.glsl>
#include <physics_fields.glsl>
vec2 foliage_lean(float sway, float frequency, vec3 base, float seconds) {
    if (sway <= 0.0) return vec2(0.0);
    vec3 push = field_push(base, 0.001, uint(force_fields.data.length()), seconds);
    vec2 lean = push.xz * sway;
    if (frequency > 0.0) {
        // Gusts, phased by position so neighbours do not move together.
        float phase = dot(base.xz, vec2(0.37, 0.61));
        lean *= 1.0 + 0.5 * sin(6.2831853 * frequency * seconds + phase);
    }
    // Past 45 degrees a copy would stretch more than it leans.
    float size = length(lean);
    return size > 1.0 ? lean / size : lean;
}
// Sideways reach per unit of lean at `y` above the base, and its slope.
// With a bend height the base stays rooted: y^2 / 2h curves up to slope 1
// at h, then runs straight. Without one the whole mesh shears.
vec2 sway_bend(float y, float height) {
    if (height <= 0.0) return vec2(y, 1.0);
    if (y <= 0.0) return vec2(0.0);
    return y < height ? vec2(y * y / (2.0 * height), y / height) : vec2(y - 0.5 * height, 1.0);
}
// Gerstner waves of water surfaces (`physics.w` bit 3), two vec4s each:
// direction xz, wavenumber, height; then steepness and travelled phase.
// The instance's normal[0].w is its crest foam, normal[1].w its first wave
// and normal[2].w the count.
layout(set = 0, binding = 16) readonly buffer WaterWaves { vec4 data[]; } water_waves;
// Moves a flat grid point to its spot on the waves; returns the normal.
// `pinch` is how far the sideways sway squeezes the surface: one minus the
// determinant of its Jacobian, 1 where a crest folds to a point.
vec3 water_wave(inout vec3 point, uint first, uint count, out float pinch) {
    vec2 start = point.xz;
    vec2 tilt = vec2(0.0);
    float up = 1.0;
    // xx, zz and xz of the Jacobian's shrink, steepness * sin * D D^T.
    vec3 squeeze = vec3(0.0);
    for (uint index = first; index < first + count; index++) {
        vec4 shape = water_waves.data[2u * index];
        vec4 motion = water_waves.data[2u * index + 1u];
        float phase = shape.z * dot(shape.xy, start) - motion.y;
        float s = sin(phase);
        float c = cos(phase);
        point.y += shape.w * s;
        point.xz += motion.x / shape.z * shape.xy * c;
        tilt += shape.z * shape.w * shape.xy * c;
        up -= motion.x * s;
        squeeze += motion.x * s * shape.xyx * shape.xyy;
    }
    pinch = 1.0 - ((1.0 - squeeze.x) * (1.0 - squeeze.y) - squeeze.z * squeeze.z);
    return normalize(vec3(-tilt.x, max(up, 1e-3), -tilt.y));
}
// The shader pack vertex hook; see vertex_hook.glsl.
#include "vertex_hook.glsl"
void main() {
    RenderInstance instance = render_instances.data[instance_index];
    mat4 model = instance.physics.x == 0xffffffffu
        ? instance.model
        : physics_states.data[instance.physics.x].model;
    vec4 world_position = model * vec4(position, 1.0);
    bool waves = (instance.physics.w & 8u) != 0u;
    vec3 wave_normal = vec3(0.0, 1.0, 0.0);
    float pinch = 0.0;
    if (waves) {
        wave_normal = water_wave(world_position.xyz, uint(instance.normal[1].w), uint(instance.normal[2].w), pinch);
    }
    v_crest = waves ? clamp(instance.normal[0].w * pinch, 0.0, 1.0) : 0.0;
    vec2 lean = waves ? vec2(0.0) : foliage_lean(instance.normal[0].w, instance.normal[1].w, model[3].xyz, camera.ambient.w);
    vec2 bend = sway_bend(world_position.y - model[3].y, instance.normal[2].w);
    world_position.xz += lean * bend.x;
    // Normals and tangents follow the local shear, the lean times the slope.
    lean *= bend.y;
    mat3 normal_matrix;
    if (instance.physics.x == 0xffffffffu) {
        normal_matrix = mat3(instance.normal);
    } else {
        // GPU bodies are rotation times scale with no shear, so dividing
        // each column by its squared length gives the inverse-transpose.
        mat3 linear = mat3(model);
        normal_matrix = mat3(
            linear[0] / dot(linear[0], linear[0]),
            linear[1] / dot(linear[1], linear[1]),
            linear[2] / dot(linear[2], linear[2]));
    }
    v_normal = waves ? wave_normal : normal_matrix * normal;
    // The lean is a shear; normals take its inverse transpose.
    v_normal.y -= lean.x * v_normal.x + lean.y * v_normal.z;
    // Terrain vertex colors are splat weights, normalized per pixel: the
    // material color tints the blended layers instead of the weights.
    bool splat = abs(instance.transmission.w - 1.0) < 0.5;
    v_color = splat ? color : instance.color * color;
    v_tint = splat ? instance.color.rgb : vec3(1.0);
    v_world_position = world_position.xyz;
    v_alpha = instance.physics.yzw;
    v_uv = uv * instance.uv_transform.xy + instance.uv_transform.zw;
    // Tangents follow the surface, so they take the model's linear part.
    v_tangent = vec4(mat3(model) * tangent.xyz, tangent.w);
    v_tangent.xz += lean * v_tangent.y;
    v_emissive = instance.emissive;
    v_surface = instance.surface;
    v_transmission = instance.transmission;
    v_splat_scale = instance.splat_scale;
    v_water = instance.water;
    v_data = data;
#ifdef RUSTING_CUSTOM_VERTEX
    VertexOutput o = VertexOutput(world_position.xyz, v_normal, v_color);
    vertex(VertexInput(position, world_position.xyz, v_normal, v_uv, v_color,
        data & 0xffffu, data & ~0xffffu, camera.ambient.w), o);
    world_position.xyz = o.world_position;
    v_world_position = o.world_position;
    v_normal = o.normal;
    v_color = o.color;
#endif
    gl_Position = camera.view_projection * world_position;
    // Viewmodel meshes take their own field of view and squash toward the
    // near plane, so they draw over the world without a depth clear.
    if ((instance.physics.w & 4u) != 0u) {
        gl_Position.xy *= camera.ground_ambient.w;
        gl_Position.z *= 0.05;
    }
}