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

Возможно ли через vertex и fragment ш-ры Градиент сделать?

СообщениеДобавлено: 06 май 2018, 14:30
Roman777
Добрый всем день!
Интересует возможность с помощью вертексного или фрагментарного шейдера сделать Градиент.
Дело в том, что хочу сделать градиент на объекте, имеющем MeshTopology.LineStrip (тобишь, представляет собой линию).
Y меня объект имеет всего 2 вертекса и представляет собой отрезок. Хочу задать направление градиентом. Думал, что во фрагментарном шейдере смогу найти позицию 1 вертекса относительно другого и таким образом задать градиенту. Но не нашёл таких возможностей.
Знаю, что есть другие способы рисования линий, но пока этот способ для меня был бы наиболее приемлемым (была бы возможность градиенту задать...).

Re: Возможно ли через vertex и fragment ш-ры Градиент сделать?

СообщениеДобавлено: 06 май 2018, 19:34
DbIMok
зачем искать во фрагментном? почему не задать цвет вертексам и использовать его во фрагментном? не знаю как в линиях, но в треугольниках градиент получается автоматически

Re: Возможно ли через vertex и fragment ш-ры Градиент сделать?

СообщениеДобавлено: 07 май 2018, 12:29
snezhok_13
Да, возможно. И в линиях будет работать.

Re: Возможно ли через vertex и fragment ш-ры Градиент сделать?

СообщениеДобавлено: 09 май 2018, 18:39
Roman777
Благодарю за рекомендации)
Сделал шейдер так:
Синтаксис:
Используется csharp
Shader "LineGradient2" {
        Properties {
                _Color1 ("Color1", Color) = (1,1,1,1)
                _Color2 ("Color2", Color) = (1,1,1,1)
                _Magnitude ("Leght", Range(0,10000)) = 0
                _Pos1 ("Pos1", Vector) = (0,0,0,0)
                _Manipule("Value", Range(0,1)) = 0.5
        }
        SubShader {
                Tags { "RenderType"="Opaque" }
                LOD 200
               
               
                Pass{
                        CGPROGRAM
                    #pragma vertex vert
                    #pragma fragment frag

                        fixed4 _Color1;
                        fixed4 _Color2;
                        float _Magnitude;
                        float3 _Pos1;
                        float _Manipule;
                        struct v2f{
                                float4 intensity : COLOR0;
                                float4 vertex : SV_POSITION;
                        };
                        struct appdata{
                                float4 vertex : POSITION;
                        };
                       
                       
                        inline float4 UnityObjectToClipPos( in float3 pos ){
                                #if defined(UNITY_SINGLE_PASS_STEREO) || defined(UNITY_USE_CONCATENATED_MATRICES)
                                        return mul(UNITY_MATRIX_VP, mul(unity_ObjectToWorld, float4(pos, 1.0)));
                                #else
                                return mul(UNITY_MATRIX_MVP, float4(pos, 1.0));
                                #endif
                        }
                       
                        v2f vert (appdata v)
                        {
                                v2f o;
                                o.vertex = UnityObjectToClipPos(v.vertex);
                                o.intensity = lerp(_Color1, _Color2, pow(2*length(v.vertex-_Pos1)/_Magnitude*_Manipule,2-2*_Manipule));
                                return o;
                        }

                        fixed4 frag (v2f i) : SV_Target{
                                return i.intensity;
                        }
                        ENDCG
                }
        }
        FallBack "Diffuse"
}

При этом создаю объект так:
Синтаксис:
Используется csharp
using UnityEngine;
using System.Collections;

public class ActionLines {

        public static GameObject DrawLine(Vector3 pos1, Vector3 pos2, Color col){
                Vector3[] verts = new Vector3[]{pos1, pos2};
                int[] indicesForLineStrip = new int[]{0,1};
                Mesh meshline = new Mesh();
                meshline.vertices = verts;
                meshline.SetIndices(indicesForLineStrip, MeshTopology.LineStrip, 0);
                meshline.RecalculateBounds();
                GameObject line = new GameObject();
                line.AddComponent<MeshFilter>();
                line.AddComponent<MeshRenderer>();
                MeshFilter mf = line.GetComponent<MeshFilter>();
                Material pMat = new Material(Shader.Find ("LineGradient2"));
//              pMat.SetVector("_Rang", pos1);
                pMat.SetColor("_Color1", new Color(0,0,0));
                pMat.SetColor("_Color2",col);
                pMat.SetVector("_Pos1", pos1);
                pMat.SetFloat("_Magnitude", (pos1-pos2).magnitude);
                line.GetComponent<MeshRenderer>().material=pMat;
                //              mesh.RecalculateNormals();
                mf.mesh = meshline;
                return line;
        }
}

Единственное, что не устраивает:
1) При таком подходе в случае динамического изменения длины (и координаты) , нужно будет каждый раз обновлять значения _Pos1 и _Magnitude. (Возможно ли в коде шейдера напрямую получить координату именно первого и второго вертексов, без передачи этих значений из кода CPU?)
2) Немного не нравится, что ф-я смещения градиенты степенная, нелинейная (pow(2*length(v.vertex-_Pos1)/_Magnitude*_Manipule,2-2*_Manipule))
... но что-то до линейного выражения думка моя не додумала ещё... мб кто подскажет... а мб потом ещё подумаю...)