 | WGSL '%' vs GLSL 'mod' |  |
Are they the same?
NO
In GLSL, the `mod(x, y)` function computes true mathematical modulo, which always returns a non-negative result in the range [0, y) , even when x is negative. This is useful for periodic operations like wrapping angles or texture coordinates. However, WGSL's % operator is a remainder operation, not a true modulo—it preserves the sign of the dividend (x % y has the same sign as x ). This means negative inputs can produce negative results, which can cause issues in polar coordinate calculations, tiling, or other cases where a positive range is expected.
To match GLSL's mod behavior in WGSL, we need to manually adjust the result. A common approach is to compute x - y * floor(x / y) , which ensures the output stays non-negative. Below is a mymod(..) function that replicates GLSL's mod in WGSL, followed by a simple example demonstrating the difference between WGSL's % and the corrected version.
 | Example: mymod vs % in WGSL |  |
// Replicates GLSL's mod(x, y) behavior fn mymod(x: f32, y: f32) -> f32 { return x - y * floor(x / y); }
@fragment fn main(@builtin(position) fragCoord: vec4<f32>) -> @location(0) vec4<f32> { let x = -5.7; let y = 3.0; // WGSL '%' (remainder, keeps sign) let wgsl_mod = x % y; // Returns -2.7 // GLSL-style mod (always positive) let glsl_mod = mymod(x, y); // Returns 0.3 (same as GLSL) // Visualize the difference if (fragCoord.x < 300.0) { return vec4<f32>(wgsl_mod, 0.0, 0.0, 1.0); // Red if negative } else { return vec4<f32>(0.0, glsl_mod, 0.0, 1.0); // Green if positive } }
This example shows that -5.7 % 3.0 in WGSL gives -2.7 (remainder), while mymod(-5.7, 3.0) correctly returns 0.3 (like GLSL). Use mymod when you need periodic wrapping without negative results.
|