Opengl 如何将遮罩应用于具有透明度的纹理以实现“看槽”效果

Opengl 如何将遮罩应用于具有透明度的纹理以实现“看槽”效果,opengl,opengl-es,libgdx,Opengl,Opengl Es,Libgdx,我正在尝试将遮罩应用于具有透明度的纹理。我试图达到的效果是一个有裂缝的物体,你应该能够看到裂缝的底部。我尝试使用混合和帧缓冲区,但没有成功 以下是我正在使用的精灵: 球: (请注意,球周围是透明的) 面具: (遮罩为白色,中间有透明裂缝) 这是我目前得到的结果: 这就是我想要的结果: (这是使用pixmaps完成的,通过检查遮罩中的每个像素,只绘制alpha>0的像素,但速度太慢,在android上会冻结一两秒钟,我无法预加载,因为在需要应用遮罩之前,我不知道要应用遮罩的对象) 这是我的渲染

我正在尝试将遮罩应用于具有透明度的纹理。我试图达到的效果是一个有裂缝的物体,你应该能够看到裂缝的底部。我尝试使用混合和帧缓冲区,但没有成功

以下是我正在使用的精灵:
球:
(请注意,球周围是透明的)
面具:
(遮罩为白色,中间有透明裂缝)

这是我目前得到的结果:

这就是我想要的结果:
(这是使用pixmaps完成的,通过检查遮罩中的每个像素,只绘制alpha>0的像素,但速度太慢,在android上会冻结一两秒钟,我无法预加载,因为在需要应用遮罩之前,我不知道要应用遮罩的对象)

这是我的渲染函数:

@Override
public void render() {
  Gdx.gl.glClearColor(1, 0, 0, 1);
  Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
  batch.begin();

  mBackground.draw(batch);

  batch.setBlendFunction(GL20.GL_ZERO, GL20.GL_SRC_COLOR);
  mMask.draw(batch);

  batch.setBlendFunction(GL20.GL_DST_ALPHA, GL20.GL_ONE_MINUS_DST_ALPHA);
  mObject.draw(batch);

  batch.end();
}
@Override
public void render() {
    Gdx.gl20.glClearColor(0, 0, 0, 1);
    Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT);

    batch.begin();
    mBackground.draw(batch);

    batch.setShader(mShaderProgram);

    Gdx.graphics.getGL20().glActiveTexture(GL20.GL_TEXTURE0);
    mObjectTexture.bind(0);
    mShaderProgram.setUniformi("u_texture", 0);

    Gdx.graphics.getGL20().glActiveTexture(GL20.GL_TEXTURE1);
    mMaskTexture.bind(1);
    mShaderProgram.setUniformi("u_mask", 1);

    Gdx.graphics.getGL20().glActiveTexture(GL20.GL_TEXTURE0);
    batch.draw(mObjectTexture, 0, 0, 500, 500);

    batch.end();
    batch.setShader(null);
}  

我通过使用着色器成功地实现了这一点。以下是我的解决方案:
渲染功能:

@Override
public void render() {
  Gdx.gl.glClearColor(1, 0, 0, 1);
  Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
  batch.begin();

  mBackground.draw(batch);

  batch.setBlendFunction(GL20.GL_ZERO, GL20.GL_SRC_COLOR);
  mMask.draw(batch);

  batch.setBlendFunction(GL20.GL_DST_ALPHA, GL20.GL_ONE_MINUS_DST_ALPHA);
  mObject.draw(batch);

  batch.end();
}
@Override
public void render() {
    Gdx.gl20.glClearColor(0, 0, 0, 1);
    Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT);

    batch.begin();
    mBackground.draw(batch);

    batch.setShader(mShaderProgram);

    Gdx.graphics.getGL20().glActiveTexture(GL20.GL_TEXTURE0);
    mObjectTexture.bind(0);
    mShaderProgram.setUniformi("u_texture", 0);

    Gdx.graphics.getGL20().glActiveTexture(GL20.GL_TEXTURE1);
    mMaskTexture.bind(1);
    mShaderProgram.setUniformi("u_mask", 1);

    Gdx.graphics.getGL20().glActiveTexture(GL20.GL_TEXTURE0);
    batch.draw(mObjectTexture, 0, 0, 500, 500);

    batch.end();
    batch.setShader(null);
}  
顶点着色器:

attribute vec4 a_position;
attribute vec4 a_color;
attribute vec2 a_texCoord0;

uniform mat4 u_projTrans;

varying vec2 v_texCoords;

void main() {
    v_texCoords = a_texCoord0;
    gl_Position = u_projTrans * a_position;
}  
片段着色器:

varying vec2 v_texCoords;
uniform sampler2D u_texture;
uniform sampler2D u_mask;
uniform mat4 u_projTrans;

void main() {
    vec4 texColor = texture2D(u_texture, v_texCoords);
    vec4 maskColor = texture2D(u_mask, v_texCoords);

    gl_FragColor = texColor * maskColor.a;
}

您是否能够在libgdx中提供自定义着色器?如果是,请创建一个从遮罩纹理和球体纹理采样的着色器,以便在片段着色器中应用遮罩。。。这意味着您的遮罩纹理采样必须与球体网格的UV很好地对齐。。。如果这不是一个开始,另一种方法可能是做一个预传递,标记裂缝所在的模具缓冲区(这里的着色器需要丢弃白色碎片),然后使用模具缓冲区遮罩后续渲染。。。只是一些想法-我不熟悉libgdx。另一个可能无法针对您的问题进行扩展的选项是,每个需要破解的纹理都有两个版本。。。一个有裂缝,一个没有。这是纹理组合器的工作,真的。但除非绝对必要,否则我尽量不解释那些讨厌的老东西。着色器是理想的,但这看起来像ES1.x级别的东西。谢谢你的帮助。我设法使用着色器使其工作。但是有一个问题,我如何定位和旋转遮罩?我希望遮罩与球处于相同的位置和角度,但这是不可能的,因为我无法旋转遮罩纹理,我需要绘制它才能旋转它。我现在的做法是:绑定球纹理,绑定遮罩纹理,在选定的位置和角度绘制球,然后着色器片段将接收两个纹理,并且仅在两个纹理的像素都不透明时绘制一个像素。好的,遮罩似乎会自动移动和旋转,问题是我使用的是纹理图集,我猜遮罩与图集对齐,而不是图集中的纹理区域。有没有办法解决这个问题?