完成了一个 流光的效果

This commit is contained in:
hawk86104 2024-04-15 21:01:29 +08:00
parent 97b3d4226d
commit c279f6dfd0
13 changed files with 336 additions and 37 deletions

View File

@ -1,7 +1,7 @@
<script setup lang="ts">
import type { Ref } from 'vue'
import { ref, useSlots, onUnmounted, watch, toRaw } from 'vue'
import { WebGLCubeRenderTarget, CubeCamera, HalfFloatType } from 'three'
import { WebGLCubeRenderTarget, CubeCamera, HalfFloatType, UnsignedByteType, NearestFilter } from 'three'
import type { CubeTexture, Texture } from 'three'
import { useTresContext, useRenderLoop } from '@tresjs/core'
import type { EnvironmentOptions } from './const'
@ -18,6 +18,7 @@ const props = withDefaults(defineProps<EnvironmentOptions>(), {
near: 1,
far: 1000,
frames: Infinity,
useDefaultScene: false
})
const texture: Ref<Texture | CubeTexture | null> = ref(null)
@ -38,7 +39,11 @@ let count = 1
onBeforeLoop(() => {
if (cubeCamera && envSence.value && fbo.value) {
if (props.frames === Infinity || count < props.frames) {
cubeCamera.update(renderer.value, toRaw(envSence.value.virtualScene))
if (props.useDefaultScene) {
cubeCamera.update(renderer.value, scene.value)
} else {
cubeCamera.update(renderer.value, toRaw(envSence.value.virtualScene))
}
count++
}
}
@ -57,23 +62,26 @@ const setTextureEnvAndBG = (fbo: WebGLCubeRenderTarget | null) => {
}
}
}
watch(useEnvironmentTexture, (value) => {
if (fbo.value) {
setTextureEnvAndBG(fbo.value)
}
}, { immediate: true, deep: true })
watch(useSlots().default, (value) => {
extend({ EnvSence })
watch(() => useSlots().default, (value) => {
if (value) {
slots = value
if (Array.isArray(slots)&&slots.length>0) {
if (typeof slots[0]?.type !== 'symbol') {
extend({ EnvSence })
fbo.value = new WebGLCubeRenderTarget(props.resolution)
fbo.value.texture.type = HalfFloatType
cubeCamera = new CubeCamera(props.near, props.far, fbo.value)
setTextureEnvAndBG(fbo.value)
return
if (!fbo.value || fbo.value.texture.type !== HalfFloatType) {
slots = value()
if (Array.isArray(slots) && slots.length > 0) {
if (typeof slots[0]?.type !== 'symbol') {
fbo.value?.dispose()
fbo.value = new WebGLCubeRenderTarget(props.resolution)
fbo.value.texture.type = HalfFloatType
cubeCamera = new CubeCamera(props.near, props.far, fbo.value)
setTextureEnvAndBG(fbo.value)
return
}
}
}
}
@ -82,6 +90,21 @@ watch(useSlots().default, (value) => {
setTextureEnvAndBG(null)
}, { immediate: true, deep: true })
texture.value = useEnvironmentTexture
watch(() => props.useDefaultScene, (newValue) => {
if (newValue) {
if (!fbo.value || fbo.value.texture.type !== UnsignedByteType) {
fbo.value?.dispose()
fbo.value = new WebGLCubeRenderTarget(props.resolution)
cubeCamera = new CubeCamera(props.near, props.far, fbo.value)
fbo.value.texture.type = UnsignedByteType
fbo.value.texture.generateMipmaps = false
fbo.value.texture.minFilter = NearestFilter
fbo.value.texture.magFilter = NearestFilter
setTextureEnvAndBG(fbo.value)
}
}
}, { immediate: true })
</script>
<template>

View File

@ -1,3 +1,11 @@
/*
* @Description:
* @Version: 1.668
* @Autor:
* @Date: 2024-04-08 14:23:31
* @LastEditors:
* @LastEditTime: 2024-04-15 15:24:56
*/
export interface EnvironmentOptions {
/**
* If true, the environment will be set as the scene's background.
@ -61,6 +69,10 @@ export interface EnvironmentOptions {
* @default Infinity
*/
frames?: number
/**
* If true, the default scene will be used.
*/
useDefaultScene?: boolean
}
export const environmentPresets = {

View File

@ -4,7 +4,7 @@
* @Autor:
* @Date: 2024-04-15 08:21:22
* @LastEditors:
* @LastEditTime: 2024-04-15 11:43:10
* @LastEditTime: 2024-04-15 11:56:56
*/
import {useTexture} from '@tresjs/core'
import * as THREE from 'three'
@ -20,7 +20,7 @@ const makeCustomShaderMaterial = (mirror: THREE.Mesh,reflector: any) => {
uReflectTexture: { type: "t", value:new THREE.Texture()},
uReflectIntensity: { type: "f", value: 15 },
uIntensity: { type: "f", value: 1 },
uLevel: { type: "f", value: 2.5 },
uLevel: { type: "f", value: 3.5 },
uResolution: { type: "v2", value: new THREE.Vector2() },
uTime: { type: "f", value: 0 },
}

View File

@ -4,23 +4,28 @@
* @Autor: 地虎降天龙
* @Date: 2024-04-14 17:59:21
* @LastEditors: 地虎降天龙
* @LastEditTime: 2024-04-14 19:05:11
* @LastEditTime: 2024-04-15 20:53:35
-->
<template>
<primitive :object="scene" :rotation-y="Math.PI" />
<Environment :blur="1" background :far="1000">
<Lightformer :intensity="0.66" :rotation-x="Math.PI / 2" :position="[0, 5, 0]" :scale="[10, 10, 1]" />
</Environment>
</template>
<script setup lang="ts">
import { useTexture } from '@tresjs/core'
import { useGLTF, Environment, Lightformer } from '@tresjs/cientos'
import { defineProps, withDefaults, watch } from 'vue'
import { useTexture, useRenderLoop } from '@tresjs/core'
import { useGLTF } from '@tresjs/cientos'
import * as THREE from 'three'
import { flatModel } from './utils'
import { MeshoptDecoder } from 'three/examples/jsm/libs/meshopt_decoder.module.js'
const props = withDefaults(
defineProps<{
run?: boolean
}>(),
{
run: false,
},
)
const { scene } = await useGLTF('./plugins/industry4/model/su7_car/sm_car.gltf', { draco: false }, (gltfLoader) => { gltfLoader.setMeshoptDecoder(MeshoptDecoder) })
const { map: pTexture } = await useTexture({ map: "./plugins/industry4/texture/t_car_body_AO.raw.jpg" })
pTexture.flipY = false
@ -30,6 +35,7 @@ pTexture.magFilter = THREE.NearestFilter
pTexture.channel = 1
const carModel = flatModel(scene)
const body = carModel[2] as THREE.Mesh
const bodyMat = body.material as THREE.MeshStandardMaterial
bodyMat.envMapIntensity = 5
@ -40,6 +46,7 @@ carModel.forEach((item: THREE.Mesh) => {
mat.aoMap = pTexture
}
})
const wheel = carModel[35] as THREE.Mesh
wheel.children.forEach((child) => {
const mesh = child as THREE.Mesh
@ -47,5 +54,33 @@ wheel.children.forEach((child) => {
mat.envMapIntensity = 5
})
const { onBeforeLoop } = useRenderLoop()
onBeforeLoop(({ delta }) => {
if (props.run) {
wheel.children.forEach((child) => {
child.rotateZ(-delta * 30 * 0.5)
})
}
})
watch(
() => props.run,
(newVal) => {
if (newVal) {
wheel.children.forEach((child) => {
const mesh = child as THREE.Mesh
const mat = mesh.material as THREE.MeshStandardMaterial
mat.roughness = 0
mat.envMapIntensity = 3
})
} else {
wheel.children.forEach((child) => {
const mesh = child as THREE.Mesh
const mat = mesh.material as THREE.MeshStandardMaterial
mat.roughness = 1
mat.envMapIntensity = 5
})
}
}
)
</script>

View File

@ -0,0 +1,70 @@
<!--
* @Description:
* @Version: 1.668
* @Autor: 地虎降天龙
* @Date: 2024-04-09 15:38:12
* @LastEditors: 地虎降天龙
* @LastEditTime: 2024-04-15 20:59:24
-->
<template></template>
<script setup lang="ts">
import { watchEffect, watch } from 'vue'
import * as THREE from 'three'
import { useTresContext, useRenderLoop } from '@tresjs/core'
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass'
import { OutputPass } from 'three/examples/jsm/postprocessing/OutputPass.js'
import { UnrealBloomPass } from 'three/examples/jsm/postprocessing/UnrealBloomPass'
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer'
const props = withDefaults(
defineProps<{
hide?: boolean
}>(),
{
hide: false,
},
)
const { camera, renderer, scene, sizes } = useTresContext()
const params = {
threshold: 0.666,
strength: 0.166,
radius: 0.3,
}
let effectComposer = null as any
let bloomPass = null as any
const Effect = (scene: THREE.Scene, camera: THREE.PerspectiveCamera, renderer: THREE.WebGLRenderer, width: number, height: number) => {
const renderScene = new RenderPass(scene, camera)
bloomPass = new UnrealBloomPass(new THREE.Vector2(width, height), params.strength, params.radius, params.threshold)
effectComposer = new EffectComposer(renderer)
//
effectComposer.addPass(renderScene)
effectComposer.addPass(bloomPass)
effectComposer.addPass(new OutputPass())
}
watchEffect(() => {
if (sizes.width.value) {
Effect(scene.value, camera.value as any, renderer.value, sizes.width.value, sizes.height.value)
}
})
watch(
() => props.hide,
(newVal) => {
if (newVal) {
bloomPass.enabled = false
} else {
bloomPass.enabled = true
}
}
)
const { onLoop } = useRenderLoop()
onLoop(() => {
if (effectComposer) {
effectComposer.render()
}
})
</script>

View File

@ -0,0 +1,40 @@
<template>
<primitive :object="scene" />
</template>
<script setup lang="ts">
import * as THREE from 'three'
import { useRenderLoop } from '@tresjs/core'
import { useGLTF } from '@tresjs/cientos'
import { MeshoptDecoder } from 'three/examples/jsm/libs/meshopt_decoder.module.js'
import CustomShaderMaterial from 'three-custom-shader-material/vanilla'
import vertexShader from '../../shaders/speedup.vert'
import fragmentShader from '../../shaders/speedup.frag'
const { scene } = await useGLTF('./plugins/industry4/model/su7_car/sm_speedup.gltf', { draco: false }, (gltfLoader) => { gltfLoader.setMeshoptDecoder(MeshoptDecoder) })
const uniforms = {
uTime: { value: 0 },
uSpeedFactor: { value: 0 },
}
const mat = new CustomShaderMaterial({
baseMaterial: THREE.ShaderMaterial,
uniforms,
vertexShader,
fragmentShader,
transparent: true,
depthWrite: false,
})
scene.traverse((child: THREE.Object3D) => {
if ((child as THREE.Mesh).isMesh) {
const mesh = child as THREE.Mesh
mesh.material = mat
}
})
const { onBeforeLoop } = useRenderLoop()
onBeforeLoop(({ delta }) => {
mat.uniforms.uTime.value += delta
mat.uniforms.uSpeedFactor.value = 1.0
})
</script>

View File

@ -4,7 +4,7 @@
* @Autor: 地虎降天龙
* @Date: 2024-03-27 10:38:54
* @LastEditors: 地虎降天龙
* @LastEditTime: 2024-04-15 11:34:26
* @LastEditTime: 2024-04-15 20:39:45
-->
<template>
<primitive :object="scene" ref="tresMesh" />
@ -20,7 +20,16 @@ import { defineExpose, ref, watch } from 'vue'
import { makeCustomShaderMaterial } from 'PLS/floor/common/reflectorCustomMaterial'
import { reflectorMipMap } from 'PLS/floor'
const { scene } = await useGLTF('./plugins/industry4/model/su7_startroom.raw.glb', { draco: true, decoderPath: './draco/' })
const props = withDefaults(
defineProps<{
hide?: boolean
}>(),
{
hide: false,
},
)
const { scene } = await useGLTF('./plugins/industry4/model/su7_car/su7_startroom.raw.glb', { draco: true, decoderPath: './draco/' })
const pTexture = await useTexture([
'./plugins/industry4/texture/t_startroom_light.raw.jpg',
@ -71,6 +80,19 @@ watch(
{ deep: true }
)
watch(
() => props.hide,
(newVal) => {
if (newVal) {
floorMat.envMapIntensity = 0.5
lightMat.opacity = 0
} else {
floorMat.envMapIntensity = 0
lightMat.opacity = 1
}
}
)
const tresMesh = ref<THREE.Mesh>()
defineExpose({
meshList: [light, floor],

View File

@ -4,7 +4,7 @@
* @Autor: 地虎降天龙
* @Date: 2023-11-29 08:34:17
* @LastEditors: 地虎降天龙
* @LastEditTime: 2023-11-29 09:36:28
* @LastEditTime: 2024-04-15 14:37:04
-->
<template>
<TresCanvas v-bind="state" window-size>
@ -24,8 +24,8 @@ import { SRGBColorSpace, BasicShadowMap, NoToneMapping } from 'three'
import { reactive } from 'vue'
import { OrbitControls } from '@tresjs/cientos'
import { Pane } from 'tweakpane'
import ByComposerTres from '../components/ByComposerTres.vue'
import { Pane } from 'tweakpane';
const state = reactive({
clearColor: '#000',

View File

@ -4,7 +4,7 @@
* @Autor: 地虎降天龙
* @Date: 2023-11-18 08:51:19
* @LastEditors: 地虎降天龙
* @LastEditTime: 2024-04-15 11:45:28
* @LastEditTime: 2024-04-15 21:00:53
-->
<template>
<loading />
@ -15,12 +15,24 @@
<TresDirectionalLight :position="[0, 2, -4]" :intensity="1" /> -->
<Suspense>
<startroom ref="startroomRef" />
<car :run="showSpeedup" />
</Suspense>
<Suspense>
<car />
<speedup :visible="showSpeedup" />
</Suspense>
<Suspense>
<startroom :hide="showSpeedup" />
</Suspense>
<Suspense>
<Environment :blur="0" :far="1000" :useDefaultScene="showSpeedup">
<Lightformer :intensity="0.66" :rotation-x="Math.PI / 2" :position="[0, 5, 0]" :scale="[10, 10, 1]" />
</Environment>
</Suspense>
<su7Effect :hide="showSpeedup" />
</TresCanvas>
</template>
@ -28,21 +40,33 @@
import { reactive, ref } from 'vue'
import { OrbitControls } from '@tresjs/cientos'
import { randomLoading as loading } from 'PLS/UIdemo'
import { Pane } from 'tweakpane'
import { Environment, Lightformer } from 'PLS/basic'
import startroom from '../components/su7/startroom.vue'
import car from '../components/su7/car.vue'
// import * as THREE from 'three'
import speedup from '../components/su7/speedup.vue'
import su7Effect from '../components/su7/effect.vue'
const state = reactive({
clearColor: '#000',
antialias: false,
// logarithmicDepthBuffer: true, //
// disableRender: true
disableRender: true
})
const controlsState = reactive({
// autoRotate: true,
autoRotate: true,
})
const startroomRef = ref(null)
const showSpeedup = ref(false)
const paneControl = new Pane({ title: '参数', })
const btn = paneControl.addButton({
title: '启动',
label: '流光模式',
})
// let count = 0
btn.on('click', () => {
showSpeedup.value = !showSpeedup.value
btn.title = showSpeedup.value ? '停止' : '启动'
})
</script>

View File

@ -0,0 +1,21 @@
// https://www.shadertoy.com/view/Msf3WH
vec2 hash(vec2 p)// replace this by something better
{
p = vec2(dot(p, vec2(127.1, 311.7)), dot(p, vec2(269.5, 183.3)));
return -1. + 2. * fract(sin(p) * 43758.5453123);
}
float noise(in vec2 p) {
const float K1 = .366025404;// (sqrt(3)-1)/2;
const float K2 = .211324865;// (3-sqrt(3))/6;
vec2 i = floor(p + (p.x + p.y) * K1);
vec2 a = p - i + (i.x + i.y) * K2;
float m = step(a.y, a.x);
vec2 o = vec2(m, 1. - m);
vec2 b = a - o + K2;
vec2 c = a - 1. + 2. * K2;
vec3 h = max(.5 - vec3(dot(a, a), dot(b, b), dot(c, c)), 0.);
vec3 n = h * h * h * h * vec3(dot(a, hash(i + 0.)), dot(b, hash(i + o)), dot(c, hash(i + 1.)));
return dot(n, vec3(70.));
}

View File

@ -0,0 +1,46 @@
#include "../../../../node_modules/lygia/generative/random.glsl
#include "../../../../node_modules/lygia/math/map.glsl
#include "./simplexNosie.glsl
#include "../../../../node_modules/lygia/generative/snoise.glsl"
varying vec2 vUv;
uniform float uTime;
uniform float uSpeedFactor;
vec3 getColor(vec2 uv) {
uv += vec2(9., 0.);
float r = random(uv + vec2(12., 2.));
float g = random(uv + vec2(7., 5.));
float b = random(uv);
vec3 col = vec3(r, g, b);
return col;
}
vec3 colorNoise(vec2 uv) {
vec2 newUV = floor(uv);
vec2 size = vec2(1.);
vec3 v1 = getColor((newUV + vec2(0.)) / size);
vec3 v2 = getColor((newUV + vec2(0., 1.)) / size);
vec3 v3 = getColor((newUV + vec2(1., 0.)) / size);
vec3 v4 = getColor((newUV + vec2(1.)) / size);
vec2 factor = smoothstep(0., 1., fract(uv));
vec3 v1Tov2 = mix(v1, v2, factor.y);
vec3 v3Tov4 = mix(v3, v4, factor.y);
vec3 mixColor = mix(v1Tov2, v3Tov4, factor.x);
return mixColor;
}
void main() {
vec2 newUV = vUv;
newUV.x += uTime * .5;
float alpha = snoise(newUV * vec2(3., 100.));
alpha = map(alpha, -1., 1., 0., 1.);
alpha = pow(clamp(alpha - .05, 0., 1.), 13.);
alpha = smoothstep(0., .04, alpha);
vec3 col = vec3(1.);
col = colorNoise(newUV * vec2(10., 100.));
col *= vec3(1.5, 1., 400.);
alpha *= smoothstep(.02, .5, vUv.x) * smoothstep(.02, .5, 1. - vUv.x);
alpha *= smoothstep(.01, .1, vUv.y) * smoothstep(.01, .1, 1. - vUv.y);
alpha *= smoothstep(0., 1., uSpeedFactor) * 5.;
csm_FragColor = vec4(col, alpha);
}

View File

@ -0,0 +1,5 @@
varying vec2 vUv;
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
vUv = uv;
}

View File

@ -4,7 +4,7 @@
* @Autor: 地虎降天龙
* @Date: 2024-04-07 14:29:57
* @LastEditors: 地虎降天龙
* @LastEditTime: 2024-04-11 14:03:08
* @LastEditTime: 2024-04-15 16:24:24
-->
<template>
<TresCanvas v-bind="tcConfig">
@ -23,7 +23,7 @@
</TresMesh>
<Suspense>
<Environment :blur="1" background :far="10000" preset="city" >
<Environment :blur="1" background :far="10000" preset="city">
<TresGroup v-if="true">
<Lightformer :intensity="0.75" :rotation-x="Math.PI / 2" :position="[0, 5, -9]" :scale="[10, 10, 1]" />
<Lightformer :intensity="4" :rotation-y="Math.PI / 2" :position="[-5, 1, -1]" :scale="[20, 0.1, 1]" />
@ -60,7 +60,8 @@ import { ref } from "vue"
import * as THREE from "three"
import { useRenderLoop } from '@tresjs/core'
import { LayerMaterial, Color, Depth } from 'PLS/basic/components/forCientos/LayerMaterial'
import { OrbitControls, Levioso,Environment, Lightformer } from '@tresjs/cientos'
import { OrbitControls, Levioso } from '@tresjs/cientos'
import { Environment, Lightformer } from 'PLS/basic'
const tcConfig = {
clearColor: "#201919",