Opengl ES 2.0 shader - discard pixels with alpha == 0 without discard and if
我的片段着色器做两件事:
但是,如果我在具有alpha == 0.0的像素的图像上应用此着色器,则我在第二种情况下会遇到问题。我希望这些像素是不可见的,但它们也是彩色的。在第一种情况下,我没有这个问题。我需要舍弃alpha == 0
的像素
例如:
我的人剪影纹理应该着色,但是应该跳过透明像素。
在程序开始时我设置了:
1 2 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); |
这是我的片段着色器:
1 2 3 4 5 6 7 | void main() { vec4 c = vec4(v_Color); vec4 p = texture2D( s_texture, v_texCoord); gl_FragColor = mix(p, c, c.a); } |
但是,如果我添加" discard",则所有的工作都可以正常进行。具有alpha == 0.0的像素将被删除。但是我正在使用OpenGL ES 2.0,着色器将在不同的android设备上运行,并且我了解了由" if"和" discard"引起的可能的性能问题。这就是为什么我使用" mix "而不是" if "的原因。
1 2 3 4 5 6 7 8 9 10 11 | void main() { vec4 c = vec4(v_Color); vec4 p = texture2D( s_texture, v_texCoord); if (p.a == 0.0) { discard; } gl_FragColor = mix(p, c, c.a); } |
我尝试了另一种解决方法。我记得原始的Alpha纹理,并在最后应用了它。但这仍然给我怪异的结果。 gl_FragColor.a = backup_alpha对结果alpha进行了某些处理,它在某种程度上是透明的,但并不完全。
1 2 3 4 5 6 7 8 9 | void main() { vec4 c = vec4(v_Color); vec4 p = texture2D( s_texture, v_texCoord); float backup_alpha = p.a; gl_FragColor = mix(p, c, c.a); gl_FragColor.a = backup_alpha; } |
感谢@ Rabbid76的帮助,这是正确的:
1 | gl_FragColor = vec4(mix(p.rgb, c.rgb*p.a, c.a), p.a); |
当你做
1 gl_FragColor = mix(p, c, c.a);
然后,如果
您必须混合使用纹理和颜色的
1 | gl_FragColor = vec4(mix(p.rgb, c.rgb, c.a), p.a); |
如果颜色应为黑色(即部分),其中纹理的alpha通道为0.0,则在混合之前,必须将颜色乘以纹理的alpha通道:
1 | gl_FragColor = vec4(mix(p.rgb, c.rgb*p.a, c.a), p.a); |
但是请注意,由于纹理过滤的原因,可能会发生某些从纹理为红色的颜色完全透明的现象。如果希望输出颜色是完全不透明或完全透明,则必须将alpha通道与阈值进行比较。这可以通过glsl函数
1 | gl_FragColor = vec4(mix(p.rgb, c.rgb, c.a), step(0.5, p.a)); |
s>
s>