为什么我的 webgl 着色器不能正确改变像素片段?
Why is my webgl shader not changing pixel fragments correctly?
我正在尝试获取片段的位置并更改位置处的颜色,但是当我尝试这样做时,我得到了一个奇怪的效果,它们不想完全改变。
注意有青色,但那部分应该是透明的。似乎发生了一些奇怪的舍入,我不确定如何解决它。这里发生了什么?
void main() {
vec4 c0 = vec4(0,1,0,1);
c0.a *= step(132.0,gl_FragCoord.x);
gl_FragColor = c0;
}
您需要显示更多代码。你启用混合了吗?你选择了什么混合函数和混合方程。你的 canvas 有 alpha 吗? canvas 的背景是什么颜色?
这是一个使用您的示例的小程序
"use strict";
var gl = twgl.getWebGLContext(document.getElementById("c"));
var programInfo = twgl.createProgramInfo(gl, ["vs", "fs"]);
var arrays = {
position: [-1, -1, 0, 1, -1, 0, -1, 1, 0, -1, 1, 0, 1, -1, 0, 1, 1, 0],
};
var bufferInfo = twgl.createBufferInfoFromArrays(gl, arrays);
var uniforms = { };
gl.useProgram(programInfo.program);
twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
twgl.setUniforms(programInfo, uniforms);
twgl.drawBufferInfo(gl, bufferInfo);
html, body {
background: red;
}
<canvas id="c"></canvas>
<script id="vs" type="notjs">
attribute vec4 position;
void main() {
gl_Position = position;
}
</script>
<script id="fs" type="notjs">
precision mediump float;
void main() {
vec4 c0 = vec4(0,1,0,1);
c0.a *= step(132.0,gl_FragCoord.x);
gl_FragColor = c0;
}
</script>
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
WebGL 将 canvas 与 HTML 合成。在这种情况下,它使用 预乘 alpha 在 red
页面
上绘制 canvas
您的着色器在 gl_FragCoord.x
小于 132 时输出 0,1,0,0
,这是无效的颜色 。
我敢肯定这听起来毫无意义,但它无效,因为浏览器需要预乘颜色。由于 alpha 为 0,这意味着 R、G 和 B 不能为零以外的任何值,因为任何 * 0 = 0。这是另一种说法,浏览器在这种情况下显示的内容是未定义的,因为它是无效的颜色 结果每个浏览器可能不同。
几个选项
预乘 alpha
将其放在着色器的末尾
gl_FragColor.rgb *= gl.FragColor.a;
告诉 WebGL 您正在使用未预乘的 alpha
gl = someCanvas.getContext("webgl", { premultipliedAlpha: false });
在那种情况下 0,1,0,0 是有效的颜色
如果不需要 alpha,请将其关闭
gl = someCanvas.getContext("webgl", { alpha: false });
另一个想法是,如果您的 canvas 与显示的大小不同,那么浏览器将绘制 canvas 过滤后的内容。这些过滤后的像素既不是 0,1,0,0 也不是 0,1,0,1,而是两者之间的双线性插值。
例如,让我们制作一个只有 10 个像素但显示 300 个像素的 canvas。我们会将您的更改更改为 3 而不是 132。
"use strict";
var gl = twgl.getWebGLContext(document.getElementById("c"));
var programInfo = twgl.createProgramInfo(gl, ["vs", "fs"]);
var arrays = {
position: [-1, -1, 0, 1, -1, 0, -1, 1, 0, -1, 1, 0, 1, -1, 0, 1, 1, 0],
};
var bufferInfo = twgl.createBufferInfoFromArrays(gl, arrays);
var uniforms = {};
gl.useProgram(programInfo.program);
twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
twgl.setUniforms(programInfo, uniforms);
twgl.drawBufferInfo(gl, bufferInfo);
html, body {
background: red;
}
<canvas id="c" width="10" style="width: 300px; height: 150px;"></canvas>
<script id="vs" type="notjs">
attribute vec4 position;
void main() {
gl_Position = position;
}
</script>
<script id="fs" type="notjs">
precision mediump float;
void main() {
vec4 c0 = vec4(0,1,0,1);
c0.a *= step(3.0,gl_FragCoord.x);
gl_FragColor = c0;
}
</script>
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
我正在尝试获取片段的位置并更改位置处的颜色,但是当我尝试这样做时,我得到了一个奇怪的效果,它们不想完全改变。
注意有青色,但那部分应该是透明的。似乎发生了一些奇怪的舍入,我不确定如何解决它。这里发生了什么?
void main() {
vec4 c0 = vec4(0,1,0,1);
c0.a *= step(132.0,gl_FragCoord.x);
gl_FragColor = c0;
}
您需要显示更多代码。你启用混合了吗?你选择了什么混合函数和混合方程。你的 canvas 有 alpha 吗? canvas 的背景是什么颜色?
这是一个使用您的示例的小程序
"use strict";
var gl = twgl.getWebGLContext(document.getElementById("c"));
var programInfo = twgl.createProgramInfo(gl, ["vs", "fs"]);
var arrays = {
position: [-1, -1, 0, 1, -1, 0, -1, 1, 0, -1, 1, 0, 1, -1, 0, 1, 1, 0],
};
var bufferInfo = twgl.createBufferInfoFromArrays(gl, arrays);
var uniforms = { };
gl.useProgram(programInfo.program);
twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
twgl.setUniforms(programInfo, uniforms);
twgl.drawBufferInfo(gl, bufferInfo);
html, body {
background: red;
}
<canvas id="c"></canvas>
<script id="vs" type="notjs">
attribute vec4 position;
void main() {
gl_Position = position;
}
</script>
<script id="fs" type="notjs">
precision mediump float;
void main() {
vec4 c0 = vec4(0,1,0,1);
c0.a *= step(132.0,gl_FragCoord.x);
gl_FragColor = c0;
}
</script>
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
WebGL 将 canvas 与 HTML 合成。在这种情况下,它使用 预乘 alpha 在 red
页面
您的着色器在 gl_FragCoord.x
小于 132 时输出 0,1,0,0
,这是无效的颜色 。
我敢肯定这听起来毫无意义,但它无效,因为浏览器需要预乘颜色。由于 alpha 为 0,这意味着 R、G 和 B 不能为零以外的任何值,因为任何 * 0 = 0。这是另一种说法,浏览器在这种情况下显示的内容是未定义的,因为它是无效的颜色 结果每个浏览器可能不同。
几个选项
预乘 alpha
将其放在着色器的末尾
gl_FragColor.rgb *= gl.FragColor.a;
告诉 WebGL 您正在使用未预乘的 alpha
gl = someCanvas.getContext("webgl", { premultipliedAlpha: false });
在那种情况下 0,1,0,0 是有效的颜色
如果不需要 alpha,请将其关闭
gl = someCanvas.getContext("webgl", { alpha: false });
另一个想法是,如果您的 canvas 与显示的大小不同,那么浏览器将绘制 canvas 过滤后的内容。这些过滤后的像素既不是 0,1,0,0 也不是 0,1,0,1,而是两者之间的双线性插值。
例如,让我们制作一个只有 10 个像素但显示 300 个像素的 canvas。我们会将您的更改更改为 3 而不是 132。
"use strict";
var gl = twgl.getWebGLContext(document.getElementById("c"));
var programInfo = twgl.createProgramInfo(gl, ["vs", "fs"]);
var arrays = {
position: [-1, -1, 0, 1, -1, 0, -1, 1, 0, -1, 1, 0, 1, -1, 0, 1, 1, 0],
};
var bufferInfo = twgl.createBufferInfoFromArrays(gl, arrays);
var uniforms = {};
gl.useProgram(programInfo.program);
twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
twgl.setUniforms(programInfo, uniforms);
twgl.drawBufferInfo(gl, bufferInfo);
html, body {
background: red;
}
<canvas id="c" width="10" style="width: 300px; height: 150px;"></canvas>
<script id="vs" type="notjs">
attribute vec4 position;
void main() {
gl_Position = position;
}
</script>
<script id="fs" type="notjs">
precision mediump float;
void main() {
vec4 c0 = vec4(0,1,0,1);
c0.a *= step(3.0,gl_FragCoord.x);
gl_FragColor = c0;
}
</script>
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>