Pass textures to a sampler2D array in GLSL shader? - opengl

I want to pass multiple textures to the shader as an array, like this:
layout(binding = 0) uniform sampler2D uTextures[8];
And how should I assign values ​​to the array above using glsl's binding points layout?

Related

GLSL Uniform layout binding and textures

I'm a bit confused on what would be the right way to bind the texture when uniforms are using the layout binding.
layout(binding = 0, std140) uniform uCommon
{
mat4 projectionMatrix;
mat4 viewMatrix;
};
layout(binding = 1, std140) uniform uModel
{
mat4 modelViewProjectionMatrix;
};
layout(binding = 3) uniform sampler2D uTexture;
To bind my first texture I should use "GL_TEXTURE0 + 3"?
glActiveTexture(GL_TEXTURE0 + 3);
glBindTexture(GL_TEXTURE_2D, textureId);
Is this the correct way?
EDIT: Or is sampler using a separate binding from other uniforms? Can I use:
layout(binding = 0) uniform sampler2D uTexture;
while still using
layout(binding = 0, std140) uniform uCommon
Uniform block binding indices have nothing to do with sampler binding locations. These are different things.
The integer-constant-expression, which is used to specify the binding point or unit has not to be unique across all usages of the keyword binding.
See OpenGL Shading Language 4.60 Specification; 4.4.5 Uniform and Shader Storage Block Layout Qualifiers; page 77
The binding identifier specifies the uniform buffer binding point corresponding to the uniform or shader storage block, which will be used to obtain the values of the member variables of the block.
See OpenGL Shading Language 4.60 Specification; 4.4.6 Opaque-Uniform Layout Qualifiers; page 79
Image and sampler types both take the uniform layout qualifier identifier for binding:
layout-qualifier-id :
binding = integer-constant-expression
The identifier binding specifies which unit will be bound.

Error loading compute shader

I'm implementing simple ray tracing with a compute shader.
But I'm stuck in linking the program object of the compute shader.
#version 440
struct triangle {
vec3 points[3];
};
struct sphere {
vec3 pos;
float r;
};
struct hitinfo {
vec2 lambda;
int idx;
};
layout(binding = 0, rgba32f) uniform image2D framebuffer;
// wrriten by compute shader
layout (local_size_x = 1, local_size_y = 1) in;
uniform triangle triangles[2500];
uniform sphere spheres[2500];
uniform int num_triangles;
uniform int num_spheres;
uniform vec3 eye;
uniform vec3 ray00;
uniform vec3 ray10;
uniform vec3 ray01;
uniform vec3 ray11;
Here is my compute shader code and I can get a "Out of resource" error.
I know the reason of this error is the size of triangles but I need that size.
Is there any way how a large number of triangles can be passed into the shader?
There is just a very limited amount of uniforms a shader can have. If you need more data then what fits in your uniforms, you can either use Uniform Buffer Objects or Shader Storage Buffer Objects to back up a uniform.
In this case, you will have to define a GLSL Interface Block and bind the buffer to that uniform. This means, that you only need one uniform in order to store a large number of similar elements.

Is glVertexAttribpointer used only for vertex, UVs, colors, and normals ? Nothing else?

I want to incorporate a custom attribute that varies per vertex. In this case it is assigned to location=4 ... but nothing happens, the other four attributes vary properly except that one. At the bottom, I added a test to produce a specific color if it encounters the value '1' (which I know exists in the buffer, because I queried the buffer earlier). Attribute 4 is stuck at the first value of its array and never moves.
Am I missing a setting ? (something to be enabled maybe ?) or is it that openGL only varies a handful attributes but nothing else ?
#version 330 //for openGL 3.3
//uniform variables stay constant for the whole glDraw call
uniform mat4 ProjViewModelMatrix;
uniform vec4 DefaultColor; //x=-1 signifies no default color
//non-uniform variables get fed per vertex from the buffers
layout (location=0) in vec3 coords; //feeding from attribute=0 of the main code
layout (location=1) in vec4 color; //per vertex color, feeding from attribute=1 of the main code
layout (location=2) in vec3 normals; //per vertex normals
layout (location=3) in vec2 UVcoord; //texture coordinates
layout (location=4) in int vertexTexUnit;//per vertex texture unit index
//Output
out vec4 thisColor;
out vec2 vertexUVcoord;
flat out int TexUnitIdx;
void main ()
{
vertexUVcoord = UVcoord;
TexUnitIdx=vertexTexUnit;
if (DefaultColor.x==-1) {thisColor = color;} //If no default color is set, use per vertex colors
else {thisColor = DefaultColor;}
gl_Position = ProjViewModelMatrix * vec4(coords,1.0); //This outputs the position to the graphics card.
//TESTING
if (vertexTexUnit==1) thisColor=vec4(1,1,0,1); //Never receives value of 1, but the buffer does contain such values
}
Because the vertexTexUnit attribute is an integer, you must use glVertexAttribIPointer() instead of glVertexAttribPointer().
You can use vertex attributes for whatever you want. OpenGL doesn't know or care what you're using them for.

Changing color of fragment

I have written a fragment shader which i would like to change the color of the fragment. for example I would like if the color it receives is black then it should change it to a blue.
This is the shader that I am using:
uniform sampler2D mytex;
layout (pixel_center_integer) in vec4 gl_FragCoord;
uniform sampler2D texture1;
void main ()
{
ivec2 screenpos = ivec2 (gl_FragCoord.xy);
vec4 color = texelFetch (mytex, screenpos, 0);
if (color == vec4 (0.0,0.0,0.0,1.0)) {
color = (0.0,0.0,0.0,0.0);
}
gl_FragColor = texture2D (texture1, gl_TexCoord[0].st);
}
And here is the log that I am getting from it:
WARNING: -1:65535: 'GL_ARB_explicit_attrib_location' : extension is not available in current GLSL version
WARNING: 0:1: 'texelFetch' : function is not available in current GLSL version
I am aware of the warning- but shouldn't it compile anyways?
The shader is not doing what i would like it to do, can someone explain why?
For one thing, you are using functions that are not available in your GLSL implementation. The result of calling these will be undefined.
However, the kicker here is that gl_FragColor has absolutely NOTHING to do with the value of color in this shader. So even if your texelFetch (...) logic actually did work correctly, changing the value of color does nothing to the final output. A smart compiler will see this as a no-op and effectively strip your shader down to this:
uniform sampler2D texture1;
void main ()
{
gl_FragColor = texture2D (texture1, gl_TexCoord[0].st);
}
If that were not enough, texelFetch (...) is completely unnecessary in this shader. If you want to lookup the texel that corresponds to the current fragment in your shader and the texture has the same dimensions as the viewport you are drawing into you can actually use texture2D (texture1, gl_FragCoord.xy); This is because the default behaviour in GLSL is to have gl_FragCoord supply the coordinate of the fragment's center (x+0.5, y+0.5) - this is also the center of the corresponding texel in your texture (if it is the same resolution), so you can do a traditional texture lookup without worrying that texture filtering will alter your sampled result.
texelFetch (...) lets you fetch an explicit texel in a texture without using normalized coordinates, it is sort of like a "grownup" rectangle texture :) It is generally useful if you are using a multisample texture and want a specific sample, or if you want to bypass texture filtering (which includes mipmap level selection). In this case, it is not needed at all.
This is probably what you really want (OpenGL 3.2):
#version 150
uniform sampler2D mytex;
uniform sampler2D texture1;
layout (location=0) out vec4 frag_color;
layout (location=1) out vec4 mytex_color;
void main ()
{
mytex_color = texture2D (mytex, gl_FragCoord.xy);
// This is not black->blue like you explained in your question...
// ... This is generally opaque->transparent, assuming 4th component = alpha
if (mytex_color == vec4 (0.0,0.0,0.0,1.0)) {
mytex_color = vec4 (0.0);
}
frag_color = texture2D (texture1, gl_TexCoord[0].st);
}
In older GLSL versions, you will have to use glBindFragDataLocation (...) and set the data locations manually or use gl_FragData[n] instead of out variables.
Now the real problem here is that you seem to be wanting to change the color of the texture you are sampling from. That will not work, at best you will have to use two fragment data outputs. Writing into the same texture you are sampling from can be done under some very controlled circumstances, but generally what you would do is ping-pong between textures. In other words, you would fetch from one texture, write to another texture and all subsequent render passes that reference to the original texture should be swapped with the one you just wrote to.
See "Fragment Data Location" for more information on Multiple Render Target drawing.

multiplying sampler lookups glsl

I pass a 1D array as sampler1D and a 2D array (basically a matrix) as sampler2D to my vertex shader.
Everything works fine - i checked the values, every value is where it should be.
BUT - I can't seem to multiply two values of those samplers with each other.
float pos=0.0;
vec4 f = texture1D(xk,ki);
vec4 H = texture2D(er,vec2(0,i));
pos=f[0]*H[0];
colorcheck=pos;
I pass colorcheck to my fragment shader, but it won't render my object, instead everything is just black (passing colorcheck=1.0 works fine). I checked both vectors after the lookup - both have valid values in all fields.
I've tried f.x*H.x, and all combinations I can think of.. I even tried multiplying in the fragment shader - won't work either..
EDIT
simplified vertex shader (doesnt work either/works when I pass colorcheck=1.0/f.x/H.x.. anything)
uniform sampler1D xk;
uniform sampler2D eigenraum;
varying float colorcheck;
void main(){
vec4 f = texture1D(xk,0);
vec4 H = texture2D(eigenraum,vec2(0,0));
colorcheck=f[0]*H[0];
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
and fragment shader:
varying float colorcheck;
void main()
{
gl_FragColor=vec4(colorcheck,1,1,1.0);
}
Thanks for your help!
EDIT2 - turns out I can't substract/add them either..
I found the solution - it's not in the shader code. I forgot the glActiveTexture call when binding the arrays to the textures!