英文:
OpenGL Alpha values having no effect in shader
问题
以下是您要翻译的内容:
我在我的2D游戏中有一个制作扫描线的简单着色器,它运行良好,代码如下:
#ifdef GL_ES
precision mediump float;
#endif
varying vec4 v_color;
varying vec2 v_texCoords;
uniform sampler2D u_texture;
void main() {
vec2 p = vec2(floor(gl_FragCoord.x), floor(gl_FragCoord.y));
if (mod(p.y, 6.0) == 0.0)
gl_FragColor = vec4(0.0, 0.0, 0.0, 0.1);
else
gl_FragColor = v_color * texture2D(u_texture, v_texCoords);
}
但是,如果我在片段颜色的vec4中更改alpha值,效果不会改变,无论在0.1还是1.0时,扫描线都是一样的黑色。我看到其他关于此问题的一些帖子建议启用混合,但我尝试过,但没有效果。
这是我的启用了混合的渲染方法:
@Override
public void render(float delta) {
Gdx.gl.glClearColor(0.0f, 0.0f, 0.0f, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
Gdx.gl.glEnable(GL20.GL_BLEND);
Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
// batch.enableBlending(); 我也尝试过这个,但没有效果
batch.setProjectionMatrix(cam.combined);
batch.setShader(shaderProgram);
batch.begin();
rendup.renderAll(batch); // 渲染所有精灵、瓦片等
batch.setShader(null);
batch.end();
}
英文:
I have a simple shader to make scanlines in my 2d game which works fine and is as follows:
#ifdef GL_ES
precision mediump float;
#endif
varying vec4 v_color;
varying vec2 v_texCoords;
uniform sampler2D u_texture;
void main() {
vec2 p = vec2(floor(gl_FragCoord.x), floor(gl_FragCoord.y));
if (mod(p.y, 6.0)==0.0)
gl_FragColor = vec4(0.0,0.0,0.0, 0.1);
else
gl_FragColor = v_color * texture2D(u_texture, v_texCoords);
}
But if I change the alpha value in the vec4 for the fragment colour, it has no effect, the scanlines are equally black at 0.1 as they are at 1.0. I saw some other questions regarding this which advised to enable blending, but I tried that to no avail.
This is my render method with blending enabled.
@Override
public void render(float delta) {
Gdx.gl.glClearColor(0.0f, 0.0f, 0.0f, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
Gdx.gl.glEnable(GL20.GL_BLEND);
Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
// batch.enableBlending(); tried this too but no effect
batch.setProjectionMatrix(cam.combined);
batch.setShader(shaderProgram);
batch.begin();
rendup.renderAll(batch);//renders all sprites, tiles etc
batch.setShader(null);
batch.end();
}
答案1
得分: 1
这不是混合问题。问题出在你的着色器上,它只会绘制半透明的黑色像素,或者绘制当前绘制的纹理区域的颜色。这些黑色像素会与屏幕上已有的内容混合在一起(在这种情况下是黑色的清除颜色)。
我猜想你实际想要的是扫描线不是纯黑色。因此,你应该在所有地方绘制纹理区域的颜色,并在扫描线所在的地方稍微加深颜色。你不希望修改着色器输出的 alpha 值,否则当精灵重叠时,扫描线在该区域会显得更暗。
所以,像这样修改你的着色器:
#ifdef GL_ES
precision mediump float;
#endif
varying vec4 v_color;
varying vec2 v_texCoords;
uniform sampler2D u_texture;
const float DARK_LINE_BRIGHTNESS = 0.9;
void main() {
vec4 color = v_color * texture2D(u_texture, v_texCoords);
vec2 p = vec2(floor(gl_FragCoord.x), floor(gl_FragCoord.y));
if (mod(p.y, 6.0)==0.0)
gl_FragColor = vec4(color.rgb * DARK_LINE_BRIGHTNESS, color.a);
else
gl_FragColor = color;
}
然而,片段着色器中应该避免使用 if
/else
,因为它在大多数情况下性能较差(例外情况是如果 if
语句对于连续的许多像素评估结果相同,比如使用 if (u_someUniformBoolean)
)。你可以像这样重新编写它:
void main() {
vec4 color = v_color * texture2D(u_texture, v_texCoords);
vec2 p = vec2(floor(gl_FragCoord.x), floor(gl_FragCoord.y));
gl_FragColor = (step(0.01, mod(p.y, 6.0)) * (1.0 - DARK_LINE_BRIGHTNESS) + DARK_LINE_BRIGHTNESS) * color;
}
英文:
This isn't a blending problem. The issue is your shader only draws either a translucent black pixel, or the color of whatever texture region is being drawn. These black pixels are just getting blended with what's already on the screen (in this case the black clear color).
I assume what you actually want here is for the scan lines not to be pure black. So you should be drawing the color of the texture region everywhere, and just darken it slightly where the scan lines are. You don't want to be modifying the alpha that the shader outputs, or when you have overlapping sprites, the scanline will appear darker in that area.
So change your shader like this:
#ifdef GL_ES
precision mediump float;
#endif
varying vec4 v_color;
varying vec2 v_texCoords;
uniform sampler2D u_texture;
const float DARK_LINE_BRIGHTNESS = 0.9;
void main() {
vec4 color = v_color * texture2D(u_texture, v_texCoords);
vec2 p = vec2(floor(gl_FragCoord.x), floor(gl_FragCoord.y));
if (mod(p.y, 6.0)==0.0)
gl_FragColor = vec4(color.rgb * DARK_LINE_BRIGHTNESS, color.a);
else
gl_FragColor = color;
}
However, if
/else
should be avoided in fragment shaders because it performs significantly worse in most cases. (Exception is if the if
statement evaluates to the same value for many pixels in a row, such as with if (u_someUniformBoolean)
.) You could rewrite it like this:
void main() {
vec4 color = v_color * texture2D(u_texture, v_texCoords);
vec2 p = vec2(floor(gl_FragCoord.x), floor(gl_FragCoord.y));
gl_FragColor = (step(0.01, mod(p.y, 6.0)) * (1.0 - DARK_LINE_BRIGHTNESS) + DARK_LINE_BRIGHTNESS) * color;
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论