Merge branch 'bx-696-startproject' of https://git.svs-tech.pro/ksenia_mikhailova/mns-mini-zabor into bx-696-startproject

This commit is contained in:
commit e74b85f7ef
33 changed files with 237 additions and 219 deletions

34
app.vue
View File

@ -34,16 +34,13 @@ const roubleSign = new Intl.NumberFormat('ru-RU', {
const aboutText = computed(() => marked.parse(about?.content || ''))
const deliveryText = computed(() => delivery?.content.split('[col]').map(el => marked.parse(el || '')))
const advantagesText = computed(() =>
advantages?.content.split('[col]').map(el => {
let c = el || ''
Object.entries(calculatorData.value || {}).map(item => {
c = c.replaceAll(`[${item[0]}]`, roubleSign.format(item[1]))
})
return marked.parse(c)
}
)
)
const advantagesText = computed(() => {
let c = advantages?.content || ''
Object.entries(calculatorData.value || {}).map(item => {
c = c.replaceAll(`[${item[0]}]`, roubleSign.format(item[1]))
})
return marked.parse(c)
})
const { data: footerData } = await useFetch<ApiFooterType[]>(`${apiBase}/footer/?ordering=small_text`)
const { data: social_networkData } = await useFetch<ApiSocial_networkType[]>(`${apiBase}/social_network/`)
@ -117,15 +114,12 @@ const { scrollToAnchor, scrollToTop } = useAnchorScroll({
</div>
</div>
<div class="siteblock bg-white">
<ExpDiagram />
</div>
<div class="siteblock bg-white" :id="advantages?.slug" v-if="advantagesText">
<div class="container">
<div class="prose col-span-12 xl:col-span-6">
<span v-html="advantagesText[0]"></span>
<div class="container gap-4">
<div class="col-span-full xl:col-span-8">
<ExpDiagram />
</div>
<div class="prose col-span-12 xl:col-span-6">
<span v-html="advantagesText[1]"></span>
<div class="col-span-full xl:col-span-4 prose">
<span v-html="advantagesText"></span>
</div>
</div>
</div>
@ -135,7 +129,9 @@ const { scrollToAnchor, scrollToTop } = useAnchorScroll({
</div>
<div class="siteblock siteblock_calc bg-white">
<CalcValues />
<CalcModels />
<Suspense>
<CalcModels />
</Suspense>
</div>
<div class="siteblock bg-white" :id="delivery?.slug" v-if="deliveryText">
<div class="container">

View File

@ -74,11 +74,7 @@ a[href^="#"] {
@apply py-10;
&_imgbg {
@apply py-0 bg-no-repeat bg-cover bg-bottom;
img {
max-height: 50vh;
}
@apply py-0 bg-no-repeat bg-cover bg-bottom h-[50vh];
}
&_calc {

View File

@ -1,82 +1,96 @@
<script setup lang="ts">
import { TresCanvas } from '@tresjs/core'
import { OrbitControls, Environment, vLightHelper } from '@tresjs/cientos'
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,
// enableZoom: false,
maxPolarAngle: (Math.PI / 2) - 0.2,
// maxZoom: 2,
// minZoom: 1,
})
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 / 600
})
const spot = reactive({
x: 10, y: 10, z: 10, intensity: 10, distance: 10, color: 'red'
})
const directional = reactive({
x: 20, y: 10, z: 10, intensity: 10, distance: 10, color: 'green'
})
const point = reactive({
x: 30, y: 10, z: 10, intensity: 10, distance: 10, color: 'blue'
cameraStat.aspect = window.innerWidth / (window.innerHeight * 0.5)
loadAll()
})
</script>
<template>
<div class="container min-w-full relative" v-if="false">
<div>
<h2>spot</h2>
<template v-for="(label, key) in spot">
<label :for="key">{{ key }}</label>
<input :id="key" :type="key == 'color' ? 'text' : 'number'" v-model="spot[key]" style="width: 100px" />
</template>
<h2>directional</h2>
<template v-for="(label, key) in directional">
<label :for="key">{{ key }}</label>
<input :id="key" :type="key == 'color' ? 'text' : 'number'" v-model="directional[key]"
style="width: 100px" />
</template>
<h2>point</h2>
<template v-for="(label, key) in point">
<label :for="key">{{ key }}</label>
<input :id="key" :type="key == 'color' ? 'text' : 'number'" v-model="point[key]" style="width: 100px" />
</template>
</div>
</div>
<div class="container min-w-full relative">
<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>
<Suspense v-if="false">
<Environment files='/hdrmaps/kloppenheim_06_4k.hdr' :background="true" />
</Suspense>
<Suspense>
<ModelParametric />
</Suspense>
<template v-if="false">
<TresSpotLight v-bind="spot" :position="[spot.x, spot.y, spot.z]" cast-shadow v-light-helper />
<TresDirectionalLight v-bind="directional" :position="[directional.x, directional.y, directional.z]"
cast-shadow v-light-helper />
<TresPointLight v-bind="point" :position="[point.x, point.y, point.z]" cast-shadow v-light-helper />
<TresAmbientLight />
<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>
<style scoped>
.container {
height: 600px;
display: block;
}
</style>
</template>

View File

@ -2,25 +2,26 @@
import { getColorNameFromRal } from '@/components/ral'
import type { ralTypes } from '@/components/ral'
const lamelles_count = useState('lamelles_count', () => 8)
const lamelles_count = useState('lamelles_count', () => 14)
const fence_section = useState<number>('fence_section', () => 2000 * 0.001)
const remove_pillar = useState<boolean>('remove_pillar', () => false)
const pillar_color = useState<ralTypes>('pillar_color', () => '3009')
const lamelle_color = useState<ralTypes>('lamelle_color', () => '3004')
const section_count = useState('section_count', () => 1)
const section_count = useState('section_count', () => 10)
const extra_section = useState('extra_section', () => 0)
const total_length = useState('total_length', () => 2000 * 0.001 * 2)
const total_length = useState('total_length', () => (2000 * 8 - 100) * 0.001)
const min_length = useState('min_length', () => 1000)
const parametric = {
length: {
min: 1000,
min: min_length.value,
max: 2400,
step: 1,
},
total_length: {
min: 1,
min: min_length.value * 0.001,
max: undefined,
step: 0.1,
step: 0.5,
},
height: {
min: 675,
@ -32,9 +33,9 @@ const form_state = reactive({
length: fence_section.value * 1000,
fence_length: 100,
height: 100 + lamelles_count.value * parametric.height.step,
total_length: fence_section.value * 2,
total_length: total_length.value,
total_length_mm: fence_section.value * 1000,
full_sections: 1,
full_sections: section_count.value,
extra_section: 0,
auto_length: false,
remove_pillar: false
@ -92,7 +93,7 @@ const changeParametres = () => {
form_state.total_length = parametric.total_length.min
form_state.length = parametric.length.min
}
}, 300)
}, 600)
total_length.value = form_state.total_length
lamelles_count.value = lamelles
@ -120,7 +121,7 @@ const toggleModal = () => {
}
const plurals = {
lamelle: { one: 'ламель', few: 'ламели', many: 'ламелей' },
fence: { one: 'cстолб', few: 'столба', many: 'столбов' },
fence: { one: 'cтолб', few: 'столба', many: 'столбов' },
section: { one: 'секция', few: 'секции', many: 'секций' },
}
</script>
@ -164,25 +165,25 @@ const plurals = {
<label for="lamelle_color">Цвет ламелей</label>
<input id="lamelle_color" type="text" :value="getColorNameFromRal(lamelle_color)"
class="w-60" disabled />
<ColorPicker :cb="setLamelleColor" />
</div>
<div class="form-item">
<template v-for="item in predefLamelleColors">
<ColorPicker :color="item" :cb="setLamelleColor" :open="false"
:active="lamelle_color == item" />
</template>
<ColorPicker :cb="setLamelleColor" />
</div>
<div class="form-item">
<label for="pillar_color">Цвет столба</label>
<input id="pillar_color" type="text" :value="getColorNameFromRal(pillar_color)" class="w-60"
disabled />
<ColorPicker :cb="setPillarColor" />
</div>
<div class="form-item">
<template v-for="item in predefPillarColors">
<ColorPicker :color="item" :cb="setPillarColor" :open="false"
:active="pillar_color == item" />
</template>
<ColorPicker :cb="setPillarColor" />
</div>
</div>
</div>

View File

@ -9,19 +9,6 @@ const controlsState = reactive({
// enableZoom: false,
maxPolarAngle: (Math.PI / 2) - 0.2,
})
const container = ref()
const koef = ref()
const scrollBlock = (e: Event) => {
const { top, bottom, height } = container.value.getBoundingClientRect();
const { innerHeight } = window;
const partiallyVisible = (top > 0 && top < innerHeight) ||
(bottom > 0 && bottom < innerHeight)
const visibleHeight = innerHeight - top
const h = height * 1.5
if (partiallyVisible && visibleHeight < h) {
koef.value = visibleHeight / h
}
}
const targetExplosion = useState('targetExplosion', () => {
const k = 1.5
return {
@ -35,15 +22,9 @@ const targetExplosion = useState('targetExplosion', () => {
})
</script>
<template>
<div class="container min-w-full" ref="container">
<div class="h-96">
<ClientOnly fallback-tag="div" fallback="Загрузка 3D модели">
<template v-for="(value, key) in targetExplosion" v-if="false">
<div>
<label for="key">{{ key }}</label>
<input type="number" v-for="(item, n) in value" v-model="targetExplosion[key][n]" step="0.25">
</div>
</template>
<TresCanvas preset="realistic">
<TresCanvas preset="realistic" heoght="600">
<TresPerspectiveCamera :position="[-7, 2, 4]" />
<OrbitControls v-bind="controlsState" make-default />
<Suspense>

View File

@ -1,11 +1,14 @@
<script setup lang="ts">
import { getColorHexFromRal } from '@/components/ral'
import type { ralTypes } from '@/components/ral'
import { CanvasTexture } from 'three';
const props = defineProps(['index', 'models'])
const lamelles_count = useState<number>('lamelles_count')
const fence_section = useState<number>('fence_section')
const section_count = useState<number>('section_count')
const extra_section = useState<number>('extra_section')
const pillar_color = useState<ralTypes>('pillar_color')
const lamelle_color = useState<ralTypes>('lamelle_color')
const remove_pillar = useState<boolean>('remove_pillar')
@ -14,11 +17,11 @@ const lSize = 0.115
const bSize = 0.0235
const pillar_size = 80 * 0.001
const pillar_one_pos = ref(fence_section.value * -0.5 - 0.01)
const pillar_one_pos = ref(fence_section.value * -0.5 - 0.015)
const pillar_two_pos = ref(fence_section.value * 0.5 + pillar_size + bSize - 0.01)
watch([fence_section, lamelles_count], () => {
pillar_one_pos.value = fence_section.value * -0.5 - 0.01
pillar_one_pos.value = fence_section.value * -0.5 - 0.015
pillar_two_pos.value = fence_section.value * 0.5 + pillar_size + bSize - 0.01
})
const scale_koef = 2.5
@ -26,13 +29,8 @@ const show_pillar_one = ref(props.index == 1)
const show_pillar_two = ref(true)
const make_translate_to_section = () => {
let r = ((props.index - 1) / 2) * (fence_section.value + pillar_size + bSize) * scale_koef
if (props.index % 2 == 0) {
show_pillar_two.value = false
show_pillar_one.value = true
r += (fence_section.value * 0.5 + bSize) * scale_koef
return -1 * r
}
const one_s = (fence_section.value + pillar_size + bSize)
let r = (props.index - 1) * one_s * scale_koef
return r
}
const translate_to_section = ref(make_translate_to_section())
@ -40,10 +38,51 @@ const translate_to_section = ref(make_translate_to_section())
watch(fence_section, () => {
translate_to_section.value = make_translate_to_section()
})
const s = 512
const canvas = document.createElement('canvas')
canvas.width = s
canvas.height = s
const ctx = canvas.getContext('2d') as CanvasRenderingContext2D
ctx.fillStyle = "red"
ctx.font = "512px serif"
ctx.textAlign = "center"
ctx.textBaseline = 'middle'
ctx.fillText(props.index, s * 0.5, s * 0.5)
const textures: any[] = []
for (let index = 0; index < lamelles_count.value; index++) {
const element = document.createElement('canvas')
element.width = s
element.height = s / lamelles_count.value
const e_ctx = element.getContext('2d') as CanvasRenderingContext2D
e_ctx.drawImage(canvas,
0, (s / lamelles_count.value) * index, s, s / lamelles_count.value,
0, 0, s, s / lamelles_count.value
);
textures.push(new CanvasTexture(element))
}
const extra = ref((extra_section && props.index == (section_count.value + 1)) ? extra_section.value * 0.001 : false)
if (extra.value) {
pillar_two_pos.value = extra.value * 0.5 + pillar_size + bSize - 0.01
}
watch([extra_section, section_count], () => {
extra.value = (extra_section && props.index == (section_count.value + 1)) ? extra_section.value * 0.001 : false
if (extra_section && props.index == (section_count.value + 1)) {
// pillar_one_pos.value = extra_section.value * -0.5 - 0.015
pillar_two_pos.value = extra.value * 0.5 + pillar_size + bSize - 0.01
} else {
// pillar_one_pos.value = fence_section.value * -0.5 - 0.015
pillar_two_pos.value = fence_section.value * 0.5 + pillar_size + bSize - 0.01
}
})
console.log({ pillar_size, fence_section: fence_section.value })
</script>
<template>
<TresGroup :scale="scale_koef" :position-x="translate_to_section" :name="`fence ${index}`">
<TresGroup name="pillar_one" v-if="!remove_pillar && show_pillar_one" :position-x="pillar_one_pos" :position-z="0">
<TresGroup :scale="scale_koef" :position-x="translate_to_section" :name="`fence ${index}`"
:position-y="extra ? 1 : 0">
<TresGroup name="pillar_one" v-if="!remove_pillar && show_pillar_one" :position-x="pillar_one_pos"
:position-z="0">
<TresGroup :position-y="(lSize * -0.5)" :scale="[1, 0.5, 1]">
<ModelItem :model="props.models.fence" :color="getColorHexFromRal(pillar_color)" />
</TresGroup>
@ -57,7 +96,8 @@ watch(fence_section, () => {
</TresGroup>
</TresGroup>
<TresGroup name="pillar_two" v-if="!remove_pillar && show_pillar_two" :position-x="pillar_two_pos" :position-z="0">
<TresGroup name="pillar_two" v-if="!remove_pillar && show_pillar_two" :position-x="pillar_two_pos"
:position-z="0">
<TresGroup :position-y="(lSize * -0.5)" :scale="[-1, 0.5, 1]">
<ModelItem :model="props.models.fence" :color="getColorHexFromRal(pillar_color)" />
</TresGroup>
@ -73,8 +113,9 @@ watch(fence_section, () => {
<TresGroup name="lamelles">
<template v-for="(n, i) in lamelles_count">
<TresGroup :position="[pillar_size * 0.5, (lSize * i), 0.02]" :scale-x="fence_section * 10">
<ModelItem :model="props.models.lamelle" :color="getColorHexFromRal(lamelle_color)" />
<TresGroup :position="[pillar_size * 0.5, (lSize * i), 0.02]" :scale-x="(extra || fence_section) * 10">
<ModelItem :model="props.models.lamelle" :color="getColorHexFromRal(lamelle_color)"
:map="textures[textures.length - 1 - i]" />
</TresGroup>
</template>
</TresGroup>
@ -93,7 +134,7 @@ watch(fence_section, () => {
</TresGroup>
</template>
</TresGroup>
<TresGroup name="top_section" :scale-x="fence_section * 10"
<TresGroup name="top_section" :scale-x="(extra || fence_section) * 10"
:position="[pillar_size * 0.5, lamelles_count * lSize, 0]">
<ModelItem :model="props.models.top" :color="getColorHexFromRal(pillar_color)" />
</TresGroup>

View File

@ -1,7 +1,7 @@
<script setup lang="ts">
import { useGLTF } from '@tresjs/cientos'
import { Box3, Color, MeshStandardMaterial, Vector3 } from 'three';
const props = defineProps(['modelUrl', 'model', 'position', 'refPosition', 'removePos', 'target', 'color'])
import { Box3, Color, DoubleSide, MeshStandardMaterial, Vector3 } from 'three';
const props = defineProps(['modelUrl', 'model', 'position', 'refPosition', 'removePos', 'target', 'color', 'map'])
let scene
if (props.modelUrl) {
@ -21,8 +21,8 @@ box.getSize(size)
const getMaterial = () => {
return new MeshStandardMaterial({
color: props.color ? new Color(props.color) : new Color('#9c9c9c'),
roughness: 0.3,
color: new Color(props.color || '#9c9c9c'),
roughness: 0.2,
metalness: 0.5,
})
}
@ -102,6 +102,10 @@ watch(targetExplosion, () => {
<TresGroup :position="props.refPosition ? targetExplosion[props.refPosition] : (props.position || [0, 0, 0])"
ref="model">
<primitive :object="scene.children[0]" />
<TresMesh v-if="props.map" :cast-shadow="false" :receive-shadow="false">
<TresPlaneGeometry :args="[size.x, size.y]" />
<TresMeshPhongMaterial :map="props.map" :transparent="true" :opacity="0.5" :side="DoubleSide" />
</TresMesh>
</TresGroup>
</Suspense>
</template>

View File

@ -1,111 +1,54 @@
<script setup lang="ts">
import { ReinhardToneMapping, PCFShadowMap, RepeatWrapping, Color, DataTexture, RGBAFormat } from 'three';
import { useTexture } from '@tresjs/core'
import { useGLTF } from '@tresjs/cientos'
const section_count = useState('section_count')
import {
ReinhardToneMapping, PCFSoftShadowMap,
PMREMGenerator, Euler,
} from 'three';
import { EXRLoader } from 'three/examples/jsm/Addons.js';
import { useGLTF, } from '@tresjs/cientos'
const section_count = useState<number>('section_count')
const extra_section = useState<number>('extra_section')
const { scene, renderer, camera } = useTresContext()
renderer.value.toneMapping = ReinhardToneMapping
renderer.value.shadowMap.enabled = true
renderer.value.shadowMap.type = PCFShadowMap
renderer.value.shadowMap.type = PCFSoftShadowMap
const pbrTexture = await useTexture({
map: '/texture/Grass001_4K-JPG/Grass001_4K-JPG_Color.jpg',
// displacementMap: '/texture/Ground039_4K-JPG_Displacement.jpg',
roughnessMap: '/texture/Grass001_4K-JPG/Grass001_4K-JPG_Roughness.jpg',
normalMap: '/texture/Grass001_4K-JPG/Grass001_4K-JPG_NormalGL.jpg',
aoMap: '/texture/Grass001_4K-JPG/Grass001_4K-JPG_AmbientOcclusion.jpg',
// metalnessMap: '/texture/Ground039_4K-JPG_Color.jpg',
// matcap: '/textures/Ground039_4K-JPG_Color.jpg',
// alphaMap: '/textures/myAlphaMapTexture.jpg'
})
const repeat = 5
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
}
}
}
const { scene: top } = await useGLTF('/models_one/verh_100.glb')
const { scene: fence } = await useGLTF('/models_one/fence.glb')
const { scene: fastening } = await useGLTF('/models_one/krepleniye_planok (1).glb')
const { scene: lamelle } = await useGLTF('/models_one/lamel_100.glb')
const { seek, seekAll } = useSeek()
watch(section_count, () => {
const fences = seekAll(scene.value, 'name', 'fence')
const { seek } = useSeek()
watch([section_count,extra_section], () => {
const base = seek(scene.value, 'name', 'base')
const n = (section_count.value as number)
if (fences.length > n) {
for (let i = fences.length; i > n; i--) {
const item = fences[i - 1]
if (item) {
base?.remove(item)
}
}
const n = (section_count.value as number) + ~~(!!extra_section.value)
if (base?.children && n < base?.children.length) {
base.children = [...base?.children.slice(0, n)]
}
})
const width = 512;
const height = 512;
const size = width * height;
const data = new Uint8Array(4 * size);
const color = new Color(0xffffff);
const r = Math.floor(color.r * 25);
const g = Math.floor(color.g * 25);
const b = Math.floor(color.b * 255);
for (let i = 0; i < size; i++) {
const stride = i * 4;
data[stride] = r;
data[stride + 1] = g;
data[stride + 2] = b;
data[stride + 3] = 255;
}
const texture_one = new DataTexture(data, width, height);
texture_one.needsUpdate = true;
const pmremGenerator = new PMREMGenerator(renderer.value);
pmremGenerator.compileEquirectangularShader();
onMounted(() => {
new EXRLoader()
.load('/hdrmaps/kloppenheim_06_4k.exr', function (texture) {
const exrCubeRenderTarget = pmremGenerator.fromEquirectangular(texture);
const exrBackground = exrCubeRenderTarget.texture;
const newEnvMap = exrCubeRenderTarget ? exrCubeRenderTarget.texture : null;
scene.value.environment = newEnvMap
scene.value.background = exrBackground
scene.value.backgroundRotation = new Euler(0, 5, 0)
texture.dispose();
});
})
const canvas = document.createElement('canvas')
canvas.width = 512
canvas.height = 512
const ctx = canvas.getContext('2d')
ctx.fillStyle = "red"
ctx.fillRect(10, 10, 512, 512)
console.log(canvas.toDataURL())
const texture = new DataTexture(ctx?.getImageData(0, 0, 512, 512).data.buffer, width, height);
texture.needsUpdate = true;
</script>
<template>
<TresGroup :translate-y="-3.25" name="base">
<TresMesh receive-shadow :position-y="-0.5" name="ground">
<TresCircleGeometry :args="[55, 32]" :rotate-x="-Math.PI * 0.5" />
<TresMeshStandardMaterial :map="pbrTexture.map" :normal-map="pbrTexture.normalMap"
:roughness-map="pbrTexture.roughnessMap" :ao-map="pbrTexture.aoMap" :metalness="0" :roughness="0.8" />
</TresMesh>
<TresMesh receive-shadow :position-y="-0.25" :position-x="10" name="ground">
<TresCircleGeometry :args="[10]" :rotate-x="-Math.PI * 0.5" />
<TresMeshStandardMaterial color="#eee" />
</TresMesh>
<TresMesh receive-shadow name="ground_test" :position-z="-10">
<TresCircleGeometry :args="[5]" :rotate-x="-Math.PI * 0.5" />
<TresMeshStandardMaterial :map="texture_one" />
</TresMesh>
<TresMesh receive-shadow name="ground_test" :position-z="10">
<TresCircleGeometry :args="[5]" :rotate-x="-Math.PI * 0.5" />
<TresMeshStandardMaterial :map="texture" />
</TresMesh>
<TresMesh :position="[-9, 0, 2]" cast-shadow receive-shadow>
<TresBoxGeometry :args="[1, 1, 1]" />
<TresMeshStandardMaterial :map="texture_one" />
</TresMesh>
<template v-for="i in section_count">
<TresGroup name="base">
<template v-for="i in (section_count + ~~(!!extra_section))">
<template v-if="i <= 20">
<ModelFence :index="i" :models="{ top, fence, fastening, lamelle }" />
</template>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 MiB

After

Width:  |  Height:  |  Size: 48 MiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

View File

@ -0,0 +1,42 @@
<?xml version="1.0"?>
<materialx version="1.38" fileprefix="./">
<standard_surface ypos="-1.879310" name="Grass004_2K_PNG_StandardSurface" type="surfaceshader" xpos="6.159420">
<input name="specular" type="float" value="0" />
<input name="coat" type="float" value="1" />
<input name="coat_color" type="color3" value="1, 1, 1" />
<input name="base" type="float" value="1" />
<input name="base_color" type="color3" nodename="Grass004_2K_PNG_Color" />
<input name="normal" type="vector3" nodename="normalmap" />
<input name="coat_normal" type="vector3" nodename="normalmap" />
<input name="specular_roughness" type="float" nodename="Grass004_2K_PNG_Roughness" />
<input name="coat_roughness" type="float" nodename="Grass004_2K_PNG_Roughness" />
</standard_surface>
<surfacematerial ypos="0.000000" name="Grass004_2K_PNG" type="material" xpos="8.695652">
<input name="surfaceshader" type="surfaceshader" nodename="Grass004_2K_PNG_StandardSurface" />
<input name="displacementshader" type="displacementshader" nodename="displacement" />
</surfacematerial>
<tiledimage ypos="-3.103448" name="Grass004_2K_PNG_Color" type="color3" xpos="3.623188">
<input colorspace="srgb_texture" name="file" type="filename" value="Grass004_2K-PNG_Color.png" />
<input name="uvtiling" type="vector2" value="1.0, 1.0" />
</tiledimage>
<tiledimage ypos="5.163793" name="Grass004_2K_PNG_Displacement" type="float" xpos="3.623188">
<input name="file" type="filename" value="Grass004_2K-PNG_Displacement.png" />
<input name="uvtiling" type="vector2" value="1.0, 1.0" />
</tiledimage>
<displacement ypos="1.879310" name="displacement" type="displacementshader" xpos="6.159420">
<input name="displacement" type="float" nodename="Grass004_2K_PNG_Displacement" />
<input name="scale" type="float" value="1.0" />
</displacement>
<tiledimage ypos="0.879310" name="Grass004_2K_PNG_NormalGL" type="vector3" xpos="1.086957">
<input name="file" type="filename" value="Grass004_2K-PNG_NormalGL.png" />
<input name="uvtiling" type="vector2" value="1.0, 1.0" />
</tiledimage>
<normalmap ypos="3.586207" name="normalmap" type="vector3" xpos="3.623188">
<input name="in" type="vector3" nodename="Grass004_2K_PNG_NormalGL" />
<input name="scale" type="float" value="1.0" />
</normalmap>
<tiledimage ypos="-0.413793" name="Grass004_2K_PNG_Roughness" type="float" xpos="3.623188">
<input name="file" type="filename" value="Grass004_2K-PNG_Roughness.png" />
<input name="uvtiling" type="vector2" value="1.0, 1.0" />
</tiledimage>
</materialx>

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 MiB

After

Width:  |  Height:  |  Size: 23 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 MiB

After

Width:  |  Height:  |  Size: 23 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 MiB

After

Width:  |  Height:  |  Size: 13 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 MiB

After

Width:  |  Height:  |  Size: 11 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 MiB