GLSL Uniform evaluation - opengl

If in a vertex shader there is:
#version 450 core
uniform bool v1;
void main()
{
if(v1 == true)
{
//do something
}
}
Since Uniform variables are constant throughout the shader run, how many times will the if be evaluated per frame? One? Or one per vertex (since we are in the vs)?

Either it will be evaluated once per vertex, or the system will recompile the shader every time you change that uniform (or maybe just have 2 forms of the shader). You should prefer the former to the latter.

Related

Can I modify vertex buffer in GPU through the vertex shader?

For some reason cannot find the answer on the web. I want to update vertex attributes in GPU through the shader in similar form:
#version 330 core
layout(location = 0) in vec4 position;
uniform mat4 someTransformation;
void main()
{
position = position * someTransformation;
gl_Position = position;
}
Is it possible?
Can you write the code you have written? Yes, that is legal code.
Will that change the contents of any GPU storage? No.
While there are ways for a VS to directly manipulate the contents of a buffer, if the buffer region being manipulated is also potentially being used as an attribute array for a rendering command, then you will have undefined behavior.
You can use SSBOs to manipulate other storage which is not being used as the input for rendering. And you can use transform feedback to accumulate data output from vertex processing. But you cannot have a VS directly modify its own input array.

Initializing global variables in glsl?

works fine in my setup but want to be sure.
using glsl 430 and I have this in my geometry shader
#version 430
layout (points) in;
layout (triangle_strip) out;
layout (max_vertices = 24) out;
uniform mat4 u_projMatrix;
uniform mat4 u_viewMatrix;
mat4 viewProjection = u_projMatrix * u_viewMatrix;
void someFunction1(){
// uses viewProjection
}
void someFunction2(){
// uses viewProjection
}
void main()
{
// uses viewProjection
}
my concern is with viewProjection , I expect viewProjection to be initialized before main(). I went through the glsl manual and looks like it will do exactly that and should compile fine.If it is not valid code can someone please refer me to the section in the spec, thanks
Yes, this code is technically fine. The specification allows you to use arbitrary expressions to initialize global variables, even ones which use uniforms and the like. Essentially, they will execute before main starts.
But you shouldn't actually use this.
First, this sort of thing is very uncommon in shader code. As such, OpenGL implementations are less likely to be properly tested against it. Which means that there is a greater chance of the implementation getting this code wrong in some way. It's much safer to just write the code in main.
Second, you're hiding the cost of your shader. If your initializations are not constant expressions, then they will actually cost execution time. But you won't see it in main nor in any function main calls. It will exist outside of what you normally think of as "code". But it will still cost performance.

Acessing VBO/VAO Data in GLSL Shader

In a vertex shader how can a function within the shader be made to access a specific attribute array value after buffering its vertex data to a VBO?
In the shader below the cmp() function is supposed to compare a uniform variable with vertex i.
#version 150 core
in vec2 vertices;
in vec3 color;
out vec3 Color;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
uniform vec2 cmp_vertex; // Vertex to compare
out int isEqual; // Output variable for cmp()
// Comparator
vec2 cmp(){
int i = 3;
return (cmp_vertex == vertices[i]);
}
void main() {
Color = color;
gl_Position = projection * view * model * vec4(vertices, 0.0, 1.0);
isEqual = cmp();
}
Also, can cmp() be modified so that it does the comparison in parallel?
Based on the naming in your shader code, and the wording of your question, it looks like you misunderstood the concept of vertex shaders.
The vertex shader is invoked once for each vertex. So when your vertex shader code executes, it always operates on a single vertex. This means that the name of your in variable is misleading:
in vec2 vertices;
This variable gives you the position of the one and only vertex your shader is working on. So it would probably be clearer if you used a name in singular form:
in vec2 vertex;
Once you realize that you're operating on a single vertex, the rest becomes easy. For the comparison:
bool cmp() {
return (cmp_vertex == vertex);
}
Vertex shaders are typically already invoked in parallel, meaning that many instances can execute at the same time, each one on its own vertex. So there is no need for parallelism within a single shader instance.
You'll probably have more issues achieving what you're after. But I hope that this gets you at least over the initial hurdle.
For example, the following out variable is problematic:
out int isEqual;
out variables of the vertex shader have matching in variables in the fragment shader. By default, the value written by the vertex shader is linearly interpolated across triangles, and the fragment shader gets the interpolated values. This is not supported for variables of type int. They only support flat interpolation:
flat out int isEqual;
But this will probably not give you what you're after, since the value you see in the fragment shader will always be the same across an entire triangle.

fragment shader if statment and loading array of mat4 into uniform

I have problem with if here, for reasons uknown to me, it dosnt work.
When i delete if statment or malualy write shadowMap[0] 1 or 2 it works fine, but with if i just get set of white triangles and squares.
here is part of my frag shader
float shadow(float bias)
{
float visibility = 0;
int index=1;
if(gl_FragCoord.z<1.0){
index=0;
}
vec4 shadowCoord=depthPV*vPos;
if ( texture(shadowMap[index], shadowCoord.xy).z < shadowCoord.z+bias){
visibility = -1;
}
return visibility;
}
Other problem i have is with loading array of mat4 into uniform here is code i tried, but it dosnt work, i use lwjgl 3 libery in java
shadowPVs=GL20.glGetUniformLocation(pId, "shadowPVs");
ByteBuffer shadowPVbuff=BufferUtils.createByteBuffer(shadePV.length*16*4);
for(int i=0;i<shadePV.length;i++){
for(int v=0;v<16;v++){
shadowPVbuff.putFloat(shadePV[i].val[v]);
}
}
shadowPVbuff.flip();
GL20.glUniformMatrix4f(shadowPVs, shadePV.length, false, shadowPVbuff);
and in shader
uniform mat4 shadowPVs[3];
What you are trying to do is not possible with current GL.
As #gemse already pointed out in the comments, the relevant part of the GLSL 3.30 spec is:
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”).
In GL 4, this constraint has been somehwat relaxed, but not far enough. In the most current GLSL 4.50 spec, the statement is:
When aggregated into arrays within a shader, samplers can only be
indexed with a dynamically uniform integral expression, otherwise
results are undefined.
With dynamically uniform being defined as
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. This is similarly defined for other shader stages, based on the
per-instance data they process. Note that constant expressions are
trivially dynamically uniform. It follows that typical loop counters
based on these are also dynamically uniform.
Your index depends on data which can vary per fragment, so you are getting undefined results.

Using input/output structs in GLSL-Shaders

In HLSL I can write:
struct vertex_in
{
float3 pos : POSITION;
float3 normal : NORMAL;
float2 tex : TEXCOORD;
};
and use this struct as an input of a vertex shader:
vertex_out VS(vertex_in v) { ... }
Is there something similar in GLSL? Or do I need to write something like:
layout(location = 0) in vec4 aPosition;
layout(location = 1) in vec4 aNormal;
...
What you are looking for are known as interface blocks in GLSL.
Unfortunately, they are not supported for the input to the Vertex Shader stage or for the output from the Fragment Shader stage. Those must have explicitly bound data locations at program link-time (or they will be automatically assigned, and you can query them later).
Regarding the use of HLSL semantics like : POSITION, : NORMAL, : TEXCOORD, modern GLSL does not have anything like that. Vertex attributes are bound to a generic (numbered) location by name either using glBindAttribLocation (...) prior to linking or as in your example, layout (location = ...).
For input / output between shader stages, that is matched entirely on the basis of variable / interface block name during GLSL program linking (except if you use the relatively new Separate Shader Objects extension). In no case will you have constant pre-defined named semantics like POSITION, NORMAL, etc. though; locations are all application- or linker-defined numbers.