Шейдер поперечного сечения для привязки ящика с помощью усиливающего шейдера - PullRequest
1 голос
/ 04 октября 2019

Я пытаюсь создать шейдер с помощью усилителя для куба, чтобы разрезать плоскость или любую сетку при поперечном сечении. Я знаю, что должен использовать для этого размер, поворот и положение, но что именно с ними делать, чего я не знаю. Да, это означает, что я новичок в усилении шейдеров, а также в программировании шейдеров, поэтому, пожалуйста, не предоставляйте код шейдера, так как мне нужно сделать его настраиваемым на будущее, поэтому, пожалуйста, помогите мне в усилении узлов шейдеров.

В настоящее время у меня есть этот эффект, но я хочу сделать его более ориентированным на рамки, а не на плоскости. enter image description here

Мне нужен не этот эффект, а эффект коробки, показанный ниже. Это было достигнуто с помощью концепции марширования лучей, но этого я хочу достичь с помощью Amplify Shader. Пожалуйста, проведите меня через это. enter image description here

Это то, что я сделал до сих пор с узлами усиления enter image description here

1 Ответ

1 голос
/ 05 октября 2019

Результат:

Вот результат выполнения шейдера с использованием «Усилительный шейдер» :

Result

Решение:

Сначала мы назовем зеленый куб "пересечением" , а красный куб "межсекретным" .

Итаккак и в случае с плоскостью, вырез работает, потому что задняя поверхность пересечения показана, когда она находится внутри интерсекрета, а передняя сторона межсекретария показана, когда она находится внутри пересекателя.

Создание шейдера (который используется обоими кубами) и сложите их в два отдельных материала - примените отдельные материалы к каждому кубу. После этого мы можем перейти к фактическому шейдерному узлу.

Сначала нам нужно убедиться, что «Режим отбраковки» выключен (Выходной узел> Режим отбраковки> выключен). Это обеспечит фактическую визуализацию задней грани (это можно оптимизировать в зависимости от того, где находится куб в пересечении).


Далее нам нужно получить точку поверхности в пространстве объектов:

enter image description here

Большинство переменных будут определены в скрипте . Матрица вращения используется для поворота точки . Тем не менее, он инвертируется, так как матрица вращения поворачивает куб в мировое пространство, поэтому, инвертируя это, можно повернуть точку мирового пространства в пространство объекта. Мы также получаем "_ Cubepos", которая является позицией куба для пересечения (например, это будет пересечение, если шейдер находится на промежуточном объекте). Это вычитается миром pos, поскольку матрица вращения вращается вокруг начала координат. После этого он добавляется обратно, чтобы быть в правильном положении.


Extents

Это приводит к следующему разделу, где экстенты добавляются и вычитаютсяна "_ Cubepos" и "_ CubeExtent" для поиска минимального и максимального экстентов.


Point inside cube?

К сожалению, у шейдера Amplify нет хорошего способа проверить, лежит ли вектор в двух векторах. Поэтому мы должны разбить его на компоненты. (Я призываю вас научиться писать шейдеры). Каждое сравнение с диапазоном возвращает 1, если точка в пространстве объекта находится в пределах экстентов для каждой оси. Если возвращается 0, мы используем последний узел умножения, чтобы убедиться, что конечный результат будет 0.


Final output

Наконец, мы получаемпоследняя часть шейдера. «IsIntersector» устанавливается в сценарии равным 1 или 0 в зависимости от того, используется ли куб, на который мы ссылаемся, для пересечения или является межсекретным. В зависимости от сценария, здесь мы устанавливаем маску непрозрачности на 1 или 0.


После этого мы должны определить скрипт для присоединения к каждому объекту. Добавьте новый скрипт и введите следующее:

    [ExecuteInEditMode]
public class SetVar : MonoBehaviour
{
    //Transform of opposite cube
    public Transform intersectingCube;

    //Is this an intersector or intersectee
    public bool isIntersector;

    //Material of object
    public Material mat;

    // Start is called before the first frame update
    void Start()
    {
        //Get material
        mat = GetComponent<Renderer>().material;
    }

    // Update is called once per frame
    void OnRenderObject()
    {
        //Calculate rotation matrix
        Matrix4x4 m = Matrix4x4.TRS(-intersectingCube.position, intersectingCube.rotation, Vector3.one);

        //Set shader variables
        mat.SetMatrix("RotationMatrix", m);
        mat.SetVector("_Cubepos", intersectingCube.position);
        mat.SetVector("_CubeExtent", intersectingCube.localScale / 2.0f);
        mat.SetFloat("_IsIntersector", (isIntersector) ? 0 : 1);
    }
}

Затем мы можем установить правильные значения инспектора в зависимости от того, является ли куб пересечением или межсекретным. Вот пример для куба пересечения:

Inspector

Убедитесь, что IsIntersector отмечен галочкой, в зависимости от того, является ли кубявляется пересечением или нет.


Вот ссылка на шейдер: http://paste.amplify.pt/view/raw/4b248bc3. Также сделать это для любой сетки очень сложная операция - слишком сложная для узлов. Узнайте о коде шейдера и используйте алгоритм лучевого вещания, чтобы определить, находится ли точка внутри куба.


Кроме того, альтернативно для любой выпуклой формы. Вы можете рассчитать каждую плоскость, а затем, используя уже используемый метод, можете проверить, работает ли точка мирового положения для каждой плоскости. Для куба было бы 6 плоскостей, однако он немного медленнее, чем описанный выше метод (так как он оптимизирован для куба).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...