Страница 1 из 1

Текстура в шейдере

СообщениеДобавлено: 02 июн 2020, 15:09
Jarico
Как рисовать в шейдере примитивную фигуру с наложением на неё текстуры?

Допустим нужно нарисовать круг и заполнить его внутри текстурой

Re: Текстура в шейдере

СообщениеДобавлено: 02 июн 2020, 20:53
waruiyume
При традиционном подходе(пара: вершинный-пиксельный шейдер)- никак(я объясню ниже, что имел в виду). Есть экзотичные геометрические шейдеры- ими можно генерировать геометрию, ваш Кэп. Но они не популярны ввиду своей относительной тормознутости, удачи найти нормальные туторы по ним.
При традиционном подходе, пиксельный шейдер запускается для многих пикселей одновременно, свой пля каждого(в реальности для групп по несколько пикселей, но для нас это ничего не меняет). Ввиду параллельности, каждый пиксель знает только о себе и менять может только себя. По этому именно нарисовать что-то нельзя.
Можно посчитать какой должен быть цвет пикселя с помощью функции, которая принимает позицию(или, допустим, цвет текстуры в этом месте), и возращает цвет исходя из этого. Круг нарисовать будет довольно просто:
если дистанция от текущего пикселя до центра, допустим текстурных координат, чем радиус круга, то ничего не рисуется или пиксель рисуется чёрным.
Попробуйте начать с нодовых редакторов типа "Amplify shader editor", а когда немного разберётесь пробовать текстовые варианты, потому как текстовая кухня крайне сумбурна и в ней чёрт ногу сломит.

Несколько ссылок:
https://en.wikibooks.org/wiki/Cg_Programming //устаревшее, но поможет разобраться в принципах
https://en.wikibooks.org/wiki/GLSL_Programming/Unity //более актуальное, но есть не всё то, что в предыдущем

https://catlikecoding.com/unity/tutorials/rendering //годные уроки, но у автора есть склонность к оверинженерингу

Пример шейдера(материал нужно натянуть на объект у которого есть UV координаты(встроенный куб))
Синтаксис:
Используется glsl
Shader "Unlit/Circle"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.uv);

                float dist = distance(0.5, i.uv);
                col*=step(dist, 0.5);

                return col;
            }
            ENDCG
        }
    }
}
 

Re: Текстура в шейдере

СообщениеДобавлено: 02 июн 2020, 20:59
seaman
Либо генерить фигуру в геометрическом шейдере, либо raymarch

Re: Текстура в шейдере

СообщениеДобавлено: 02 июн 2020, 21:11
waruiyume
либо raymarch

В смысле?

Re: Текстура в шейдере

СообщениеДобавлено: 02 июн 2020, 22:19
seaman
Raymarchin-ом можно отрисовать любую поверхность, уж круг то элементарно
http://jamie-wong.com/2016/07/15/ray-ma ... functions/
https://medium.com/@shahriyarshahrabi/r ... c72664252a

Вот сложный пример
https://www.shadertoy.com/view/MdX3Rr

Да, и все это рассчитывается во фрагменьном шейдере...

Re: Текстура в шейдере

СообщениеДобавлено: 02 июн 2020, 23:20
Jarico
waruiyume писал(а):потому как текстовая кухня крайне сумбурна и в ней чёрт ногу сломит.


Сделал смену дня и ночи на основе дефолтного процедурного скайбокса (из UnityBuildInShaders)
Есть небо голубое, ночное небо со звёздами, не хватает луны но вот как прилепить луну на внутреннюю половину сферы ума не приложу. Был вариант с наложением поверх звёзд еще одного слоя с кубической прозрачной текстурой и луной но фаз лун очень много и это уж думаю слишком будет занимать видео память ибо нужно ведь постоянно держать текстуры фаз в памяти + я учитываю долготу и широту, дату и время (http://www.stjarnhimlen.se/comp/ppcomp.html). Широта, долгота, дата и время всегда (почти) соответствуют реальным положениям небесных тел и на это идёт расчёт

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

Re: Текстура в шейдере

СообщениеДобавлено: 08 июн 2021, 07:49
iNji555
waruiyume писал(а):При традиционном подходе(пара: вершинный-пиксельный шейдер)- никак(я объясню ниже, что имел в виду). Есть экзотичные геометрические шейдеры- ими можно генерировать геометрию, ваш Кэп. Но они не популярны ввиду своей относительной тормознутости, удачи найти нормальные туторы по ним.
При традиционном подходе, пиксельный шейдер запускается для многих пикселей одновременно, свой пля каждого(в реальности для групп по несколько пикселей, но для нас это ничего не меняет). Ввиду параллельности, каждый пиксель знает только о себе и менять может только себя. По этому именно нарисовать что-то нельзя.
Можно посчитать какой должен быть цвет пикселя с помощью функции, которая принимает позицию(или, допустим, цвет текстуры в этом месте), и возращает цвет исходя из этого. Круг нарисовать будет довольно просто:
если дистанция от текущего пикселя до центра, допустим текстурных координат, чем радиус круга, то ничего не рисуется или пиксель рисуется чёрным.
Попробуйте начать с нодовых редакторов типа "Amplify shader editor", а когда немного разберётесь пробовать текстовые варианты, потому как текстовая кухня крайне сумбурна и в ней чёрт ногу сломит.

Несколько ссылок:
https://en.wikibooks.org/wiki/Cg_Programming //устаревшее, но поможет разобраться в принципах
https://en.wikibooks.org/wiki/GLSL_Programming/Unity //более актуальное, но есть не всё то, что в предыдущем

https://catlikecoding.com/unity/tutorials/rendering //годные уроки, но у автора есть склонность к оверинженерингу

Пример шейдера(материал нужно натянуть на объект у которого есть UV координаты(встроенный куб))
Синтаксис:
Используется glsl
Shader "Unlit/Circle"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.uv);

                float dist = distance(0.5, i.uv);
                col*=step(dist, 0.5);

                return col;
            }
            ENDCG
        }
    }
}
 


Подскажи, пожалуйста, такой момент. Можно этот код поменять так, чтобы рисовало квадрат заданного цвета в заданной координате? И можно ли как-то управлять этим процессом из скриптов юнити?
Цель сделать пиксельный экран заданного разрешения и отрисовывать там из кода разные фигуры попиксельно. Пока реализовал это через управление спрайтом, но оно тормозное (особенно на телефоне), и все говорят используй шейдеры, но никто не говорит как, и нагуглить эту магию тоже не получается. Этот пост и твой код, пока самое близкое что нашел.

Re: Текстура в шейдере

СообщениеДобавлено: 08 июн 2021, 10:15
waruiyume