1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
//! `bevy-pbr-rust`-backed `RustGpuMaterial` implementation for `StandardMaterial`.

use bevy::{prelude::StandardMaterial, render::render_resource::ShaderDefVal};

use crate::{
    prelude::{EntryPoint, EntryPointName, EntryPointParameters, RustGpuMaterial},
    EntryPointConstants,
};

/// `bevy_rust_gpu::mesh::entry_points::vertex`
pub enum MeshVertex {}

impl EntryPoint for MeshVertex {
    const NAME: EntryPointName = "mesh::entry_points::vertex";

    fn parameters() -> EntryPointParameters {
        &[
            (&[("VERTEX_TANGENTS", "some")], "none"),
            (&[("VERTEX_COLORS", "some")], "none"),
            (&[("SKINNED", "some")], "none"),
        ]
    }
}

/// `bevy_rust_gpu::mesh::entry_points::fragment`
pub enum MeshFragment {}

impl EntryPoint for MeshFragment {
    const NAME: EntryPointName = "mesh::entry_points::fragment";
}

/// `bevy_rust_gpu::pbr::entry_points::fragment`
pub enum PbrFragment {}

impl EntryPoint for PbrFragment {
    const NAME: EntryPointName = "pbr::entry_points::fragment";
    fn parameters() -> EntryPointParameters {
        &[
            (&[("NO_TEXTURE_ARRAYS_SUPPORT", "texture")], "array"),
            (&[("VERTEX_UVS", "some")], "none"),
            (&[("VERTEX_TANGENTS", "some")], "none"),
            (&[("VERTEX_COLORS", "some")], "none"),
            (&[("STANDARDMATERIAL_NORMAL_MAP", "some")], "none"),
            (&[("SKINNED", "some")], "none"),
            (&[("TONEMAP_IN_SHADER", "some")], "none"),
            (&[("DEBAND_DITHER", "some")], "none"),
            (
                &[
                    ("BLEND_MULTIPLY", "multiply"),
                    ("BLEND_PREMULTIPLIED_ALPHA", "blend_premultiplied_alpha"),
                ],
                "none",
            ),
            (&[("ENVIRONMENT_MAP", "some")], "none"),
            (&[("PREMULTIPLY_ALPHA", "some")], "none"),
            (
                &[
                    ("CLUSTERED_FORWARD_DEBUG_Z_SLICES", "debug_z_slices"),
                    (
                        "CLUSTERED_FORWARD_DEBUG_CLUSTER_LIGHT_COMPLEXITY",
                        "debug_cluster_light_complexity",
                    ),
                    (
                        "CLUSTERED_FORWARD_DEBUG_CLUSTER_COHERENCY",
                        "debug_cluster_coherency",
                    ),
                ],
                "none",
            ),
            (
                &[("DIRECTIONAL_LIGHT_SHADOW_MAP_DEBUG_CASCADES", "some")],
                "none",
            ),
        ]
    }

    fn constants() -> EntryPointConstants {
        &["MAX_DIRECTIONAL_LIGHTS", "MAX_CASCADES_PER_LIGHT"]
    }

    fn permutation(shader_defs: &Vec<ShaderDefVal>) -> Vec<String> {
        let mut permutation = vec![];

        for (defined, undefined) in Self::parameters().iter() {
            if let Some(mapping) = defined.iter().find_map(|(def, mapping)| {
                if shader_defs.contains(&ShaderDefVal::Bool(def.to_string(), true)) {
                    Some(mapping)
                } else {
                    None
                }
            }) {
                permutation.push(mapping.to_string());
            } else {
                permutation.push(undefined.to_string())
            };
        }

        if let Some(ge) = shader_defs.iter().find_map(|def| match def {
            bevy::render::render_resource::ShaderDefVal::UInt(key, value) => {
                if key.as_str() == "AVAILABLE_STORAGE_BUFFER_BINDINGS" {
                    Some(*value >= 3)
                } else {
                    None
                }
            }
            _ => None,
        }) {
            if ge {
                permutation.insert(1, "storage".to_string())
            } else {
                permutation.insert(1, "uniform".to_string())
            }
        }

        permutation
    }
}

/// `StandardMaterial` implementation
impl RustGpuMaterial for StandardMaterial {
    type Vertex = MeshVertex;
    type Fragment = PbrFragment;
}