iPhone中GLSL ES 2.0上多点光源的2D照明



因为我是一个完全不懂着色器的人,所以我在尝试使用2D照明系统时遇到了一些问题,该系统基本上用2D黑色纹理覆盖屏幕,并在发光区域有透明孔。

由于我只使用一个纹理,我想我必须在碎片着色器中这样做,对吧?

片段着色器:

#ifdef GL_ES
precision mediump float;
#endif
// Texture, coordinates and size
uniform sampler2D u_texture;
varying vec2 v_texCoord;
uniform vec2 textureSize;
uniform int lightCount;
struct LightSource
{
    vec2 position;
    float radius;
    float strength;
};
uniform LightSource lights[10];
void main()
{
    float alpha = 1.0;
    vec2 pos = vec2(v_texCoord.x * textureSize.x, v_texCoord.y * textureSize.y);
    int i;
    for (i = 0; i < lightCount; i++)
    {
        LightSource source = lights[i];
        float distance = distance(source.position, pos);
        if (distance < source.radius)
        {
            alpha -= mix(source.strength, 0.0, distance/source.radius);
        }
    }
    gl_FragColor = vec4(0.0, 0.0, 0.0, alpha);
}

问题是性能真的很糟糕(不能在2盏灯的情况下以60fps的速度运行,屏幕上没有其他东西),有什么建议可以让它变得更好,甚至用不同的方法来解决这个问题吗?

顺便说一句,我是从cocos2d-x开始做这件事的,所以如果有人有任何使用cocos2d元素的想法,那也很受欢迎:)


我完全同意蒂姆的观点。如果你想提高总速度,你必须避免绕圈。我建议您,如果lights数组的大小始终为10,则将循环语句与循环内容的10个副本进行交换。您应该注意,在循环语句中声明的任何变量都将在循环结束时释放!因此,将循环分为十部分是个好主意(很难看,但这是一个老派把戏;))
此外,我还建议你在每一句话中都印上一些println,看看有什么说明在乱写。我敢打赌,混合行动是罪魁祸首。我对椰子2d一无所知,但是,在这个过程结束时,是否可以发出一个独特的混合呼吁,将距离和强度进行汇总?在某个时刻,似乎有一个相当耗时的浮点操作

我会尝试两件事(不能保证有帮助)

  1. 删除for循环,只在两个指示灯中进行硬编码。如果驱动程序没有正确处理For循环,则其成本可能很高。如果知道这是否会让你慢下来,那就太好了。

  2. If语句可能很昂贵,而且我认为这不是mix的一个好应用(您正在做a*(1-c) + 0.0 * c,该术语的后半部分毫无意义)。我可能会尝试替换这个if语句:

    if (distance < source.radius)
    {
        alpha -= mix(source.strength, 0.0, distance/source.radius);
    }
    

    使用这条单行:

    alpha -= (1.0-min(distance/source.radius, 1.0)) * source.strength;
    

最新更新