NAN in OpenGL textures - opengl

I use 1D, 2D and 3D OpenGL textures containing float 32 data (GL_RGBA32F format), in a desktop application (Windows/Linux, GLSL 4.2).
These textures contains results of precomputed physical data and could contains some NAN values where the precompute failed (this is "normal" in my application, some cases cannot be computed, this is rare but "normal")
I need to detect these values in the shader.
Is there any standard on handling NAN values in GLSL sampler ?
More specifically :
is it sure that a NAN value written in a texture a read as NAN by "textureXXX" GLSL methods ?
if a "textureXXX" method is called with non-NEAREST filtering and one of the interpolated values is a NAN, should I get a NAN value as result ?
Thanks.
Edit :
As the answers says, nothing is required about NaN support in OpenGL specifications.
So I will :
replace NaN values with a "special" value in case the NaN value in a texture is not read as NaN in GLSL
implement the mipmapping by myself
test all values against the "special" value
This is extra work, but seems to be necessary to ensure support of my invalid values on different platforms / different hardware.

Based on my interpretation of the spec, the answer is NO to both. The most conclusive evidence I found for this is in section 4.7.1 "Range and Precision" of recent GLSL specs (e.g. page 65 of the GLSL 4.20 spec):
Operations and built-in functions that operate on a NaN are not required to return a NaN as the result.
The texture() GLSL calls are built-in functions, so I believe this rule applies to them, and you can't count on them returning NaN for textures that contain NaN values.

Section 2.3.4.1 of the OpenGL 4.5 compatibility spec says that "Implementations are permitted,
but not required, to support Inf s and NaN s in their floating-point computations."
I didn't find any mention of NaN values in the texture minification section of the spec (8.14.2 in OpenGL 4.5 compatibility spec). However, the equations used in fragment minification seem fairly well specified, so I imagine implementations will respect NaN values in them. If you are afraid, however, you can use raw texture access functions to implement mipmapping yourself. As Reto Koradi notes, texture functions may not return NaN values for filtered textures.

Related

range of interpolateAtOffset()'s offset parameter

Both the GLSL 4.6 and GLSL ES 3.2 spec say:
The range and granularity of offsets supported by this function [interpolateAtOffset] is implementation-dependent.
This seems too open-ended to be useful. How am I expected to know what will actually work across multiple vendors? Is there at least a minimum supported range specified somewhere in the standards? If not, is there something de-facto supported by the major vendors that I can rely on?
For Vulkan, the 1.2 specification requires the range and granularity to be reported with minInterpolationOffset, maxInterpolationOffset, and subPixelInterpolationOffsetBits, where:
The values minInterpolationOffset and maxInterpolationOffset describe the closed interval of supported interpolation offsets: [minInterpolationOffset, maxInterpolationOffset]. The ULP is determined by subPixelInterpolationOffsetBits. If subPixelInterpolationOffsetBits is 4, this provides increments of (1/24) = 0.0625, and thus the range of supported interpolation offsets would be [-0.5, 0.4375].
Based on the minimum values of these required by the specification, you can rely on at least [-0.5, 0.4375] being available if sampleRateShading is supported.
For OpenGL, the 4.6 specification says:
The built-in function interpolateAtOffset will sample variables at a specified (x, y) offset relative to the center of the pixel. The range and granularity of offsets supported by this function is implementation-dependent. If either component of the specified offset is less than the value of MIN_FRAGMENT_INTERPOLATION_OFFSET or greater than the value of MAX_FRAGMENT_INTERPOLATION_OFFSET, the position used to interpolate the variable is undefined. Not all values of offset may be supported; x and y offsets may be rounded to fixed-point values with the number of fraction bits given by the value of the implementation-dependent constant FRAGMENT_INTERPOLATION_OFFSET_BITS.
The required minimums are the same as Vulkan.
Trying to search through PDFs is painful so I won't bother looking at the ES spec, I would assume it's the same.

What's the use case of glTexParameterIiv and glTexParameterIuiv?

The OpenGL documentation says very little about these two functions. When it would make sense to use glTexParameterIiv instead of glTexParameteriv or even glTexParameterfv?
If the values for GL_TEXTURE_BORDER_COLOR are specified with glTexParameterIiv or glTexParameterIuiv, the values are stored unmodified with an internal data type of integer. If specified with glTexParameteriv, they are converted to floating point with the following equation: f=(2c+1)/(2b−1). If specified with glTexParameterfv, they are stored unmodified as floating-point values.
You sort of answered your own question with the snippet you pasted. Traditional textures are fixed-point (unsigned normalized, where values like 255 are converted to 1.0 through normalization), but GL 3.0 introduced integral (signed / unsigned integer) texture types (where integer values stay integers).
If you had an integer texture and wanted to assign a border color (for use with the GL_CLAMP_TO_BORDER wrap mode), you would use one variant of those two functions (depending on whether you want signed or unsigned).
You cannot filter integer textures, but you can still have texture coordinate wrap behavior. Since said textures are integer and glTexParameteriv (...) normalizes the color values it is passed, an extra function had to be created to keep the color data integer.
You will find this same sort of thing with glVertexAttribIPointer (...) and so forth; adding support for integer data (as opposed to simply converting integer data to floating-point) to the GL pipeline required a lot of new commands.

what is need of integer and SNORM textures

What is the advantage or need of integer and SNORM textures? when do we use (-1,0) range for textures?
Any example where we need specifically integer or SNORM textures?
According to https://www.opengl.org/registry/specs/EXT/texture_snorm.txt,
signed normalized integer texture formats are used to represent a floating-point values in the range [-1.0, 1.0] with an exact value of floating point zero.
It is nice for storing noise, especially Perlin.
Better than float textures because no bits wasted on the exponent.
Unfortunately, as of GL4.4 none of the snorm formats can be rendered to.
You can use the unorm formats and *2-1 for the same effect, although there may be issues with getting an exact 0.

Using GL_RGB10_A2UI internal format in glCopyTexImage1D() OpenGL 3.3

I am using GL_RGB10_A2UI internal format in glCopyTexImage1D() API but getting GL_INVALID_OPERATION error. Does OpenGL 3.3 support GL_RGB10_A2UI in glCopyTexImage1D() ?
GL_RGB10_A2UI is an integral image format; it contains integers, not normalized floating-point values that are stored as integers. Therefore, unless your framebuffer also contains unsigned integer values, this copy operation will fail with the expected error.
Of course, the only way for your framebuffer to have unsigned integers (rather than unsigned normalized integers, which is the usual case) would be to use an FBO. In which case, you could just be rendering directly to this texture, and you wouldn't need to copy from it.
I'm guessing you probably meant to use GL_RGB10_A2, which represent unsigned normalized values.

glsl infinity constant

Does GLSL have any pre-defined constants for +/-infinity or NaN? I'm doing this as a workaround but I wonder if there is a cleaner way:
// GLSL FRAGMENT SHADER
#version 410
<snip>
const float infinity = 1. / 0.;
void main ()
{
<snip>
}
I am aware of the isinf function but I need to assign infinity to a variable so that does not help me.
Like Nicol mentioned, there are no pre-defined constants.
However, from OpenGL 4.1 on, your solution is at least guaranteed to work and correctly generate an infinite value.
See for example in glsl 4.4:
4.7.1 Range and Precision
...
However, dividing a non-zero by 0 results in the
appropriately signed IEEE Inf: If both positive and negative zeros are implemented, the correctly signed
Inf will be generated, otherwise positive Inf is generated.
Be careful when you use an older version of OpenGL though:
For example in glsl 4.0 it says:
4.1.4 Floats
...
Similarly, treatment of conditions such as divide by 0 may lead to an unspecified result, but in no case should such a condition lead to the interruption or termination of processing.
There are no pre-defined constants for it, but there is the isinf function to test if something is infinity.
While I'm at it, are there constants for other things like FLT_MAX FLT_EPSILON etc the way there are in C?
No, there are not.
This might work?
const float pos_infinity = uintBitsToFloat(0x7F800000);
const float neg_infinity = uintBitsToFloat(0xFF800000);
"If the encoding of a floating point infinity is passed in parameter x, the resulting floating-point value is the corresponding (positive or negative) floating point infinity"