@@ -23,6 +23,8 @@ import { Texture } from "./Textures/texture";
2323import type { CubeTexture } from "./Textures/cubeTexture" ;
2424import type { Color3 } from "core/Maths/math.color" ;
2525import { 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.
2830export * 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
0 commit comments