5 ms·
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
by sgtnoodle 5y ago
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.
- merlincorey 5y agoYou 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.
- sgtnoodle 5y agoI'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.
- hwillis 5y ago> 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 the conversion so that the precision doesn't change over the range. That doesn't help either. Unless you round the time uniform CPU side- sending a counter that is incremented once per second to the fog shader, and different counter incremented once per millisecond to the shimmer shader- you're still sending a giant number to a function that is periodic over a 1,000,000x smaller window. Precision errors will still cause wildly varying outputs. Sending separate uniforms only solves the problem for very, very slowly varying functions. > With 1 second precision, you should be good for a few months with a 32 bit float. Human vision is exceptionally well-tuned for noticing sudden changes, even relatively subtle ones. A gradual change over 1 second can be hundreds of times larger than a sudden change before it's noticeable.
- sgtnoodle 5y agoThat 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.