image.ts 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. /**
  2. * Copyright (c) 2019-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. */
  6. import { WebGLContext } from '../../mol-gl/webgl/context';
  7. import { RenderTarget } from '../../mol-gl/webgl/render-target';
  8. import { Renderer } from '../../mol-gl/renderer';
  9. import { Scene } from '../../mol-gl/scene';
  10. import { ParamDefinition as PD } from '../../mol-util/param-definition';
  11. import { DrawPass } from './draw';
  12. import { PostprocessingParams } from './postprocessing';
  13. import { MultiSamplePass, MultiSampleParams, MultiSampleHelper } from './multi-sample';
  14. import { Camera } from '../camera';
  15. import { Viewport } from '../camera/util';
  16. import { PixelData } from '../../mol-util/image';
  17. import { Helper } from '../helper/helper';
  18. import { CameraHelper, CameraHelperParams } from '../helper/camera-helper';
  19. import { MarkingParams } from './marking';
  20. export const ImageParams = {
  21. transparentBackground: PD.Boolean(false),
  22. multiSample: PD.Group(MultiSampleParams),
  23. postprocessing: PD.Group(PostprocessingParams),
  24. marking: PD.Group(MarkingParams),
  25. cameraHelper: PD.Group(CameraHelperParams),
  26. };
  27. export type ImageProps = PD.Values<typeof ImageParams>
  28. export class ImagePass {
  29. private _width = 0;
  30. private _height = 0;
  31. private _camera = new Camera();
  32. readonly props: ImageProps;
  33. private _colorTarget: RenderTarget;
  34. get colorTarget() { return this._colorTarget; }
  35. private readonly drawPass: DrawPass;
  36. private readonly multiSamplePass: MultiSamplePass;
  37. private readonly multiSampleHelper: MultiSampleHelper;
  38. private readonly helper: Helper;
  39. get width() { return this._width; }
  40. get height() { return this._height; }
  41. constructor(private webgl: WebGLContext, private renderer: Renderer, private scene: Scene, private camera: Camera, helper: Helper, enableWboit: boolean, props: Partial<ImageProps>) {
  42. this.props = { ...PD.getDefaultValues(ImageParams), ...props };
  43. this.drawPass = new DrawPass(webgl, 128, 128, enableWboit);
  44. this.multiSamplePass = new MultiSamplePass(webgl, this.drawPass);
  45. this.multiSampleHelper = new MultiSampleHelper(this.multiSamplePass);
  46. this.helper = {
  47. camera: new CameraHelper(webgl, this.props.cameraHelper),
  48. debug: helper.debug,
  49. handle: helper.handle,
  50. };
  51. this.setSize(1024, 768);
  52. }
  53. setSize(width: number, height: number) {
  54. if (width === this._width && height === this._height) return;
  55. this._width = width;
  56. this._height = height;
  57. this.drawPass.setSize(width, height);
  58. this.multiSamplePass.syncSize();
  59. }
  60. setProps(props: Partial<ImageProps> = {}) {
  61. Object.assign(this.props, props);
  62. if (props.cameraHelper) this.helper.camera.setProps(props.cameraHelper);
  63. }
  64. render() {
  65. Camera.copySnapshot(this._camera.state, this.camera.state);
  66. Viewport.set(this._camera.viewport, 0, 0, this._width, this._height);
  67. this._camera.update();
  68. const ctx = { renderer: this.renderer, camera: this._camera, scene: this.scene, helper: this.helper };
  69. if (MultiSamplePass.isEnabled(this.props.multiSample)) {
  70. this.multiSampleHelper.render(ctx, this.props, false);
  71. this._colorTarget = this.multiSamplePass.colorTarget;
  72. } else {
  73. this.drawPass.render(ctx, this.props, false);
  74. this._colorTarget = this.drawPass.getColorTarget(this.props.postprocessing);
  75. }
  76. }
  77. getImageData(width: number, height: number, viewport?: Viewport) {
  78. this.setSize(width, height);
  79. this.render();
  80. this.colorTarget.bind();
  81. const w = viewport?.width ?? width, h = viewport?.height ?? height;
  82. const array = new Uint8Array(w * h * 4);
  83. if (!viewport) {
  84. this.webgl.readPixels(0, 0, w, h, array);
  85. } else {
  86. this.webgl.readPixels(viewport.x, height - viewport.y - viewport.height, w, h, array);
  87. }
  88. const pixelData = PixelData.create(array, w, h);
  89. PixelData.flipY(pixelData);
  90. PixelData.divideByAlpha(pixelData);
  91. return new ImageData(new Uint8ClampedArray(array), w, h);
  92. }
  93. }