Skip to content

Commit b9aca41

Browse files
committed
feat(WebGPU): add coincident topology offsets to CellArrayMapper
1 parent 920f0ce commit b9aca41

1 file changed

Lines changed: 84 additions & 1 deletion

File tree

  • Sources/Rendering/WebGPU/CellArrayMapper

Sources/Rendering/WebGPU/CellArrayMapper/index.js

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { mat3, mat4 } from 'gl-matrix';
22

33
import * as macro from 'vtk.js/Sources/macros';
4+
import CoincidentTopologyHelper from 'vtk.js/Sources/Rendering/Core/Mapper/CoincidentTopologyHelper';
45
import vtkMapper from 'vtk.js/Sources/Rendering/Core/Mapper';
56
import vtkProp from 'vtk.js/Sources/Rendering/Core/Prop';
67
import vtkProperty from 'vtk.js/Sources/Rendering/Core/Property';
@@ -12,6 +13,7 @@ import vtkWebGPUUniformBuffer from 'vtk.js/Sources/Rendering/WebGPU/UniformBuffe
1213
import vtkWebGPUSimpleMapper from 'vtk.js/Sources/Rendering/WebGPU/SimpleMapper';
1314
import vtkWebGPUTypes from 'vtk.js/Sources/Rendering/WebGPU/Types';
1415

16+
const { Resolve } = CoincidentTopologyHelper;
1517
const { BufferUsage, PrimitiveTypes } = vtkWebGPUBufferManager;
1618
const { Representation } = vtkProperty;
1719
const { ScalarMode } = vtkMapper;
@@ -541,6 +543,9 @@ function vtkWebGPUCellArrayMapper(publicAPI, model) {
541543
model.UBO.setValue('LineWidth', ppty.getLineWidth());
542544
model.UBO.setValue('Opacity', ppty.getOpacity());
543545
model.UBO.setValue('PropID', model.WebGPUActor.getPropID());
546+
const cp = publicAPI.getCoincidentParameters();
547+
model.UBO.setValue('CoincidentFactor', cp.factor);
548+
model.UBO.setValue('CoincidentOffset', cp.offset);
544549

545550
// Only send if needed
546551
model.UBO.sendIfNeeded(model.WebGPURenderWindow.getDevice());
@@ -582,6 +587,57 @@ function vtkWebGPUCellArrayMapper(publicAPI, model) {
582587
},
583588
});
584589

590+
publicAPI.getCoincidentParameters = () => {
591+
let cp = {
592+
factor: 0.0,
593+
offset: 0.0,
594+
};
595+
596+
const actor = model.WebGPUActor?.getRenderable();
597+
const prop = actor?.getProperty?.();
598+
if (!prop) {
599+
return cp;
600+
}
601+
602+
if (
603+
// backwards compat with code that (errorneously) set this to boolean
604+
// eslint-disable-next-line eqeqeq
605+
model.renderable.getResolveCoincidentTopology() ==
606+
Resolve.PolygonOffset ||
607+
(prop.getEdgeVisibility() &&
608+
prop.getRepresentation() === Representation.SURFACE)
609+
) {
610+
const primType = model.primitiveType;
611+
if (
612+
primType === PrimitiveTypes.Verts ||
613+
prop.getRepresentation() === Representation.POINTS
614+
) {
615+
cp = model.renderable.getCoincidentTopologyPointOffsetParameter();
616+
} else if (
617+
primType === PrimitiveTypes.Lines ||
618+
prop.getRepresentation() === Representation.WIREFRAME
619+
) {
620+
cp = model.renderable.getCoincidentTopologyLineOffsetParameters();
621+
} else if (
622+
primType === PrimitiveTypes.Triangles ||
623+
primType === PrimitiveTypes.TriangleStrips
624+
) {
625+
cp = model.renderable.getCoincidentTopologyPolygonOffsetParameters();
626+
}
627+
628+
if (
629+
primType === PrimitiveTypes.TriangleEdges ||
630+
primType === PrimitiveTypes.TriangleStripEdges
631+
) {
632+
cp = model.renderable.getCoincidentTopologyPolygonOffsetParameters();
633+
cp.factor /= 2.0;
634+
cp.offset /= 2.0;
635+
}
636+
}
637+
638+
return cp;
639+
};
640+
585641
publicAPI.replaceShaderPosition = (hash, pipeline, vertexInput) => {
586642
const vDesc = pipeline.getShaderDescription('vertex');
587643
vDesc.addBuiltinOutput('vec4<f32>', '@builtin(position) Position');
@@ -631,16 +687,41 @@ function vtkWebGPUCellArrayMapper(publicAPI, model) {
631687
]).result;
632688
}
633689
code = vtkWebGPUShaderCache.substitute(code, '//VTK::Position::Impl', [
690+
' pCoord.z = clamp(pCoord.z - 0.000016 * mapperUBO.CoincidentOffset * pCoord.w, 0.0, pCoord.w);',
634691
' output.Position = pCoord;',
635692
]).result;
636-
637693
vDesc.setCode(code);
638694
};
639695
model.shaderReplacements.set(
640696
'replaceShaderPosition',
641697
publicAPI.replaceShaderPosition
642698
);
643699

700+
publicAPI.replaceShaderCoincidentOffset = (hash, pipeline, vertexInput) => {
701+
const fDesc = pipeline.getShaderDescription('fragment');
702+
if (!fDesc) {
703+
return;
704+
}
705+
706+
fDesc.addBuiltinInput('vec4<f32>', '@builtin(position) fragPos');
707+
fDesc.addBuiltinOutput('f32', '@builtin(frag_depth) fragDepth');
708+
709+
let code = fDesc.getCode();
710+
code = vtkWebGPUShaderCache.substitute(code, '//VTK::Position::Impl', [
711+
' var coincidentDepth: f32 = input.fragPos.z;',
712+
' if (mapperUBO.CoincidentFactor != 0.0) {',
713+
' let cscale = length(vec2<f32>(dpdx(input.fragPos.z), dpdy(input.fragPos.z)));',
714+
' coincidentDepth = coincidentDepth - mapperUBO.CoincidentFactor * cscale;',
715+
' }',
716+
' output.fragDepth = clamp(coincidentDepth, 0.0, 1.0);',
717+
]).result;
718+
fDesc.setCode(code);
719+
};
720+
model.shaderReplacements.set(
721+
'replaceShaderCoincidentOffset',
722+
publicAPI.replaceShaderCoincidentOffset
723+
);
724+
644725
publicAPI.replaceShaderNormal = (hash, pipeline, vertexInput) => {
645726
const normalBuffer = vertexInput.getBuffer('normalMC');
646727
const actor = model.WebGPUActor.getRenderable();
@@ -1487,6 +1568,8 @@ export function extend(publicAPI, model, initiaLalues = {}) {
14871568
model.UBO.addEntry('Opacity', 'f32');
14881569
model.UBO.addEntry('OpacityBF', 'f32');
14891570
model.UBO.addEntry('ZValue', 'f32');
1571+
model.UBO.addEntry('CoincidentFactor', 'f32');
1572+
model.UBO.addEntry('CoincidentOffset', 'f32');
14901573
model.UBO.addEntry('PropID', 'u32');
14911574
model.UBO.addEntry('ClipNear', 'f32');
14921575
model.UBO.addEntry('ClipFar', 'f32');

0 commit comments

Comments
 (0)