opengl - Strange behavior of GLSL array-element-operator on sampler2D array -
i'm writing simple shader , ran strange problem.
i'm rendering bunch of textures using sampler2d array select texture needed.
#version 330 core layout (location = 0) out vec4 color; in data { vec4 position; vec4 color; vec2 texcoord; flat int texid; } fs_in; uniform sampler2d textures[16]; void main() { vec4 texcolor = fs_in.color; if (fs_in.texid > 0) { texcolor = fs_in.color * texture(textures[fs_in.texid - 1], fs_in.texcoord); } color = texcolor; }
this code, however, gives me strange artifacts on textures: image
now here strange part:
replacing
texcolor = fs_in.color * texture(textures[fs_in.texid - 1], fs_in.texcoord);
with following
for (int = 0; < 16; i++) if (fs_in.texid - 1 == i) texcolor = fs_in.color * texture(textures[i], fs_in.texcoord);
fixed problem: image
also, problem appearing on amd based computer using opengl 4.5.13469 compatibility profile context 21.19.525.258
running original program on surface pro works fine.
maybe i'm missing obvious, have no clue why problem occurring or why change fixed it. explanation appreciated.
~ stone
#version 330 core
in glsl 3.30, arrays of samplers can only accessed constant expressions. shader should not have compiled.
but let's pretend hardware supports more glsl 3.30. in case:
textures[fs_in.texid - 1]
in glsl 4.00+, arrays of samplers can only accessed dynamically uniform expressions. , unless you're rendering 1 triangle, or every triangle has same fs_in.texid
value, expression not dynamically uniform. , i'm guessing it's not, since didn't use uniform
.
if index array of opaque types expression not dynamically uniform, undefined behavior.
with following
for (int = 0; < 16; i++) if (fs_in.texid - 1 == i) texcolor = fs_in.color * texture(textures[i], fs_in.texcoord);
even invokes undefined behavior. while expression i
may dynamically uniform, because statement executed conditionally, condition not guarantee value of i
used same invocations within invocation group.
so it's still not dynamically uniform. it's undefined behavior happened work. there's no guarantee work on else.
you can't escape rules; cannot switch texture use in middle of rendering command. if that's want, don't want array of textures; want array texture:
uniform sampler2darray textures; void main() { vec4 texcolor = fs_in.color; if (fs_in.texid > 0) { texcolor = fs_in.color * texture(textures, vec3(fs_in.texcoord, fs_in.texid - 1)); } color = texcolor; }
or, remove condition, make layer 0 of texture contain ones, , fetch texture (since doing conditionally may require manually provide derivatives):
uniform sampler2darray textures; void main() { color = fs_in.color * texture(textures, vec3(fs_in.texcoord, fs_in.texid)); }
Comments
Post a Comment