// luma.gl // SPDX-License-Identifier: MIT // Copyright (c) vis.gl contributors import { assert } from '@luma.gl/core'; import { GL } from '@luma.gl/constants'; import { WebGLResource } from "./webgl-resource.js"; import { isRenderbufferFormatSupported } from "../converters/texture-formats.js"; import { convertTextureFormatToGL, getTextureFormatBytesPerPixel } from "../converters/texture-formats.js"; /** * Renderbuffers are GPU objects that contain images. * In contrast to Textures they are optimized for use as render targets, with Framebuffers. * while Textures may not be, and are the logical choice when * you do not need to sample (i.e. in a post-pass shader) * from the produced image. If you need to resample * (such as when reading depth back in a second shader pass), * use Textures instead. * Renderbuffer objects also natively accommodate Multisampling (MSAA). */ export class WEBGLRenderbuffer extends WebGLResource { static defaultProps = { id: undefined, handle: undefined, userData: undefined, format: undefined, // 'depth16unorm' width: 1, height: 1, samples: 0 }; get [Symbol.toStringTag]() { return 'Renderbuffer'; } get width() { return this.props.width; } get height() { return this.props.height; } get format() { return this.props.format; } get samples() { return this.props.samples; } get attachment() { return; } /** WebGL format constant */ glFormat; static isTextureFormatSupported(device, format) { return isRenderbufferFormatSupported(device.gl, format, device._extensions); } constructor(device, props) { // TODO - remove temporary sanity check if (typeof props.format === 'number') { throw new Error('Renderbuffer'); } super(device, props, WEBGLRenderbuffer.defaultProps); this.glFormat = convertTextureFormatToGL(this.props.format); this._initialize(this.props); } resize(size) { // Don't resize if width/height haven't changed if (size.width !== this.width || size.height !== this.height) { Object.assign(this.props, { ...size, format: this.format, samples: this.samples }); this._initialize(this.props); } } // PRIVATE METHODS /** Creates and initializes a renderbuffer object's data store */ _initialize(props) { const { format, width, height, samples } = props; assert(format, 'Needs format'); this.trackDeallocatedMemory(); this.gl.bindRenderbuffer(36161, this.handle); if (samples !== 0) { this.gl.renderbufferStorageMultisample(36161, samples, this.glFormat, width, height); } else { this.gl.renderbufferStorage(36161, this.glFormat, width, height); } this.gl.bindRenderbuffer(36161, null); this.trackAllocatedMemory(width * height * (samples || 1) * getTextureFormatBytesPerPixel(this.format)); } // RESOURCE IMPLEMENTATION _createHandle() { return this.gl.createRenderbuffer(); } _deleteHandle() { this.gl.deleteRenderbuffer(this.handle); this.trackDeallocatedMemory(); } _bindHandle(handle) { this.gl.bindRenderbuffer(36161, handle); } }