问题
I am working on a 3D renderer which was working as expected but now I am trying to batch every cube into a single draw call (my renderer can only draw cubes right now).
Here I have my glsl program that runs for each batch
#type vertex
#version 330 core
layout(location = 0) in vec3 a_Position;
layout(location = 1) in vec4 a_Color;
layout(location = 2) in vec3 a_TexCoord;
layout(location = 3) in int a_TexIndex;
uniform mat4 u_ProjectionView;
out vec4 v_Color;
out vec3 v_TexCoord;
out flat int v_TexIndex;
void main()
{
v_Color = a_Color;
v_TexCoord = a_TexCoord;
v_TexIndex = a_TexIndex;
gl_Position = u_ProjectionView * vec4(a_Position, 1.0);
}
#type fragment
#version 330 core
out vec4 color;
in vec4 v_Color;
in vec3 v_TexCoord;
in flat int v_TexIndex;
uniform samplerCube u_Textures[32];
void main()
{
color = texture(u_Textures[v_TexIndex], v_TexCoord) * v_Color;
}
The only part that does not work is the sampling part at the very end.
When I tested my code, I loaded two textures into the u_Textures
array in the first two indices and tried to draw a cube with the first texture and another cube with the second texture.
If I hardcode an index like this
color = texture(u_Textures[0], v_TexCoord) * v_Color;
Or like this
color = texture(u_Textures[1], v_TexCoord) * v_Color;
The correct texture at index 0 or 1 is sampled but as soon as I place the v_TexIndex
variable, it gives me weird artifacts or just nothing at all.
So I automatically thought that my v_TexIndex
variable must not be what I expect it to be but if I replace the line with
color = vec4(v_TexIndex, 1.0, 1.0, 1.0);
I get a white texture when I expect v_TexIndex
to be 1 and a turquoise when I expect it to be 0!
回答1:
Arrays of samplers (u_Textures
) cannot be indexed by fragment shader inputs such as v_TexIndex
.u_Textures[v_TexIndex]
is undefined behavior, because v_TexIndex
is not Dynamically uniform.
See GLSL version 4.60 (most recent) (from OpenGL Shading Language 4.60 Specification - 4.1.7. Opaque Types):
When aggregated into arrays within a shader, these types can only be indexed with a dynamically uniform expression, or texture lookup will result in undefined values.
In the GLSL version 330, the restriction is even harder. See OpenGL Shading Language 3.30 Specification - 4.1.7 Samplers:
Samplers aggregated into arrays within a shader (using square brackets [ ]) can only be indexed with integral constant expressions.
That clearly explains why the "hardcode" index (u_Textures[0]
, u_Textures[1]
) works, but u_Textures[v_TexIndex]
fails and gives "weird artifacts".
I recommend to use s samplerCubeArray
(see Sampler) rather than an array of samplerCube
.
When you use a samplerCubeArray
, then you don't need any indexing at all, because the "index" is encoded in the 4rd component of the texture coordinate at texture lookup (see texture).
回答2:
I looked at the links that you put in the answer and I did not completely understand how to use samplerCubeArray's; however, I have found a "hack" around my problem and it is by passing the index as a floating point value into the shader program and then texturing like this
color = texture(u_Textures[int(v_TexIndex + 0.5)], v_TexCoord) * v_Color;
来源:https://stackoverflow.com/questions/61873935/why-are-glsl-variables-not-working-as-expected