Add support for water material in runtime host
This commit is contained in:
@@ -38,6 +38,7 @@ import {
|
||||
resolveBoxVolumeRenderPaths,
|
||||
type ResolvedBoxVolumeRenderPaths
|
||||
} from "../rendering/advanced-rendering";
|
||||
import { collectWaterContactPatches, createWaterMaterial } from "../rendering/water-material";
|
||||
import {
|
||||
areAdvancedRenderingSettingsEqual,
|
||||
cloneAdvancedRenderingSettings,
|
||||
@@ -88,6 +89,7 @@ export class RuntimeHost {
|
||||
private readonly brushMeshes = new Map<string, Mesh<BufferGeometry, Material[]>>();
|
||||
private volumeTime = 0;
|
||||
private readonly volumeAnimatedMaterials: ShaderMaterial[] = [];
|
||||
private readonly volumeAnimatedUniforms: Array<{ value: number }> = [];
|
||||
private readonly localLightObjects = new Map<string, Group>();
|
||||
private readonly modelRenderObjects = new Map<string, Group>();
|
||||
private readonly materialTextureCache = new Map<string, CachedMaterialTexture>();
|
||||
@@ -518,17 +520,32 @@ export class RuntimeHost {
|
||||
this.clearBrushMeshes();
|
||||
const volumeRenderPaths: ResolvedBoxVolumeRenderPaths =
|
||||
this.currentWorld === null ? { fog: "performance", water: "performance" } : resolveBoxVolumeRenderPaths(this.currentWorld.advancedRendering);
|
||||
const colliderBounds = this.runtimeScene?.colliders.map((collider) => ({
|
||||
min: collider.worldBounds.min,
|
||||
max: collider.worldBounds.max
|
||||
})) ?? [];
|
||||
|
||||
for (const brush of brushes) {
|
||||
const geometry = buildBoxBrushDerivedMeshData(brush).geometry;
|
||||
const contactPatches =
|
||||
brush.volume.mode === "water"
|
||||
? collectWaterContactPatches(
|
||||
{
|
||||
center: brush.center,
|
||||
rotationDegrees: brush.rotationDegrees,
|
||||
size: brush.size
|
||||
},
|
||||
colliderBounds
|
||||
)
|
||||
: [];
|
||||
|
||||
const materials = [
|
||||
this.createFaceMaterial(brush, "posX", brush.faces.posX.material, volumeRenderPaths),
|
||||
this.createFaceMaterial(brush, "negX", brush.faces.negX.material, volumeRenderPaths),
|
||||
this.createFaceMaterial(brush, "posY", brush.faces.posY.material, volumeRenderPaths),
|
||||
this.createFaceMaterial(brush, "negY", brush.faces.negY.material, volumeRenderPaths),
|
||||
this.createFaceMaterial(brush, "posZ", brush.faces.posZ.material, volumeRenderPaths),
|
||||
this.createFaceMaterial(brush, "negZ", brush.faces.negZ.material, volumeRenderPaths)
|
||||
this.createFaceMaterial(brush, "posX", brush.faces.posX.material, volumeRenderPaths, contactPatches),
|
||||
this.createFaceMaterial(brush, "negX", brush.faces.negX.material, volumeRenderPaths, contactPatches),
|
||||
this.createFaceMaterial(brush, "posY", brush.faces.posY.material, volumeRenderPaths, contactPatches),
|
||||
this.createFaceMaterial(brush, "negY", brush.faces.negY.material, volumeRenderPaths, contactPatches),
|
||||
this.createFaceMaterial(brush, "posZ", brush.faces.posZ.material, volumeRenderPaths, contactPatches),
|
||||
this.createFaceMaterial(brush, "negZ", brush.faces.negZ.material, volumeRenderPaths, contactPatches)
|
||||
];
|
||||
|
||||
const mesh = new Mesh(geometry, materials);
|
||||
@@ -593,20 +610,32 @@ export class RuntimeHost {
|
||||
brush: RuntimeBoxBrushInstance,
|
||||
faceId: "posX" | "negX" | "posY" | "negY" | "posZ" | "negZ",
|
||||
material: RuntimeBoxBrushInstance["faces"]["posX"]["material"],
|
||||
volumeRenderPaths: { fog: "performance" | "quality"; water: "performance" | "quality" }
|
||||
volumeRenderPaths: { fog: "performance" | "quality"; water: "performance" | "quality" },
|
||||
contactPatches: ReturnType<typeof collectWaterContactPatches>
|
||||
): Material {
|
||||
if (brush.volume.mode === "water") {
|
||||
if (volumeRenderPaths.water === "quality") {
|
||||
return this.createWaterQualityMaterial(brush.volume.water, faceId);
|
||||
}
|
||||
// Performance fallback: simple transparent material
|
||||
const baseOpacity = Math.max(0.05, Math.min(1, brush.volume.water.surfaceOpacity));
|
||||
return new MeshBasicMaterial({
|
||||
color: brush.volume.water.colorHex,
|
||||
transparent: true,
|
||||
const waterMaterial = createWaterMaterial({
|
||||
colorHex: brush.volume.water.colorHex,
|
||||
surfaceOpacity: brush.volume.water.surfaceOpacity,
|
||||
waveStrength: brush.volume.water.waveStrength,
|
||||
opacity: faceId === "posY" ? Math.min(1, baseOpacity + 0.18) : baseOpacity * 0.5,
|
||||
depthWrite: false
|
||||
quality: volumeRenderPaths.water === "quality",
|
||||
wireframe: false,
|
||||
isTopFace: faceId === "posY",
|
||||
time: this.volumeTime,
|
||||
halfSize: {
|
||||
x: brush.size.x * 0.5,
|
||||
z: brush.size.z * 0.5
|
||||
},
|
||||
contactPatches
|
||||
});
|
||||
|
||||
if (waterMaterial.animationUniform !== null) {
|
||||
this.volumeAnimatedUniforms.push(waterMaterial.animationUniform);
|
||||
}
|
||||
|
||||
return waterMaterial.material;
|
||||
}
|
||||
|
||||
if (brush.volume.mode === "fog") {
|
||||
|
||||
Reference in New Issue
Block a user