Feature: Implement wind simulation for foliage rendering across renderer, runtime, and viewport hosts
This commit is contained in:
@@ -473,6 +473,8 @@ export class FoliageInstancedRenderer {
|
||||
private scatter: FoliageScatterResult | null = null;
|
||||
private prototypeRegistry: FoliagePrototypeRegistry = {};
|
||||
private quality: FoliageQualitySettings = resolveFoliageQualitySettings(null);
|
||||
private windTime = 0;
|
||||
private windUniforms: FoliageWindUniformSet[] = [];
|
||||
private currentView: FoliageRenderView | null = null;
|
||||
private viewSignature: string | null = null;
|
||||
private renderResourceSignature: string | null = null;
|
||||
@@ -498,6 +500,18 @@ export class FoliageInstancedRenderer {
|
||||
this.group.userData.nonPickable = true;
|
||||
}
|
||||
|
||||
updateWind(deltaSeconds: number) {
|
||||
if (!this.shouldApplyWindShader()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Number.isFinite(deltaSeconds) && deltaSeconds > 0) {
|
||||
this.windTime += deltaSeconds;
|
||||
}
|
||||
|
||||
this.writeWindUniforms();
|
||||
}
|
||||
|
||||
sync(input: FoliageInstancedRendererSyncInput) {
|
||||
const terrains = normalizeTerrainRegistry(input.terrains);
|
||||
const quality = resolveFoliageQualitySettings(input.quality);
|
||||
@@ -536,6 +550,7 @@ export class FoliageInstancedRenderer {
|
||||
renderResourceSignature === this.renderResourceSignature &&
|
||||
this.scatter !== null
|
||||
) {
|
||||
this.writeWindUniforms();
|
||||
this.applyCurrentViewToRenderResources();
|
||||
return;
|
||||
}
|
||||
@@ -668,6 +683,7 @@ export class FoliageInstancedRenderer {
|
||||
this.currentView = null;
|
||||
this.viewSignature = null;
|
||||
this.renderResourceSignature = null;
|
||||
this.windUniforms = [];
|
||||
this.sourceMeshPromisesByBundledPath.clear();
|
||||
this.clearActiveBatches();
|
||||
}
|
||||
@@ -677,6 +693,7 @@ export class FoliageInstancedRenderer {
|
||||
this.activeBatchKeyByChunkKey.clear();
|
||||
this.activeLodLevelByChunkKey.clear();
|
||||
this.renderChunks = [];
|
||||
this.windUniforms = [];
|
||||
|
||||
if (this.activeBatchGroup === null) {
|
||||
return;
|
||||
@@ -696,6 +713,41 @@ export class FoliageInstancedRenderer {
|
||||
console.warn(message);
|
||||
}
|
||||
|
||||
private shouldApplyWindShader(): boolean {
|
||||
return (
|
||||
this.quality.enabled &&
|
||||
this.quality.densityMultiplier > 0 &&
|
||||
this.quality.windEnabled
|
||||
);
|
||||
}
|
||||
|
||||
private registerWindUniforms = (uniforms: FoliageWindUniformSet) => {
|
||||
writeFoliageWindUniformValues(uniforms, this.quality, this.windTime);
|
||||
this.windUniforms.push(uniforms);
|
||||
};
|
||||
|
||||
private writeWindUniforms() {
|
||||
if (!this.shouldApplyWindShader()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const uniforms of this.windUniforms) {
|
||||
writeFoliageWindUniformValues(uniforms, this.quality, this.windTime);
|
||||
}
|
||||
}
|
||||
|
||||
private getWindMaterialOptions(): FoliageWindMaterialOptions | undefined {
|
||||
if (!this.shouldApplyWindShader()) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return {
|
||||
getSettings: () => this.quality,
|
||||
getTime: () => this.windTime,
|
||||
registerUniforms: this.registerWindUniforms
|
||||
};
|
||||
}
|
||||
|
||||
private loadTemplateSourceMeshes(
|
||||
bundledPath: string
|
||||
): Promise<FoliageTemplateSourceMesh[]> {
|
||||
@@ -761,8 +813,12 @@ export class FoliageInstancedRenderer {
|
||||
batchGroup.userData.foliageLayerId = batch.layerId;
|
||||
batchGroup.userData.foliageTerrainId = batch.terrainId;
|
||||
|
||||
const windOptions = this.getWindMaterialOptions();
|
||||
|
||||
for (const sourceMesh of sourceMeshes) {
|
||||
batchGroup.add(createInstancedMeshForSource(batch, sourceMesh));
|
||||
batchGroup.add(
|
||||
createInstancedMeshForSource(batch, sourceMesh, windOptions)
|
||||
);
|
||||
}
|
||||
|
||||
applyRendererRenderCategoryFromMaterial(batchGroup);
|
||||
|
||||
Reference in New Issue
Block a user