调整画布和webGL纹理的大小



我想调整我的窗口大小,并有我的画布和它的一切拉伸,以填补窗口的扩展/收缩。

这有点棘手,因为在我的webgl代码中,我正在创建一个帧缓冲区和片段着色器的菊花链之间的反馈循环。有一个小的转换发生在一个顶点着色器,以保持反馈循环进行。如果我在一个resize事件上调用下面的函数,它会进行一个我不想要的额外转换,并使反馈循环失去控制。但是,它会拉伸纹理以适应窗口。

gl.viewport(0,0,canvas.clientWidth, canvas.clientHeight);

我也试过做一个事件监听器来调整画布的大小,但纹理不随它调整大小。相反,它们一直被锁在我窗户的左下角。检查canvas元素会发现canvas确实改变了大小,但是纹理没有改变。

window.addEventListener( 'resize', resizeCanvas );
function resizeCanvas(){
var width = canvas.clientWidth;
var height = canvas.clientHeight;
if(canvas.width != width ||
 canvas.height != height){
 canvas.width = width;
 canvas.height = height;
 //gl.viewport(0,0,width, height);
 }
}

我想这样做,而不必重新分配我的fbo。出于某种原因,我以为我可以伸展我的画布和它的一切,但我似乎不能让它工作。

这是一个链接到一个页面与我的完整的webgl代码。为了简单起见,这个没有任何反馈循环,但如果有帮助的话,我可以贴一个。提前感谢您的帮助!

我不确定我理解这个问题,但浏览你的代码,如果你的framebuffer附件(在这种情况下纹理)是一个不同的大小比你的画布,你需要调用gl.viewport每次你改变当前的framebuffer。

换句话说在伪代码中

function(render) {
  resizeCanvas();
  gl.bindFramebuffer(gl.FRAMEBUFFER, someFramebuffer);
  gl.viewport(0, 0, widthOfSomeFramebuffer, heightOfSomeFramebuffer);
  drawStuffToFramebuffer();
  gl.bindFramebuffer(gl.FRAMEBUFFER, someOtherFramebuffer);
  gl.viewport(0, 0, widthOfSomeOtherFramebuffer, heightOtherOfSomeFramebuffer);
  drawStuffToOtherFramebuffer();
  gl.bindFramebuffer(gl.FRAMEBUFFER, null);
  gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
  drawStuffToCanvas();
  requestAnimationFrame(render);
}
render();

在大多数情况下,当绘制到画布时,视口应该始终设置为画布的大小(widthheight而不是clientWidthclientHeight)。使用clientWidthclientHeight来调整大小和/或计算投影的宽高比,无论该投影是2d还是3d。事实上,clientWidthclientHeight代替gl.viewport是错误的

你可以把gl.viewport看作是你想要绘制的区域。将其设置为gl.viewport(0, 0, gl.canvas.width, gl.canvas.height)基本上是说你想在整个画布上绘制。

这并不是全部的真相。gl.viewport基本上设置了如何从clipspace (-1 <-> +1)转换,在你的着色器中使用的空间,回到当前绘图表面(画布或framebuffer)上的像素空间。因此,将视口设置为gl.viewport(x, y, width, height)表示x中的-1到+1从当前绘图表面的x像素到x + w -1, y中的-1到+1从当前绘图表面的y像素到y +高度-1。

由于在大多数情况下你想绘制整个绘图表面,你需要将gl.viewport设置为你要绘制的表面的大小。

希望这能清楚地说明为什么使用clientWidthclientHeightgl.viewport是错误的,因为clientWidthclientHeight与画布的实际大小(其中的像素)没有关系。它们只与这些像素被拉伸或收缩的大小有关。换句话说

<canvas width="10" height="20" style="width: 30px; height: 40px"></canvas>
...
console.log("canvas.width       : " + canvas.width);
console.log("canvas.height      : " + canvas.height);
console.log("canvas.clientWidth : " + canvas.clientWidth);
console.log("canvas.clientHeight: " + canvas.clientHeight);

将打印

canvas.width       : 10
canvas.height      : 20
canvas.clientWidth : 30
canvas.clientHeight: 40

这意味着画布上只有10x20的实际像素,但它们在页面上被拉伸到30x40。将视口设置为gl.viewport(0, 0, canvas.clientWidth, canvas.clientHeight)意味着你想绘制一个宽30像素,高40像素的区域但实际上你只有10像素宽20像素下

就处理调整大小而言,如果你正在不断渲染(看起来像你在你的代码),那么在渲染循环开始时调用调整大小是最简单和最好的。

相关内容

  • 没有找到相关文章

最新更新