应用alpha来纹理某个剪辑空间坐标

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了应用alpha来纹理某个剪辑空间坐标相关的知识,希望对你有一定的参考价值。

这不是我的问题,而是它的简化版本。说,我有一个全屏大小的图像显示。我想修改这个图像的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所以任何指针都会非常感激。任何关于如何解决问题的提示对我都有很大的帮助。提前致谢!

答案

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

因为每个顶点评估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的插值。

以上是关于应用alpha来纹理某个剪辑空间坐标的主要内容,如果未能解决你的问题,请参考以下文章

三维渲染引擎设计与实践

Unity3D - 将在 iOS 设备上剪辑纹理的着色器

从剪辑空间到屏幕坐标的转换何时发生?

使用 Alpha 渲染纹理的问题

四元数理论基础与工程应用方向

使用纹理更改帧部分的 alpha 值