Opengl es 2.0自定义着色器低帧率(安卓)

3
我正在制作一个简单的应用程序/壁纸,为背景图像添加简单的水波纹效果。
我在HTC Desire(Android 2.2)上进行测试。
我已经找到了如何实现这个效果的解释,并将其实现到了android平台上。链接地址如下:Adrian Boeing: Blog
问题是性能非常低。如果我使用普通着色器来处理静态图片,fps大约为40-50fps。如果我加上计算sinc函数的部分,然后使用新计算出的值来处理纹理,fps会下降到20fps。
问题是我想添加不止一个水波纹,而且随着水波纹数量的增加,fps会减半(例如2个水波纹= 10fps,3个水波纹=5fps等...)。
我是否错误地实现了这个着色器?是否有极大的优化空间,或者类似于这样的效果是以其他方式实现的?
该效果类似于Android上默认的动态壁纸“Water”(秋叶落入涟漪池中)。
以下是我的着色器代码:
    private final String fragmentShaderCode = 
        "precision mediump float;" + 
        "uniform sampler2D uTexture;"+ 
        "varying vec2 vTexCoordinate;"+ 
        "uniform float mTime;"+ //time variable 
        "uniform float offX;"+//center of wave 
        "uniform float offY;"+//center of wave 
        "uniform float size;"+//size of wave (so you can make it smaller over time) 
        "void main() {" + 
        "        vec2 off2 = vec2(offX,offY);"+ 
        "        vec2 cPos = -1.0 + 2.0 * vTexCoordinate.xy;" + //bring coordinate to middle of screen 
        "        vec2 ofvec = cPos+off2;"+ //doda offset 
        "        float r = length(ofvec);"+ //length of vector 
        "        cPos = vTexCoordinate + (size)/(r*2.0)*sin(r*100.0-mTime); "+ //sinc function for wave simulation 
        "        gl_FragColor = texture2D(uTexture,cPos);" + //draw texture 
        "}"; 

注意:我添加了这段代码是为了使其更易于阅读。使用多个触摸事件的代码只是使用 offX、offY 的向量,并在 for 循环中执行下面的代码。
1个回答

3
在片段着色器中进行大量的重计算会严重影响性能。在移动OpenGL ES设备优化中,常见的做法是将繁重的计算转移到顶点着色器中。
在这种情况下,您需要重新考虑着色器的逻辑并修改几何形状。我建议使用足够好的镶嵌网格模拟水波,并改变顶点位置以产生涟漪效果。
或者,您可以保留所有逻辑在片段着色器中,但通过使用带有偏移数据的外部烘焙纹理来改变UV偏移的计算。这样,您将获得相同质量的效果,但性能显着提高。您必须在单独的纹理中存储给定距离的UV增量的烘焙数据,并从该纹理中读取已经预先计算好的值。所有移动设备GPU都至少有2个纹理采样器,因此额外的 texture2D() 调用几乎没有成本。
要了解其工作原理,请阅读此文章http://prideout.net/blog/?p=56。它是关于路径变形的,但您应该查看从纹理中采样特定预计算数据的方法。

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