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