rusting_engine 0.1.43

A high-performance Vulkano-based 3D engine with GPU physics.
Documentation
#version 450
// VERTEX SHADER - Base PBR Vertex Shader

// This shader transforms mesh vertices from model space to clip space.
// It supports instanced rendering and optional frustum culling.

// Per-instance data structure - one per draw instance
// Layout matches the GPU buffer layout for InstanceData
struct InstanceData {
    mat4 model;           // Model-to-world transformation matrix
    vec4 color;           // xyz = base color, w = emissive intensity
    vec4 mat_props;      // x = roughness, y = metalness, z = unused, w = unused
    vec4 velocity;       // xyz = linear velocity, w = bounciness
    vec4 physic;          // x = collision type sort key, y = mass, z = gravity scale, w = unused
    vec4 rotation;       // x = angular velocity X, y = Y, z = Z, w = friction
};

// INPUT ATTRIBUTES (from vertex buffers)

// Vertex attribute layout must match the mesh's vertex format
layout(location = 0) in vec3 position;   // Vertex position in model space
layout(location = 1) in vec3 normal;   // Vertex normal in model space  
layout(location = 2) in vec2 uv;       // Texture coordinates

// OUTPUT VARYINGS (to fragment shader)

layout(location = 0) out vec3 v_color;          // Base color RGB
layout(location = 1) out vec3 v_normal;        // World-space normal (for lighting)
layout(location = 2) out vec3 v_pos;        // World-space position (for lighting)
layout(location = 3) out vec4 v_mat_data;     // Material properties (roughness, metalness)
layout(location = 4) out vec2 v_uv;        // Texture coordinates
layout(location = 5) out float v_emissive;  // Emissive strength (1.0 = glowing)
layout(location = 6) out vec2 v_screen_uv;  // NDC coordinates for post-processing

// UNIFORM BUFFER - Camera and scene data

layout(set = 0, binding = 0) uniform UniformBufferObject {
    mat4 view;       // View matrix (world to camera)
    mat4 proj;       // Projection matrix (camera to clip)
    vec3 eye_pos;   // Camera position in world space
    uint v_base_instance;  // Base instance ID (unused here)
} ubo;

// PUSH CONSTANTS - Per-draw parameters

layout(push_constant) uniform MeshPush {
    uint v_visible_list_offset;   // Offset into visible list for indirect rendering
    uint v_use_culling;        // 0 = draw all, 1 = cull with visible list
} mesh_pc;

// STORAGE BUFFERS - Instance data

// Read-only buffer containing all instance transforms and properties
layout(std430, set = 0, binding = 2) readonly buffer InstanceBuffer { 
    InstanceData instances[]; 
};

// Read-only buffer containing visible instance indices (filled by cull shader)
layout(std430, set = 0, binding = 3) readonly buffer VisibleIndices { 
    uint data[]; 
};

// MAIN ENTRY POINT

void main() {
    // Determine which instance to render:
    // If culling is enabled, read from visible list.
    // Otherwise, use instance ID directly.
    uint actual_id;
    if (mesh_pc.v_use_culling == 1) {
        // Read instance index from the culling output buffer
        actual_id = data[gl_InstanceIndex];
    } else {
        // Direct instance indexing (no culling)
        actual_id = gl_InstanceIndex;
    }
    
    // Fetch this instance's data from the buffer
    InstanceData inst = instances[actual_id];

    // Transform vertex position from model space to world space
    vec4 world_pos = inst.model * vec4(position, 1.0);
    
    // Transform to clip space for rasterization
    gl_Position = ubo.proj * ubo.view * world_pos;

    // Pass world-space position to fragment shader for lighting
    v_pos = world_pos.xyz;
    
    // Pass color and emissive to fragment shader
    v_color = inst.color.xyz;
    v_emissive = inst.color.w;

    // Transform normal to world space using normal matrix
    // The normal matrix is the inverse-transpose of the model matrix's upper 3x3
    mat3 normal_matrix = transpose(inverse(mat3(inst.model)));
    v_normal = normal_matrix * normal;

    // Pass material properties for PBR shading
    v_mat_data = inst.mat_props;
    
    // Pass texture coordinates
    v_uv = uv;
    
    // Calculate screen-space UV for post-processing (vignette, etc.)
    v_screen_uv = (gl_Position.xy / gl_Position.w) * 0.5 + 0.5;
}