Add water reflection functionality to ViewportHost
This commit is contained in:
@@ -2198,6 +2198,111 @@ export class ViewportHost {
|
||||
metalness: 0.02
|
||||
});
|
||||
}
|
||||
getWaterReflectionMode() {
|
||||
if (this.currentWorld === null ||
|
||||
!this.currentWorld.advancedRendering.enabled ||
|
||||
this.currentWorld.advancedRendering.waterPath !== "quality" ||
|
||||
this.displayMode !== "normal" ||
|
||||
this.viewMode !== "perspective") {
|
||||
return "none";
|
||||
}
|
||||
return this.currentWorld.advancedRendering.waterReflectionMode;
|
||||
}
|
||||
createWaterReflectionRenderTarget() {
|
||||
const canvasWidth = this.container?.clientWidth ?? this.renderer.domElement.width;
|
||||
const canvasHeight = this.container?.clientHeight ?? this.renderer.domElement.height;
|
||||
const width = Math.max(128, Math.round(Math.max(canvasWidth, 512) * 0.5));
|
||||
const height = Math.max(128, Math.round(Math.max(canvasHeight, 512) * 0.5));
|
||||
return new WebGLRenderTarget(width, height);
|
||||
}
|
||||
resizeWaterReflectionTargets() {
|
||||
const canvasWidth = this.container?.clientWidth ?? this.renderer.domElement.width;
|
||||
const canvasHeight = this.container?.clientHeight ?? this.renderer.domElement.height;
|
||||
const width = Math.max(128, Math.round(Math.max(canvasWidth, 512) * 0.5));
|
||||
const height = Math.max(128, Math.round(Math.max(canvasHeight, 512) * 0.5));
|
||||
for (const binding of this.viewportWaterSurfaceBindings) {
|
||||
binding.reflectionRenderTarget?.setSize(width, height);
|
||||
}
|
||||
}
|
||||
updateViewportWaterReflections() {
|
||||
const activeCamera = this.getActiveCamera();
|
||||
if (!(activeCamera instanceof PerspectiveCamera)) {
|
||||
for (const binding of this.viewportWaterSurfaceBindings) {
|
||||
if (binding.reflectionEnabledUniform !== null) {
|
||||
binding.reflectionEnabledUniform.value = 0;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
const reflectionMode = this.getWaterReflectionMode();
|
||||
for (const binding of this.viewportWaterSurfaceBindings) {
|
||||
if (reflectionMode === "none" ||
|
||||
binding.reflectionTextureUniform === null ||
|
||||
binding.reflectionMatrixUniform === null ||
|
||||
binding.reflectionEnabledUniform === null) {
|
||||
if (binding.reflectionEnabledUniform !== null) {
|
||||
binding.reflectionEnabledUniform.value = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (binding.reflectionRenderTarget === null) {
|
||||
binding.reflectionRenderTarget = this.createWaterReflectionRenderTarget();
|
||||
}
|
||||
const canRenderReflection = updatePlanarReflectionCamera(binding.brush, activeCamera, this.waterReflectionCamera, binding.reflectionMatrixUniform.value);
|
||||
if (!canRenderReflection || binding.reflectionRenderTarget === null) {
|
||||
binding.reflectionEnabledUniform.value = 0;
|
||||
continue;
|
||||
}
|
||||
const hiddenObjects = [];
|
||||
const hideObject = (object) => {
|
||||
if (object === null || object === undefined) {
|
||||
return;
|
||||
}
|
||||
hiddenObjects.push({ object, visible: object.visible });
|
||||
object.visible = false;
|
||||
};
|
||||
for (const waterBinding of this.viewportWaterSurfaceBindings) {
|
||||
const renderObjects = this.brushRenderObjects.get(waterBinding.brush.id);
|
||||
if (renderObjects !== undefined) {
|
||||
hideObject(renderObjects.mesh);
|
||||
}
|
||||
}
|
||||
for (const renderObjects of this.brushRenderObjects.values()) {
|
||||
hideObject(renderObjects.edges);
|
||||
for (const edgeHelper of renderObjects.edgeHelpers) {
|
||||
hideObject(edgeHelper.line);
|
||||
}
|
||||
for (const vertexHelper of renderObjects.vertexHelpers) {
|
||||
hideObject(vertexHelper.mesh);
|
||||
}
|
||||
}
|
||||
hideObject(this.axesHelper);
|
||||
hideObject(this.gridHelpers.xz);
|
||||
hideObject(this.gridHelpers.xy);
|
||||
hideObject(this.gridHelpers.yz);
|
||||
hideObject(this.entityGroup);
|
||||
hideObject(this.transformGizmoGroup);
|
||||
hideObject(this.boxCreatePreviewMesh);
|
||||
hideObject(this.boxCreatePreviewEdges);
|
||||
hideObject(this.creationPreviewObject);
|
||||
if (reflectionMode === "world") {
|
||||
hideObject(this.modelGroup);
|
||||
}
|
||||
const previousAutoClear = this.renderer.autoClear;
|
||||
const previousRenderTarget = this.renderer.getRenderTarget();
|
||||
this.renderer.autoClear = true;
|
||||
this.renderer.setRenderTarget(binding.reflectionRenderTarget);
|
||||
this.renderer.clear();
|
||||
this.renderer.render(this.scene, this.waterReflectionCamera);
|
||||
this.renderer.setRenderTarget(previousRenderTarget);
|
||||
this.renderer.autoClear = previousAutoClear;
|
||||
for (const hiddenObject of hiddenObjects) {
|
||||
hiddenObject.object.visible = hiddenObject.visible;
|
||||
}
|
||||
binding.reflectionTextureUniform.value = binding.reflectionRenderTarget.texture;
|
||||
binding.reflectionEnabledUniform.value = 0.36;
|
||||
}
|
||||
}
|
||||
getOrCreateTexture(material) {
|
||||
const signature = createStarterMaterialSignature(material);
|
||||
const cachedTexture = this.materialTextureCache.get(material.id);
|
||||
@@ -2377,6 +2482,10 @@ export class ViewportHost {
|
||||
}
|
||||
this.brushRenderObjects.clear();
|
||||
this.volumeAnimatedUniforms.length = 0;
|
||||
for (const binding of this.viewportWaterSurfaceBindings) {
|
||||
binding.reflectionRenderTarget?.dispose();
|
||||
}
|
||||
this.viewportWaterSurfaceBindings.length = 0;
|
||||
}
|
||||
clearEntityMarkers() {
|
||||
for (const renderObjects of this.entityRenderObjects.values()) {
|
||||
|
||||
Reference in New Issue
Block a user