【发布时间】:2013-04-03 13:59:37
【问题描述】:
我试图将 vec3 数组作为统一传递,然后在每个像素上迭代它们。数组的大小因情况而异,因此我无法以恒定的迭代次数进行循环。
代码如下:
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,当我添加新粒子时它会改变,所以经常..它可以是 15,然后是 20,然后是 30,然后是 15,我可以将它始终设置为 40,例如但那是低效的。
-
将迭代次数设置为较小的常量时获得更好结果的原因是编译器循环展开和常量数组索引。如果您有动态中断子句,则无法展开循环。您是否在片段着色器 (gl_FragClolor) 中运行提供的代码?如果是,那么计算顶点着色器中的值并将 accum 作为变量传递会更有效。
-
@Kimi,是的,这是一个片段着色器。我正在渲染一个全屏四边形,所以我无法计算顶点的值。我认为有一些解决方案可以解决如何在着色器上实现这种行为,但更有效。我实际上可以保留常量 = 40,但是如果有 10 个粒子,它将进行 30 次迭代。这对性能。
-
另外,我建议在真实设备上进行测试,而忽略您在模拟器中获得的任何性能。 sim 与帧速率无关。它可以更快或更慢。即使在两代不同的设备之间,您也会看到性能差异很大。 iPhone 5 比 iPhone 4 甚至 4S 快得多。
标签: iphone opengl-es opengl-es-2.0 glsl shader