Skip to content

Commit 33b07ed

Browse files
author
Mike Bond
committed
Handle vertex pulling of different data type
1 parent 3d8897e commit 33b07ed

File tree

3 files changed

+267
-110
lines changed

3 files changed

+267
-110
lines changed

packages/dev/core/src/Materials/materialHelper.functions.ts

Lines changed: 99 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ import { Texture } from "./Textures/texture";
2323
import type { CubeTexture } from "./Textures/cubeTexture";
2424
import type { Color3 } from "core/Maths/math.color";
2525
import { GetTypeByteLength } from "../Buffers/bufferUtils";
26+
import type { Geometry } from "../Meshes/geometry";
27+
import { Vector3 } from "core/Maths/math.vector";
2628

2729
// For backwards compatibility, we export everything from the pure version of this file.
2830
export * from "./materialHelper.functions.pure";
@@ -600,24 +602,105 @@ export function GetFogState(mesh: AbstractMesh, scene: Scene) {
600602
}
601603

602604
/**
603-
* Helper used to prepare vertex pulling metadata defines (stride, offset, component count)
604-
* This should be called when USE_VERTEX_PULLING is enabled to properly configure buffer access
605-
* @param mesh The mesh being rendered
606-
* @param defines The defines object to update
607-
* @param attributeNames Array of attribute names to configure (e.g., ["position", "normal"])
605+
* Interface representing metadata for vertex pulling
608606
*/
609-
export function PrepareDefinesForVertexPullingMetadata(mesh: AbstractMesh, defines: any, attributeNames: string[] = ["position"]): void {
610-
if (!defines["USE_VERTEX_PULLING"]) {
607+
export interface IVertexPullingMetadata {
608+
/**
609+
* Offset in vertex buffer where data starts
610+
*/
611+
offset: number;
612+
613+
/**
614+
* Stride between elements in the vertex buffer
615+
*/
616+
stride: number;
617+
618+
/**
619+
* Type of the vertex buffer (e.g., float, int)
620+
*/
621+
type: number; // VertexBuffer type constant
622+
}
623+
624+
// Store vertex pulling metadata per geometry
625+
const _VertexPullingMetadataCache = new WeakMap<Geometry, Map<string, IVertexPullingMetadata>>();
626+
627+
/**
628+
* Prepares vertex pulling uniforms for the given attributes and mesh
629+
* @param geometry The geometry containing the vertex buffers
630+
* @returns A map of attribute names to their metadata, or null if unavailable
631+
*/
632+
export function PrepareVertexPullingUniforms(geometry: Geometry): Nullable<Map<string, IVertexPullingMetadata>> {
633+
if (!geometry) {
634+
return null;
635+
}
636+
const vertexBuffers = geometry.getVertexBuffers();
637+
if (!vertexBuffers) {
638+
return null;
639+
}
640+
641+
// Check cache first
642+
let metadata = _VertexPullingMetadataCache.get(geometry);
643+
if (!metadata) {
644+
metadata = new Map<string, IVertexPullingMetadata>();
645+
_VertexPullingMetadataCache.set(geometry, metadata);
646+
} else {
647+
// Return cached metadata if it exists and hasn't changed
648+
let needsUpdate = false;
649+
for (const vb in vertexBuffers) {
650+
if (!metadata.has(vb)) {
651+
needsUpdate = true;
652+
break;
653+
}
654+
}
655+
if (!needsUpdate) {
656+
return metadata;
657+
}
658+
}
659+
660+
// Build or update metadata
661+
for (const vb in vertexBuffers) {
662+
const vertexBuffer = vertexBuffers[vb];
663+
if (vertexBuffer) {
664+
const offset = vertexBuffer.byteOffset;
665+
const stride = vertexBuffer.byteStride;
666+
const type = vertexBuffer.type;
667+
668+
metadata.set(vb, {
669+
offset: offset,
670+
stride: stride,
671+
type: type,
672+
});
673+
}
674+
}
675+
676+
return metadata;
677+
}
678+
679+
export function BindVertexPullingUniforms(effect: Effect, metadata: Map<string, IVertexPullingMetadata>): void {
680+
if (!metadata || !effect) {
611681
return;
612682
}
613683

614-
const geometry = mesh.geometry;
684+
for (const [attribute, data] of metadata) {
685+
const uniformName = `vp_${attribute}_info`;
686+
// Pack into vec4: (offset, stride, type)
687+
effect.setVector3(uniformName, new Vector3(data.offset, data.stride, data.type));
688+
}
689+
}
690+
691+
/**
692+
* Helper used to prepare vertex pulling metadata defines (stride, offset, component count)
693+
* This should be called when USE_VERTEX_PULLING is enabled to properly configure buffer access
694+
* @param geometry The geometry being rendered
695+
* @param defines The defines object to update
696+
*/
697+
export function PrepareDefinesForVertexPullingMetadata(geometry: Geometry, defines: any): void {
615698
if (!geometry) {
616699
return;
617700
}
618-
619-
for (const attributeName of attributeNames) {
620-
const vertexBuffer = geometry.getVertexBuffer(attributeName);
701+
const vertexBuffers = geometry.getVertexBuffers();
702+
for (const attributeName in vertexBuffers) {
703+
const vertexBuffer = vertexBuffers[attributeName];
621704
if (!vertexBuffer) {
622705
continue;
623706
}
@@ -626,11 +709,14 @@ export function PrepareDefinesForVertexPullingMetadata(mesh: AbstractMesh, defin
626709
const sizeInBytes = GetTypeByteLength(vertexBuffer.type);
627710
// Calculate stride in float32 elements
628711
const stride = vertexBuffer.effectiveByteStride / sizeInBytes;
629-
defines[`${upperName}_STRIDE`] = stride || vertexBuffer.getSize();
712+
defines.push(`#define ${upperName}_STRIDE ${stride}`);
630713

631714
// Calculate offset in float32 elements
632715
const offset = vertexBuffer.effectiveByteOffset / sizeInBytes;
633-
defines[`${upperName}_OFFSET`] = offset;
716+
defines.push(`#define ${upperName}_OFFSET ${offset}`);
717+
// Calculate component count
718+
const componentBytes = GetTypeByteLength(vertexBuffer.type);
719+
defines.push(`#define ${upperName}_COMPONENT_BYTES ${componentBytes}`);
634720
}
635721
}
636722

packages/dev/core/src/Materials/shaderMaterial.ts

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import { EngineStore } from "../Engines/engineStore";
2121
import { Constants } from "../Engines/constants";
2222
import { AddClipPlaneUniforms, BindClipPlane, PrepareStringDefinesForClipPlanes } from "./clipPlaneMaterialHelper";
2323
import type { WebGPUEngine } from "core/Engines/webgpuEngine";
24-
import { GetTypeByteLength } from "../Buffers/bufferUtils";
2524

2625
import type { ExternalTexture } from "./Textures/externalTexture";
2726
import {
@@ -31,8 +30,12 @@ import {
3130
BindMorphTargetParameters,
3231
BindSceneUniformBuffer,
3332
PrepareDefinesAndAttributesForMorphTargets,
33+
PrepareDefinesForVertexPullingMetadata,
34+
PrepareVertexPullingUniforms,
35+
BindVertexPullingUniforms,
3436
PushAttributesForInstances,
3537
} from "./materialHelper.functions";
38+
import type { IVertexPullingMetadata } from "./materialHelper.functions";
3639
import type { IColor3Like, IColor4Like, IVector2Like, IVector3Like, IVector4Like } from "core/Maths/math.like";
3740
import type { InternalTexture } from "./Textures/internalTexture";
3841

@@ -148,6 +151,7 @@ export class ShaderMaterial extends PushMaterial {
148151
private _cachedWorldViewMatrix = new Matrix();
149152
private _cachedWorldViewProjectionMatrix = new Matrix();
150153
private _multiview = false;
154+
private _vertexPullingMetadata: Map<string, IVertexPullingMetadata> | null = null;
151155

152156
/**
153157
* @internal
@@ -920,22 +924,8 @@ export class ShaderMaterial extends PushMaterial {
920924
// Add vertex buffer metadata defines for proper stride/offset handling
921925
const geometry = renderingMesh.geometry;
922926
if (geometry) {
923-
const vertexBuffers = geometry.getVertexBuffers();
924-
if (vertexBuffers) {
925-
for (const attributeName in vertexBuffers) {
926-
const vertexBuffer = vertexBuffers[attributeName];
927-
if (vertexBuffer) {
928-
const componentBytes = GetTypeByteLength(vertexBuffer.type);
929-
const upperName = attributeName.toUpperCase();
930-
const stride = vertexBuffer.effectiveByteStride / 4;
931-
const offset = vertexBuffer.effectiveByteOffset / 4;
932-
933-
defines.push(`#define ${upperName}_STRIDE ${stride}`);
934-
defines.push(`#define ${upperName}_OFFSET ${offset}`);
935-
defines.push(`#define ${upperName}_COMPONENT_BYTES ${componentBytes}`);
936-
}
937-
}
938-
}
927+
PrepareDefinesForVertexPullingMetadata(geometry, defines);
928+
this._vertexPullingMetadata = PrepareVertexPullingUniforms(geometry);
939929
}
940930
}
941931

@@ -1107,6 +1097,10 @@ export class ShaderMaterial extends PushMaterial {
11071097
// Clip plane
11081098
BindClipPlane(effect, this, scene);
11091099

1100+
if (this._vertexPullingMetadata) {
1101+
BindVertexPullingUniforms(effect, this._vertexPullingMetadata);
1102+
}
1103+
11101104
// Misc
11111105
if (this._useLogarithmicDepth) {
11121106
BindLogDepth(storeEffectOnSubMeshes ? subMesh.materialDefines : effect.defines, effect, scene);

0 commit comments

Comments
 (0)