在GLSL ES

时间:2015-07-05 23:12:22

标签: android opengl-es opengl-es-2.0 glsles

我正在使用Android中的OpenGL ES 2创建一个2D游戏,其中包含一个健康栏。随着健康状况的降低,健康栏会在5种颜色之间变化(绿色,黄绿色,黄色,橙色,红色)。健康栏的纹理来自纹理图集,我宁愿不会为每种颜色用条形图弄乱纹理图集(将来更容易改变这些颜色)。

这是我想用GLSL重现的原始绿色。它的基色是#77ee9a。

我尝试过的是创建纹理的黑白版本。基础绿色在这里成为#aeaeae。

然后,我将我想要的颜色与这个黑白图像相乘。我意识到这不会完全正确,所以我采取了我想要的绿色(#77ee9a)并在乘以之前将其除以黑白等效物(#aeaeae)。这导致:

我意识到除以灰色会导致原始绿色的rgb值的绿色部分超过255,从而在图像的明亮部分周围产生伪影。

我不确定是否有更好的方法来实现这种着色效果,但我希望有一个解决方案可以让我这样做。

如果没有,我将能够创建两个纹理,一个是纯白色的条形,另一个是透明效果。然后我可以叠加这些,但它需要另外的纹理和游戏中的另一个精灵。

谢谢!

2 个答案:

答案 0 :(得分:1)

您可以使用GLSL混合函数计算2个单独的渐变:一个从黑色到所选颜色,对应于灰色值0到0.68(#aeaeae),另一个从所选颜色到达白色为灰色值0.68至1.0。

将色调(例如绿色)作为制服传递:

uniform vec4 uTintColor;

读取灰色值并取任何组件(因为它们都是相同的)。然后计算灰度值在每个梯度中的位置并应用它们。当它在较低的渐变中时,upperGradientCol将等于uTintColor,因为upperGradientPos将为零,因此upperGradientCol可以用作较低渐变的上限。

// read grey scale value
vec4 texel = texture2D(uTexture, vTexCoord);
float greyValue = texel.r;

// compute position in gradients:
float upperGradientPos = clamp((greyValue - 0.68) / 0.32, 0.0, 1.0);
float lowerGradientPos = clamp(greyValue / 0.68, 0.0, 1.0);

// apply upper gradient from uTintColor up to white:
vec4 upperGradientCol = mix(uTintColor, vec4(1.0, 1.0, 1.0, 1.0), upperGradientPos);
// apply lower gradient from black up to uTintColor:
vec4 lowerGradientCol = mix(vec4(0.0, 0.0, 0.0, 1.0), upperGradientCol, lowerGradientPos);
gl_FragColor = vec4(lowerGradientCol.rgb, texel.a);

为了使这个更加通用,您可以传递不同的颜色而不是黑色和白色作为制服,并且对应于色调颜色的灰色值(当前硬编码为0.68)相同。

答案 1 :(得分:0)

你实际上可以写一个着色器,所以你只需要一个纹理,它会被修改为:失去的荒地越多,得到的灰色就越多 要获得将使用的“灰色纹理”的颜色值:

Grayvalue = 0,299×Red + 0,587×Green + 0,114×Blue

因此着色器中的公式如下:

Healthpercantage * 0.711 + 0.299,Healthpercantage * 413 + 0,587,Healthpercantage * 0.886 + 0.114