render-target.ts 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. /**
  2. * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. */
  6. import { Context, createImageData } from './context'
  7. import { idFactory } from 'mol-util/id-factory';
  8. import { createTexture } from './texture';
  9. import { createFramebuffer } from './framebuffer';
  10. import { createRenderbuffer } from './renderbuffer';
  11. const getNextRenderTargetId = idFactory()
  12. export interface RenderTarget {
  13. readonly id: number
  14. bind: () => void
  15. setSize: (width: number, height: number) => void
  16. getImageData: () => ImageData
  17. destroy: () => void
  18. }
  19. export function createRenderTarget (ctx: Context, _width: number, _height: number): RenderTarget {
  20. const { gl } = ctx
  21. const image = {
  22. array: new Uint8Array(_width * _height * 4),
  23. width: _width,
  24. height: _height
  25. }
  26. const targetTexture = createTexture(ctx, 'rgba', 'ubyte')
  27. targetTexture.load(image)
  28. const framebuffer = createFramebuffer(ctx)
  29. // attach the texture as the first color attachment
  30. targetTexture.attachFramebuffer(framebuffer, 'color0')
  31. // make a depth renderbuffer of the same size as the targetTexture
  32. const depthRenderbuffer = createRenderbuffer(ctx, 'depth16', 'depth', _width, _height)
  33. let destroyed = false
  34. return {
  35. id: getNextRenderTargetId(),
  36. bind: () => {
  37. framebuffer.bind()
  38. gl.viewport(0, 0, _width, _height);
  39. },
  40. setSize: (width: number, height: number) => {
  41. _width = width
  42. _height = height
  43. image.array = new Uint8Array(_width * _height * 4)
  44. image.width = _width
  45. image.height = _height
  46. targetTexture.load(image)
  47. depthRenderbuffer.setSize(_width, _height)
  48. },
  49. getImageData: () => {
  50. framebuffer.bind()
  51. ctx.readPixels(0, 0, _width, _height, image.array)
  52. return createImageData(image.array, _width, _height)
  53. },
  54. destroy: () => {
  55. if (destroyed) return
  56. targetTexture.destroy()
  57. framebuffer.destroy()
  58. depthRenderbuffer.destroy()
  59. destroyed = true
  60. }
  61. }
  62. }