OpenGL ES 2.0中等离子体着色器的性能

3

我在我的Android (libGDX)应用程序中使用等离子体着色器,我从这里找到它:

http://www.bidouille.org/prog/plasma

这是我的着色器(稍作修改):

#define LOWP lowp
precision mediump float;
#else
define LOWP
#endif
#define PI 3.1415926535897932384626433832795

uniform float time;
uniform float alpha;
uniform vec2 scale;

void main() {
  float v = 0.0;
  vec2 c = gl_FragCoord.xy * scale - scale/2.0;
  v += sin((c.x+time));
  v += sin((c.y+time)/2.0);
  v += sin((c.x+c.y+time)/2.0);
  c += scale/2.0 * vec2(sin(time/3.0), cos(time/2.0));
  v += sin(sqrt(c.x*c.x+c.y*c.y+1.0)+time);
  v = v/2.0;
  vec3 col = vec3(1, sin(PI*v), cos(PI*v));
  gl_FragColor = vec4(col *.5 + .5, alpha);
}

我正在使用ImmediateModeRendererGL20作为四边形渲染器来呈现它。

然而,对于我的需求来说它显得太慢了。我试图在Nexus 7(第一代)上用着色器填充几乎整个屏幕,但我无法接近60 FPS。

这真的是我第一次涉足GLSL世界,我不知道这些东西通常应该表现如何!

我想知道如何优化这个着色器?我真的不在乎图像质量,可以牺牲它。我得出结论,一种查找表可能是我需要的,或者降低着色器的分辨率..?但我不确定从哪里开始。我仍然非常新于GLSL,“低级”编程从未真正是我的强项,但我渴望至少尝试一下!


1
不想挑剔,但你列出的着色器至少在开头缺少一行。目前看来,你有一个无法匹配的#if/#else/#endif预处理器分支。 - Andon M. Coleman
1
此外,gl_FragCoord.xy 在您的屏幕对齐的四边形上进行插值... 如果您真的不关心图像质量,实际上可以将四边形分成一堆瓷砖,并在顶点着色器中评估它。图像质量和处理时间将随您决定使用的瓷砖数量而增加。 - Andon M. Coleman
请提供顶点着色器和片段着色器。 - keaukraine
1个回答

3

加速计算的终极方法是预先计算计算量大的内容(例如sin()cos()),并将其烘焙到纹理中,然后从中获取准备好的值。这将使它超级快,因为您的着色器不会进行任何重型计算,而是消耗预先计算的值。

正如评论中所述,您可以通过将某些计算移动到顶点着色器来优化性能。例如,您可以将此行移动:

vec2 c = gl_FragCoord.xy * scale - scale/2.0;

要将顶点着色器转换为线性函数,而不会损失任何质量,因此插值不会扭曲它。请按照以下步骤操作:

// vertex
...
uniform float scale;
varying mediump vec2 c;
const float TWO = 2.0;
...
void main() {
    ...
    gl_FragCoord = ...
    c = gl_FragCoord.xy * scale - scale / TWO;
    ...
}

// fragment
...
varying mediump vec2 c;
...
void main() {
    ...
    // just use `c` as usual
    ...
}

此外,请使用常量而不是字面量 - 字面量使用您的统一空间。尽管这可能不会影响性能,但仍然很糟糕(如果您过多使用它们,则可能在某些GPU上用完最大uniforms)。更多信息请参见:在顶点着色器中声明常量而不是字面常量。标准做法还是无谓的严格要求?

谢谢你的回答!我决定尝试查找表,并已成功显示了静态等离子体。如果听起来有点慢,那是因为我有点难以理解时间的概念。如果你(或其他人)能够用查找表解释时间变量出现的理论,那就太好了!谢谢! - user2499946

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接