Javascript WebGL在像素级混合颜色

Javascript WebGL在像素级混合颜色,javascript,canvas,three.js,shader,webgl,Javascript,Canvas,Three.js,Shader,Webgl,我想写一个计算素数的小程序。我的想法是使用webgl/threejs将所有表示素数(基于坐标)的像素涂成白色,其余的涂成黑色。我的问题是WebGL不知何故混合了像素级别的颜色(如果你在黑色画布中间有一个白色像素,它与环境混合,而一个白色像素周围的像素变为灰色)。有了这个问题,我无法正确识别白色和黑色像素 我的问题:我如何告诉webgl或canvas在不混合东西的情况下为每个像素使用正确的颜色 这是一个演示,我将每2个像素涂成白色: <!DOCTYPE html> <html l

我想写一个计算素数的小程序。我的想法是使用webgl/threejs将所有表示素数(基于坐标)的像素涂成白色,其余的涂成黑色。我的问题是WebGL不知何故混合了像素级别的颜色(如果你在黑色画布中间有一个白色像素,它与环境混合,而一个白色像素周围的像素变为灰色)。有了这个问题,我无法正确识别白色和黑色像素

我的问题:我如何告诉webgl或canvas在不混合东西的情况下为每个像素使用正确的颜色

这是一个演示,我将每2个像素涂成白色:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ProjectLaGPU</title>
</head>
<body>
    <script id="vertex-shader" type="x-shader/x-vertex">
        uniform float u_start;

        varying float v_start;

        void main() {
            v_start = u_start;
            gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
        }
    </script>
    <script id="fragment-shader" type="x-shader/x-fragment">
        varying float v_start;

        void main () {
            if (int(gl_FragCoord.x)%2==0 && int(gl_FragCoord.y)%2==0) {
                gl_FragColor = vec4(1, 1, 1, 1);
            } else {
                gl_FragColor = vec4(0, 0, 0, 1);
            }
        }
    </script>
    <script src="https://threejs.org/build/three.js"></script>
    <script src="main.js"></script>
</body>
</html>

这是未配置设备像素比率的典型副作用。这意味着您的应用程序不一定在本机解决方案中运行。下面生成了预期的结果(我制作了一个屏幕截图并检查了Gimp中的颜色值)

const scene=new THREE.scene();
常量摄影机=新的三个正交摄影机(.5、.5、.5、.5、-1、1);
const renderer=new THREE.WebGLRenderer();
const geometry=新的三个.PlaneBufferGeometry();
const material=新的3.ShaderMaterial({
vertexShader:document.getElementById(“顶点着色器”).innerText,
fragmentShader:document.getElementById(“片段着色器”).innerText,
});
常量网格=新的三个网格(几何体、材质);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth、window.innerHeight);
document.body.appendChild(renderer.doElement);
场景.添加(网格)
渲染器。渲染(场景、摄影机)
正文{
保证金:0;
}

void main(){
gl_位置=projectionMatrix*modelViewMatrix*vec4(位置,1.0);
}
空干管(){
if(int(gl_FragCoord.x)%2==0&&int(gl_FragCoord.y)%2==0){
gl_FragColor=vec4(1,1,1,1);
}否则{
gl_FragColor=vec4(0,0,0,1);
}
}

被接受的答案是不正确的,只能靠运气解决。。。换句话说,如果它对你有效,你很幸运,你的机器/浏览器/操作系统/当前设置似乎正常工作。更改一个设置,切换到另一个浏览器/操作系统/机器,它将无法工作

这里有许多问题被混为一谈

1.获取非模糊画布 要得到一张不模糊的画布,你必须做两件事

关闭浏览器的过滤功能 在Chrome/Edge/Safari中,您可以使用firefox上的
canvas{image rendering:pixelated;}
canvas{image rendering:crisp edges;}

请注意,
pixelated
crip edges
更适合这种情况。从规范中,给定此原始图像

并将其显示为浏览器默认算法的3倍大小,但典型示例可能如下所示

像素化
看起来像这样

脆边
看起来像这样


但是请注意,用于绘制图像的实际算法并不是由规范定义的,这要感谢为我工作的规范!这是不正确的,只能靠运气。“我已经做了截图并检查了值”!=它起作用了。下面是我的机器上的示例:您可能需要添加一个
else if(entry.contentBoxSize){
子句,当前FF还没有按顺序传递它,但它确实有它。它与
contentRect
不同吗?
contentRect
正在消失吗?在我的FF上,值确实不同是的,而且我看不到任何东西说
contentRect
会离开。嗯,在我的测试中
contentRect.width
似乎比n
contentBoxSize.inlineSize
。后者似乎被截断了。对我来说,它们的值确实不同,但在5位小数之后。这很奇怪,因为根据规范,它们应该是相同的“内容矩形”…事实上,
.contentRect
在未来可能确实会被弃用,但我希望当浏览器这样做时,它们也会实现devicePixelContentBoxSize,或者至少将contentBoxSize作为一个序列。
/* main.js */
async function init() {
    const scene = new THREE.Scene();
    const camera = new THREE.OrthographicCamera(-.5, .5, .5, -.5, -1, 1);
    const renderer = new THREE.WebGLRenderer({
        preserveDrawingBuffer: true,
        powerPreference: "high-performance",
        depth: false,
        stencil: false
    });

    const geometry = new THREE.PlaneGeometry();
    const material = new THREE.ShaderMaterial({
        uniforms: {
            u_start: { value: 0.5 },
        },
        vertexShader: document.getElementById("vertex-shader").innerText,
        fragmentShader: document.getElementById("fragment-shader").innerText,
      });
    const mesh = new THREE.Mesh(geometry, material);
    renderer.setSize(1000, 1000);
    document.body.appendChild(renderer.domElement);
    scene.add(mesh)
    renderer.render(scene, camera);
}

init();