wboit.ts 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. /**
  2. * Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Áron Samuel Kovács <aron.kovacs@mail.muni.cz>
  5. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  6. */
  7. import { QuadSchema, QuadValues } from '../../mol-gl/compute/util';
  8. import { ComputeRenderable, createComputeRenderable } from '../../mol-gl/renderable';
  9. import { TextureSpec, UniformSpec, Values } from '../../mol-gl/renderable/schema';
  10. import { ShaderCode } from '../../mol-gl/shader-code';
  11. import { WebGLContext } from '../../mol-gl/webgl/context';
  12. import { createComputeRenderItem } from '../../mol-gl/webgl/render-item';
  13. import { Texture } from '../../mol-gl/webgl/texture';
  14. import { ValueCell } from '../../mol-util';
  15. import { quad_vert } from '../../mol-gl/shader/quad.vert';
  16. import { evaluateWboit_frag } from '../../mol-gl/shader/evaluate-wboit.frag';
  17. import { Framebuffer } from '../../mol-gl/webgl/framebuffer';
  18. import { Vec2 } from '../../mol-math/linear-algebra';
  19. import { isDebugMode } from '../../mol-util/debug';
  20. const EvaluateWboitSchema = {
  21. ...QuadSchema,
  22. tWboitA: TextureSpec('texture', 'rgba', 'float', 'nearest'),
  23. tWboitB: TextureSpec('texture', 'rgba', 'float', 'nearest'),
  24. uTexSize: UniformSpec('v2'),
  25. };
  26. const EvaluateWboitShaderCode = ShaderCode('evaluate-wboit', quad_vert, evaluateWboit_frag);
  27. type EvaluateWboitRenderable = ComputeRenderable<Values<typeof EvaluateWboitSchema>>
  28. function getEvaluateWboitRenderable(ctx: WebGLContext, wboitATexture: Texture, wboitBTexture: Texture): EvaluateWboitRenderable {
  29. const values: Values<typeof EvaluateWboitSchema> = {
  30. ...QuadValues,
  31. tWboitA: ValueCell.create(wboitATexture),
  32. tWboitB: ValueCell.create(wboitBTexture),
  33. uTexSize: ValueCell.create(Vec2.create(wboitATexture.getWidth(), wboitATexture.getHeight())),
  34. };
  35. const schema = { ...EvaluateWboitSchema };
  36. const renderItem = createComputeRenderItem(ctx, 'triangles', EvaluateWboitShaderCode, schema, values);
  37. return createComputeRenderable(renderItem, values);
  38. }
  39. //
  40. export class WboitPass {
  41. private readonly renderable: EvaluateWboitRenderable
  42. private readonly framebuffer: Framebuffer
  43. private readonly textureA: Texture
  44. private readonly textureB: Texture
  45. private _supported = false;
  46. get supported() {
  47. return this._supported;
  48. }
  49. bind() {
  50. const { state, gl } = this.webgl;
  51. this.framebuffer.bind();
  52. state.clearColor(0, 0, 0, 1);
  53. gl.clear(gl.COLOR_BUFFER_BIT);
  54. state.disable(gl.DEPTH_TEST);
  55. state.blendFuncSeparate(gl.ONE, gl.ONE, gl.ZERO, gl.ONE_MINUS_SRC_ALPHA);
  56. state.enable(gl.BLEND);
  57. }
  58. render() {
  59. const { state, gl } = this.webgl;
  60. state.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
  61. state.enable(gl.BLEND);
  62. this.renderable.update();
  63. this.renderable.render();
  64. }
  65. setSize(width: number, height: number) {
  66. const [w, h] = this.renderable.values.uTexSize.ref.value;
  67. if (width !== w || height !== h) {
  68. this.textureA.define(width, height);
  69. this.textureB.define(width, height);
  70. ValueCell.update(this.renderable.values.uTexSize, Vec2.set(this.renderable.values.uTexSize.ref.value, width, height));
  71. }
  72. }
  73. reset() {
  74. if (this._supported) this._init();
  75. }
  76. private _init() {
  77. const { extensions: { drawBuffers } } = this.webgl;
  78. this.framebuffer.bind();
  79. drawBuffers!.drawBuffers([
  80. drawBuffers!.COLOR_ATTACHMENT0,
  81. drawBuffers!.COLOR_ATTACHMENT1,
  82. ]);
  83. this.textureA.attachFramebuffer(this.framebuffer, 'color0');
  84. this.textureB.attachFramebuffer(this.framebuffer, 'color1');
  85. }
  86. static isSupported(webgl: WebGLContext) {
  87. const { extensions: { drawBuffers, textureFloat, colorBufferFloat, depthTexture } } = webgl;
  88. if (!textureFloat || !colorBufferFloat || !depthTexture || !drawBuffers) {
  89. if (isDebugMode) {
  90. const missing: string[] = [];
  91. if (!textureFloat) missing.push('textureFloat');
  92. if (!colorBufferFloat) missing.push('colorBufferFloat');
  93. if (!depthTexture) missing.push('depthTexture');
  94. if (!drawBuffers) missing.push('drawBuffers');
  95. console.log(`Missing "${missing.join('", "')}" extensions required for "wboit"`);
  96. }
  97. return false;
  98. } else {
  99. return true;
  100. }
  101. }
  102. constructor(private webgl: WebGLContext, width: number, height: number) {
  103. if (!WboitPass.isSupported(webgl)) return;
  104. const { resources } = webgl;
  105. this.textureA = resources.texture('image-float32', 'rgba', 'float', 'nearest');
  106. this.textureA.define(width, height);
  107. this.textureB = resources.texture('image-float32', 'rgba', 'float', 'nearest');
  108. this.textureB.define(width, height);
  109. this.renderable = getEvaluateWboitRenderable(webgl, this.textureA, this.textureB);
  110. this.framebuffer = resources.framebuffer();
  111. this._supported = true;
  112. this._init();
  113. }
  114. }