Как сохранить размеры текстуры в Three.js при масштабировании сетки?

Я работаю над проектом Three.js, где у меня есть объект-сетка с нанесенной текстурой. Текстура представляет собой файл PNG размером 64x64.

Проблема: При изменении размеров объекта-сетки текстура растягивается по высоте и ширине, что искажает ее внешний вид. Я хочу, чтобы текстура сохраняла свои первоначальные размеры (64x64) независимо от размера сетки.

Когда сетка 64x64
Как сохранить размеры текстуры в Three.js при масштабировании сетки?

Когда сетка имеет размер 16x07 (или любой другой, кроме NxN)
Как сохранить размеры текстуры в Three.js при масштабировании сетки?

Я пытался изучить свойства текстуры и настройки материала в Three.js, но не смог найти способ сохранить фиксированные размеры текстуры при масштабировании сетки.

Как я могу предотвратить растяжение текстуры и сохранить ее исходный размер 64x64, когда размеры сетки изменяются в Three.js?

Вот как создается объект и материал меша
Создание Материала

function _createMaterial(url: string): THREE.MeshBasicMaterial {
    let material = new THREE.MeshBasicMaterial();

    this.loader.load(url, (texture) => {
        texture.magFilter = THREE.NearestFilter;
        texture.minFilter = THREE.LinearMipMapLinearFilter;
        material.setValues({ map: texture });
    });
    return material;
}

Создание MeshObject

this._meshObject = new Utils3.myTHREE.Mesh(geometry, material);
Применение градиента к изображению с помощью CSS
Применение градиента к изображению с помощью CSS
Здравствуйте, братья и сестры, как дела? Недавно я застрял на применении градиента к изображению. Я применял это много раз, но иногда наши требования...
Получение URL-адреса изображения курса в Moodle с помощью PHP
Получение URL-адреса изображения курса в Moodle с помощью PHP
Moodle - это популярная система управления обучением с открытым исходным кодом, используемая многими учебными заведениями и организациями по всему...
2
0
79
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете попробовать использовать: non-indexed геометрию и разделить сетку вручную, вы можете использовать собственный шейдер и создать сопоставленный шейдер для геометрии, вы можете попытаться вручную изменить UV сопоставленной геометрии, вы можете попробовать использовать несколько материалов (пользовательские шейдер) по геометрии. Но все эти усилия будут бессмысленны, потому что если не изолировать текстуру от геометрии, она всегда будет зависеть от нее.

Примечание. После первоначального использования текстуры ее размеры, формат и Тип не может быть изменен...

Всегда будет растягиваться, повторяться и т. д. В принципе, это имеет смысл при отображении, не так ли?

На вашем месте я бы использовал DecalGeometry в данном конкретном случае. Это позволяет независимо манипулировать двумя геометриями. Более того, судя по картинкам, которые вы показали, у меня это выглядит так, скажем так, как декаль.

const boxGeometry = new THREE.BoxGeometry(2, 2);
const loader = new THREE.TextureLoader();
const texture = loader.load('https://media.craiyon.com/2023-11-26/2ets6-v1SVGOdKAtPxmlMw.webp');
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00, wireframe: true });
const mesh = new THREE.Mesh(boxGeometry, material);
scene.add(mesh);

const position = new THREE.Vector3(0,0,1);
const orientation = new THREE.Euler();
const size = new THREE.Vector3(1, 1 ,1);

const decalGeometry = new DecalGeometry(mesh, position, orientation, size);
const decalMaterial = new THREE.MeshBasicMaterial({ map: texture, polygonOffset: true, polygonOffsetFactor: -1 });
const decalMesh = new THREE.Mesh(decalGeometry, decalMaterial);

https://codepen.io/Lucas_Mas/full/VwOrYGR

ОБНОВЛЯТЬ

Спрайт — версия, в которой текстура всегда обращена к камере. Важно в 3D-контексте.

https://codepen.io/Lucas_Mas/full/wvbPrvW

Я также пришел к тому же решению, но из-за некоторых специфических требований в моем случае использования я выбрал другой подход к использованию спрайтов. Тем не менее, спасибо за ваш вклад.

Kuldeep J 13.06.2024 14:54
Ответ принят как подходящий

Решение, предложенное Лукашом Д. Масталерцем, также имеет смысл, но в моем случае я отказался от текстурного подхода и использовал спрайты.

Создание спрайта:

    private static _createSprite(url: string): THREE.Sprite {
        let spriteMaterial: THREE.SpriteMaterial = null;
        let sprite: THREE.Sprite = new THREE.Sprite(); // Initialize the sprite
    
        this.loader.load(url, (texture) => {
            // Create a sprite material with the loaded texture
            spriteMaterial = new THREE.SpriteMaterial({ map: texture });
        
            // Assign the material to the sprite
            sprite.material = spriteMaterial;
    
            // Set the dimensions of the sprite
            sprite.scale.set(32, 32, 1);
    
            // Indicate that the sprite needs an update
            sprite.material.needsUpdate = true;
    
            // this.render(); // Uncomment if you need to render the scene after loading the texture
        });
    
        // Return the sprite, even if the texture is not done loading
        return sprite;
    }

Линия,

// Set the dimensions of the sprite  
sprite.scale.set(32, 32, 1);

играет важную роль в размещении изображения внутри объекта-сетки.

Вот конечный результат
screenshot

Конечно, окончательное решение всегда за вами. Но имейте в виду, что спрайт всегда смотрит в сторону камеры. Это может иметь решающее значение в 3D-среде. Просто включите «Наклейку» на «Спрайт» в моей ручке, и вы поймете, о чем я говорю. Если это решение по-прежнему вам подходит… это хорошо. ;)

Łukasz D. Mastalerz 13.06.2024 15:15

Другие вопросы по теме