Cache materials in gltf as the abstract class of Material
Use the abstract material class instead of BaseMaterial3D. This allows inserting ShaderMaterials into gltf. Like in VRM.
This commit is contained in:
parent
e3a51e53ef
commit
baab97302a
4 changed files with 207 additions and 199 deletions
|
@ -66,7 +66,7 @@
|
|||
</description>
|
||||
</method>
|
||||
<method name="get_materials">
|
||||
<return type="BaseMaterial3D[]" />
|
||||
<return type="Material[]" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
|
@ -169,7 +169,7 @@
|
|||
</method>
|
||||
<method name="set_materials">
|
||||
<return type="void" />
|
||||
<param index="0" name="materials" type="BaseMaterial3D[]" />
|
||||
<param index="0" name="materials" type="Material[]" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
|
|
|
@ -2484,12 +2484,12 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) {
|
|||
if (surface_i < instance_materials.size()) {
|
||||
v = instance_materials.get(surface_i);
|
||||
}
|
||||
Ref<BaseMaterial3D> mat = v;
|
||||
Ref<Material> mat = v;
|
||||
if (!mat.is_valid()) {
|
||||
mat = import_mesh->get_surface_material(surface_i);
|
||||
}
|
||||
if (mat.is_valid()) {
|
||||
HashMap<Ref<BaseMaterial3D>, GLTFMaterialIndex>::Iterator material_cache_i = state->material_cache.find(mat);
|
||||
HashMap<Ref<Material>, GLTFMaterialIndex>::Iterator material_cache_i = state->material_cache.find(mat);
|
||||
if (material_cache_i && material_cache_i->value != -1) {
|
||||
primitive["material"] = material_cache_i->value;
|
||||
} else {
|
||||
|
@ -2937,16 +2937,18 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) {
|
|||
}
|
||||
}
|
||||
|
||||
Ref<BaseMaterial3D> mat;
|
||||
Ref<Material> mat;
|
||||
String mat_name;
|
||||
if (!state->discard_meshes_and_materials) {
|
||||
if (p.has("material")) {
|
||||
const int material = p["material"];
|
||||
ERR_FAIL_INDEX_V(material, state->materials.size(), ERR_FILE_CORRUPT);
|
||||
Ref<BaseMaterial3D> mat3d = state->materials[material];
|
||||
Ref<Material> mat3d = state->materials[material];
|
||||
ERR_FAIL_NULL_V(mat3d, ERR_FILE_CORRUPT);
|
||||
if (has_vertex_color) {
|
||||
mat3d->set_flag(BaseMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
|
||||
|
||||
Ref<BaseMaterial3D> base_material = mat3d;
|
||||
if (has_vertex_color && base_material.is_valid()) {
|
||||
base_material->set_flag(BaseMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
|
||||
}
|
||||
mat = mat3d;
|
||||
|
||||
|
@ -2954,7 +2956,7 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) {
|
|||
Ref<StandardMaterial3D> mat3d;
|
||||
mat3d.instantiate();
|
||||
if (has_vertex_color) {
|
||||
mat3d->set_flag(BaseMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
|
||||
mat3d->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
|
||||
}
|
||||
mat = mat3d;
|
||||
}
|
||||
|
@ -3382,8 +3384,7 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) {
|
|||
Array materials;
|
||||
for (int32_t i = 0; i < state->materials.size(); i++) {
|
||||
Dictionary d;
|
||||
|
||||
Ref<BaseMaterial3D> material = state->materials[i];
|
||||
Ref<Material> material = state->materials[i];
|
||||
if (material.is_null()) {
|
||||
materials.push_back(d);
|
||||
continue;
|
||||
|
@ -3391,11 +3392,12 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) {
|
|||
if (!material->get_name().is_empty()) {
|
||||
d["name"] = _gen_unique_name(state, material->get_name());
|
||||
}
|
||||
{
|
||||
Ref<BaseMaterial3D> base_material = material;
|
||||
if (base_material.is_valid()) {
|
||||
Dictionary mr;
|
||||
{
|
||||
Array arr;
|
||||
const Color c = material->get_albedo().srgb_to_linear();
|
||||
const Color c = base_material->get_albedo().srgb_to_linear();
|
||||
arr.push_back(c.r);
|
||||
arr.push_back(c.g);
|
||||
arr.push_back(c.b);
|
||||
|
@ -3404,12 +3406,13 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) {
|
|||
}
|
||||
{
|
||||
Dictionary bct;
|
||||
Ref<Texture2D> albedo_texture = material->get_texture(BaseMaterial3D::TEXTURE_ALBEDO);
|
||||
if (base_material.is_valid()) {
|
||||
Ref<Texture2D> albedo_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_ALBEDO);
|
||||
GLTFTextureIndex gltf_texture_index = -1;
|
||||
|
||||
if (albedo_texture.is_valid() && albedo_texture->get_image().is_valid()) {
|
||||
albedo_texture->set_name(material->get_name() + "_albedo");
|
||||
gltf_texture_index = _set_texture(state, albedo_texture, material->get_texture_filter(), material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT));
|
||||
gltf_texture_index = _set_texture(state, albedo_texture, base_material->get_texture_filter(), base_material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT));
|
||||
}
|
||||
if (gltf_texture_index != -1) {
|
||||
bct["index"] = gltf_texture_index;
|
||||
|
@ -3421,20 +3424,21 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) {
|
|||
mr["baseColorTexture"] = bct;
|
||||
}
|
||||
}
|
||||
|
||||
mr["metallicFactor"] = material->get_metallic();
|
||||
mr["roughnessFactor"] = material->get_roughness();
|
||||
bool has_roughness = material->get_texture(BaseMaterial3D::TEXTURE_ROUGHNESS).is_valid() && material->get_texture(BaseMaterial3D::TEXTURE_ROUGHNESS)->get_image().is_valid();
|
||||
bool has_ao = material->get_feature(BaseMaterial3D::FEATURE_AMBIENT_OCCLUSION) && material->get_texture(BaseMaterial3D::TEXTURE_AMBIENT_OCCLUSION).is_valid();
|
||||
bool has_metalness = material->get_texture(BaseMaterial3D::TEXTURE_METALLIC).is_valid() && material->get_texture(BaseMaterial3D::TEXTURE_METALLIC)->get_image().is_valid();
|
||||
}
|
||||
if (base_material.is_valid()) {
|
||||
mr["metallicFactor"] = base_material->get_metallic();
|
||||
mr["roughnessFactor"] = base_material->get_roughness();
|
||||
bool has_roughness = base_material->get_texture(BaseMaterial3D::TEXTURE_ROUGHNESS).is_valid() && base_material->get_texture(BaseMaterial3D::TEXTURE_ROUGHNESS)->get_image().is_valid();
|
||||
bool has_ao = base_material->get_feature(BaseMaterial3D::FEATURE_AMBIENT_OCCLUSION) && base_material->get_texture(BaseMaterial3D::TEXTURE_AMBIENT_OCCLUSION).is_valid();
|
||||
bool has_metalness = base_material->get_texture(BaseMaterial3D::TEXTURE_METALLIC).is_valid() && base_material->get_texture(BaseMaterial3D::TEXTURE_METALLIC)->get_image().is_valid();
|
||||
if (has_ao || has_roughness || has_metalness) {
|
||||
Dictionary mrt;
|
||||
Ref<Texture2D> roughness_texture = material->get_texture(BaseMaterial3D::TEXTURE_ROUGHNESS);
|
||||
BaseMaterial3D::TextureChannel roughness_channel = material->get_roughness_texture_channel();
|
||||
Ref<Texture2D> metallic_texture = material->get_texture(BaseMaterial3D::TEXTURE_METALLIC);
|
||||
BaseMaterial3D::TextureChannel metalness_channel = material->get_metallic_texture_channel();
|
||||
Ref<Texture2D> ao_texture = material->get_texture(BaseMaterial3D::TEXTURE_AMBIENT_OCCLUSION);
|
||||
BaseMaterial3D::TextureChannel ao_channel = material->get_ao_texture_channel();
|
||||
Ref<Texture2D> roughness_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_ROUGHNESS);
|
||||
BaseMaterial3D::TextureChannel roughness_channel = base_material->get_roughness_texture_channel();
|
||||
Ref<Texture2D> metallic_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_METALLIC);
|
||||
BaseMaterial3D::TextureChannel metalness_channel = base_material->get_metallic_texture_channel();
|
||||
Ref<Texture2D> ao_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_AMBIENT_OCCLUSION);
|
||||
BaseMaterial3D::TextureChannel ao_channel = base_material->get_ao_texture_channel();
|
||||
Ref<ImageTexture> orm_texture;
|
||||
orm_texture.instantiate();
|
||||
Ref<Image> orm_image;
|
||||
|
@ -3480,7 +3484,7 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) {
|
|||
metallness_image->decompress();
|
||||
}
|
||||
}
|
||||
Ref<Texture2D> albedo_texture = material->get_texture(BaseMaterial3D::TEXTURE_ALBEDO);
|
||||
Ref<Texture2D> albedo_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_ALBEDO);
|
||||
if (albedo_texture.is_valid() && albedo_texture->get_image().is_valid()) {
|
||||
height = albedo_texture->get_height();
|
||||
width = albedo_texture->get_width();
|
||||
|
@ -3539,7 +3543,7 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) {
|
|||
GLTFTextureIndex orm_texture_index = -1;
|
||||
if (has_ao || has_roughness || has_metalness) {
|
||||
orm_texture->set_name(material->get_name() + "_orm");
|
||||
orm_texture_index = _set_texture(state, orm_texture, material->get_texture_filter(), material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT));
|
||||
orm_texture_index = _set_texture(state, orm_texture, base_material->get_texture_filter(), base_material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT));
|
||||
}
|
||||
if (has_ao) {
|
||||
Dictionary occt;
|
||||
|
@ -3556,15 +3560,15 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) {
|
|||
mr["metallicRoughnessTexture"] = mrt;
|
||||
}
|
||||
}
|
||||
}
|
||||
d["pbrMetallicRoughness"] = mr;
|
||||
}
|
||||
|
||||
if (material->get_feature(BaseMaterial3D::FEATURE_NORMAL_MAPPING)) {
|
||||
if (base_material->get_feature(BaseMaterial3D::FEATURE_NORMAL_MAPPING)) {
|
||||
Dictionary nt;
|
||||
Ref<ImageTexture> tex;
|
||||
tex.instantiate();
|
||||
{
|
||||
Ref<Texture2D> normal_texture = material->get_texture(BaseMaterial3D::TEXTURE_NORMAL);
|
||||
Ref<Texture2D> normal_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_NORMAL);
|
||||
if (normal_texture.is_valid()) {
|
||||
// Code for uncompressing RG normal maps
|
||||
Ref<Image> img = normal_texture->get_image();
|
||||
|
@ -3594,30 +3598,30 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) {
|
|||
GLTFTextureIndex gltf_texture_index = -1;
|
||||
if (tex.is_valid() && tex->get_image().is_valid()) {
|
||||
tex->set_name(material->get_name() + "_normal");
|
||||
gltf_texture_index = _set_texture(state, tex, material->get_texture_filter(), material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT));
|
||||
gltf_texture_index = _set_texture(state, tex, base_material->get_texture_filter(), base_material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT));
|
||||
}
|
||||
nt["scale"] = material->get_normal_scale();
|
||||
nt["scale"] = base_material->get_normal_scale();
|
||||
if (gltf_texture_index != -1) {
|
||||
nt["index"] = gltf_texture_index;
|
||||
d["normalTexture"] = nt;
|
||||
}
|
||||
}
|
||||
|
||||
if (material->get_feature(BaseMaterial3D::FEATURE_EMISSION)) {
|
||||
const Color c = material->get_emission().linear_to_srgb();
|
||||
if (base_material->get_feature(BaseMaterial3D::FEATURE_EMISSION)) {
|
||||
const Color c = base_material->get_emission().linear_to_srgb();
|
||||
Array arr;
|
||||
arr.push_back(c.r);
|
||||
arr.push_back(c.g);
|
||||
arr.push_back(c.b);
|
||||
d["emissiveFactor"] = arr;
|
||||
}
|
||||
if (material->get_feature(BaseMaterial3D::FEATURE_EMISSION)) {
|
||||
if (base_material->get_feature(BaseMaterial3D::FEATURE_EMISSION)) {
|
||||
Dictionary et;
|
||||
Ref<Texture2D> emission_texture = material->get_texture(BaseMaterial3D::TEXTURE_EMISSION);
|
||||
Ref<Texture2D> emission_texture = base_material->get_texture(BaseMaterial3D::TEXTURE_EMISSION);
|
||||
GLTFTextureIndex gltf_texture_index = -1;
|
||||
if (emission_texture.is_valid() && emission_texture->get_image().is_valid()) {
|
||||
emission_texture->set_name(material->get_name() + "_emission");
|
||||
gltf_texture_index = _set_texture(state, emission_texture, material->get_texture_filter(), material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT));
|
||||
gltf_texture_index = _set_texture(state, emission_texture, base_material->get_texture_filter(), base_material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT));
|
||||
}
|
||||
|
||||
if (gltf_texture_index != -1) {
|
||||
|
@ -3625,14 +3629,14 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) {
|
|||
d["emissiveTexture"] = et;
|
||||
}
|
||||
}
|
||||
const bool ds = material->get_cull_mode() == BaseMaterial3D::CULL_DISABLED;
|
||||
const bool ds = base_material->get_cull_mode() == BaseMaterial3D::CULL_DISABLED;
|
||||
if (ds) {
|
||||
d["doubleSided"] = ds;
|
||||
}
|
||||
if (material->get_transparency() == BaseMaterial3D::TRANSPARENCY_ALPHA_SCISSOR) {
|
||||
if (base_material->get_transparency() == BaseMaterial3D::TRANSPARENCY_ALPHA_SCISSOR) {
|
||||
d["alphaMode"] = "MASK";
|
||||
d["alphaCutoff"] = material->get_alpha_scissor_threshold();
|
||||
} else if (material->get_transparency() != BaseMaterial3D::TRANSPARENCY_DISABLED) {
|
||||
d["alphaCutoff"] = base_material->get_alpha_scissor_threshold();
|
||||
} else if (base_material->get_transparency() != BaseMaterial3D::TRANSPARENCY_DISABLED) {
|
||||
d["alphaMode"] = "BLEND";
|
||||
}
|
||||
materials.push_back(d);
|
||||
|
@ -3838,6 +3842,7 @@ void GLTFDocument::_set_texture_transform_uv1(const Dictionary &d, Ref<BaseMater
|
|||
if (d.has("extensions")) {
|
||||
const Dictionary &extensions = d["extensions"];
|
||||
if (extensions.has("KHR_texture_transform")) {
|
||||
if (material.is_valid()) {
|
||||
const Dictionary &texture_transform = extensions["KHR_texture_transform"];
|
||||
const Array &offset_arr = texture_transform["offset"];
|
||||
if (offset_arr.size() == 2) {
|
||||
|
@ -3852,15 +3857,22 @@ void GLTFDocument::_set_texture_transform_uv1(const Dictionary &d, Ref<BaseMater
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GLTFDocument::spec_gloss_to_rough_metal(Ref<GLTFSpecGloss> r_spec_gloss, Ref<BaseMaterial3D> p_material) {
|
||||
if (r_spec_gloss.is_null()) {
|
||||
return;
|
||||
}
|
||||
if (r_spec_gloss->spec_gloss_img.is_null()) {
|
||||
return;
|
||||
}
|
||||
if (r_spec_gloss->diffuse_img.is_null()) {
|
||||
return;
|
||||
}
|
||||
if (p_material.is_null()) {
|
||||
return;
|
||||
}
|
||||
bool has_roughness = false;
|
||||
bool has_metal = false;
|
||||
p_material->set_roughness(1.0f);
|
||||
|
@ -6657,21 +6669,17 @@ Dictionary _serialize_texture_transform_uv(Vector2 p_offset, Vector2 p_scale) {
|
|||
}
|
||||
|
||||
Dictionary GLTFDocument::_serialize_texture_transform_uv1(Ref<BaseMaterial3D> p_material) {
|
||||
if (p_material.is_valid()) {
|
||||
ERR_FAIL_NULL_V(p_material, Dictionary());
|
||||
Vector3 offset = p_material->get_uv1_offset();
|
||||
Vector3 scale = p_material->get_uv1_scale();
|
||||
return _serialize_texture_transform_uv(Vector2(offset.x, offset.y), Vector2(scale.x, scale.y));
|
||||
}
|
||||
return Dictionary();
|
||||
}
|
||||
|
||||
Dictionary GLTFDocument::_serialize_texture_transform_uv2(Ref<BaseMaterial3D> p_material) {
|
||||
if (p_material.is_valid()) {
|
||||
ERR_FAIL_NULL_V(p_material, Dictionary());
|
||||
Vector3 offset = p_material->get_uv2_offset();
|
||||
Vector3 scale = p_material->get_uv2_scale();
|
||||
return _serialize_texture_transform_uv(Vector2(offset.x, offset.y), Vector2(scale.x, scale.y));
|
||||
}
|
||||
return Dictionary();
|
||||
}
|
||||
|
||||
Error GLTFDocument::_serialize_version(Ref<GLTFState> state) {
|
||||
|
|
|
@ -209,11 +209,11 @@ void GLTFState::set_meshes(TypedArray<GLTFMesh> p_meshes) {
|
|||
GLTFTemplateConvert::set_from_array(meshes, p_meshes);
|
||||
}
|
||||
|
||||
TypedArray<BaseMaterial3D> GLTFState::get_materials() {
|
||||
TypedArray<Material> GLTFState::get_materials() {
|
||||
return GLTFTemplateConvert::to_array(materials);
|
||||
}
|
||||
|
||||
void GLTFState::set_materials(TypedArray<BaseMaterial3D> p_materials) {
|
||||
void GLTFState::set_materials(TypedArray<Material> p_materials) {
|
||||
GLTFTemplateConvert::set_from_array(materials, p_materials);
|
||||
}
|
||||
|
||||
|
|
|
@ -72,8 +72,8 @@ class GLTFState : public Resource {
|
|||
Vector<Ref<GLTFMesh>> meshes; // meshes are loaded directly, no reason not to.
|
||||
|
||||
Vector<AnimationPlayer *> animation_players;
|
||||
HashMap<Ref<BaseMaterial3D>, GLTFMaterialIndex> material_cache;
|
||||
Vector<Ref<BaseMaterial3D>> materials;
|
||||
HashMap<Ref<Material>, GLTFMaterialIndex> material_cache;
|
||||
Vector<Ref<Material>> materials;
|
||||
|
||||
String scene_name;
|
||||
Vector<int> root_nodes;
|
||||
|
@ -138,8 +138,8 @@ public:
|
|||
TypedArray<GLTFMesh> get_meshes();
|
||||
void set_meshes(TypedArray<GLTFMesh> p_meshes);
|
||||
|
||||
TypedArray<BaseMaterial3D> get_materials();
|
||||
void set_materials(TypedArray<BaseMaterial3D> p_materials);
|
||||
TypedArray<Material> get_materials();
|
||||
void set_materials(TypedArray<Material> p_materials);
|
||||
|
||||
String get_scene_name();
|
||||
void set_scene_name(String p_scene_name);
|
||||
|
|
Loading…
Reference in a new issue