]> git.tdb.fi Git - libs/gl.git/blobdiff - shaderlib/splat.glsl
Implement a splat material type
[libs/gl.git] / shaderlib / splat.glsl
diff --git a/shaderlib/splat.glsl b/shaderlib/splat.glsl
new file mode 100644 (file)
index 0000000..4a5582a
--- /dev/null
@@ -0,0 +1,115 @@
+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);
+}