Как заменить один цветовой канал в текстуре?

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

Как заменить один цветовой канал в текстуре?

Сообщение aigame 18 сен 2019, 14:27

Здравствуйте! Пытаюсь быстро заменить один цветовой канал текстуры на канал от другой с помощью Graphics.DrawTexture(new Rect(0, 0, 1024, 1024), texture, mat); - по идеи должен нарисовать текстурой с помощью материала mat. Пытаюсь написать шейдер материала который рисовал бы только в один канал, к примеру R, остальные бы не трогал. Но чтобы не пробовал получается не корректно, затрагиваются другие каналы.
Пример шейдера:
Синтаксис:
Используется csharp
Shader "Plane/DrawGrab" {
                Properties {
                _MainTex ("RGBA", 2D) = "white" {}

                [Toggle]
                _Channal_R ("Channal R", float) = 1
                [Toggle]
                _Channal_G ("Channal G", float) = 1
                [Toggle]
                _Channal_B ("Channal B", float) = 1
                [Toggle]
                _Channal_A ("Channal A", float) = 1
        }
        SubShader {


                Tags
                {
                        "Queue" = "Transparent"
                        "RenderType" = "Transparent"    
                }
               
                Blend SrcAlpha OneMinusSrcAlpha

                GrabPass { }


                Pass {
                        CGPROGRAM


                        #include "UnityCG.cginc"
                       
                        #pragma vertex ComputeVertex
                        #pragma fragment ComputeFragment
                       
                        sampler2D _MainTex;
                        sampler2D _GrabTexture;

                        half _Channal_R;
                        half _Channal_G;
                        half _Channal_B;
                        half _Channal_A;
                       
            struct VertexInput
                        {
                                float4 vertex : POSITION;
                                float4 color : COLOR;
                                float2 texcoord : TEXCOORD0;
                        };

                        struct VertexOutput
                        {
                                float4 vertex : SV_POSITION;
                                fixed4 color : COLOR;
                                half2 texcoord : TEXCOORD0;
                                float4 screenPos : TEXCOORD1;
                        };
                       
                        VertexOutput ComputeVertex (VertexInput vertexInput)
                        {
                                VertexOutput vertexOutput;
                               
                                vertexOutput.vertex = UnityObjectToClipPos(vertexInput.vertex);
                                vertexOutput.screenPos = vertexOutput.vertex;  
                                vertexOutput.texcoord = vertexInput.texcoord;
                                vertexOutput.color = vertexInput.color;
                                                       
                                return vertexOutput;
                        }


                        fixed4 ComputeFragment (VertexOutput vertexOutput) : SV_Target
                        {
                                half4 a = tex2D(_MainTex, vertexOutput.texcoord);

                                float2 grabTexcoord = vertexOutput.screenPos.xy / vertexOutput.screenPos.w;
                                grabTexcoord.x = (grabTexcoord.x + 1.0) * .5;
                                grabTexcoord.y = (grabTexcoord.y + 1.0) * .5;

                                #if UNITY_UV_STARTS_AT_TOP
                                grabTexcoord.y = 1.0 - grabTexcoord.y;
                                #endif

                                fixed4 b = tex2D(_GrabTexture, grabTexcoord);

                if (_Channal_R != 1) a.r = b.r;
                     
                if (_Channal_G != 1) a.g = b.g;
                         
                if (_Channal_B != 1) a.b = b.b;
                   
                if (_Channal_A != 1) a.a = b.a;

                                return float4(a.r, a.g, a.b, a.a);
                        }
                        ENDCG
                }
               
        }
}
 


Возможно есть другие способы быстрой замены каналов в текстурах, пописельно переписывать текстуру конечно не вариант. Подскажите, помогите.
aigame
UNец
 
Сообщения: 4
Зарегистрирован: 06 янв 2018, 15:03

Re: Как заменить один цветовой канал в текстуре?

Сообщение Woolf 18 сен 2019, 14:55

if (_Channal_R != 1)

эй-эй.. оно же float, так нельзя!

Пробуйте так:
Синтаксис:
Используется csharp
a.r = b.r * _Channal_R;
              a.g = b.g * _Channal_G;
              a.b = b.b * _Channal_B;
              a.a = b.a*  _Channal_A;    


в _Channal_G нолик - канала нет (будет черным), единичка - канал есть
Разработчик Atom Fishing - Рыбалка на поплавок, донку, нахлыст, блесну в постъядерный период.
Разработчик Atom Fishing II - Первая 3D MMO про рыбалку
Аватара пользователя
Woolf
Адепт
 
Сообщения: 6910
Зарегистрирован: 02 мар 2009, 16:59

Re: Как заменить один цветовой канал в текстуре?

Сообщение aigame 18 сен 2019, 17:28

Как раз передавать 0 в канал не нужно, желательно передавать цвет Grab текстуры, прозрачность.
Я переписал эту часть шейдера, так:
Синтаксис:
Используется csharp
a.r = a.r * _Channal_R + b.r * (1 - _Channal_R);
a.g = a.g * _Channal_G + b.g * (1 - _Channal_G);
a.b = a.b * _Channal_B + b.b * (1 - _Channal_B);
a.a = a.a * _Channal_A + b.a * (1 - _Channal_A);
 


Результата идентичный. Такие условия с вещественными прекрасно работают, хоть и нежелательно их использовать в шейдерах.
Возможно я неправильно использую логику Graphics.DrawTexture
aigame
UNец
 
Сообщения: 4
Зарегистрирован: 06 янв 2018, 15:03


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

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

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