diff options
Diffstat (limited to 'src/asset/model.c')
| -rw-r--r-- | src/asset/model.c | 109 |
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 | ||
| 749 | static 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 |
