active-voxels.ts 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. /**
  2. * Copyright (c) 2019-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. */
  6. import { ComputeRenderable, createComputeRenderable } from '../../renderable';
  7. import { WebGLContext } from '../../webgl/context';
  8. import { createComputeRenderItem } from '../../webgl/render-item';
  9. import { Values, TextureSpec, UniformSpec } from '../../renderable/schema';
  10. import { Texture } from '../../../mol-gl/webgl/texture';
  11. import { ShaderCode } from '../../../mol-gl/shader-code';
  12. import { ValueCell } from '../../../mol-util';
  13. import { Vec3, Vec2 } from '../../../mol-math/linear-algebra';
  14. import { QuadSchema, QuadValues } from '../util';
  15. import { getTriCount } from './tables';
  16. import { quad_vert } from '../../../mol-gl/shader/quad.vert';
  17. import { activeVoxels_frag } from '../../../mol-gl/shader/marching-cubes/active-voxels.frag';
  18. import { isTimingMode } from '../../../mol-util/debug';
  19. const ActiveVoxelsSchema = {
  20. ...QuadSchema,
  21. tTriCount: TextureSpec('image-uint8', 'alpha', 'ubyte', 'nearest'),
  22. tVolumeData: TextureSpec('texture', 'rgba', 'ubyte', 'nearest'),
  23. uIsoValue: UniformSpec('f'),
  24. uGridDim: UniformSpec('v3'),
  25. uGridTexDim: UniformSpec('v3'),
  26. uScale: UniformSpec('v2'),
  27. };
  28. type ActiveVoxelsValues = Values<typeof ActiveVoxelsSchema>
  29. const ActiveVoxelsName = 'active-voxels';
  30. function getActiveVoxelsRenderable(ctx: WebGLContext, volumeData: Texture, gridDim: Vec3, gridTexDim: Vec3, isoValue: number, scale: Vec2): ComputeRenderable<ActiveVoxelsValues> {
  31. if (ctx.namedComputeRenderables[ActiveVoxelsName]) {
  32. const v = ctx.namedComputeRenderables[ActiveVoxelsName].values as ActiveVoxelsValues;
  33. ValueCell.update(v.uQuadScale, scale);
  34. ValueCell.update(v.tVolumeData, volumeData);
  35. ValueCell.updateIfChanged(v.uIsoValue, isoValue);
  36. ValueCell.update(v.uGridDim, gridDim);
  37. ValueCell.update(v.uGridTexDim, gridTexDim);
  38. ValueCell.update(v.uScale, scale);
  39. ctx.namedComputeRenderables[ActiveVoxelsName].update();
  40. } else {
  41. ctx.namedComputeRenderables[ActiveVoxelsName] = createActiveVoxelsRenderable(ctx, volumeData, gridDim, gridTexDim, isoValue, scale);
  42. }
  43. return ctx.namedComputeRenderables[ActiveVoxelsName];
  44. }
  45. function createActiveVoxelsRenderable(ctx: WebGLContext, volumeData: Texture, gridDim: Vec3, gridTexDim: Vec3, isoValue: number, scale: Vec2) {
  46. const values: ActiveVoxelsValues = {
  47. ...QuadValues,
  48. tTriCount: ValueCell.create(getTriCount()),
  49. uQuadScale: ValueCell.create(scale),
  50. tVolumeData: ValueCell.create(volumeData),
  51. uIsoValue: ValueCell.create(isoValue),
  52. uGridDim: ValueCell.create(gridDim),
  53. uGridTexDim: ValueCell.create(gridTexDim),
  54. uScale: ValueCell.create(scale),
  55. };
  56. const schema = { ...ActiveVoxelsSchema };
  57. const shaderCode = ShaderCode('active-voxels', quad_vert, activeVoxels_frag);
  58. const renderItem = createComputeRenderItem(ctx, 'triangles', shaderCode, schema, values);
  59. return createComputeRenderable(renderItem, values);
  60. }
  61. function setRenderingDefaults(ctx: WebGLContext) {
  62. const { gl, state } = ctx;
  63. state.disable(gl.CULL_FACE);
  64. state.disable(gl.BLEND);
  65. state.disable(gl.DEPTH_TEST);
  66. state.enable(gl.SCISSOR_TEST);
  67. state.depthMask(false);
  68. state.colorMask(true, true, true, true);
  69. state.clearColor(0, 0, 0, 0);
  70. }
  71. export function calcActiveVoxels(ctx: WebGLContext, volumeData: Texture, gridDim: Vec3, gridTexDim: Vec3, isoValue: number, gridScale: Vec2) {
  72. if (isTimingMode) ctx.timer.mark('calcActiveVoxels');
  73. const { gl, resources } = ctx;
  74. const width = volumeData.getWidth();
  75. const height = volumeData.getHeight();
  76. if (!ctx.namedFramebuffers[ActiveVoxelsName]) {
  77. ctx.namedFramebuffers[ActiveVoxelsName] = resources.framebuffer();
  78. }
  79. const framebuffer = ctx.namedFramebuffers[ActiveVoxelsName];
  80. framebuffer.bind();
  81. if (!ctx.namedTextures[ActiveVoxelsName]) {
  82. ctx.namedTextures[ActiveVoxelsName] = resources.texture('image-uint8', 'rgba', 'ubyte', 'nearest');
  83. }
  84. const activeVoxelsTex = ctx.namedTextures[ActiveVoxelsName];
  85. activeVoxelsTex.define(width, height);
  86. const renderable = getActiveVoxelsRenderable(ctx, volumeData, gridDim, gridTexDim, isoValue, gridScale);
  87. ctx.state.currentRenderItemId = -1;
  88. activeVoxelsTex.attachFramebuffer(framebuffer, 0);
  89. setRenderingDefaults(ctx);
  90. gl.viewport(0, 0, width, height);
  91. gl.scissor(0, 0, width, height);
  92. gl.clear(gl.COLOR_BUFFER_BIT);
  93. gl.scissor(0, 0, gridTexDim[0], gridTexDim[1]);
  94. renderable.render();
  95. // console.log('gridScale', gridScale, 'gridTexDim', gridTexDim, 'gridDim', gridDim);
  96. // console.log('volumeData', volumeData);
  97. // console.log('at', readTexture(ctx, activeVoxelsTex));
  98. gl.finish();
  99. if (isTimingMode) ctx.timer.markEnd('calcActiveVoxels');
  100. return activeVoxelsTex;
  101. }