myth_render 0.3.0

Core rendering system for the Myth engine (render graph, pipeline, GPU management).
Documentation
// ── Punctual Light Evaluation (Pure Function Module) ─────────────────────
//
// Resolves a light's type (directional / point / spot) and computes
// incident light direction, color, and distance/spot attenuation.
// Dispatches shadow queries to modules/lighting/shadow when enabled.
//
// Depends on:
//   - core/common.wgsl (getDistanceAttenuation, getSpotAttenuation, IncidentLight)
//   - modules/lighting/shadow.wgsl (sample_shadow, sample_point_shadow)

{$ include 'modules/lighting/shadow' $}

$$ if USE_ATMOSPHERE_TRANSMITTANCE is defined
{$ include 'entry/utility/atmosphere/transmittance_math' $}

struct AtmosphereBakeParams {
    sun_direction: vec3<f32>,
    sun_intensity: f32,
    moon_direction: vec3<f32>,
    moon_intensity: f32,
    star_axis: vec3<f32>,
    sun_disk_size: f32,
    moon_disk_size: f32,
    planet_radius: f32,
    atmosphere_radius: f32,
    star_intensity: f32,
    star_rotation: f32,
};

@group(3) @binding(11) var t_atmosphere_transmittance: texture_2d<f32>;
@group(3) @binding(12) var<uniform> u_atmosphere_bake_params: AtmosphereBakeParams;

fn sample_celestial_light_transmittance(
    world_position: vec3<f32>,
    direction_to_light: vec3<f32>,
) -> vec3<f32> {
    let planet_radius = u_atmosphere_bake_params.planet_radius;
    let atmosphere_radius = max(
        u_atmosphere_bake_params.atmosphere_radius,
        planet_radius + 1.0,
    );
    if (planet_radius <= 0.0) {
        return vec3<f32>(1.0);
    }

    let max_altitude = max(atmosphere_radius - planet_radius, 1.0);
    let planet_center = vec3<f32>(0.0, -planet_radius, 0.0);
    let altitude = clamp(
        length(world_position - planet_center) - planet_radius,
        0.0,
        max_altitude,
    );
    let trans_uv = transmittance_lut_uv(
        altitude,
        clamp(direction_to_light.y, -1.0, 1.0),
        planet_radius,
        atmosphere_radius,
    );
    return textureSampleLevel(
        t_atmosphere_transmittance,
        s_screen_sampler,
        trans_uv,
        0.0,
    ).rgb;
}
$$ endif

fn get_light_info( light: Struct_lights, geometry: GeometricContext ) -> IncidentLight {
    let light_type = light.light_type;
    var light_info: IncidentLight;

    light_info.visible = true;
    light_info.color = light.color.rgb * light.intensity;

    if ( light_type == 0u ) {
        light_info.direction = -light.direction.xyz;
    } else if ( light_type == 1u ) {
        let i_vector = light.position - geometry.position;
        light_info.direction = normalize(i_vector);
        let light_distance = length(i_vector);
        light_info.color *= getDistanceAttenuation( light_distance, light.range, light.decay );
        light_info.visible = any(light_info.color != vec3<f32>(0.0));
    } else if ( light_type == 2u ) {
        let i_vector = light.position - geometry.position;
        light_info.direction = normalize(i_vector);
        let angle_cos = dot(light_info.direction, -light.direction.xyz);
        let spot_attenuation = getSpotAttenuation(light.outer_cone_cos, light.inner_cone_cos, angle_cos);
        if ( spot_attenuation > 0.0 ) {
            let light_distance = length( i_vector );
            light_info.color = light.color.rgb * light.intensity;
            light_info.color *= spot_attenuation;
            light_info.color *= getDistanceAttenuation( light_distance, light.range, light.decay );
            light_info.visible = any(light_info.color != vec3<f32>(0.0));
        } else {
            light_info.color = vec3<f32>( 0.0 );
            light_info.visible = false;
        }

    }

    $$ if USE_ATMOSPHERE_TRANSMITTANCE is defined
    if (light_info.visible && (light.flags & 3u) != 0u) {
        light_info.color *= sample_celestial_light_transmittance(
            geometry.position,
            light_info.direction,
        );
        light_info.visible = any(light_info.color != vec3<f32>(0.0));
    }
    $$ endif

    return light_info;
}

fn evaluate_light_visibility(
    light: Struct_lights,
    geometry: GeometricContext
) -> IncidentLight {
    var punctual_light = get_light_info(light, geometry);

    $$ if HAS_SHADOWS and RECEIVE_SHADOWS
    if (punctual_light.visible) {
        let shadow_pos = geometry.position + geometry.normal * light.shadow_normal_bias;
        var shadow = 1.0;

        if (light.light_type == 1u && light.point_shadow_index >= 0) {
            shadow = sample_point_shadow(
                light.position,
                shadow_pos,
                light.range,
                light.point_shadow_index,
                light.shadow_bias,
            );
        } else if (light.shadow_layer_index >= 0) {
            if (light.light_type == 0u && light.cascade_count > 1u) {
                let view_pos = u_render_state.view_matrix * vec4<f32>(geometry.position, 1.0);
                let view_depth = -view_pos.z;

                var cascade_idx = light.cascade_count - 1u;
                if (view_depth < light.cascade_splits.x) {
                    cascade_idx = 0u;
                } else if (light.cascade_count > 1u && view_depth < light.cascade_splits.y) {
                    cascade_idx = 1u;
                } else if (light.cascade_count > 2u && view_depth < light.cascade_splits.z) {
                    cascade_idx = 2u;
                }

                let layer = light.shadow_layer_index + i32(cascade_idx);
                let matrix = light.shadow_matrices[cascade_idx];
                shadow = sample_shadow(matrix, layer, shadow_pos, light.shadow_bias);
            } else {
                shadow = sample_shadow(
                    light.shadow_matrices[0],
                    light.shadow_layer_index,
                    shadow_pos,
                    light.shadow_bias
                );
            }
        }

        punctual_light.color *= shadow;

        if (shadow <= 0.0001) {
            punctual_light.visible = false;
        }
    }
    $$ endif

    return punctual_light;
}


fn evaluate_punctual_lights(
    geometry: GeometricContext,
    material: SurfaceContext,
    reflected_light: ptr<function, ReflectedLight>,
    frag_coord: vec4<f32>
) {
    $$ if USE_CLUSTERED_SHADING is defined
    let grid_x = max(u_clustered_lighting.screen_dimensions.z, 1u);
    let grid_y = max(u_clustered_lighting.screen_dimensions.w, 1u);
    let grid_z = max(u_clustered_lighting.grid_dimensions.x, 1u);
    let tile_size_x = max(f32(u_clustered_lighting.grid_dimensions.z), 1.0);
    let tile_size_y = max(f32(u_clustered_lighting.grid_dimensions.w), 1.0);
    let directional_light_count = u_environment.directional_light_count;

    let cluster_x = min(u32(frag_coord.x / tile_size_x), grid_x - 1u);
    let cluster_y = min(u32(frag_coord.y / tile_size_y), grid_y - 1u);

    let view_pos = u_render_state.view_matrix * vec4<f32>(geometry.position, 1.0);
    let view_depth = max(-view_pos.z, u_clustered_lighting.depth_params.x);
    let cluster_z = min(
        u32(max(
            floor(log(view_depth) * u_clustered_lighting.depth_params.z
                + u_clustered_lighting.depth_params.w),
            0.0,
        )),
        grid_z - 1u,
    );

    let cluster_index = min(
        cluster_z * (grid_x * grid_y) + cluster_y * grid_x + cluster_x,
        max(u_clustered_lighting.grid_dimensions.y, 1u) - 1u,
    );
    let cluster = st_cluster_records[cluster_index];

    for (var light_index = 0u; light_index < directional_light_count; light_index ++ ) {
        let punctual_light = evaluate_light_visibility(st_directional_lights[light_index], geometry);
        if (punctual_light.visible) {
            RE_Direct( punctual_light, geometry, material, reflected_light );
        }
    }

    for (var i = 0u; i < cluster.count; i ++ ) {
        let light_index = st_cluster_light_indices[cluster.offset + i];
        if (light_index >= u_local_light_buffer_metadata.total_light_count) {
            continue;
        }

        let punctual_light = evaluate_light_visibility(st_local_lights[light_index], geometry);
        if (punctual_light.visible) {
            RE_Direct( punctual_light, geometry, material, reflected_light );
        }
    }
    $$ else
    for (var i = 0u; i < u_environment.directional_light_count; i ++ ) {
        let punctual_light = evaluate_light_visibility(st_directional_lights[i], geometry);
        if (punctual_light.visible) {
            RE_Direct( punctual_light, geometry, material, reflected_light );
        }
    }

    for (var i = 0u; i < u_local_light_buffer_metadata.total_light_count; i ++ ) {
        let punctual_light = evaluate_light_visibility(st_local_lights[i], geometry);
        if (punctual_light.visible) {
            RE_Direct( punctual_light, geometry, material, reflected_light );
        }
    }
    $$ endif
}