|
|
@@ -15,6 +15,7 @@ import flowNormalTexUrl from '../assets/texture/FlowTexture/T_FlowTexture_BC_NOR
|
|
|
import foamMacroNormalTexUrl from '../assets/texture/FlowTexture/T_FoamMacro_BC_NORM.PNG'
|
|
|
import langGLBUrl from '../assets/lang.glb'
|
|
|
import cscwaterGLBUrl from '../assets/CSCwater.glb'
|
|
|
+import water02GLBUrl from '../assets/water02.glb'
|
|
|
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
|
|
|
import { TilesRenderer } from '3d-tiles-renderer'
|
|
|
import { ReorientationPlugin } from '3d-tiles-renderer/plugins'
|
|
|
@@ -33,6 +34,7 @@ import {
|
|
|
sceneLabels,
|
|
|
type WaterLevelLabelConfig,
|
|
|
cameraPresets,
|
|
|
+ labelToPresetMap,
|
|
|
} from '../config/sceneConfig'
|
|
|
|
|
|
// ==================== 外部 Props(嵌入其他项目时使用)====================
|
|
|
@@ -97,6 +99,9 @@ const showCameraPresetPanel = ref(false)
|
|
|
// ========== 水面材质参数 ==========
|
|
|
const waterParams = ref<WaterMaterialParams>({ ...defaultWaterParams })
|
|
|
|
|
|
+// ========== water02(一期沉砂池水面)独立材质参数 ==========
|
|
|
+const water02Params = ref<WaterMaterialParams>({ ...defaultWaterParams })
|
|
|
+
|
|
|
// ========== CSCwater 独立材质参数(与主水面分开调节)==========
|
|
|
const cscwaterParams = ref<CscwaterMaterialParams>({ ...defaultCscwaterParams })
|
|
|
|
|
|
@@ -206,6 +211,25 @@ function saveWaterDefaults() {
|
|
|
showToast('水面材质默认值已保存')
|
|
|
}
|
|
|
|
|
|
+const WATER02_DEFAULTS_KEY = 'water02Params_defaults'
|
|
|
+
|
|
|
+function loadWater02Defaults() {
|
|
|
+ const saved = localStorage.getItem(WATER02_DEFAULTS_KEY)
|
|
|
+ if (saved) {
|
|
|
+ try {
|
|
|
+ const parsed = JSON.parse(saved)
|
|
|
+ Object.assign(water02Params.value, parsed)
|
|
|
+ } catch (e) {
|
|
|
+ console.warn('Failed to parse water02 defaults:', e)
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function saveWater02Defaults() {
|
|
|
+ localStorage.setItem(WATER02_DEFAULTS_KEY, JSON.stringify(water02Params.value))
|
|
|
+ showToast('一期沉砂池水面材质默认值已保存')
|
|
|
+}
|
|
|
+
|
|
|
const CSCWATER_DEFAULTS_KEY = 'cscwaterParams_defaults'
|
|
|
|
|
|
function loadCscwaterDefaults() {
|
|
|
@@ -227,6 +251,22 @@ function saveCscwaterDefaults() {
|
|
|
|
|
|
const MODEL_DEFAULTS_KEY = 'modelTransform_defaults'
|
|
|
|
|
|
+function loadModelDefaults() {
|
|
|
+ const saved = localStorage.getItem(MODEL_DEFAULTS_KEY)
|
|
|
+ if (saved) {
|
|
|
+ try {
|
|
|
+ const data = JSON.parse(saved)
|
|
|
+ for (const key in data) {
|
|
|
+ if (modelTransformMap[key]) {
|
|
|
+ Object.assign(modelTransformMap[key], data[key])
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ console.warn('Failed to parse model transform defaults:', e)
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
function saveModelDefaults() {
|
|
|
const t = modelTransform.value
|
|
|
modelTransformMap[selectedModelKey.value] = {
|
|
|
@@ -261,6 +301,9 @@ for (const key of Object.keys(configModelTransformMap)) {
|
|
|
modelTransformMap[key] = { ...configModelTransformMap[key] }
|
|
|
}
|
|
|
|
|
|
+// 加载保存的模型变换默认值
|
|
|
+loadModelDefaults()
|
|
|
+
|
|
|
// 当前选中的模型变换值(双向绑定)
|
|
|
const modelTransform = ref({ ...modelTransformMap.foam })
|
|
|
|
|
|
@@ -269,7 +312,7 @@ function applyModelTransform(key: string) {
|
|
|
const obj = modelList[key]
|
|
|
if (!obj) return
|
|
|
const t = modelTransform.value
|
|
|
- if (key === 'foam' && 'isMesh' in obj) {
|
|
|
+ if ((key === 'foam' || key === 'foam2') && 'isMesh' in obj) {
|
|
|
const mesh = obj as THREE.Mesh
|
|
|
mesh.position.set(t.positionX, t.positionY, t.positionZ)
|
|
|
mesh.rotation.order = 'YXZ'
|
|
|
@@ -317,6 +360,15 @@ function applyModelTransform(key: string) {
|
|
|
THREE.MathUtils.degToRad(t.rotationZ)
|
|
|
)
|
|
|
obj.scale.set(t.scaleX, t.scaleY, t.scaleZ)
|
|
|
+ } else if (key === 'water02') {
|
|
|
+ obj.position.set(t.positionX, t.positionY, t.positionZ)
|
|
|
+ obj.rotation.order = 'YXZ'
|
|
|
+ obj.rotation.set(
|
|
|
+ THREE.MathUtils.degToRad(t.rotationX),
|
|
|
+ THREE.MathUtils.degToRad(t.rotationY),
|
|
|
+ THREE.MathUtils.degToRad(t.rotationZ)
|
|
|
+ )
|
|
|
+ obj.scale.set(t.scaleX, t.scaleY, t.scaleZ)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -364,10 +416,14 @@ let waterMesh: THREE.Mesh
|
|
|
let water2Mesh: THREE.Mesh | null = null
|
|
|
let foamMesh: THREE.Mesh | null = null
|
|
|
let foamMaterial: THREE.ShaderMaterial | null = null
|
|
|
+let foam2Mesh: THREE.Mesh | null = null
|
|
|
+let foam2Material: THREE.ShaderMaterial | null = null
|
|
|
let flowMesh: THREE.Mesh | null = null
|
|
|
let flowMaterial: THREE.ShaderMaterial | null = null
|
|
|
let cscwaterModel: THREE.Object3D | null = null
|
|
|
let cscwaterMaterial: THREE.ShaderMaterial | null = null
|
|
|
+let water02Model: THREE.Object3D | null = null
|
|
|
+let water02Material: THREE.ShaderMaterial | null = null
|
|
|
let sunDirection: THREE.Vector3
|
|
|
let animationId: number
|
|
|
let tilesRenderer: SuperMapTilesRenderer | null = null
|
|
|
@@ -495,6 +551,56 @@ function createWaterFoamSurface() {
|
|
|
materialList['foam'] = foamMaterial
|
|
|
}
|
|
|
|
|
|
+// 创建第二个泡沫片面(一期沉砂池泡沫效果)
|
|
|
+function createWaterFoamSurface2() {
|
|
|
+ const textureLoader = new THREE.TextureLoader()
|
|
|
+ const foamTexture = textureLoader.load(foamTexUrl)
|
|
|
+ foamTexture.wrapS = THREE.RepeatWrapping
|
|
|
+ foamTexture.wrapT = THREE.RepeatWrapping
|
|
|
+
|
|
|
+ const directionalFoamTexture = textureLoader.load(directionalFoamTexUrl)
|
|
|
+ directionalFoamTexture.wrapS = THREE.RepeatWrapping
|
|
|
+ directionalFoamTexture.wrapT = THREE.RepeatWrapping
|
|
|
+
|
|
|
+ foam2Material = createWaterFoamUEMaterial({
|
|
|
+ colour: new THREE.Color(foamMatParams.value.colour),
|
|
|
+ opacity: foamMatParams.value.opacity,
|
|
|
+ waterfallSpeed: foamMatParams.value.waterfallSpeed,
|
|
|
+ edgeMaskTiling: foamMatParams.value.edgeMaskTiling,
|
|
|
+ edgeMaskSpeed: foamMatParams.value.edgeMaskSpeed,
|
|
|
+ fresnelExponent: foamMatParams.value.fresnelExponent,
|
|
|
+ directionalFoamIntensity: foamMatParams.value.directionalFoamIntensity,
|
|
|
+ directionalFoamContrast: foamMatParams.value.directionalFoamContrast,
|
|
|
+ directionalFoam1Intensity: foamMatParams.value.directionalFoam1Intensity,
|
|
|
+ directionalFoam2Intensity: foamMatParams.value.directionalFoam2Intensity,
|
|
|
+ directionalFoam2Tiling: foamMatParams.value.directionalFoam2Tiling,
|
|
|
+ directionalFoam2Speed: foamMatParams.value.directionalFoam2Speed,
|
|
|
+ directionalFoam3Intensity: foamMatParams.value.directionalFoam3Intensity,
|
|
|
+ foamFalloff: foamMatParams.value.foamFalloff,
|
|
|
+ gradientTop: foamMatParams.value.gradientTop,
|
|
|
+ gradientBottom: foamMatParams.value.gradientBottom,
|
|
|
+ gradientPower: foamMatParams.value.gradientPower,
|
|
|
+ foamTexture,
|
|
|
+ directionalFoamTexture,
|
|
|
+ })
|
|
|
+
|
|
|
+ const t = modelTransformMap.foam2
|
|
|
+ const geometry = new THREE.PlaneGeometry(t.scaleX, t.scaleY)
|
|
|
+ foam2Mesh = new THREE.Mesh(geometry, foam2Material)
|
|
|
+ foam2Mesh.rotation.order = 'YXZ'
|
|
|
+ foam2Mesh.rotation.set(
|
|
|
+ THREE.MathUtils.degToRad(t.rotationX),
|
|
|
+ THREE.MathUtils.degToRad(t.rotationY),
|
|
|
+ THREE.MathUtils.degToRad(t.rotationZ)
|
|
|
+ )
|
|
|
+ foam2Mesh.position.set(t.positionX, t.positionY, t.positionZ)
|
|
|
+ foam2Mesh.name = 'foam2'
|
|
|
+ foam2Mesh.renderOrder = 1
|
|
|
+ scene.add(foam2Mesh)
|
|
|
+ modelList['foam2'] = foam2Mesh
|
|
|
+ materialList['foam2'] = foam2Material
|
|
|
+}
|
|
|
+
|
|
|
// 加载流动水纹理模型(GLB 模型+流动纹理材质)
|
|
|
function loadWaterFlowModel() {
|
|
|
const textureLoader = new THREE.TextureLoader()
|
|
|
@@ -596,6 +702,48 @@ function loadCSCWaterModel() {
|
|
|
})
|
|
|
}
|
|
|
|
|
|
+// 加载 water02.glb 模型
|
|
|
+function loadWater02Model() {
|
|
|
+ water02Material = StylizedWaterMaterial.clone()
|
|
|
+ water02Material.uniforms = THREE.UniformsUtils.clone(StylizedWaterMaterial.uniforms)
|
|
|
+ water02Material.polygonOffset = true
|
|
|
+ water02Material.polygonOffsetFactor = 5
|
|
|
+ water02Material.polygonOffsetUnits = 5
|
|
|
+
|
|
|
+ const loader = new GLTFLoader()
|
|
|
+ loader.load(water02GLBUrl, (gltf) => {
|
|
|
+ const object = gltf.scene
|
|
|
+ object.traverse((child) => {
|
|
|
+ if ((child as THREE.Mesh).isMesh) {
|
|
|
+ const mesh = child as THREE.Mesh
|
|
|
+ mesh.material = water02Material!
|
|
|
+ mesh.castShadow = true
|
|
|
+ mesh.receiveShadow = true
|
|
|
+ mesh.frustumCulled = false
|
|
|
+ mesh.renderOrder = 1
|
|
|
+ mesh.material.polygonOffset = true
|
|
|
+ mesh.material.polygonOffsetFactor = 1
|
|
|
+ mesh.material.polygonOffsetUnits = 1
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ const t = modelTransformMap.water02
|
|
|
+ object.position.set(t.positionX, t.positionY, t.positionZ)
|
|
|
+ object.rotation.order = 'YXZ'
|
|
|
+ object.rotation.set(
|
|
|
+ THREE.MathUtils.degToRad(t.rotationX),
|
|
|
+ THREE.MathUtils.degToRad(t.rotationY),
|
|
|
+ THREE.MathUtils.degToRad(t.rotationZ)
|
|
|
+ )
|
|
|
+ object.scale.set(t.scaleX, t.scaleY, t.scaleZ)
|
|
|
+ object.name = 'water02'
|
|
|
+ scene.add(object)
|
|
|
+ modelList['water02'] = object
|
|
|
+ water02Model = object
|
|
|
+ materialList['water02'] = water02Material
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
// 加载超图 3D Tiles 瓦片数据(大范围三维场景)
|
|
|
async function load3DTiles() {
|
|
|
const tilesetUrl = props.tilesetUrl
|
|
|
@@ -684,6 +832,26 @@ function disposeScene() {
|
|
|
cscwaterMaterial = null
|
|
|
}
|
|
|
|
|
|
+ if (water02Model) {
|
|
|
+ if (scene) scene.remove(water02Model)
|
|
|
+ water02Model.traverse((child) => {
|
|
|
+ const mesh = child as THREE.Mesh
|
|
|
+ if (mesh.isMesh) {
|
|
|
+ mesh.geometry?.dispose()
|
|
|
+ if (Array.isArray(mesh.material)) {
|
|
|
+ mesh.material.forEach(m => m.dispose())
|
|
|
+ } else {
|
|
|
+ mesh.material?.dispose()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ water02Model = null
|
|
|
+ }
|
|
|
+ if (water02Material) {
|
|
|
+ water02Material.dispose()
|
|
|
+ water02Material = null
|
|
|
+ }
|
|
|
+
|
|
|
if (waterMesh) {
|
|
|
if (scene) scene.remove(waterMesh)
|
|
|
waterMesh.geometry.dispose()
|
|
|
@@ -805,8 +973,10 @@ function initScene() {
|
|
|
createWaterSurface()
|
|
|
createWater2Surface()
|
|
|
createWaterFoamSurface()
|
|
|
+ createWaterFoamSurface2()
|
|
|
loadWaterFlowModel()
|
|
|
loadCSCWaterModel()
|
|
|
+ loadWater02Model()
|
|
|
load3DTiles()
|
|
|
labelDataList.forEach(d => d.componentRef.value?.init(scene, camera))
|
|
|
initRaycaster()
|
|
|
@@ -831,6 +1001,27 @@ function onMouseClick(event: MouseEvent) {
|
|
|
mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1
|
|
|
mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1
|
|
|
raycaster.setFromCamera(mouse, camera)
|
|
|
+
|
|
|
+ // 首先检测标签精灵(图标)点击
|
|
|
+ const labelSprites: THREE.Object3D[] = []
|
|
|
+ labelDataList.forEach(d => {
|
|
|
+ const sprite = d.componentRef.value?.getSprite()
|
|
|
+ if (sprite) {
|
|
|
+ labelSprites.push(sprite)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ const labelIntersects = raycaster.intersectObjects(labelSprites, true)
|
|
|
+ if (labelIntersects.length > 0) {
|
|
|
+ const clickedSprite = labelIntersects[0].object as THREE.Sprite
|
|
|
+ const labelId = clickedSprite.name.replace('label_', '')
|
|
|
+ const presetId = labelToPresetMap[labelId]
|
|
|
+ if (presetId) {
|
|
|
+ flyToPreset(presetId)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 然后检测其他物体
|
|
|
const intersectObjects: THREE.Object3D[] = []
|
|
|
if (tilesRenderer?.group) {
|
|
|
intersectObjects.push(tilesRenderer.group)
|
|
|
@@ -872,6 +1063,10 @@ function animate() {
|
|
|
foamMaterial.uniforms.uTime.value += 0.016
|
|
|
foamMaterial.uniforms.uCameraPos.value.copy(camera.position)
|
|
|
}
|
|
|
+ if (foam2Material) {
|
|
|
+ foam2Material.uniforms.uTime.value += 0.016
|
|
|
+ foam2Material.uniforms.uCameraPos.value.copy(camera.position)
|
|
|
+ }
|
|
|
if (flowMaterial) {
|
|
|
flowMaterial.uniforms.uTime.value += 0.016
|
|
|
}
|
|
|
@@ -881,6 +1076,12 @@ function animate() {
|
|
|
cscwaterMaterial.uniforms.collisionFoamTime.value += 0.016
|
|
|
cscwaterMaterial.uniforms.cameraPos.value.copy(camera.position)
|
|
|
}
|
|
|
+ if (water02Material) {
|
|
|
+ water02Material.uniforms.depthSampler.value = depthRenderTarget.depthTexture
|
|
|
+ water02Material.uniforms.iTime.value += 0.016
|
|
|
+ water02Material.uniforms.collisionFoamTime.value += 0.016
|
|
|
+ water02Material.uniforms.cameraPos.value.copy(camera.position)
|
|
|
+ }
|
|
|
labelDataList.forEach(d => d.componentRef.value?.tick())
|
|
|
StylizedWaterMaterial.uniforms.cameraPos.value.copy(camera.position)
|
|
|
|
|
|
@@ -962,29 +1163,75 @@ function syncWaterParams() {
|
|
|
watch(() => waterParams.value, syncWaterParams, { deep: true })
|
|
|
syncWaterParams()
|
|
|
|
|
|
+function syncWater02Params() {
|
|
|
+ if (!water02Material || !water02Material.uniforms) return
|
|
|
+ const p = water02Params.value
|
|
|
+ water02Material.uniforms.alpha.value = p.alpha
|
|
|
+ water02Material.uniforms.flowSpeed.value = p.flowSpeed
|
|
|
+ water02Material.uniforms.flowDirection.value.set(p.flowDirectionX, p.flowDirectionY)
|
|
|
+ water02Material.uniforms.normalRotation.value = p.normalRotation
|
|
|
+ water02Material.uniforms.waveHeight.value = p.waveHeight
|
|
|
+ water02Material.uniforms.shallowColor.value.set(p.waterColor)
|
|
|
+ water02Material.uniforms.deepColor.value.set(p.deepColor)
|
|
|
+ water02Material.uniforms.foamIntensity.value = p.foamIntensity
|
|
|
+ water02Material.uniforms.specIntensity.value = p.specIntensity
|
|
|
+ water02Material.uniforms.specPower.value = p.specPower
|
|
|
+ water02Material.uniforms.fresnelPower.value = p.fresnelPower
|
|
|
+ water02Material.uniforms.fresnelIntensity.value = p.fresnelIntensity
|
|
|
+ water02Material.uniforms.depthRange.value = p.depthRange
|
|
|
+ water02Material.uniforms.waterNormalStrength.value = p.waterNormalStrength
|
|
|
+ water02Material.uniforms.waterNormalTiling.value = p.waterNormalTiling
|
|
|
+ water02Material.uniforms.collisionFoamThreshold.value = p.collisionFoamThreshold
|
|
|
+ water02Material.uniforms.collisionFoamStrength.value = p.collisionFoamStrength
|
|
|
+ water02Material.uniforms.fresnelDistanceNear.value = p.fresnelDistanceNear
|
|
|
+ water02Material.uniforms.fresnelDistanceFar.value = p.fresnelDistanceFar
|
|
|
+}
|
|
|
+
|
|
|
+watch(() => water02Params.value, syncWater02Params, { deep: true })
|
|
|
+
|
|
|
watch(() => cscwaterParams.value, () => {
|
|
|
syncCscwaterParams()
|
|
|
}, { deep: true })
|
|
|
|
|
|
watch(() => foamMatParams.value, (p) => {
|
|
|
- if (!foamMaterial) return
|
|
|
- foamMaterial.uniforms.uColour.value.set(p.colour)
|
|
|
- foamMaterial.uniforms.uOpacity.value = p.opacity
|
|
|
- foamMaterial.uniforms.uWaterfallSpeed.value = p.waterfallSpeed
|
|
|
- foamMaterial.uniforms.uEdgeMaskTiling.value = p.edgeMaskTiling
|
|
|
- foamMaterial.uniforms.uEdgeMaskSpeed.value = p.edgeMaskSpeed
|
|
|
- foamMaterial.uniforms.uFresnelExponent.value = p.fresnelExponent
|
|
|
- foamMaterial.uniforms.uDirectionalFoamIntensity.value = p.directionalFoamIntensity
|
|
|
- foamMaterial.uniforms.uDirectionalFoamContrast.value = p.directionalFoamContrast
|
|
|
- foamMaterial.uniforms.uDirectionalFoam1Intensity.value = p.directionalFoam1Intensity
|
|
|
- foamMaterial.uniforms.uDirectionalFoam2Intensity.value = p.directionalFoam2Intensity
|
|
|
- foamMaterial.uniforms.uDirectionalFoam2Tiling.value = p.directionalFoam2Tiling
|
|
|
- foamMaterial.uniforms.uDirectionalFoam2Speed.value = p.directionalFoam2Speed
|
|
|
- foamMaterial.uniforms.uDirectionalFoam3Intensity.value = p.directionalFoam3Intensity
|
|
|
- foamMaterial.uniforms.uFoamFalloff.value = p.foamFalloff
|
|
|
- foamMaterial.uniforms.uGradientTop.value = p.gradientTop
|
|
|
- foamMaterial.uniforms.uGradientBottom.value = p.gradientBottom
|
|
|
- foamMaterial.uniforms.uGradientPower.value = p.gradientPower
|
|
|
+ if (foamMaterial) {
|
|
|
+ foamMaterial.uniforms.uColour.value.set(p.colour)
|
|
|
+ foamMaterial.uniforms.uOpacity.value = p.opacity
|
|
|
+ foamMaterial.uniforms.uWaterfallSpeed.value = p.waterfallSpeed
|
|
|
+ foamMaterial.uniforms.uEdgeMaskTiling.value = p.edgeMaskTiling
|
|
|
+ foamMaterial.uniforms.uEdgeMaskSpeed.value = p.edgeMaskSpeed
|
|
|
+ foamMaterial.uniforms.uFresnelExponent.value = p.fresnelExponent
|
|
|
+ foamMaterial.uniforms.uDirectionalFoamIntensity.value = p.directionalFoamIntensity
|
|
|
+ foamMaterial.uniforms.uDirectionalFoamContrast.value = p.directionalFoamContrast
|
|
|
+ foamMaterial.uniforms.uDirectionalFoam1Intensity.value = p.directionalFoam1Intensity
|
|
|
+ foamMaterial.uniforms.uDirectionalFoam2Intensity.value = p.directionalFoam2Intensity
|
|
|
+ foamMaterial.uniforms.uDirectionalFoam2Tiling.value = p.directionalFoam2Tiling
|
|
|
+ foamMaterial.uniforms.uDirectionalFoam2Speed.value = p.directionalFoam2Speed
|
|
|
+ foamMaterial.uniforms.uDirectionalFoam3Intensity.value = p.directionalFoam3Intensity
|
|
|
+ foamMaterial.uniforms.uFoamFalloff.value = p.foamFalloff
|
|
|
+ foamMaterial.uniforms.uGradientTop.value = p.gradientTop
|
|
|
+ foamMaterial.uniforms.uGradientBottom.value = p.gradientBottom
|
|
|
+ foamMaterial.uniforms.uGradientPower.value = p.gradientPower
|
|
|
+ }
|
|
|
+ if (foam2Material) {
|
|
|
+ foam2Material.uniforms.uColour.value.set(p.colour)
|
|
|
+ foam2Material.uniforms.uOpacity.value = p.opacity
|
|
|
+ foam2Material.uniforms.uWaterfallSpeed.value = p.waterfallSpeed
|
|
|
+ foam2Material.uniforms.uEdgeMaskTiling.value = p.edgeMaskTiling
|
|
|
+ foam2Material.uniforms.uEdgeMaskSpeed.value = p.edgeMaskSpeed
|
|
|
+ foam2Material.uniforms.uFresnelExponent.value = p.fresnelExponent
|
|
|
+ foam2Material.uniforms.uDirectionalFoamIntensity.value = p.directionalFoamIntensity
|
|
|
+ foam2Material.uniforms.uDirectionalFoamContrast.value = p.directionalFoamContrast
|
|
|
+ foam2Material.uniforms.uDirectionalFoam1Intensity.value = p.directionalFoam1Intensity
|
|
|
+ foam2Material.uniforms.uDirectionalFoam2Intensity.value = p.directionalFoam2Intensity
|
|
|
+ foam2Material.uniforms.uDirectionalFoam2Tiling.value = p.directionalFoam2Tiling
|
|
|
+ foam2Material.uniforms.uDirectionalFoam2Speed.value = p.directionalFoam2Speed
|
|
|
+ foam2Material.uniforms.uDirectionalFoam3Intensity.value = p.directionalFoam3Intensity
|
|
|
+ foam2Material.uniforms.uFoamFalloff.value = p.foamFalloff
|
|
|
+ foam2Material.uniforms.uGradientTop.value = p.gradientTop
|
|
|
+ foam2Material.uniforms.uGradientBottom.value = p.gradientBottom
|
|
|
+ foam2Material.uniforms.uGradientPower.value = p.gradientPower
|
|
|
+ }
|
|
|
}, { deep: true })
|
|
|
|
|
|
watch(() => flowParams.value, () => {
|
|
|
@@ -1170,7 +1417,9 @@ defineExpose({
|
|
|
<select v-model="selectedModelKey" class="model-select">
|
|
|
<option value="water">水面</option>
|
|
|
<option value="water2">水面2</option>
|
|
|
+ <option value="water02">一期沉砂池水面</option>
|
|
|
<option value="foam">泡沫片面</option>
|
|
|
+ <option value="foam2">一期沉砂池泡沫</option>
|
|
|
<option value="flow">流动纹理模型</option>
|
|
|
<option value="cscwater">CSCwater</option>
|
|
|
</select>
|
|
|
@@ -1235,6 +1484,7 @@ defineExpose({
|
|
|
<div class="section-label">选择材质</div>
|
|
|
<select v-model="selectedMaterialKey" class="model-select">
|
|
|
<option value="water">水材质</option>
|
|
|
+ <option value="water02">一期沉砂池水面材质</option>
|
|
|
<option value="foam">泡沫材质</option>
|
|
|
<option value="flow">流动纹理材质</option>
|
|
|
<option value="cscwater">CSCwater 材质</option>
|
|
|
@@ -1373,6 +1623,138 @@ defineExpose({
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
+ <template v-if="selectedMaterialKey === 'water02'">
|
|
|
+ <div class="material-section">
|
|
|
+ <div class="section-label">透明度</div>
|
|
|
+ <div class="slider-item">
|
|
|
+ <input type="range" v-model.number="water02Params.alpha" min="0" max="1" step="0.01" />
|
|
|
+ <span class="slider-value">{{ water02Params.alpha.toFixed(2) }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="material-section">
|
|
|
+ <div class="section-label">浪高</div>
|
|
|
+ <div class="slider-item">
|
|
|
+ <input type="range" v-model.number="water02Params.waveHeight" min="0" max="2" step="0.05" />
|
|
|
+ <span class="slider-value">{{ water02Params.waveHeight.toFixed(2) }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="material-section">
|
|
|
+ <div class="section-label">水流速度</div>
|
|
|
+ <div class="slider-item">
|
|
|
+ <input type="range" v-model.number="water02Params.flowSpeed" min="0" max="3" step="0.1" />
|
|
|
+ <span class="slider-value">{{ water02Params.flowSpeed.toFixed(1) }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="material-section">
|
|
|
+ <div class="section-label">流向 X</div>
|
|
|
+ <div class="slider-item">
|
|
|
+ <input type="range" v-model.number="water02Params.flowDirectionX" min="-2" max="2" step="0.1" />
|
|
|
+ <span class="slider-value">{{ water02Params.flowDirectionX.toFixed(1) }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="material-section">
|
|
|
+ <div class="section-label">流向 Z</div>
|
|
|
+ <div class="slider-item">
|
|
|
+ <input type="range" v-model.number="water02Params.flowDirectionY" min="-2" max="2" step="0.1" />
|
|
|
+ <span class="slider-value">{{ water02Params.flowDirectionY.toFixed(1) }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="material-section">
|
|
|
+ <div class="section-label">法线旋转</div>
|
|
|
+ <div class="slider-item">
|
|
|
+ <input type="range" v-model.number="water02Params.normalRotation" min="-180" max="180" step="1" />
|
|
|
+ <span class="slider-value">{{ water02Params.normalRotation.toFixed(0) }}°</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="material-section">
|
|
|
+ <div class="section-label">浅水颜色</div>
|
|
|
+ <div class="color-item">
|
|
|
+ <input type="color" v-model="water02Params.waterColor" />
|
|
|
+ <span class="color-value">{{ water02Params.waterColor }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="material-section">
|
|
|
+ <div class="section-label">深水颜色</div>
|
|
|
+ <div class="color-item">
|
|
|
+ <input type="color" v-model="water02Params.deepColor" />
|
|
|
+ <span class="color-value">{{ water02Params.deepColor }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="material-section">
|
|
|
+ <div class="section-label">水深范围</div>
|
|
|
+ <div class="slider-item">
|
|
|
+ <input type="range" v-model.number="water02Params.depthRange" min="1" max="50" step="0.5" />
|
|
|
+ <span class="slider-value">{{ water02Params.depthRange.toFixed(1) }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="material-section">
|
|
|
+ <div class="section-label">水法线强度</div>
|
|
|
+ <div class="slider-item">
|
|
|
+ <input type="range" v-model.number="water02Params.waterNormalStrength" min="0" max="2" step="0.05" />
|
|
|
+ <span class="slider-value">{{ water02Params.waterNormalStrength.toFixed(2) }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="material-section">
|
|
|
+ <div class="section-label">水纹平铺</div>
|
|
|
+ <div class="slider-item">
|
|
|
+ <input type="range" v-model.number="water02Params.waterNormalTiling" min="0.01" max="5" step="0.01" />
|
|
|
+ <span class="slider-value">{{ water02Params.waterNormalTiling.toFixed(2) }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="material-section">
|
|
|
+ <div class="section-label">高光强度</div>
|
|
|
+ <div class="slider-item">
|
|
|
+ <input type="range" v-model.number="water02Params.specIntensity" min="0" max="5" step="0.1" />
|
|
|
+ <span class="slider-value">{{ water02Params.specIntensity.toFixed(1) }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="material-section">
|
|
|
+ <div class="section-label">高光锐度</div>
|
|
|
+ <div class="slider-item">
|
|
|
+ <input type="range" v-model.number="water02Params.specPower" min="1" max="256" step="1" />
|
|
|
+ <span class="slider-value">{{ water02Params.specPower.toFixed(0) }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="material-section">
|
|
|
+ <div class="section-label">菲涅尔功率</div>
|
|
|
+ <div class="slider-item">
|
|
|
+ <input type="range" v-model.number="water02Params.fresnelPower" min="0.1" max="10" step="0.1" />
|
|
|
+ <span class="slider-value">{{ water02Params.fresnelPower.toFixed(1) }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="material-section">
|
|
|
+ <div class="section-label">菲涅尔强度</div>
|
|
|
+ <div class="slider-item">
|
|
|
+ <input type="range" v-model.number="water02Params.fresnelIntensity" min="0" max="3" step="0.1" />
|
|
|
+ <span class="slider-value">{{ water02Params.fresnelIntensity.toFixed(1) }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="material-section">
|
|
|
+ <div class="section-label">泡沫强度</div>
|
|
|
+ <div class="slider-item">
|
|
|
+ <input type="range" v-model.number="water02Params.foamIntensity" min="0" max="2" step="0.05" />
|
|
|
+ <span class="slider-value">{{ water02Params.foamIntensity.toFixed(2) }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="material-section">
|
|
|
+ <div class="section-label">碰撞泡沫阈值</div>
|
|
|
+ <div class="slider-item">
|
|
|
+ <input type="range" v-model.number="water02Params.collisionFoamThreshold" min="0" max="2" step="0.05" />
|
|
|
+ <span class="slider-value">{{ water02Params.collisionFoamThreshold.toFixed(2) }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="material-section">
|
|
|
+ <div class="section-label">碰撞泡沫强度</div>
|
|
|
+ <div class="slider-item">
|
|
|
+ <input type="range" v-model.number="water02Params.collisionFoamStrength" min="0" max="3" step="0.1" />
|
|
|
+ <span class="slider-value">{{ water02Params.collisionFoamStrength.toFixed(1) }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="material-section">
|
|
|
+ <button class="default-btn" @click="saveWater02Defaults">设置默认值</button>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+
|
|
|
<template v-if="selectedMaterialKey === 'foam'">
|
|
|
<div class="material-section">
|
|
|
<div class="section-label">颜色</div>
|