Тайлинг текстуры относительно скейла объекта

Шейдеры и все-все-все.

Тайлинг текстуры относительно скейла объекта

Сообщение Cylau 30 июн 2020, 01:26

Только начал погружаться в эти ваши шейдеры и тут же столкнулся с проблемой.
Хочу, чтобы текстура тайлилась на каждую грань в зависимости от скейла объекта. Если X Y Z одинаковые, то проблем не возникает.
Скрытый текст:
Изображение

Но если задать какие-нибудь произвольные значения для скейла, то всё начинает плыть.
Скрытый текст:
Изображение
Изображение

Возможно ли сделать так, чтобы текстура тайлилась на любую форму меша так же, как на первом скрине?

Фрагмент шейдера, отвечающий за тайлинг текстуры
Скрытый текст:
Изображение
И сама текстура
Изображение
Cylau
UNец
 
Сообщения: 7
Зарегистрирован: 25 июн 2019, 00:40

Re: Тайлинг текстуры относительно скейла объекта

Сообщение Tolking 30 июн 2020, 09:52

Невозможно сделать чтобы текстура тайлилась на ЛЮБУЮ форму меша. Нельзя листом бумаги обернуть мячик, чтобы на бумаге не было складок.
Ковчег построил любитель, профессионалы построили Титаник.
Аватара пользователя
Tolking
Адепт
 
Сообщения: 2714
Зарегистрирован: 08 июн 2009, 18:22
Откуда: Тула

Re: Тайлинг текстуры относительно скейла объекта

Сообщение alew 01 июл 2020, 01:32

С помощью UV координат можно это сделать
Изображение


Синтаксис:
Используется csharp
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;

public class uvScale : MonoBehaviour
{
    GameObject g;
    Mesh mesh;
    Material m;
    Texture2D texture2d;
    public Vector2[] uv;
    Vector2[] uvLast;
    bool loadTexture = false;
   
    void Start()
    {
        g = GameObject.CreatePrimitive(PrimitiveType.Cube);
        mesh = g.GetComponent<MeshFilter>().mesh;
        StartCoroutine(textureLoad());
        uv = mesh.uv;
        uvLast = mesh.uv;
       
    }

    // Update is called once per frame
    void Update()
    {
        if (loadTexture)
        {
            if (!uv.Equals(uvLast))
            {
                mesh.SetUVs(0, uv);
                uvLast = mesh.uv;
            }
   
            if (Input.GetKey(KeyCode.S))
            {
                ScaleUV(.01f);
            }
            if (Input.GetKey(KeyCode.X))
            {
                ScaleUV(-.01f);
            }
            MoveUVHorizontal(Input.GetAxis("Horizontal")*0.01f);
            MoveUVVertical(Input.GetAxis("Vertical")*0.01f);
            }
        void ScaleUV(float s)
        {
            Vector2 v = uv[6];
            v.x += s;
            v.y += -s;
            uv[6]  =v;
            v = uv[7];
            v.x += -s;
            v.y +=- s;
            uv[7] = v;
            v = uv[10];
            v.x += s;
            v.y += s;
            uv[10] = v;
            v = uv[11];
            v.x += -s;
            v.y += s;
            uv[11] = v;
        }
        void MoveUVHorizontal(float s)
        {
            Vector2 v = uv[6];
            v.x += s;
            uv[6] = v;
            v = uv[7];
            v.x += s;
            uv[7] = v;
            v = uv[10];
            v.x += s;
            uv[10] = v;
            v = uv[11];
            v.x += s;
            uv[11] = v;
        }
        void MoveUVVertical(float s)
        {
            Vector2 v = uv[6];
            v.y += s;
            uv[6] = v;
            v = uv[7];
            v.y += s;
            uv[7] = v;
            v = uv[10];
            v.y += s;
            uv[10] = v;
            v = uv[11];
            v.y += s;
            uv[11] = v;
        }
    }
    private void OnGUI()
    {
        GUILayout.Label("press S,X to scale");
        GUILayout.Label("press arrows to move");
    }
    IEnumerator textureLoad()
    {
        UnityWebRequest request = UnityWebRequestTexture.GetTexture("https://opengameart.org/sites/default/files/styles/medium/public/preview_874.png");
        yield return request.SendWebRequest();
        if (request.isHttpError || request.isNetworkError)
            print("егор, наверно нет текстуры");
        else
            texture2d = DownloadHandlerTexture.GetContent(request);
        loadTexture = true;
        texture2d.filterMode = FilterMode.Point;
        m = new Material(Shader.Find("Unlit/Texture"));
        m.SetTexture(1, texture2d);
        g.GetComponent<MeshRenderer>().material = m;
    }
}

 
alew
UNIт
 
Сообщения: 76
Зарегистрирован: 23 ноя 2018, 19:59

Re: Тайлинг текстуры относительно скейла объекта

Сообщение Tolking 01 июл 2020, 02:43

На кубический меш можно. На ЛЮБУЮ форму меша - нет.
Ковчег построил любитель, профессионалы построили Титаник.
Аватара пользователя
Tolking
Адепт
 
Сообщения: 2714
Зарегистрирован: 08 июн 2009, 18:22
Откуда: Тула

Re: Тайлинг текстуры относительно скейла объекта

Сообщение jetyb 03 июл 2020, 08:19

Посмотрите как сделан трипланарный шейдер:
есть точка и ось координат Oxyz
берется три плоскости Oxy, Oyz, Oxz
для каждой плоскости находится проекция мировой позиции точки - двумерная координата UV_z, UV_x, UV_y
затем считаются веса: скалярные произведения нормали точки на нормали этих плоскостей w_z, w_x, w_y
веса нормируются
UV = w_z * UV_z + w_x * UV_x + w_y * UV_y
полученное UV - проскэйленная координата

Если кубик как-то развернут, то можно брать за ось Oxyz локальные координаты кубика (определяются через мировую матрицу модели - параметр _Object2World). Не забудьте поставить тэг DisableBatching, чтобы батчинг не похерил мировую матрицу модели.
jetyb
Адепт
 
Сообщения: 1486
Зарегистрирован: 31 окт 2011, 17:21


Вернуться в Shader Lab

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2