목차

WebGL2Fundamentals.org

Fix, Fork, Contribute

WebGL2 Framebuffer

이 글은 WebGL에서 framebuffer가 무엇인지에 대한 대략적인 이미지를 제공할 겁니다. Framebuffer는 텍스처에 렌더링할 때 언급되는데요.

Framebuffer는 그냥 attachment collection입니다. 그게 전부에요! 텍스처와 renderbuffer로 렌더링하는데 사용되죠.

이런식으로 framebuffer 객체를 생각하실 수 있으며

class Framebuffer {
  constructor() {
    this.attachments = new Map();  // attachment point별 attachment
    this.drawBuffers = [gl.COLOR_ATTACHMENT0, gl.NONE, gl.NONE, gl.NONE, ...];
    this.readBuffer = gl.COLOR_ATTACHMENT0,
  }
}

그리고 WebGL2RenderingContext(gl 객체)는 이렇게

// 의사 코드
gl = {
  drawFramebufferBinding: defaultFramebufferForCanvas,
  readFramebufferBinding: defaultFramebufferForCanvas,
}

바인딩 포인트는 2개입니다. 이런식으로 설정되는데

gl.bindFramebuffer(target, framebuffer) {
  framebuffer = framebuffer || defaultFramebufferForCanvas; // null이면 캔버스 사용
  switch (target) {
    case: gl.DRAW_FRAMEBUFFER:
      this.drawFramebufferBinding = framebuffer;
      break;
    case: gl.READ_FRAMEBUFFER:
      this.readFramebufferBinding = framebuffer;
      break;
    case: gl.FRAMEBUFFER:
      this.drawFramebufferBinding = framebuffer;
      this.readFramebufferBinding = framebuffer;
      break;
    default:
      ... error ...
  }
}

framebufferTexture2D, framebufferRenderbuffer, framebufferTextureLayer, 3개의 함수를 통해 attachment를 framebuffer에 추가할 수 있습니다.

구현이 이런식으로 되어 있을 것이라 상상할 수 있는데

// 의사 코드
gl._getFramebufferByTarget(target) {
  switch (target) {
    case gl.FRAMEBUFFER:
    case gl.DRAW_FRAMEBUFFER:
      return this.drawFramebufferBinding;
    case gl.READ_FRAMEBUFFER:
      return this.readFramebufferBinding;
  }
}
gl.framebufferTexture2D(target, attachmentPoint, texTarget, texture, mipLevel) {
  const framebuffer = this._getFramebufferByTarget(target);
  framebuffer.attachments.set(attachmentPoint, {
    texture, texTarget, mipLevel,
  });
}
gl.framebufferTextureLayer(target, attachmentPoint, texture, mipLevel, layer) {
  const framebuffer = this._getFramebufferByTarget(target);
  framebuffer.attachments.set(attachmentPoint, {
    texture, texTarget, mipLevel, layer
  });
}
gl.framebufferRenderbuffer(target, attachmentPoint, renderbufferTarget, renderbuffer) {
  const framebuffer = this._getFramebufferByTarget(target);
  framebuffer.attachments.set(attachmentPoint, {
    renderbufferTarget, renderbuffer
  });
}

이렇게 구현되어 있을 것이라 상상할 수 있는 gl.drawBuffers로 drawing buffer 배열을 설정할 수 있는데

// 의사 코드
gl.drawBuffers(drawBuffers) {
  const framebuffer = this._getFramebufferByTarget(gl.DRAW_FRAMEBUFFER);
  for (let i = 0; i < maxDrawBuffers; ++i) {
    framebuffer.drawBuffers[i] = i < drawBuffers.length
        ? drawBuffers[i]
        : gl.NONE
  }
}

And you can set the read buffer with gl.readBuffer

// pseudo code
gl.readBuffer(readBuffer) {
  const framebuffer = this._getFramebufferByTarget(gl.READ_FRAMEBUFFER);
  framebuffer.readBuffer = readBuffer;
}

중요한 건 framebuffer는 단순한 attachment 모음이라는 겁니다. 문제는 attachment가 될 수 있는 것들과 작동하는 조합에 대한 제한인데요. 예를 들어 floating point texture attachment는 기본적으로 렌더링될 수 없습니다. extension은 EXT_color_buffer_float같은 걸 활성화할 수 있습니다. 마찬가지로 2개 이상의 attachment가 있다면 모두 동일한 넓이여야 합니다.

이슈나 버그가 있나요? 깃헙에서 이슈 만들기.
comments powered by Disqus