aboutsummaryrefslogtreecommitdiff
path: root/src/asset/model.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/asset/model.c')
-rw-r--r--src/asset/model.c109
1 files changed, 67 insertions, 42 deletions
diff --git a/src/asset/model.c b/src/asset/model.c
index 2ee3cd1..b5c6b0d 100644
--- a/src/asset/model.c
+++ b/src/asset/model.c
@@ -138,6 +138,7 @@
138#define DEFINE_HAS_NORMAL_MAP "HAS_NORMAL_MAP" 138#define DEFINE_HAS_NORMAL_MAP "HAS_NORMAL_MAP"
139#define DEFINE_HAS_OCCLUSION_MAP "HAS_OCCLUSION_MAP" 139#define DEFINE_HAS_OCCLUSION_MAP "HAS_OCCLUSION_MAP"
140#define DEFINE_HAS_EMISSIVE_MAP "HAS_EMISSIVE_MAP" 140#define DEFINE_HAS_EMISSIVE_MAP "HAS_EMISSIVE_MAP"
141#define DEFINE_HAS_TRANSPARENCY "HAS_TRANSPARENCY"
141#define DEFINE_HAS_JOINTS "HAS_JOINTS" 142#define DEFINE_HAS_JOINTS "HAS_JOINTS"
142#define DEFINE_MAX_JOINTS "MAX_JOINTS" 143#define DEFINE_MAX_JOINTS "MAX_JOINTS"
143 144
@@ -166,6 +167,8 @@ typedef struct MeshPermutation {
166 bool has_normal_map : 1; 167 bool has_normal_map : 1;
167 bool has_occlusion_map : 1; 168 bool has_occlusion_map : 1;
168 bool has_emissive_map : 1; 169 bool has_emissive_map : 1;
170 // Material.
171 bool has_transparency : 1;
169 }; 172 };
170 int32_t all; 173 int32_t all;
171 }; 174 };
@@ -192,6 +195,7 @@ static size_t make_defines(
192 check(has_normal_map, DEFINE_HAS_NORMAL_MAP); 195 check(has_normal_map, DEFINE_HAS_NORMAL_MAP);
193 check(has_occlusion_map, DEFINE_HAS_OCCLUSION_MAP); 196 check(has_occlusion_map, DEFINE_HAS_OCCLUSION_MAP);
194 check(has_emissive_map, DEFINE_HAS_EMISSIVE_MAP); 197 check(has_emissive_map, DEFINE_HAS_EMISSIVE_MAP);
198 check(has_transparency, DEFINE_HAS_TRANSPARENCY);
195 199
196 if (perm.has_joints) { 200 if (perm.has_joints) {
197 defines[next].name = sstring_make(DEFINE_MAX_JOINTS); 201 defines[next].name = sstring_make(DEFINE_MAX_JOINTS);
@@ -208,12 +212,12 @@ static ShaderProgram* make_shader_permutation(
208 LOGD( 212 LOGD(
209 "Compiling Cook-Torrance shader permutation: texcoords: %d, normals: " 213 "Compiling Cook-Torrance shader permutation: texcoords: %d, normals: "
210 "%d, tangents: %d, joints: %d, weights: %d, albedo map: %d, " 214 "%d, tangents: %d, joints: %d, weights: %d, albedo map: %d, "
211 "metallic-roughness map: " 215 "metallic-roughness map: %d, normal map: %d, AO map: %d, emissive map: "
212 "%d, normal " 216 "%d, has transparency: %d",
213 "map: %d, AO map: %d, emissive map: %d",
214 perm.has_texcoords, perm.has_normals, perm.has_tangents, perm.has_joints, 217 perm.has_texcoords, perm.has_normals, perm.has_tangents, perm.has_joints,
215 perm.has_weights, perm.has_albedo_map, perm.has_metallic_roughness_map, 218 perm.has_weights, perm.has_albedo_map, perm.has_metallic_roughness_map,
216 perm.has_normal_map, perm.has_occlusion_map, perm.has_emissive_map); 219 perm.has_normal_map, perm.has_occlusion_map, perm.has_emissive_map,
220 perm.has_transparency);
217 221
218 ShaderCompilerDefine defines[GFX_MAX_SHADER_COMPILER_DEFINES]; 222 ShaderCompilerDefine defines[GFX_MAX_SHADER_COMPILER_DEFINES];
219 const size_t num_defines = make_defines(perm, defines); 223 const size_t num_defines = make_defines(perm, defines);
@@ -742,6 +746,19 @@ static bool load_texture_and_uniform(
742 return true; 746 return true;
743} 747}
744 748
749static AlphaMode to_gfx_alpha_mode(cgltf_alpha_mode mode) {
750 switch (mode) {
751 case cgltf_alpha_mode_opaque:
752 return Opaque;
753 case cgltf_alpha_mode_mask:
754 return Mask;
755 case cgltf_alpha_mode_blend:
756 return Blend;
757 }
758 FAIL("unhandled alpha mode");
759 return Opaque;
760}
761
745/// Load all materials from the glTF scene. 762/// Load all materials from the glTF scene.
746/// 763///
747/// Return an array of Materials such that the index of each descriptor matches 764/// Return an array of Materials such that the index of each descriptor matches
@@ -770,27 +787,27 @@ static bool load_materials(
770 787
771 assert(next_uniform < GFX_MAX_UNIFORMS_PER_MATERIAL); 788 assert(next_uniform < GFX_MAX_UNIFORMS_PER_MATERIAL);
772 desc.uniforms[next_uniform++] = (ShaderUniform){ 789 desc.uniforms[next_uniform++] = (ShaderUniform){
773 .name = sstring_make(UNIFORM_BASE_COLOR_FACTOR), 790 .name = sstring_make(UNIFORM_BASE_COLOR_FACTOR),
774 .type = UniformVec4, 791 .type = UniformVec4,
775 .value.vec4 = vec4_from_array(pbr->base_color_factor)}; 792 .value.uniform_vec4 = vec4_from_array(pbr->base_color_factor)};
776 793
777 assert(next_uniform < GFX_MAX_UNIFORMS_PER_MATERIAL); 794 assert(next_uniform < GFX_MAX_UNIFORMS_PER_MATERIAL);
778 desc.uniforms[next_uniform++] = 795 desc.uniforms[next_uniform++] =
779 (ShaderUniform){.name = sstring_make(UNIFORM_METALLIC_FACTOR), 796 (ShaderUniform){.name = sstring_make(UNIFORM_METALLIC_FACTOR),
780 .type = UniformFloat, 797 .type = UniformFloat,
781 .value.scalar = pbr->metallic_factor}; 798 .value.uniform_float = pbr->metallic_factor};
782 799
783 assert(next_uniform < GFX_MAX_UNIFORMS_PER_MATERIAL); 800 assert(next_uniform < GFX_MAX_UNIFORMS_PER_MATERIAL);
784 desc.uniforms[next_uniform++] = 801 desc.uniforms[next_uniform++] =
785 (ShaderUniform){.name = sstring_make(UNIFORM_ROUGHNESS_FACTOR), 802 (ShaderUniform){.name = sstring_make(UNIFORM_ROUGHNESS_FACTOR),
786 .type = UniformFloat, 803 .type = UniformFloat,
787 .value.scalar = pbr->roughness_factor}; 804 .value.uniform_float = pbr->roughness_factor};
788 805
789 assert(next_uniform < GFX_MAX_UNIFORMS_PER_MATERIAL); 806 assert(next_uniform < GFX_MAX_UNIFORMS_PER_MATERIAL);
790 desc.uniforms[next_uniform++] = 807 desc.uniforms[next_uniform++] = (ShaderUniform){
791 (ShaderUniform){.name = sstring_make(UNIFORM_EMISSIVE_FACTOR), 808 .name = sstring_make(UNIFORM_EMISSIVE_FACTOR),
792 .type = UniformVec3, 809 .type = UniformVec3,
793 .value.vec3 = vec3_from_array(mat->emissive_factor)}; 810 .value.uniform_vec3 = vec3_from_array(mat->emissive_factor)};
794 811
795 if (pbr->base_color_texture.texture) { 812 if (pbr->base_color_texture.texture) {
796 if (!load_texture_and_uniform( 813 if (!load_texture_and_uniform(
@@ -837,6 +854,9 @@ static bool load_materials(
837 assert(next_uniform < GFX_MAX_UNIFORMS_PER_MATERIAL); 854 assert(next_uniform < GFX_MAX_UNIFORMS_PER_MATERIAL);
838 desc.num_uniforms = next_uniform; 855 desc.num_uniforms = next_uniform;
839 856
857 desc.alpha_mode = to_gfx_alpha_mode(mat->alpha_mode);
858 desc.alpha_cutoff = mat->alpha_cutoff;
859
840 materials[i] = gfx_make_material(&desc); 860 materials[i] = gfx_make_material(&desc);
841 if (!materials[i]) { 861 if (!materials[i]) {
842 return false; 862 return false;
@@ -852,27 +872,27 @@ static Material* make_default_material() {
852 872
853 assert(desc.num_uniforms < GFX_MAX_UNIFORMS_PER_MATERIAL); 873 assert(desc.num_uniforms < GFX_MAX_UNIFORMS_PER_MATERIAL);
854 desc.uniforms[desc.num_uniforms++] = 874 desc.uniforms[desc.num_uniforms++] =
855 (ShaderUniform){.name = sstring_make(UNIFORM_BASE_COLOR_FACTOR), 875 (ShaderUniform){.name = sstring_make(UNIFORM_BASE_COLOR_FACTOR),
856 .type = UniformVec4, 876 .type = UniformVec4,
857 .value.vec4 = vec4_make(1, 1, 1, 1)}; 877 .value.uniform_vec4 = vec4_make(1, 1, 1, 1)};
858 878
859 assert(desc.num_uniforms < GFX_MAX_UNIFORMS_PER_MATERIAL); 879 assert(desc.num_uniforms < GFX_MAX_UNIFORMS_PER_MATERIAL);
860 desc.uniforms[desc.num_uniforms++] = 880 desc.uniforms[desc.num_uniforms++] =
861 (ShaderUniform){.name = sstring_make(UNIFORM_METALLIC_FACTOR), 881 (ShaderUniform){.name = sstring_make(UNIFORM_METALLIC_FACTOR),
862 .type = UniformFloat, 882 .type = UniformFloat,
863 .value.scalar = 0}; 883 .value.uniform_float = 0};
864 884
865 assert(desc.num_uniforms < GFX_MAX_UNIFORMS_PER_MATERIAL); 885 assert(desc.num_uniforms < GFX_MAX_UNIFORMS_PER_MATERIAL);
866 desc.uniforms[desc.num_uniforms++] = 886 desc.uniforms[desc.num_uniforms++] =
867 (ShaderUniform){.name = sstring_make(UNIFORM_ROUGHNESS_FACTOR), 887 (ShaderUniform){.name = sstring_make(UNIFORM_ROUGHNESS_FACTOR),
868 .type = UniformFloat, 888 .type = UniformFloat,
869 .value.scalar = 1}; 889 .value.uniform_float = 1};
870 890
871 assert(desc.num_uniforms < GFX_MAX_UNIFORMS_PER_MATERIAL); 891 assert(desc.num_uniforms < GFX_MAX_UNIFORMS_PER_MATERIAL);
872 desc.uniforms[desc.num_uniforms++] = 892 desc.uniforms[desc.num_uniforms++] =
873 (ShaderUniform){.name = sstring_make(UNIFORM_EMISSIVE_FACTOR), 893 (ShaderUniform){.name = sstring_make(UNIFORM_EMISSIVE_FACTOR),
874 .type = UniformVec3, 894 .type = UniformVec3,
875 .value.vec3 = vec3_make(0, 0, 0)}; 895 .value.uniform_vec3 = vec3_make(0, 0, 0)};
876 896
877 return gfx_make_material(&desc); 897 return gfx_make_material(&desc);
878} 898}
@@ -950,6 +970,7 @@ static bool load_meshes(
950 perm.has_normal_map = mat->normal_texture.texture != 0; 970 perm.has_normal_map = mat->normal_texture.texture != 0;
951 perm.has_occlusion_map = mat->occlusion_texture.texture != 0; 971 perm.has_occlusion_map = mat->occlusion_texture.texture != 0;
952 perm.has_emissive_map = mat->emissive_texture.texture != 0; 972 perm.has_emissive_map = mat->emissive_texture.texture != 0;
973 perm.has_transparency = mat->alpha_mode != cgltf_alpha_mode_opaque;
953 974
954 if (mat->has_pbr_metallic_roughness) { 975 if (mat->has_pbr_metallic_roughness) {
955 const cgltf_pbr_metallic_roughness* pbr = 976 const cgltf_pbr_metallic_roughness* pbr =
@@ -1009,7 +1030,6 @@ static bool load_meshes(
1009 const cgltf_attribute* attrib = &prim->attributes[a]; 1030 const cgltf_attribute* attrib = &prim->attributes[a];
1010 const cgltf_accessor* accessor = attrib->data; 1031 const cgltf_accessor* accessor = attrib->data;
1011 const cgltf_buffer_view* view = accessor->buffer_view; 1032 const cgltf_buffer_view* view = accessor->buffer_view;
1012 const cgltf_size offset = accessor->offset + view->offset;
1013 const cgltf_size buffer_index = view->buffer - data->buffers; 1033 const cgltf_size buffer_index = view->buffer - data->buffers;
1014 1034
1015 assert(buffer_index < data->buffers_count); 1035 assert(buffer_index < data->buffers_count);
@@ -1099,12 +1119,20 @@ static bool load_meshes(
1099 break; 1119 break;
1100 } 1120 }
1101 1121
1102#define CONFIGURE_BUFFER(buf) \ 1122 // See comments here for accessor/view/buffer invariants:
1103 if (buf) { \ 1123 // https://github.com/KhronosGroup/glTF-Sample-Assets/issues/242
1104 buf->buffer = buffer; \ 1124 // Gfx only has Buffer and BufferView, not accessors. We must combine
1105 buf->offset_bytes = offset; \ 1125 // the glTF's accessor and view offsets correctly.
1106 buf->size_bytes = view->size; \ 1126 const cgltf_size offset = accessor->offset + view->offset;
1107 buf->stride_bytes = view->stride; \ 1127 const cgltf_size size_bytes = view->size - accessor->offset;
1128
1129#define CONFIGURE_BUFFER(buf) \
1130 if (buf) { \
1131 buf->buffer = buffer; \
1132 buf->offset_bytes = offset; \
1133 buf->size_bytes = size_bytes; \
1134 buf->stride_bytes = view->stride; \
1135 buf->count = accessor->count; \
1108 } 1136 }
1109 CONFIGURE_BUFFER(buffer_view_2d); 1137 CONFIGURE_BUFFER(buffer_view_2d);
1110 CONFIGURE_BUFFER(buffer_view_3d); 1138 CONFIGURE_BUFFER(buffer_view_3d);
@@ -1139,14 +1167,11 @@ static bool load_meshes(
1139 // either 2d or 3d positions but not both, here we can perform addition 1167 // either 2d or 3d positions but not both, here we can perform addition
1140 // to compute the total number of vertices. 1168 // to compute the total number of vertices.
1141 geometry_desc.num_verts = 1169 geometry_desc.num_verts =
1142 (geometry_desc.positions2d.size_bytes / sizeof(vec2)) + 1170 geometry_desc.positions2d.count + geometry_desc.positions3d.count;
1143 (geometry_desc.positions3d.size_bytes / sizeof(vec3)); 1171
1144 1172#define CHECK_COUNT(buffer_view, type, num_components) \
1145#define CHECK_COUNT(buffer_view, type, num_components) \ 1173 if (geometry_desc.buffer_view.buffer) { \
1146 if (geometry_desc.buffer_view.buffer) { \ 1174 assert(geometry_desc.buffer_view.count == geometry_desc.num_verts); \
1147 assert( \
1148 (geometry_desc.buffer_view.size_bytes / \
1149 (num_components * sizeof(type))) == geometry_desc.num_verts); \
1150 } 1175 }
1151 1176
1152 // Check that the number of vertices is consistent across all vertex 1177 // Check that the number of vertices is consistent across all vertex