Live data from Hacker News

A Shader Trick

the-witness.net

21–30 of 56 posts

Re: A Shader Trick

#21

The blog suggests that you need to use integers to describe time because floats have problems. Granted. Why limit one’s self to absolutely having to describe it in a single integer value? Why not some wrapper around a handful of integer values that can handle a much bigger max? Would this have a meaningful performance cost?

You could simply use a single 64 bit integer in, say, nanoseconds. That would give you 584 years of range.

Just convert the integer into a float before passing it into the shader. For periodic effects, apply the appropriate modulo. Fog doesn't change very rapidly, so if wrapping is a pain, you could just accept the loss in precision. You could round the value as part of the conversion so that the precision doesn't change over the range. With 1 second precision, you should be good for a few months with a 32 bit float.

Re: A Shader Trick

#22
post #14

i have been doing this for a while playing around with shadertoy. i don't think i learned it from anywhere, i just wanted some things to match up and repeat over hours and it was obvious that sin/cos are periodic, and cycling the time value would improve the imprecision at the seam. seeing it delivered as a clever trick in a blog post makes me wonder if i'm more competent than i thought, or if everyone else is genera…

It's a little bit of both, probably?

Re: A Shader Trick

#23
I've used a similar trick for decades: for example I put it in the code for my Hypnocube (www.hypnocube.com) product in 2005 (Hypnocube). I used it in games and digital art projects before (and after) that.

For embedded or low resource computing, sin/cos may be expensive, so I use a table based fixed point version. I pick the table to have size power of 2, making lots of things easier. Then to make time wrap, I use a large power of 2, which is exactly the same as this trick, with base 10 replaced with base 2 (and using fixed point math).

You also hit problems where delta times can go negative, so those also need to be max time aware. In short, I always make a timing module, it tracks time (and stretches it as needed), and doles out a few things used everywhere: a delta frame time, a large time (say 64 bits as ns for 584 year wraparound), and a capped time (say 16 or 24 bits) to use in places where you know the wrap amount and still give space for computations not to overflow.

As far as I know the Hypnocube never repeats nor does anything flicker at any time due to bad wraparounds. But that took work to ensure.

Re: A Shader Trick

#25
post #2

I think I've read that minecraft behaves differently depending on how far away you are standing from the origin for similar reasons: [1] https://minecraft.fandom.com/wiki/Bedrock_Edition_distance_e... [2] https://minecraft.fandom.com/wiki/Java_Edition_distance_effe...

I've encountered that, too, in my Excel 97 easter egg reproduction. My terrain loops in the shader, but camera position is governed by the JavaScript, so it can get weird far from origin if I don't sanitize.

Here's how the terrain normally looks, zoomed out with the grid on:

https://rezmason.github.io/excel_97_egg/?o=bq

And here's how it looks 8589990 units from the origin, with sanitizing off:

https://rezmason.github.io/excel_97_egg/?o=bq&sanitizePositi...

There's two weird phenomena happening there: the lack of camera position precision causes the terrain to shift left and right, but a little bit further, you can see that all the terrain quads collapse in one dimension for some reason.

Someone also made a game out of this, called Floating Point Leviathan:

https://yanknoopdev.itch.io/fpl

Re: A Shader Trick

#26
post #2

I think I've read that minecraft behaves differently depending on how far away you are standing from the origin for similar reasons: [1] https://minecraft.fandom.com/wiki/Bedrock_Edition_distance_e... [2] https://minecraft.fandom.com/wiki/Java_Edition_distance_effe...

Yes, the Minecraft Farlands are caused by precision issues of floating point numbers. The game becomes jittery as it tries snapping to fewer and fewer precise digits. This is most obvious at first in the selection box around blocks, but the terrain also becomes unstable after a certain point. Note that one Youtuber KurtJMac has been walking to the Farlands since 2011. He's been raising money for charity as part of th…

Huh, I remember seeing some of his videos about five years ago and wondering if he'd ever make it. Glad to see he's still going!

Re: A Shader Trick

#28
When I need something like that, I usually passing [ 0 .. 1 ] float phase to the shaders, and when updating the number on CPU I wrap the value into that range after the increment.

Re: A Shader Trick

#29

The blog suggests that you need to use integers to describe time because floats have problems. Granted. Why limit one’s self to absolutely having to describe it in a single integer value? Why not some wrapper around a handful of integer values that can handle a much bigger max? Would this have a meaningful performance cost?

You could simply use a single 64 bit integer in, say, nanoseconds. That would give you 584 years of range. Just convert the integer into a float before passing it into the shader. For periodic effects, apply the appropriate modulo. Fog doesn't change very rapidly, so if wrapping is a pain, you could just accept the loss in precision. You could round the value as part of the conversion so that the precision doesn't ch…

You can't put a 64 bit integer into a 32 or even 64 bit floating point number since at least some of those bits aren't available even in the 64 bit floating point number.

Re: A Shader Trick

#30

The blog suggests that you need to use integers to describe time because floats have problems. Granted. Why limit one’s self to absolutely having to describe it in a single integer value? Why not some wrapper around a handful of integer values that can handle a much bigger max? Would this have a meaningful performance cost?

It doesn't suggest using integers. It suggests resetting your time uniform every 1000, 10000, 100000... etc. In values of ten raised to some (integer) power. The sole reason for picking a number like that is because programmers will tend to use constants like 32.768 instead of some fractional value. If you use 32.768 and reset your time uniform at 1000, the functions used with 32.768 will still loop seamlessly.

Double precision operations are much slower on GPUs. This can get very bad indeed for certain optimizations, like LUTs. 32 bit integers can accumulate much more time delta than floats without precision errors, but have similar problems.

You can pass in an integer and convert it to a float, but that doesn't really solve any problems. The accumulated time is being used in functions that noticeably change over a dozen milliseconds. The total accumulation is simply too large to for floats to represent with that precision; you would also need to convert most of the math surrounding the time uniform.

It is a much better solution to limit the time uniform. The periodic functions depending on it are sensitive to millisecond changes and loop every 100-10000 milliseconds; there's no reason for time to ever be much larger than 10000.

Post reply on HN