1、后期效果 增加了 库,后期 调试各种后期

2、增加了 电影体积光 的演示实例
3、增加了 新 cientos 的 反射材质
4、增加了 cubeCamera 的组件
This commit is contained in:
hawk86104 2024-04-30 16:15:55 +08:00
parent 01f46c7ca1
commit 0f4144f098
21 changed files with 1159 additions and 13 deletions

View File

@ -61,6 +61,7 @@
"patch-package": "^8.0.0",
"pinia": "^2.1.7",
"postinstall-postinstall": "^2.1.0",
"postprocessing": "^6.35.4",
"three": "0.162.0",
"three-bvh-csg": "^0.0.16",
"three-mesh-bvh": "0.7.3",

View File

Before

Width:  |  Height:  |  Size: 311 KiB

After

Width:  |  Height:  |  Size: 311 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 KiB

Binary file not shown.

View File

@ -0,0 +1,61 @@
<!--
* @Description:
* @Version: 1.668
* @Autor: 地虎降天龙
* @Date: 2024-04-30 10:04:22
* @LastEditors: 地虎降天龙
* @LastEditTime: 2024-04-30 10:40:39
-->
<template>
<TresGroup>
<primitive :object="camera" />
<TresGroup ref="rgRef"> <slot /> </TresGroup>
</TresGroup>
</template>
<script setup lang="ts">
import * as THREE from 'three'
import { useRenderLoop } from '@tresjs/core'
import { useCubeCamera } from './useCubeCamera.ts'
import { ref, defineExpose } from 'vue'
const props = withDefaults(
defineProps<{
resolution?: number
near?: number
far?: number
envMap?: THREE.Texture
fog?: THREE.Fog | THREE.FogExp2
frames?: number
}>(),
{
resolution: 256,
near: 0.1,
far: 1000,
envMap: null,
fog: null,
frames: Infinity,
},
)
const { fbo, camera, update } = useCubeCamera({
resolution: props.resolution,
near: props.near,
far: props.far,
envMap: props.envMap,
fog: props.fog,
})
const { onBeforeLoop } = useRenderLoop()
let count = 0
const rgRef = ref(null)
onBeforeLoop(() => {
if (rgRef.value && (props.frames === Infinity || count < props.frames)) {
rgRef.value.visible = false
update()
rgRef.value.visible = true
count++
}
})
defineExpose({
texture: fbo.value?.texture,
})
</script>

View File

@ -0,0 +1,70 @@
/*
* @Description:
* @Version: 1.668
* @Autor:
* @Date: 2024-04-30 09:23:53
* @LastEditors:
* @LastEditTime: 2024-04-30 10:39:45
*/
import { useTresContext } from '@tresjs/core'
import * as THREE from 'three'
import { HalfFloatType, Fog, FogExp2, WebGLCubeRenderTarget } from 'three'
import type { Ref } from 'vue'
import { onBeforeUnmount, ref,watch } from 'vue'
export type CubeCameraOptions = {
/** Resolution of the FBO, 256 */
resolution?: number
/** Camera near, 0.1 */
near?: number
/** Camera far, 1000 */
far?: number
/** Custom environment map that is temporarily set as the scenes background */
envMap?: THREE.Texture
/** Custom fog that is temporarily set as the scenes fog */
fog?: Fog | FogExp2
}
export function useCubeCamera({ resolution = 256, near = 0.1, far = 1000, envMap, fog }: CubeCameraOptions = {}) {
const { renderer, scene } = useTresContext()
const fbo: Ref<WebGLCubeRenderTarget | null> = ref(null)
const resolutionR = ref(resolution)
const nearR = ref(near)
const farR = ref(far)
const camera: Ref<THREE.CubeCamera | null> = ref(null)
watch(()=>resolutionR, (r) => {
fbo.value?.dispose()
fbo.value = new WebGLCubeRenderTarget(r.value)
fbo.value.texture.type = HalfFloatType
}, { immediate: true })
watch([nearR, farR, fbo], ([n, fa, fb]) => {
if (fb) {
camera.value = new THREE.CubeCamera(n, fa, fb)
}
}, { immediate: true })
onBeforeUnmount(() => {
fbo.value?.dispose()
})
let originalFog
let originalBackground
const update = () => {
originalFog = scene.value.fog
originalBackground = scene.value.background
scene.value.background = envMap || originalBackground
scene.value.fog = fog || originalFog
camera.value?.update(renderer.value, scene.value)
scene.value.fog = originalFog
scene.value.background = originalBackground
}
return {
fbo,
camera,
update,
}
}

View File

@ -0,0 +1,101 @@
import type {
WebGLRenderer,
} from 'three'
import {
Mesh,
BufferGeometry,
BufferAttribute,
LinearFilter,
Scene,
WebGLRenderTarget,
Camera,
Vector2,
HalfFloatType,
} from 'three'
import { ConvolutionMaterial } from './convolutionMaterial'
export interface BlurPassProps {
resolution: number
width?: number
height?: number
minDepthThreshold?: number
maxDepthThreshold?: number
depthScale?: number
depthToBlurRatioBias?: number
}
export class BlurPass {
readonly renderTargetA: WebGLRenderTarget
readonly renderTargetB: WebGLRenderTarget
readonly convolutionMaterial: ConvolutionMaterial
readonly scene: Scene
readonly camera: Camera
readonly screen: Mesh
renderToScreen: boolean = false
constructor({
resolution,
width = 500,
height = 500,
minDepthThreshold = 0,
maxDepthThreshold = 1,
depthScale = 0,
depthToBlurRatioBias = 0.25,
}: BlurPassProps) {
this.renderTargetA = new WebGLRenderTarget(resolution, resolution, {
minFilter: LinearFilter,
magFilter: LinearFilter,
stencilBuffer: false,
depthBuffer: false,
type: HalfFloatType,
})
this.renderTargetB = this.renderTargetA.clone()
this.convolutionMaterial = new ConvolutionMaterial()
this.convolutionMaterial.setTexelSize(1.0 / width, 1.0 / height)
this.convolutionMaterial.setResolution(new Vector2(width, height))
this.scene = new Scene()
this.camera = new Camera()
this.convolutionMaterial.uniforms.minDepthThreshold.value = minDepthThreshold
this.convolutionMaterial.uniforms.maxDepthThreshold.value = maxDepthThreshold
this.convolutionMaterial.uniforms.depthScale.value = depthScale
this.convolutionMaterial.uniforms.depthToBlurRatioBias.value = depthToBlurRatioBias
this.convolutionMaterial.defines.USE_DEPTH = depthScale > 0
const vertices = new Float32Array([-1, -1, 0, 3, -1, 0, -1, 3, 0])
const uvs = new Float32Array([0, 0, 2, 0, 0, 2])
const geometry = new BufferGeometry()
geometry.setAttribute('position', new BufferAttribute(vertices, 3))
geometry.setAttribute('uv', new BufferAttribute(uvs, 2))
this.screen = new Mesh(geometry, this.convolutionMaterial)
this.screen.frustumCulled = false
this.scene.add(this.screen)
}
render(renderer, inputBuffer, outputBuffer) {
const scene = this.scene
const camera = this.camera
const renderTargetA = this.renderTargetA
const renderTargetB = this.renderTargetB
const material = this.convolutionMaterial
const uniforms = material.uniforms
uniforms.depthBuffer.value = inputBuffer.depthTexture
const kernel = material.kernel
let lastRT = inputBuffer
let destRT
let i, l
// Apply the multi-pass blur.
for (i = 0, l = kernel.length - 1; i < l; ++i) {
// Alternate between targets.
destRT = (i & 1) === 0 ? renderTargetA : renderTargetB
uniforms.kernel.value = kernel[i]
uniforms.inputBuffer.value = lastRT.texture
renderer.setRenderTarget(destRT)
renderer.render(scene, camera)
lastRT = destRT
}
uniforms.kernel.value = kernel[i]
uniforms.inputBuffer.value = lastRT.texture
renderer.setRenderTarget(this.renderToScreen ? null : outputBuffer)
renderer.render(scene, camera)
}
}

View File

@ -0,0 +1,101 @@
import { ShaderMaterial, Vector2, Uniform, NoBlending,REVISION } from 'three'
const getVersion = () => parseInt(REVISION.replace(/\D+/g, ''))
const version = getVersion()
export class ConvolutionMaterial extends ShaderMaterial {
readonly kernel: Float32Array
constructor(texelSize = new Vector2()) {
super({
uniforms: {
inputBuffer: new Uniform(null),
depthBuffer: new Uniform(null),
resolution: new Uniform(new Vector2()),
texelSize: new Uniform(new Vector2()),
halfTexelSize: new Uniform(new Vector2()),
kernel: new Uniform(0.0),
scale: new Uniform(1.0),
cameraNear: new Uniform(0.0),
cameraFar: new Uniform(1.0),
minDepthThreshold: new Uniform(0.0),
maxDepthThreshold: new Uniform(1.0),
depthScale: new Uniform(0.0),
depthToBlurRatioBias: new Uniform(0.25),
},
fragmentShader: `#include <common>
#include <dithering_pars_fragment>
uniform sampler2D inputBuffer;
uniform sampler2D depthBuffer;
uniform float cameraNear;
uniform float cameraFar;
uniform float minDepthThreshold;
uniform float maxDepthThreshold;
uniform float depthScale;
uniform float depthToBlurRatioBias;
varying vec2 vUv;
varying vec2 vUv0;
varying vec2 vUv1;
varying vec2 vUv2;
varying vec2 vUv3;
void main() {
float depthFactor = 0.0;
#ifdef USE_DEPTH
vec4 depth = texture2D(depthBuffer, vUv);
depthFactor = smoothstep(minDepthThreshold, maxDepthThreshold, 1.0-(depth.r * depth.a));
depthFactor *= depthScale;
depthFactor = max(0.0, min(1.0, depthFactor + 0.25));
#endif
vec4 sum = texture2D(inputBuffer, mix(vUv0, vUv, depthFactor));
sum += texture2D(inputBuffer, mix(vUv1, vUv, depthFactor));
sum += texture2D(inputBuffer, mix(vUv2, vUv, depthFactor));
sum += texture2D(inputBuffer, mix(vUv3, vUv, depthFactor));
gl_FragColor = sum * 0.25 ;
#include <dithering_fragment>
#include <tonemapping_fragment>
#include <${version >= 154 ? 'colorspace_fragment' : 'encodings_fragment'}>
}`,
vertexShader: `uniform vec2 texelSize;
uniform vec2 halfTexelSize;
uniform float kernel;
uniform float scale;
varying vec2 vUv;
varying vec2 vUv0;
varying vec2 vUv1;
varying vec2 vUv2;
varying vec2 vUv3;
void main() {
vec2 uv = position.xy * 0.5 + 0.5;
vUv = uv;
vec2 dUv = (texelSize * vec2(kernel) + halfTexelSize) * scale;
vUv0 = vec2(uv.x - dUv.x, uv.y + dUv.y);
vUv1 = vec2(uv.x + dUv.x, uv.y + dUv.y);
vUv2 = vec2(uv.x + dUv.x, uv.y - dUv.y);
vUv3 = vec2(uv.x - dUv.x, uv.y - dUv.y);
gl_Position = vec4(position.xy, 1.0, 1.0);
}`,
blending: NoBlending,
depthWrite: false,
depthTest: false,
})
this.toneMapped = false
this.setTexelSize(texelSize.x, texelSize.y)
this.kernel = new Float32Array([0.0, 1.0, 2.0, 2.0, 3.0])
}
setTexelSize(x: number, y: number) {
this.uniforms.texelSize.value.set(x, y)
this.uniforms.halfTexelSize.value.set(x, y).multiplyScalar(0.5)
}
setResolution(resolution: Vector2) {
this.uniforms.resolution.value.copy(resolution)
}
}

View File

@ -0,0 +1,318 @@
<script setup lang="ts">
import { shallowRef, onBeforeUnmount, watchEffect, toRefs, shallowReactive, computed, useAttrs } from 'vue'
import { useRenderLoop, useTresContext } from '@tresjs/core'
import type { TresObject } from '@tresjs/core'
import type {
Texture,
MeshStandardMaterial,
TextureDataType,
Mapping,
} from 'three'
import {
Plane,
Vector3,
Vector4,
Matrix4,
PerspectiveCamera,
LinearFilter,
WebGLRenderTarget,
DepthTexture,
DepthFormat,
UnsignedShortType,
HalfFloatType,
} from 'three'
import { BlurPass } from '../blurPass'
import { MeshReflectorMaterial } from './material'
const props = withDefaults(
defineProps<MeshReflectorMaterialProps>(),
{
mixBlur: 0,
mixStrength: 1,
resolution: 256,
blur: () => [0, 0],
minDepthThreshold: 0.9,
maxDepthThreshold: 1,
depthScale: 0,
depthToBlurRatioBias: 0.25,
mirror: 0,
distortion: 1,
mixContrast: 1,
reflectorOffset: 0,
},
)
export interface MeshReflectorMaterialProps extends /* @vue-ignore */ MeshStandardMaterial {
resolution?: number
mixBlur?: number
mixStrength?: number
blur?: [number, number] | number
mirror?: number
minDepthThreshold?: number
maxDepthThreshold?: number
depthScale?: number
depthToBlurRatioBias?: number
distortionMap?: Texture
distortion?: number
mixContrast?: number
reflectorOffset?: number
}
/**
* Finds the parent mesh using the specified material UUID.
*
* @param {THREE.Scene} scene - The Three.js scene to search.
* @param {string} materialUuid - The UUID of the material.
* @returns {THREE.Mesh | undefined} - The mesh using the material, or undefined if not found.
*/
function findMeshByMaterialUuid(scene: TresObject, materialUuid: string): TresObject {
let foundMesh
scene.traverse((object: TresObject) => {
if (object.isMesh && object.material && object.material.uuid === materialUuid) {
foundMesh = object
}
})
return foundMesh as unknown as TresObject
}
function beforeRender(parent: TresObject) {
state.reflectorWorldPosition.setFromMatrixPosition(parent.matrixWorld)
state.cameraWorldPosition.setFromMatrixPosition(camera.value?.matrixWorld as Matrix4)
state.rotationMatrix.extractRotation(parent.matrixWorld)
state.normal.set(0, 0, 1)
state.normal.applyMatrix4(state.rotationMatrix)
state.reflectorWorldPosition.addScaledVector(state.normal, props.reflectorOffset)
state.view.subVectors(state.reflectorWorldPosition, state.cameraWorldPosition)
// Avoid rendering when reflector is facing away
if (state.view.dot(state.normal) > 0) return
state.view.reflect(state.normal).negate()
state.view.add(state.reflectorWorldPosition)
state.rotationMatrix.extractRotation(camera.value?.matrixWorld as Matrix4)
state.lookAtPosition.set(0, 0, -1)
state.lookAtPosition.applyMatrix4(state.rotationMatrix)
state.lookAtPosition.add(state.cameraWorldPosition)
state.target.subVectors(state.reflectorWorldPosition, state.lookAtPosition)
state.target.reflect(state.normal).negate()
state.target.add(state.reflectorWorldPosition)
state.virtualCamera.position.copy(state.view)
state.virtualCamera.up.set(0, 1, 0)
state.virtualCamera.up.applyMatrix4(state.rotationMatrix)
state.virtualCamera.up.reflect(state.normal)
state.virtualCamera.lookAt(state.target)
state.virtualCamera.far = (camera?.value as PerspectiveCamera).far
state.virtualCamera.updateMatrixWorld()
state.virtualCamera.projectionMatrix.copy((camera?.value as PerspectiveCamera).projectionMatrix)
// Update the texture matrix
state.textureMatrix.set(0.5, 0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.5, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 1.0)
state.textureMatrix.multiply(state.virtualCamera.projectionMatrix)
state.textureMatrix.multiply(state.virtualCamera.matrixWorldInverse)
state.textureMatrix.multiply(parent.matrixWorld)
// Now update projection matrix with new clip reflectorPlane, implementing code from: http://www.terathon.com/code/oblique.html
// Paper explaining this technique: http://www.terathon.com/lengyel/Lengyel-Oblique.pdf
state.reflectorPlane.setFromNormalAndCoplanarPoint(state.normal, state.reflectorWorldPosition)
state.reflectorPlane.applyMatrix4(state.virtualCamera.matrixWorldInverse)
state.clipPlane.set(
state.reflectorPlane.normal.x,
state.reflectorPlane.normal.y,
state.reflectorPlane.normal.z,
state.reflectorPlane.constant,
)
const projectionMatrix = state.virtualCamera.projectionMatrix
state.q.x = (Math.sign(state.clipPlane.x) + projectionMatrix.elements[8]) / projectionMatrix.elements[0]
state.q.y = (Math.sign(state.clipPlane.y) + projectionMatrix.elements[9]) / projectionMatrix.elements[5]
state.q.z = -1.0
state.q.w = (1.0 + projectionMatrix.elements[10]) / projectionMatrix.elements[14]
// Calculate the scaled reflectorPlane vector
state.clipPlane.multiplyScalar(2.0 / state.clipPlane.dot(state.q))
// Replacing the third row of the projection matrix
projectionMatrix.elements[2] = state.clipPlane.x
projectionMatrix.elements[6] = state.clipPlane.y
projectionMatrix.elements[10] = state.clipPlane.z + 1.0
projectionMatrix.elements[14] = state.clipPlane.w
}
const {
resolution,
minDepthThreshold,
maxDepthThreshold,
depthScale,
depthToBlurRatioBias,
blur,
mirror,
mixBlur,
mixStrength,
distortion,
distortionMap,
mixContrast,
} = toRefs(props)
const { camera, scene, renderer, extend } = useTresContext()
extend({ MeshReflectorMaterial })
const fbo = shallowRef<WebGLRenderTarget>()
const outputFbo = shallowRef<WebGLRenderTarget>()
const blurpass = shallowRef<BlurPass>()
const reflectorParams = shallowRef()
const computedBlur = computed(() => {
if (typeof blur.value === 'number') {
return [blur.value, blur.value]
}
return blur.value
})
const hasBlur = computed(() => computedBlur.value[0] > 0 || computedBlur.value[1] > 0)
const state = {
reflectorPlane: new Plane(),
normal: new Vector3(),
reflectorWorldPosition: new Vector3(),
cameraWorldPosition: new Vector3(),
rotationMatrix: new Matrix4(),
lookAtPosition: new Vector3(0, 0, -1),
clipPlane: new Vector4(),
view: new Vector3(),
target: new Vector3(),
q: new Vector4(),
virtualCamera: new PerspectiveCamera(),
textureMatrix: new Matrix4(),
}
watchEffect(() => {
fbo.value?.texture.dispose()
const parameters = {
minFilter: LinearFilter,
magFilter: LinearFilter,
type: HalfFloatType,
}
fbo.value = new WebGLRenderTarget(
resolution.value, resolution.value,
{
...parameters,
depthBuffer: true,
depthTexture: new DepthTexture(
resolution.value, resolution.value,
DepthFormat as TextureDataType,
UnsignedShortType as Mapping,
),
},
)
outputFbo.value = new WebGLRenderTarget(
resolution.value, resolution.value,
parameters,
)
blurpass.value = new BlurPass({
resolution: resolution.value,
width: computedBlur.value[0],
height: computedBlur.value[1],
minDepthThreshold: minDepthThreshold.value,
maxDepthThreshold: maxDepthThreshold.value,
depthScale: depthScale.value,
depthToBlurRatioBias: depthToBlurRatioBias.value,
})
reflectorParams.value = {
mirror,
textureMatrix: state.textureMatrix,
mixBlur,
tDiffuse: fbo.value.texture,
tDepth: fbo.value.depthTexture,
tDiffuseBlur: fbo.value.texture,
hasBlur,
mixStrength,
minDepthThreshold,
maxDepthThreshold,
depthScale,
depthToBlurRatioBias,
distortion,
distortionMap: distortionMap.value,
mixContrast,
'defines-USE_BLUR': hasBlur.value ? '' : undefined,
'defines-USE_DEPTH': depthScale.value > 0 ? '' : undefined,
'defines-USE_DISTORTION': distortionMap.value ? '' : undefined,
}
})
const materialRef = shallowRef()
const { onLoop } = useRenderLoop()
onLoop(() => {
if (!materialRef.value || !renderer.value || !fbo.value || !camera.value) return
const parent: TresObject = findMeshByMaterialUuid(scene.value as unknown as TresObject, materialRef.value.uuid)
if (!parent) return
parent.visible = false // Avoid re-rendering the reflected object
const currentXrEnabled = renderer.value.xr.enabled
const currentShadowAutoUpdate = renderer.value.shadowMap.autoUpdate
beforeRender(parent)
renderer.value.shadowMap.autoUpdate = false
renderer.value.setRenderTarget(fbo.value)
if (!renderer.value.autoClear) renderer.value.clear()
renderer.value.render(scene.value, state.virtualCamera)
blurpass?.value?.render(renderer.value, fbo.value, outputFbo.value)
// Restore the previous render target and material
renderer.value.xr.enabled = currentXrEnabled
renderer.value.shadowMap.autoUpdate = currentShadowAutoUpdate
parent.visible = true
renderer.value.setRenderTarget(null)
})
const attrs = useAttrs()
const merged = computed(() => {
const m = { }
Object.assign(m, props)
Object.assign(m, attrs.value)
return m
})
onBeforeUnmount(() => {
fbo?.value?.dispose()
outputFbo?.value?.dispose()
})
</script>
<template>
<TresMeshReflectorMaterial
:key="
`key${
reflectorParams['defines-USE_BLUR']
}${reflectorParams['defines-USE_DEPTH']
}${reflectorParams['defines-USE_DISTORTION']}`
"
ref="materialRef"
v-bind="merged"
:texture-matrix="state.textureMatrix"
:mirror="mirror"
:t-diffuse="fbo?.texture"
:t-depth="fbo?.depthTexture"
:t-diffuse-blur="outputFbo?.texture"
:has-blur="hasBlur"
:mix-strength="mixStrength"
:min-depth-threshold="minDepthThreshold"
:max-depth-threshold="maxDepthThreshold"
:depth-scale="depthScale"
:depth-to-blur-ratio-bias="depthToBlurRatioBias"
:distortion="distortion"
:distortionMap="distortionMap"
:mix-contrast="mixContrast"
:defines-USE_BLUR="hasBlur ? '' : undefined"
:defines-USE_DEPTH="depthScale > 0 ? '' : undefined"
:defines-USE_DISTORTION="distortionMap ? '' : undefined"
/>
</template>

View File

@ -0,0 +1,265 @@
import type { Matrix4, Texture } from 'three'
import { MeshStandardMaterial } from 'three'
// Borrowed from @pmdrs drei implementation https://github.com/pmndrs/drei/blob/master/src/materials/MeshReflectorMaterial.tsx
interface UninitializedUniform<Value> { value: Value | null }
export class MeshReflectorMaterial extends MeshStandardMaterial {
private _tDepth: UninitializedUniform<Texture> = { value: null }
private _distortionMap: UninitializedUniform<Texture> = { value: null }
private _tDiffuse: UninitializedUniform<Texture> = { value: null }
private _tDiffuseBlur: UninitializedUniform<Texture> = { value: null }
private _textureMatrix: UninitializedUniform<Matrix4> = { value: null }
private _hasBlur: { value: boolean } = { value: false }
private _mirror: { value: number } = { value: 0.0 }
private _mixBlur: { value: number } = { value: 0.0 }
private _blurStrength: { value: number } = { value: 0.5 }
private _minDepthThreshold: { value: number } = { value: 0.9 }
private _maxDepthThreshold: { value: number } = { value: 1 }
private _depthScale: { value: number } = { value: 0 }
private _depthToBlurRatioBias: { value: number } = { value: 0.25 }
private _distortion: { value: number } = { value: 1 }
private _mixContrast: { value: number } = { value: 1.0 }
constructor(parameters = {}) {
super(parameters)
this.setValues(parameters)
}
onBeforeCompile(shader) {
if (!shader.defines?.USE_UV) {
shader.defines.USE_UV = ''
}
shader.uniforms.hasBlur = this._hasBlur
shader.uniforms.tDiffuse = this._tDiffuse
shader.uniforms.tDepth = this._tDepth
shader.uniforms.distortionMap = this._distortionMap
shader.uniforms.tDiffuseBlur = this._tDiffuseBlur
shader.uniforms.textureMatrix = this._textureMatrix
shader.uniforms.mirror = this._mirror
shader.uniforms.mixBlur = this._mixBlur
shader.uniforms.mixStrength = this._blurStrength
shader.uniforms.minDepthThreshold = this._minDepthThreshold
shader.uniforms.maxDepthThreshold = this._maxDepthThreshold
shader.uniforms.depthScale = this._depthScale
shader.uniforms.depthToBlurRatioBias = this._depthToBlurRatioBias
shader.uniforms.distortion = this._distortion
shader.uniforms.mixContrast = this._mixContrast
shader.vertexShader = `
uniform mat4 textureMatrix;
varying vec4 my_vUv;
${shader.vertexShader}`
shader.vertexShader = shader.vertexShader.replace(
'#include <project_vertex>',
`#include <project_vertex>
my_vUv = textureMatrix * vec4( position, 1.0 );
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );`,
)
shader.fragmentShader = `
uniform sampler2D tDiffuse;
uniform sampler2D tDiffuseBlur;
uniform sampler2D tDepth;
uniform sampler2D distortionMap;
uniform float distortion;
uniform float cameraNear;
uniform float cameraFar;
uniform bool hasBlur;
uniform float mixBlur;
uniform float mirror;
uniform float mixStrength;
uniform float minDepthThreshold;
uniform float maxDepthThreshold;
uniform float mixContrast;
uniform float depthScale;
uniform float depthToBlurRatioBias;
varying vec4 my_vUv;
${shader.fragmentShader}`
shader.fragmentShader = shader.fragmentShader.replace(
'#include <emissivemap_fragment>',
`#include <emissivemap_fragment>
float distortionFactor = 0.0;
#ifdef USE_DISTORTION
distortionFactor = texture2D(distortionMap, vUv).r * distortion;
#endif
vec4 new_vUv = my_vUv;
new_vUv.x += distortionFactor;
new_vUv.y += distortionFactor;
vec4 base = texture2DProj(tDiffuse, new_vUv);
vec4 blur = texture2DProj(tDiffuseBlur, new_vUv);
vec4 merge = base;
#ifdef USE_NORMALMAP
vec2 normal_uv = vec2(0.0);
vec4 normalColor = texture2D(normalMap, vUv * normalScale);
vec3 my_normal = normalize( vec3( normalColor.r * 2.0 - 1.0, normalColor.b, normalColor.g * 2.0 - 1.0 ) );
vec3 coord = new_vUv.xyz / new_vUv.w;
normal_uv = coord.xy + coord.z * my_normal.xz * 0.05;
vec4 base_normal = texture2D(tDiffuse, normal_uv);
vec4 blur_normal = texture2D(tDiffuseBlur, normal_uv);
merge = base_normal;
blur = blur_normal;
#endif
float depthFactor = 0.0001;
float blurFactor = 0.0;
#ifdef USE_DEPTH
vec4 depth = texture2DProj(tDepth, new_vUv);
depthFactor = smoothstep(minDepthThreshold, maxDepthThreshold, 1.0-(depth.r * depth.a));
depthFactor *= depthScale;
depthFactor = max(0.0001, min(1.0, depthFactor));
#ifdef USE_BLUR
blur = blur * min(1.0, depthFactor + depthToBlurRatioBias);
merge = merge * min(1.0, depthFactor + 0.5);
#else
merge = merge * depthFactor;
#endif
#endif
float reflectorRoughnessFactor = roughness;
#ifdef USE_ROUGHNESSMAP
vec4 reflectorTexelRoughness = texture2D( roughnessMap, vUv );
reflectorRoughnessFactor *= reflectorTexelRoughness.g;
#endif
#ifdef USE_BLUR
blurFactor = min(1.0, mixBlur * reflectorRoughnessFactor);
merge = mix(merge, blur, blurFactor);
#endif
vec4 newMerge = vec4(0.0, 0.0, 0.0, 1.0);
newMerge.r = (merge.r - 0.5) * mixContrast + 0.5;
newMerge.g = (merge.g - 0.5) * mixContrast + 0.5;
newMerge.b = (merge.b - 0.5) * mixContrast + 0.5;
diffuseColor.rgb = diffuseColor.rgb * ((1.0 - min(1.0, mirror)) + newMerge.rgb * mixStrength);
`,
)
}
get tDiffuse(): Texture | null {
return this._tDiffuse.value
}
set tDiffuse(v: Texture | null) {
this._tDiffuse.value = v
}
get tDepth(): Texture | null {
return this._tDepth.value
}
set tDepth(v: Texture | null) {
this._tDepth.value = v
}
get distortionMap(): Texture | null {
return this._distortionMap.value
}
set distortionMap(v: Texture | null) {
this._distortionMap.value = v
}
get tDiffuseBlur(): Texture | null {
return this._tDiffuseBlur.value
}
set tDiffuseBlur(v: Texture | null) {
this._tDiffuseBlur.value = v
}
get textureMatrix(): Matrix4 | null {
return this._textureMatrix.value
}
set textureMatrix(v: Matrix4 | null) {
this._textureMatrix.value = v
}
get hasBlur(): boolean {
return this._hasBlur.value
}
set hasBlur(v: boolean) {
this._hasBlur.value = v
}
get mirror(): number {
return this._mirror.value
}
set mirror(v: number) {
this._mirror.value = v
}
get mixBlur(): number {
return this._mixBlur.value
}
set mixBlur(v: number) {
this._mixBlur.value = v
}
get mixStrength(): number {
return this._blurStrength.value
}
set mixStrength(v: number) {
this._blurStrength.value = v
}
get minDepthThreshold(): number {
return this._minDepthThreshold.value
}
set minDepthThreshold(v: number) {
this._minDepthThreshold.value = v
}
get maxDepthThreshold(): number {
return this._maxDepthThreshold.value
}
set maxDepthThreshold(v: number) {
this._maxDepthThreshold.value = v
}
get depthScale(): number {
return this._depthScale.value
}
set depthScale(v: number) {
this._depthScale.value = v
}
get depthToBlurRatioBias(): number {
return this._depthToBlurRatioBias.value
}
set depthToBlurRatioBias(v: number) {
this._depthToBlurRatioBias.value = v
}
get distortion(): number {
return this._distortion.value
}
set distortion(v: number) {
this._distortion.value = v
}
get mixContrast(): number {
return this._mixContrast.value
}
set mixContrast(v: number) {
this._mixContrast.value = v
}
}

View File

@ -4,7 +4,7 @@
* @Autor:
* @Date: 2024-04-15 11:08:17
* @LastEditors:
* @LastEditTime: 2024-04-25 16:49:52
* @LastEditTime: 2024-04-30 09:26:36
*/
import { useRenderLoop, useTresContext } from '@tresjs/core'
import type { Camera, WebGLRenderTargetOptions } from 'three'

View File

@ -4,7 +4,7 @@
* @Autor: 地虎降天龙
* @Date: 2024-04-09 11:27:03
* @LastEditors: 地虎降天龙
* @LastEditTime: 2024-04-29 16:51:19
* @LastEditTime: 2024-04-30 10:29:07
*/
import Environment from './components/forCientos/useEnvironment/component.vue'
@ -14,5 +14,7 @@ import TransmissionMaterial from './components/forCientos/TransmissionMaterial/i
import Center from './components/forCientos/Center/index.vue'
import Caustics from './components/forCientos/Caustics/index.vue'
import Pcss from './components/forCientos/Pcss/index.vue'
import meshReflectionMaterial from './components/forCientos/meshReflectionMaterial/index.vue'
import CubeCamera from './components/forCientos/CubeCamera/index.vue'
export { Environment, Lightformer, useFBO, TransmissionMaterial, Center, Caustics, Pcss }
export { Environment, Lightformer, useFBO, TransmissionMaterial, Center, Caustics, Pcss, meshReflectionMaterial, CubeCamera }

View File

@ -4,7 +4,7 @@
* @Autor: 地虎降天龙
* @Date: 2024-01-16 08:58:24
* @LastEditors: 地虎降天龙
* @LastEditTime: 2024-04-29 15:38:23
* @LastEditTime: 2024-04-30 16:10:39
*/
export default {
@ -50,14 +50,7 @@ export default {
type: 'img',
name: 'arrangement',
title: '桌面陈设',
referenceSource: { title: 'react-three-fiber', url: 'https://codesandbox.io/p/sandbox/caustics-szj6p7' },
},
{
src: 'plugins/eCommerce/preview/roomup.png',
type: 'img',
name: 'roomup',
title: '日式会厅',
referenceSource: { title: 'react-three-fiber', url: 'https://codesandbox.io/p/sandbox/room-with-soft-shadows-ykfpw' },
referenceSource: { title: 'react-three-fiber', url: 'https://codesandbox.io/s/szj6p7' },
},
],
}

View File

@ -1,7 +1,15 @@
<!--
* @Description:
* @Version: 1.668
* @Autor: 地虎降天龙
* @Date: 2024-04-29 17:32:18
* @LastEditors: 地虎降天龙
* @LastEditTime: 2024-04-30 16:11:56
-->
<script setup lang="ts">
import { useGLTF } from '@tresjs/cientos'
const { nodes, materials } = await useGLTF('./plugins/eCommerce/model/room-transformed.glb', { draco: true, decoderPath: './draco/' })
const { nodes, materials } = await useGLTF('./plugins/visualArts/model/room-transformed.glb', { draco: true, decoderPath: './draco/' })
</script>
<template>

View File

@ -0,0 +1,86 @@
<!--
* @Description:
* @Version: 1.668
* @Autor: 地虎降天龙
* @Date: 2024-04-30 10:59:33
* @LastEditors: 地虎降天龙
* @LastEditTime: 2024-04-30 16:05:53
-->
<template></template>
<script setup lang="ts">
import { watchEffect, toRaw } from 'vue'
import * as THREE from 'three'
import { useTresContext, useRenderLoop } from '@tresjs/core'
import { EffectComposer, EffectPass, RenderPass, BloomEffect, GodRaysEffect } from 'postprocessing'
const props = withDefaults(
defineProps<{
screen: THREE.Mesh
}>(),
{},
)
const { camera, renderer, scene, sizes } = useTresContext()
let effectComposer = null as any
let effectPass = null as any
const effects = [] as any[]
const init = (scene: THREE.Scene, camera: THREE.PerspectiveCamera, renderer: THREE.WebGLRenderer, width: number, height: number) => {
effectComposer = new EffectComposer(renderer, {
frameBufferType: THREE.HalfFloatType,
multisampling: 8,
})
const renderPass = new RenderPass(scene, camera)
effectComposer.addPass(renderPass)
}
const addBloomEffect = () => {
effects.push(
new BloomEffect({
luminanceThreshold: 0,
mipmapBlur: true,
luminanceSmoothing: 0.0,
intensity: 1,
}),
)
}
const addGodRaysEffect = (camera: THREE.PerspectiveCamera) => {
const sunMaterial = new THREE.MeshBasicMaterial({
color: 0xffddaa,
transparent: true,
fog: false,
})
const sunGeometry = new THREE.SphereGeometry(0.75, 32, 32)
const sun = new THREE.Mesh(sunGeometry, sunMaterial)
sun.frustumCulled = false
sun.matrixAutoUpdate = false
const godRaysEffect = new GodRaysEffect(camera, toRaw(props.screen), {
blur: true,
decay: 0.8,
exposure: 0.34,
})
effects.push(godRaysEffect)
}
const makeEffectPass = (camera: THREE.PerspectiveCamera) => {
effectPass = new EffectPass(camera, ...effects)
effectComposer.addPass(effectPass)
}
watchEffect(() => {
if (sizes.width.value) {
const camerav = camera.value as any
init(scene.value, camerav, renderer.value, sizes.width.value, sizes.height.value)
addGodRaysEffect(camerav)
addBloomEffect()
makeEffectPass(camerav)
}
})
const { onAfterLoop } = useRenderLoop()
onAfterLoop(() => {
if (effectComposer) {
effectComposer.render()
}
})
</script>

View File

@ -0,0 +1,34 @@
<template>
<TresMesh ref="tmSceen" :position="[0, 0, -16]">
<TresPlaneGeometry :args="[16, 10]" />
<TresMeshBasicMaterial :map="texture" />
<TresMesh :scale="[16.05, 10.05, 1]" :position="[0, 0, -0.01]">
<TresPlaneGeometry />
<TresMeshBasicMaterial color="black" />
</TresMesh>
</TresMesh>
<CubeCamera ref="cubeCameraRef" :position="[-3, -1, -5]" :resolution="256">
<TresMesh>
<TresSphereGeometry :args="[2, 32, 32]" />
<TresMeshStandardMaterial :metalness="1" :roughness="0.1" :envMap="envMap" />
</TresMesh>
</CubeCamera>
</template>
<script lang="ts" setup>
import { ref, watch } from 'vue'
import * as THREE from 'three'
import { useVideoTexture } from '@tresjs/cientos'
import { CubeCamera } from 'PLS/basic'
const texture = ref()
texture.value = await useVideoTexture('./plugins/visualArts/video/vlg.mp4', { loop: true })
texture.value.colorSpace = THREE.SRGBColorSpace
const cubeCameraRef = ref()
const envMap = ref()
watch(cubeCameraRef, (value) => {
envMap.value = value.texture
})
const tmSceen = ref()
</script>

View File

@ -0,0 +1,36 @@
/*
* @Description:
* @Version: 1.668
* @Autor: 地虎降天龙
* @Date: 2024-04-30 08:18:21
* @LastEditors: 地虎降天龙
* @LastEditTime: 2024-04-30 16:12:30
*/
export default {
name: 'visualArts',
title: '视觉艺术',
intro: '这里展示一些视觉艺术的效果',
version: '0.0.1',
author: '地虎降天龙',
website: 'https://gitee.com/hawk86104',
state: 'active',
creatTime: '2024-04-30',
updateTime: '2024-04-30',
require: [],
preview: [
{
src: 'plugins/visualArts/preview/volumetricLightGodray.png',
type: 'img',
name: 'volumetricLightGodray',
title: '电影体积光',
referenceSource: { title: 'react-three-fiber', url: 'https://codesandbox.io/s/yggpw5' },
},
{
src: 'plugins/visualArts/preview/roomup.png',
type: 'img',
name: 'roomup',
title: '日式会厅',
referenceSource: { title: 'react-three-fiber', url: 'https://codesandbox.io/s/ykfpwf' },
},
],
}

View File

@ -0,0 +1,70 @@
<!--
* @Description:
* @Version: 1.668
* @Autor: 地虎降天龙
* @Date: 2024-04-30 08:18:21
* @LastEditors: 地虎降天龙
* @LastEditTime: 2024-04-30 16:07:08
-->
<template>
<TresCanvas v-bind="state" window-size>
<TresPerspectiveCamera :position="[0, 0, 30]" :fov="45" :near="0.1" :far="1000" />
<OrbitControls v-bind="controlsState" />
<TresAmbientLight :intensity="0.5" />
<Suspense>
<screen ref="screenRef" />
</Suspense>
<TresMesh :position="[0, -5.02, 0]" receiveShadow :rotation="[-Math.PI / 2, 0, 0]">
<TresPlaneGeometry :args="[50, 50]" />
<meshReflectionMaterial
:blur="[300, 50]"
:resolution="1024"
:mixBlur="1"
:mixStrength="100"
:roughness="1"
:depthScale="1.2"
:minDepthThreshold="0.4"
:maxDepthThreshold="1.4"
color="#202020"
:metalness="0.8"
/>
</TresMesh>
<effectComposer v-if="tmSceen" :screen="tmSceen" />
</TresCanvas>
</template>
<script setup lang="ts">
import { reactive, ref, watch, nextTick, onMounted } from 'vue'
import { TresCanvas } from '@tresjs/core'
import { OrbitControls } from '@tresjs/cientos'
import { meshReflectionMaterial } from 'PLS/basic'
import screen from '../components/volumetricLightGodray/screen.vue'
import effectComposer from '../components/volumetricLightGodray/effectComposer.vue'
const state = reactive({
clearColor: '#050505',
antialias: false,
disableRender: true,
})
const controlsState = reactive({
enableDamping: true,
})
const screenRef = ref(null)
const tmSceen = ref(null)
watch(
() => screenRef,
(newValue: any) => {
nextTick(() => {
if (newValue && newValue.value.$refs.tmSceen !== undefined) {
tmSceen.value = newValue.value.$refs.tmSceen
}
})
},
{ deep: true },
)
</script>