(self, *, texture=None, width=None, height=None, channels=None, dtype=None, msaa=0)
| 220 | |
| 221 | class Framebuffer: |
| 222 | def __init__(self, *, texture=None, width=None, height=None, channels=None, dtype=None, msaa=0): |
| 223 | self.texture = texture |
| 224 | self.gl_id = None |
| 225 | self.gl_color = None |
| 226 | self.gl_depth_stencil = None |
| 227 | self.msaa = msaa |
| 228 | |
| 229 | # Determine size and dtype. |
| 230 | if texture is not None: |
| 231 | assert isinstance(self.texture, Texture) |
| 232 | self.width = texture.width |
| 233 | self.height = texture.height |
| 234 | self.channels = texture.channels |
| 235 | self.dtype = texture.dtype |
| 236 | else: |
| 237 | assert width is not None and height is not None |
| 238 | self.width = width |
| 239 | self.height = height |
| 240 | self.channels = channels if channels is not None else 4 |
| 241 | self.dtype = np.dtype(dtype) if dtype is not None else np.float32 |
| 242 | |
| 243 | # Validate size and dtype. |
| 244 | assert isinstance(self.width, int) and self.width >= 0 |
| 245 | assert isinstance(self.height, int) and self.height >= 0 |
| 246 | assert isinstance(self.channels, int) and self.channels >= 1 |
| 247 | assert width is None or width == self.width |
| 248 | assert height is None or height == self.height |
| 249 | assert channels is None or channels == self.channels |
| 250 | assert dtype is None or dtype == self.dtype |
| 251 | |
| 252 | # Create framebuffer object. |
| 253 | self.gl_id = gl.glGenFramebuffers(1) |
| 254 | with self.bind(): |
| 255 | |
| 256 | # Setup color buffer. |
| 257 | if self.texture is not None: |
| 258 | assert self.msaa == 0 |
| 259 | gl.glFramebufferTexture2D(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0, gl.GL_TEXTURE_2D, self.texture.gl_id, 0) |
| 260 | else: |
| 261 | fmt = get_texture_format(self.dtype, self.channels) |
| 262 | self.gl_color = gl.glGenRenderbuffers(1) |
| 263 | gl.glBindRenderbuffer(gl.GL_RENDERBUFFER, self.gl_color) |
| 264 | gl.glRenderbufferStorageMultisample(gl.GL_RENDERBUFFER, self.msaa, fmt.internalformat, self.width, self.height) |
| 265 | gl.glFramebufferRenderbuffer(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0, gl.GL_RENDERBUFFER, self.gl_color) |
| 266 | |
| 267 | # Setup depth/stencil buffer. |
| 268 | self.gl_depth_stencil = gl.glGenRenderbuffers(1) |
| 269 | gl.glBindRenderbuffer(gl.GL_RENDERBUFFER, self.gl_depth_stencil) |
| 270 | gl.glRenderbufferStorageMultisample(gl.GL_RENDERBUFFER, self.msaa, gl.GL_DEPTH24_STENCIL8, self.width, self.height) |
| 271 | gl.glFramebufferRenderbuffer(gl.GL_FRAMEBUFFER, gl.GL_DEPTH_STENCIL_ATTACHMENT, gl.GL_RENDERBUFFER, self.gl_depth_stencil) |
| 272 | |
| 273 | def delete(self): |
| 274 | if self.gl_id is not None: |
nothing calls this directly
no test coverage detected