@kitware/vtk.js 25.1.1 → 25.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Rendering/Core/Light.d.ts +36 -2
- package/Rendering/Core/Light.js +10 -4
- package/Rendering/Core/Property.d.ts +120 -0
- package/Rendering/Core/Property.js +17 -1
- package/Rendering/Core/Texture.js +31 -0
- package/Rendering/WebGPU/Actor2D.js +2 -0
- package/Rendering/WebGPU/BufferManager.js +1 -1
- package/Rendering/WebGPU/CellArrayMapper.js +220 -50
- package/Rendering/WebGPU/Glyph3DMapper.js +2 -1
- package/Rendering/WebGPU/Renderer.js +109 -4
- package/Rendering/WebGPU/SphereMapper.js +2 -2
- package/Rendering/WebGPU/StickMapper.js +2 -2
- package/Rendering/WebGPU/Texture.js +8 -0
- package/Rendering/WebGPU/Types.js +3 -3
- package/Widgets/Core/AbstractWidgetFactory.js +8 -8
- package/Widgets/Widgets3D/AngleWidget.js +8 -4
- package/Widgets/Widgets3D/DistanceWidget.js +8 -4
- package/Widgets/Widgets3D/EllipseWidget.js +2 -2
- package/Widgets/Widgets3D/ImageCroppingWidget.js +10 -6
- package/Widgets/Widgets3D/ImplicitPlaneWidget.js +12 -4
- package/Widgets/Widgets3D/InteractiveOrientationWidget.js +12 -4
- package/Widgets/Widgets3D/LabelWidget.js +4 -3
- package/Widgets/Widgets3D/LineWidget.js +9 -5
- package/Widgets/Widgets3D/PaintWidget.js +13 -9
- package/Widgets/Widgets3D/PolyLineWidget.js +8 -4
- package/Widgets/Widgets3D/RectangleWidget.js +2 -3
- package/Widgets/Widgets3D/ResliceCursorWidget.js +12 -5
- package/Widgets/Widgets3D/SphereWidget.js +8 -3
- package/Widgets/Widgets3D/SplineWidget.js +16 -13
- package/package.json +1 -1
|
@@ -9,6 +9,7 @@ import vtkWebGPUBufferManager from './BufferManager.js';
|
|
|
9
9
|
import vtkWebGPUShaderCache from './ShaderCache.js';
|
|
10
10
|
import vtkWebGPUUniformBuffer from './UniformBuffer.js';
|
|
11
11
|
import vtkWebGPUSimpleMapper from './SimpleMapper.js';
|
|
12
|
+
import vtkWebGPUTypes from './Types.js';
|
|
12
13
|
|
|
13
14
|
var BufferUsage = vtkWebGPUBufferManager.BufferUsage,
|
|
14
15
|
PrimitiveTypes = vtkWebGPUBufferManager.PrimitiveTypes;
|
|
@@ -17,7 +18,7 @@ var ScalarMode = vtkMapper.ScalarMode;
|
|
|
17
18
|
var CoordinateSystem = vtkProp.CoordinateSystem;
|
|
18
19
|
var DisplayLocation = vtkProperty2D.DisplayLocation;
|
|
19
20
|
var vtkWebGPUPolyDataVS = "\n//VTK::Renderer::Dec\n\n//VTK::Color::Dec\n\n//VTK::Normal::Dec\n\n//VTK::TCoord::Dec\n\n//VTK::Select::Dec\n\n//VTK::Mapper::Dec\n\n//VTK::IOStructs::Dec\n\n@vertex\nfn main(\n//VTK::IOStructs::Input\n)\n//VTK::IOStructs::Output\n{\n var output : vertexOutput;\n\n var vertex: vec4<f32> = vertexBC;\n\n //VTK::Color::Impl\n\n //VTK::Normal::Impl\n\n //VTK::TCoord::Impl\n\n //VTK::Select::Impl\n\n //VTK::Position::Impl\n\n return output;\n}\n";
|
|
20
|
-
var vtkWebGPUPolyDataFS = "\n//VTK::Renderer::Dec\n\n//VTK::Color::Dec\n\n// optional surface normal declaration\n//VTK::Normal::Dec\n\n//VTK::
|
|
21
|
+
var vtkWebGPUPolyDataFS = "\nstruct PBRData {\n diffuse: vec3<f32>,\n specular: vec3<f32>,\n}\n\n// Dot product with the max already in it\nfn mdot(a: vec3<f32>, b: vec3<f32>) -> f32 {\n return max(0.0, dot(a, b));\n}\n\n// Lambertian diffuse model\nfn lambertDiffuse(base: vec3<f32>, N: vec3<f32>, L: vec3<f32>) -> vec3<f32> {\n var pi: f32 = 3.14159265359; \n var NdotL: f32 = mdot(N, L);\n NdotL = pow(NdotL, 1.5);\n return (base/pi)*NdotL;\n}\n\n// Yasuhiro Fujii improvement on the Oren-Nayar model\n// https://mimosa-pudica.net/improved-oren-nayar.html\n// p is surface color, o is roughness\nfn fujiiOrenNayar(p: vec3<f32>, o: f32, N: vec3<f32>, L: vec3<f32>, V: vec3<f32>) -> vec3<f32> {\n var invpi: f32 = 0.31830988618; // 1/pi\n\n var o2 = o*o;\n var NdotL: f32 = mdot(N, L);\n NdotL = pow(NdotL, 1.5); // Less physically accurate, but hides the \"seams\" between lights better\n\n var NdotV: f32 = mdot(N, V);\n var LdotV: f32 = mdot(L, V);\n\n var s: f32 = LdotV - NdotL*NdotV;\n var t: f32 = mix(1, max(NdotL, NdotV), step(0, s)); // Mix with step is the equivalent of an if statement\n var A: vec3<f32> = 0.5*(o2 / (o2 + 0.33)) + 0.17*p*(o2 / (o2 + 0.13));\n A = invpi*(1 - A);\n var B: f32 = 0.45*(o2 / (o2 + 0.09));\n B = invpi*B;\n\n return p*NdotL*(A + B*(s/t));\n}\n\n// Fresnel portion of BRDF (IOR only, simplified)\nfn schlickFresnelIOR(V: vec3<f32>, N: vec3<f32>, ior: f32, k: f32) -> f32 {\n var NdotV: f32 = mdot(V, N);\n // var R0: f32 = pow((ior - 1.0) / (ior + 1.0), 2); // 1.0 is about the ior of air, and it is assumed that light will be traveling through air\n var F0: f32 = (pow((ior - 1.0), 2) + k*k) / (pow((ior + 1.0), 2) + k*k); // This takes into account the roughness, whic the other one does not\n return F0 + (1 - F0) * pow((1-NdotV), 5); \n}\n\n// Fresnel portion of BRDF (Color ior, better)\nfn schlickFresnelRGB(V: vec3<f32>, N: vec3<f32>, F0: vec3<f32>) -> vec3<f32> {\n var NdotV: f32 = mdot(V, N);\n return F0 + (1 - F0) * pow((1-NdotV), 5); \n}\n\n// Normal portion of BRDF\n// https://learnopengl.com/PBR/Theory\n// Trowbridge-Reitz GGX functions: normal, halfway, roughness^2\nfn trGGX(N: vec3<f32>, H: vec3<f32>, a: f32) -> f32 {\n var pi: f32 = 3.14159265359; \n\n var a2: f32 = a*a;\n var NdotH = mdot(N, H);\n var NdotH2 = NdotH*NdotH;\n \n var denom: f32 = NdotH2 * (a2 - 1.0) + 1.0;\n\n return a2 / max((pi*denom*denom), 0.000001);\n}\n\n// A VERY bad approximation of anisotropy. Real anisotropic calculations require tangent and bitangent\nfn anisotrophicTrGGX(N: vec3<f32>, H: vec3<f32>, O: vec3<f32>, s: f32, a: f32) -> f32 {\n var Op: vec3<f32> = (rendererUBO.WCVCNormals * vec4<f32>(normalize(O) * s, 0.)).xyz;\n\n var ggx1: f32 = trGGX(N + Op*s, H, a);\n var ggx2: f32 = trGGX(N - Op*s, H, a);\n return (0.5 * ggx1 + 0.5 * ggx2);\n}\n\n// Geometry portion of BRDF\nfn schlickGGX(N: vec3<f32>, X: vec3<f32>, k: f32) -> f32 {\n var NdotX = mdot(N, X);\n return NdotX / max(0.000001, (NdotX*(1-k) + k));\n}\n\nfn smithSurfaceRoughness(N: vec3<f32>, V: vec3<f32>, L: vec3<f32>, k: f32) -> f32 {\n var ggx1: f32 = max(0.01, schlickGGX(N, V, k)); // Prevents void zones at the cost of some accuracy\n var ggx2: f32 = schlickGGX(N, L, k);\n return ggx1*ggx2;\n}\n\n// BRDF Combination\nfn cookTorrance(D: f32, F: f32, G: f32, N: vec3<f32>, V: vec3<f32>, L: vec3<f32>) -> f32 {\n var num: f32 = D*F*G;\n var denom: f32 = 4*mdot(V, N)*mdot(L, N);\n\n return num / max(denom, 0.000001);\n}\n\n// Different lighting calculations for different light sources\nfn calcDirectionalLight(N: vec3<f32>, V: vec3<f32>, ior: f32, roughness: f32, metallic: f32, direction: vec3<f32>, color: vec3<f32>, base: vec3<f32>) -> PBRData { \n var L: vec3<f32> = normalize(direction); // Light Vector\n var H: vec3<f32> = normalize(L + V); // Halfway Vector\n\n var alpha = roughness*roughness;\n var k: f32 = alpha*alpha / 2;\n\n var D: f32 = trGGX(N, H, alpha); // Distribution\n // var F: f32 = schlickFresnelIOR(V, N, ior, k); // Fresnel\n var G: f32 = smithSurfaceRoughness(N, V, L, k); // Geometry\n\n var brdf: f32 = cookTorrance(D, 1, G, N, V, L); // Fresnel term is replaced with 1 because it is added later\n var incoming: vec3<f32> = color;\n var angle: f32 = mdot(L, N);\n angle = pow(angle, 1.5);\n\n var specular: vec3<f32> = brdf*incoming*angle;\n // Oren-Nayar gives a clay-like effect when fully rough which some people may not want, so it might be better to give a separate\n // control property for the diffuse vs specular roughness\n var diffuse: vec3<f32> = incoming*fujiiOrenNayar(base, roughness, N, L, V); \n // Stores the specular and diffuse separately to allow for finer post processing\n // Could also be done (propably more properly) with a struct\n var out = PBRData(diffuse, specular);\n \n return out; // Returns angle along with color of light so the final color can be multiplied by angle as well (creates black areas)\n}\n\n// TODO: find some way to reduce the number of arguments going in here\nfn calcPointLight(N: vec3<f32>, V: vec3<f32>, fragPos: vec3<f32>, ior: f32, roughness: f32, metallic: f32, position: vec3<f32>, color: vec3<f32>, base: vec3<f32>) -> PBRData {\n var L: vec3<f32> = normalize(position - fragPos); // Light Vector\n var H: vec3<f32> = normalize(L + V); // Halfway Vector\n var dist = distance(position, fragPos);\n\n var alpha = roughness*roughness;\n var k: f32 = alpha*alpha / 2; // could also be pow(alpha + 1.0, 2) / 8\n\n var D: f32 = trGGX(N, H, alpha); // Distribution\n // var F: f32 = schlickFresnelIOR(V, N, ior, k); // Fresnel\n var G: f32 = smithSurfaceRoughness(N, V, L, k); // Geometry\n\n var brdf: f32 = cookTorrance(D, 1, G, N, V, L); \n var incoming: vec3<f32> = color * (1. / (dist*dist));\n var angle: f32 = mdot(L, N);\n angle = pow(angle, 1.5); // Smoothing factor makes it less accurate, but reduces ugly \"seams\" bewteen light sources\n\n var specular: vec3<f32> = brdf*incoming*angle;\n var diffuse: vec3<f32> = incoming*fujiiOrenNayar(base, roughness, N, L, V);\n\n // Stores the specular and diffuse separately to allow for finer post processing\n // Could also be done (propably more properly) with a struct\n var out = PBRData(diffuse, specular);\n \n return out; // Returns angle along with color of light so the final color can be multiplied by angle as well (creates black areas)\n}\n\n// For a reason unknown to me, spheres dont seem to behave propperly with head-on spot lights\nfn calcSpotLight(N: vec3<f32>, V: vec3<f32>, fragPos: vec3<f32>, ior: f32, roughness: f32, metallic: f32, position: vec3<f32>, direction: vec3<f32>, cones: vec2<f32>, color: vec3<f32>, base: vec3<f32>) -> PBRData {\n var L: vec3<f32> = normalize(position - fragPos);\n var H: vec3<f32> = normalize(L + V); // Halfway Vector\n var dist = distance(position, fragPos);\n\n var alpha = roughness*roughness;\n var k: f32 = alpha*alpha / 2; // could also be pow(alpha + 1.0, 2) / 8\n\n var D: f32 = trGGX(N, H, alpha); // Distribution\n // var F: f32 = schlickFresnelIOR(V, N, ior, k); // Fresnel\n var G: f32 = smithSurfaceRoughness(N, V, L, k); // Geometry\n\n var brdf: f32 = cookTorrance(D, 1, G, N, V, L); \n \n // Cones.x is the inner phi and cones.y is the outer phi\n var theta: f32 = mdot(normalize(direction), L);\n var epsilon: f32 = cones.x - cones.y;\n var intensity: f32 = (theta - cones.y) / epsilon;\n intensity = clamp(intensity, 0.0, 1.0);\n intensity /= dist*dist;\n\n var incoming: vec3<f32> = color * intensity;\n\n var angle: f32 = mdot(L, N);\n angle = pow(angle, 1.5); // Smoothing factor makes it less accurate, but reduces ugly \"seams\" bewteen light sources\n\n var specular: vec3<f32> = brdf*incoming*angle;\n var diffuse: vec3<f32> = incoming*fujiiOrenNayar(base, roughness, N, L, V);\n\n // Stores the specular and diffuse separately to allow for finer post processing\n // Could also be done (propably more properly) with a struct\n var out = PBRData(diffuse, specular);\n \n return out; // Returns angle along with color of light so the final color can be multiplied by angle as well (creates black areas)\n}\n\n// Environment mapping stuff\n// Takes in a vector and converts it to an equivalent coordinate in a rectilinear texture. Should be replaced with cubemaps at some point\nfn vecToRectCoord(dir: vec3<f32>) -> vec2<f32> {\n var tau: f32 = 6.28318530718;\n var out: vec2<f32> = vec2<f32>(0.);\n\n out.x = atan2(dir.z, dir.x) / tau;\n out.x += 0.5;\n\n out.y = (dir.y * .5) + .5;\n\n return out;\n}\n\n//VTK::Renderer::Dec\n\n//VTK::Color::Dec\n\n//VTK::TCoord::Dec\n\n// optional surface normal declaration\n//VTK::Normal::Dec\n\n//VTK::Select::Dec\n\n//VTK::RenderEncoder::Dec\n\n//VTK::Mapper::Dec\n\n//VTK::IOStructs::Dec\n\n@fragment\nfn main(\n//VTK::IOStructs::Input\n)\n//VTK::IOStructs::Output\n{\n var output : fragmentOutput;\n\n // Temporary ambient, diffuse, and opacity\n var ambientColor: vec4<f32> = mapperUBO.AmbientColor;\n var diffuseColor: vec4<f32> = mapperUBO.DiffuseColor;\n var opacity: f32 = mapperUBO.Opacity;\n\n // This should be declared somewhere else\n var _diffuseMap: vec4<f32> = vec4<f32>(1);\n var _roughnessMap: vec4<f32> = vec4<f32>(1);\n var _metallicMap: vec4<f32> = vec4<f32>(1);\n var _normalMap: vec4<f32> = vec4<f32>(0, 0, 1, 0); // normal map was setting off the normal vector detection in fragment\n var _ambientOcclusionMap: vec4<f32> = vec4<f32>(0);\n var _emissionMap: vec4<f32> = vec4<f32>(0);\n\n //VTK::Color::Impl\n\n //VTK::TCoord::Impl\n\n //VTK::Normal::Impl\n\n var computedColor: vec4<f32> = vec4<f32>(diffuseColor.rgb, 1.);\n\n //VTK::Light::Impl\n\n //VTK::Select::Impl\n\n if (computedColor.a == 0.0) { discard; };\n\n //VTK::Position::Impl\n\n //VTK::RenderEncoder::Impl\n\n return output;\n}\n";
|
|
21
22
|
|
|
22
23
|
function isEdges(hash) {
|
|
23
24
|
// edge pipelines have "edge" in them
|
|
@@ -71,6 +72,9 @@ function vtkWebGPUCellArrayMapper(publicAPI, model) {
|
|
|
71
72
|
var utime = model.UBO.getSendTime();
|
|
72
73
|
|
|
73
74
|
if (publicAPI.getMTime() > utime || ppty.getMTime() > utime || model.renderable.getMTime() > utime) {
|
|
75
|
+
var _ppty$getEdgeColorByR;
|
|
76
|
+
|
|
77
|
+
// Matricies
|
|
74
78
|
var keyMats = model.WebGPUActor.getKeyMatrices(model.WebGPURenderer);
|
|
75
79
|
model.UBO.setArray('BCWCMatrix', keyMats.bcwc);
|
|
76
80
|
model.UBO.setArray('BCSCMatrix', keyMats.bcsc);
|
|
@@ -78,25 +82,42 @@ function vtkWebGPUCellArrayMapper(publicAPI, model) {
|
|
|
78
82
|
|
|
79
83
|
if (model.is2D) {
|
|
80
84
|
model.UBO.setValue('ZValue', model.WebGPUActor.getRenderable().getProperty().getDisplayLocation() === DisplayLocation.FOREGROUND ? 1.0 : 0.0);
|
|
81
|
-
|
|
85
|
+
|
|
86
|
+
var _aColor = ppty.getColorByReference();
|
|
87
|
+
|
|
82
88
|
model.UBO.setValue('AmbientIntensity', 1.0);
|
|
83
|
-
model.UBO.setArray('
|
|
89
|
+
model.UBO.setArray('DiffuseColor', [_aColor[0], _aColor[1], _aColor[2], 1.0]);
|
|
84
90
|
model.UBO.setValue('DiffuseIntensity', 0.0);
|
|
85
91
|
model.UBO.setValue('SpecularIntensity', 0.0);
|
|
86
92
|
} else {
|
|
87
|
-
|
|
93
|
+
// Base Colors
|
|
94
|
+
var _aColor2 = ppty.getAmbientColorByReference();
|
|
88
95
|
|
|
89
96
|
model.UBO.setValue('AmbientIntensity', ppty.getAmbient());
|
|
90
|
-
model.UBO.setArray('AmbientColor', [
|
|
97
|
+
model.UBO.setArray('AmbientColor', [_aColor2[0], _aColor2[1], _aColor2[2], 1.0]);
|
|
91
98
|
model.UBO.setValue('DiffuseIntensity', ppty.getDiffuse());
|
|
92
|
-
|
|
93
|
-
model.UBO.setArray('DiffuseColor', [
|
|
99
|
+
_aColor2 = ppty.getDiffuseColorByReference();
|
|
100
|
+
model.UBO.setArray('DiffuseColor', [_aColor2[0], _aColor2[1], _aColor2[2], 1.0]); // Roughness
|
|
101
|
+
|
|
102
|
+
model.UBO.setValue('Roughness', ppty.getRoughness());
|
|
103
|
+
model.UBO.setValue('BaseIOR', ppty.getBaseIOR()); // Metallic
|
|
104
|
+
|
|
105
|
+
model.UBO.setValue('Metallic', ppty.getMetallic()); // Normal
|
|
106
|
+
|
|
107
|
+
model.UBO.setValue('NormalStrength', ppty.getNormalStrength()); // Emission
|
|
108
|
+
|
|
109
|
+
model.UBO.setValue('Emission', ppty.getEmission()); // Specular
|
|
110
|
+
|
|
94
111
|
model.UBO.setValue('SpecularIntensity', ppty.getSpecular());
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
112
|
+
_aColor2 = ppty.getSpecularColorByReference();
|
|
113
|
+
model.UBO.setArray('SpecularColor', [_aColor2[0], _aColor2[1], _aColor2[2], 1.0]);
|
|
114
|
+
} // Edge and line rendering
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
var aColor = (_ppty$getEdgeColorByR = ppty.getEdgeColorByReference) === null || _ppty$getEdgeColorByR === void 0 ? void 0 : _ppty$getEdgeColorByR.call(ppty);
|
|
118
|
+
|
|
119
|
+
if (aColor) {
|
|
120
|
+
model.UBO.setArray('EdgeColor', [aColor[0], aColor[1], aColor[2], 1.0]);
|
|
100
121
|
}
|
|
101
122
|
|
|
102
123
|
model.UBO.setValue('LineWidth', ppty.getLineWidth());
|
|
@@ -129,10 +150,11 @@ function vtkWebGPUCellArrayMapper(publicAPI, model) {
|
|
|
129
150
|
publicAPI.replaceShaderPosition = function (hash, pipeline, vertexInput) {
|
|
130
151
|
var vDesc = pipeline.getShaderDescription('vertex');
|
|
131
152
|
vDesc.addBuiltinOutput('vec4<f32>', '@builtin(position) Position');
|
|
153
|
+
if (!vDesc.hasOutput('vertexVC')) vDesc.addOutput('vec4<f32>', 'vertexVC');
|
|
132
154
|
var code = vDesc.getCode();
|
|
133
155
|
|
|
134
156
|
if (model.useRendererMatrix) {
|
|
135
|
-
code = vtkWebGPUShaderCache.substitute(code, '//VTK::Position::Impl', [' var pCoord: vec4<f32> = rendererUBO.SCPCMatrix*mapperUBO.BCSCMatrix*vertexBC;', '//VTK::Position::Impl']).result;
|
|
157
|
+
code = vtkWebGPUShaderCache.substitute(code, '//VTK::Position::Impl', [' var pCoord: vec4<f32> = rendererUBO.SCPCMatrix*mapperUBO.BCSCMatrix*vertexBC;', ' output.vertexVC = rendererUBO.SCVCMatrix * mapperUBO.BCSCMatrix * vec4<f32>(vertexBC.xyz, 1.0);', '//VTK::Position::Impl']).result;
|
|
136
158
|
|
|
137
159
|
if (model.forceZValue) {
|
|
138
160
|
code = vtkWebGPUShaderCache.substitute(code, '//VTK::Position::Impl', ['pCoord = vec4<f32>(pCoord.xyz/pCoord.w, 1.0);', 'pCoord.z = mapperUBO.ZValue;', '//VTK::Position::Impl']).result;
|
|
@@ -160,16 +182,38 @@ function vtkWebGPUCellArrayMapper(publicAPI, model) {
|
|
|
160
182
|
|
|
161
183
|
publicAPI.replaceShaderNormal = function (hash, pipeline, vertexInput) {
|
|
162
184
|
var normalBuffer = vertexInput.getBuffer('normalMC');
|
|
185
|
+
var actor = model.WebGPUActor.getRenderable();
|
|
163
186
|
|
|
164
187
|
if (normalBuffer) {
|
|
165
188
|
var vDesc = pipeline.getShaderDescription('vertex');
|
|
166
|
-
|
|
189
|
+
|
|
190
|
+
if (!vDesc.hasOutput('normalVC')) {
|
|
191
|
+
vDesc.addOutput('vec3<f32>', 'normalVC', normalBuffer.getArrayInformation()[0].interpolation);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (!vDesc.hasOutput('tangentVC')) {
|
|
195
|
+
vDesc.addOutput('vec3<f32>', 'tangentVC', normalBuffer.getArrayInformation()[0].interpolation);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (!vDesc.hasOutput('bitangentVC')) {
|
|
199
|
+
vDesc.addOutput('vec3<f32>', 'bitangentVC', normalBuffer.getArrayInformation()[0].interpolation);
|
|
200
|
+
}
|
|
201
|
+
|
|
167
202
|
var code = vDesc.getCode();
|
|
168
|
-
code = vtkWebGPUShaderCache.substitute(code, '//VTK::Normal::Impl', [' output.normalVC = normalize((rendererUBO.WCVCNormals * mapperUBO.MCWCNormals * normalMC).xyz);'
|
|
203
|
+
code = vtkWebGPUShaderCache.substitute(code, '//VTK::Normal::Impl', [' output.normalVC = normalize((rendererUBO.WCVCNormals * mapperUBO.MCWCNormals * normalMC).xyz);', // This is just an approximation, but it happens to work extremely well
|
|
204
|
+
// It only works well for normals that are head on and not super angled though
|
|
205
|
+
// Definitely needs to be replaced
|
|
206
|
+
' var c1: vec3<f32> = cross(output.normalVC, vec3<f32>(0, 0, 1));', ' var c2: vec3<f32> = cross(output.normalVC, vec3<f32>(0, 1, 0));', ' var tangent: vec3<f32> = mix(c1, c2, distance(c1, c2));', ' output.tangentVC = normalize(tangent);', ' output.bitangentVC = normalize(cross(output.normalVC, tangent));']).result;
|
|
169
207
|
vDesc.setCode(code);
|
|
170
208
|
var fDesc = pipeline.getShaderDescription('fragment');
|
|
171
209
|
code = fDesc.getCode();
|
|
172
|
-
|
|
210
|
+
|
|
211
|
+
if (actor.getProperty().getNormalTexture()) {
|
|
212
|
+
code = vtkWebGPUShaderCache.substitute(code, '//VTK::Normal::Impl', [' var normal: vec3<f32> = input.normalVC;', ' if (!input.frontFacing) { normal = -normal; }', ' var tangent: vec3<f32> = input.tangentVC;', ' var bitangent: vec3<f32> = input.bitangentVC;', ' var TCVCMatrix: mat3x3<f32> = mat3x3<f32>(', ' tangent.x, bitangent.x, normal.x,', ' tangent.y, bitangent.y, normal.y,', ' tangent.z, bitangent.z, normal.z,', ' );', ' normal = TCVCMatrix * (_normalMap.xyz * 2 - 1);', ' normal = mix(input.normalVC, normal, mapperUBO.NormalStrength);', ' normal = normalize(normal);']).result;
|
|
213
|
+
} else {
|
|
214
|
+
code = vtkWebGPUShaderCache.substitute(code, '//VTK::Normal::Impl', [' var normal: vec3<f32> = input.normalVC;', ' if (!input.frontFacing) { normal = -normal; }', ' normal = normalize(normal);']).result;
|
|
215
|
+
}
|
|
216
|
+
|
|
173
217
|
fDesc.setCode(code);
|
|
174
218
|
}
|
|
175
219
|
};
|
|
@@ -178,14 +222,24 @@ function vtkWebGPUCellArrayMapper(publicAPI, model) {
|
|
|
178
222
|
// fragment shader code. That is the lighting trigger.
|
|
179
223
|
|
|
180
224
|
publicAPI.replaceShaderLight = function (hash, pipeline, vertexInput) {
|
|
225
|
+
if (hash.includes('sel')) return;
|
|
226
|
+
var vDesc = pipeline.getShaderDescription('vertex');
|
|
227
|
+
if (!vDesc.hasOutput('vertexVC')) vDesc.addOutput('vec4<f32>', 'vertexVC');
|
|
181
228
|
var fDesc = pipeline.getShaderDescription('fragment');
|
|
182
|
-
var code = fDesc.getCode();
|
|
183
|
-
|
|
184
|
-
if (code.includes('var normal')) {
|
|
185
|
-
code = vtkWebGPUShaderCache.substitute(code, '//VTK::Light::Impl', [
|
|
186
|
-
|
|
229
|
+
var code = fDesc.getCode(); // Code that runs if the fragment shader includes normals
|
|
230
|
+
|
|
231
|
+
if (code.includes('var normal:') && model.useRendererMatrix && !isEdges(hash) && !model.is2D && !hash.includes('sel')) {
|
|
232
|
+
code = vtkWebGPUShaderCache.substitute(code, '//VTK::Light::Impl', [// Constants
|
|
233
|
+
' var pi: f32 = 3.14159265359;', // Vectors needed for light calculations
|
|
234
|
+
' var fragPos: vec3<f32> = vec3<f32>(input.vertexVC.xyz);', ' var V: vec3<f32> = mix(normalize(-fragPos), vec3<f32>(0, 0, 1), f32(rendererUBO.cameraParallel)); // View Vector', // Values needed for light calculations
|
|
235
|
+
' var baseColor: vec3<f32> = _diffuseMap.rgb * diffuseColor.rgb;', ' var roughness: f32 = max(0.000001, mapperUBO.Roughness * _roughnessMap.r);', // Need to have a different way of sampling greyscale values aside from .r
|
|
236
|
+
' var metallic: f32 = mapperUBO.Metallic * _metallicMap.r;', ' var alpha: f32 = roughness*roughness;', ' var ior: f32 = mapperUBO.BaseIOR;', ' var k: f32 = alpha*alpha / 2;', // Split diffuse and specular components
|
|
237
|
+
' var diffuse: vec3<f32> = vec3<f32>(0.);', ' var specular: vec3<f32> = vec3<f32>(0.);', ' var emission: vec3<f32> = _emissionMap.rgb * mapperUBO.Emission;', // Summing diffuse and specular components of directional lights
|
|
238
|
+
' {', ' var i: i32 = 0;', ' loop {', ' if !(i < rendererUBO.LightCount) { break; }', ' switch (i32(rendererLightSSBO.values[i].LightData.x)) {', ' // Point Light', ' case 0 {', ' var color: vec3<f32> = rendererLightSSBO.values[i].LightColor.rgb * rendererLightSSBO.values[i].LightColor.w;', ' var pos: vec3<f32> = (rendererLightSSBO.values[i].LightPos).xyz;', ' var calculated: PBRData = calcPointLight(normal, V, fragPos, ior, roughness, metallic, pos, color, baseColor);', ' diffuse += max(vec3<f32>(0), calculated.diffuse);', ' specular += max(vec3<f32>(0), calculated.specular);', ' }', ' // Directional light', ' case 1 {', ' var dir: vec3<f32> = (rendererUBO.WCVCNormals * vec4<f32>(normalize(rendererLightSSBO.values[i].LightDir.xyz), 0.)).xyz;', ' dir = normalize(dir);', ' var color: vec3<f32> = rendererLightSSBO.values[i].LightColor.rgb * rendererLightSSBO.values[i].LightColor.w;', ' var calculated: PBRData = calcDirectionalLight(normal, V, ior, roughness, metallic, dir, color, baseColor); // diffuseColor.rgb needs to be fixed with a more dynamic diffuse color', ' diffuse += max(vec3<f32>(0), calculated.diffuse);', ' specular += max(vec3<f32>(0), calculated.specular);', ' }', ' // Spot Light', ' case 2 {', ' var color: vec3<f32> = rendererLightSSBO.values[i].LightColor.rgb * rendererLightSSBO.values[i].LightColor.w;', ' var pos: vec3<f32> = (rendererLightSSBO.values[i].LightPos).xyz;', ' var dir: vec3<f32> = (rendererUBO.WCVCNormals * vec4<f32>(normalize(rendererLightSSBO.values[i].LightDir.xyz), 0.)).xyz;', ' dir = normalize(dir);', ' var cones: vec2<f32> = vec2<f32>(rendererLightSSBO.values[i].LightData.y, rendererLightSSBO.values[i].LightData.z);', ' var calculated: PBRData = calcSpotLight(normal, V, fragPos, ior, roughness, metallic, pos, dir, cones, color, baseColor);', ' diffuse += max(vec3<f32>(0), calculated.diffuse);', ' specular += max(vec3<f32>(0), calculated.specular);', ' }', ' default { continue; }', ' }', ' continuing { i++; }', ' }', ' }', // Final variables for combining specular and diffuse
|
|
239
|
+
' var fresnel: f32 = schlickFresnelIOR(V, normal, ior, k); // Fresnel', ' fresnel = min(1, fresnel);', ' // This could be controlled with its own variable (that isnt base color) for better artistic control', ' var fresnelMetallic: vec3<f32> = schlickFresnelRGB(V, normal, baseColor); // Fresnel for metal, takes color into account', ' var kS: vec3<f32> = mix(vec3<f32>(fresnel), fresnelMetallic, metallic);', ' kS = min(vec3<f32>(1), kS);', ' var kD: vec3<f32> = (1.0 - kS) * (1.0 - metallic);', ' var PBR: vec3<f32> = mapperUBO.DiffuseIntensity*kD*diffuse + kS*specular;', ' PBR += emission;', ' computedColor = vec4<f32>(PBR, mapperUBO.Opacity);']).result;
|
|
240
|
+
fDesc.setCode(code); // If theres no normals, just set the specular color to be flat
|
|
187
241
|
} else {
|
|
188
|
-
code = vtkWebGPUShaderCache.substitute(code, '//VTK::Light::Impl', [' var diffuse: vec3<f32> = diffuseColor.rgb;', ' var specular: vec3<f32> = mapperUBO.SpecularColor.rgb * mapperUBO.SpecularColor.a;']).result;
|
|
242
|
+
code = vtkWebGPUShaderCache.substitute(code, '//VTK::Light::Impl', [' var diffuse: vec3<f32> = diffuseColor.rgb;', ' var specular: vec3<f32> = mapperUBO.SpecularColor.rgb * mapperUBO.SpecularColor.a;', ' computedColor = vec4<f32>(diffuse, mapperUBO.Opacity);']).result;
|
|
189
243
|
fDesc.setCode(code);
|
|
190
244
|
}
|
|
191
245
|
};
|
|
@@ -193,6 +247,7 @@ function vtkWebGPUCellArrayMapper(publicAPI, model) {
|
|
|
193
247
|
model.shaderReplacements.set('replaceShaderLight', publicAPI.replaceShaderLight);
|
|
194
248
|
|
|
195
249
|
publicAPI.replaceShaderColor = function (hash, pipeline, vertexInput) {
|
|
250
|
+
// By default, set the colors to be flat
|
|
196
251
|
if (isEdges(hash)) {
|
|
197
252
|
var _fDesc = pipeline.getShaderDescription('fragment');
|
|
198
253
|
|
|
@@ -203,15 +258,18 @@ function vtkWebGPUCellArrayMapper(publicAPI, model) {
|
|
|
203
258
|
_fDesc.setCode(_code);
|
|
204
259
|
|
|
205
260
|
return;
|
|
206
|
-
}
|
|
261
|
+
} // If there's no vertex color buffer return the shader as is
|
|
262
|
+
|
|
207
263
|
|
|
208
264
|
var colorBuffer = vertexInput.getBuffer('colorVI');
|
|
209
|
-
if (!colorBuffer) return;
|
|
265
|
+
if (!colorBuffer) return; // Modifies the vertex shader to include the vertex colors and interpolation in the outputs
|
|
266
|
+
|
|
210
267
|
var vDesc = pipeline.getShaderDescription('vertex');
|
|
211
268
|
vDesc.addOutput('vec4<f32>', 'color', colorBuffer.getArrayInformation()[0].interpolation);
|
|
212
269
|
var code = vDesc.getCode();
|
|
213
270
|
code = vtkWebGPUShaderCache.substitute(code, '//VTK::Color::Impl', [' output.color = colorVI;']).result;
|
|
214
|
-
vDesc.setCode(code);
|
|
271
|
+
vDesc.setCode(code); // Sets the fragment shader to accept the color inputs from the vertex shader
|
|
272
|
+
|
|
215
273
|
var fDesc = pipeline.getShaderDescription('fragment');
|
|
216
274
|
code = fDesc.getCode();
|
|
217
275
|
code = vtkWebGPUShaderCache.substitute(code, '//VTK::Color::Impl', ['ambientColor = input.color;', 'diffuseColor = input.color;', 'opacity = mapperUBO.Opacity * input.color.a;']).result;
|
|
@@ -221,19 +279,70 @@ function vtkWebGPUCellArrayMapper(publicAPI, model) {
|
|
|
221
279
|
model.shaderReplacements.set('replaceShaderColor', publicAPI.replaceShaderColor);
|
|
222
280
|
|
|
223
281
|
publicAPI.replaceShaderTCoord = function (hash, pipeline, vertexInput) {
|
|
282
|
+
var _actor$getProperty$ge, _actor$getProperty, _actor$getProperty$ge2, _actor$getProperty$ge4, _actor$getProperty3, _actor$getProperty$ge5, _actor$getProperty$ge6, _actor$getProperty4, _actor$getProperty$ge7, _actor$getProperty$ge8, _actor$getProperty5, _actor$getProperty$ge9, _actor$getProperty$ge10, _actor$getProperty6, _actor$getProperty$ge11, _actor$getProperty$ge12, _actor$getProperty7, _actor$getProperty$ge13;
|
|
283
|
+
|
|
224
284
|
if (!vertexInput.hasAttribute('tcoord')) return;
|
|
225
285
|
var vDesc = pipeline.getShaderDescription('vertex');
|
|
226
|
-
|
|
286
|
+
var tcoords = vertexInput.getBuffer('tcoord');
|
|
287
|
+
var numComp = vtkWebGPUTypes.getNumberOfComponentsFromBufferFormat(tcoords.getArrayInformation()[0].format);
|
|
227
288
|
var code = vDesc.getCode();
|
|
228
|
-
|
|
289
|
+
vDesc.addOutput("vec".concat(numComp, "<f32>"), 'tcoordVS');
|
|
290
|
+
code = vtkWebGPUShaderCache.substitute(code, '//VTK::TCoord::Impl', [' output.tcoordVS = tcoord;' // Ensure that UV coordinates are always between 0-1
|
|
291
|
+
]).result;
|
|
229
292
|
vDesc.setCode(code);
|
|
293
|
+
if (model.is2D) return;
|
|
230
294
|
var fDesc = pipeline.getShaderDescription('fragment');
|
|
231
|
-
code = fDesc.getCode();
|
|
295
|
+
code = fDesc.getCode();
|
|
296
|
+
var actor = model.WebGPUActor.getRenderable();
|
|
297
|
+
|
|
298
|
+
var checkDims = function checkDims(texture) {
|
|
299
|
+
if (!texture) return false;
|
|
300
|
+
var dims = texture.getDimensionality();
|
|
301
|
+
return dims === numComp;
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
var usedTextures = [];
|
|
305
|
+
|
|
306
|
+
if ((_actor$getProperty$ge = (_actor$getProperty = actor.getProperty()).getDiffuseTexture) !== null && _actor$getProperty$ge !== void 0 && (_actor$getProperty$ge2 = _actor$getProperty$ge.call(_actor$getProperty)) !== null && _actor$getProperty$ge2 !== void 0 && _actor$getProperty$ge2.getImageLoaded() || actor.getTextures()[0] || model.colorTexture) {
|
|
307
|
+
var _actor$getProperty$ge3, _actor$getProperty2;
|
|
232
308
|
|
|
233
|
-
|
|
234
|
-
|
|
309
|
+
if ( // Chained or statements here are questionable
|
|
310
|
+
checkDims((_actor$getProperty$ge3 = (_actor$getProperty2 = actor.getProperty()).getDiffuseTexture) === null || _actor$getProperty$ge3 === void 0 ? void 0 : _actor$getProperty$ge3.call(_actor$getProperty2)) || checkDims(actor.getTextures()[0]) || checkDims(model.colorTexture)) {
|
|
311
|
+
usedTextures.push('_diffuseMap = textureSample(DiffuseTexture, DiffuseTextureSampler, input.tcoordVS);');
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
if ((_actor$getProperty$ge4 = (_actor$getProperty3 = actor.getProperty()).getRoughnessTexture) !== null && _actor$getProperty$ge4 !== void 0 && (_actor$getProperty$ge5 = _actor$getProperty$ge4.call(_actor$getProperty3)) !== null && _actor$getProperty$ge5 !== void 0 && _actor$getProperty$ge5.getImageLoaded()) {
|
|
316
|
+
if (checkDims(actor.getProperty().getRoughnessTexture())) {
|
|
317
|
+
usedTextures.push('_roughnessMap = textureSample(RoughnessTexture, RoughnessTextureSampler, input.tcoordVS);');
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
if ((_actor$getProperty$ge6 = (_actor$getProperty4 = actor.getProperty()).getMetallicTexture) !== null && _actor$getProperty$ge6 !== void 0 && (_actor$getProperty$ge7 = _actor$getProperty$ge6.call(_actor$getProperty4)) !== null && _actor$getProperty$ge7 !== void 0 && _actor$getProperty$ge7.getImageLoaded()) {
|
|
322
|
+
if (checkDims(actor.getProperty().getMetallicTexture())) {
|
|
323
|
+
usedTextures.push('_metallicMap = textureSample(MetallicTexture, MetallicTextureSampler, input.tcoordVS);');
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
if ((_actor$getProperty$ge8 = (_actor$getProperty5 = actor.getProperty()).getNormalTexture) !== null && _actor$getProperty$ge8 !== void 0 && (_actor$getProperty$ge9 = _actor$getProperty$ge8.call(_actor$getProperty5)) !== null && _actor$getProperty$ge9 !== void 0 && _actor$getProperty$ge9.getImageLoaded()) {
|
|
328
|
+
if (checkDims(actor.getProperty().getNormalTexture())) {
|
|
329
|
+
usedTextures.push('_normalMap = textureSample(NormalTexture, NormalTextureSampler, input.tcoordVS);');
|
|
330
|
+
}
|
|
235
331
|
}
|
|
236
332
|
|
|
333
|
+
if ((_actor$getProperty$ge10 = (_actor$getProperty6 = actor.getProperty()).getAmbientOcclusionTexture) !== null && _actor$getProperty$ge10 !== void 0 && (_actor$getProperty$ge11 = _actor$getProperty$ge10.call(_actor$getProperty6)) !== null && _actor$getProperty$ge11 !== void 0 && _actor$getProperty$ge11.getImageLoaded()) {
|
|
334
|
+
if (checkDims(actor.getProperty().getAmbientOcclusionTexture())) {
|
|
335
|
+
usedTextures.push('_ambientOcclusionMap = textureSample(AmbientOcclusionTexture, AmbientOcclusionTextureSampler, input.tcoordVS);');
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
if ((_actor$getProperty$ge12 = (_actor$getProperty7 = actor.getProperty()).getEmissionTexture) !== null && _actor$getProperty$ge12 !== void 0 && (_actor$getProperty$ge13 = _actor$getProperty$ge12.call(_actor$getProperty7)) !== null && _actor$getProperty$ge13 !== void 0 && _actor$getProperty$ge13.getImageLoaded()) {
|
|
340
|
+
if (checkDims(actor.getProperty().getEmissionTexture())) {
|
|
341
|
+
usedTextures.push('_emissionMap = textureSample(EmissionTexture, EmissionTextureSampler, input.tcoordVS);');
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
code = vtkWebGPUShaderCache.substitute(code, '//VTK::TCoord::Impl', usedTextures).result;
|
|
237
346
|
fDesc.setCode(code);
|
|
238
347
|
};
|
|
239
348
|
|
|
@@ -300,7 +409,8 @@ function vtkWebGPUCellArrayMapper(publicAPI, model) {
|
|
|
300
409
|
default:
|
|
301
410
|
return 'line-list';
|
|
302
411
|
}
|
|
303
|
-
};
|
|
412
|
+
}; // TODO: calculate tangents
|
|
413
|
+
|
|
304
414
|
|
|
305
415
|
publicAPI.buildVertexInput = function () {
|
|
306
416
|
var _model$renderable$get, _model$renderable;
|
|
@@ -366,10 +476,13 @@ function vtkWebGPUCellArrayMapper(publicAPI, model) {
|
|
|
366
476
|
|
|
367
477
|
|
|
368
478
|
var usage = publicAPI.getUsage(representation, primType);
|
|
479
|
+
model._usesCellNormals = false;
|
|
369
480
|
|
|
370
481
|
if (!model.is2D && ( // no lighting on Property2D
|
|
371
482
|
usage === BufferUsage.Triangles || usage === BufferUsage.Strips)) {
|
|
372
|
-
var normals = pd.getPointData().getNormals();
|
|
483
|
+
var normals = pd.getPointData().getNormals(); // https://vtk.org/doc/nightly/html/classvtkPolyDataTangents.html
|
|
484
|
+
// Need to find some way of using precomputed tangents (or computing new ones)
|
|
485
|
+
|
|
373
486
|
var _buffRequest2 = {
|
|
374
487
|
format: 'snorm8x4',
|
|
375
488
|
indexBuffer: indexBuffer,
|
|
@@ -387,6 +500,7 @@ function vtkWebGPUCellArrayMapper(publicAPI, model) {
|
|
|
387
500
|
|
|
388
501
|
vertexInput.addBuffer(_buff, ['normalMC']);
|
|
389
502
|
} else if (primType === PrimitiveTypes.Triangles) {
|
|
503
|
+
model._usesCellNormals = true;
|
|
390
504
|
_buffRequest2.hash = "PFN".concat(points.getMTime(), "I").concat(indexBuffer.getMTime(), "snorm8x4");
|
|
391
505
|
_buffRequest2.dataArray = points;
|
|
392
506
|
_buffRequest2.cells = cells;
|
|
@@ -455,7 +569,7 @@ function vtkWebGPUCellArrayMapper(publicAPI, model) {
|
|
|
455
569
|
};
|
|
456
570
|
|
|
457
571
|
publicAPI.updateTextures = function () {
|
|
458
|
-
var _model$renderable$get2, _model$renderable2;
|
|
572
|
+
var _model$renderable$get2, _model$renderable2, _actor$getProperty$ge14, _actor$getProperty8, _actor$getProperty$ge15, _actor$getProperty9, _actor$getProperty$ge16, _actor$getProperty10, _actor$getProperty$ge17, _actor$getProperty11, _actor$getProperty$ge18, _actor$getProperty12, _actor$getProperty$ge19, _actor$getProperty13, _renderer$getBackgrou;
|
|
459
573
|
|
|
460
574
|
// we keep track of new and used textures so
|
|
461
575
|
// that we can clean up any unused textures so we don't hold onto them
|
|
@@ -472,28 +586,69 @@ function vtkWebGPUCellArrayMapper(publicAPI, model) {
|
|
|
472
586
|
}
|
|
473
587
|
|
|
474
588
|
model.colorTexture.setInputData(idata);
|
|
475
|
-
newTextures.push(model.colorTexture);
|
|
589
|
+
newTextures.push(['Diffuse', model.colorTexture]);
|
|
476
590
|
} // actor textures?
|
|
477
591
|
|
|
478
592
|
|
|
479
593
|
var actor = model.WebGPUActor.getRenderable();
|
|
480
|
-
var
|
|
594
|
+
var renderer = model.WebGPURenderer.getRenderable(); // Reusing the old code for new and old textures, just loading in from properties instead of actor.getTextures()
|
|
595
|
+
|
|
596
|
+
var textures = []; // Feels like there should be a better way than individually adding all
|
|
597
|
+
|
|
598
|
+
if ((_actor$getProperty$ge14 = (_actor$getProperty8 = actor.getProperty()).getDiffuseTexture) !== null && _actor$getProperty$ge14 !== void 0 && _actor$getProperty$ge14.call(_actor$getProperty8)) {
|
|
599
|
+
var pair = ['Diffuse', actor.getProperty().getDiffuseTexture()];
|
|
600
|
+
textures.push(pair);
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
if (actor.getTextures()[0]) {
|
|
604
|
+
var _pair = ['Diffuse', actor.getTextures()[0]];
|
|
605
|
+
textures.push(_pair);
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
if ((_actor$getProperty$ge15 = (_actor$getProperty9 = actor.getProperty()).getRoughnessTexture) !== null && _actor$getProperty$ge15 !== void 0 && _actor$getProperty$ge15.call(_actor$getProperty9)) {
|
|
609
|
+
var _pair2 = ['Roughness', actor.getProperty().getRoughnessTexture()];
|
|
610
|
+
textures.push(_pair2);
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
if ((_actor$getProperty$ge16 = (_actor$getProperty10 = actor.getProperty()).getMetallicTexture) !== null && _actor$getProperty$ge16 !== void 0 && _actor$getProperty$ge16.call(_actor$getProperty10)) {
|
|
614
|
+
var _pair3 = ['Metallic', actor.getProperty().getMetallicTexture()];
|
|
615
|
+
textures.push(_pair3);
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
if ((_actor$getProperty$ge17 = (_actor$getProperty11 = actor.getProperty()).getNormalTexture) !== null && _actor$getProperty$ge17 !== void 0 && _actor$getProperty$ge17.call(_actor$getProperty11)) {
|
|
619
|
+
var _pair4 = ['Normal', actor.getProperty().getNormalTexture()];
|
|
620
|
+
textures.push(_pair4);
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
if ((_actor$getProperty$ge18 = (_actor$getProperty12 = actor.getProperty()).getAmbientOcclusionTexture) !== null && _actor$getProperty$ge18 !== void 0 && _actor$getProperty$ge18.call(_actor$getProperty12)) {
|
|
624
|
+
var _pair5 = ['AmbientOcclusion', actor.getProperty().getAmbientOcclusionTexture()];
|
|
625
|
+
textures.push(_pair5);
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
if ((_actor$getProperty$ge19 = (_actor$getProperty13 = actor.getProperty()).getEmissionTexture) !== null && _actor$getProperty$ge19 !== void 0 && _actor$getProperty$ge19.call(_actor$getProperty13)) {
|
|
629
|
+
var _pair6 = ['Emission', actor.getProperty().getEmissionTexture()];
|
|
630
|
+
textures.push(_pair6);
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
if ((_renderer$getBackgrou = renderer.getBackgroundTexture) !== null && _renderer$getBackgrou !== void 0 && _renderer$getBackgrou.call(renderer)) {
|
|
634
|
+
var _pair7 = ['Background', renderer.getBackgroundTexture()];
|
|
635
|
+
textures.push(_pair7);
|
|
636
|
+
}
|
|
481
637
|
|
|
482
638
|
for (var i = 0; i < textures.length; i++) {
|
|
483
|
-
if (textures[i].getInputData() || textures[i].getJsImageData() || textures[i].getCanvas()) {
|
|
639
|
+
if (textures[i][1].getInputData() || textures[i][1].getJsImageData() || textures[i][1].getCanvas()) {
|
|
484
640
|
newTextures.push(textures[i]);
|
|
485
641
|
}
|
|
486
642
|
|
|
487
|
-
if (textures[i].getImage() && textures[i].getImageLoaded()) {
|
|
643
|
+
if (textures[i][1].getImage() && textures[i][1].getImageLoaded()) {
|
|
488
644
|
newTextures.push(textures[i]);
|
|
489
645
|
}
|
|
490
646
|
}
|
|
491
647
|
|
|
492
|
-
var usedCount = 0;
|
|
493
|
-
|
|
494
648
|
for (var _i = 0; _i < newTextures.length; _i++) {
|
|
495
|
-
var srcTexture = newTextures[_i];
|
|
496
|
-
var
|
|
649
|
+
var srcTexture = newTextures[_i][1];
|
|
650
|
+
var textureName = newTextures[_i][0];
|
|
651
|
+
var newTex = model.device.getTextureManager().getTextureForVTKTexture(srcTexture); // Generates hash
|
|
497
652
|
|
|
498
653
|
if (newTex.getReady()) {
|
|
499
654
|
// is this a new texture
|
|
@@ -501,7 +656,6 @@ function vtkWebGPUCellArrayMapper(publicAPI, model) {
|
|
|
501
656
|
|
|
502
657
|
for (var t = 0; t < model.textures.length; t++) {
|
|
503
658
|
if (model.textures[t] === newTex) {
|
|
504
|
-
usedCount++;
|
|
505
659
|
found = true;
|
|
506
660
|
usedTextures[t] = true;
|
|
507
661
|
}
|
|
@@ -509,7 +663,7 @@ function vtkWebGPUCellArrayMapper(publicAPI, model) {
|
|
|
509
663
|
|
|
510
664
|
if (!found) {
|
|
511
665
|
usedTextures[model.textures.length] = true;
|
|
512
|
-
var tview = newTex.createView("
|
|
666
|
+
var tview = newTex.createView("".concat(textureName, "Texture"));
|
|
513
667
|
model.textures.push(newTex);
|
|
514
668
|
model.textureViews.push(tview);
|
|
515
669
|
var interpolate = srcTexture.getInterpolate() ? 'linear' : 'nearest';
|
|
@@ -548,7 +702,9 @@ function vtkWebGPUCellArrayMapper(publicAPI, model) {
|
|
|
548
702
|
}
|
|
549
703
|
|
|
550
704
|
if (model.vertexInput.hasAttribute("tcoord")) {
|
|
551
|
-
|
|
705
|
+
var tcoords = model.vertexInput.getBuffer('tcoord');
|
|
706
|
+
var numComp = vtkWebGPUTypes.getNumberOfComponentsFromBufferFormat(tcoords.getArrayInformation()[0].format);
|
|
707
|
+
pipelineHash += "t".concat(numComp);
|
|
552
708
|
}
|
|
553
709
|
|
|
554
710
|
if (model.textures.length) {
|
|
@@ -556,6 +712,10 @@ function vtkWebGPUCellArrayMapper(publicAPI, model) {
|
|
|
556
712
|
}
|
|
557
713
|
}
|
|
558
714
|
|
|
715
|
+
if (model._usesCellNormals) {
|
|
716
|
+
pipelineHash += "cn";
|
|
717
|
+
}
|
|
718
|
+
|
|
559
719
|
if (model.SSBO) {
|
|
560
720
|
pipelineHash += "ssbo";
|
|
561
721
|
}
|
|
@@ -606,14 +766,15 @@ var DEFAULT_VALUES = {
|
|
|
606
766
|
}; // ----------------------------------------------------------------------------
|
|
607
767
|
|
|
608
768
|
function extend(publicAPI, model) {
|
|
609
|
-
var
|
|
610
|
-
Object.assign(model, DEFAULT_VALUES,
|
|
769
|
+
var initiaLalues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
770
|
+
Object.assign(model, DEFAULT_VALUES, initiaLalues); // Inheritance
|
|
611
771
|
|
|
612
|
-
vtkWebGPUSimpleMapper.extend(publicAPI, model,
|
|
772
|
+
vtkWebGPUSimpleMapper.extend(publicAPI, model, initiaLalues);
|
|
613
773
|
model.fragmentShaderTemplate = vtkWebGPUPolyDataFS;
|
|
614
774
|
model.vertexShaderTemplate = vtkWebGPUPolyDataVS;
|
|
615
775
|
model._tmpMat3 = mat3.identity(new Float64Array(9));
|
|
616
|
-
model._tmpMat4 = mat4.identity(new Float64Array(16));
|
|
776
|
+
model._tmpMat4 = mat4.identity(new Float64Array(16)); // UBO
|
|
777
|
+
|
|
617
778
|
model.UBO = vtkWebGPUUniformBuffer.newInstance({
|
|
618
779
|
label: 'mapperUBO'
|
|
619
780
|
});
|
|
@@ -626,12 +787,21 @@ function extend(publicAPI, model) {
|
|
|
626
787
|
model.UBO.addEntry('SpecularColor', 'vec4<f32>');
|
|
627
788
|
model.UBO.addEntry('AmbientIntensity', 'f32');
|
|
628
789
|
model.UBO.addEntry('DiffuseIntensity', 'f32');
|
|
790
|
+
model.UBO.addEntry('Roughness', 'f32');
|
|
791
|
+
model.UBO.addEntry('Metallic', 'f32');
|
|
792
|
+
model.UBO.addEntry('Ambient', 'f32');
|
|
793
|
+
model.UBO.addEntry('Normal', 'f32');
|
|
794
|
+
model.UBO.addEntry('Emission', 'f32');
|
|
795
|
+
model.UBO.addEntry('NormalStrength', 'f32');
|
|
796
|
+
model.UBO.addEntry('BaseIOR', 'f32');
|
|
629
797
|
model.UBO.addEntry('SpecularIntensity', 'f32');
|
|
630
798
|
model.UBO.addEntry('LineWidth', 'f32');
|
|
631
799
|
model.UBO.addEntry('Opacity', 'f32');
|
|
632
|
-
model.UBO.addEntry('SpecularPower', 'f32');
|
|
633
800
|
model.UBO.addEntry('ZValue', 'f32');
|
|
634
|
-
model.UBO.addEntry('PropID', 'u32');
|
|
801
|
+
model.UBO.addEntry('PropID', 'u32');
|
|
802
|
+
model.UBO.addEntry('ClipNear', 'f32');
|
|
803
|
+
model.UBO.addEntry('ClipFar', 'f32');
|
|
804
|
+
model.UBO.addEntry('Time', 'u32'); // Build VTK API
|
|
635
805
|
|
|
636
806
|
setGet(publicAPI, model, ['cellArray', 'currentInput', 'cellOffset', 'is2D', 'primitiveType', 'renderEncoder']);
|
|
637
807
|
model.textures = []; // Object methods
|
|
@@ -29,8 +29,9 @@ function vtkWebGPUGlyph3DCellArrayMapper(publicAPI, model) {
|
|
|
29
29
|
var vDesc = pipeline.getShaderDescription('vertex');
|
|
30
30
|
vDesc.addBuiltinInput('u32', '@builtin(instance_index) instanceIndex');
|
|
31
31
|
vDesc.addBuiltinOutput('vec4<f32>', '@builtin(position) Position');
|
|
32
|
+
if (!vDesc.hasOutput('vertexVC')) vDesc.addOutput('vec3<f32>', 'vertexVC');
|
|
32
33
|
var code = vDesc.getCode();
|
|
33
|
-
code = vtkWebGPUShaderCache.substitute(code, '//VTK::Position::Impl', ['
|
|
34
|
+
code = vtkWebGPUShaderCache.substitute(code, '//VTK::Position::Impl', [' var vertexSC: vec4<f32> = mapperUBO.BCSCMatrix*glyphSSBO.values[input.instanceIndex].matrix*vertexBC;', ' output.vertexVC = (rendererUBO.SCVCMatrix*vertexSC).xyz;', ' output.Position = rendererUBO.SCPCMatrix*vertexSC;']).result;
|
|
34
35
|
vDesc.setCode(code);
|
|
35
36
|
};
|
|
36
37
|
|