Live data from Hacker News

A Shader Trick

the-witness.net

51–56 of 56 posts

Re: A Shader Trick

#52
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…

The trick isn't so much about looping the sine/cosine. It's about setting synchronizing the maximum time value passed to a shader, with maximum precision of an arbitrary multiplicand used in the shader.

> How do we ensure that, easily, in a way that people don't have to think about?

The relation is that the time should switch from 10^x to 0, and in the shader the number of digits after a dot should be no more than x.

Re: A Shader Trick

#53
post #33

Earlier quoted context omitted.

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…

> Just convert the integer into a float before passing it into the shader. That solves no problems at all. The number needs to stay an integer until after it is fed to a periodic function, which will restore it to a small enough number to be precisely represented as a float. > 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 t…

That is what I'm proposing; use an integer representation in the CPU as the source of truth, then convert it to various floats as needed in the shaders, passed in as an argument to the shader on each frame. I haven't touched GPU code in a decade, but that's a reasonable thing to do on each frame isn't it?

``` float periodic_animation_sec = (now_ns % periodic_animation_period_ns) * 1e-9f; float fog_sec = now_ns / 1000000000; // or use a power of 2 ```

Regarding the acceptable level of approximation for human perception, I think my point still stands. My assumption is that the frequency content of fog is low enough that pixel colors won't change appreciably over the course of a second. Want 30Hz? That will give you a few days before the precision degrades. 10Hz? About a week or so. Or, find a different solution, like using the CPU to reset the state of the shader every so often. Figure out how to do that seamlessly, or just make sure there's an in-game sunny day every few hours.

Re: A Shader Trick

#54

Earlier quoted context omitted.

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.

I'm specifically suggesting transforming the integer in an intelligent way to map well to the mantissa of the floating point representation, based on the intended usage. High frequency animations can chop off the most significant bits, while low frequency animations can chop off the bottom bits.

If you aren't able to constrain the design or make assumptions about frequencies, then it seems like you have to instead parameterize time as some sort of tuple so that you have more bits, such as the sum of a course absolute and a fine offset, and write the shader to cope with it. That's how time APIs in many operating systems work, where there's integer seconds and integer micro or nanoseconds.

Re: A Shader Trick

#55

Earlier quoted context omitted.

I think one of the key flourishes of the game has to do with intrinsic vs extrinsic motivation. The game never presents a locked door where there is some key elsewhere, and the key goes into your inventory, and now you can open the door. At all times, all doors are openable. But you may not know the rules to the puzzle on the door yet. Once you learn them, the 'key' is knowledge and the 'inventory' is your mind. If y…

Outer Wilds does this as well.

This is one of my favorite things about that game. You could technically beat The Outer Wilds on your very first time loop, but in practice you need to explore just about everything in order to understand how to do it.

Re: A Shader Trick

#56

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…

I remember seeing Hypnocube references and your site probably around 2005 or 2006, but it was so far beyond me at the time I just wrote it off as "cool OK". YouTube wasn't quite what it is today so I never did get to see what it looks like in motion. Today I assume similar things can be done extraordinarily cheap and easily but I still have no idea how. I'm not motivated enough right now to ask, but I just wanted to…

Cool. Glad you liked it. It's been a fun gadget to make and sell.
Post reply on HN