UNPKG

@kitware/vtk.js

Version:

Visualization Toolkit for the Web

214 lines (185 loc) 7.28 kB
import { m as macro } from '../../macros2.js'; import vtkWebGPUFullScreenQuad from './FullScreenQuad.js'; import vtkWebGPUOpaquePass from './OpaquePass.js'; import vtkWebGPUOrderIndepenentTranslucentPass from './OrderIndependentTranslucentPass.js'; import vtkWebGPURenderEncoder from './RenderEncoder.js'; import vtkWebGPUVolumePass from './VolumePass.js'; import vtkRenderPass from '../SceneGraph/RenderPass.js'; import vtkWebGPUSampler from './Sampler.js'; import vtkWebGPUTextureView from './TextureView.js'; const finalBlitFragTemplate = ` //VTK::Mapper::Dec //VTK::TCoord::Dec //VTK::RenderEncoder::Dec //VTK::IOStructs::Dec @fragment fn main( //VTK::IOStructs::Input ) //VTK::IOStructs::Output { var output: fragmentOutput; var computedColor: vec4<f32> = clamp(textureSampleLevel(opaquePassColorTexture, finalPassSampler, input.tcoordVS, 0.0),vec4<f32>(0.0),vec4<f32>(1.0)); //VTK::RenderEncoder::Impl return output; } `; // ---------------------------------------------------------------------------- function vtkForwardPass(publicAPI, model) { // Set our className model.classHierarchy.push('vtkForwardPass'); // this pass implements a forward rendering pipeline // if both volumes and opaque geometry are present // it will mix the two together by capturing a zbuffer // first publicAPI.traverse = (viewNode, parent = null) => { if (model.deleted) { return; } // we just render our delegates in order model._currentParent = parent; // build publicAPI.setCurrentOperation('buildPass'); viewNode.traverse(publicAPI); if (!model.opaquePass) { model.opaquePass = vtkWebGPUOpaquePass.newInstance(); } const numlayers = viewNode.getRenderable().getNumberOfLayers(); // iterate over renderers const renderers = viewNode.getChildren(); for (let i = 0; i < numlayers; i++) { for (let index = 0; index < renderers.length; index++) { const renNode = renderers[index]; const ren = viewNode.getRenderable().getRenderers()[index]; if (ren.getDraw() && ren.getLayer() === i) { // check for both opaque and volume actors model.opaqueActorCount = 0; model.translucentActorCount = 0; model.volumes = []; publicAPI.setCurrentOperation('queryPass'); renNode.traverse(publicAPI); publicAPI.setCurrentOperation('cameraPass'); renNode.traverse(publicAPI); // always do opaque pass to get a valid color and zbuffer, even if empty model.opaquePass.traverse(renNode, viewNode); // optional translucent pass if (model.translucentActorCount > 0) { if (!model.translucentPass) { model.translucentPass = vtkWebGPUOrderIndepenentTranslucentPass.newInstance(); } model.translucentPass.setColorTextureView(model.opaquePass.getColorTextureView()); model.translucentPass.setDepthTextureView(model.opaquePass.getDepthTextureView()); model.translucentPass.traverse(renNode, viewNode); } // optional volume pass if (model.volumes.length > 0) { if (!model.volumePass) { model.volumePass = vtkWebGPUVolumePass.newInstance(); } model.volumePass.setColorTextureView(model.opaquePass.getColorTextureView()); model.volumePass.setDepthTextureView(model.opaquePass.getDepthTextureView()); model.volumePass.setVolumes(model.volumes); model.volumePass.traverse(renNode, viewNode); } // blit the result into the swap chain publicAPI.finalPass(viewNode, renNode); } } } }; publicAPI.finalPass = (viewNode, renNode) => { if (!model._finalBlitEncoder) { publicAPI.createFinalBlitEncoder(viewNode); } model._finalBlitOutputTextureView.createFromTextureHandle(viewNode.getCurrentTexture(), { depth: 1, format: viewNode.getPresentationFormat() }); model._finalBlitEncoder.attachTextureViews(); model._finalBlitEncoder.begin(viewNode.getCommandEncoder()); renNode.scissorAndViewport(model._finalBlitEncoder); model._fullScreenQuad.prepareAndDraw(model._finalBlitEncoder); model._finalBlitEncoder.end(); }; publicAPI.createFinalBlitEncoder = viewNode => { model._finalBlitEncoder = vtkWebGPURenderEncoder.newInstance({ label: 'forwardPassBlit' }); model._finalBlitEncoder.setDescription({ colorAttachments: [{ view: null, loadOp: 'load', storeOp: 'store' }] }); model._finalBlitEncoder.setPipelineHash('fpf'); model._finalBlitEncoder.setPipelineSettings({ primitive: { cullMode: 'none' }, fragment: { targets: [{ format: viewNode.getPresentationFormat(), blend: { color: { srcFactor: 'src-alpha', dstFactor: 'one-minus-src-alpha' }, alpha: { srcFactor: 'one', dstFactor: 'one-minus-src-alpha' } } }] } }); model._fsqSampler = vtkWebGPUSampler.newInstance({ label: 'finalPassSampler' }); model._fsqSampler.create(viewNode.getDevice(), { minFilter: 'linear', magFilter: 'linear' }); model._fullScreenQuad = vtkWebGPUFullScreenQuad.newInstance(); model._fullScreenQuad.setDevice(viewNode.getDevice()); model._fullScreenQuad.setPipelineHash('fpfsq'); model._fullScreenQuad.setTextureViews([model.opaquePass.getColorTextureView()]); model._fullScreenQuad.setAdditionalBindables([model._fsqSampler]); model._fullScreenQuad.setFragmentShaderTemplate(finalBlitFragTemplate); model._finalBlitOutputTextureView = vtkWebGPUTextureView.newInstance(); model._finalBlitEncoder.setColorTextureView(0, model._finalBlitOutputTextureView); }; publicAPI.incrementOpaqueActorCount = () => model.opaqueActorCount++; publicAPI.incrementTranslucentActorCount = () => model.translucentActorCount++; publicAPI.addVolume = volume => { model.volumes.push(volume); }; } // ---------------------------------------------------------------------------- // Object factory // ---------------------------------------------------------------------------- const DEFAULT_VALUES = { opaqueActorCount: 0, translucentActorCount: 0, volumes: null, opaqueRenderEncoder: null, translucentPass: null, volumePass: null }; // ---------------------------------------------------------------------------- function extend(publicAPI, model, initialValues = {}) { Object.assign(model, DEFAULT_VALUES, initialValues); // Build VTK API vtkRenderPass.extend(publicAPI, model, initialValues); macro.setGet(publicAPI, model, ['opaquePass', 'translucentPass', 'volumePass']); // Object methods vtkForwardPass(publicAPI, model); } // ---------------------------------------------------------------------------- const newInstance = macro.newInstance(extend, 'vtkForwardPass'); // ---------------------------------------------------------------------------- var vtkForwardPass$1 = { newInstance, extend }; export { vtkForwardPass$1 as default, extend, newInstance };