android - 如何在不剪裁基础纹理的情况下将纹理叠加在另一个纹理上?

标签 android opengl-es shader opengl-es-2.0

我已经编写了这个简单的着色器来将纹理覆盖在另一个(基础)纹理上 -

 varying highp vec2 textureCoordinate;
 varying highp vec2 textureCoordinate2;

 uniform sampler2D inputImageTexture;
 uniform sampler2D inputImageTexture2;

 void main()
 {
     mediump vec4 base = texture2D(inputImageTexture, textureCoordinate);
     mediump vec4 overlay = texture2D(inputImageTexture2, textureCoordinate2);

     mediump float ra = (overlay.a) * overlay.r + (1.0 - overlay.a) * base.r;
     mediump float ga = (overlay.a) * overlay.g + (1.0 - overlay.a) * base.g;
     mediump float ba = (overlay.a) * overlay.b + (1.0 - overlay.a) * base.b;

     gl_FragColor = vec4(ra, ga, ba, 1.0);
 }

问题 - 除一个问题外,此方法有效。如果叠加图像小于基础图像,则叠加图像的外部区域的 alpha 值为 1.0,即 overlay.a == 1.0。因此,基本图像被叠加图像裁剪。覆盖层外的区域显示为黑色。

我是 opengl 的新手,并期望在其边界之外,纹理的 alpha 应该显示为 0.0?如何修复我的着色器代码以实现所需的行为?或者我是否需要修改我的图形管道?

编辑 下面的顶点着色器-

attribute vec4 inputTextureCoordinate2;

varying vec2 textureCoordinate;
varying vec2 textureCoordinate2;

void main()
{
    gl_Position = pos;
    textureCoordinate = uv;
    textureCoordinate2 = inputTextureCoordinate2.xy;
}

最佳答案

I was expecting that outside its bounds, the texture's alpha should appear as 0.0

您如何对边界外的纹理进行采样?对纹理进行采样时,uv 坐标的范围应为 0 到 1。如果坐标超出此范围,则会发生以下两种情况之一:

  • 如果设置了 GL_CLAMP_TO_EDGE,则坐标将被限制在 (0, 1) 范围内,您将对边缘像素进行采样
  • 如果 GL_REPEAT 被设置,那么坐标的小数部分将被获取,并且您将在纹理中间的某处采样

参见 the docs有关更多详细信息,请访问 glTexParameter。

如果您的用例只是简单地叠加图像,也许您应该尝试编写一个 pixel shader .

  • 将视口(viewport)设置为基本图像尺寸并从 (-1, 1) 绘制四边形。
  • 您的 fragment 着色器现在将对每个像素(称为纹素)进行操作。使用 gl_FragCoord
  • 获取纹素
  • 通过纹素对基底和叠加层进行采样,例如使用 texelFetch
  • 如果纹理元素在叠加层之外,则将叠加层的 rgba 值设置为 0

例如

//fragment shader
uniform ivec2 overlayDim;
uniform sampler2D baseTexture;
uniform sampler2D overlayTexture;

void main() {
   vec2 texelf = floor(gl_FragCoord.xy);
   ivec2 texel = (int(texelf.x), int(texelf.y));

  vec4 base = texelFetch(baseTexture, texel, 0);
  vec4 overlay = texelFetch(overlayTexture, texel, 0);

  float overlayIsValid = float(texel.x < overlayDim.x && texel.y < overlayDim.y);

  overlay *= overlayIsValid;

  //rest of code
}

关于android - 如何在不剪裁基础纹理的情况下将纹理叠加在另一个纹理上?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35849939/

相关文章:

ios - 在顶点着色器中创建纹理并传递给片段以实现使用 Metal 涂抹画笔?

ios - 如何使用 Metal 将纹理缓冲区数据传递给着色器?

android - 使用自定义图标字体时如何修复 Android Lollipop 中的字体基线?

安卓平面按钮

ios - 扩展 EXT_shader_texture_lod 不适用于 OpenGL ES 3.0 iOS

ios - 在 iOS 5.1 上的 OpenGL ES 应用程序中,它们真的使用它们声明的顶点数组吗?

android - Unity手游卡顿+profiler帮助

java - 如何缓存 Json 数据以供离线使用?

java - 如何使用 Android setTranslation ? (或另一种移动 TextView 的方法?)

java - OpenGL雾是基于Z轴而不是深度