来自iPhone上GLSL ES 2.0的多点源的2D照明

时间:2012-09-05 16:09:36

标签: iphone c++ opengl-es opengl-es-2.0 cocos2d-x

因为我是一个带有着色器的完整菜鸟我在尝试开始工作时遇到了一些问题,这个系统基本上覆盖了带有透明孔的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);
}

问题在于性能非常糟糕(无法以60fps运行2灯并且屏幕上没有其他内容),是否有任何建议可以让它更好甚至以不同方式解决这个问题?

顺便说一句,我是从cocos2d-x做的,所以如果有人有任何使用cocos2d元素的想法,也会受到欢迎:)

2 个答案:

答案 0 :(得分:2)


  我完全赞同蒂姆。如果你想提高总速度,你必须避免循环。我建议您,如果灯数组大小始终为10,则将循环语句与循环内容的十个副本交换。您应该知道,您在循环语句中声明的任何变量都将在循环结束时释放!所以最好跨越十个部分循环(丑陋,但这是一个老派的伎俩;))))
  此外,我还建议你在每个声明中加入一些println,看看有什么说明乱七八糟。我敢打赌混合操作是罪魁祸首。我对cocos2d一无所知,但是,有可能在流程结束时进行一次独特的调用,以及距离和强度的优化?似乎在某些时候有一个漂亮的浮动消耗烦人的操作

答案 1 :(得分:1)

我会尝试两件事(不保证会提供帮助)

  1. 删除for循环并在两个灯光下进行硬编码。如果驱动程序无法正确处理循环,则循环可能很昂贵。很高兴知道这是否会让你失望。

  2. 如果陈述费用昂贵,我认为这不是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;