Skip to content
Closed
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions packages/dev/core/src/Engines/WebGPU/webgpuDrawContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,14 @@ export class WebGPUDrawContext implements IDrawContext {
this._bufferManager.setRawData(this.indirectDrawBuffer, 0, this._indirectDrawData, 0, 20);
}

/**
* Setup or disable vertex pulling as needed.
* @param useVertexPulling Use vertex pulling or not
* @param webgpuPipelineContext The WebGPU pipeline context
* @param vertexBuffers The current vertex buffers
* @param indexBuffer The current index buffer
* @param overrideVertexBuffers The vertex buffers to override
*/
public setVertexPulling(
useVertexPulling: boolean,
webgpuPipelineContext: WebGPUPipelineContext,
Expand Down
86 changes: 86 additions & 0 deletions packages/dev/core/src/Materials/materialHelper.functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { MaterialFlags } from "./materialFlags";
import { Texture } from "./Textures/texture";
import type { CubeTexture } from "./Textures/cubeTexture";
import type { Color3 } from "core/Maths/math.color";
import type { Geometry } from "../Meshes/geometry";

// For backwards compatibility, we export everything from the pure version of this file.
export * from "./materialHelper.functions.pure";
Expand Down Expand Up @@ -598,6 +599,91 @@ export function GetFogState(mesh: AbstractMesh, scene: Scene) {
return scene.fogEnabled && mesh.applyFog && scene.fogMode !== Constants.FOGMODE_NONE;
}

/**
* Interface representing metadata for vertex pulling
*/
export interface IVertexPullingMetadata {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we move everything related to Vertex Pulling in a vertexPullingHelper.functions.ts ?

/**
* Offset in vertex buffer where data starts
*/
offset: number;

/**
* Stride between elements in the vertex buffer
*/
stride: number;

/**
* Type of the vertex buffer (e.g., float, int)
*/
type: number; // VertexBuffer type constant
}

// Store vertex pulling metadata per geometry
const _VertexPullingMetadataCache = new WeakMap<Geometry, Map<string, IVertexPullingMetadata>>();

/**
* Prepares vertex pulling uniforms for the given attributes and mesh
* @param geometry The geometry containing the vertex buffers
* @returns A map of attribute names to their metadata, or null if unavailable
*/
export function PrepareVertexPullingUniforms(geometry: Geometry): Nullable<Map<string, IVertexPullingMetadata>> {
const vertexBuffers = geometry.getVertexBuffers();
if (!vertexBuffers) {
return null;
}

// Check cache first
let metadata = _VertexPullingMetadataCache.get(geometry);
if (!metadata) {
metadata = new Map<string, IVertexPullingMetadata>();
_VertexPullingMetadataCache.set(geometry, metadata);
} else {
// Return cached metadata if it exists and hasn't changed
let needsUpdate = false;
for (const vb in vertexBuffers) {
if (!metadata.has(vb)) {
needsUpdate = true;
break;
}
}
if (!needsUpdate) {
return metadata;
}
}

// Build or update metadata
for (const vb in vertexBuffers) {
const vertexBuffer = vertexBuffers[vb];
if (vertexBuffer) {
const offset = vertexBuffer.byteOffset;
const stride = vertexBuffer.byteStride;
const type = vertexBuffer.type;

metadata.set(vb, {
offset: offset,
stride: stride,
type: type,
});
}
}

return metadata;
}

/**
* Bind vertex pulling uniforms to the effect
* @param effect The effect to bind the uniforms to
* @param metadata The vertex pulling metadata
*/
export function BindVertexPullingUniforms(effect: Effect, metadata: Map<string, IVertexPullingMetadata>): void {
metadata.forEach((data, attribute) => {
const uniformName = `vp_${attribute}_info`;
// Pack into vec3: (offset, stride, type)
effect.setFloat3(uniformName, data.offset, data.stride, data.type);
});
}

/**
* Helper used to prepare the list of defines associated with misc. values for shader compilation
* @param mesh defines the current mesh
Expand Down
25 changes: 23 additions & 2 deletions packages/dev/core/src/Materials/shaderMaterial.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,11 @@ import {
BindMorphTargetParameters,
BindSceneUniformBuffer,
PrepareDefinesAndAttributesForMorphTargets,
PrepareVertexPullingUniforms,
BindVertexPullingUniforms,
PushAttributesForInstances,
} from "./materialHelper.functions";
import type { IVertexPullingMetadata } from "./materialHelper.functions";
import type { IColor3Like, IColor4Like, IVector2Like, IVector3Like, IVector4Like } from "core/Maths/math.like";
import type { InternalTexture } from "./Textures/internalTexture";

Expand Down Expand Up @@ -147,6 +150,7 @@ export class ShaderMaterial extends PushMaterial {
private _cachedWorldViewMatrix = new Matrix();
private _cachedWorldViewProjectionMatrix = new Matrix();
private _multiview = false;
private _vertexPullingMetadata: Map<string, IVertexPullingMetadata> | null = null;

/**
* @internal
Expand Down Expand Up @@ -897,19 +901,32 @@ export class ShaderMaterial extends PushMaterial {
}
}

const renderingMesh = subMesh ? subMesh.getRenderingMesh() : mesh;
if (renderingMesh && this.useVertexPulling) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use the same condition with the code adding the defines ?

// Add vertex buffer metadata defines for proper stride/offset handling
const geometry = renderingMesh.geometry;
if (geometry) {
this._vertexPullingMetadata = PrepareVertexPullingUniforms(geometry);
if (this._vertexPullingMetadata) {
this._vertexPullingMetadata.forEach((_, attribute) => {
uniforms.push(`vp_${attribute}_info`);
});
}
}
}

if (this.customShaderNameResolve) {
uniforms = uniforms.slice();
uniformBuffers = uniformBuffers.slice();
samplers = samplers.slice();
shaderName = this.customShaderNameResolve(this.name, uniforms, uniformBuffers, samplers, defines, attribs);
}

const renderingMesh = subMesh ? subMesh.getRenderingMesh() : mesh;
if (renderingMesh && this.useVertexPulling) {
defines.push("#define USE_VERTEX_PULLING");

const indexBuffer = renderingMesh.geometry?.getIndexBuffer();
if (indexBuffer) {
if (indexBuffer && !(renderingMesh as Mesh).isUnIndexed) {
defines.push("#define VERTEX_PULLING_USE_INDEX_BUFFER");
if (indexBuffer.is32Bits) {
defines.push("#define VERTEX_PULLING_INDEX_BUFFER_32BITS");
Expand Down Expand Up @@ -1085,6 +1102,10 @@ export class ShaderMaterial extends PushMaterial {
// Clip plane
BindClipPlane(effect, this, scene);

if (this._vertexPullingMetadata) {
BindVertexPullingUniforms(effect, this._vertexPullingMetadata);
}

// Misc
if (this._useLogarithmicDepth) {
BindLogDepth(storeEffectOnSubMeshes ? subMesh.materialDefines : effect.defines, effect, scene);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,9 @@ export class _IblShadowsVoxelRenderer {
* @param includedMeshes
*/
public updateVoxelGrid(includedMeshes: Mesh[]) {
if (this._voxelizationInProgress) {
return;
}
this._stopVoxelization();
this._includedMeshes = includedMeshes;
this._voxelizationInProgress = true;
Expand Down Expand Up @@ -738,6 +741,7 @@ export class _IblShadowsVoxelRenderer {
if (axis === 1) {
upDirection = new Vector3(1, 0, 0);
}
mrt.onBeforeRenderObservable.clear();
mrt.onBeforeRenderObservable.add(() => {
voxelMaterial.setMatrix("viewMatrix", Matrix.LookAtLH(cameraPosition, targetPosition, upDirection));
voxelMaterial.setMatrix("invWorldScale", this._invWorldScaleMatrix);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#if NUM_BONE_INFLUENCERS > 0
attribute matricesIndices : vec4<f32>;
attribute matricesWeights : vec4<f32>;
attribute matricesIndices : vec4f;
attribute matricesWeights : vec4f;
#if NUM_BONE_INFLUENCERS > 4
attribute matricesIndicesExtra : vec4<f32>;
attribute matricesWeightsExtra : vec4<f32>;
attribute matricesIndicesExtra : vec4f;
attribute matricesWeightsExtra : vec4f;
#endif

#ifndef BAKED_VERTEX_ANIMATION_TEXTURE
Expand Down
Loading