diff --git a/editor_modules/gltf/config.py b/editor_modules/gltf/config.py
index a4ee871ef..41b76769b 100644
--- a/editor_modules/gltf/config.py
+++ b/editor_modules/gltf/config.py
@@ -22,6 +22,7 @@ def get_doc_classes():
"GLTFSpecGloss",
"GLTFState",
"GLTFTexture",
+ "GLTFTextureSampler",
"PackedSceneGLTF",
]
diff --git a/editor_modules/gltf/doc_classes/GLTFState.xml b/editor_modules/gltf/doc_classes/GLTFState.xml
index 71621841b..80cd8ce7c 100644
--- a/editor_modules/gltf/doc_classes/GLTFState.xml
+++ b/editor_modules/gltf/doc_classes/GLTFState.xml
@@ -86,6 +86,12 @@
+
+
+
+ Retrieves the array of texture samplers that are used by the textures contained in the GLTF.
+
+
@@ -173,6 +179,13 @@
+
+
+
+
+ Sets the array of texture samplers that are used by the textures contained in the GLTF.
+
+
diff --git a/editor_modules/gltf/doc_classes/GLTFTexture.xml b/editor_modules/gltf/doc_classes/GLTFTexture.xml
index 767626300..08d09f110 100644
--- a/editor_modules/gltf/doc_classes/GLTFTexture.xml
+++ b/editor_modules/gltf/doc_classes/GLTFTexture.xml
@@ -10,6 +10,9 @@
+
+ ID of the texture sampler to use when sampling the image. If -1, then the default texture sampler is used (linear filtering, and repeat wrapping in both axes).
+
diff --git a/editor_modules/gltf/gltf_document.cpp b/editor_modules/gltf/gltf_document.cpp
index 7dfa42bef..4a617c2f9 100644
--- a/editor_modules/gltf/gltf_document.cpp
+++ b/editor_modules/gltf/gltf_document.cpp
@@ -135,71 +135,71 @@ Error GLTFDocument::serialize(Ref state, Node *p_root, const String &
return Error::FAILED;
}
- /* STEP 7 SERIALIZE ANIMATIONS */
+ /* STEP 7 SERIALIZE TEXTURE SAMPLERS */
+ err = _serialize_texture_samplers(state);
+ if (err != OK) {
+ return Error::FAILED;
+ }
+
+ /* STEP 8 SERIALIZE ANIMATIONS */
err = _serialize_animations(state);
if (err != OK) {
return Error::FAILED;
}
- /* STEP 8 SERIALIZE ACCESSORS */
+ /* STEP 9 SERIALIZE ACCESSORS */
err = _encode_accessors(state);
if (err != OK) {
return Error::FAILED;
}
- /* STEP 9 SERIALIZE IMAGES */
+ /* STEP 10 SERIALIZE IMAGES */
err = _serialize_images(state, p_path);
if (err != OK) {
return Error::FAILED;
}
- /* STEP 10 SERIALIZE TEXTURES */
- err = _serialize_textures(state);
- if (err != OK) {
- return Error::FAILED;
- }
-
for (GLTFBufferViewIndex i = 0; i < state->buffer_views.size(); i++) {
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;
@@ -2950,7 +2950,7 @@ Error GLTFDocument::_serialize_images(Ref state, const String &p_path
ERR_CONTINUE(state->images[i].is_null());
- Ref image = state->images[i]->get_data();
+ Ref image = state->images[i];
ERR_CONTINUE(image.is_null());
if (p_path.to_lower().ends_with("glb")) {
@@ -3155,11 +3155,7 @@ Error GLTFDocument::_parse_images(Ref state, const String &p_base_pat
continue;
}
- Ref 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()));
@@ -3178,6 +3174,11 @@ Error GLTFDocument::_serialize_textures(Ref state) {
Ref t = state->textures[i];
ERR_CONTINUE(t->get_src_image() == -1);
d["source"] = t->get_src_image();
+
+ GLTFTextureSamplerIndex sampler_index = t->get_sampler();
+ if (sampler_index != -1) {
+ d["sampler"] = sampler_index;
+ }
textures.push_back(d);
}
state->json["textures"] = textures;
@@ -3199,7 +3200,24 @@ Error GLTFDocument::_parse_textures(Ref state) {
Ref t;
t.instance();
t->set_src_image(d["source"]);
+ if (d.has("sampler")) {
+ t->set_sampler(d["sampler"]);
+ } else {
+ t->set_sampler(-1);
+ }
state->textures.push_back(t);
+
+ // Create and cache the texture used in the engine
+ Ref imgTex;
+ imgTex.instance();
+ imgTex->create_from_image(state->images[t->get_src_image()]);
+
+ // Set texture filter and repeat based on sampler settings
+ const Ref sampler = _get_sampler_for_texture(state, t->get_sampler());
+ Texture::Flags flags = sampler->get_texture_flags();
+ imgTex->set_flags(flags);
+
+ state->texture_cache.insert(i, imgTex);
}
return OK;
@@ -3207,24 +3225,124 @@ Error GLTFDocument::_parse_textures(Ref state) {
GLTFTextureIndex GLTFDocument::_set_texture(Ref state, Ref 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 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());
+
+ GLTFTextureSamplerIndex gltf_sampler_i = _set_sampler_for_mode(state, p_texture->get_flags());
+
gltf_texture->set_src_image(gltf_src_image_i);
+ gltf_texture->set_sampler(gltf_sampler_i);
+
GLTFTextureIndex gltf_texture_i = state->textures.size();
state->textures.push_back(gltf_texture);
+ state->texture_cache[gltf_texture_i] = p_texture;
return gltf_texture_i;
}
Ref GLTFDocument::_get_texture(Ref state, const GLTFTextureIndex p_texture) {
ERR_FAIL_INDEX_V(p_texture, state->textures.size(), Ref());
- const GLTFImageIndex image = state->textures[p_texture]->get_src_image();
+ return state->texture_cache[p_texture];
+}
- ERR_FAIL_INDEX_V(image, state->images.size(), Ref());
+GLTFTextureSamplerIndex GLTFDocument::_set_sampler_for_mode(Ref state, uint32_t p_mode) {
+ for (int i = 0; i < state->texture_samplers.size(); ++i) {
+ if (state->texture_samplers[i]->get_texture_flags() == p_mode) {
+ return i;
+ }
+ }
- return state->images[image];
+ GLTFTextureSamplerIndex gltf_sampler_i = state->texture_samplers.size();
+ Ref gltf_sampler;
+ gltf_sampler.instance();
+ gltf_sampler->set_texture_flags(p_mode);
+ state->texture_samplers.push_back(gltf_sampler);
+ return gltf_sampler_i;
+}
+
+Ref GLTFDocument::_get_sampler_for_texture(Ref state, const GLTFTextureIndex p_texture) {
+ ERR_FAIL_INDEX_V(p_texture, state->textures.size(), Ref());
+ const GLTFTextureSamplerIndex sampler = state->textures[p_texture]->get_sampler();
+
+ if (sampler == -1) {
+ return state->default_texture_sampler;
+ } else {
+ ERR_FAIL_INDEX_V(sampler, state->texture_samplers.size(), Ref());
+
+ return state->texture_samplers[sampler];
+ }
+}
+
+Error GLTFDocument::_serialize_texture_samplers(Ref state) {
+ if (!state->texture_samplers.size()) {
+ return OK;
+ }
+
+ Array samplers;
+ for (int32_t i = 0; i < state->texture_samplers.size(); ++i) {
+ Dictionary d;
+ Ref s = state->texture_samplers[i];
+ d["magFilter"] = s->get_mag_filter();
+ d["minFilter"] = s->get_min_filter();
+ d["wrapS"] = s->get_wrap_s();
+ d["wrapT"] = s->get_wrap_t();
+ samplers.push_back(d);
+ }
+ state->json["samplers"] = samplers;
+
+ return OK;
+}
+
+Error GLTFDocument::_parse_texture_samplers(Ref state) {
+ state->default_texture_sampler.instance();
+ state->default_texture_sampler->set_min_filter(GLTFTextureSampler::FilterMode::LINEAR_MIPMAP_LINEAR);
+ state->default_texture_sampler->set_mag_filter(GLTFTextureSampler::FilterMode::LINEAR);
+ state->default_texture_sampler->set_wrap_s(GLTFTextureSampler::WrapMode::REPEAT);
+ state->default_texture_sampler->set_wrap_t(GLTFTextureSampler::WrapMode::REPEAT);
+
+ if (!state->json.has("samplers")) {
+ return OK;
+ }
+
+ const Array &samplers = state->json["samplers"];
+ for (int i = 0; i < samplers.size(); ++i) {
+ const Dictionary &d = samplers[i];
+
+ Ref sampler;
+ sampler.instance();
+
+ if (d.has("minFilter")) {
+ sampler->set_min_filter(d["minFilter"]);
+ } else {
+ sampler->set_min_filter(GLTFTextureSampler::FilterMode::LINEAR_MIPMAP_LINEAR);
+ }
+ if (d.has("magFilter")) {
+ sampler->set_mag_filter(d["magFilter"]);
+ } else {
+ sampler->set_mag_filter(GLTFTextureSampler::FilterMode::LINEAR);
+ }
+
+ if (d.has("wrapS")) {
+ sampler->set_wrap_s(d["wrapS"]);
+ } else {
+ sampler->set_wrap_s(GLTFTextureSampler::WrapMode::REPEAT);
+ }
+
+ if (d.has("wrapT")) {
+ sampler->set_wrap_t(d["wrapT"]);
+ } else {
+ sampler->set_wrap_t(GLTFTextureSampler::WrapMode::REPEAT);
+ }
+
+ state->texture_samplers.push_back(sampler);
+ }
+
+ return OK;
}
Error GLTFDocument::_serialize_materials(Ref state) {
@@ -6668,13 +6786,19 @@ Error GLTFDocument::parse(Ref state, String p_path, bool p_read_binar
return Error::FAILED;
}
+ /* PARSE TEXTURE SAMPLERS */
+ err = _parse_texture_samplers(state);
+ if (err != OK) {
+ return Error::FAILED;
+ }
+
/* PARSE TEXTURES */
err = _parse_textures(state);
if (err != OK) {
return Error::FAILED;
}
- /* PARSE TEXTURES */
+ /* PARSE MATERIALS */
err = _parse_materials(state);
if (err != OK) {
return Error::FAILED;
diff --git a/editor_modules/gltf/gltf_document.h b/editor_modules/gltf/gltf_document.h
index 5c882969f..ba7b4e651 100644
--- a/editor_modules/gltf/gltf_document.h
+++ b/editor_modules/gltf/gltf_document.h
@@ -52,6 +52,7 @@ class GLTFSkin;
class GLTFNode;
class GLTFSpecGloss;
class GLTFSkeleton;
+class GLTFTextureSampler;
class MultiMeshInstance;
using GLTFAccessorIndex = int;
@@ -67,6 +68,7 @@ using GLTFNodeIndex = int;
using GLTFSkeletonIndex = int;
using GLTFSkinIndex = int;
using GLTFTextureIndex = int;
+using GLTFTextureSamplerIndex = int;
class GLTFDocument : public Resource {
GDCLASS(GLTFDocument, Resource);
@@ -178,6 +180,10 @@ private:
GLTFTextureIndex _set_texture(Ref state, Ref p_texture);
Ref _get_texture(Ref state,
const GLTFTextureIndex p_texture);
+ GLTFTextureSamplerIndex _set_sampler_for_mode(Ref state,
+ uint32_t p_mode);
+ Ref _get_sampler_for_texture(Ref state,
+ const GLTFTextureIndex p_texture);
Error _parse_json(const String &p_path, Ref state);
Error _parse_glb(const String &p_path, Ref state);
void _compute_node_heights(Ref state);
@@ -225,10 +231,12 @@ private:
const bool p_for_vertex);
Error _parse_meshes(Ref state);
Error _serialize_textures(Ref state);
+ Error _serialize_texture_samplers(Ref state);
Error _serialize_images(Ref state, const String &p_path);
Error _serialize_lights(Ref state);
Error _parse_images(Ref state, const String &p_base_path);
Error _parse_textures(Ref state);
+ Error _parse_texture_samplers(Ref state);
Error _parse_materials(Ref state);
void _set_texture_transform_uv1(const Dictionary &d, Ref material);
void spec_gloss_to_rough_metal(Ref r_spec_gloss,
diff --git a/editor_modules/gltf/gltf_state.cpp b/editor_modules/gltf/gltf_state.cpp
index 7c9818b94..46579b61f 100644
--- a/editor_modules/gltf/gltf_state.cpp
+++ b/editor_modules/gltf/gltf_state.cpp
@@ -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);
@@ -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
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "textures", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_textures", "get_textures"); // Vector[>
+ 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][>
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "images", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_images", "get_images"); // Vector][
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "skins", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_skins", "get_skins"); // Vector][>
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "cameras", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_cameras", "get_cameras"); // Vector][>
@@ -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);
}
diff --git a/editor_modules/gltf/gltf_state.h b/editor_modules/gltf/gltf_state.h
index fd4411c82..94a20b061 100644
--- a/editor_modules/gltf/gltf_state.h
+++ b/editor_modules/gltf/gltf_state.h
@@ -47,6 +47,9 @@
#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"
class GLTFState : public Resource {
GDCLASS(GLTFState, Resource);
@@ -77,7 +80,10 @@ class GLTFState : public Resource {
String scene_name;
Vector root_nodes;
Vector][> textures;
- Vector][> images;
+ Vector][> texture_samplers;
+ Ref default_texture_sampler;
+ Vector][> images;
+ Map> texture_cache;
Vector][> skins;
Vector][> cameras;
@@ -139,6 +145,9 @@ public:
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);
diff --git a/editor_modules/gltf/gltf_texture.cpp b/editor_modules/gltf/gltf_texture.cpp
index 2a21cb3df..5cc96e322 100644
--- a/editor_modules/gltf/gltf_texture.cpp
+++ b/editor_modules/gltf/gltf_texture.cpp
@@ -33,8 +33,11 @@
void GLTFTexture::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_src_image"), &GLTFTexture::get_src_image);
ClassDB::bind_method(D_METHOD("set_src_image", "src_image"), &GLTFTexture::set_src_image);
+ ClassDB::bind_method(D_METHOD("get_sampler"), &GLTFTexture::get_sampler);
+ ClassDB::bind_method(D_METHOD("set_sampler", "sampler"), &GLTFTexture::set_sampler);
ADD_PROPERTY(PropertyInfo(Variant::INT, "src_image"), "set_src_image", "get_src_image"); // int
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "sampler"), "set_sampler", "get_sampler"); // int
}
GLTFImageIndex GLTFTexture::get_src_image() const {
@@ -44,3 +47,11 @@ GLTFImageIndex GLTFTexture::get_src_image() const {
void GLTFTexture::set_src_image(GLTFImageIndex val) {
src_image = val;
}
+
+GLTFTextureSamplerIndex GLTFTexture::get_sampler() const {
+ return sampler;
+}
+
+void GLTFTexture::set_sampler(GLTFTextureSamplerIndex val) {
+ sampler = val;
+}
diff --git a/editor_modules/gltf/gltf_texture.h b/editor_modules/gltf/gltf_texture.h
index 886777c1b..82e5d5dd1 100644
--- a/editor_modules/gltf/gltf_texture.h
+++ b/editor_modules/gltf/gltf_texture.h
@@ -39,6 +39,7 @@ class GLTFTexture : public Resource {
private:
GLTFImageIndex src_image = 0;
+ GLTFTextureSamplerIndex sampler = -1;
protected:
static void _bind_methods();
@@ -46,6 +47,8 @@ protected:
public:
GLTFImageIndex get_src_image() const;
void set_src_image(GLTFImageIndex val);
+ GLTFTextureSamplerIndex get_sampler() const;
+ void set_sampler(GLTFTextureSamplerIndex val);
};
#endif // GLTF_TEXTURE_H
diff --git a/editor_modules/gltf/register_types.cpp b/editor_modules/gltf/register_types.cpp
index 4ce376eaf..bd5e4b753 100644
--- a/editor_modules/gltf/register_types.cpp
+++ b/editor_modules/gltf/register_types.cpp
@@ -78,6 +78,7 @@ void register_gltf_types() {
ClassDB::register_class();
ClassDB::register_class();
ClassDB::register_class();
+ ClassDB::register_class();
ClassDB::register_class();
ClassDB::register_class();
ClassDB::register_class();
diff --git a/modules/gltf/doc_classes/GLTFTextureSampler.xml b/modules/gltf/doc_classes/GLTFTextureSampler.xml
new file mode 100644
index 000000000..9f468e671
--- /dev/null
+++ b/modules/gltf/doc_classes/GLTFTextureSampler.xml
@@ -0,0 +1,29 @@
+
+
+
+ Represents a GLTF texture sampler
+
+
+ Represents a texture sampler as defined by the base GLTF spec. Texture samplers in GLTF specify how to sample data from the texture's base image, when rendering the texture on an object.
+
+
+
+
+
+
+
+ Texture's magnification filter, used when the texture appears larger on screen than the source image.
+
+
+ Texture's minification filter, used when the texture appears smaller on screen than the source image.
+
+
+ Wrapping mode to use for S-axis (horizontal) texture coordinates.
+
+
+ Wrapping mode to use for T-axis (vertical) texture coordinates.
+
+
+
+
+
diff --git a/modules/gltf/gltf_texture_sampler.cpp b/modules/gltf/gltf_texture_sampler.cpp
new file mode 100644
index 000000000..6cf615b6c
--- /dev/null
+++ b/modules/gltf/gltf_texture_sampler.cpp
@@ -0,0 +1,47 @@
+/*************************************************************************/
+/* gltf_texture_sampler.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "gltf_texture_sampler.h"
+
+void GLTFTextureSampler::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("get_mag_filter"), &GLTFTextureSampler::get_mag_filter);
+ ClassDB::bind_method(D_METHOD("set_mag_filter", "filter_mode"), &GLTFTextureSampler::set_mag_filter);
+ ClassDB::bind_method(D_METHOD("get_min_filter"), &GLTFTextureSampler::get_min_filter);
+ ClassDB::bind_method(D_METHOD("set_min_filter", "filter_mode"), &GLTFTextureSampler::set_min_filter);
+ ClassDB::bind_method(D_METHOD("get_wrap_s"), &GLTFTextureSampler::get_wrap_s);
+ ClassDB::bind_method(D_METHOD("set_wrap_s", "wrap_mode"), &GLTFTextureSampler::set_wrap_s);
+ ClassDB::bind_method(D_METHOD("get_wrap_t"), &GLTFTextureSampler::get_wrap_t);
+ ClassDB::bind_method(D_METHOD("set_wrap_t", "wrap_mode"), &GLTFTextureSampler::set_wrap_t);
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "mag_filter"), "set_mag_filter", "get_mag_filter");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "min_filter"), "set_min_filter", "get_min_filter");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "wrap_s"), "set_wrap_s", "get_wrap_s");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "wrap_t"), "set_wrap_t", "get_wrap_t");
+}
diff --git a/modules/gltf/gltf_texture_sampler.h b/modules/gltf/gltf_texture_sampler.h
new file mode 100644
index 000000000..05f442845
--- /dev/null
+++ b/modules/gltf/gltf_texture_sampler.h
@@ -0,0 +1,165 @@
+/*************************************************************************/
+/* gltf_texture_sampler.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef GLTF_TEXTURE_SAMPLER_H
+#define GLTF_TEXTURE_SAMPLER_H
+
+#include "core/resource.h"
+#include "scene/resources/texture.h"
+
+class GLTFTextureSampler : public Resource {
+ GDCLASS(GLTFTextureSampler, Resource);
+
+public:
+ enum FilterMode {
+ NEAREST = 9728,
+ LINEAR = 9729,
+ NEAREST_MIPMAP_NEAREST = 9984,
+ LINEAR_MIPMAP_NEAREST = 9985,
+ NEAREST_MIPMAP_LINEAR = 9986,
+ LINEAR_MIPMAP_LINEAR = 9987
+ };
+
+ enum WrapMode {
+ CLAMP_TO_EDGE = 33071,
+ MIRRORED_REPEAT = 33648,
+ REPEAT = 10497
+ };
+
+ int get_mag_filter() const {
+ return mag_filter;
+ }
+
+ void set_mag_filter(const int filter_mode) {
+ mag_filter = (FilterMode)filter_mode;
+ }
+
+ int get_min_filter() const {
+ return min_filter;
+ }
+
+ void set_min_filter(const int filter_mode) {
+ min_filter = (FilterMode)filter_mode;
+ }
+
+ int get_wrap_s() const {
+ return wrap_s;
+ }
+
+ void set_wrap_s(const int wrap_mode) {
+ wrap_s = (WrapMode)wrap_mode;
+ }
+
+ int get_wrap_t() const {
+ return wrap_t;
+ }
+
+ void set_wrap_t(const int wrap_mode) {
+ wrap_s = (WrapMode)wrap_mode;
+ }
+
+ Texture::Flags get_filter_mode() const {
+ switch (min_filter) {
+ case NEAREST:
+ return (Texture::Flags)0;
+ case LINEAR:
+ return Texture::Flags::FLAG_FILTER;
+ case NEAREST_MIPMAP_NEAREST:
+ case NEAREST_MIPMAP_LINEAR:
+ return Texture::Flags::FLAG_MIPMAPS;
+ case LINEAR_MIPMAP_NEAREST:
+ case LINEAR_MIPMAP_LINEAR:
+ default:
+ return (Texture::Flags)(Texture::Flags::FLAG_FILTER | Texture::Flags::FLAG_MIPMAPS);
+ }
+ }
+
+ void set_filter_mode(uint32_t flags) {
+ const bool filter = (flags & Texture::Flags::FLAG_FILTER);
+ const bool mipmaps = (flags & Texture::Flags::FLAG_MIPMAPS);
+
+ if (filter && mipmaps) {
+ min_filter = FilterMode::LINEAR_MIPMAP_LINEAR;
+ mag_filter = FilterMode::LINEAR;
+ } else if (filter) {
+ min_filter = FilterMode::LINEAR;
+ mag_filter = FilterMode::LINEAR;
+ } else if (mipmaps) {
+ min_filter = FilterMode::NEAREST_MIPMAP_LINEAR;
+ mag_filter = FilterMode::NEAREST;
+ } else {
+ min_filter = FilterMode::NEAREST;
+ mag_filter = FilterMode::NEAREST;
+ }
+ }
+
+ Texture::Flags get_wrap_mode() const {
+ if ((wrap_s == WrapMode::MIRRORED_REPEAT) && (wrap_t == WrapMode::MIRRORED_REPEAT)) {
+ return Texture::Flags::FLAG_MIRRORED_REPEAT;
+ } else if ((wrap_s == WrapMode::REPEAT) && (wrap_t == WrapMode::REPEAT)) {
+ return Texture::Flags::FLAG_REPEAT;
+ } else {
+ return (Texture::Flags)0;
+ }
+ }
+
+ void set_wrap_mode(uint32_t flags) {
+ if (flags & Texture::Flags::FLAG_MIRRORED_REPEAT) {
+ wrap_s = WrapMode::MIRRORED_REPEAT;
+ wrap_t = WrapMode::MIRRORED_REPEAT;
+ } else if (flags & Texture::Flags::FLAG_REPEAT) {
+ wrap_s = WrapMode::REPEAT;
+ wrap_t = WrapMode::REPEAT;
+ } else {
+ wrap_s = WrapMode::CLAMP_TO_EDGE;
+ wrap_t = WrapMode::CLAMP_TO_EDGE;
+ }
+ }
+
+ Texture::Flags get_texture_flags() const {
+ return (Texture::Flags)(get_filter_mode() | get_wrap_mode());
+ }
+
+ void set_texture_flags(uint32_t flags) {
+ set_filter_mode(flags);
+ set_wrap_mode(flags);
+ }
+
+protected:
+ static void _bind_methods();
+
+private:
+ FilterMode mag_filter = FilterMode::LINEAR;
+ FilterMode min_filter = FilterMode::LINEAR_MIPMAP_LINEAR;
+ WrapMode wrap_s = WrapMode::REPEAT;
+ WrapMode wrap_t = WrapMode::REPEAT;
+};
+
+#endif // GLTF_TEXTURE_SAMPLER_H
]