Как использовать маску из PNG файла, вместо генерируемой?

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

Как использовать маску из PNG файла, вместо генерируемой?

Сообщение iprogrammer 25 дек 2016, 15:01

Есть у меня шейдер, в котором поворачивается прозрачность по часовой стрелке. Делает два полных оборота. При втором плавно "заходит" за основную текстуру. Выглядит это так:

Изображение
Маска прозрачности генерируете непосредственно в коде шейдера. Она (маска) выглядит:
Изображение

Сам код шейдера:
Синтаксис:
Используется csharp
    Shader "Custom/RadialOpacity" {
        Properties {
            [PerRendererData]_MainTex ("MainTex", 2D) = "white" {}
            _Color ("Color", Color) = (1,1,1,1)
            _OpacityRotator ("Opacity Rotator", Range(-360, 360)) = -360 //  2 full circles
            [HideInInspector]_Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
            [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0          
        }
 
        SubShader {
            Tags {
                "IgnoreProjector"="True"
                "Queue"="Transparent"
                "RenderType"="Transparent"
                "CanUseSpriteAtlas"="True"
                "PreviewType"="Plane"
            }
 
            Pass {
                Name "FORWARD"
                Tags {
                    "LightMode"="ForwardBase"
                }
 
                Blend One OneMinusSrcAlpha
                         
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag          
                #pragma multi_compile _ PIXELSNAP_ON
             
                #include "UnityCG.cginc"                    
                #pragma target 3.0
                uniform sampler2D _MainTex;
                uniform float4 _MainTex_ST;
                uniform float4 _Color;
                uniform float _OpacityRotator;          
             
                static const float TAU = float(6.283185); // это 2 * PI
 
                struct VertexInput {
                    float4 vertex : POSITION;                            
                    float2 texcoord0 : TEXCOORD0;
                };
 
                struct VertexOutput {
                    float4 pos : SV_POSITION;
                    float2 uv0 : TEXCOORD0;              
                    float3 normalDir : TEXCOORD2;                              
                };
 
                VertexOutput vert (VertexInput v) {
                    VertexOutput o = (VertexOutput)0;
                    o.uv0 = v.texcoord0;
                    o.pos = mul(UNITY_MATRIX_MVP, v.vertex );
                    #ifdef PIXELSNAP_ON
                        o.pos = UnityPixelSnap(o.pos);
                    #endif
 
                    return o;
                }
 
                float4 frag(VertexOutput i) : COLOR {
                    i.normalDir = normalize(i.normalDir);              
                    float4 _MainTex_var = tex2D(_MainTex,TRANSFORM_TEX(i.uv0, _MainTex));              
                 
                    float2 oStart = (i.uv0 - 0.5);
                    float2 oVector = float2(-1, -1);
                    float oRotatorNormalized = _OpacityRotator / 360.0;
 
                    float oRotator_ang = oRotatorNormalized * -TAU;
                    float oRotator_cos = cos(oRotator_ang);
                    float oRotator_sin = sin(oRotator_ang);              
                    float2x2 oRotationMatrix = float2x2(oRotator_cos, -oRotator_sin, oRotator_sin, oRotator_cos);              
 
                    float2 oRotatorComponent = mul(oVector * oStart, oRotationMatrix);
 
                    /* generating opacity mask BEGIN_SECTION */
                    float2 oMaskHorizOrVert = atan2(oRotatorComponent.g, oRotatorComponent.r);        
                    float oAtan2MaskNormalized = (oMaskHorizOrVert / TAU) + 0.5;              
                    float oAtan2MaskRotatable = oRotatorNormalized - oAtan2MaskNormalized;
                    float oWhiteToBlackMask = ceil(oAtan2MaskRotatable);              
                    /* generating opacity mask END_SECTION */                
 
                    float oFinalMultiply = _MainTex_var.a * max(oAtan2MaskNormalized, ceil(oWhiteToBlackMask));
 
                    /*** (Emissive) ***/              
                    float3 finalColor = _MainTex_var.rgb * _Color.rgb * oFinalMultiply;              
                    return fixed4(finalColor, oFinalMultiply);
                }
 
                ENDCG
            }      
        }
 
        FallBack "Diffuse"  
    }
 


Как можно переделать код так, чтобы вместо генерации маски (в коде выделена как generating opacity mask BEGIN_SECTION) можно было взять маску из текстуры texture2D?
То есть я хочу получить что-то типа такого:

Синтаксис:
Используется csharp
Properties {
        ...
        _OpacityMask ("OpacityMask", 2D) = "white" {}
        ...
    }
 
    ...
 
    float oWhiteToBlackMask = ceil(OpacityMask);
    float oFinalMultiply = _MainTex_var.a * max(oAtan2MaskNormalized, ceil(oWhiteToBlackMask));
 
    ...
 


Но не знаю что где как заменить.
iprogrammer
UNец
 
Сообщения: 41
Зарегистрирован: 25 июн 2016, 07:10

Re: Как использовать маску из PNG файла, вместо генерируемой?

Сообщение kripto289 26 дек 2016, 15:46

Не понимаю что не выходит? Выведите в шейдере так
return max(oAtan2MaskNormalized, ceil(oWhiteToBlackMask));
Повесьте шейдер на quad, сделайте скрин и юзайте получившуюся текстуру в дальнейшем как-то так
MainTex_var.a * tex2D(_OpacityMask, uv).r;
Последний раз редактировалось DbIMok 26 дек 2016, 18:04, всего редактировалось 1 раз.
Причина: убрал оверквоттинг
Аватара пользователя
kripto289
UNIверсал
 
Сообщения: 476
Зарегистрирован: 30 сен 2013, 03:30
Откуда: Екатеринбург
  • Сайт

Re: Как использовать маску из PNG файла, вместо генерируемой?

Сообщение iprogrammer 29 дек 2016, 11:10

kripto289 писал(а):Не понимаю что не выходит? Выведите в шейдере так
return max(oAtan2MaskNormalized, ceil(oWhiteToBlackMask));
Повесьте шейдер на quad, сделайте скрин и юзайте получившуюся текстуру в дальнейшем как-то так
MainTex_var.a * tex2D(_OpacityMask, uv).r;



На просто там маска генерилась из r/g каналов вращающейся компоненты, так сказать.....
А как прилепить текстуру и чтоб она также вращалась, я что-то не соображу. Поэтому просто заменить max(oAtan2MaskNormalized, ceil(oWhiteToBlackMask)); на MainTex_var.a * tex2D(_OpacityMask, uv).r; - это что-то не то.

А даже если каким-либо боком припёком получается что-то с текстурой сделать, чтоб провернулась, то у неё получается странный эффект в конце, как будто она прыгает на батут, отскакивает, а затем, в конце-концов падает...
Изображение

Поэтому даже не знаю что делать и как правильно это переделать.
iprogrammer
UNец
 
Сообщения: 41
Зарегистрирован: 25 июн 2016, 07:10

Re: Как использовать маску из PNG файла, вместо генерируемой?

Сообщение Ert Donuell 29 дек 2016, 18:53

Не просто отскакивает, аки на батуте, а ещё и проходит едва заметно чуть дальше!
Скрытый текст:
Похоже на эффект квантового туннелирования :D
Добавить dmitrii.baranov.yumasoft в Skype
Аватара пользователя
Ert Donuell
Старожил
 
Сообщения: 781
Зарегистрирован: 05 июл 2010, 09:50
Откуда: Санкт-Петербург
  • ICQ

Re: Как использовать маску из PNG файла, вместо генерируемой?

Сообщение iprogrammer 29 дек 2016, 21:40

Ert Donuell писал(а):Не просто отскакивает, аки на батуте, а ещё и проходит едва заметно чуть дальше!
Скрытый текст:
Похоже на эффект квантового туннелирования :D



Это мне не помогло :))
iprogrammer
UNец
 
Сообщения: 41
Зарегистрирован: 25 июн 2016, 07:10

Re: Как использовать маску из PNG файла, вместо генерируемой?

Сообщение jetyb 30 дек 2016, 09:26

математику учите, у вас не код а говно: черт ногу сломит что хотите, а где ошибки
/* generating opacity mask BEGIN_SECTION */
float2 oMaskHorizOrVert = atan2(oRotatorComponent.g, oRotatorComponent.r);
float oAtan2MaskNormalized = (oMaskHorizOrVert / TAU) + 0.5; //арктангенс от [-pi/2 ; +pi/2] => результат от [1/4, 3/4]
float oAtan2MaskRotatable = oRotatorNormalized - oAtan2MaskNormalized;
float oWhiteToBlackMask = ceil(oAtan2MaskRotatable);
/* generating opacity mask END_SECTION */

Вот например аналог, оптимизировать лень - пишу по сути, на деле всю тригонометрию можно заранее предпросчитать скриптом.
Тестировать на [0 - 1] квадрате
Синтаксис:
Используется csharp
                        float _Angle;  //в градусах
                        float _Offset; // defaut: 45
                        fixed4 frag (v2f i) : SV_Target
                        {
                                float s, c;
                                sincos(radians(_Angle), s, c);
                                float2 vAngle = float2(c, s);
                                float2 vFrag = normalize(i.uv - 0.5);

                                s = vFrag.x * vAngle.y - vFrag.y * vAngle.x;
                                c = dot(vAngle, vFrag);

                                float lerpSinStart = sin(radians(_Offset));
                                float t = (s > 0) && (s < lerpSinStart) && (c > 0);
                                t *= 1 - s / lerpSinStart;
                                t *= t; // for better visual interpolation

                                // sample the texture
                                fixed4 col = tex2D(_MainTex, i.uv);                            
                                col.rgb = lerp(col.rgb, fixed3(0, 1, 0), t);
               
                                return col;
                        }
 

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


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

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

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