[英]How to stretch a WebGL canvas without blurring? The style "image-rendering" doesn't work
我创建了一个带有width=16
和height=16
的画布。 然后我使用 WebGL 向它渲染图像。 这是它的样子:
之后,我使用width: 256px
和height: 256px
缩放画布。 我还将image-rendering
设置为pixelated
:
canvas {
image-rendering: optimizeSpeed; /* STOP SMOOTHING, GIVE ME SPEED */
image-rendering: -moz-crisp-edges; /* Firefox */
image-rendering: -o-crisp-edges; /* Opera */
image-rendering: -webkit-optimize-contrast; /* Chrome (and eventually Safari) */
image-rendering: pixelated; /* Chrome */
image-rendering: optimize-contrast; /* CSS3 Proposed */
-ms-interpolation-mode: nearest-neighbor; /* IE8+ */
width: 256px;
height: 256px;
}
这是结果:
图像模糊。 为什么? 我在 OSX Mojave 上使用 Safari 12.0.2。
Safari 尚不支持image-rendering: pixelated;
在 WebGL 上。 提交了一个错误
crisp-edges
也不 != pixelated
。 crisp-edges
可以是任意数量的算法。 这并不意味着pixelated
。 这意味着应用一些算法来保持清晰的边缘,其中有大量的算法。
规范本身显示了示例:
鉴于此图像:
这是pixelated
的:
重要提示:请参阅底部的更新,因为允许浏览器使用各种算法来处理crisp-edges
,例如结果可能是
所以换句话说,你的 CSS 可能不会产生你期望的结果。 如果浏览器不支持像素化但支持清晰边缘,并且如果它们使用上述算法,那么您将不会看到像素化外观。
在没有image-rendering: pixelated
是绘制到一个小纹理,然后使用NEAREST
过滤将该纹理绘制到画布上。
const vs = ` attribute vec4 position; void main() { gl_Position = position; } `; const fs = ` precision mediump float; void main() { gl_FragColor = vec4(1, 0, 0, 1); } `; const screenVS = ` attribute vec4 position; varying vec2 v_texcoord; void main() { gl_Position = position; // because we know position goes from -1 to 1 v_texcoord = position.xy * 0.5 + 0.5; } `; const screenFS = ` precision mediump float; varying vec2 v_texcoord; uniform sampler2D u_tex; void main() { gl_FragColor = texture2D(u_tex, v_texcoord); } `; const gl = document.querySelector('canvas').getContext('webgl', {antialias: false}); // compile shaders, link programs, look up locations const programInfo = twgl.createProgramInfo(gl, [vs, fs]); const screenProgramInfo = twgl.createProgramInfo(gl, [screenVS, screenFS]); const width = 16; const height = 16; const tex = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, tex); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); const fb = gl.createFramebuffer(); gl.bindFramebuffer(gl.FRAMEBUFFER, fb); gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0); // create buffers and put data in const quadBufferInfo = twgl.createBufferInfoFromArrays(gl, { position: { numComponents: 2, data: [ -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1, ], } }); render(); function render() { // draw at 16x16 to texture gl.bindFramebuffer(gl.FRAMEBUFFER, fb); gl.viewport(0, 0, width, height); gl.useProgram(programInfo.program); // bind buffers and set attributes twgl.setBuffersAndAttributes(gl, programInfo, quadBufferInfo); gl.drawArrays(gl.TRIANGLES, 0, 3); // only draw the first triangle // draw texture to canvas gl.bindFramebuffer(gl.FRAMEBUFFER, null); gl.viewport(0, 0, gl.canvas.width, gl.canvas.height); gl.useProgram(screenProgramInfo.program); // bind buffers and set attributes twgl.setBuffersAndAttributes(gl, screenProgramInfo, quadBufferInfo); // uniforms default to 0 so in this simple case // no need to bind texture or set uniforms since // we only have 1 texture, it's on texture unit 0 // and the uniform defaults to 0 gl.drawArrays(gl.TRIANGLES, 0, 6); }
<canvas width="256" height="256"></canvas> <script src="https://twgljs.org/dist/4.x/twgl.min.js"></script>
注意:如果您正在渲染 3D 或出于其他原因需要深度缓冲区,则需要将深度渲染缓冲区附件添加到帧缓冲区。
请注意, optimizeSpeed
也不是一个真正的选择。 它已经被弃用很久了,就像crisp-edges
一样,由浏览器来解释。
规格于 2021 年 2 月更改。 crisp-edges
意思是“使用最近的邻居”,而pixelated
的意思是“让它看起来像素化”,可以翻译为“如果你想做比最近的邻居更好的事情来保持图像像素化”。 看到这个答案
这是一个非常古老的Webkit 错误,发生在 Blink 分叉之前。 从那以后,Blink修复了它,Webkit 仍然没有。
您可能希望通过评论尚未解决的问题让他们知道这仍然是一个问题。
至于解决方法,有几种,但没有完美的。
但这里真正的问题是确定您是否需要这种解决方法。 我认为对这种情况进行功能测试没有任何意义(至少没有 Houdini),因此这意味着您要么必须进行丑陋的用户代理检测,要么将解决方法应用于每个人。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.