render-target.ts 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /**
  2. * Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. */
  6. import { idFactory } from '../../mol-util/id-factory';
  7. import { createNullTexture, Texture, TextureFilter } from './texture';
  8. import { createNullFramebuffer, Framebuffer } from './framebuffer';
  9. import { WebGLResources } from './resources';
  10. import { GLRenderingContext, isWebGL2 } from './compat';
  11. const getNextRenderTargetId = idFactory();
  12. export interface RenderTarget {
  13. readonly id: number
  14. readonly texture: Texture
  15. readonly framebuffer: Framebuffer
  16. getWidth: () => number
  17. getHeight: () => number
  18. /** binds framebuffer */
  19. bind: () => void
  20. setSize: (width: number, height: number) => void
  21. reset: () => void
  22. destroy: () => void
  23. }
  24. export function createRenderTarget(gl: GLRenderingContext, resources: WebGLResources, _width: number, _height: number, depth = true, type: 'uint8' | 'float32' | 'fp16' = 'uint8', filter: TextureFilter = 'nearest'): RenderTarget {
  25. const framebuffer = resources.framebuffer();
  26. const targetTexture = type === 'fp16'
  27. ? resources.texture('image-float16', 'rgba', 'fp16', filter)
  28. : type === 'float32'
  29. ? resources.texture('image-float32', 'rgba', 'float', filter)
  30. : resources.texture('image-uint8', 'rgba', 'ubyte', filter);
  31. // make a depth renderbuffer of the same size as the targetTexture
  32. const depthRenderbuffer = !depth
  33. ? null
  34. : isWebGL2(gl)
  35. ? resources.renderbuffer('depth32f', 'depth', _width, _height)
  36. : resources.renderbuffer('depth16', 'depth', _width, _height);
  37. function init() {
  38. targetTexture.define(_width, _height);
  39. targetTexture.attachFramebuffer(framebuffer, 'color0');
  40. if (depthRenderbuffer) depthRenderbuffer.attachFramebuffer(framebuffer);
  41. }
  42. init();
  43. let destroyed = false;
  44. return {
  45. id: getNextRenderTargetId(),
  46. texture: targetTexture,
  47. framebuffer,
  48. getWidth: () => _width,
  49. getHeight: () => _height,
  50. bind: () => {
  51. framebuffer.bind();
  52. },
  53. setSize: (width: number, height: number) => {
  54. if (_width === width && _height === height) {
  55. return;
  56. }
  57. _width = width;
  58. _height = height;
  59. targetTexture.define(_width, _height);
  60. if (depthRenderbuffer) depthRenderbuffer.setSize(_width, _height);
  61. },
  62. reset: () => {
  63. init();
  64. },
  65. destroy: () => {
  66. if (destroyed) return;
  67. targetTexture.destroy();
  68. framebuffer.destroy();
  69. if (depthRenderbuffer) depthRenderbuffer.destroy();
  70. destroyed = true;
  71. }
  72. };
  73. }
  74. //
  75. export function createNullRenderTarget(gl: GLRenderingContext): RenderTarget {
  76. return {
  77. id: getNextRenderTargetId(),
  78. texture: createNullTexture(gl),
  79. framebuffer: createNullFramebuffer(),
  80. getWidth: () => 0,
  81. getHeight: () => 0,
  82. bind: () => {
  83. gl.bindFramebuffer(gl.FRAMEBUFFER, null);
  84. },
  85. setSize: () => {},
  86. reset: () => {},
  87. destroy: () => {}
  88. };
  89. }