Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/397.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 调整画布和webGL纹理的大小_Javascript_Canvas_Resize_Webgl_Feedback Loop - Fatal编程技术网

Javascript 调整画布和webGL纹理的大小

Javascript 调整画布和webGL纹理的大小,javascript,canvas,resize,webgl,feedback-loop,Javascript,Canvas,Resize,Webgl,Feedback Loop,我想调整我的窗口大小,让画布和其中的所有东西随着窗口的扩展/收缩而拉伸填充 这有点棘手,因为在我的webgl代码中,我在帧缓冲区和片段着色器的菊花链之间创建了一个反馈循环。在一个顶点着色器中发生了一个小的变换以保持反馈循环。如果我在resize事件中调用以下命令,它会进行我不希望的额外转换,并使反馈循环失去控制。但是,它会拉伸纹理以适合窗口 gl.viewport(0,0,canvas.clientWidth, canvas.clientHeight); 我还尝试过使用事件侦听器调整画布的大小

我想调整我的窗口大小,让画布和其中的所有东西随着窗口的扩展/收缩而拉伸填充

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

gl.viewport(0,0,canvas.clientWidth, canvas.clientHeight);
我还尝试过使用事件侦听器调整画布的大小,但纹理不会随之调整大小。相反,它们只是锁在我窗口的左下角。检查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代码的页面。为了简单起见,这篇文章没有任何反馈循环,但是如果有帮助的话,我可以发布一篇。提前感谢您的帮助

我不确定我是否理解这个问题,但浏览一下您的代码,如果您的帧缓冲区附件(在本例中为纹理)的大小与画布的大小不同,则每次更改当前帧缓冲区时,都需要调用
gl.viewport

换句话说,在伪代码中

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。事实上,对
gl.viewport
使用
clientWidth
clientHeight
可能是错误的

您可以将
gl.viewport
视为定义要绘制到的区域。将其设置为
gl.viewport(0,0,gl.canvas.width,gl.canvas.height)
基本上是说您希望在整个画布上绘制

但这并不是全部事实
gl.viewport
基本上设置如何将着色器中使用的空间clipspace(-1+1)转换回当前绘图曲面(画布或帧缓冲区)上的像素空间。因此,将视口设置为
gl.viewport(x,y,width,height)
表示-1到+1 in x在当前图形表面上从像素x到x+w-1,而-1到+1 in y在当前图形表面上从像素y到y+height-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);
这意味着画布中只有10x20个实际像素,但在页面上它们被拉伸到30x40。将视口设置为
gl.viewport(0,0,canvas.clientWidth,canvas.clientHeight)
表示您希望绘制到30像素宽、40像素高的区域,但实际上只有10像素宽、20像素低


就处理resize而言,如果您一直在渲染(看起来您在代码中),那么在渲染循环开始时调用resize是最简单也是最好的方法

我不确定我是否理解这个问题,但浏览一下您的代码,如果您的帧缓冲区附件(在本例中为纹理)的大小与画布的大小不同,则每次更改当前帧缓冲区时,都需要调用
gl.viewport

换句话说,在伪代码中

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。事实上,对
gl.viewport
使用
clientWidth
clientHeight
可能是错误的

您可以将
gl.viewport
视为定义要绘制到的区域。将其设置为
gl.viewport(0,0,gl.canvas.width,gl.canvas.height)
基本上是说您希望在整个画布上绘制

但这并不是全部事实
gl.viewport
基本上设置如何将着色器中使用的空间clipspace(-1+1)转换回当前绘图曲面(画布或帧缓冲区)上的像素空间。因此,将视口设置为
gl.viewport(x,y,width,height)
表示-1到+1 in x在当前图形表面上从像素x到x+w-1,而-1到+1 in y在当前图形表面上从像素y到y+height-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);
这意味着只有10x20个实际像素i