ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

javascript – 如何在不模糊的情况下拉伸WebGL画布?风格“图像渲染”不起作用

2019-08-27 21:43:01  阅读:255  来源: 互联网

标签:html javascript css webgl canvas


我创建了一个宽度为16且高度为16的画布.然后我使用WebGL渲染图像.这就是它的样子:

enter image description here

之后,我使用宽度:256px和高度:256px来缩放画布.我还将图像渲染设置为像素化:

      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;
      }

这是结果:

enter image description here

图像模糊.为什么?我在OSX Mojave上使用Safari 12.0.2.

解决方法:

Safari尚不支持图像渲染:像素化;在WebGL上. Filed a bug

脆边也不是!=像素化.清晰边缘可以是任何数量的算法.它并不意味着像素化.这意味着应用一些算法,保持清晰的边缘,其中有大量的算法.

The spec itself显示了示例:

鉴于此图片:

enter image description here

这是像素化的:

enter image description here

允许浏览器使用各种算法进行清晰边缘的情况,例如结果可能如此

enter image description here

换句话说,您的CSS可能无法产生您期望的结果.如果浏览器不支持像素化但支持清晰边缘,如果他们使用上面的算法,那么你将不会像素化的外观.

在没有图像渲染的情况下绘制像素化图形的最高效方法:像素化是绘制一个小纹理,然后使用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也不是一个真正的选择.它已被长期弃用,并且像浏览器一样可以解释清晰边缘.

标签:html,javascript,css,webgl,canvas
来源: https://codeday.me/bug/20190827/1745305.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有