1

因为我是一个完全没有着色器的菜鸟,所以在尝试使用 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);
}

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

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

4

2 回答 2

2


我完全同意蒂姆。如果你想提高总速度,你必须避免 for 循环。我建议您,如果灯光数组大小始终为 10,则将循环语句与循环内容的 10 个副本交换。您应该知道,您在循环语句中声明的任何变量都将在循环结束时被释放!因此,将循环分成十个部分是一个好主意(丑陋,但这是一个老派的把戏;))))
此外,我还建议您在每个语句中添加一些 println ,看看哪些指令在搞乱。我敢打赌,混合操作是罪魁祸首。我对 cocos2d 一无所知,但是,可以在流程结束时进行独特的调用来混合,并总结距离和优势?似乎在某个时候有'

于 2012-09-06T08:04:12.537 回答
1

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

  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;
    
于 2012-09-05T17:07:04.690 回答