【问题标题】:Apply alpha to texture at certain clipspace coordinates在某些剪辑空间坐标处将 alpha 应用于纹理
【发布时间】:2019-08-24 19:42:04
【问题描述】:

这不完全是我遇到的问题,而是它的简化版本。说,我有一个全屏尺寸的图像显示。我想修改此图像的 alpha,以便在屏幕的左半部分(水平),alpha 为 0.5,而在右半部分,alpha 为 1。只有 alpha 0.5 或 1,中间没有其他内容。

到目前为止,这是我的(失败的)代码

这是我设置 webgl 的 javascript 代码

this.gl = canvas.getContext('webgl', {
    alpha: false,
});
this.gl.enable(this.gl.BLEND);
this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA);
this.gl.clearColor(1, 0, 0, 0); // red to highlight alpha problem

这是我的顶点着色器代码

mediump float;
attribute vec2 coordinates;
attribute vec2 a_texcoord;

varying vec2 v_texcoord;
varying float alpha;

void main() {
    gl_Position = vec4(coordinates.x, coordinates.y, 1.0, 1.0);
    v_texcoord = a_texcoord;
    if (coordinates.x <= 0) {
        alpha = 0.5;
    } else {
        alpha = 1.0;
    }
}    

我的片段着色器是标准的简单

precision mediump float;
varying vec2 v_texcoord;
varying float alpha;
uniform sampler2D u_texture;
void main() {
    vec4 color = texture2D(u_texture, v_texcoord).rgba;
    gl_FragColor = color;
}

在绘制时

window.canvas.gl.clear(window.canvas.gl.COLOR_BUFFER_BIT);
window.canvas.gl.useProgram(this.drawProgram);
window.canvas.gl.bindBuffer(window.canvas.gl.ARRAY_BUFFER, this.vertexBuffer);
window.canvas.gl.enableVertexAttribArray(this.positionLocation);
window.canvas.gl.vertexAttribPointer(this.positionLocation, 2, window.canvas.gl.FLOAT, false, 0, 0);
window.canvas.gl.bindBuffer(window.canvas.gl.ARRAY_BUFFER, null);
window.canvas.gl.bindBuffer(window.canvas.gl.ARRAY_BUFFER, this.texcoordBuffer);
window.canvas.gl.enableVertexAttribArray(this.texcoordLocation);
window.canvas.gl.vertexAttribPointer(this.texcoordLocation, 2, window.canvas.gl.FLOAT, false, 0, 0);
window.canvas.gl.bindBuffer(window.canvas.gl.ARRAY_BUFFER, null);

window.canvas.gl.bindTexture(window.canvas.gl.TEXTURE_2D, this.texture);
window.canvas.gl.uniform1i(this.textureLocation, 0);
window.canvas.gl.drawArrays(window.canvas.gl.TRIANGLES, 0, 6);

使用这些代码,我无法实现我想要的。首先,透明度不是从屏幕中间开始(剪辑空间 x = 0),而是从看似随机的位置开始。此外,从 alpha 1.0 逐渐下降到 alpha 0.5,而不仅仅是我希望的 2 个值 0.5 和 1.0。而且我不知道这种逐渐过渡从何而来。

显然我正在学习 webgl,所以任何指针都会非常感激。任何有关如何解决问题的提示都会对我有很大帮助。提前致谢!

【问题讨论】:

  • 您可能会发现these articles 很有帮助
  • 你好!谁想学习 webgl 但没有去过你的网站? :)) '红色突出显示 alpha 问题' 直接来自您。非常感谢你所有的好文章!但我想我只是一个坏学生,跳过了关于顶点插值的部分:P

标签: javascript glsl webgl textures shader


【解决方案1】:

透明度不是从屏幕中间开始的 [..]

因为alpha 是针对每个顶点进行评估并针对片段进行插值的。

您必须对每个片段而不是每个顶点进行评估。

coordinates.xgl_Position.x/gl_Position.w 从顶点着色器传递到片段着色器:

mediump float;
attribute vec2 coordinates;
attribute vec2 a_texcoord;

varying vec2  v_texcoord;
varying vec2  pos;

void main() {
    gl_Position = vec4(coordinates.xy, 1.0, 1.0);
    v_texcoord = a_texcoord;
    pos        = coordinates.xy;
}    

在片段着色器中计算 alpha 值:

precision mediump float;

varying vec2 v_texcoord;
varying vec2 pos;

uniform sampler2D u_texture;

void main() {
    vec4 color = texture2D(u_texture, v_texcoord).rgba;
    float alpha = pos.x < 0.5 ? 0.5 : 1.0; 
    gl_FragColor = vec4(color.rgb, color.a * alpha);  
}

注意,顶点着色器对每个顶点坐标执行一次。坐标定义了图元的角。为每个片段执行片段着色器。顶点着色器的输出参数根据片段在图元上的位置进行插值。插值是片段着色器的输入。
如果在顶点着色器中计算alpha,则左侧片段的alpha 值为0.5,右侧为1.0。中间的片段在 [0.5, 1.0] 范围内得到一个平滑的插值。
当位置从顶点着色器传递到片段着色器时,也会发生同样的情况。但是由于alpha是在片段着色器中计算出来的,所以每个片段的alpha值要么是0.5要么是1.0,取决于pos.x的插值

【讨论】:

  • 感谢您的回答。但是,正如标题中提到的,我想基于剪辑空间坐标,而不是纹理坐标。上面的问题只是一个简化版本,我原来的问题真的取决于剪辑空间坐标。很抱歉没有在问题本身中再次提及它。如果你知道怎么做,请帮忙!
  • Buggy 好的,所以您必须将位置从顶点着色器传递到片段着色器。计算每个片段而不是每个顶点的 alpha。
  • 谢谢@Rabbid76!我按照您的指示解决了示例和我原来的问题!竖起大拇指!我接受了你的回答。但是,如果你有时间,你能解释一下我之前失败的原因吗?我刚刚根据坐标.x 计算了顶点着色器中的 alpha,然后将 alpha 传递给片段着色器。我没有在顶点分配它,但仍然没有达到预期的结果。是不是因为坐标.x(甚至 gl_Position.x / gl_Position.w)还没有真正在剪辑空间中?
  • @Buggy 我试图在答案中解释它。请参阅我现在添加的最后一部分。
  • @Rabbit76 你的回答现在解释了一切!一切。非常感谢您的耐心和大力帮助!干杯!
猜你喜欢
  • 1970-01-01
  • 2020-05-24
  • 1970-01-01
  • 2013-09-23
  • 2017-03-27
  • 2022-01-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多