hyperstellar 1.5.6__py3-none-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hyperstellar/__init__.py +299 -0
- hyperstellar/__init__.pyi +1019 -0
- hyperstellar/_native/linux-x64/shaders/axis.frag +8 -0
- hyperstellar/_native/linux-x64/shaders/axis.vert +13 -0
- hyperstellar/_native/linux-x64/shaders/fragShader.frag +27 -0
- hyperstellar/_native/linux-x64/shaders/geoShader.geom +69 -0
- hyperstellar/_native/linux-x64/shaders/math.comp +2177 -0
- hyperstellar/_native/linux-x64/shaders/paint.comp +1214 -0
- hyperstellar/_native/linux-x64/shaders/quad.frag +26 -0
- hyperstellar/_native/linux-x64/shaders/quad.geom +149 -0
- hyperstellar/_native/linux-x64/shaders/quad.vert +39 -0
- hyperstellar/_native/linux-x64/shaders/vertexShader.vert +13 -0
- hyperstellar/_native/linux-x64/stellar.so +0 -0
- hyperstellar/_native/windows-x64/shaders/axis.frag +8 -0
- hyperstellar/_native/windows-x64/shaders/axis.vert +13 -0
- hyperstellar/_native/windows-x64/shaders/fragShader.frag +27 -0
- hyperstellar/_native/windows-x64/shaders/geoShader.geom +69 -0
- hyperstellar/_native/windows-x64/shaders/math.comp +2177 -0
- hyperstellar/_native/windows-x64/shaders/paint.comp +1214 -0
- hyperstellar/_native/windows-x64/shaders/quad.frag +26 -0
- hyperstellar/_native/windows-x64/shaders/quad.geom +149 -0
- hyperstellar/_native/windows-x64/shaders/quad.vert +39 -0
- hyperstellar/_native/windows-x64/shaders/vertexShader.vert +13 -0
- hyperstellar/_native/windows-x64/stellar.pyd +0 -0
- hyperstellar/debug.py +169 -0
- hyperstellar/jit.py +2010 -0
- hyperstellar/jit_linter.py +3 -0
- hyperstellar/py.typed +0 -0
- hyperstellar/shader.py +1356 -0
- hyperstellar/typed.py +152 -0
- hyperstellar-1.5.6.dist-info/METADATA +470 -0
- hyperstellar-1.5.6.dist-info/RECORD +35 -0
- hyperstellar-1.5.6.dist-info/WHEEL +5 -0
- hyperstellar-1.5.6.dist-info/licenses/LICENSE +24 -0
- hyperstellar-1.5.6.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,1214 @@
|
|
|
1
|
+
#version 430 core
|
|
2
|
+
layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
|
|
3
|
+
|
|
4
|
+
// ----------------------------------------------------------------------------
|
|
5
|
+
// DATA STRUCTURES (same as math.comp)
|
|
6
|
+
// ----------------------------------------------------------------------------
|
|
7
|
+
struct Object {
|
|
8
|
+
vec2 position;
|
|
9
|
+
vec2 velocity;
|
|
10
|
+
float mass;
|
|
11
|
+
float charge;
|
|
12
|
+
int visualSkinType;
|
|
13
|
+
int collisionShapeType;
|
|
14
|
+
vec4 visualData;
|
|
15
|
+
vec4 collisionData;
|
|
16
|
+
vec4 color;
|
|
17
|
+
int equationID;
|
|
18
|
+
int scriptID;
|
|
19
|
+
int _pad[2];
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
// ----------------------------------------------------------------------------
|
|
23
|
+
// BUFFERS (binding 0 = object SSBO, 2 = tokens, 3 = constants)
|
|
24
|
+
// ----------------------------------------------------------------------------
|
|
25
|
+
layout(std430, binding = 0) readonly buffer ObjectsIn { Object objectsIn[]; };
|
|
26
|
+
layout(std430, binding = 2) readonly buffer PaintTokens { int allTokens[]; };
|
|
27
|
+
layout(std430, binding = 3) readonly buffer PaintConstants { float allConstants[]; };
|
|
28
|
+
|
|
29
|
+
// ----------------------------------------------------------------------------
|
|
30
|
+
// TEXTURES (double‑buffered)
|
|
31
|
+
// ----------------------------------------------------------------------------
|
|
32
|
+
uniform sampler2D uPrevFrame;
|
|
33
|
+
layout(rgba8, binding = 0) writeonly uniform image2D uPaintTarget;
|
|
34
|
+
|
|
35
|
+
// ----------------------------------------------------------------------------
|
|
36
|
+
// UNIFORMS
|
|
37
|
+
// ----------------------------------------------------------------------------
|
|
38
|
+
uniform int uNumObjects;
|
|
39
|
+
uniform float uTime;
|
|
40
|
+
uniform float uCameraX;
|
|
41
|
+
uniform float uCameraY;
|
|
42
|
+
uniform float uHalfWidth;
|
|
43
|
+
uniform float uHalfHeight;
|
|
44
|
+
uniform int uScreenWidth;
|
|
45
|
+
uniform int uScreenHeight;
|
|
46
|
+
uniform int uTexWidth;
|
|
47
|
+
uniform int uTexHeight;
|
|
48
|
+
|
|
49
|
+
uniform int uTokenOffset_r; uniform int uTokenCount_r; uniform int uConstOffset_r;
|
|
50
|
+
uniform int uTokenOffset_g; uniform int uTokenCount_g; uniform int uConstOffset_g;
|
|
51
|
+
uniform int uTokenOffset_b; uniform int uTokenCount_b; uniform int uConstOffset_b;
|
|
52
|
+
uniform int uTokenOffset_a; uniform int uTokenCount_a; uniform int uConstOffset_a;
|
|
53
|
+
|
|
54
|
+
// ----------------------------------------------------------------------------
|
|
55
|
+
// TOKEN CODES (must match parser/gpu_serializer)
|
|
56
|
+
// ----------------------------------------------------------------------------
|
|
57
|
+
const int TOKEN_NUMBER = 0;
|
|
58
|
+
const int TOKEN_VARIABLE = 1;
|
|
59
|
+
const int TOKEN_OBJECT_REF = 2;
|
|
60
|
+
const int TOKEN_ADD = 3;
|
|
61
|
+
const int TOKEN_SUB = 4;
|
|
62
|
+
const int TOKEN_MUL = 5;
|
|
63
|
+
const int TOKEN_DIV = 6;
|
|
64
|
+
const int TOKEN_NEG = 7;
|
|
65
|
+
const int TOKEN_POW = 8;
|
|
66
|
+
const int TOKEN_SIN = 9;
|
|
67
|
+
const int TOKEN_COS = 10;
|
|
68
|
+
const int TOKEN_TAN = 11;
|
|
69
|
+
const int TOKEN_SQRT = 12;
|
|
70
|
+
const int TOKEN_LOG = 13;
|
|
71
|
+
const int TOKEN_EXP = 14;
|
|
72
|
+
const int TOKEN_ABS = 15;
|
|
73
|
+
const int TOKEN_MIN = 16;
|
|
74
|
+
const int TOKEN_MAX = 17;
|
|
75
|
+
const int TOKEN_CLAMP = 18;
|
|
76
|
+
const int TOKEN_FLOOR = 19;
|
|
77
|
+
const int TOKEN_CEIL = 20;
|
|
78
|
+
const int TOKEN_FRAC = 21;
|
|
79
|
+
const int TOKEN_MOD = 22;
|
|
80
|
+
const int TOKEN_ATAN2 = 23;
|
|
81
|
+
const int TOKEN_REAL = 24;
|
|
82
|
+
const int TOKEN_IMAG = 25;
|
|
83
|
+
const int TOKEN_CONJ = 26;
|
|
84
|
+
const int TOKEN_ARG = 27;
|
|
85
|
+
const int TOKEN_SIGN = 28;
|
|
86
|
+
const int TOKEN_STEP = 29;
|
|
87
|
+
const int TOKEN_OPEN_PAREN = 30;
|
|
88
|
+
const int TOKEN_CLOSE_PAREN = 31;
|
|
89
|
+
const int TOKEN_COMMA = 32;
|
|
90
|
+
const int TOKEN_DERIVATIVE = 33;
|
|
91
|
+
const int TOKEN_DOT = 34;
|
|
92
|
+
const int TOKEN_CROSS = 35;
|
|
93
|
+
const int TOKEN_NORM = 36;
|
|
94
|
+
const int TOKEN_SELECT = 37;
|
|
95
|
+
const int TOKEN_NOISE = 38;
|
|
96
|
+
const int TOKEN_RAND = 39;
|
|
97
|
+
const int TOKEN_SUM_NEIGHBORS = 40;
|
|
98
|
+
const int TOKEN_NEIGHBOR_INDEX= 41;
|
|
99
|
+
const int TOKEN_TENSOR_LIT = 42;
|
|
100
|
+
const int TOKEN_LT = 43;
|
|
101
|
+
const int TOKEN_LE = 44;
|
|
102
|
+
const int TOKEN_GT = 45;
|
|
103
|
+
const int TOKEN_GE = 46;
|
|
104
|
+
const int TOKEN_EQ = 47;
|
|
105
|
+
const int TOKEN_NE = 48;
|
|
106
|
+
const int TOKEN_COMP = 49;
|
|
107
|
+
|
|
108
|
+
// ----------------------------------------------------------------------------
|
|
109
|
+
// VARIABLE HASHES (same as math.comp + paint additions)
|
|
110
|
+
// ----------------------------------------------------------------------------
|
|
111
|
+
const int VAR_HASH_X = 1;
|
|
112
|
+
const int VAR_HASH_Y = 2;
|
|
113
|
+
const int VAR_HASH_VX = 3;
|
|
114
|
+
const int VAR_HASH_VY = 4;
|
|
115
|
+
const int VAR_HASH_AX = 5;
|
|
116
|
+
const int VAR_HASH_AY = 6;
|
|
117
|
+
const int VAR_HASH_T = 7;
|
|
118
|
+
const int VAR_HASH_THETA = 8;
|
|
119
|
+
const int VAR_HASH_OMEGA = 27;
|
|
120
|
+
const int VAR_HASH_MASS = 22;
|
|
121
|
+
const int VAR_HASH_CHARGE = 23;
|
|
122
|
+
const int VAR_HASH_R = 9;
|
|
123
|
+
const int VAR_HASH_G = 10;
|
|
124
|
+
const int VAR_HASH_B = 11;
|
|
125
|
+
const int VAR_HASH_A = 12;
|
|
126
|
+
const int VAR_HASH_VIS_X = 100;
|
|
127
|
+
const int VAR_HASH_VIS_Y = 101;
|
|
128
|
+
const int VAR_HASH_RADIUS = 102;
|
|
129
|
+
const int VAR_HASH_WIDTH = 103;
|
|
130
|
+
const int VAR_HASH_HEIGHT = 104;
|
|
131
|
+
const int VAR_HASH_PI = 17;
|
|
132
|
+
const int VAR_HASH_E = 18;
|
|
133
|
+
const int VAR_HASH_I = 16;
|
|
134
|
+
const int VAR_HASH_K = 19;
|
|
135
|
+
const int VAR_HASH_B_DAMP = 20;
|
|
136
|
+
const int VAR_HASH_G_GRAV = 21;
|
|
137
|
+
const int VAR_HASH_COUPLING = 24;
|
|
138
|
+
const int VAR_HASH_FREQ = 25;
|
|
139
|
+
const int VAR_HASH_AMP = 26;
|
|
140
|
+
const int VAR_HASH_PX = 200;
|
|
141
|
+
const int VAR_HASH_PY = 201;
|
|
142
|
+
const int VAR_HASH_PREV_R = 202;
|
|
143
|
+
const int VAR_HASH_PREV_G = 203;
|
|
144
|
+
const int VAR_HASH_PREV_B = 204;
|
|
145
|
+
const int VAR_HASH_PREV_A = 205;
|
|
146
|
+
|
|
147
|
+
// ----------------------------------------------------------------------------
|
|
148
|
+
// CONSTANTS
|
|
149
|
+
// ----------------------------------------------------------------------------
|
|
150
|
+
const float PI = 3.14159265359;
|
|
151
|
+
const float E = 2.71828182846;
|
|
152
|
+
const float EPSILON = 1e-6;
|
|
153
|
+
const float SAFE_MIN_VALUE = 1e-6;
|
|
154
|
+
const float SAFE_MAX_EXP = 50.0;
|
|
155
|
+
|
|
156
|
+
// ----------------------------------------------------------------------------
|
|
157
|
+
// UTILITIES (same as math.comp)
|
|
158
|
+
// ----------------------------------------------------------------------------
|
|
159
|
+
float safeDivide(float n, float d) {
|
|
160
|
+
return (abs(d) < EPSILON) ? 0.0 : n / d;
|
|
161
|
+
}
|
|
162
|
+
float safePow(float base, float exp) {
|
|
163
|
+
if (base < 0.0) {
|
|
164
|
+
float intPart;
|
|
165
|
+
if (abs(modf(exp, intPart)) < EPSILON) {
|
|
166
|
+
float result = pow(-base, exp);
|
|
167
|
+
if (int(intPart) % 2 == 1) result = -result;
|
|
168
|
+
return result;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return pow(max(0.0, base), exp);
|
|
172
|
+
}
|
|
173
|
+
float safeLog(float v) {
|
|
174
|
+
return log(max(SAFE_MIN_VALUE, v));
|
|
175
|
+
}
|
|
176
|
+
float safeExp(float v) {
|
|
177
|
+
return exp(clamp(v, -SAFE_MAX_EXP, SAFE_MAX_EXP));
|
|
178
|
+
}
|
|
179
|
+
bool isInvalid(float v) {
|
|
180
|
+
return isinf(v) || isnan(v);
|
|
181
|
+
}
|
|
182
|
+
vec2 sanitizeVec2(vec2 v) {
|
|
183
|
+
if (isInvalid(v.x)) v.x = 0.0;
|
|
184
|
+
if (isInvalid(v.y)) v.y = 0.0;
|
|
185
|
+
return v;
|
|
186
|
+
}
|
|
187
|
+
vec4 sanitizeVec4(vec4 v) {
|
|
188
|
+
for (int i = 0; i < 4; ++i)
|
|
189
|
+
if (isInvalid(v[i])) v[i] = 0.0;
|
|
190
|
+
return v;
|
|
191
|
+
}
|
|
192
|
+
float signFunc(float x) { return (x > 0.0) ? 1.0 : ((x < 0.0) ? -1.0 : 0.0); }
|
|
193
|
+
float stepFunc(float x) { return (x >= 0.0) ? 1.0 : 0.0; }
|
|
194
|
+
|
|
195
|
+
// ----------------------------------------------------------------------------
|
|
196
|
+
// COMPLEX NUMBERS (same as math.comp)
|
|
197
|
+
// ----------------------------------------------------------------------------
|
|
198
|
+
vec2 cAdd(vec2 a, vec2 b) { return a + b; }
|
|
199
|
+
vec2 cSub(vec2 a, vec2 b) { return a - b; }
|
|
200
|
+
vec2 cMul(vec2 a, vec2 b) {
|
|
201
|
+
return vec2(a.x*b.x - a.y*b.y, a.x*b.y + a.y*b.x);
|
|
202
|
+
}
|
|
203
|
+
vec2 cDiv(vec2 a, vec2 b) {
|
|
204
|
+
float d = b.x*b.x + b.y*b.y;
|
|
205
|
+
if (abs(d) < EPSILON) return vec2(0.0);
|
|
206
|
+
return vec2((a.x*b.x + a.y*b.y)/d, (a.y*b.x - a.x*b.y)/d);
|
|
207
|
+
}
|
|
208
|
+
vec2 cLog(vec2 z) {
|
|
209
|
+
return vec2(safeLog(length(z)), atan(z.y, z.x));
|
|
210
|
+
}
|
|
211
|
+
vec2 cExp(vec2 z) {
|
|
212
|
+
float ea = safeExp(z.x);
|
|
213
|
+
return vec2(ea * cos(z.y), ea * sin(z.y));
|
|
214
|
+
}
|
|
215
|
+
vec2 cPow(vec2 b, vec2 e) {
|
|
216
|
+
if (length(b) < EPSILON) return vec2(0.0);
|
|
217
|
+
return cExp(cMul(e, cLog(b)));
|
|
218
|
+
}
|
|
219
|
+
vec2 cSin(vec2 z) { return vec2(sin(z.x)*cosh(z.y), cos(z.x)*sinh(z.y)); }
|
|
220
|
+
vec2 cCos(vec2 z) { return vec2(cos(z.x)*cosh(z.y), -sin(z.x)*sinh(z.y)); }
|
|
221
|
+
vec2 cTan(vec2 z) { return cDiv(cSin(z), cCos(z)); }
|
|
222
|
+
|
|
223
|
+
// ----------------------------------------------------------------------------
|
|
224
|
+
// RANDOM & NOISE (same as math.comp)
|
|
225
|
+
// ----------------------------------------------------------------------------
|
|
226
|
+
float rand(vec2 seed) {
|
|
227
|
+
return fract(sin(dot(seed, vec2(12.9898, 78.233))) * 43758.5453);
|
|
228
|
+
}
|
|
229
|
+
float smoothNoise(vec2 p) {
|
|
230
|
+
vec2 i = floor(p);
|
|
231
|
+
vec2 f = fract(p);
|
|
232
|
+
vec2 u = f * f * (3.0 - 2.0 * f);
|
|
233
|
+
float a = rand(i);
|
|
234
|
+
float b = rand(i + vec2(1.0, 0.0));
|
|
235
|
+
float c = rand(i + vec2(0.0, 1.0));
|
|
236
|
+
float d = rand(i + vec2(1.0, 1.0));
|
|
237
|
+
return mix(mix(a, b, u.x), mix(c, d, u.x), u.y);
|
|
238
|
+
}
|
|
239
|
+
float noise(vec2 p) {
|
|
240
|
+
float sum = 0.0;
|
|
241
|
+
float amp = 0.5;
|
|
242
|
+
float freq = 4.0;
|
|
243
|
+
for (int i = 0; i < 3; ++i) {
|
|
244
|
+
sum += amp * smoothNoise(p * freq);
|
|
245
|
+
amp *= 0.5;
|
|
246
|
+
freq *= 2.0;
|
|
247
|
+
}
|
|
248
|
+
return sum;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// ----------------------------------------------------------------------------
|
|
252
|
+
// OBJECT PROPERTY GETTER
|
|
253
|
+
// ----------------------------------------------------------------------------
|
|
254
|
+
float getObjectProperty(int idx, int hash, int self) {
|
|
255
|
+
if (idx < 0 || idx >= uNumObjects || idx == self) return 0.0;
|
|
256
|
+
Object o = objectsIn[idx];
|
|
257
|
+
switch (hash) {
|
|
258
|
+
case VAR_HASH_X: return o.position.x;
|
|
259
|
+
case VAR_HASH_Y: return o.position.y;
|
|
260
|
+
case VAR_HASH_VX: return o.velocity.x;
|
|
261
|
+
case VAR_HASH_VY: return o.velocity.y;
|
|
262
|
+
case VAR_HASH_AX: return o.collisionData.x;
|
|
263
|
+
case VAR_HASH_AY: return o.collisionData.y;
|
|
264
|
+
case VAR_HASH_MASS: return o.mass;
|
|
265
|
+
case VAR_HASH_CHARGE: return o.charge;
|
|
266
|
+
case VAR_HASH_THETA: return o.visualData.z;
|
|
267
|
+
case VAR_HASH_OMEGA: return o.visualData.w;
|
|
268
|
+
case VAR_HASH_R: return o.color.r;
|
|
269
|
+
case VAR_HASH_G: return o.color.g;
|
|
270
|
+
case VAR_HASH_B: return o.color.b;
|
|
271
|
+
case VAR_HASH_A: return o.color.a;
|
|
272
|
+
case VAR_HASH_VIS_X: return o.visualData.x;
|
|
273
|
+
case VAR_HASH_VIS_Y: return o.visualData.y;
|
|
274
|
+
case VAR_HASH_RADIUS: return o.visualData.x;
|
|
275
|
+
case VAR_HASH_WIDTH: return o.visualData.x;
|
|
276
|
+
case VAR_HASH_HEIGHT: return o.visualData.y;
|
|
277
|
+
default: return 0.0;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// ----------------------------------------------------------------------------
|
|
282
|
+
// GET VARIABLE VALUE (with paint context)
|
|
283
|
+
// ----------------------------------------------------------------------------
|
|
284
|
+
float getVariableValue(int hash,
|
|
285
|
+
float px, float py,
|
|
286
|
+
float prev_r, float prev_g, float prev_b, float prev_a) {
|
|
287
|
+
// In paint mode we only have px, py, prev_*, and constants.
|
|
288
|
+
// We ignore velocity, mass, etc. Too lazy
|
|
289
|
+
switch (hash) {
|
|
290
|
+
case VAR_HASH_X: return px;
|
|
291
|
+
case VAR_HASH_Y: return py;
|
|
292
|
+
case VAR_HASH_T: return uTime;
|
|
293
|
+
case VAR_HASH_PI: return PI;
|
|
294
|
+
case VAR_HASH_E: return E;
|
|
295
|
+
case VAR_HASH_I: return 0.0;
|
|
296
|
+
case VAR_HASH_PX: return px;
|
|
297
|
+
case VAR_HASH_PY: return py;
|
|
298
|
+
case VAR_HASH_PREV_R: return prev_r;
|
|
299
|
+
case VAR_HASH_PREV_G: return prev_g;
|
|
300
|
+
case VAR_HASH_PREV_B: return prev_b;
|
|
301
|
+
case VAR_HASH_PREV_A: return prev_a;
|
|
302
|
+
default: return 0.0;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// ----------------------------------------------------------------------------
|
|
307
|
+
// FORWARD DECLARATIONS (non‑recursive)
|
|
308
|
+
// ----------------------------------------------------------------------------
|
|
309
|
+
float evaluateScalarTokenList(float px, float py, float prev_r, float prev_g, float prev_b, float prev_a,
|
|
310
|
+
int offset, int count, int constOffset, int self, int neighbor);
|
|
311
|
+
float computeDerivative(float px, float py, float prev_r, float prev_g, float prev_b, float prev_a,
|
|
312
|
+
int wrtHash, int order,
|
|
313
|
+
int exprOffset, int exprCount, int constOffset, int self);
|
|
314
|
+
float evalScalarSubExpr(float px, float py, float prev_r, float prev_g, float prev_b, float prev_a,
|
|
315
|
+
int offset, int count, int constOffset, int self, int neighbor);
|
|
316
|
+
|
|
317
|
+
// ----------------------------------------------------------------------------
|
|
318
|
+
// SCALAR TOKEN LIST EVALUATOR (non‑recursive, stack‑based)
|
|
319
|
+
// ----------------------------------------------------------------------------
|
|
320
|
+
// I hate my life >﹏<
|
|
321
|
+
float evaluateScalarTokenList(float px, float py, float prev_r, float prev_g, float prev_b, float prev_a,
|
|
322
|
+
int offset, int count, int constOffset, int self, int neighbor) {
|
|
323
|
+
if (count <= 0) return 0.0;
|
|
324
|
+
|
|
325
|
+
float stack[32];
|
|
326
|
+
int sp = 0;
|
|
327
|
+
int idx = offset;
|
|
328
|
+
int end = offset + count;
|
|
329
|
+
|
|
330
|
+
while (idx < end) {
|
|
331
|
+
int token = allTokens[idx++];
|
|
332
|
+
|
|
333
|
+
if (token == TOKEN_NUMBER) {
|
|
334
|
+
int cidx = allTokens[idx++];
|
|
335
|
+
stack[sp++] = allConstants[constOffset + cidx];
|
|
336
|
+
}
|
|
337
|
+
else if (token == TOKEN_VARIABLE) {
|
|
338
|
+
int h = allTokens[idx++];
|
|
339
|
+
if (h == VAR_HASH_I) {
|
|
340
|
+
stack[sp++] = 0.0; // imaginary unit => real part 0
|
|
341
|
+
continue;
|
|
342
|
+
}
|
|
343
|
+
stack[sp++] = getVariableValue(h, px, py, prev_r, prev_g, prev_b, prev_a);
|
|
344
|
+
}
|
|
345
|
+
else if (token == TOKEN_OBJECT_REF) {
|
|
346
|
+
int obj = allTokens[idx++];
|
|
347
|
+
int prop = allTokens[idx++];
|
|
348
|
+
stack[sp++] = getObjectProperty(obj, prop, self);
|
|
349
|
+
}
|
|
350
|
+
else if (token == TOKEN_NEIGHBOR_INDEX) {
|
|
351
|
+
stack[sp++] = float(neighbor);
|
|
352
|
+
}
|
|
353
|
+
else if (token == TOKEN_DERIVATIVE) {
|
|
354
|
+
// Skip derivatives inside scalar evaluator (handled at top level)
|
|
355
|
+
int dummy1 = allTokens[idx++];
|
|
356
|
+
int dummy2 = allTokens[idx++];
|
|
357
|
+
int dummy3 = allTokens[idx++];
|
|
358
|
+
int subc = allTokens[idx++];
|
|
359
|
+
idx += subc;
|
|
360
|
+
stack[sp++] = 0.0;
|
|
361
|
+
}
|
|
362
|
+
// Binary arithmetic and comparisons
|
|
363
|
+
else if (token == TOKEN_ADD || token == TOKEN_SUB || token == TOKEN_MUL ||
|
|
364
|
+
token == TOKEN_DIV || token == TOKEN_POW ||
|
|
365
|
+
token == TOKEN_LT || token == TOKEN_LE || token == TOKEN_GT ||
|
|
366
|
+
token == TOKEN_GE || token == TOKEN_EQ || token == TOKEN_NE) {
|
|
367
|
+
if (sp < 2) { stack[0] = 0.0; sp = 1; continue; }
|
|
368
|
+
float b = stack[--sp];
|
|
369
|
+
float a = stack[--sp];
|
|
370
|
+
if (token == TOKEN_ADD) stack[sp++] = a + b;
|
|
371
|
+
else if (token == TOKEN_SUB) stack[sp++] = a - b;
|
|
372
|
+
else if (token == TOKEN_MUL) stack[sp++] = a * b;
|
|
373
|
+
else if (token == TOKEN_DIV) stack[sp++] = safeDivide(a, b);
|
|
374
|
+
else if (token == TOKEN_POW) stack[sp++] = safePow(a, b);
|
|
375
|
+
else if (token == TOKEN_LT) stack[sp++] = (a < b) ? 1.0 : 0.0;
|
|
376
|
+
else if (token == TOKEN_LE) stack[sp++] = (a <= b) ? 1.0 : 0.0;
|
|
377
|
+
else if (token == TOKEN_GT) stack[sp++] = (a > b) ? 1.0 : 0.0;
|
|
378
|
+
else if (token == TOKEN_GE) stack[sp++] = (a >= b) ? 1.0 : 0.0;
|
|
379
|
+
else if (token == TOKEN_EQ) stack[sp++] = (abs(a - b) < EPSILON) ? 1.0 : 0.0;
|
|
380
|
+
else stack[sp++] = (abs(a - b) >= EPSILON) ? 1.0 : 0.0; // NE
|
|
381
|
+
}
|
|
382
|
+
// Unary operators
|
|
383
|
+
else if (token == TOKEN_NEG || token == TOKEN_SIN || token == TOKEN_COS || token == TOKEN_TAN ||
|
|
384
|
+
token == TOKEN_EXP || token == TOKEN_LOG || token == TOKEN_SQRT || token == TOKEN_ABS ||
|
|
385
|
+
token == TOKEN_FLOOR || token == TOKEN_CEIL || token == TOKEN_FRAC ||
|
|
386
|
+
token == TOKEN_SIGN || token == TOKEN_STEP) {
|
|
387
|
+
if (sp < 1) { stack[0] = 0.0; sp = 1; continue; }
|
|
388
|
+
float a = stack[--sp];
|
|
389
|
+
if (token == TOKEN_NEG) stack[sp++] = -a;
|
|
390
|
+
else if (token == TOKEN_SIN) stack[sp++] = sin(a);
|
|
391
|
+
else if (token == TOKEN_COS) stack[sp++] = cos(a);
|
|
392
|
+
else if (token == TOKEN_TAN) stack[sp++] = tan(a);
|
|
393
|
+
else if (token == TOKEN_EXP) stack[sp++] = safeExp(a);
|
|
394
|
+
else if (token == TOKEN_LOG) stack[sp++] = safeLog(a);
|
|
395
|
+
else if (token == TOKEN_SQRT)stack[sp++] = sqrt(max(0.0, a));
|
|
396
|
+
else if (token == TOKEN_ABS) stack[sp++] = abs(a);
|
|
397
|
+
else if (token == TOKEN_FLOOR)stack[sp++] = floor(a);
|
|
398
|
+
else if (token == TOKEN_CEIL)stack[sp++] = ceil(a);
|
|
399
|
+
else if (token == TOKEN_FRAC)stack[sp++] = fract(a);
|
|
400
|
+
else if (token == TOKEN_SIGN)stack[sp++] = signFunc(a);
|
|
401
|
+
else stack[sp++] = stepFunc(a);
|
|
402
|
+
}
|
|
403
|
+
else if (token == TOKEN_MOD) {
|
|
404
|
+
if (sp < 2) { stack[0] = 0.0; sp = 1; continue; }
|
|
405
|
+
float b = stack[--sp];
|
|
406
|
+
float a = stack[--sp];
|
|
407
|
+
stack[sp++] = (abs(b) < EPSILON) ? 0.0 : mod(a, b);
|
|
408
|
+
}
|
|
409
|
+
else if (token == TOKEN_MIN || token == TOKEN_MAX) {
|
|
410
|
+
if (sp < 2) { stack[0] = 0.0; sp = 1; continue; }
|
|
411
|
+
float b = stack[--sp];
|
|
412
|
+
float a = stack[--sp];
|
|
413
|
+
stack[sp++] = (token == TOKEN_MIN) ? min(a, b) : max(a, b);
|
|
414
|
+
}
|
|
415
|
+
else if (token == TOKEN_ATAN2) {
|
|
416
|
+
if (sp < 2) { stack[0] = 0.0; sp = 1; continue; }
|
|
417
|
+
float xv = stack[--sp];
|
|
418
|
+
float yv = stack[--sp];
|
|
419
|
+
stack[sp++] = atan(yv, xv);
|
|
420
|
+
}
|
|
421
|
+
else if (token == TOKEN_CLAMP) {
|
|
422
|
+
if (sp < 3) { stack[0] = 0.0; sp = 1; continue; }
|
|
423
|
+
float maxv = stack[--sp];
|
|
424
|
+
float minv = stack[--sp];
|
|
425
|
+
float val = stack[--sp];
|
|
426
|
+
stack[sp++] = clamp(val, minv, maxv);
|
|
427
|
+
}
|
|
428
|
+
else if (token == TOKEN_NOISE) {
|
|
429
|
+
if (sp < 2) { stack[sp++] = 0.0; continue; }
|
|
430
|
+
float yv = stack[--sp];
|
|
431
|
+
float xv = stack[--sp];
|
|
432
|
+
stack[sp++] = noise(vec2(xv, yv));
|
|
433
|
+
}
|
|
434
|
+
else if (token == TOKEN_RAND) {
|
|
435
|
+
stack[sp++] = rand(vec2(uTime, float(self)));
|
|
436
|
+
}
|
|
437
|
+
// NOTE: SELECT, SUM_NEIGHBORS, TENSOR_LIT, DOT, CROSS, NORM, COMP are not used inside scalar evaluator.
|
|
438
|
+
//Too lazy to add those ¯\_(ツ)_/¯
|
|
439
|
+
}
|
|
440
|
+
return (sp > 0) ? stack[0] : 0.0;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
// ----------------------------------------------------------------------------
|
|
444
|
+
// NUMERICAL DERIVATIVE (non‑recursive)
|
|
445
|
+
// ----------------------------------------------------------------------------
|
|
446
|
+
float computeDerivative(float px, float py, float prev_r, float prev_g, float prev_b, float prev_a,
|
|
447
|
+
int wrtHash, int order,
|
|
448
|
+
int exprOffset, int exprCount, int constOffset, int self) {
|
|
449
|
+
if (order <= 0) {
|
|
450
|
+
return evaluateScalarTokenList(px, py, prev_r, prev_g, prev_b, prev_a,
|
|
451
|
+
exprOffset, exprCount, constOffset, self, -1);
|
|
452
|
+
}
|
|
453
|
+
if (order > 4) return 0.0;
|
|
454
|
+
|
|
455
|
+
float eps = 1e-5;
|
|
456
|
+
float h = eps;
|
|
457
|
+
float orig = (wrtHash == VAR_HASH_PX) ? px : py;
|
|
458
|
+
if (abs(orig) > EPSILON) h = eps * abs(orig);
|
|
459
|
+
|
|
460
|
+
if (order == 1) {
|
|
461
|
+
float px_plus = px, px_minus = px, py_plus = py, py_minus = py;
|
|
462
|
+
if (wrtHash == VAR_HASH_PX) { px_plus = px + h; px_minus = px - h; }
|
|
463
|
+
else { py_plus = py + h; py_minus = py - h; }
|
|
464
|
+
float fp = evaluateScalarTokenList(px_plus, py_plus, prev_r, prev_g, prev_b, prev_a,
|
|
465
|
+
exprOffset, exprCount, constOffset, self, -1);
|
|
466
|
+
float fm = evaluateScalarTokenList(px_minus, py_minus, prev_r, prev_g, prev_b, prev_a,
|
|
467
|
+
exprOffset, exprCount, constOffset, self, -1);
|
|
468
|
+
return (fp - fm) / (2.0 * h);
|
|
469
|
+
}
|
|
470
|
+
else if (order == 2) {
|
|
471
|
+
float px_plus = px, px_minus = px, py_plus = py, py_minus = py;
|
|
472
|
+
if (wrtHash == VAR_HASH_PX) { px_plus = px + h; px_minus = px - h; }
|
|
473
|
+
else { py_plus = py + h; py_minus = py - h; }
|
|
474
|
+
float f0 = evaluateScalarTokenList(px, py, prev_r, prev_g, prev_b, prev_a,
|
|
475
|
+
exprOffset, exprCount, constOffset, self, -1);
|
|
476
|
+
float fp = evaluateScalarTokenList(px_plus, py_plus, prev_r, prev_g, prev_b, prev_a,
|
|
477
|
+
exprOffset, exprCount, constOffset, self, -1);
|
|
478
|
+
float fm = evaluateScalarTokenList(px_minus, py_minus, prev_r, prev_g, prev_b, prev_a,
|
|
479
|
+
exprOffset, exprCount, constOffset, self, -1);
|
|
480
|
+
return (fp - 2.0*f0 + fm) / (h * h);
|
|
481
|
+
}
|
|
482
|
+
// Higher orders (3,4) can be added similarly; not needed for typical paint use coz I said so.
|
|
483
|
+
return 0.0;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
// ----------------------------------------------------------------------------
|
|
487
|
+
// SCALAR SUB‑EXPRESSION EVALUATOR (used in SELECT, SUM_NEIGHBORS, TENSOR_LIT)
|
|
488
|
+
// ----------------------------------------------------------------------------
|
|
489
|
+
float evalScalarSubExpr(float px, float py, float prev_r, float prev_g, float prev_b, float prev_a,
|
|
490
|
+
int offset, int count, int constOffset, int self, int neighbor) {
|
|
491
|
+
return evaluateScalarTokenList(px, py, prev_r, prev_g, prev_b, prev_a,
|
|
492
|
+
offset, count, constOffset, self, neighbor);
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// ----------------------------------------------------------------------------
|
|
496
|
+
// MAIN TYPED EVALUATOR (handles all tokens, identical to math.comp)
|
|
497
|
+
// ----------------------------------------------------------------------------
|
|
498
|
+
float evaluateRPNComponent(float px, float py, float prev_r, float prev_g, float prev_b, float prev_a,
|
|
499
|
+
int componentType,
|
|
500
|
+
int tokenOffset, int tokenCount, int constantOffset, int self) {
|
|
501
|
+
if (tokenCount <= 0) {
|
|
502
|
+
if (componentType == 0 || componentType == 1) return 0.0; // ax, ay
|
|
503
|
+
if (componentType == 2) return 0.0; // angular
|
|
504
|
+
return 1.0; // color default
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
int stack_type[128];
|
|
508
|
+
float stack_data[128][4];
|
|
509
|
+
int stack_rank[128];
|
|
510
|
+
int stack_shape[128][4];
|
|
511
|
+
int stack_size[128];
|
|
512
|
+
bool stack_isComplex[128];
|
|
513
|
+
int sp = 0;
|
|
514
|
+
|
|
515
|
+
int idx = tokenOffset;
|
|
516
|
+
int end = tokenOffset + tokenCount;
|
|
517
|
+
|
|
518
|
+
while (idx < end) {
|
|
519
|
+
int token = allTokens[idx++];
|
|
520
|
+
|
|
521
|
+
// ----- DERIVATIVE -----
|
|
522
|
+
if (token == TOKEN_DERIVATIVE) {
|
|
523
|
+
int wrtHash = allTokens[idx++];
|
|
524
|
+
int order = allTokens[idx++];
|
|
525
|
+
int method = allTokens[idx++];
|
|
526
|
+
int subCount = allTokens[idx++];
|
|
527
|
+
int subOffset = idx;
|
|
528
|
+
idx += subCount;
|
|
529
|
+
float deriv = computeDerivative(px, py, prev_r, prev_g, prev_b, prev_a,
|
|
530
|
+
wrtHash, order, subOffset, subCount, constantOffset, self);
|
|
531
|
+
stack_type[sp] = 0;
|
|
532
|
+
stack_data[sp][0] = deriv;
|
|
533
|
+
stack_isComplex[sp] = false;
|
|
534
|
+
stack_rank[sp] = 0;
|
|
535
|
+
stack_size[sp] = 1;
|
|
536
|
+
sp++;
|
|
537
|
+
continue;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
// ----- TENSOR LITERAL -----
|
|
541
|
+
if (token == TOKEN_TENSOR_LIT) {
|
|
542
|
+
int rank = allTokens[idx++];
|
|
543
|
+
int shape[4]; int total = 1;
|
|
544
|
+
for (int d = 0; d < rank; ++d) {
|
|
545
|
+
shape[d] = allTokens[idx++];
|
|
546
|
+
total *= shape[d];
|
|
547
|
+
}
|
|
548
|
+
if (total > 4) {
|
|
549
|
+
for (int c = 0; c < total; ++c) {
|
|
550
|
+
int compCount = allTokens[idx++];
|
|
551
|
+
idx += compCount;
|
|
552
|
+
}
|
|
553
|
+
stack_type[sp] = 0;
|
|
554
|
+
stack_data[sp][0] = 0.0;
|
|
555
|
+
stack_isComplex[sp] = false;
|
|
556
|
+
stack_rank[sp] = 0;
|
|
557
|
+
stack_size[sp] = 1;
|
|
558
|
+
sp++;
|
|
559
|
+
continue;
|
|
560
|
+
}
|
|
561
|
+
if (rank == 1 && total >= 2 && total <= 4) {
|
|
562
|
+
float comps[4];
|
|
563
|
+
for (int c = 0; c < total; ++c) {
|
|
564
|
+
int compCount = allTokens[idx++];
|
|
565
|
+
int compOffset = idx;
|
|
566
|
+
idx += compCount;
|
|
567
|
+
comps[c] = evalScalarSubExpr(px, py, prev_r, prev_g, prev_b, prev_a,
|
|
568
|
+
compOffset, compCount, constantOffset, self, -1);
|
|
569
|
+
}
|
|
570
|
+
int vecType = (total == 2) ? 1 : (total == 3) ? 2 : 3;
|
|
571
|
+
stack_type[sp] = vecType;
|
|
572
|
+
for (int c = 0; c < total; ++c) stack_data[sp][c] = comps[c];
|
|
573
|
+
stack_rank[sp] = 1;
|
|
574
|
+
stack_shape[sp][0] = total;
|
|
575
|
+
stack_size[sp] = total;
|
|
576
|
+
stack_isComplex[sp] = false;
|
|
577
|
+
sp++;
|
|
578
|
+
} else {
|
|
579
|
+
int firstCount = allTokens[idx++];
|
|
580
|
+
int firstOffset = idx;
|
|
581
|
+
idx += firstCount;
|
|
582
|
+
float firstVal = evalScalarSubExpr(px, py, prev_r, prev_g, prev_b, prev_a,
|
|
583
|
+
firstOffset, firstCount, constantOffset, self, -1);
|
|
584
|
+
for (int c = 1; c < total; ++c) {
|
|
585
|
+
int compCount = allTokens[idx++];
|
|
586
|
+
idx += compCount;
|
|
587
|
+
}
|
|
588
|
+
stack_type[sp] = 0;
|
|
589
|
+
stack_data[sp][0] = firstVal;
|
|
590
|
+
stack_isComplex[sp] = false;
|
|
591
|
+
stack_rank[sp] = 0;
|
|
592
|
+
stack_size[sp] = 1;
|
|
593
|
+
sp++;
|
|
594
|
+
}
|
|
595
|
+
continue;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
// ----- SELECT -----
|
|
599
|
+
if (token == TOKEN_SELECT) {
|
|
600
|
+
int condCount = allTokens[idx++];
|
|
601
|
+
int condOffset = idx; idx += condCount;
|
|
602
|
+
int aCount = allTokens[idx++];
|
|
603
|
+
int aOffset = idx; idx += aCount;
|
|
604
|
+
int bCount = allTokens[idx++];
|
|
605
|
+
int bOffset = idx; idx += bCount;
|
|
606
|
+
float cond = evalScalarSubExpr(px, py, prev_r, prev_g, prev_b, prev_a,
|
|
607
|
+
condOffset, condCount, constantOffset, self, -1);
|
|
608
|
+
if (cond > 0.0) {
|
|
609
|
+
float aVal = evalScalarSubExpr(px, py, prev_r, prev_g, prev_b, prev_a,
|
|
610
|
+
aOffset, aCount, constantOffset, self, -1);
|
|
611
|
+
stack_type[sp] = 0;
|
|
612
|
+
stack_data[sp][0] = aVal;
|
|
613
|
+
stack_isComplex[sp] = false;
|
|
614
|
+
stack_rank[sp] = 0;
|
|
615
|
+
stack_size[sp] = 1;
|
|
616
|
+
} else {
|
|
617
|
+
float bVal = evalScalarSubExpr(px, py, prev_r, prev_g, prev_b, prev_a,
|
|
618
|
+
bOffset, bCount, constantOffset, self, -1);
|
|
619
|
+
stack_type[sp] = 0;
|
|
620
|
+
stack_data[sp][0] = bVal;
|
|
621
|
+
stack_isComplex[sp] = false;
|
|
622
|
+
stack_rank[sp] = 0;
|
|
623
|
+
stack_size[sp] = 1;
|
|
624
|
+
}
|
|
625
|
+
sp++;
|
|
626
|
+
continue;
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
// ----- SUM_NEIGHBORS -----
|
|
630
|
+
if (token == TOKEN_SUM_NEIGHBORS) {
|
|
631
|
+
int weightCount = allTokens[idx++];
|
|
632
|
+
int weightOffset = idx; idx += weightCount;
|
|
633
|
+
int bodyCount = allTokens[idx++];
|
|
634
|
+
int bodyOffset = idx; idx += bodyCount;
|
|
635
|
+
float sum = 0.0;
|
|
636
|
+
for (int n = 0; n < uNumObjects; ++n) {
|
|
637
|
+
if (n == self) continue;
|
|
638
|
+
float w = evalScalarSubExpr(px, py, prev_r, prev_g, prev_b, prev_a,
|
|
639
|
+
weightOffset, weightCount, constantOffset, self, n);
|
|
640
|
+
if (abs(w) < EPSILON) continue;
|
|
641
|
+
float v = evalScalarSubExpr(px, py, prev_r, prev_g, prev_b, prev_a,
|
|
642
|
+
bodyOffset, bodyCount, constantOffset, self, n);
|
|
643
|
+
sum += w * v;
|
|
644
|
+
}
|
|
645
|
+
stack_type[sp] = 0;
|
|
646
|
+
stack_data[sp][0] = sum;
|
|
647
|
+
stack_isComplex[sp] = false;
|
|
648
|
+
stack_rank[sp] = 0;
|
|
649
|
+
stack_size[sp] = 1;
|
|
650
|
+
sp++;
|
|
651
|
+
continue;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
// ----- NUMBER -----
|
|
655
|
+
if (token == TOKEN_NUMBER) {
|
|
656
|
+
int constIdx = allTokens[idx++];
|
|
657
|
+
float val = allConstants[constantOffset + constIdx];
|
|
658
|
+
stack_type[sp] = 0;
|
|
659
|
+
stack_data[sp][0] = val;
|
|
660
|
+
stack_isComplex[sp] = false;
|
|
661
|
+
stack_rank[sp] = 0;
|
|
662
|
+
stack_size[sp] = 1;
|
|
663
|
+
sp++;
|
|
664
|
+
continue;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
// ----- VARIABLE -----
|
|
668
|
+
if (token == TOKEN_VARIABLE) {
|
|
669
|
+
int h = allTokens[idx++];
|
|
670
|
+
if (h == VAR_HASH_I) {
|
|
671
|
+
stack_type[sp] = 0;
|
|
672
|
+
stack_data[sp][0] = 0.0;
|
|
673
|
+
stack_data[sp][1] = 1.0;
|
|
674
|
+
stack_isComplex[sp] = true;
|
|
675
|
+
stack_rank[sp] = 0;
|
|
676
|
+
stack_size[sp] = 1;
|
|
677
|
+
sp++;
|
|
678
|
+
continue;
|
|
679
|
+
}
|
|
680
|
+
float val = getVariableValue(h, px, py, prev_r, prev_g, prev_b, prev_a);
|
|
681
|
+
stack_type[sp] = 0;
|
|
682
|
+
stack_data[sp][0] = val;
|
|
683
|
+
stack_isComplex[sp] = false;
|
|
684
|
+
stack_rank[sp] = 0;
|
|
685
|
+
stack_size[sp] = 1;
|
|
686
|
+
sp++;
|
|
687
|
+
continue;
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
// ----- OBJECT REFERENCE -----
|
|
691
|
+
if (token == TOKEN_OBJECT_REF) {
|
|
692
|
+
int obj = allTokens[idx++];
|
|
693
|
+
int prop = allTokens[idx++];
|
|
694
|
+
float val = getObjectProperty(obj, prop, self);
|
|
695
|
+
stack_type[sp] = 0;
|
|
696
|
+
stack_data[sp][0] = val;
|
|
697
|
+
stack_isComplex[sp] = false;
|
|
698
|
+
stack_rank[sp] = 0;
|
|
699
|
+
stack_size[sp] = 1;
|
|
700
|
+
sp++;
|
|
701
|
+
continue;
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
// ----- NEIGHBOR INDEX -----
|
|
705
|
+
if (token == TOKEN_NEIGHBOR_INDEX) {
|
|
706
|
+
stack_type[sp] = 0;
|
|
707
|
+
stack_data[sp][0] = -1.0;
|
|
708
|
+
stack_isComplex[sp] = false;
|
|
709
|
+
stack_rank[sp] = 0;
|
|
710
|
+
stack_size[sp] = 1;
|
|
711
|
+
sp++;
|
|
712
|
+
continue;
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
// ----- NOISE -----
|
|
716
|
+
if (token == TOKEN_NOISE) {
|
|
717
|
+
if (sp < 2) { stack_type[sp]=0; stack_data[sp][0]=0.0; stack_rank[sp]=0; stack_size[sp]=1; sp++; continue; }
|
|
718
|
+
float yv = stack_data[sp-1][0]; sp--;
|
|
719
|
+
float xv = stack_data[sp-1][0]; sp--;
|
|
720
|
+
stack_type[sp] = 0;
|
|
721
|
+
stack_data[sp][0] = noise(vec2(xv, yv));
|
|
722
|
+
stack_isComplex[sp] = false;
|
|
723
|
+
stack_rank[sp] = 0;
|
|
724
|
+
stack_size[sp] = 1;
|
|
725
|
+
sp++;
|
|
726
|
+
continue;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
// ----- RAND -----
|
|
730
|
+
if (token == TOKEN_RAND) {
|
|
731
|
+
stack_type[sp] = 0;
|
|
732
|
+
stack_data[sp][0] = rand(vec2(uTime, float(self)));
|
|
733
|
+
stack_isComplex[sp] = false;
|
|
734
|
+
stack_rank[sp] = 0;
|
|
735
|
+
stack_size[sp] = 1;
|
|
736
|
+
sp++;
|
|
737
|
+
continue;
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
// ----- DOT PRODUCT -----
|
|
741
|
+
if (token == TOKEN_DOT) {
|
|
742
|
+
if (sp < 2) { stack_type[sp]=0; stack_data[sp][0]=0.0; stack_rank[sp]=0; stack_size[sp]=1; sp++; continue; }
|
|
743
|
+
sp--; int b = sp;
|
|
744
|
+
sp--; int a = sp;
|
|
745
|
+
int sz = min(stack_size[a], stack_size[b]);
|
|
746
|
+
float result = 0.0;
|
|
747
|
+
for (int c = 0; c < sz; ++c) {
|
|
748
|
+
float av = stack_isComplex[a] ? stack_data[a][0] : stack_data[a][c];
|
|
749
|
+
float bv = stack_isComplex[b] ? stack_data[b][0] : stack_data[b][c];
|
|
750
|
+
result += av * bv;
|
|
751
|
+
}
|
|
752
|
+
stack_type[sp] = 0;
|
|
753
|
+
stack_data[sp][0] = result;
|
|
754
|
+
stack_isComplex[sp] = false;
|
|
755
|
+
stack_rank[sp] = 0;
|
|
756
|
+
stack_size[sp] = 1;
|
|
757
|
+
sp++;
|
|
758
|
+
continue;
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
// ----- CROSS PRODUCT -----
|
|
762
|
+
if (token == TOKEN_CROSS) {
|
|
763
|
+
if (sp < 2) { stack_type[sp]=0; stack_data[sp][0]=0.0; stack_rank[sp]=0; stack_size[sp]=1; sp++; continue; }
|
|
764
|
+
sp--; int b = sp;
|
|
765
|
+
sp--; int a = sp;
|
|
766
|
+
vec3 va = vec3(0.0), vb = vec3(0.0);
|
|
767
|
+
for (int c = 0; c < min(stack_size[a], 3); ++c) va[c] = stack_data[a][c];
|
|
768
|
+
for (int c = 0; c < min(stack_size[b], 3); ++c) vb[c] = stack_data[b][c];
|
|
769
|
+
vec3 cr = cross(va, vb);
|
|
770
|
+
stack_type[sp] = 2; // vec3
|
|
771
|
+
stack_data[sp][0] = cr.x;
|
|
772
|
+
stack_data[sp][1] = cr.y;
|
|
773
|
+
stack_data[sp][2] = cr.z;
|
|
774
|
+
stack_isComplex[sp] = false;
|
|
775
|
+
stack_rank[sp] = 1;
|
|
776
|
+
stack_shape[sp][0] = 3;
|
|
777
|
+
stack_size[sp] = 3;
|
|
778
|
+
sp++;
|
|
779
|
+
continue;
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
// ----- NORM -----
|
|
783
|
+
if (token == TOKEN_NORM) {
|
|
784
|
+
if (sp < 1) { stack_type[sp]=0; stack_data[sp][0]=0.0; stack_rank[sp]=0; stack_size[sp]=1; sp++; continue; }
|
|
785
|
+
sp--; int a = sp;
|
|
786
|
+
float lenSq = 0.0;
|
|
787
|
+
for (int c = 0; c < stack_size[a]; ++c) {
|
|
788
|
+
float v = stack_isComplex[a] ? stack_data[a][0] : stack_data[a][c];
|
|
789
|
+
lenSq += v * v;
|
|
790
|
+
}
|
|
791
|
+
stack_type[sp] = 0;
|
|
792
|
+
stack_data[sp][0] = sqrt(lenSq);
|
|
793
|
+
stack_isComplex[sp] = false;
|
|
794
|
+
stack_rank[sp] = 0;
|
|
795
|
+
stack_size[sp] = 1;
|
|
796
|
+
sp++;
|
|
797
|
+
continue;
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
// ----- COMP -----
|
|
801
|
+
if (token == TOKEN_COMP) {
|
|
802
|
+
int index = allTokens[idx++];
|
|
803
|
+
if (sp < 1) { stack_type[sp]=0; stack_data[sp][0]=0.0; stack_rank[sp]=0; stack_size[sp]=1; sp++; continue; }
|
|
804
|
+
sp--; int a = sp;
|
|
805
|
+
float result = 0.0;
|
|
806
|
+
if (index >= 0 && index < stack_size[a]) result = stack_data[a][index];
|
|
807
|
+
stack_type[sp] = 0;
|
|
808
|
+
stack_data[sp][0] = result;
|
|
809
|
+
stack_isComplex[sp] = false;
|
|
810
|
+
stack_rank[sp] = 0;
|
|
811
|
+
stack_size[sp] = 1;
|
|
812
|
+
sp++;
|
|
813
|
+
continue;
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
// ----- POWER (supports complex and scalar) -----
|
|
817
|
+
else if (token == TOKEN_POW) {
|
|
818
|
+
if (sp < 2) { stack_type[sp]=0; stack_data[sp][0]=0.0; stack_rank[sp]=0; stack_size[sp]=1; stack_isComplex[sp]=false; sp++; continue; }
|
|
819
|
+
sp--; int b = sp;
|
|
820
|
+
sp--; int a = sp;
|
|
821
|
+
bool use_complex = stack_isComplex[a] || stack_isComplex[b];
|
|
822
|
+
if (!use_complex) {
|
|
823
|
+
float base_val = stack_data[a][0];
|
|
824
|
+
float exp_val = stack_data[b][0];
|
|
825
|
+
float result = safePow(base_val, exp_val);
|
|
826
|
+
stack_type[sp] = 0;
|
|
827
|
+
stack_data[sp][0] = result;
|
|
828
|
+
stack_rank[sp] = 0;
|
|
829
|
+
stack_size[sp] = 1;
|
|
830
|
+
stack_isComplex[sp] = false;
|
|
831
|
+
} else {
|
|
832
|
+
vec2 base_c = vec2(stack_data[a][0], stack_data[a][1]);
|
|
833
|
+
vec2 exp_c = vec2(stack_data[b][0], stack_data[b][1]);
|
|
834
|
+
vec2 result = cPow(base_c, exp_c);
|
|
835
|
+
stack_type[sp] = 0;
|
|
836
|
+
stack_data[sp][0] = result.x;
|
|
837
|
+
stack_data[sp][1] = result.y;
|
|
838
|
+
stack_rank[sp] = 0;
|
|
839
|
+
stack_size[sp] = 1;
|
|
840
|
+
stack_isComplex[sp] = true;
|
|
841
|
+
}
|
|
842
|
+
sp++;
|
|
843
|
+
continue;
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
// ----- BINARY OPERATORS (ADD, SUB, MUL, DIV, comparisons) -----
|
|
847
|
+
if (token == TOKEN_ADD || token == TOKEN_SUB || token == TOKEN_MUL ||
|
|
848
|
+
token == TOKEN_DIV || token == TOKEN_POW ||
|
|
849
|
+
token == TOKEN_LT || token == TOKEN_LE || token == TOKEN_GT ||
|
|
850
|
+
token == TOKEN_GE || token == TOKEN_EQ || token == TOKEN_NE) {
|
|
851
|
+
|
|
852
|
+
if (sp < 2) { stack_type[sp]=0; stack_data[sp][0]=0.0; stack_rank[sp]=0; stack_size[sp]=1; sp++; continue; }
|
|
853
|
+
sp--; int b = sp;
|
|
854
|
+
sp--; int a = sp;
|
|
855
|
+
|
|
856
|
+
// Complex arithmetic for arithmetic ops
|
|
857
|
+
if ((token == TOKEN_ADD || token == TOKEN_SUB || token == TOKEN_MUL ||
|
|
858
|
+
token == TOKEN_DIV || token == TOKEN_POW) &&
|
|
859
|
+
(stack_isComplex[a] || stack_isComplex[b])) {
|
|
860
|
+
vec2 ca = stack_isComplex[a] ? vec2(stack_data[a][0], stack_data[a][1])
|
|
861
|
+
: vec2(stack_data[a][0], 0.0);
|
|
862
|
+
vec2 cb = stack_isComplex[b] ? vec2(stack_data[b][0], stack_data[b][1])
|
|
863
|
+
: vec2(stack_data[b][0], 0.0);
|
|
864
|
+
vec2 cr;
|
|
865
|
+
if (token == TOKEN_ADD) cr = ca + cb;
|
|
866
|
+
else if (token == TOKEN_SUB) cr = ca - cb;
|
|
867
|
+
else if (token == TOKEN_MUL) cr = cMul(ca, cb);
|
|
868
|
+
else if (token == TOKEN_DIV) cr = cDiv(ca, cb);
|
|
869
|
+
else cr = cPow(ca, cb);
|
|
870
|
+
stack_type[sp] = 0;
|
|
871
|
+
stack_data[sp][0] = cr.x;
|
|
872
|
+
stack_data[sp][1] = cr.y;
|
|
873
|
+
stack_isComplex[sp] = true;
|
|
874
|
+
stack_rank[sp] = 0;
|
|
875
|
+
stack_size[sp] = 1;
|
|
876
|
+
sp++;
|
|
877
|
+
continue;
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
// Scalar * vector broadcast
|
|
881
|
+
if ((token == TOKEN_ADD || token == TOKEN_SUB || token == TOKEN_MUL ||
|
|
882
|
+
token == TOKEN_DIV || token == TOKEN_POW) &&
|
|
883
|
+
stack_type[a] == 0 && !stack_isComplex[a] && stack_type[b] != 0) {
|
|
884
|
+
float s = stack_data[a][0];
|
|
885
|
+
for (int c = 0; c < stack_size[b]; ++c) {
|
|
886
|
+
if (token == TOKEN_ADD) stack_data[b][c] += s;
|
|
887
|
+
else if (token == TOKEN_SUB) stack_data[b][c] -= s;
|
|
888
|
+
else if (token == TOKEN_MUL) stack_data[b][c] *= s;
|
|
889
|
+
else if (token == TOKEN_DIV) stack_data[b][c] = safeDivide(stack_data[b][c], s);
|
|
890
|
+
else stack_data[b][c] = safePow(stack_data[b][c], s);
|
|
891
|
+
}
|
|
892
|
+
stack_type[sp] = stack_type[b];
|
|
893
|
+
stack_rank[sp] = stack_rank[b];
|
|
894
|
+
for (int d = 0; d < 4; ++d) stack_shape[sp][d] = stack_shape[b][d];
|
|
895
|
+
stack_size[sp] = stack_size[b];
|
|
896
|
+
stack_isComplex[sp] = false;
|
|
897
|
+
sp++;
|
|
898
|
+
continue;
|
|
899
|
+
}
|
|
900
|
+
if ((token == TOKEN_ADD || token == TOKEN_SUB || token == TOKEN_MUL ||
|
|
901
|
+
token == TOKEN_DIV || token == TOKEN_POW) &&
|
|
902
|
+
stack_type[b] == 0 && !stack_isComplex[b] && stack_type[a] != 0) {
|
|
903
|
+
float s = stack_data[b][0];
|
|
904
|
+
for (int c = 0; c < stack_size[a]; ++c) {
|
|
905
|
+
if (token == TOKEN_ADD) stack_data[a][c] += s;
|
|
906
|
+
else if (token == TOKEN_SUB) stack_data[a][c] -= s;
|
|
907
|
+
else if (token == TOKEN_MUL) stack_data[a][c] *= s;
|
|
908
|
+
else if (token == TOKEN_DIV) stack_data[a][c] = safeDivide(stack_data[a][c], s);
|
|
909
|
+
else stack_data[a][c] = safePow(stack_data[a][c], s);
|
|
910
|
+
}
|
|
911
|
+
stack_type[sp] = stack_type[a];
|
|
912
|
+
stack_rank[sp] = stack_rank[a];
|
|
913
|
+
for (int d = 0; d < 4; ++d) stack_shape[sp][d] = stack_shape[a][d];
|
|
914
|
+
stack_size[sp] = stack_size[a];
|
|
915
|
+
stack_isComplex[sp] = false;
|
|
916
|
+
sp++;
|
|
917
|
+
continue;
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
// Component‑wise for vectors; comparisons produce scalar.
|
|
921
|
+
int sz = max(stack_size[a], stack_size[b]);
|
|
922
|
+
|
|
923
|
+
if (stack_size[a] == 1 && stack_size[b] == 1 && !stack_isComplex[a] && !stack_isComplex[b]) {
|
|
924
|
+
float av = stack_data[a][0];
|
|
925
|
+
float bv = stack_data[b][0];
|
|
926
|
+
float res;
|
|
927
|
+
if (token == TOKEN_ADD) res = av + bv;
|
|
928
|
+
else if (token == TOKEN_SUB) res = av - bv;
|
|
929
|
+
else if (token == TOKEN_MUL) res = av * bv;
|
|
930
|
+
else if (token == TOKEN_DIV) res = safeDivide(av, bv);
|
|
931
|
+
else res = safePow(av, bv);
|
|
932
|
+
stack_type[sp] = 0;
|
|
933
|
+
stack_data[sp][0] = res;
|
|
934
|
+
stack_rank[sp] = 0;
|
|
935
|
+
stack_size[sp] = 1;
|
|
936
|
+
stack_isComplex[sp] = false;
|
|
937
|
+
sp++;
|
|
938
|
+
continue;
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
stack_type[sp] = (token >= TOKEN_LT) ? 0 : stack_type[a];
|
|
942
|
+
stack_rank[sp] = (token >= TOKEN_LT) ? 0 : stack_rank[a];
|
|
943
|
+
for (int d = 0; d < 4; ++d) stack_shape[sp][d] = (token >= TOKEN_LT) ? 0 : stack_shape[a][d];
|
|
944
|
+
stack_size[sp] = (token >= TOKEN_LT) ? 1 : sz;
|
|
945
|
+
for (int c = 0; c < sz && c < 4; ++c) {
|
|
946
|
+
float av = (c < stack_size[a]) ? stack_data[a][c] : 0.0;
|
|
947
|
+
float bv = (c < stack_size[b]) ? stack_data[b][c] : 0.0;
|
|
948
|
+
if (token == TOKEN_ADD) stack_data[sp][c] = av + bv;
|
|
949
|
+
else if (token == TOKEN_SUB) stack_data[sp][c] = av - bv;
|
|
950
|
+
else if (token == TOKEN_MUL) stack_data[sp][c] = av * bv;
|
|
951
|
+
else if (token == TOKEN_DIV) stack_data[sp][c] = safeDivide(av, bv);
|
|
952
|
+
else if (token == TOKEN_POW) stack_data[sp][c] = safePow(av, bv);
|
|
953
|
+
else if (token == TOKEN_LT) stack_data[sp][c] = (av < bv) ? 1.0 : 0.0;
|
|
954
|
+
else if (token == TOKEN_LE) stack_data[sp][c] = (av <= bv) ? 1.0 : 0.0;
|
|
955
|
+
else if (token == TOKEN_GT) stack_data[sp][c] = (av > bv) ? 1.0 : 0.0;
|
|
956
|
+
else if (token == TOKEN_GE) stack_data[sp][c] = (av >= bv) ? 1.0 : 0.0;
|
|
957
|
+
else if (token == TOKEN_EQ) stack_data[sp][c] = (abs(av - bv) < EPSILON) ? 1.0 : 0.0;
|
|
958
|
+
else stack_data[sp][c] = (abs(av - bv) >= EPSILON) ? 1.0 : 0.0;
|
|
959
|
+
}
|
|
960
|
+
stack_isComplex[sp] = false;
|
|
961
|
+
sp++;
|
|
962
|
+
continue;
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
// ----- UNARY OPERATORS (NEG, SIN, COS, ...) -----
|
|
966
|
+
if (token == TOKEN_NEG || token == TOKEN_SIN || token == TOKEN_COS ||
|
|
967
|
+
token == TOKEN_TAN || token == TOKEN_EXP || token == TOKEN_LOG ||
|
|
968
|
+
token == TOKEN_SQRT || token == TOKEN_ABS || token == TOKEN_FLOOR ||
|
|
969
|
+
token == TOKEN_CEIL || token == TOKEN_FRAC || token == TOKEN_SIGN ||
|
|
970
|
+
token == TOKEN_STEP) {
|
|
971
|
+
if (sp < 1) continue;
|
|
972
|
+
sp--; int a = sp;
|
|
973
|
+
|
|
974
|
+
if (stack_isComplex[a]) {
|
|
975
|
+
vec2 z = vec2(stack_data[a][0], stack_data[a][1]);
|
|
976
|
+
vec2 r;
|
|
977
|
+
if (token == TOKEN_NEG) r = -z;
|
|
978
|
+
else if (token == TOKEN_SIN) r = cSin(z);
|
|
979
|
+
else if (token == TOKEN_COS) r = cCos(z);
|
|
980
|
+
else if (token == TOKEN_TAN) r = cTan(z);
|
|
981
|
+
else if (token == TOKEN_EXP) r = cExp(z);
|
|
982
|
+
else if (token == TOKEN_LOG) r = cLog(z);
|
|
983
|
+
else if (token == TOKEN_SQRT)r = cPow(z, vec2(0.5, 0.0));
|
|
984
|
+
else if (token == TOKEN_ABS) {
|
|
985
|
+
stack_type[sp] = 0;
|
|
986
|
+
stack_data[sp][0] = length(z);
|
|
987
|
+
stack_isComplex[sp] = false;
|
|
988
|
+
stack_rank[sp] = 0;
|
|
989
|
+
stack_size[sp] = 1;
|
|
990
|
+
sp++;
|
|
991
|
+
continue;
|
|
992
|
+
} else {
|
|
993
|
+
r = z;
|
|
994
|
+
}
|
|
995
|
+
stack_type[sp] = 0;
|
|
996
|
+
stack_data[sp][0] = r.x;
|
|
997
|
+
stack_data[sp][1] = r.y;
|
|
998
|
+
stack_isComplex[sp] = true;
|
|
999
|
+
stack_rank[sp] = 0;
|
|
1000
|
+
stack_size[sp] = 1;
|
|
1001
|
+
sp++;
|
|
1002
|
+
continue;
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
// Real case: elementwise
|
|
1006
|
+
for (int c = 0; c < stack_size[a]; ++c) {
|
|
1007
|
+
float v = stack_data[a][c];
|
|
1008
|
+
if (token == TOKEN_NEG) stack_data[a][c] = -v;
|
|
1009
|
+
else if (token == TOKEN_SIN) stack_data[a][c] = sin(v);
|
|
1010
|
+
else if (token == TOKEN_COS) stack_data[a][c] = cos(v);
|
|
1011
|
+
else if (token == TOKEN_TAN) stack_data[a][c] = tan(v);
|
|
1012
|
+
else if (token == TOKEN_EXP) stack_data[a][c] = safeExp(v);
|
|
1013
|
+
else if (token == TOKEN_LOG) stack_data[a][c] = safeLog(v);
|
|
1014
|
+
else if (token == TOKEN_SQRT)stack_data[a][c] = sqrt(max(0.0, v));
|
|
1015
|
+
else if (token == TOKEN_ABS) stack_data[a][c] = abs(v);
|
|
1016
|
+
else if (token == TOKEN_FLOOR)stack_data[a][c] = floor(v);
|
|
1017
|
+
else if (token == TOKEN_CEIL)stack_data[a][c] = ceil(v);
|
|
1018
|
+
else if (token == TOKEN_FRAC)stack_data[a][c] = fract(v);
|
|
1019
|
+
else if (token == TOKEN_SIGN)stack_data[a][c] = signFunc(v);
|
|
1020
|
+
else stack_data[a][c] = stepFunc(v);
|
|
1021
|
+
}
|
|
1022
|
+
stack_type[sp] = stack_type[a];
|
|
1023
|
+
stack_rank[sp] = stack_rank[a];
|
|
1024
|
+
for (int d = 0; d < 4; ++d) stack_shape[sp][d] = stack_shape[a][d];
|
|
1025
|
+
stack_size[sp] = stack_size[a];
|
|
1026
|
+
stack_isComplex[sp] = false;
|
|
1027
|
+
sp++;
|
|
1028
|
+
continue;
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
// ----- COMPLEX OPERATIONS: REAL, IMAG, CONJ, ARG -----
|
|
1032
|
+
if (token == TOKEN_REAL) {
|
|
1033
|
+
if (sp < 1) continue;
|
|
1034
|
+
sp--; int a = sp;
|
|
1035
|
+
if (stack_isComplex[a]) {
|
|
1036
|
+
stack_type[sp] = 0;
|
|
1037
|
+
stack_data[sp][0] = stack_data[a][0];
|
|
1038
|
+
stack_isComplex[sp] = false;
|
|
1039
|
+
stack_rank[sp] = 0;
|
|
1040
|
+
stack_size[sp] = 1;
|
|
1041
|
+
} else {
|
|
1042
|
+
stack_type[sp] = stack_type[a];
|
|
1043
|
+
stack_rank[sp] = stack_rank[a];
|
|
1044
|
+
for (int d = 0; d < 4; ++d) stack_shape[sp][d] = stack_shape[a][d];
|
|
1045
|
+
stack_size[sp] = stack_size[a];
|
|
1046
|
+
stack_isComplex[sp] = false;
|
|
1047
|
+
}
|
|
1048
|
+
sp++;
|
|
1049
|
+
continue;
|
|
1050
|
+
}
|
|
1051
|
+
if (token == TOKEN_IMAG) {
|
|
1052
|
+
if (sp < 1) continue;
|
|
1053
|
+
sp--; int a = sp;
|
|
1054
|
+
if (stack_isComplex[a]) {
|
|
1055
|
+
stack_type[sp] = 0;
|
|
1056
|
+
stack_data[sp][0] = stack_data[a][1];
|
|
1057
|
+
stack_isComplex[sp] = false;
|
|
1058
|
+
stack_rank[sp] = 0;
|
|
1059
|
+
stack_size[sp] = 1;
|
|
1060
|
+
} else {
|
|
1061
|
+
stack_type[sp] = 0;
|
|
1062
|
+
stack_data[sp][0] = 0.0;
|
|
1063
|
+
stack_isComplex[sp] = false;
|
|
1064
|
+
stack_rank[sp] = 0;
|
|
1065
|
+
stack_size[sp] = 1;
|
|
1066
|
+
}
|
|
1067
|
+
sp++;
|
|
1068
|
+
continue;
|
|
1069
|
+
}
|
|
1070
|
+
if (token == TOKEN_CONJ) {
|
|
1071
|
+
if (sp < 1) continue;
|
|
1072
|
+
sp--; int a = sp;
|
|
1073
|
+
if (stack_isComplex[a]) {
|
|
1074
|
+
stack_type[sp] = 0;
|
|
1075
|
+
stack_data[sp][0] = stack_data[a][0];
|
|
1076
|
+
stack_data[sp][1] = -stack_data[a][1];
|
|
1077
|
+
stack_isComplex[sp] = true;
|
|
1078
|
+
stack_rank[sp] = 0;
|
|
1079
|
+
stack_size[sp] = 1;
|
|
1080
|
+
} else {
|
|
1081
|
+
stack_type[sp] = stack_type[a];
|
|
1082
|
+
stack_rank[sp] = stack_rank[a];
|
|
1083
|
+
for (int d = 0; d < 4; ++d) stack_shape[sp][d] = stack_shape[a][d];
|
|
1084
|
+
stack_size[sp] = stack_size[a];
|
|
1085
|
+
stack_isComplex[sp] = false;
|
|
1086
|
+
}
|
|
1087
|
+
sp++;
|
|
1088
|
+
continue;
|
|
1089
|
+
}
|
|
1090
|
+
if (token == TOKEN_ARG) {
|
|
1091
|
+
if (sp < 1) continue;
|
|
1092
|
+
sp--; int a = sp;
|
|
1093
|
+
if (stack_isComplex[a]) {
|
|
1094
|
+
float arg = atan(stack_data[a][1], stack_data[a][0]);
|
|
1095
|
+
stack_type[sp] = 0;
|
|
1096
|
+
stack_data[sp][0] = arg;
|
|
1097
|
+
stack_isComplex[sp] = false;
|
|
1098
|
+
stack_rank[sp] = 0;
|
|
1099
|
+
stack_size[sp] = 1;
|
|
1100
|
+
} else {
|
|
1101
|
+
stack_type[sp] = 0;
|
|
1102
|
+
stack_data[sp][0] = (stack_data[a][0] >= 0.0) ? 0.0 : PI;
|
|
1103
|
+
stack_isComplex[sp] = false;
|
|
1104
|
+
stack_rank[sp] = 0;
|
|
1105
|
+
stack_size[sp] = 1;
|
|
1106
|
+
}
|
|
1107
|
+
sp++;
|
|
1108
|
+
continue;
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
// ----- MOD, MIN, MAX, ATAN2, CLAMP -----
|
|
1112
|
+
if (token == TOKEN_MOD) {
|
|
1113
|
+
if (sp < 2) continue;
|
|
1114
|
+
float bv = stack_data[--sp][0];
|
|
1115
|
+
float av = stack_data[--sp][0];
|
|
1116
|
+
stack_type[sp] = 0;
|
|
1117
|
+
stack_data[sp][0] = (abs(bv) < EPSILON) ? 0.0 : mod(av, bv);
|
|
1118
|
+
stack_isComplex[sp] = false;
|
|
1119
|
+
stack_rank[sp] = 0;
|
|
1120
|
+
stack_size[sp] = 1;
|
|
1121
|
+
sp++;
|
|
1122
|
+
continue;
|
|
1123
|
+
}
|
|
1124
|
+
if (token == TOKEN_MIN || token == TOKEN_MAX) {
|
|
1125
|
+
if (sp < 2) continue;
|
|
1126
|
+
float bv = stack_data[--sp][0];
|
|
1127
|
+
float av = stack_data[--sp][0];
|
|
1128
|
+
stack_type[sp] = 0;
|
|
1129
|
+
stack_data[sp][0] = (token == TOKEN_MIN) ? min(av, bv) : max(av, bv);
|
|
1130
|
+
stack_isComplex[sp] = false;
|
|
1131
|
+
stack_rank[sp] = 0;
|
|
1132
|
+
stack_size[sp] = 1;
|
|
1133
|
+
sp++;
|
|
1134
|
+
continue;
|
|
1135
|
+
}
|
|
1136
|
+
if (token == TOKEN_ATAN2) {
|
|
1137
|
+
if (sp < 2) continue;
|
|
1138
|
+
float xv = stack_data[--sp][0];
|
|
1139
|
+
float yv = stack_data[--sp][0];
|
|
1140
|
+
stack_type[sp] = 0;
|
|
1141
|
+
stack_data[sp][0] = atan(yv, xv);
|
|
1142
|
+
stack_isComplex[sp] = false;
|
|
1143
|
+
stack_rank[sp] = 0;
|
|
1144
|
+
stack_size[sp] = 1;
|
|
1145
|
+
sp++;
|
|
1146
|
+
continue;
|
|
1147
|
+
}
|
|
1148
|
+
if (token == TOKEN_CLAMP) {
|
|
1149
|
+
if (sp < 3) continue;
|
|
1150
|
+
float maxv = stack_data[--sp][0];
|
|
1151
|
+
float minv = stack_data[--sp][0];
|
|
1152
|
+
float val = stack_data[--sp][0];
|
|
1153
|
+
stack_type[sp] = 0;
|
|
1154
|
+
stack_data[sp][0] = clamp(val, minv, maxv);
|
|
1155
|
+
stack_isComplex[sp] = false;
|
|
1156
|
+
stack_rank[sp] = 0;
|
|
1157
|
+
stack_size[sp] = 1;
|
|
1158
|
+
sp++;
|
|
1159
|
+
continue;
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
// Extract result
|
|
1164
|
+
if (sp == 0) return 0.0;
|
|
1165
|
+
float result = 0.0;
|
|
1166
|
+
if (stack_isComplex[0]) result = stack_data[0][0];
|
|
1167
|
+
else if (stack_type[0] == 0) result = stack_data[0][0];
|
|
1168
|
+
else if (stack_size[0] > 0) result = stack_data[0][0];
|
|
1169
|
+
if (isInvalid(result)) {
|
|
1170
|
+
if (componentType >= 3 && componentType <= 6) return 1.0;
|
|
1171
|
+
return 0.0;
|
|
1172
|
+
}
|
|
1173
|
+
if (componentType >= 3 && componentType <= 6) result = clamp(result, 0.0, 1.0);
|
|
1174
|
+
return result;
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
// ----------------------------------------------------------------------------
|
|
1178
|
+
// MAIN
|
|
1179
|
+
// ----------------------------------------------------------------------------
|
|
1180
|
+
void main() {
|
|
1181
|
+
ivec2 coord = ivec2(gl_GlobalInvocationID.xy);
|
|
1182
|
+
if (coord.x >= uTexWidth || coord.y >= uTexHeight) return;
|
|
1183
|
+
|
|
1184
|
+
float screenX = (float(coord.x) + 0.5) * float(uScreenWidth) / float(uTexWidth);
|
|
1185
|
+
float screenY = (float(coord.y) + 0.5) * float(uScreenHeight) / float(uTexHeight);
|
|
1186
|
+
float ndcX = (screenX / uScreenWidth) * 2.0 - 1.0;
|
|
1187
|
+
float ndcY = 1.0 - (screenY / uScreenHeight) * 2.0;
|
|
1188
|
+
float px = uCameraX + ndcX * uHalfWidth;
|
|
1189
|
+
float py = uCameraY + ndcY * uHalfHeight;
|
|
1190
|
+
|
|
1191
|
+
vec4 prev = texelFetch(uPrevFrame, coord, 0);
|
|
1192
|
+
float prev_r = prev.r;
|
|
1193
|
+
float prev_g = prev.g;
|
|
1194
|
+
float prev_b = prev.b;
|
|
1195
|
+
float prev_a = prev.a;
|
|
1196
|
+
|
|
1197
|
+
float r = evaluateRPNComponent(px, py, prev_r, prev_g, prev_b, prev_a,
|
|
1198
|
+
3, uTokenOffset_r, uTokenCount_r, uConstOffset_r, 0);
|
|
1199
|
+
float g = evaluateRPNComponent(px, py, prev_r, prev_g, prev_b, prev_a,
|
|
1200
|
+
4, uTokenOffset_g, uTokenCount_g, uConstOffset_g, 0);
|
|
1201
|
+
float b = evaluateRPNComponent(px, py, prev_r, prev_g, prev_b, prev_a,
|
|
1202
|
+
5, uTokenOffset_b, uTokenCount_b, uConstOffset_b, 0);
|
|
1203
|
+
float a = evaluateRPNComponent(px, py, prev_r, prev_g, prev_b, prev_a,
|
|
1204
|
+
6, uTokenOffset_a, uTokenCount_a, uConstOffset_a, 0);
|
|
1205
|
+
|
|
1206
|
+
// Clamp already done inside evaluateRPNComponent for color components,
|
|
1207
|
+
// but we'll do it again just in case. I am definately not delulu
|
|
1208
|
+
r = clamp(r, 0.0, 1.0);
|
|
1209
|
+
g = clamp(g, 0.0, 1.0);
|
|
1210
|
+
b = clamp(b, 0.0, 1.0);
|
|
1211
|
+
a = clamp(a, 0.0, 1.0);
|
|
1212
|
+
|
|
1213
|
+
imageStore(uPaintTarget, ivec2(coord.x, uTexHeight - 1 - coord.y), vec4(r, g, b, a));
|
|
1214
|
+
}
|