GLSL: Data Distortion - glsl

I'm using OpenGL 3.3 GLSL 1.5 compatibility. I'm getting a strange problem with my vertex data. I'm trying to pass an index value to the fragment shader, but the value seems to change based on my camera position.
This should be simple : I pass a GLfloat through the vertex shader to the fragment shader. I then convert this value to an unsigned integer. The value is correct the majority of the time, except for the edges of the fragment. No matter what I do the same distortion appears. Why is does my camera position change this value? Even in the ridiculous example below, tI erratically equals something other than 1.0;
uint i;
if (tI == 1.0) i = 1;
else i = 0;
vec4 color = texture2D(tex[i], t) ;
If I send integer data instead of float data I get the exact same problem. It does not seem to matter what I enter as vertex Data. The value I enter into the data is not consistent across the fragment. The distortion even looks the exact same each time.

What you are doing here is invalid in OpenGL/GLSL 3.30.
Let me quote the GLSL 3.30 specification, section 4.1.7 "Samplers" (emphasis mine):
Samplers aggregated into arrays within a shader (using square brackets
[ ]) can only be indexed with integral constant expressions (see
section 4.3.3 “Constant Expressions”).
Using a varying as index to a texture does not represent a constant expression as defined by the spec.
Beginning with GL 4.0, this was somewhat relaxed. The GLSL 4.00 specification states now the following (still my emphasis):
Samplers aggregated into arrays within a shader (using square brackets
[ ]) can only be indexed with a dynamically uniform integral
expression, otherwise results are undefined.
With dynamically uniform being defined as follows:
A fragment-shader expression is dynamically uniform if all fragments
evaluating it get the same resulting value. When loops are involved,
this refers to the expression's value for the same loop iteration.
When functions are involved, this refers to calls from the same call
point.
So now this is a bit tricky. If all fragment shader invocations actaully get the same value for that varying, it would be allowed, I guess. But it is unclear that your code guarantees that. You should also take into account that the fragment might be even sampled outside of the primitive.
However, you should never check floats for equality. There will be numerical issues. I don't know what exactly you are trying to achieve here, but you might use some simple rounding behavior, or use an integer varying. You also should disable the interpolation of the value in any case using the flat qualifier (which is required for the integer case anyway), which should greatly improve the changes of that construct to become dynamically uniform.

Related

Is glGetUniformLocation necessary

I am following tutorials on both Youtube and online and they all say to use glGetUniformLocation to get the uniform location of the uniform in the shader. But what if you know the index of the uniform location to begin with, it saves one draw call at the start of program and you can just hard code in a value.
I'm asking specifically about whether its necessary due to being able to hard code in the value. Not the new features of openGL that gives you the ability to get the same result.
In my program I tried inputting the following. glUniform4f(0, 0.1, 0.4, 0.6, 0.3); and it works!. Its linking to the first uniform in the shader.
I've tried searching "importance of glGetUniformLocation" and "Is glGetUniformLocation necessary" in stackoverflow and found no one asking the same question as I am. As a new openGl learning, reading through the openGL books I can't seem to find any explanation of this either.
Until GLSL gained the ability to specify a uniform's location in the text itself, you needed to call glGetUniformLocation (or an equivalent) at least once for any particular program, for any particular uniform within that program which you wanted to manipulate. You could cache that value, either in specific variables or in data structures. But you needed to call it at least once.
However, once a program could specify the location of its uniforms, there was no longer a reason to do this. After all, the shader must specify the correct name that your glGetUniformLocation call looks for, right? What is the difference between the shader specifying a name and the shader specifying a number? They're just identifiers representing some conceptual meaning within that program; one is a string, the other a number. And the shader has to use the correct identifier, the one which matches the thing your code expects to find.
So if you have the ability to specify locations in your shader, you should just do that and forgo any glGetUniformLocation usage.

Using only part of a varying variable

Let's say I have a varying variable between any two GLSL shader stages (e.g. the vertex and fragment stage) declared as a vec4:
in/out/varying vec4 texCoord;
What happens if I only use part of that variable (say, through swizzling) in both shaders, i.e. I only write to a part of it in the vertex shader and only read from that same part in the fragment shader?
// vertex shader
texCoord.st = ...
// fragment shader
... = texture2D(..., texCoord.st);
Is that guartanteed (i.e. by specification) to always produce sane results? It seems reasonable that it does, however I'm not too well-versed in the intricacies of GLSL language-lawyering and don't know if that varying variable is interpreted as somehow "incomplete" by the compiler/linker because it isn't fully written to in the preceding stage. I'm sure the values of texCoord.pq will be undefined anyway, but does that affect the validity of texCoord.st too or does the whole varying system operate on a pure component level?
I haven't found anything to that effect in the GLSL specification on first glance and I would prefer answers based either on the actual specification or any other "official" guarantees, rather than statements that it should work on reasonable hardware (unless of course this case simply is unspecified or implementation-defined). I would also be interested in any possible changes of that throughout GLSL history, including all the way back to its appliance to deprecated builtin varying variables like gl_TexCoord[] in good old GLSL 1.10.
I'm trying to argue that your code will be fine, as per the specification. However, I'm not sure if you will find my reasoning 100% convincing, because I think that the spec seems somewhat imprecise about this. I'm going to refer to the OpenGL 4.5 Core Profile Specification and the OpenGL Shading language 4.50 specification.
Concerning input and output variables, the GLSL spec established the following in section 4.3.4
Shader input variables are declared with the storage qualifier in. They form the input interface between
previous stages of the OpenGL pipeline and the declaring shader. [...] Values from the previous pipeline stage are copied into input variables at the beginning of
shader execution.
and 4.3.6, respectively:
Shader output variables are declared with a storage qualifier using the storage qualifier out. They form
the output interface between the declaring shader and the subsequent stages of the OpenGL pipeline. [...]
During shader execution they will behave as normal
unqualified global variables. Their values are copied out to the subsequent pipeline stage on shader exit.
Only output variables that are read by the subsequent pipeline stage need to be written; it is allowed to
have superfluous declarations of output variables.
Section 5.8 "Assignments" establishes that
Reading a variable before writing (or initializing) it is legal, however the value is undefined.
Since the assignment of the .st vector will write to the sub-vector, we can establish that this variable will contain two intialized and two un-initialized components at the end of the shader invocation, and the whole vector will be copied to the output.
Section 11.1.2.1 of the GL spec states:
If the output variables are passed directly to the vertex processing
stages leading to rasterization, the values of all outputs are
expected to be interpolated across the primitive being rendered,
unless flatshaded. Otherwise the values of all outputs are collected
by the primitive assembly stage and passed on to the subsequent
pipeline stage once enough data for one primitive has been collected.
"The values of all outputs" are determined by the shader, and although some components have undefined values, they still have values, and there is no undefined or implementation-defined behavior here. The interpolation formulas for the line and polygon primitives (sections 14.5.1 and 14.6.1) also never mix between the components, so any defined component value will result in a defined value in the interpolated datum.
Section 11.1.2.1 also contains this statement about the vertex shader outputs:
When a program is linked, all components of any outputs written by a
vertex shader will count against this limit. A program whose vertex
shader writes more than the value of MAX_VERTEX_OUTPUT_COMPONENTS
components worth of outputs may fail to link, unless device-dependent
optimizations are able to make the program fit within available
hardware resources.
Note that this language implies that the full 4 components of a vec4 are counted against the limit as soon as a single component is written to.
On output variables, the specification says:
Their values are copied out to the subsequent pipeline stage on shader exit.
So the question boils down to two things:
What is the value of such an output variable?
That is easily answered. The section on swizzling makes it clear that writing to a swizzle mask will not modify the components that are not part of the swizzle mask. Since you did not write to those components, their values are undefined. So undefined values will be copied out to the subsequent pipeline stage.
Will interpolation of undefined values affect the interpolation of defined values?
No. Interpolation is a component-wise operation. The result of one component's interpolation cannot affect another's.
So this is fine.

Use sampler without passing through value

I'm dealing with texture in fragment shader and I use a sampler2D to get the 2D texture but I do not pass through the value in OpenGL program. However, the value of that sampler2D is correct.
I feel really confused about this and any explanation about this?
The default value of a sampler variable is 0. From the GLSL 3.30 spec, section "4.3.5 Uniforms":
The link time initial value is either the value of the variable's initializer, if present, or 0 if no initializer is present. Sampler types cannot have initializers.
Since a value of 0 means that it's sampling from texture unit 0, it will work without ever setting the value as long as you bind your textures to unit 0. This is well defined behavior.
Since texture unit 0 is also the default until you call glActiveTexture() with a value other than GL_TEXTURE0, it's very common to always use unit 0 as long as shaders do not need more than one texture. Which means that often times, setting the sampler uniforms is redundant for simple applications.
I would still prefer to always set the values. If nothing else, it makes it clear to anybody reading your code that you really mean to sample from texture unit 0, and did not just forget to set the value.

why gl_VertexID is not an unsigned int?

I am in the process of designing a shader program that makes use of the built-in variable gl_VertexID:
gl_VertexID — contains the index of the current vertex
The variable is defined as a signed int. Why it is not an unsigned int? What happens when it is used with very large arrays (e.g. a 2^30 long array)?
Does GLSL treat it as an unsigned int?
I want to use its content as an output of my shader (e.g writing it into an output FBO buffer) I will read its content using glReadPixels with GL_RED_INTEGER as format and either GL_INT or GL_UNSIGNED_INT as type.
Which one is correct?
If I use GL_INT I will not be able to address very large arrays.
In order to use GL_UNSIGNED_INT I might cast the generated gl_VertexID to a uint inside my shader but again, how to access long array?
Most likely historical reasons. gl_VertexID was first defined as part of the EXT_gpu_shader4 extension. This extension is defined based on OpenGL 2.0:
This extension is written against the OpenGL 2.0 specification and version 1.10.59 of the OpenGL Shading Language specification.
GLSL did not yet support unsigned types at the time. They were not introduced until OpenGL 3.0.
I cannot tell if OpenGL might treat the vertex id as unsigned int, but you could most likely create your own (full 32-bit) ID. I have done this some time ago by specifying a rgba8888 vertex color attribute which is converted to an id in the shader by bit-shifting the r,g,b, and a components.
Doing this i also noticed that this wasn't anyhow slower than using gl_VertexID, which seemed to introduce some overhead. Nowadays just use an unsigned int attribute.
Also, i wonder, why would you want to read back the gl_VertexID?
(i did this once for an algorithm and it turned out to be not thought through and now has been replaced by sth more efficient ;) )

what parameters does the function texture() takes?

float texture(gsampler2DArrayShadow sampler, vec4 P, [float bias]);
Look at this function in OpenGL ES (shader lang). I do not understand the difference between gsampler2DArrayShadow and sampler2DArrayShadow. Can you explain this? I read that 'g' can mean nothing or i or u. But what then is this type?
Also, Does '[float bias]' mean that we have 2 functions: with this parameter and without?
Anytime you see a variable type in GLSL prefixed with g in a function prototype, that is a shorthand convention that means there is an overload for every type of data. A function that accepts gvec, for instance, means it has an overload for ivec, uvec, vec, dvec, bvec and so on.
Desktop GLSL has support for integer samplers in addition to fixed-/floating-point so you will see a lot of functions defined using gsampler... instead of sampler..., that means the function has isampler... and usampler... overloads in addition to the more traditional variety.
As for [float bias], that is used to control mipmap LOD bias. When you do not supply a value to that parameter, GL computes the bias itself.
Interestingly because of the way mipmap LODs are computed, only the fragment shader variety of the texture lookups support automatic mipmap selection (it has to do with the per-fragment derivative calculation). To use mipmapping in the vertex shader, you have to explicitly select the LOD with textureLod (...) or supply your own partial derivative using textureGrad (...).