awsm-renderer 0.1.7

awsm-renderer
Documentation
//***** INPUT/OUTPUT *****

struct ApplyVertexInput {
    vertex_index: u32,
    position: vec3<f32>,      // Model-space position
    normal: vec3<f32>,        // Model-space normal
    tangent: vec4<f32>,       // Model-space tangent (w = handedness)
    {% if instancing_transforms %}
        // instance transform matrix
        instance_transform_row_0: vec4<f32>,
        instance_transform_row_1: vec4<f32>,
        instance_transform_row_2: vec4<f32>,
        instance_transform_row_3: vec4<f32>,
    {% endif %}
}

struct ApplyVertexOutput {
    clip_position: vec4<f32>,
    world_normal: vec3<f32>,     // Transformed world-space normal
    world_tangent: vec4<f32>,    // Transformed world-space tangent (w = handedness)
    world_position: vec3<f32>,   // Transformed world-space position
}

fn apply_vertex(vertex_orig: ApplyVertexInput, camera: Camera) -> ApplyVertexOutput {
    var out: ApplyVertexOutput;

    var vertex = vertex_orig;
    var normal = vertex_orig.normal;
    var tangent = vertex_orig.tangent;

    // Apply morphs to position, normal, and tangent
    if geometry_mesh_meta.morph_geometry_target_len != 0 {
        vertex = apply_position_morphs(vertex);

        // Apply morphed normals (correct behavior)
        normal = apply_normal_morphs(vertex_orig, normal);
        tangent = apply_tangent_morphs(vertex_orig, tangent);
    }

    // Apply skinning to position, normal, and tangent
    if geometry_mesh_meta.skin_sets_len != 0 {
        vertex = apply_position_skin(vertex);
        normal = apply_normal_skin(vertex_orig, normal);
        tangent = vec4<f32>(apply_normal_skin(vertex_orig, tangent.xyz), tangent.w);
    }

    {% if instancing_transforms %}
        // Transform the vertex position by the instance transform
        let instance_transform = mat4x4<f32>(
            vertex.instance_transform_row_0,
            vertex.instance_transform_row_1,
            vertex.instance_transform_row_2,
            vertex.instance_transform_row_3,
        );

        let model_transform = get_model_transform(geometry_mesh_meta.transform_offset) * instance_transform;
    {% else %}
        let model_transform = get_model_transform(geometry_mesh_meta.transform_offset);
    {% endif %}

    let world_pos = model_transform * vec4<f32>(vertex.position, 1.0);
    out.clip_position = camera.view_proj * world_pos;


    // Transform normal/tangent to world space (ignore translation)
    let model_matrix3 = mat3x3<f32>(
        model_transform[0].xyz,
        model_transform[1].xyz,
        model_transform[2].xyz
    );
    // Correct normal transform for non-uniform scaling using an explicit
    // inverse-transpose (cofactor) path, avoiding WGSL inverse() support issues.
    let c0 = model_matrix3[0];
    let c1 = model_matrix3[1];
    let c2 = model_matrix3[2];
    let r0 = vec3<f32>(c0.x, c1.x, c2.x);
    let r1 = vec3<f32>(c0.y, c1.y, c2.y);
    let r2 = vec3<f32>(c0.z, c1.z, c2.z);

    let cof0 = cross(r1, r2);
    let cof1 = cross(r2, r0);
    let cof2 = cross(r0, r1);
    let det_model = dot(r0, cof0);

    let world_normal_unnormalized = select(
        model_matrix3 * normal,
        vec3<f32>(
            dot(cof0, normal),
            dot(cof1, normal),
            dot(cof2, normal),
        ) / det_model,
        abs(det_model) > 1e-8
    );
    let world_normal = normalize(world_normal_unnormalized);

    // Tangents transform with the model matrix, then must be re-orthonormalized against N.
    let tangent_raw = model_matrix3 * tangent.xyz;
    var tangent_ortho = tangent_raw - world_normal * dot(tangent_raw, world_normal);
    let tangent_len_sq = dot(tangent_ortho, tangent_ortho);
    if (tangent_len_sq > 1e-8) {
        tangent_ortho *= inverseSqrt(tangent_len_sq);
    } else {
        // Deterministic fallback tangent orthogonal to N.
        let fallback_axis = select(
            vec3<f32>(0.0, 0.0, 1.0),
            vec3<f32>(0.0, 1.0, 0.0),
            abs(world_normal.z) > 0.999
        );
        tangent_ortho = normalize(cross(fallback_axis, world_normal));
    }

    out.world_normal = world_normal;
    out.world_tangent = vec4<f32>(tangent_ortho, tangent.w);

    out.world_position = world_pos.xyz;

    return out;
}