Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GLTF Texture Filter Importing #54044

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
199 changes: 178 additions & 21 deletions modules/gltf/gltf_document.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,13 +128,19 @@ Error GLTFDocument::serialize(Ref<GLTFState> state, Node *p_root, const String &
return Error::FAILED;
}

// /* STEP 9 SERIALIZE ANIMATIONS */
/* STEP 9 SERIALIZE TEXTURE SAMPLERS */
err = _serialize_texture_samplers(state);
if (err != OK) {
return Error::FAILED;
}

// /* STEP 10 SERIALIZE ANIMATIONS */
err = _serialize_animations(state);
if (err != OK) {
return Error::FAILED;
}

/* STEP 10 SERIALIZE ACCESSORS */
/* STEP 11 SERIALIZE ACCESSORS */
err = _encode_accessors(state);
if (err != OK) {
return Error::FAILED;
Expand All @@ -144,43 +150,43 @@ Error GLTFDocument::serialize(Ref<GLTFState> state, Node *p_root, const String &
state->buffer_views.write[i]->buffer = 0;
}

/* STEP 11 SERIALIZE BUFFER VIEWS */
/* STEP 12 SERIALIZE BUFFER VIEWS */
err = _encode_buffer_views(state);
if (err != OK) {
return Error::FAILED;
}

/* STEP 12 SERIALIZE NODES */
/* STEP 13 SERIALIZE NODES */
err = _serialize_nodes(state);
if (err != OK) {
return Error::FAILED;
}

/* STEP 13 SERIALIZE SCENE */
/* STEP 15 SERIALIZE SCENE */
err = _serialize_scenes(state);
if (err != OK) {
return Error::FAILED;
}

/* STEP 14 SERIALIZE SCENE */
/* STEP 16 SERIALIZE SCENE */
err = _serialize_lights(state);
if (err != OK) {
return Error::FAILED;
}

/* STEP 15 SERIALIZE EXTENSIONS */
/* STEP 17 SERIALIZE EXTENSIONS */
err = _serialize_extensions(state);
if (err != OK) {
return Error::FAILED;
}

/* STEP 16 SERIALIZE VERSION */
/* STEP 18 SERIALIZE VERSION */
err = _serialize_version(state);
if (err != OK) {
return Error::FAILED;
}

/* STEP 17 SERIALIZE FILE */
/* STEP 19 SERIALIZE FILE */
err = _serialize_file(state, p_path);
if (err != OK) {
return Error::FAILED;
Expand Down Expand Up @@ -3126,11 +3132,11 @@ Error GLTFDocument::_parse_images(Ref<GLTFState> state, const String &p_base_pat
continue;
}

Ref<ImageTexture> t;
t.instance();
t->create_from_image(img);
//Ref<ImageTexture> t;
//t.instance();
//t->create_from_image(img);

state->images.push_back(t);
state->images.push_back(img);
}

print_verbose("glTF: Total images: " + itos(state->images.size()));
Expand All @@ -3149,6 +3155,7 @@ Error GLTFDocument::_serialize_textures(Ref<GLTFState> state) {
Ref<GLTFTexture> t = state->textures[i];
ERR_CONTINUE(t->get_src_image() == -1);
d["source"] = t->get_src_image();
d["sampler"] = t->get_sampler();
textures.push_back(d);
}
state->json["textures"] = textures;
Expand All @@ -3170,32 +3177,176 @@ Error GLTFDocument::_parse_textures(Ref<GLTFState> state) {
Ref<GLTFTexture> t;
t.instance();
t->set_src_image(d["source"]);
t->set_sampler(d["sampler"]);
state->textures.push_back(t);

// Create and cache the texture used in the engine
Ref<ImageTexture> imgTex;
imgTex.instance();
imgTex->create_from_image(state->images[t->get_src_image()]);

// Set texture filter and mipmap based on sampler object
const Ref<GLTFTextureSampler> sampler = state->texture_samplers[t->get_sampler()];

using MinFilter = GLTFTextureSampler::MinFilter;
using MagFilter = GLTFTextureSampler::MagFilter;
using WrapMode = GLTFTextureSampler::WrapMode;

uint32_t flags = 0;

// Set mipmap enabled
switch ((MinFilter)sampler->get_min_filter()) {
case MinFilter::LINEAR_MIPMAP_LINEAR:
case MinFilter::LINEAR_MIPMAP_NEAREST:
case MinFilter::NEAREST_MIPMAP_LINEAR:
case MinFilter::NEAREST_MIPMAP_NEAREST:
flags |= Texture::Flags::FLAG_MIPMAPS;
break;
}

// Set texture filter
switch ((MinFilter)sampler->get_min_filter()) {
case MinFilter::LINEAR_MIPMAP_LINEAR:
case MinFilter::LINEAR_MIPMAP_NEAREST:
case MinFilter::LINEAR:
flags |= Texture::Flags::FLAG_FILTER;
break;
}
if ((MagFilter)sampler->get_mag_filter() == MagFilter::LINEAR) {
flags |= Texture::Flags::FLAG_FILTER;
}

// Set wrapping/repeat mode
// Note: Currently, the engine does not support different wrapping modes for each sampling direction, so the S and T wrap modes are merged.
if ((WrapMode)sampler->get_wrap_s() == WrapMode::MIRRORED_REPEAT || (WrapMode)sampler->get_wrap_t() == WrapMode::MIRRORED_REPEAT) {
flags |= Texture::Flags::FLAG_MIRRORED_REPEAT;
} else if ((WrapMode)sampler->get_wrap_s() == WrapMode::REPEAT || (WrapMode)sampler->get_wrap_t() == WrapMode::REPEAT) {
flags |= Texture::Flags::FLAG_REPEAT;
}

imgTex->set_flags(flags);

state->textures_cache.insert(i, imgTex);
}

return OK;
}

GLTFTextureIndex GLTFDocument::_set_texture(Ref<GLTFState> state, Ref<Texture> p_texture) {
ERR_FAIL_COND_V(p_texture.is_null(), -1);
ERR_FAIL_COND_V(p_texture->get_data().is_null(), -1);

// Create GLTF data structures for the new texture
Ref<GLTFTexture> gltf_texture;
gltf_texture.instance();
ERR_FAIL_COND_V(p_texture->get_data().is_null(), -1);
GLTFImageIndex gltf_src_image_i = state->images.size();
state->images.push_back(p_texture);

state->images.push_back(p_texture->get_data());

gltf_texture->set_src_image(gltf_src_image_i);

Ref<GLTFTextureSampler> gltf_sampler;
gltf_sampler.instance();

bool mipmaps = (p_texture->get_flags() & Texture::FLAG_MIPMAPS) > 0;
bool filter = (p_texture->get_flags() & Texture::FLAG_FILTER) > 0;

// Interpret the texture flags as sampler properties
if (filter) {
if (mipmaps) {
gltf_sampler->set_min_filter((int)GLTFTextureSampler::MinFilter::LINEAR_MIPMAP_LINEAR);
} else {
gltf_sampler->set_min_filter((int)GLTFTextureSampler::MinFilter::LINEAR);
}
gltf_sampler->set_mag_filter((int)GLTFTextureSampler::MagFilter::LINEAR);
} else {
if (mipmaps) {
gltf_sampler->set_min_filter((int)GLTFTextureSampler::MinFilter::NEAREST_MIPMAP_NEAREST);
} else {
gltf_sampler->set_min_filter((int)GLTFTextureSampler::MinFilter::NEAREST);
}
gltf_sampler->set_mag_filter((int)GLTFTextureSampler::MagFilter::NEAREST);
}

if (p_texture->get_flags() & Texture::FLAG_MIRRORED_REPEAT > 0) {
gltf_sampler->set_wrap_s((int)GLTFTextureSampler::WrapMode::MIRRORED_REPEAT);
gltf_sampler->set_wrap_t((int)GLTFTextureSampler::WrapMode::MIRRORED_REPEAT);
} else if (p_texture->get_flags() & Texture::FLAG_REPEAT > 0) {
gltf_sampler->set_wrap_s((int)GLTFTextureSampler::WrapMode::REPEAT);
gltf_sampler->set_wrap_t((int)GLTFTextureSampler::WrapMode::REPEAT);
} else {
gltf_sampler->set_wrap_s((int)GLTFTextureSampler::WrapMode::CLAMP_TO_EDGE);
gltf_sampler->set_wrap_t((int)GLTFTextureSampler::WrapMode::CLAMP_TO_EDGE);
}

GLTFTextureSamplerIndex gltf_sampler_i = state->texture_samplers.size();
gltf_texture->set_sampler(gltf_sampler_i);

GLTFTextureIndex gltf_texture_i = state->textures.size();
state->textures.push_back(gltf_texture);
state->textures_cache[gltf_texture_i] = p_texture;
return gltf_texture_i;
}

Ref<Texture> GLTFDocument::_get_texture(Ref<GLTFState> state, const GLTFTextureIndex p_texture) {
ERR_FAIL_INDEX_V(p_texture, state->textures.size(), Ref<Texture>());
const GLTFImageIndex image = state->textures[p_texture]->get_src_image();
return state->textures_cache[p_texture];
}

Error GLTFDocument::_serialize_texture_samplers(Ref<GLTFState> state) {
if (!state->texture_samplers.size()) {
return OK;
}

Array samplers;
for (int32_t i = 0; i < state->texture_samplers.size(); ++i) {
Dictionary d;
Ref<GLTFTextureSampler> s = state->texture_samplers[i];
d["magFilter"] = (int32_t)s->get_mag_filter();
d["minFilter"] = (int32_t)s->get_min_filter();
d["wrapS"] = (int32_t)s->get_wrap_s();
d["wrapT"] = (int32_t)s->get_wrap_t();
samplers.push_back(d);
}
state->json["samplers"] = samplers;

return OK;
}

Error GLTFDocument::_parse_texture_samplers(Ref<GLTFState> state) {
if (!state->json.has("samplers")) {
return OK;
}

ERR_FAIL_INDEX_V(image, state->images.size(), Ref<Texture>());
const Array &samplers = state->json["samplers"];
for (int i = 0; i < samplers.size(); ++i) {
const Dictionary &d = samplers[i];

return state->images[image];
ERR_FAIL_COND_V(!d.has("minFilter"), ERR_PARSE_ERROR);
ERR_FAIL_COND_V(!d.has("magFilter"), ERR_PARSE_ERROR);

Ref<GLTFTextureSampler> sampler;
sampler.instance();
sampler->set_min_filter(d["minFilter"]);
sampler->set_mag_filter(d["magFilter"]);

// Wrapping modes are optional and have default values.
if (d.has("wrapS")) {
sampler->set_wrap_s(d["wrapS"]);
} else {
sampler->set_wrap_s((int)GLTFTextureSampler::WrapMode::DEFAULT);
}

if (d.has("wrapT")) {
sampler->set_wrap_t(d["wrapT"]);
} else {
sampler->set_wrap_t((int)GLTFTextureSampler::WrapMode::DEFAULT);
}

state->texture_samplers.push_back(sampler);
}

return OK;
}

Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) {
Expand Down Expand Up @@ -6572,19 +6723,25 @@ Error GLTFDocument::parse(Ref<GLTFState> state, String p_path, bool p_read_binar
return Error::FAILED;
}

/* STEP 5 PARSE IMAGES */
/* STEP 5 PARSE TEXTURE SAMPLERS */
err = _parse_texture_samplers(state);
if (err != OK) {
return Error::FAILED;
}

/* STEP 6 PARSE IMAGES */
err = _parse_images(state, p_path.get_base_dir());
if (err != OK) {
return Error::FAILED;
}

/* STEP 6 PARSE TEXTURES */
/* STEP 7 PARSE TEXTURES */
err = _parse_textures(state);
if (err != OK) {
return Error::FAILED;
}

/* STEP 7 PARSE TEXTURES */
/* STEP 8 PARSE MATERIALS */
err = _parse_materials(state);
if (err != OK) {
return Error::FAILED;
Expand Down
3 changes: 3 additions & 0 deletions modules/gltf/gltf_document.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ using GLTFNodeIndex = int;
using GLTFSkeletonIndex = int;
using GLTFSkinIndex = int;
using GLTFTextureIndex = int;
using GLTFTextureSamplerIndex = int;

class GLTFDocument : public Resource {
GDCLASS(GLTFDocument, Resource);
Expand Down Expand Up @@ -217,10 +218,12 @@ class GLTFDocument : public Resource {
const bool p_for_vertex);
Error _parse_meshes(Ref<GLTFState> state);
Error _serialize_textures(Ref<GLTFState> state);
Error _serialize_texture_samplers(Ref<GLTFState> state);
Error _serialize_images(Ref<GLTFState> state, const String &p_path);
Error _serialize_lights(Ref<GLTFState> state);
Error _parse_images(Ref<GLTFState> state, const String &p_base_path);
Error _parse_textures(Ref<GLTFState> state);
Error _parse_texture_samplers(Ref<GLTFState> state);
Error _parse_materials(Ref<GLTFState> state);
void _set_texture_transform_uv1(const Dictionary &d, Ref<SpatialMaterial> material);
void spec_gloss_to_rough_metal(Ref<GLTFSpecGloss> r_spec_gloss,
Expand Down
11 changes: 11 additions & 0 deletions modules/gltf/gltf_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ void GLTFState::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_root_nodes", "root_nodes"), &GLTFState::set_root_nodes);
ClassDB::bind_method(D_METHOD("get_textures"), &GLTFState::get_textures);
ClassDB::bind_method(D_METHOD("set_textures", "textures"), &GLTFState::set_textures);
ClassDB::bind_method(D_METHOD("get_texture_samplers"), &GLTFState::get_texture_samplers);
ClassDB::bind_method(D_METHOD("set_texture_samplers", "texture_samplers"), &GLTFState::set_texture_samplers);
ClassDB::bind_method(D_METHOD("get_images"), &GLTFState::get_images);
ClassDB::bind_method(D_METHOD("set_images", "images"), &GLTFState::set_images);
ClassDB::bind_method(D_METHOD("get_skins"), &GLTFState::get_skins);
Expand Down Expand Up @@ -95,6 +97,7 @@ void GLTFState::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::STRING, "scene_name"), "set_scene_name", "get_scene_name"); // String
ADD_PROPERTY(PropertyInfo(Variant::POOL_INT_ARRAY, "root_nodes"), "set_root_nodes", "get_root_nodes"); // Vector<int>
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "textures", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_textures", "get_textures"); // Vector<Ref<GLTFTexture>>
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "texture_samplers", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_texture_samplers", "get_texture_samplers"); //Vector<Ref<GLTFTextureSampler>>
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "images", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_images", "get_images"); // Vector<Ref<Texture>
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "skins", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_skins", "get_skins"); // Vector<Ref<GLTFSkin>>
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "cameras", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_cameras", "get_cameras"); // Vector<Ref<GLTFCamera>>
Expand Down Expand Up @@ -218,6 +221,14 @@ void GLTFState::set_textures(Array p_textures) {
GLTFDocument::set_from_array(textures, p_textures);
}

Array GLTFState::get_texture_samplers() {
return GLTFDocument::to_array(texture_samplers);
}

void GLTFState::set_texture_samplers(Array p_texture_samplers) {
GLTFDocument::set_from_array(texture_samplers, p_texture_samplers);
}

Array GLTFState::get_images() {
return GLTFDocument::to_array(images);
}
Expand Down
8 changes: 7 additions & 1 deletion modules/gltf/gltf_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include "gltf_skeleton.h"
#include "gltf_skin.h"
#include "gltf_texture.h"
#include "gltf_texture_sampler.h"
#include "scene/animation/animation_player.h"
#include "scene/resources/texture.h"

Expand Down Expand Up @@ -76,7 +77,9 @@ class GLTFState : public Resource {
String scene_name;
Vector<int> root_nodes;
Vector<Ref<GLTFTexture>> textures;
Vector<Ref<Texture>> images;
Vector<Ref<GLTFTextureSampler>> texture_samplers;
Vector<Ref<Image>> images;
Map<GLTFTextureIndex, Ref<Texture>> textures_cache;

Vector<Ref<GLTFSkin>> skins;
Vector<Ref<GLTFCamera>> cameras;
Expand Down Expand Up @@ -135,6 +138,9 @@ class GLTFState : public Resource {
Array get_textures();
void set_textures(Array p_textures);

Array get_texture_samplers();
void set_texture_samplers(Array p_texture_samplers);

Array get_images();
void set_images(Array p_images);

Expand Down
Loading