增加 城市案例中 一个扩散 亮圈的例子

This commit is contained in:
hawk86104 2024-09-12 19:12:50 +08:00
parent 2e96c37f1b
commit e9db7c6eaf
8 changed files with 275 additions and 72 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 KiB

View File

@ -4,7 +4,7 @@
* @Autor: 地虎降天龙
* @Date: 2023-11-03 16:02:49
* @LastEditors: 地虎降天龙
* @LastEditTime: 2024-05-24 18:25:48
* @LastEditTime: 2024-09-12 19:10:41
-->
<template>
<FDivider titlePlacement="left">{{ props.onePlugin.title + ' - ' + props.onePlugin.name }}</FDivider>
@ -43,7 +43,7 @@
<video controls class="w-full max-h-70 h-14em" v-if="onePreview.type === 'video'">
<source :src="publicPath + onePreview.src" type="video/mp4" autoplay="true" loop="true" />
</video>
<FImage class="w-full max-h-70 h-14em" v-else-if="onePreview.type === 'img'" :src="publicPath + onePreview.src" lazy />
<FImage class="w-full max-h-70 h-14em" fit="contain" v-else-if="onePreview.type === 'img'" :src="publicPath + onePreview.src" lazy />
<div
class="w-full h-48 text-3 text-left mb-2"
style="background-color: rgb(55 56 61); overflow: hidden; border-radius: 10px"

View File

@ -0,0 +1,27 @@
/*
* @Description:
* @Version: 1.668
* @Autor:
* @Date: 2024-09-12 16:47:13
* @LastEditors:
* @LastEditTime: 2024-09-12 16:58:34
*/
import { useTresContext } from '@tresjs/core'
const { sizes } = useTresContext()
export function useDepthBuffer({ size = 256, frames = Infinity }: { size?: number; frames?: number } = {}) {
const dpr = sizes.aspectRatio.value
const width = sizes.width.value
const height = sizes.height.value
const w = size || width * dpr
const h = size || height * dpr
const depthConfig =
const depthTexture = new DepthTexture(w, h)
depthTexture.format = DepthFormat
depthTexture.type = UnsignedShortType
return { depthTexture }
// return target
}

View File

@ -1,95 +1,97 @@
/*
* @Description:
* @Description:
* @Version: 1.668
* @Autor:
* @Date: 2024-04-15 11:08:17
* @LastEditors:
* @LastEditTime: 2024-04-30 09:26:36
* @LastEditTime: 2024-09-12 18:13:42
*/
import { useRenderLoop, useTresContext } from '@tresjs/core'
import type { Camera, WebGLRenderTargetOptions } from 'three'
import { DepthTexture, FloatType, HalfFloatType, LinearFilter, WebGLRenderTarget } from 'three'
import { DepthTexture, DepthFormat, UnsignedShortType, HalfFloatType, LinearFilter, WebGLRenderTarget } from 'three'
import type { Ref } from 'vue'
import { isReactive, onBeforeUnmount, reactive, ref, toRefs, watchEffect } from 'vue'
import { isReactive, onBeforeUnmount, reactive, ref, toRefs, watchEffect, toRaw } from 'vue'
export interface FboOptions {
/*
* The width of the frame buffer object. Defaults to the width of the canvas.
*
* @type {number}
* @memberof FboProps
*/
width?: number
/*
* The width of the frame buffer object. Defaults to the width of the canvas.
*
* @type {number}
* @memberof FboProps
*/
width?: number
/*
* The height of the frame buffer object. Defaults to the height of the canvas.
*
* @type {number}
* @memberof FboProps
*/
height?: number
/*
* The height of the frame buffer object. Defaults to the height of the canvas.
*
* @type {number}
* @memberof FboProps
*/
height?: number
/*
* If set, the scene depth will be rendered into buffer.depthTexture.
*
* @default false
* @type {boolean}
* @memberof FboProps
*/
depth?: boolean
/*
* If set, the scene depth will be rendered into buffer.depthTexture.
*
* @default false
* @type {boolean}
* @memberof FboProps
*/
depth?: boolean
/*
* Additional settings for the render target.
* See https://threejs.org/docs/#api/en/renderers/WebGLRenderTarget for more information.
*
* @default {}
* @type {WebGLRenderTargetOptions}
* @memberof FboProps
*/
settings?: WebGLRenderTargetOptions
/*
* Additional settings for the render target.
* See https://threejs.org/docs/#api/en/renderers/WebGLRenderTarget for more information.
*
* @default {}
* @type {WebGLRenderTargetOptions}
* @memberof FboProps
*/
settings?: WebGLRenderTargetOptions
isLoop?: boolean
isLoop?: boolean
}
export function useFBO(options: FboOptions) {
const target: Ref<WebGLRenderTarget | null> = ref(null)
const target: Ref<WebGLRenderTarget | null> = ref(null)
const { height, width, settings, depth, isLoop } = isReactive(options) ? toRefs(options) : toRefs(reactive(options))
const { height, width, settings, depth, isLoop } = isReactive(options) ? toRefs(options) : toRefs(reactive(options))
const { onLoop } = useRenderLoop()
const { camera, renderer, scene, sizes } = useTresContext()
const { onLoop } = useRenderLoop()
const { camera, renderer, scene, sizes } = useTresContext()
watchEffect(() => {
target.value?.dispose()
target.value = new WebGLRenderTarget(width?.value || sizes.width.value, height?.value || sizes.height.value, {
minFilter: LinearFilter,
magFilter: LinearFilter,
type: HalfFloatType,
...settings?.value,
watchEffect(() => {
target.value?.dispose()
target.value = new WebGLRenderTarget(width?.value || sizes.width.value, height?.value || sizes.height.value, {
minFilter: LinearFilter,
magFilter: LinearFilter,
type: HalfFloatType,
...settings?.value,
})
if (depth?.value) {
target.value.depthTexture = new DepthTexture(
width?.value || sizes.width.value,
height?.value || sizes.height.value,
// FloatType,
)
target.value.depthTexture.format = DepthFormat
target.value.depthTexture.type = UnsignedShortType
}
})
if (depth?.value) {
target.value.depthTexture = new DepthTexture(
width?.value || sizes.width.value,
height?.value || sizes.height.value,
FloatType,
)
}
})
onLoop(() => {
if (isLoop?.value) {
renderer.value.setRenderTarget(toRaw(target.value))
renderer.value.clear()
renderer.value.render(toRaw(scene.value), toRaw(camera.value) as Camera)
onLoop(() => {
if (isLoop?.value) {
renderer.value.setRenderTarget(target.value)
renderer.value.clear()
renderer.value.render(scene.value, camera.value as Camera)
renderer.value.setRenderTarget(null)
}
})
renderer.value.setRenderTarget(null)
}
})
onBeforeUnmount(() => {
target.value?.dispose()
})
onBeforeUnmount(() => {
target.value?.dispose()
})
return target
return target
}

View File

@ -0,0 +1,136 @@
threshold
<template>
<TresMesh :renderOrder="2200">
<TresSphereGeometry :args="[props.radius, 64, 64]" />
<TresShaderMaterial v-bind="shader" />
</TresMesh>
</template>
<script setup lang="ts">
import { toRaw, watch } from 'vue'
import { useRenderLoop, useTresContext } from '@tresjs/core'
import { useFBO } from 'PLS/basic'
import * as THREE from 'three'
const props = withDefaults(
defineProps<{
radius?: number
shieldColor?: string
rimColor?: string
threshold?: number
}>(),
{
radius: 100,
shieldColor: '#ffff00',
rimColor: '#ffffff',
threshold: 0.005,
},
)
const { sizes, camera } = useTresContext()
const dpr = sizes.aspectRatio.value
const widths = sizes.width.value
const heights = sizes.height.value
const ws = widths * dpr
const hs = heights * dpr
const fbo = useFBO({ height: ws, width: hs, depth: true, isLoop: true }) //autoRender
const shader = {
blending: THREE.NormalBlending,
transparent: true,
depthWrite: false,
depthTest: true,
side: THREE.DoubleSide,
// depthTest: true,
vertexShader: `
varying vec2 vUv;
varying vec3 vNormal;
varying vec3 vPosition;
void main() {
vUv = uv;
vec4 worldPos = modelMatrix * vec4(position, 1.0);
vec4 modelNormal = modelMatrix * vec4(normal, 0.0);
vec4 mvPosition = viewMatrix * worldPos;
gl_Position = projectionMatrix * mvPosition;
vNormal = modelNormal.xyz;
vPosition = worldPos.xyz;
}
`,
fragmentShader: `
uniform sampler2D uDepthTexture;
uniform vec2 uResolution;
uniform float uNear;
uniform float uFar;
uniform float uThreshold;
uniform vec3 uShieldColor;
uniform vec3 uRimColor;
varying vec2 vUv;
varying vec3 vNormal;
varying vec3 vPosition;
#include <packing>
float LinearizeDepth(float depth) {
float zNdc = 2.0 * depth - 1.0;
float zEye = (2.0 * uFar * uNear) / ((uFar + uNear) - zNdc * (uFar - uNear));
float linearDepth = (zEye - uNear) / (uFar - uNear);
return linearDepth;
}
void main() {
vec3 normal = normalize(vNormal);
if(gl_FrontFacing) {
normal *= -1.0;
}
vec3 viewDirection = normalize(cameraPosition - vPosition);
float fresnel = 1. + dot(normal, viewDirection);
fresnel = pow(fresnel, 4.0);
vec2 worldCoords = gl_FragCoord.xy/uResolution;
float sceneDepth = LinearizeDepth(texture2D(uDepthTexture, worldCoords).r);
float bubbleDepth = LinearizeDepth(gl_FragCoord.z);
float difference = abs( sceneDepth - bubbleDepth);
float normalizedDistance = clamp(difference / uThreshold, 0.0, 1.0);
vec4 intersection = mix(vec4(1.0), vec4(0.0), normalizedDistance) ;
intersection.rgb *= uRimColor;
vec4 color = vec4(uShieldColor, 0.3);
gl_FragColor = color + intersection + vec4(uRimColor, 1.0) * fresnel ;
}
`,
uniforms: {
uDepthTexture: { value: toRaw(fbo?.value?.depthTexture) },
uResolution: { value: new THREE.Vector2(widths, heights) },
uNear: {
value: 1, //camera.value?.near,
},
uFar: {
value: 10000, //camera.value?.far,
},
uThreshold: {
value: 0.005,
},
uShieldColor: { value: new THREE.Color(props.shieldColor) },
uRimColor: { value: new THREE.Color(props.rimColor) },
},
}
const { onLoop } = useRenderLoop()
onLoop(() => {
// debugger
// camera
// shader.uniforms.uDepthTexture.value = toRaw(fbo?.value?.depthTexture)
})
watch(
() => [props.rimColor, props.shieldColor, props.threshold],
([rimColor, shieldColor, threshold]) => {
shader.uniforms.uRimColor.value.setStyle(rimColor)
shader.uniforms.uShieldColor.value.setStyle(shieldColor)
shader.uniforms.uThreshold.value = threshold
},
)
</script>

View File

@ -4,7 +4,7 @@
* @Autor: 地虎降天龙
* @Date: 2023-10-26 09:20:42
* @LastEditors: 地虎降天龙
* @LastEditTime: 2024-08-19 19:07:32
* @LastEditTime: 2024-09-12 16:16:49
*/
export default {
name: 'digitalCity',
@ -19,6 +19,7 @@ export default {
// { "src": "plugins/digitalCity/preview/buildings.mp4", "type": "video", "name": "buildings", "title": "建筑物" },
{ src: 'plugins/digitalCity/preview/buildings.png', type: 'img', name: 'buildings', title: '建筑物' },
{ src: 'plugins/digitalCity/preview/radars.png', type: 'img', name: 'radars', title: '雷达' },
{ src: 'plugins/digitalCity/preview/depthBufferDiffuse.png', type: 'img', name: 'depthBufferDiffuse', title: '带深度的半球扩散' },
{ src: 'plugins/digitalCity/preview/weather.png', type: 'img', name: 'weather', title: '天气' },
{ src: 'plugins/digitalCity/preview/lightningStorm.png', type: 'img', name: 'lightningStorm', title: '闪电' },
{ src: 'plugins/digitalCity/preview/clouds.png', type: 'img', name: 'clouds', title: '云☁️' },

View File

@ -4,10 +4,11 @@
* @Autor: 地虎降天龙
* @Date: 2024-03-15 22:00:55
* @LastEditors: 地虎降天龙
* @LastEditTime: 2024-08-19 19:05:24
* @LastEditTime: 2024-09-12 16:28:47
*/
import radraA from './components/radras/radraA.vue'
import radraB from './components/radras/radraB.vue'
import depthBufferDiffuse from './components/radras/depthBufferDiffuse.vue'
import precipitation from './components/weather/precipitation.vue'
import cloudMesh from './components/weather/cloudMesh.vue'
import markA from './components/buildings/buildingsMarkA.vue'
@ -23,6 +24,7 @@ import { reAnchorCenter, toMeshSceneCenter, objectToSceneCenter, adjustGroupCent
export {
radraA,
radraB,
depthBufferDiffuse,
precipitation,
cloudMesh,
markA,

View File

@ -0,0 +1,35 @@
<template>
<loading></loading>
<pagesShow ref="pagesShowRef">
<template v-slot:ability>
<depthBufferDiffuse :position="[0, 30, 0]" v-bind="cmConfig" />
</template>
</pagesShow>
</template>
<script setup lang="ts">
import { defaultLoading as loading } from 'PLS/UIdemo'
import { depthBufferDiffuse } from 'PLS/digitalCity'
import { Pane } from 'tweakpane'
import { reactive, shallowRef, watchEffect } from 'vue'
import pagesShow from '../components/pagesShow.vue'
const cmConfig = reactive({
shieldColor: '#ffff00',
rimColor: '#ffffff',
threshold: 0.005,
radius: 100,
})
const paneControl = new Pane()
paneControl.addBinding(cmConfig, 'shieldColor', { label: '圈颜色' })
paneControl.addBinding(cmConfig, 'rimColor', { label: '条颜色' })
paneControl.addBinding(cmConfig, 'threshold', { label: '线条参数', min: 0.00001, max: 0.01, step: 0.00001 })
paneControl.addBinding(cmConfig, 'radius', { label: '大小', min: 10, max: 200, step: 1 })
const pagesShowRef = shallowRef(null)
watchEffect(() => {
if (pagesShowRef.value) {
pagesShowRef.value.$refs.perspectiveCameraRef.position.set(-135, 250, 320)
}
})
</script>