96 lines
3.6 KiB
Vue
96 lines
3.6 KiB
Vue
<script setup lang="ts">
|
|
import { FrontSide, RepeatWrapping } from 'three';
|
|
import { TresCanvas, useTexture } from '@tresjs/core'
|
|
import { OrbitControls, Environment, useGLTF } from '@tresjs/cientos'
|
|
|
|
const section_count = useState<number>('section_count')
|
|
const fence_section = useState<number>('fence_section')
|
|
|
|
const controlsState = reactive({
|
|
minDistance: 5,
|
|
maxDistance: 12,
|
|
enablePan: false,
|
|
maxPolarAngle: (Math.PI / 2) - 0.2,
|
|
})
|
|
const cameraStat = reactive({
|
|
position: [-4, 2, 8],
|
|
aspect: 1920 / 600,
|
|
fov: 40,
|
|
})
|
|
|
|
const pointLight = ref()
|
|
|
|
const groundMaterial = ref({
|
|
color: "#555",
|
|
roughness: 0.25,
|
|
metalness: 0,
|
|
side: FrontSide
|
|
})
|
|
const loadAll = async () => {
|
|
const { scene: light } = await useGLTF('/models_light/zabor_so_svetom.glb')
|
|
pointLight.value = light.children[2]
|
|
pointLight.value.color = '#f0dea9'
|
|
pointLight.value.shadow.camera.near = 50
|
|
pointLight.value.shadow.bias = -0.001
|
|
|
|
const pbrTexture = await useTexture({
|
|
map: '/texture/Grass004_2K-PNG/Grass004_2K-PNG_Color.png',
|
|
displacementMap: '/texture/Grass004_2K-PNG/Grass004_2K-PNG_Displacement.png',
|
|
roughnessMap: '/texture/Grass004_2K-PNG/Grass004_2K-PNG_Roughness.png',
|
|
normalMap: '/texture/Grass004_2K-PNG/Grass004_2K-PNG_NormalDX.png',
|
|
aoMap: '/texture/Grass004_2K-PNG/Grass004_2K-PNG_AmbientOcclusion.png',
|
|
})
|
|
const repeat = 10
|
|
for (const key in pbrTexture) {
|
|
if (Object.prototype.hasOwnProperty.call(pbrTexture, key)) {
|
|
const key_p = key as keyof typeof pbrTexture
|
|
const element = pbrTexture[key_p]
|
|
if (element && element.wrapS) {
|
|
element.wrapS = RepeatWrapping
|
|
element.wrapT = RepeatWrapping
|
|
element.repeat.x = repeat
|
|
element.repeat.y = repeat
|
|
element.flipY = false
|
|
}
|
|
}
|
|
}
|
|
groundMaterial.value = Object.assign(groundMaterial.value, {
|
|
map: pbrTexture.map,
|
|
displacementMap: pbrTexture.displacementMap,
|
|
normalMap: pbrTexture.normalMap,
|
|
})
|
|
}
|
|
onMounted(() => {
|
|
cameraStat.aspect = window.innerWidth / (window.innerHeight * 0.5)
|
|
loadAll()
|
|
})
|
|
</script>
|
|
<template>
|
|
<div class="container min-w-full relative h-[50vh]">
|
|
<ClientOnly fallback-tag="div" fallback="Загрузка 3D модели">
|
|
<Loader />
|
|
<TresCanvas shadows>
|
|
<TresPerspectiveCamera v-bind="cameraStat" />
|
|
<OrbitControls v-bind="controlsState" make-default />
|
|
<Suspense v-if="false">
|
|
<Environment files='/hdrmaps/kloppenheim_06_4k.hdr' :background="true" />
|
|
</Suspense>
|
|
<TresGroup :position-x="Math.min(section_count, 20) * fence_section * -1" :position-y="-3">
|
|
<Suspense>
|
|
<ModelParametric />
|
|
</Suspense>
|
|
</TresGroup>
|
|
<TresMesh receive-shadow :position-y="-3.65" name="ground">
|
|
<TresCircleGeometry :args="[100, 32]" :rotate-x="-Math.PI * 0.5" />
|
|
<TresMeshStandardMaterial v-bind="groundMaterial" />
|
|
</TresMesh>
|
|
<template v-if="pointLight">
|
|
<TresPointLight v-bind="pointLight" :intensity="pointLight.intensity * 0.5"
|
|
:position="Object.values(pointLight.position).map((el: any) => el * 3)" cast-shadow />
|
|
</template>
|
|
|
|
<TresAmbientLight color="rgb(191,231,255)" :intensity="5" />
|
|
</TresCanvas>
|
|
</ClientOnly>
|
|
</div>
|
|
</template> |