【问题标题】:Why is my webgl shader not changing pixel fragments correctly?为什么我的 webgl 着色器没有正确更改像素片段?
【发布时间】:2016-03-10 02:42:32
【问题描述】:

我正在尝试获取片段的位置并更改位置的颜色,但是当我尝试这样做时,我得到了一种奇怪的效果,它们不想完全改变。

注意青色是如何出现的,但那部分应该是透明的。似乎发生了一些奇怪的舍入,我不知道如何解决它。这里发生了什么?

        void main() {
        vec4 c0 = vec4(0,1,0,1);
        c0.a *= step(132.0,gl_FragCoord.x);
        gl_FragColor = c0;
        }

【问题讨论】:

  • 这似乎是 Chrome 浏览器的问题。它在 Firefox 中看起来不错,如果我在 NW.js 应用程序中运行它也看起来不错。我可以在 Chrome 中更改特定设置来解决此问题吗?
  • 可能不相关,但使用整数定义向量分量无法在我的机器上编译。
  • LJ,用整数定义向量分量是完全好的 WebGL 并且有一致性测试。如果这在你的机器上不起作用,你应该提交一个错误。

标签: webgl shader rounding precision pixel


【解决方案1】:

您需要显示更多代码。你启用混合了吗?你选择了什么混合函数和混合方程。你的画布有 alpha 吗?画布的背景是什么颜色,或者它的底色是什么颜色?

这是一个使用您的示例的小程序

"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 将画布与 HTML 合成。在这种情况下,它使用 premultiplied alphared 页面上绘制画布

gl_FragCoord.x 小于 132 这是无效颜色时,您的着色器正在输出 0,1,0,0

我确信这听起来毫无意义,但它无效,因为浏览器需要预乘颜色。由于 alpha 为 0,这意味着 R、G 和 B 不能是零,因为任何东西 * 0 = 0。这是另一种说法,在这种情况下浏览器显示的内容是未定义的,因为它是无效的颜色 结果在每个浏览器中可能会有所不同。

几个选项

  1. 预乘 alpha

    把它放在你的着色器的末尾

    gl_FragColor.rgb *= gl.FragColor.a;
    
  2. 告诉 WebGL 你正在使用未预乘的 alpha

    gl = someCanvas.getContext("webgl", { premultipliedAlpha: false });
    

    在这种情况下,0,1,0,0 是有效的颜色

  3. 如果您不需要 alpha,请将其关闭

    gl = someCanvas.getContext("webgl", { alpha: false });
    

另一个想法是,如果您的画布与显示的大小不同,那么浏览器将绘制过滤后的画布。这些过滤后的像素既不是 0,1,0,0 也不是 0,1,0,1,而是两者之间的双线性插值。

作为示例,让我们制作一个只有 10 像素宽但显示 300 像素宽的画布。我们会将您的更改更改为 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>

【讨论】:

  • 感谢您的精彩解释!解决了这个问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-05-30
  • 1970-01-01
  • 2013-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多