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: