我想传递一个统一的vec3数组,然后在每个像素上遍历它们。数组的大小因情况而异,所以我无法使循环的迭代次数保持不变。iPhone GLSL动态分支问题
下面是代码:
precision highp float;
precision highp int;
varying vec4 v_fragmentColor;
varying vec4 v_pos;
uniform int u_numberOfParticles;
const int numberOfAccumsToCapture = 3;
const float threshold = 0.15;
const float gooCoeff = 1.19;
uniform mat4 u_MVPMatrix;
uniform vec3 u_waterVertices[100];
void main()
{
vec4 finalColor = vec4(0.0, 0.0, 0.0, 0.0);
vec2 currPos = v_pos.xy;
float accum = 0.0;
vec3 normal = vec3(0, 0, 0);
for (int i = 0; i < u_numberOfParticles; ++i)
{
vec2 dir2 = u_waterVertices[i].xy - currPos.xy;
vec3 dir3 = vec3(dir2, 0.1);
float q = dot(dir2, dir2);
accum += u_waterVertices[i].z/q;
}
float normalizeToEdge = 1.0 - (accum - threshold)/2.0;
if (normalizeToEdge < 0.4)
finalColor = vec4(0.1, normalizeToEdge + 0.5, 0.9-normalizeToEdge*0.4, 1.0);
if (normalizeToEdge < 0.2)
{
finalColor = vec4(120.0/255.0, 245.0/255.0, 245.0/255.0, 1.0);
float shade = mix(0.7, 1.0, normal.x);
finalColor *= shade;
}
gl_FragColor = vec4(finalColor);
}
的问题是在这里:
for (int i = 0; i < u_numberOfParticles; ++i)
{
vec2 dir2 = u_waterVertices[i].xy - currPos.xy;
vec3 dir3 = vec3(dir2, 0.1);
float q = dot(dir2, dir2);
accum += u_waterVertices[i].z/q;
}
当我做for循环这样
for (int i = 0; i < 2; ++i)
{
//...
}
我得到双倍帧速率,甚至虽然u_numberOfParticles也是2
使它像这样
for (int i = 0; i < 100; ++i)
{
if (i == u_numberOfParticles)
break;
//...
}
没有改善。
我知道应对这种情况的唯一方法是创建多个着色器。但是数组的大小可能在1到40之间变化,并且由于for循环是愚蠢的,所以可以制作40个不同的着色器。任何帮助或想法如何处理这种情况?
u_numberOfParticles多久更改一次?你可以在运行期间设置一次吗? – Kimi
@Kimi,当我添加新的粒子时,它会发生变化,所以很常见。它可以是15,然后是20,然后是30,然后是15,我可以将它总是设置为40。但效率不高。 – Terko
将迭代次数设置为一个小常数时,您获得更好结果的原因是编译器循环展开和常量数组索引。如果您有动态断点子句,则循环无法展开。你在片段着色器(gl_FragClolor)中运行提供的代码吗?如果是,则计算顶点着色器中的值并将累加值作为变量传递将会更有效。 – Kimi