What is the texture sampling precision? - opengl-es

In OpenGL, when sampling a texture, what is the precision or format used for the location?
To elaborate: when sampling with texture(sampler, vTextureCoordinates) in a shader, on e.g. precision highp float, two float32+ go in. However, is that precision used to sample the texture, or will it be degraded (e.g. "snapped to fixed point" like in d3d)?
While I am primarily interested in WebGL2, this would also be interesting to know for other OpenGL versions.
My current guess is, that it will be truncated to a 16-bit normalized unsigned integer, but I am not sure. Perhaps it is also unspecified, in which case, what can be depended upon?
This is related to my texture-coordinate-inaccuracy question. Now that I have several hints, that this degradation might really take place, I can ask about the specific part. Should sampling precision indeed be a 16-bit normalized integer, I could also close that one.

This is a function of the hardware, not the graphics API commanding that hardware. So it doesn't matter if you're using D3D, WebGL, Vulkan, or whatever, the precision of texture coordinate sampling is based on the hardware you're running on.
Most APIs don't actually tell you what this precision is. They will generally require some minimum precision, but hardware can vary.
Vulkan actually allows implementations to tell you the sub-texel precision. The minimum requirement is 4 bits of sub-texel precision (16 values). The Vulkan hardware database shows that hardware varies between 4 and 8, with 8 being 10x more common than 4.

Related

Any way to control FP precision in desktop OpenGL?

Is it possible to force a GPU to use highp floats in shaders when the OpenGL version being used is 2.0? I know that precision modifiers are basically a GLES concept, but floats do seem to use mediump by default on a desktop I was provided for testing, and it`s driving me nuts.
I`ve stumbled across that problem while running my GL project under Win10 with a GTX1070 GPU (driver version 23.21.13-9135). I don`t even have #version set in my shaders, so I expected the precision to be automatically maxed out.
AFAIK, OpenGL 2.x standard does not define any ways to hint the GPU that at least 20 of 24 mantissa bits are significant (passing integers through floats, since GL 2.0 cannot operate on integers natively), but that`s the first time in 3++ years that I`ve seen a desktop GPU do such a thing, so I`ve never even thought it possible.
Help needed.

What is a good algo for glsl lowp random number generation (for use in graphics)?

I need a random number generator to create some graphical static. I'm not looking for noise algorithms- I just want white noise. All I need for this is a random number generator in glsl. Specifically, I'll be using it to create a random lightness offset per-fragment, over time.
Requirements:
generates number between 0.0 and 1.0 (don't care if inclusive/exclusive)
This needn't be that random. This won't be used for any security purposes, it just needs to be "random" to the naked eye.
It needs to be computable with lowp floats only! (for use on mobile)
Only has fragment_x, fragment_y, and time_mod_ten_pi as inputs (time_mod_ten_pi is exactly what it sounds like; the time (in seconds) since the game began, mod (10*3.1415) passed in as a float to allow for easy, continuous oscillations without worrying about precision issues. and 30 seconds is waaay more than enough time that a human won't notice repeating noise)
when displayed on a fragment_x * fragment_y grid, I don't want any visible patterns (statically, or in motion)
the simpler/faster, the better!
want to reiterate here- needs to function with only lowp floats. that one-liner going around the internet (fract(sin(dot(...)))) does not fulfill this condition! (at least, I assume the issue is with the lowp floats... could be really feeble sin implementation as well... so if you can avoid sin of high numbers too? bonus?)
This is the best I've been able to come up with, but I'm still not 100% satisfied (you can still see a small kaleidoscope-like effect if you look hard enough...
float rand(float frag_x, float frag_y, float t)
{
float r = t*7.924;
return fract(sin(frag_y+frag_x)*r+sin(frag_y-frag_x)*r*.7);
}
(the 7.924 and the .7 is me mashing on the keyboard- nothing more)
GLSL ES 1.0 (the version of GLSL used in OpenGL ES 2.0 and WebGL 1.0) requires at least support for mediump precision numbers in fragment shaders and other shaders. For your purposes, mediump numbers cover at least all integers in the range (-1024, 1024) (so 10 bits in precision besides the sign bit), and mediump floating-point numbers cover all multiples of 1/1024 in the range [0, 1]. These ranges are quite small, however. (For further information on mediump number requirements, see sec. 4.5, "Precision and Precision Qualifiers", of the GLSL ES 1.0 specification).
Your use of the term "lowp floats" is rather vague, though, so for the purposes of this question, I assume you use "lowp floats" to mean floating-point numbers meeting the minimum requirements for mediump numbers in GLSL ES 1.0, which have to be available in all implementations of GLSL ES 1.0. (Note that GLSL ES 1.0's lowp numbers can have a range as low as (-2, 2) and a precision as low as 8 bits, making them much less suitable for your purposes.)
Thus, for "lowp floats" as just defined, you should find a pseudorandom number generator (or hash function) that can be calculated:
With 5-bit integers only. The function can perform two calls of the generator (one for the first 5 bits, another for the last 5 bits), combine the results, then divide by 1024.0.
With 10-bit integers only. The function can thus perform one call of the generator, then divide the generated number by 1024.0.
This approach will generate a pseudorandom number in the interval [0, 1) that's a multiple of 1/1024.
For GLSL, a viable alternative may be to sample from a texture made up of uniformly distributed pseudorandom numbers. See also "Free blue noise textures" for a similar approach involving sampling blue noise textures. Obviously, since "lowp floats" have a precision as low as 10 bits, the texture should not be more than 1024 pixels wide or 1024 pixels high.

Fast approximate algorithm for RGB/LAB conversion?

I am working on a data visualization tool using OpenGL, and the LAB color space is the most comprehensible color space for visualization of the data I'm dealing with (3 axes of data are mapped to the 3 axes of the color space). Is there a fast (e.g. no non-integer exponentiation, suitable for execution in a shader) algorithm for approximate conversion of LAB values to and from RGB values?
If doing the actual conversion calculation in a shader is too complex/expensive, you can always use a lookup table. Since both color spaces have 3 components, you can use a 3D RGB texture to represent the lookup table.
Using a 3D texture might sound like a lot of overhead. Since 8 bits/component is often used to represent colors in OpenGL, you would need a 256x256x256 3D texture. At 4 bytes/texel, that's a 64 MByte texture, which is not outrageous, but very substantial.
However, depending on how smooth the values in the translation table are, you might be able to get away with a lower resolution. Keep in mind that texture sampling uses linear interpolation. If piecewise linear interpolation is good enough with a certain base-resolution of the lookup table, you can greatly reduce the size.
If you go this direction, and can't afford to use 64 MBytes for the LUT, you'll have to play with the size of the LUT, and make a possible size/performance vs. quality tradeoff.

Are there noise functions in GLSL OpenGL ES 2.0 (iOS)?

Or any counterpart?
How can I generate a cheap random number?
GLSL ES doesn't come with noise functions, and the desktop GLSL noise functions are almost never implemented.
However, there are some freeware noise functions available. They're supposed to be pretty decent and fast. I've never used them myself, but they should work. It's MIT-licensed code, if you're worried about that.
Define "cheap".
The way random numbers work in computers is, they're not really random. You start with a number (the seed), and for each random number you want you do some fancy looking calculations on that number to get another number which looks random, and you use that number as your random number and the seed for the next random number. See here for the gory details.
Problem is, that procedure is inherently sequential, which is no good for shaders.
You could theoretically write a function in a fragment shader that makes some hash out of, say, the fragment position and potentially some uniform int that is incremented every frame, but that is an awful lot of work for a fragment shader, just to produce something that looks like noise.
The conventional technique for producing noise effects in OpenGL is to create a noisy texture and have the shader(s) use it in various ways. You could simply apply the texture as a standard texture to your surface, or you could stretch it or clamp its color values. For time-varying effects you might want to use a 3D texture, or have a larger 2D texture and pass a random texture coordinate offset to the fragment shader stage each frame via a uniform.
Also have a look at perlin noise, which essentially uses a variation of the effect described above.

Precision/units in OpenGL

I am currently developing in OpenGL and use the meter as my own unit, i.e. 0.2 for a 20 cm wide triangle.
However OpenGL seems to round these figures, which ends in shapes not exactly following my wishes.
Is this normal in OpenGL, and should I use centimeters as the unit instead?
You seem to use 1m for 1 unit in GL space, the shape distortion might be caused the incorrect perspective, either too much twisted or flattened, or higher than usual. This is because of incorrect viewport ratio, etc.
OpenGL never rounds up anything, only the precision limit of float or double types.
If you are using OpenGL for architecture, I suggest considering 1 GL unit as 1mm.
OpenGL units are simply units, measures of some unspecified thing. They can mean whatever you want. Unless you are getting incredibly small, large, or precise, it won't make a practical difference. 0.2 should be fine.

Resources