feo-oop-engine 0.0.5

An Object Oriented game engine for rust.
Documentation
#version 450

// This feature is not complete. I discovered through this feature that the depth buffer is not working properly
// 

layout(input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput u_normals;
layout(input_attachment_index = 1, set = 0, binding = 1) uniform subpassInput u_diffuse;
layout(input_attachment_index = 3, set = 0, binding = 2) uniform subpassInput u_specular;
layout(input_attachment_index = 4, set = 0, binding = 3) uniform subpassInput u_depth;

layout(push_constant) uniform PushConstants {
    // Screen space to camera space projection matrix
    mat4 screen_to_camera;
    // The point lights color
    vec4 color;
    // The position of the light in camera space
    vec4 position_camera_space;
} push_constants;

// layout(location = 0) in vec2 v_screen_coords;

layout(location = 0) out vec4 f_color;

void main() {
    float in_depth = subpassLoad(u_depth).z;

    // Only render what exists/is visible
    if (in_depth >= 1.0) {
        discard;
    }

    // depth = -<z> (n + f) / (f - n) - 2fn / (f - n)
    // depth (f - n) = -<z> (n + f) - 2fn
    // depth (f - n) + 2fn = -<z> (n + f)
    // (depth (f - n) + 2fn) / (n + f) = -<z> 
    // (depth (f - n) / (n + f)) + (2fn / (n + f)) = -<z>

    // post thought
    
    // LET M = Matrix4::new(
    //     [ self.near_plane / half_w,                       0.0,                                                                      0.0,                                                                            0.0],
    //     [                      0.0, self.near_plane / -half_h,                                                                      0.0,                                                                            0.0],
    //     [                      0.0,                       0.0, -(self.near_plane + self.far_plane) / (self.far_plane - self.near_plane), (-2.0 * self.far_plane * self.near_plane) / (self.far_plane - self.near_plane)],
    //     [                      0.0,                       0.0,                                                                     -1.0,                                                                            0.0]
    // ).inverse() =
    // Matrix4::new(
    //     [ half_w / self.near_plane,                       0.0,                                                                            0.0,                                                                           0.0],
    //     [                      0.0, -half_h / self.near_plane,                                                                            0.0,                                                                           0.0],
    //     [                      0.0,                       0.0,                                                                            0.0,                                                                          -1.0],
    //     [                      0.0,                       0.0, -(self.far_plane - self.near_plane) / (2.0 * self.far_plane * self.near_plane), (self.far_plane + self.near_plane) / (2.0 * self.far_plane * self.near_plane)]
    // ) 
    
    // LET R_0 = 1 / M[3][3] = 2fn / (n + f)
    // LET R_1 = -(-(f - n) / 2fn) * (2fn / (n + f)) = -M[3][2] * R_0 = (f - n) / (n + f)

    //  depth * R_1 + R_0 = -<z> = <w> 

    // Reminder
    // (x', y', z', w') -> (x',y', z', _1_) / w' = gl_FragCoord in fs_draw
    // z' -> z_buffer by default
    
    // Trace back screen coord to camera space
    float R_0 = 1.0 / push_constants.screen_to_camera[3][3];
    float R_1 = -push_constants.screen_to_camera[2][3] * R_0;

    float w = in_depth * R_1 + R_0;
    vec4 texel_camera_space = push_constants.screen_to_camera * vec4(gl_FragCoord.x * w, gl_FragCoord.y * w, in_depth * w, w);
    
    vec3 in_normal = normalize(subpassLoad(u_normals).xyz);
    vec3 texel_to_light = push_constants.position_camera_space.xyz - texel_camera_space.xyz;
    float light_distance_to_texel = length(texel_to_light);
    vec3 unit_texel_to_light = normalize(texel_to_light);

    // Calculate Specular reflectance
    vec4 in_specular_all = subpassLoad(u_specular).rgba;
    vec3 specular_color = in_specular_all.rgb;
    float shine = in_specular_all.a; // NOTE     \/\/                 \/
    float specular_intensity = pow(dot(normalize(unit_texel_to_light - texel_camera_space.xyz), in_normal), shine);
    vec3 specular = specular_color * specular_intensity;

    // Calculate the the inverse of the spread of photons over the texel 
    float light_concentration = max(dot(unit_texel_to_light, in_normal), 0.0);

    // Take into account the distance of the light source
    light_concentration /= light_distance_to_texel * light_distance_to_texel;

    // Take into account the distance of the light source
    // wrong because surface becomes smaller at same rate to the eye meaning that the
    // same amount of photons hit the retna per U^2 on the inside of the eye.
    float texel_distance = length(texel_camera_space.xyz);
    light_concentration /= texel_distance * texel_distance;

    // TO REMOVE
    // Take into account the distance of the light source 
    float light_distance = length(push_constants.position_camera_space.xyz);
    light_concentration /= light_distance * light_distance;

    vec3 in_diffuse = subpassLoad(u_diffuse).rgb;

    vec3 light_color = push_constants.color.rgb * light_concentration;

    f_color.rgb = light_color * in_diffuse; // specular
    f_color.a = 1.0;
    
    // if (texel_camera_space.x > 0.0) { // ERR: depth buffer is filled with zeros
    //     f_color.rgb = vec3(100.0*in_depth, 0.0, 0.0);
    // }
}