渲染到(或读取?)帧缓冲区在移动 Safari 中不起作用
Rendering to (or reading from?) framebuffer doesn't work in mobile Safari
出于某种原因,渲染到帧缓冲区然后从缓冲区渲染到屏幕似乎无法在移动版 Safari 上运行。我没有机会检查桌面 Safari,但我的 Firefox 可以很好地呈现 Microsoft 徽标,在我的 phone 上我只看到边框:
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: texture bound to texture unit 0 is not renderable. It maybe non-power-of-2 and have incompatible texture filtering or is not 'texture complete', or it is a float/half-float type with linear filtering and without the relevant float/half-float linear extension enabled.
为了找出问题出在哪个纹理上,使用了 webgl-lint 并添加了这些行
const ext = glCtx.getExtension('GMAN_debug_helper');
const tagObject = ext ? ext.tagObject.bind(ext) : () => {};
tagObject(imgTx, 'imgTx');
tagObject(scnBf.attachments[0], 'colorAttach');
然后我得到这个错误
error in drawElements(TRIANGLES, 6, UNSIGNED_SHORT, 0): texture WebGLTexture("colorAttach") on texture unit 0 referenced by uniform sampler2D u_texture is not renderable: texture's width(800) is not a power of 2 and height(600) is not a power of 2 but TEXTURE_WRAP_S (REPEAT) is not CLAMP_TO_EDGE and TEXTURE_WRAP_T (REPEAT) is not CLAMP_TO_EDGE.
with WebGLProgram("unnamed") as current program
with the default vertex array bound
问题是 twgl.getContext
returns 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_EDGE
、minMag: 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[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>
出于某种原因,渲染到帧缓冲区然后从缓冲区渲染到屏幕似乎无法在移动版 Safari 上运行。我没有机会检查桌面 Safari,但我的 Firefox 可以很好地呈现 Microsoft 徽标,在我的 phone 上我只看到边框:
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: texture bound to texture unit 0 is not renderable. It maybe non-power-of-2 and have incompatible texture filtering or is not 'texture complete', or it is a float/half-float type with linear filtering and without the relevant float/half-float linear extension enabled.
为了找出问题出在哪个纹理上,使用了 webgl-lint 并添加了这些行
const ext = glCtx.getExtension('GMAN_debug_helper');
const tagObject = ext ? ext.tagObject.bind(ext) : () => {};
tagObject(imgTx, 'imgTx');
tagObject(scnBf.attachments[0], 'colorAttach');
然后我得到这个错误
error in drawElements(TRIANGLES, 6, UNSIGNED_SHORT, 0): texture WebGLTexture("colorAttach") on texture unit 0 referenced by uniform sampler2D u_texture is not renderable: texture's width(800) is not a power of 2 and height(600) is not a power of 2 but TEXTURE_WRAP_S (REPEAT) is not CLAMP_TO_EDGE and TEXTURE_WRAP_T (REPEAT) is not CLAMP_TO_EDGE. with WebGLProgram("unnamed") as current program with the default vertex array bound
问题是 twgl.getContext
returns 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_EDGE
、minMag: 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[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>