GLSL (shadertoy) to HLSL(Unity Shader)

I am trying to convert GLSL from shadertoy to unity HLSL shaderlab. And I have below error messages:

  • Shader error in ‘ShaderMan/matrix3D’: incorrect number of arguments to numeric-type constructor at line 81 (on d3d11)
  • invalid subscript “y” at line 124

Please help what is wrong with my code. Thanks.
The original code from shadertoy(GLSL):

1:
2: Shader “ShaderMan/matrix3D”
3: {
4:
5: Properties{
6: //Properties
7: }
8:
9: SubShader
10: {
11: Tags { “RenderType” = “Transparent” “Queue” = “Transparent” }
12:
13: Pass
14: {
15: ZWrite Off
16:
17: Blend SrcAlpha OneMinusSrcAlpha
18:
19: CGPROGRAM
20: #pragma vertex vert
21: #pragma fragment frag
22: # include “UnityCG.cginc”
23:
24: struct VertexInput
25: {
26: fixed4 vertex : POSITION;
27: fixed2 uv:TEXCOORD0;
28: fixed4 tangent : TANGENT;
29: fixed3 normal : NORMAL;
30: //VertexInput
31: };
32:
33:
34: struct VertexOutput
35: {
36: fixed4 pos : SV_POSITION;
37: fixed2 uv:TEXCOORD0;
38: //VertexOutput
39: };
40:
41: //Variables
42:
43: /*
44: Feel free to do anything you want with this code.
45: This shader uses “runes” code by FabriceNeyret2 (Shader - Shadertoy BETA)
46: which is based on “runes” by otaviogood (Shader - Shadertoy BETA).
47: These random runes look good as matrix symbols and have acceptable performance.
48: /
49:
50: const int ITERATIONS = 40; //use less value if you need more performance
51: const fixed SPEED = 1.;
52:
53: const fixed STRIP_CHARS_MIN = 7.;
54: const fixed STRIP_CHARS_MAX = 40.;
55: const fixed STRIP_CHAR_HEIGHT = 0.15;
56: const fixed STRIP_CHAR_WIDTH = 0.10;
57: static const fixed ZCELL_SIZE = 1. * (STRIP_CHAR_HEIGHT * STRIP_CHARS_MAX); //the multiplier can’t be less than 1.
58: static const fixed XYCELL_SIZE = 12. * STRIP_CHAR_WIDTH; //the multiplier can’t be less than 1.
59:
60: const int BLOCK_SIZE = 10; //in cells
61: const int BLOCK_GAP = 2; //in cells
62:
63: static const fixed WALK_SPEED = 1. * XYCELL_SIZE;
64: const fixed BLOCKS_BEFORE_TURN = 3.;
65:
66:
67: const fixed PI = 3.14159265359;
68:
69:
70: // ---- random ----
71:
72: fixed hash(fixed v) {
73: return frac(sin(v) 43758.5453123);
74: }
75:
76: fixed hash(fixed2 v) {
77: return hash(dot(v, fixed2(5.3983, 5.4427)));
78: }
79:
80: float2 hash2(float2 v)
81: {
82: v = float2(v * float2x2(127.1,311.7,269.5,183.3));
83: return frac(sin(v) * 43758.5453123);
84: }
85:
86: fixed4 hash4(fixed2 v)
87: {
88: fixed4 p = fixed4(v * float4x2(127.1,311.7,
89: 269.5,183.3,
90: 113.5,271.9,
91: 246.1,124.6));
92: return frac(sin(p) * 43758.5453123);
93: }
94:
95: fixed4 hash4(fixed3 v)
96: {
97: fixed4 p = fixed4(v * float4x3(127.1,311.7,74.7,
98: 269.5,183.3,246.1,
99: 113.5,271.9,124.6,
100: 271.9,269.5,311.7));
101: return frac(sin(p) * 43758.5453123);
102: }
103:
104:
105: // ---- symbols ----
106: // Slightly fmodified version of “runes” by FabriceNeyret2 - Shader - Shadertoy BETA
107: // Which is based on “runes” by otaviogood - Shader - Shadertoy BETA
108:
109: fixed rune_line(fixed2 p,fixed2 a,fixed2 b) { // from Shader - Shadertoy BETA
110: p -= a, b -= a;
111: fixed h = clamp(dot(p,b) / dot(b,b),0.,1.); // proj coord on line
112: return length(p - b
h); // dist to segment
113: }
114:
115: fixed rune(fixed2 U,fixed2 seed, fixed highlight)
116: {
117: fixed d = 1e5;
118: for (int i = 0; i< 4; i++) // number of strokes
119: {
120: fixed4 pos = hash4(seed);
121: seed += 1.;
122:
123: // each rune touches the edge of its box on all 4 sides
124: if (i == 0) pos.y = .0;
125: if (i == 1) pos.x = .999;
126: if (i == 2) pos.x = .0;
127: if (i == 3) pos.y = .999;
128: // snap the random line endpoints to a grid 2x3
129: fixed4 snaps = fixed4(2,3,2,3);
130: pos = (floor(pos
snaps) + .5) / snaps;
131:
132: if (pos.xy != pos.zw) //filter out single points (when start and end are the same)
133: d = min(d,rune_line(U, pos.xy, pos.zw + .001) ); // closest line
134: }
135: return smoothstep(0.1, 0.,d) + highlight* smoothstep(0.4, 0.,d);
136: }
137:
138: fixed random_char(fixed2 outer,fixed2 inner, fixed highlight) {
139: fixed2 seed = fixed2(dot(outer,fixed2(269.5,183.3)),dot(outer,fixed2(113.5,271.9)));
140: return rune(inner,seed,highlight);
141: }
142:
143:
144: // ---- digital rain ----
145:
146: // xy - horizontal, z - vertical
147: fixed3 rain(fixed3 ro3,fixed3 rd3, fixed time)
148: {
149: fixed4 result = fixed3(0.,0.,0.,0.);
150:
151: // normalized 2d projection
152: fixed2 ro2 = fixed2(ro3,ro3);
153: fixed2 rd2 = normalize(fixed2(rd3,rd3));
154:
155: // we use formulas ro3 + rd3 * t3 and ro2 + rd2 * t2, t3_to_t2 is a multiplier to convert t3 to t2
156: bool prefer_dx = abs(rd2.x) > abs(rd2.y);
157: fixed t3_to_t2 = prefer_dx ? rd3.x / rd2.x : rd3.y / rd2.y;
158:
159: // at first, horizontal space (xy) is divided into cells (which are columns in 3D)
160: // then each xy-cell is divided into vertical cells (along z) - each of these cells contains one raindrop
161:
162: fixed3 cell_side = fixed3(step(0.,rd3)); //for positive rd.x use cell side with higher x (1) as the next side, for negative - with lower x (0), the same for y and z
163: fixed3 cell_shift = fixed3(sign(rd3)); //shift to move to the next cell
164:
165: // move through xy-cells in the ray direction
166: fixed t2 = 0.; // the ray formula is: ro2 + rd2 * t2, where t2 is positive as the ray has a direction.
167: fixed2 next_cell = fixed2(floor(ro2 / XYCELL_SIZE)); //first cell index where ray origin is located
168: for(int i = 0;i < ITERATIONS;i++)
169: {
170: fixed2 cell = next_cell; //save cell value before changing
171: fixed t2s = t2; //and t
172:
173: // find the intersection with the nearest side of the current xy-cell (since we know the direction, we only need to check one vertical side and one horizontal side)
174: fixed2 side = fixed2(next_cell + cell_side.xy,next_cell + cell_side.xy) * XYCELL_SIZE; //side.x is x coord of the y-axis side, side.y - y of the x-axis side
175: fixed2 t2_side = (side - ro2) / rd2; // t2_side.x and t2_side.y are two candidates for the next value of t2, we need the nearest
176: if(t2_side.x < t2_side.y)
177: {
178: t2 = t2_side.x;
179: next_cell.x += cell_shift.x; //cross through the y-axis side
180: }
181: else
182: {
183: t2 = t2_side.y;
184: next_cell.y += cell_shift.y; //cross through the x-axis side
185: }
186: //now t2 is the value of the end point in the current cell (and the same point is the start value in the next cell)
187:
188: // gap cells
189: fixed2 cell_in_block = frac(fixed2(cell,cell) / fixed (BLOCK_SIZE));
190: fixed gap = fixed (BLOCK_GAP) / fixed (BLOCK_SIZE)
191: ;
192: if(cell_in_block.x < gap || cell_in_block.y < gap || (cell_in_block.x < (gap + 0.1) && cell_in_block.y < (gap + 0.1)))
193: {
194: continue;
195: }
196:
197: // return to 3d - we have start and end points of the ray segment inside the column (t3s and t3e)
198: fixed t3s = t2s / t3_to_t2;
199:
200: // move through z-cells of the current column in the ray direction (don’t need much to check, two nearest cells are enough)
201: fixed pos_z = ro3.z + rd3.z * t3s;
202: fixed xycell_hash = hash(fixed2(cell,cell));
203: fixed z_shift = xycell_hash * 11. - time * (0.5 + xycell_hash * 1.0 + xycell_hash * xycell_hash * 1.0 + pow(xycell_hash,16.) * 3.0); //a different z shift for each xy column
204: fixed char_z_shift = floor(z_shift / STRIP_CHAR_HEIGHT);
205: z_shift = char_z_shift * STRIP_CHAR_HEIGHT;
206: int zcell = int(floor((pos_z - z_shift) / ZCELL_SIZE)); //z-cell index
207: for(int j = 0;j < 2;j++)
208: { //2 iterations is enough if camera doesn’t look much up or down
209: // calcaulate coordinates of the target (raindrop)
210: fixed4 cell_hash = hash4(fixed3(fixed3(cell,zcell)));
211: fixed4 cell_hash2 = frac(cell_hash * fixed4(127.1,311.7,271.9,124.6));
212:
213: fixed chars_count = cell_hash.w * (STRIP_CHARS_MAX - STRIP_CHARS_MIN) + STRIP_CHARS_MIN;
214: fixed target_length = chars_count * STRIP_CHAR_HEIGHT;
215: fixed target_rad = STRIP_CHAR_WIDTH / 2.;
216: fixed target_z = (fixed (zcell)
217: ZCELL_SIZE + z_shift) +cell_hash.z * (ZCELL_SIZE - target_length);
218: fixed2 target = fixed2(cell,cell) * XYCELL_SIZE + target_rad + cell_hash.xy * (XYCELL_SIZE - target_rad * 2.);
219:
220: // We have a line segment (t0,t). Now calculate the distance between line segment and cell target (it’s easier in 2d)
221: fixed2 s = target - ro2;
222: fixed tmin = dot(s,rd2); //tmin - point with minimal distance to target
223: if(tmin >= t2s && tmin <= t2)
224: {
225: fixed u = s.x * rd2.y - s.y * rd2.x; //horizontal coord in the matrix strip
226: if(abs(u) < target_rad)
227: {
228: u = (u / target_rad + 1.) / 2.;
229: fixed z = ro3.z + rd3.z * tmin / t3_to_t2;
230: fixed v = (z - target_z) / target_length; //vertical coord in the matrix strip
231: if(v >= 0.0 && v < 1.0)
232: {
233: fixed c = floor(v * chars_count); //symbol index relative to the start of the strip, with addition of char_z_shift it becomes an index relative to the whole cell
234: fixed q = frac(v * chars_count);
235: fixed2 char_hash = hash2(fixed2(c + char_z_shift,cell_hash2.x));
236: if(char_hash.x >= 0.1 || c == 0.)
237: { //10% of missed symbols
238: fixed time_factor = floor(c == 0. ? time * 5.0 : //first symbol is changed fast
239: time * (1.0 * cell_hash2.z + //strips are changed sometime with different speed
240: cell_hash2.w * cell_hash2.w * 4.
pow(char_hash.y,4.))); //some symbols in some strips are changed relatively often
241: fixed a = random_char(fixed2(char_hash.x,time_factor),fixed2(u,q),max(1.,3. - c / 2.) * 0.2); //alpha
242: a = clamp((chars_count - 0.5 - c) / 2.,0.,1.); //tail fade
243: if(a > 0.)
244: {
245: fixed attenuation = 1. + pow(0.06 * tmin / t3_to_t2,2.);
246: fixed3 col = (c == 0. ? fixed3(0.67,1.0,0.82) : fixed3(0.25,0.80,0.40)) / attenuation;
247: fixed a1 = result.a;
248: result.a = a1 + (1. - a1) * a;
249: result.xyz = (result.xyz * a1 + col * (1. - a1) * a) / result.a;
250: if(result.a > 0.98)
251: return result.xyz;
252: }
253: }
254: }
255: }
256: }
257: // not found in this cell - go to next vertical cell
258: zcell += cell_shift.z;
259: }
260: // go to next horizontal cell
261: }
262:
263: return result.xyz
result.a;
264: }
265:
266:
267: // ---- main, camera ----
268:
269: fixed2 rotate(fixed2 v, fixed a)
270: {
271: fixed s = sin(a);
272: fixed c = cos(a);
273: fixed2x2 m = fixed2x2(c,-s,s,c);
274: return m * v;
275: }
276:
277: fixed3 rotateX(fixed3 v, fixed a)
278: {
279: fixed s = sin(a);
280: fixed c = cos(a);
281: return fixed3x3(1.,0.,0.,0.,c,-s,0.,s,c) * v;
282: }
283:
284: fixed3 rotateY(fixed3 v, fixed a)
285: {
286: fixed s = sin(a);
287: fixed c = cos(a);
288: return fixed3x3(c,0.,-s,0.,1.,0.,s,0.,c) * v;
289: }
290:
291: fixed3 rotateZ(fixed3 v, fixed a)
292: {
293: fixed s = sin(a);
294: fixed c = cos(a);
295: return fixed3x3(c,-s,0.,s,c,0.,0.,0.,1.) * v;
296: }
297:
298: fixed smoothstep1(fixed x) {
299: return smoothstep(0., 1.,x);
300: }
301:
302:
303:
304:
305:
306: VertexOutput vert(VertexInput v)
307: {
308: VertexOutput o;
309: o.pos = UnityObjectToClipPos(v.vertex);
310: o.uv = v.uv;
311: //VertexFactory
312: return o;
313: }
314: fixed4 frag(VertexOutput i) : SV_Target
315: {
316:
317: if (STRIP_CHAR_WIDTH > XYCELL_SIZE || STRIP_CHAR_HEIGHT* STRIP_CHARS_MAX > ZCELL_SIZE) {
318: // error
319: return fixed4(1., 0., 0., 1.);
320: return;
321:
322: }
323: ENDCG
324: }
325: }
326: }
327:

Use the

[code]

tag please.

Make material from following shader and just add to quad or plane.

Translated by P.Z.

Shader "InsideTheMatrix"
{
    SubShader
    {
        Pass
        {
            CGPROGRAM
            #pragma exclude_renderers gles
            #pragma vertex SetVertexShader
            #pragma fragment SetPixelShader
                  
            static const int ITERATIONS = 40;
            static const float SPEED = 1.;
            static const float STRIP_CHARS_MIN =  7.;
            static const float STRIP_CHARS_MAX = 40.;
            static const float STRIP_CHAR_HEIGHT = 0.15;
            static const float STRIP_CHAR_WIDTH = 0.10;
            static const float ZCELL_SIZE = 1. * (STRIP_CHAR_HEIGHT * STRIP_CHARS_MAX);
            static const float XYCELL_SIZE = 12. * STRIP_CHAR_WIDTH;
            static const int BLOCK_SIZE = 10;
            static const int BLOCK_GAP = 2;
            static const float WALK_SPEED = 1. * XYCELL_SIZE;
            static const float BLOCKS_BEFORE_TURN = 3.;
            static const float PI = 3.14159265359;
          
            float hash(float v)
            {
                return frac(sin(v)*43758.5453123);
            }

            float hash(float2 v)
            {
                return hash(dot(v, float2(5.3983, 5.4427)));
            }

            float2 hash2(float2 v)
            {
                v = float2(mul(float2x2(127.1, 311.7,  269.5, 183.3),v));
                return frac(sin(v)*43758.5453123);
            }

            float4 hash4(float2 v)
            {
                float4 p = float4(mul(float4x2( 127.1, 311.7,269.5, 183.3,113.5, 271.9,246.1, 124.6 ),v));
                return frac(sin(p)*43758.5453123);
            }

            float4 hash4(float3 v)
            {
                float4 p = float4(mul(float4x3( 127.1, 311.7, 74.7,269.5, 183.3, 246.1,113.5, 271.9, 124.6,271.9, 269.5, 311.7 ),v) );
                return frac(sin(p)*43758.5453123);
            }

            float rune_line(float2 p, float2 a, float2 b)
            {
                p -= a, b -= a;
                float h = clamp(dot(p, b) / dot(b, b), 0., 1.);
                return length(p - b * h);
            }

            float rune(float2 U, float2 seed, float highlight)
            {
                float d = 1e5;
                for (int i = 0; i < 4; i++)
                {
                    float4 pos = hash4(seed);
                    seed += 1.;
                    if (i == 0) pos.y = .0;
                    if (i == 1) pos.x = .999;
                    if (i == 2) pos.x = .0;
                    if (i == 3) pos.y = .999;
                    float4 snaps = float4(2., 3., 2., 3.);
                    pos = ( floor(pos * snaps) + .5) / snaps;
                    if (pos.x != pos.z && pos.y!=pos.w)
                        d = min(d, rune_line(U, pos.xy, pos.zw + .001) );
                }
                return smoothstep(0.1, 0., d) + highlight*smoothstep(0.4, 0., d);
            }

            float random_char(float2 outer, float2 inner, float highlight)
            {
                float2 seed = float2(dot(outer, float2(269.5, 183.3)), dot(outer, float2(113.5, 271.9)));
                return rune(inner, seed, highlight);
            }   

            float3 rain(float3 ro3, float3 rd3, float time)
            {
                float4 result = float4(0,0,0,0);
                float2 ro2 = float2(ro3.xy);
                float2 rd2 = normalize(float2(rd3.xy));
                bool prefer_dx = abs(rd2.x) > abs(rd2.y);
                float t3_to_t2 = prefer_dx ? rd3.x / rd2.x : rd3.y / rd2.y;
                int3 cell_side = int3(step(0., rd3));
                int3 cell_shift = int3(sign(rd3));
                float t2 = 0.;
                int2 next_cell = int2(floor(ro2/XYCELL_SIZE));
                for (int i=0; i<ITERATIONS; i++)
                {
                    int2 cell = next_cell;
                    float t2s = t2;
                    float2 side = float2(next_cell + cell_side.xy) * XYCELL_SIZE;
                    float2 t2_side = (side - ro2) / rd2;
                    if (t2_side.x < t2_side.y)
                    {
                        t2 = t2_side.x;
                        next_cell.x += cell_shift.x;
                    }
                    else
                    {
                        t2 = t2_side.y;
                        next_cell.y += cell_shift.y;
                    }
                    float2 cell_in_block = frac(float2(cell) / float(BLOCK_SIZE));
                    float gap = float(BLOCK_GAP) / float(BLOCK_SIZE);
                    if (cell_in_block.x < gap || cell_in_block.y < gap || (cell_in_block.x < (gap+0.1) && cell_in_block.y < (gap+0.1))) {
                        continue;
                    }
                    float t3s = t2s / t3_to_t2;
                    float pos_z = ro3.z + rd3.z * t3s;
                    float xycell_hash = hash(float2(cell));
                    float z_shift = xycell_hash*11. - time * (0.5 + xycell_hash * 1.0 + xycell_hash * xycell_hash * 1.0 + pow(xycell_hash, 16.) * 3.0);  //a different z shift for each xy column
                    float char_z_shift = floor(z_shift / STRIP_CHAR_HEIGHT);
                    z_shift = char_z_shift * STRIP_CHAR_HEIGHT;
                    int zcell = int(floor((pos_z - z_shift)/ZCELL_SIZE));
                    for (int j=0; j<2; j++)
                    {
                        float4 cell_hash = hash4(float3(int3(cell, zcell)));
                        float4 cell_hash2 = frac(cell_hash * float4(127.1, 311.7, 271.9, 124.6));
                        float chars_count = cell_hash.w * (STRIP_CHARS_MAX - STRIP_CHARS_MIN) + STRIP_CHARS_MIN;
                        float target_length = chars_count * STRIP_CHAR_HEIGHT;
                        float target_rad = STRIP_CHAR_WIDTH / 2.;
                        float target_z = (float(zcell)*ZCELL_SIZE + z_shift) + cell_hash.z * (ZCELL_SIZE - target_length);
                        float2 target = float2(cell) * XYCELL_SIZE + target_rad + cell_hash.xy * (XYCELL_SIZE - target_rad*2.);
                        float2 s = target - ro2;
                        float tmin = dot(s, rd2);
                        if (tmin >= t2s && tmin <= t2)
                        {
                            float u = s.x * rd2.y - s.y * rd2.x;
                            if (abs(u) < target_rad)
                            {
                                u = (u/target_rad + 1.) / 2.;
                                float z = ro3.z + rd3.z * tmin/t3_to_t2;
                                float v = (z - target_z) / target_length;
                                if (v >= 0.0 && v < 1.0)
                                {
                                    float c = floor(v * chars_count); 
                                    float q = frac(v * chars_count);
                                    float2 char_hash = hash2(float2(c+char_z_shift, cell_hash2.x));
                                    if (char_hash.x >= 0.1 || c == 0.)
                                    {
                                        float time_factor = floor(c == 0. ? time*5.0 : time*(1.0*cell_hash2.z +  cell_hash2.w*cell_hash2.w*4.*pow(char_hash.y, 4.)));
                                        float a = random_char(float2(char_hash.x, time_factor), float2(u,q), max(1., 3. - c/2.)*0.2);
                                        a *= clamp((chars_count - 0.5 - c) / 2., 0., 1.);
                                        if (a > 0.)
                                        {
                                            float attenuation = 1. + pow(0.06*tmin/t3_to_t2, 2.);
                                            float3 col = (c == 0. ? float3(0.67, 1.0, 0.82) : float3(0.25, 0.80, 0.40)) / attenuation;
                                            float a1 = result.a;
                                            result.a = a1 + (1. - a1) * a;
                                            result.xyz = (result.xyz * a1 + col * (1. - a1) * a) / result.a;
                                            if (result.a > 0.98)  return result.xyz;
                                        }
                                    }
                                }
                            }
                        }
                        zcell += cell_shift.z;
                    }
                }
                return result.xyz * result.a;
            }

            float2 rotate(float2 v, float a)
            {
                float s = sin(a);
                float c = cos(a);
                float2x2 m = float2x2(c, -s, s, c);
                return mul(v,m);
            }

            float3 rotateX(float3 v, float a)
            {
                float s = sin(a);
                float c = cos(a);
                return mul(v,float3x3(1.,0.,0.,0.,c,-s,0.,s,c));
            }

            float3 rotateY(float3 v, float a)
            {
                float s = sin(a);
                float c = cos(a);
                return mul(v,float3x3(c,0.,-s,0.,1.,0.,s,0.,c));
            }

            float3 rotateZ(float3 v, float a)
            {
                float s = sin(a);
                float c = cos(a);
                return mul(v,float3x3(c,-s,0.,s,c,0.,0.,0.,1.));
            }

            float smoothstep1(float x)
            {
                return smoothstep(0., 1., x);
            }

      
            void SetVertexShader (inout float4 vertex:POSITION,inout float2 uv:TEXCOORD0)
            {
                vertex = UnityObjectToClipPos(vertex);
            }
          
            void SetPixelShader (float4 vertex:POSITION,float2 uv:TEXCOORD0, out float4 fragColor: SV_TARGET)
            {
                if (STRIP_CHAR_WIDTH > XYCELL_SIZE || STRIP_CHAR_HEIGHT * STRIP_CHARS_MAX > ZCELL_SIZE)
                {
                    fragColor = float4(1., 0., 0., 1.);
                    return;
                }
                uv = float2(2.0*uv.xy-1.0);
                float time = _Time.g * SPEED;
                const float turn_rad = 0.25 / BLOCKS_BEFORE_TURN;
                const float turn_abs_time = (PI/2.*turn_rad) * 1.5;
                const float turn_time = turn_abs_time / (1. - 2.*turn_rad + turn_abs_time);
                float level1_size = float(BLOCK_SIZE) * BLOCKS_BEFORE_TURN * XYCELL_SIZE;
                float level2_size = 4. * level1_size;
                float gap_size = float(BLOCK_GAP) * XYCELL_SIZE;
                float3 ro = float3(gap_size/2., gap_size/2., 0.);
                float3 rd = float3(uv.x, 2.0, uv.y);
                float tq = frac(time / (level2_size*4.) * WALK_SPEED);
                float t8 = frac(tq*4.);
                float t1 = frac(t8*8.);
                float2 prev;
                float2 dir;
                if (tq < 0.25)
                {
                    prev = float2(0.,0.);
                    dir = float2(0.,1.);
                }
                else if (tq < 0.5)
                {
                    prev = float2(0.,1.);
                    dir = float2(1.,0.);
                }
                else if (tq < 0.75)
                {
                    prev = float2(1.,1.);
                    dir = float2(0.,-1.);
                }
                else
                {
                    prev = float2(1.,0.);
                    dir = float2(-1.,0.);
                }
                float angle = floor(tq * 4.);
                prev *= 4.;
                const float first_turn_look_angle = 0.4;
                const float second_turn_drift_angle = 0.5;
                const float fifth_turn_drift_angle = 0.25;
                float2 turn;
                float turn_sign = 0.;
                float2 dirL = rotate(dir, -PI/2.);
                float2 dirR = -dirL;
                float up_down = 0.;
                float rotate_on_turns = 1.;
                float roll_on_turns = 1.;
                float add_angel = 0.;
                if (t8 < 0.125)
                {
                    turn = dirL;
                    turn_sign = -1.;
                    angle -= first_turn_look_angle*(max(0.,t1-(1.-turn_time*2.))/turn_time - max(0., t1-(1. - turn_time)) / turn_time * 2.5);
                    roll_on_turns = 0.;
                }
                else if (t8 < 0.250)
                {
                    prev += dir;
                    turn = dir;
                    dir = dirL;
                    angle -= 1.;
                    turn_sign = 1.;
                    add_angel += first_turn_look_angle*0.5 + (-first_turn_look_angle*0.5+1.0+second_turn_drift_angle)*t1;
                    rotate_on_turns = 0.;
                    roll_on_turns = 0.;
                }
                else if (t8 < 0.375)
                {
                    prev += dir + dirL;
                    turn = dirR;
                    turn_sign = 1.;
                    add_angel += second_turn_drift_angle*sqrt(1.-t1);
                }
                else if (t8 < 0.5)
                {
                    prev += dir + dir + dirL;
                    turn = dirR;
                    dir = dirR;
                    angle += 1.;
                    turn_sign = 0.;
                    up_down = sin(t1*PI) * 0.37;
                }
                else if (t8 < 0.625)
                {
                    prev += dir + dir;
                    turn = dir;
                    dir = dirR;
                    angle += 1.;
                    turn_sign = -1.;
                    up_down = sin(-min(1., t1/(1.-turn_time))*PI) * 0.37;
                }
                else if (t8 < 0.750)
                {
                    prev += dir + dir + dirR;
                    turn = dirL;
                    turn_sign = -1.;
                    add_angel -= (fifth_turn_drift_angle + 1.) * smoothstep1(t1);
                    rotate_on_turns = 0.;
                    roll_on_turns = 0.;
                }
                else if (t8 < 0.875)
                {
                    prev += dir + dir + dir + dirR;
                    turn = dir;
                    dir = dirL;
                    angle -= 1.;
                    turn_sign = 1.;
                    add_angel -= fifth_turn_drift_angle - smoothstep1(t1) * (fifth_turn_drift_angle * 2. + 1.);
                    rotate_on_turns = 0.;
                    roll_on_turns = 0.;
                }
                else
                {
                    prev += dir + dir + dir;
                    turn = dirR;
                    turn_sign = 1.;
                    angle += fifth_turn_drift_angle*(1.5*min(1.,(1.-t1)/turn_time)-0.5*smoothstep1(1.-min(1.,t1/(1.-turn_time))));
                }
                angle += add_angel;
                rd = rotateX(rd, up_down);
                float2 p;
                if (turn_sign == 0.)
                {
                    p = prev + dir * (turn_rad + 1. * t1);
                }
                else if (t1 > (1. - turn_time))
                {
                    float tr = (t1 - (1. - turn_time)) / turn_time;
                    float2 c = prev + dir * (1. - turn_rad) + turn * turn_rad;
                    p = c + turn_rad * rotate(dir, (tr - 1.) * turn_sign * PI/2.);
                    angle += tr * turn_sign * rotate_on_turns;
                    rd = rotateY(rd, sin(tr*turn_sign*PI) * 0.2 * roll_on_turns);
                }
                else
                {
                    t1 /= (1. - turn_time);
                    p = prev + dir * (turn_rad + (1. - turn_rad*2.) * t1);
                }
                rd = rotateZ(rd, angle * PI/2.);
                ro.xy += level1_size * p;
                ro += rd * 0.2;
                rd = normalize(rd);
                float3 col = rain(ro, rd, time);
                fragColor = float4(col, 1.);
            }
            ENDCG
        }
    }
}
1 Like

OMG!!! Thank you sooooo much. It works. You are genius!!!