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

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

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

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

Сам код шейдера:
Синтаксис:
Используется 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));
 
    ...
 


Но не знаю что где как заменить.

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

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

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

СообщениеДобавлено: 29 дек 2016, 11:10
iprogrammer
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; - это что-то не то.

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

Поэтому даже не знаю что делать и как правильно это переделать.

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

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

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

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



Это мне не помогло :))

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

СообщениеДобавлено: 30 дек 2016, 09:26
jetyb
математику учите, у вас не код а говно: черт ногу сломит что хотите, а где ошибки
/* 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 - поворачивается (а ля как у вас умножением на матрицу поворота) и затем от результата берется текст ура в маске.