I am aiming at the following case:
bind shader
set uniform variable
..draw box..
set uniform variable to different value
..draw another box, with the new variable applied in the vertex shader..
Is it possible to set GLSL variables in between operations?
Yes, you can freely set uniforms after compilation and mix the settings with draw calls.
Related
I have a GLSL shader that makes use of the gl_InstanceID input variable which is set by a glDrawArraysInstanced all. I want this shader to work with a drawcall that doesn't set gl_InstanceID. Here, I want to set gl_InstanceID manually uniform style.
Is it legal / defined behavior to bind glInstanceID as a uniform for these cases?
GLint const instanceIdx = glGetUniformLocation(pid, "gl_InstanceID");
If you're trying to manually provide a value for gl_InstanceID, getting its location as a uniform isn't going to work for several reasons but mainly because it's not a uniform. It is a built-in vertex shader input variable, which is different from a vertex attribute (which is user provided, not built-in).
The value of gl_InstanceID will be zero for any draw call that doesn't use instancing. If you want it to be non-zero for such calls, that's not possible. gl_BaseInstance from GLSL 4.60/ARB_shader_draw_parameters will track the base instance value from BaseInstance draw calls. So you could use that to effectively set the instance index.
But without that, there's nothing you can do.
I have GLSL compute shader. Very simple one. I specify input texture and output image, mapped to the texture.
layout (binding=2) uniform sampler2D srcTex;
layout (binding=5, r32f) writeonly uniform image2D destTex;
In my code, I need to call glBindImageTexture to attach texture to image. Now, first parameter of this function is
unit
Specifies the index of the image unit to which to bind the texture
I know, that I can set this value to 5 from code manually, but how to do this automatically.
If I create shader I use refraction to get variable names and its locations.
How can I get binding ID?
How can I get texture format from layout (r32f) to set it in my code automatically?
If I create shader I use refraction to get variable names and its locations.
I think you mean reflection and not refraction, assuming you mean the programming language concept.
Now, the interesting thing here is that image2D and sampler2D are what are known as opaque types in GLSL (handles to an image unit). Ordinarily, you could use the modern glGetProgramResource* (...) API (GL_ARB_program_interface_query or core in 4.3) to query really detailed information about uniforms, buffers, etc. in a GLSL shader. However, opaque types are not considered program resources by GLSL and are not compatible with that feature - the information you want is related to the image unit the uniform references and not the uniform itself.
How can I get binding ID?
This is fairly straight-forward.
You can call glGetUniformiv (...) to get the value assigned to your image2D. On the GL-side of things opaque uniforms work no differently than any other uniform (for assigning and querying values), but in GLSL you cannot assign a value to an opaque data type using the = operator. That is why the layout (binding = ...) semantics were created, they allow you to assign the binding in the shader itself rather than having to call an API function and are completely optional.
How can I get texture format from layout (r32f) to set it in my code automatically?
That is not currently possible, and in the future may become irrelevant for loads (it already is for stores). You do not technically need an exact match here. As long as image format size / class match, you can do an image load no problem.
In truth, the only reason you have to declare the format in GLSL is so that the return format for imageLoad (...) is known at compile-time (that makes it irrelevant for writeonly qualified images). There is an EXT extension right now (GL_EXT_shader_image_load_formatted) that completely eliminates the need to establish the image format for non-writeonly images.
Even for non-writeonly images, since only the size / class need to match, I do not think you really need this. r32f has an image class of 1x32 and a size of 32, but the fact that it is floating-point is not relevant to anything. Thus, what you might really consider is naming your uniforms by their image class instead - call this uniform something like destTex_1x32 and it will be obvious that it's a 1-component 32-bit image.
I'm using apple's opengl shader builder to learn GLSL.
And the problem I'm having is that I do not understand how to modify the uniform I defined in a frag shader.
As you can see I have a uniform variable named "someValue" with type GL_INT.
And in the Symbols view it shows three blank field for me to filled out.
The variable I defined is in GL_INT type so which blank should I use anyway and why is there 3 blank fields ?
And for the uniform "tex":
say I have 3 texture in slot 0 ~ 2.
What should I fill in the 3 blank fields to change the texture I want to use ? (I tried some combination and it seems only the second blank will do the work -- eg. fill in 1 for GL_TEXTURE1)
It is explained in the "Modifying Uniform Variables" section of this article: https://developer.apple.com/library/mac/documentation/GraphicsImaging/Conceptual/OpenGLShaderBuilderUserGuide/Tasks/Tasks.html
In the section on the bottom, the controls are shown for whichever uniform that you have selected on the top.
Some Uniform variables have more than one value (for example, a vec3 has vec3.r vec3.g vec3.b (which can also be referenced as x,y,z)), and there will be a separate controller for each value in the uniform variable.
Now, Apple wants you to play around with your shaders a little bit, so they've given you the ability to write in three potential numbers for each value in a uniform. The idea is that you put in some numbers and then use the slider below to "morph" between those numbers, and then see what happens inside of your shader as a result.
In the case of a texture, you will probably want to set all three fields to the same value.
"Global variables and Interface Blocks can be declared with the uniform​ qualifier. This means that the value does not change between multiple executions of a shader during the rendering of a primitive (ie: during a glDraw* call). These values are set by the user from the OpenGL API.
They are constant, but not compile-time constant (so not const​)."
http://www.opengl.org/wiki/Type_Qualifier_(GLSL)#Storage_qualifier
I guess I'm asking why the uniform variables cannot just be constant at compile time as well.
Because they are not constant!
They are constant for every rendering call, but you can set a new value for each one.
For example you could set a uniform to contain a color value, set it to pink and draw your 3d model and it will contain a constant value every time it calls the fragment shader for that drawing operation. But then you can draw something else using the same shader with that uniform set to "green"
I have a fragment shader that uses a few uniforms which are set on a per-object basis. Is there a way to store these uniforms on the graphics card somehow? I've heard of (but cannot find a tutorial for) vertex buffer objects--is there a trick to storing the information in there, so that I don't need to re-set the variables every time I draw a new object?
Each object has very few vertices, but they are completely static.
There are indeed Uniform Buffer Objects in later versions of OpenGL http://www.opengl.org/wiki/Uniform_Buffer_Object
If you use the same shader program ID for all the objects, then you can just set the uniforms once before you render your objects as their value will stay the same until you set them again. So e.g. in your code where you load and compile the shader source, set the uniform variables that are common for all the objects, then render your objects, only setting the per-object uniforms.
The uniform buffer idea in one of the answers can be used if you have different shaders for different objects but you want to share some data between them. This is not necessary in your case as you mention a single shader.