--- /dev/null
+import common;
+import cooktorrance;
+
+struct SplatMaterialParameters
+{
+ vec4 base_color;
+ vec4 tint;
+ vec4 emission;
+ float metalness;
+ float roughness;
+ int base_color_layer;
+ int normal_layer;
+ int metalness_layer;
+ int roughness_layer;
+ int occlusion_layer;
+ int emission_layer;
+};
+
+const int max_materials = 128;
+layout(set=1) uniform SplatMaterial
+{
+ SplatMaterialParameters splat_materials[max_materials];
+};
+
+layout(set=1) uniform sampler2DArray base_color_array;
+layout(set=1) uniform sampler2DArray normal_array;
+layout(set=1) uniform sampler2DArray metalness_array;
+layout(set=1) uniform sampler2DArray roughness_array;
+layout(set=1) uniform sampler2DArray occlusion_array;
+layout(set=1) uniform sampler2DArray emission_array;
+
+layout(constant_id=auto) const bool use_base_color_map = false;
+layout(constant_id=auto) const bool use_metalness_map = false;
+layout(constant_id=auto) const bool use_roughness_map = false;
+layout(constant_id=auto) const bool use_occlusion_map = false;
+layout(constant_id=auto) const bool use_emission = false;
+layout(constant_id=auto) const bool use_emission_map = false;
+
+#pragma MSP stage(fragment)
+void main()
+{
+ vec2 uv = texcoord.xy;
+ vec4 base_color = vec4(0.0);
+ vec3 normal = vec3(0.0);
+ float metalness = 0.0;
+ float roughness = 0.0;
+ float occlusion = (use_occlusion_map ? 0.0 : 1.0);
+ vec3 emission = vec3(0.0);
+
+ for(int i=0; i<3; ++i)
+ {
+ float w = weight[i];
+ if(w>0.0)
+ {
+ SplatMaterialParameters mat = splat_materials[group[i]];
+
+ if(use_base_color_map)
+ {
+ int layer = mat.base_color_layer;
+ base_color += w*(layer>=0 ? texture(base_color_array, vec3(uv, layer)) : mat.base_color)*mat.tint;
+ }
+ else
+ base_color += w*mat.base_color*mat.tint;
+
+ if(use_normal_map)
+ {
+ int layer = mat.normal_layer;
+ normal += w*(layer>=0 ? texture(normal_array, vec3(uv, layer)).xyz*2.0-1.0 : vec3(0.0, 0.0, 1.0));
+ }
+
+ if(use_metalness_map)
+ {
+ int layer = mat.metalness_layer;
+ metalness += w*(layer>=0 ? texture(metalness_array, vec3(uv, layer)).r : mat.metalness);
+ }
+ else
+ metalness += w*mat.metalness;
+
+ if(use_roughness_map)
+ {
+ int layer = mat.roughness_layer;
+ roughness += w*(layer>=0 ? texture(roughness_array, vec3(uv, layer)).r : mat.roughness);
+ }
+ else
+ roughness += w*mat.roughness;
+
+ if(use_occlusion_map)
+ {
+ int layer = mat.occlusion_layer;
+ occlusion += w*(layer>=0 ? texture(occlusion_array, vec3(uv, layer)).r : 1.0);
+ }
+
+ if(use_emission_map)
+ {
+ int layer = mat.emission_layer;
+ emission += w*(layer>=0 ? texture(emission_array, vec3(uv, layer)).rgb : mat.emission.rgb);
+ }
+ else
+ emission += w*mat.emission.rgb;
+ }
+ }
+
+ if(use_normal_map)
+ normal = world_tbn_matrix*normalize(normal);
+ else
+ normal = normalize(world_normal);
+
+ vec3 look = normalize(world_look_dir);
+
+ vec3 lit_color = cooktorrance_lighting(normal, look, base_color.rgb, metalness, roughness, occlusion);
+ if(use_emission)
+ lit_color += emission;
+
+ frag_color = vec4(lit_color, base_color.a);
+}