summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author3gg <3gg@shellblade.net>2023-02-11 09:13:18 -0800
committer3gg <3gg@shellblade.net>2023-02-11 09:13:18 -0800
commitdbbdcf4be06c05f60798b322890c88b79d802bd8 (patch)
treee565963320d938d26ce72a83ca7449424dab827c
parent8f0726b6343073f3a3677cadd217736f96e0d4dd (diff)
Create default material for meshes that do not specify one.
-rw-r--r--gfx/src/util/scene.c101
1 files changed, 70 insertions, 31 deletions
diff --git a/gfx/src/util/scene.c b/gfx/src/util/scene.c
index 49e661d..6f34922 100644
--- a/gfx/src/util/scene.c
+++ b/gfx/src/util/scene.c
@@ -803,13 +803,44 @@ static bool load_materials(
803 return true; 803 return true;
804} 804}
805 805
806/// Create a default material for meshes that do not have a material.
807static Material* make_default_material() {
808 MaterialDesc desc = (MaterialDesc){0};
809
810 assert(desc.num_uniforms < GFX_MAX_UNIFORMS_PER_MATERIAL);
811 desc.uniforms[desc.num_uniforms++] = (ShaderUniform){
812 .name = sstring_make(UNIFORM_BASE_COLOR_FACTOR),
813 .type = UniformVec4,
814 .value.vec4 = vec4_make(1, 1, 1, 1)};
815
816 assert(desc.num_uniforms < GFX_MAX_UNIFORMS_PER_MATERIAL);
817 desc.uniforms[desc.num_uniforms++] = (ShaderUniform){
818 .name = sstring_make(UNIFORM_METALLIC_FACTOR),
819 .type = UniformFloat,
820 .value.scalar = 0};
821
822 assert(desc.num_uniforms < GFX_MAX_UNIFORMS_PER_MATERIAL);
823 desc.uniforms[desc.num_uniforms++] = (ShaderUniform){
824 .name = sstring_make(UNIFORM_ROUGHNESS_FACTOR),
825 .type = UniformFloat,
826 .value.scalar = 1};
827
828 assert(desc.num_uniforms < GFX_MAX_UNIFORMS_PER_MATERIAL);
829 desc.uniforms[desc.num_uniforms++] = (ShaderUniform){
830 .name = sstring_make(UNIFORM_EMISSIVE_FACTOR),
831 .type = UniformVec3,
832 .value.vec3 = vec3_make(0, 0, 0)};
833
834 return gfx_make_material(&desc);
835}
836
806/// Load all meshes from the glTF scene. 837/// Load all meshes from the glTF scene.
807static bool load_meshes( 838static bool load_meshes(
808 const cgltf_data* data, Gfx* gfx, Buffer** buffers, 839 const cgltf_data* data, Gfx* gfx, Buffer** buffers,
809 Buffer** tangent_buffers, const cgltfTangentBuffer* cgltf_tangent_buffers, 840 Buffer** tangent_buffers, const cgltfTangentBuffer* cgltf_tangent_buffers,
810 cgltf_size num_tangent_buffers, Material** materials, ShaderProgram* shader, 841 cgltf_size num_tangent_buffers, Material** materials,
811 size_t primitive_count, Geometry** geometries, Mesh** meshes, 842 ShaderProgram* const shader, size_t primitive_count, Geometry** geometries,
812 SceneObject** scene_objects) { 843 Mesh** meshes, SceneObject** scene_objects) {
813 // Walk through the mesh primitives to create Meshes. A GLTF mesh primitive 844 // Walk through the mesh primitives to create Meshes. A GLTF mesh primitive
814 // has a material (Mesh) and vertex data (Geometry). A GLTF mesh maps to 845 // has a material (Mesh) and vertex data (Geometry). A GLTF mesh maps to
815 // a SceneObject. 846 // a SceneObject.
@@ -852,16 +883,21 @@ static bool load_meshes(
852 const cgltf_primitive* prim = &mesh->primitives[p]; 883 const cgltf_primitive* prim = &mesh->primitives[p];
853 const cgltf_material* mat = prim->material; 884 const cgltf_material* mat = prim->material;
854 885
855 MeshPermutation perm = {0}; 886 MeshPermutation perm = {0};
856 perm.has_normal_map = mat->normal_texture.texture != 0; 887 if (mat) {
857 perm.has_occlusion_map = mat->occlusion_texture.texture != 0; 888 perm.has_normal_map = mat->normal_texture.texture != 0;
858 perm.has_emissive_map = mat->emissive_texture.texture != 0; 889 perm.has_occlusion_map = mat->occlusion_texture.texture != 0;
859 // TODO: specular/glossiness and other material parameters. 890 perm.has_emissive_map = mat->emissive_texture.texture != 0;
860 if (mat->has_pbr_metallic_roughness) { 891
861 const cgltf_pbr_metallic_roughness* pbr = &mat->pbr_metallic_roughness; 892 if (mat->has_pbr_metallic_roughness) {
862 perm.has_albedo_map = pbr->base_color_texture.texture != 0; 893 const cgltf_pbr_metallic_roughness* pbr =
863 perm.has_metallic_roughness_map = 894 &mat->pbr_metallic_roughness;
864 pbr->metallic_roughness_texture.texture != 0; 895 perm.has_albedo_map = pbr->base_color_texture.texture != 0;
896 perm.has_metallic_roughness_map =
897 pbr->metallic_roughness_texture.texture != 0;
898 } else {
899 // TODO: specular/glossiness and other material parameters.
900 }
865 } 901 }
866 902
867 GeometryDesc geometry_desc = { 903 GeometryDesc geometry_desc = {
@@ -1034,36 +1070,39 @@ static bool load_meshes(
1034 CHECK_COUNT(weights.u16, uint16_t, 4); 1070 CHECK_COUNT(weights.u16, uint16_t, 4);
1035 CHECK_COUNT(weights.floats, float, 4); 1071 CHECK_COUNT(weights.floats, float, 4);
1036 1072
1037 const cgltf_size material_index = prim->material - data->materials; 1073 Material* material = 0;
1038 assert(material_index < data->materials_count); 1074 if (mat) {
1039 Material* material = materials[material_index]; 1075 const cgltf_size material_index = mat - data->materials;
1076 assert(material_index < data->materials_count);
1077 material = materials[material_index];
1078 } else {
1079 // Create a default material for meshes that do not specify one.
1080 material = make_default_material();
1081 }
1082 assert(material);
1040 1083
1041 geometries[next_mesh] = gfx_make_geometry(render_backend, &geometry_desc); 1084 geometries[next_mesh] = gfx_make_geometry(render_backend, &geometry_desc);
1042 if (!geometries[next_mesh]) { 1085 if (!geometries[next_mesh]) {
1043 return false; 1086 return false;
1044 } 1087 }
1045 1088
1046 // If the user specifies a custom shader, use that instead. 1089 // If the user specifies a custom shader, use that instead. Otherwise
1047 // else TODO: Build a shader based on permutation. 1090 // compile a shader based on the mesh's permutation.
1048 // 1091 //
1049 // TODO: We should cache shader permutations to re-use shader programs. 1092 // Note that Gfx takes care of caching shaders and shader programs.
1050 // Caching should not be done locally here because a caller may call
1051 // gfx_load_scene() multiple times to load multiple scenes, and we want
1052 // shader re-use across scenes too.
1053 // 1093 //
1054 // On the other hand, caching materials is not necessary since, provided 1094 // Caching materials could be useful, but, provided they can share
1055 // they can share shaders, the renderer can check later whether uniforms 1095 // shaders, the renderer can check later whether uniforms have the same
1056 // have the same values. Also, changing uniforms is much faster than 1096 // values. Also, changing uniforms is much faster than swapping shaders,
1057 // swapping shaders, so shader caching is the most important thing here. 1097 // so shader caching is the most important thing here.
1058 if (!shader) { 1098 ShaderProgram* mesh_shader =
1059 shader = make_shader_permutation(render_backend, perm); 1099 shader ? shader : make_shader_permutation(render_backend, perm);
1060 } 1100 assert(mesh_shader);
1061 assert(shader);
1062 1101
1063 meshes[next_mesh] = gfx_make_mesh(&(MeshDesc){ 1102 meshes[next_mesh] = gfx_make_mesh(&(MeshDesc){
1064 .geometry = geometries[next_mesh], 1103 .geometry = geometries[next_mesh],
1065 .material = material, 1104 .material = material,
1066 .shader = shader}); 1105 .shader = mesh_shader});
1067 1106
1068 if (!meshes[next_mesh]) { 1107 if (!meshes[next_mesh]) {
1069 return false; 1108 return false;