渲染到或从中读取?帧缓冲区在移动Safari中不起作用

问题描述

由于某些原因,在移动Safari上似乎无法渲染到帧缓冲区,然后从缓冲区渲染到屏幕。我没有机会查看桌面Safari,但是我的Firefox可以很好地显示Microsoft徽标,在我的手机上我只能看到边框:

const dmnsn = [800,600],glCtx = twgl.getContext(document.createElement("canvas")),imgLc =
    "https://upload.wikimedia.org/wikipedia/commons/b/b6/Microsoft_logo_%281987%29.svg";
var bfInf = twgl.primitives.createXYQuadBufferInfo(glCtx),pgInf = twgl.createProgramInfo(glCtx,["vs","fs"]),imgTx = twgl.createTexture(glCtx,{ src: imgLc },tstSB),scnBf = twgl.createFramebufferInfo(glCtx,[{ wrap: glCtx.REPEAT}],dmnsn[0],dmnsn[1]);

function plcCv() {
  document.body.append(glCtx.canvas);
  glCtx.canvas.width = dmnsn[0];
  glCtx.canvas.height = dmnsn[1];
}
function drwTx(tx,fbi,fy) {
  twgl.bindFramebufferInfo(glCtx,fbi);
  twgl.drawObjectList(glCtx,[
    {
      programInfo: pgInf,bufferInfo: bfInf,uniforms: { u_texture: tx,u_flipy: fy }
    }
  ]);
}
function tstSB() {
  plcCv();
  drwTx(imgTx,scnBf,true);
  drwTx(scnBf.attachments[0],null,false);
}
html{
  height:100%;
}
body{
  margin:0;
  height:100%;
  display: flex;
  align-items: center;
  justify-content: center;
}
canvas{
  border-style:solid;
}
<script id="vs" type="x-shader/x-vertex">
  
  attribute vec4 position;
  attribute vec2 texcoord;
    
  uniform bool u_flipy;
  
  varying vec2 v_texcoord;

  void main() {
    if(u_flipy) {
      v_texcoord = vec2(texcoord.x,1.0 - texcoord.y);
    } else {
      v_texcoord = texcoord;
    }
    gl_Position = position;
  }
</script>
<script id="fs" type="x-shader/x-fragment">
precision mediump float;

varying vec2 v_texcoord;

uniform sampler2D u_texture;

void main() {
  gl_FragColor=texture2D(u_texture,v_texcoord);
}
</script>
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>

我知道绘制SVG只是实验性的,但是在移动Safari上似乎也可以正常工作。

解决方法

检查我看到的Safari中的错误

WebGL:drawElements:绑定到纹理单元0的纹理不可渲染。它可能不是2的幂,并且具有不兼容的纹理过滤或不是“纹理完整”的,或者是具有线性过滤功能且未启用相关的float / half-float线性扩展的float / half-float类型。>

要找出问题所在的纹理,请使用webgl-lint并添加这些行

  const ext = glCtx.getExtension('GMAN_debug_helper');
  const tagObject = ext ? ext.tagObject.bind(ext) : () => {};
  tagObject(imgTx,'imgTx');
  tagObject(scnBf.attachments[0],'colorAttach');

然后我收到此错误

drawElements(TRIANGLES,6,UNSIGNED_SHORT,0)中的错误:统一采样器2D引用的纹理单元0上的纹理WebGLTexture(“ colorAttach”)u_texture无法渲染:纹理的width(800)不是2的幂和height( 600)不是2的幂,但是TEXTURE_WRAP_S(REPEAT)不是CLAMP_TO_EDGE,而TEXTURE_WRAP_T(REPEAT)不是CLAMP_TO_EDGE。 使用WebGLProgram(“ unnamed ”)作为当前程序 绑定了默认的顶点数组

问题是twgl.getContext在Chrome / Firefox上返回WebGL2,但在Safari上仅返回WebGL1(尚不支持WebGL2)

我添加了此webgl-helper以禁用WebGL2,并且在Chrome中出现了相同的错误。

如果您始终只想使用WebGL1,则不要使用twgl.getContext

否则,您可以修复它,更改twgl.createFramebufferInfo的行以设置与WebGL1兼容的参数

  scnBf = twgl.createFramebufferInfo(glCtx,[{ }],dmnsn[0],dmnsn[1]);

IIRC twgl中createFramebufferInfo的默认值为wrap: CLAMP_TO_EDGEminMag: LINEAR

const dmnsn = [800,600],glCtx = twgl.getContext(document.createElement("canvas")),imgLc =
    "https://upload.wikimedia.org/wikipedia/commons/b/b6/Microsoft_logo_%281987%29.svg";
var bfInf = twgl.primitives.createXYQuadBufferInfo(glCtx),pgInf = twgl.createProgramInfo(glCtx,["vs","fs"]),imgTx = twgl.createTexture(glCtx,{ src: imgLc },tstSB),scnBf = twgl.createFramebufferInfo(glCtx,dmnsn[1]);

function plcCv() {
  document.body.append(glCtx.canvas);
  glCtx.canvas.width = dmnsn[0];
  glCtx.canvas.height = dmnsn[1];
}
function drwTx(tx,fbi,fy) {
  twgl.bindFramebufferInfo(glCtx,fbi);
  twgl.drawObjectList(glCtx,[
    {
      programInfo: pgInf,bufferInfo: bfInf,uniforms: { u_texture: tx,u_flipy: fy }
    }
  ]);
}
function tstSB() {
  plcCv();
  drwTx(imgTx,scnBf,true);
  drwTx(scnBf.attachments[0],null,false);
}
html{
  height:100%;
}
body{
  margin:0;
  height:100%;
  display: flex;
  align-items: center;
  justify-content: center;
}
canvas{
  border-style:solid;
}
<script id="vs" type="x-shader/x-vertex">
  
  attribute vec4 position;
  attribute vec2 texcoord;
    
  uniform bool u_flipy;
  
  varying vec2 v_texcoord;

  void main() {
    if(u_flipy) {
      v_texcoord = vec2(texcoord.x,1.0 - texcoord.y);
    } else {
      v_texcoord = texcoord;
    }
    gl_Position = position;
  }
</script>
<script id="fs" type="x-shader/x-fragment">
precision mediump float;

varying vec2 v_texcoord;

uniform sampler2D u_texture;

void main() {
  gl_FragColor=texture2D(u_texture,v_texcoord);
}
</script>
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...