我想调整我的窗口大小,并有我的画布和它的一切拉伸,以填补窗口的扩展/收缩。
这有点棘手,因为在我的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();
在大多数情况下,当绘制到画布时,视口应该始终设置为画布的大小(width
和height
而不是clientWidth
和clientHeight
)。使用clientWidth
和clientHeight
来调整大小和/或计算投影的宽高比,无论该投影是2d还是3d。事实上,用clientWidth
和clientHeight
代替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
设置为你要绘制的表面的大小。
希望这能清楚地说明为什么使用clientWidth
和clientHeight
对gl.viewport
是错误的,因为clientWidth
和clientHeight
与画布的实际大小(其中的像素)没有关系。它们只与这些像素被拉伸或收缩的大小有关。换句话说
<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像素下
就处理调整大小而言,如果你正在不断渲染(看起来像你在你的代码),那么在渲染循环开始时调用调整大小是最简单和最好的。