这不是我所遇到的问题,而是它的简化版本。说,我有一个全屏显示的图像。我想修改此图像的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,所以任何指针都将不胜感激。关于如何解决问题的任何提示都将对我有很大帮助。预先感谢!
答案 0 :(得分:0)
透明度不从屏幕[..]中间开始
因为alpha
是针对每个顶点求值并针对片段进行插值的。
您必须对每个片段进行评估,而不是对每个顶点进行评估。
将coordinates.x
或gl_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
的内插值