增加了 基于geometric缩放加材质的 外发光案例

This commit is contained in:
hawk86104 2024-12-13 21:13:46 +08:00
parent 072bc40009
commit a44f4e7737
7 changed files with 224 additions and 1 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

View File

@ -0,0 +1,46 @@
/*
* @Description:
* @Version: 1.668
* @Autor: 地虎降天龙
* @Date: 2024-12-13 14:35:16
* @LastEditors: 地虎降天龙
* @LastEditTime: 2024-12-13 14:35:19
*/
/**
* Dilate or erode a geometry inplace
* @param {THREE.BufferGeometry} geometry - Geometry to dilate
* @param {Number} length - Scale factor (positive to dilate, negative to erode)
*/
function dilateBufferGeometry(geometry, length) {
if (!geometry.isBufferGeometry) {
console.error('The geometry must be a BufferGeometry.')
return
}
// Ensure the geometry has normals
if (!geometry.attributes.normal) {
geometry.computeVertexNormals()
}
// Get positions and normals
const position = geometry.attributes.position
const normal = geometry.attributes.normal
const posArray = position.array
const normalArray = normal.array
// Iterate over each vertex
for (let i = 0; i < position.count; i++) {
const i3 = i * 3
// Modify the position by the normal scaled by length
posArray[i3] += normalArray[i3] * length // x
posArray[i3 + 1] += normalArray[i3 + 1] * length // y
posArray[i3 + 2] += normalArray[i3 + 2] * length // z
}
// Notify Three.js that the position has been updated
position.needsUpdate = true
}
export { dilateBufferGeometry }

View File

@ -0,0 +1,85 @@
<template>
<TresGroup>
<TresMesh :geometry="erodedGeometry">
<TresShaderMaterial v-bind="inMaterialConfig" :blending="THREE.AdditiveBlending" transparent :depthWrite="false" :side="THREE.FontSide" />
</TresMesh>
<TresMesh :geometry="dilatedGeometry" :visible="true">
<TresShaderMaterial v-bind="outMaterialConfig" :blending="THREE.AdditiveBlending" transparent :depthWrite="false" :side="THREE.BackSide" />
</TresMesh>
</TresGroup>
</template>
<script setup lang="ts">
import { watch } from 'vue'
import * as THREE from 'three'
import { dilateBufferGeometry } from '../common/utils'
import vertexShader from '../shader/geometricGlow.vert'
import fragmentShader from '../shader/geometricGlow.frag'
const props = defineProps({
geometry: Object,
inColor: {
default: 'hotpink',
},
outColor: {
default: 'hotpink',
},
inPower: {
default: 1.4,
},
outPower: {
default: 1.2,
},
inCoeficient: {
default: 1.1,
},
outCoeficient: {
default: 0.1,
},
})
const erodedGeometry = props.geometry.clone()
dilateBufferGeometry(erodedGeometry, 0.01)
const dilatedGeometry = props.geometry.clone()
dilateBufferGeometry(dilatedGeometry, 0.2)
const inMaterialConfig = {
uniforms: {
coeficient: { value: props.inCoeficient },
power: { value: props.inPower },
glowColor: { value: new THREE.Color(props.inColor) },
viewVector: { value: new THREE.Vector3(0, 0, 1) },
},
vertexShader,
fragmentShader,
}
const outMaterialConfig = {
uniforms: {
coeficient: { value: props.outCoeficient },
power: { value: props.outPower },
glowColor: { value: new THREE.Color(props.outColor) },
viewVector: { value: new THREE.Vector3(0, 0, 1) },
},
vertexShader,
fragmentShader,
}
watch(
() => [props.inColor, props.outColor],
([inColor, outColor]) => {
inMaterialConfig.uniforms.glowColor.value.set(inColor)
outMaterialConfig.uniforms.glowColor.value.set(outColor)
},
)
watch(
() => [props.inPower, props.outPower, props.inCoeficient, props.outCoeficient],
([inPower, outPower, inCoeficient, outCoeficient]) => {
inMaterialConfig.uniforms.power.value = inPower
outMaterialConfig.uniforms.power.value = outPower
inMaterialConfig.uniforms.coeficient.value = inCoeficient
outMaterialConfig.uniforms.coeficient.value = outCoeficient
},
)
</script>

View File

@ -4,7 +4,7 @@
* @Autor: 地虎降天龙
* @Date: 2023-11-03 15:07:09
* @LastEditors: 地虎降天龙
* @LastEditTime: 2024-12-12 17:55:02
* @LastEditTime: 2024-12-13 14:38:17
*/
export default {
name: 'basic',
@ -97,6 +97,10 @@ export default {
preview: [
{ src: 'plugins/basic/shine/preview/spriteImage.png', type: 'img', name: 'spriteImage', title: '点精灵贴图' },
{ src: 'plugins/basic/shine/preview/shader.png', type: 'img', name: 'shader', title: '着色器方式' },
{
src: 'plugins/basic/shine/preview/geometricGlow.png', type: 'img', name: 'geometricGlow', title: 'geometric缩放',
referenceSource: { title: 'jeromeetienne', url: 'https://github.com/jeromeetienne/threex.geometricglow' },
},
{
src: 'plugins/basic/shine/preview/fakeGlow.png',
type: 'img',

View File

@ -0,0 +1,66 @@
<!--
* @Description:
* @Version: 1.668
* @Autor: 地虎降天龙
* @Date: 2024-12-13 14:36:33
* @LastEditors: 地虎降天龙
* @LastEditTime: 2024-12-13 21:09:49
-->
<template>
<TresCanvas window-size clearColor="#333333">
<TresPerspectiveCamera :position="[5, 5, 5]" />
<OrbitControls />
<TresMesh :position="[0, 1, -4]" :geometry="geometry">
<TresMeshNormalMaterial transparent :opacity="0.8" />
<TresMesh :geometry="erodedGeometry">
<TresMeshBasicMaterial wireframe color="#000" />
</TresMesh>
</TresMesh>
<TresMesh :position="[0, 1, 4]" :geometry="geometry">
<TresMeshNormalMaterial transparent :opacity="0.9" />
<TresMesh :geometry="dilatedGeometry">
<TresMeshBasicMaterial wireframe color="#000" />
</TresMesh>
</TresMesh>
<TresMesh :position="[0, 1, 0]" :geometry="geometry" :renderOrder="1">
<TresMeshBasicMaterial color="gray" />
<geometricGlowMesh :geometry="geometry" v-bind="geometricGlowState" />
</TresMesh>
<TresGridHelper :args="[10, 10]" />
</TresCanvas>
</template>
<script setup lang="ts">
import { reactive } from 'vue'
import * as THREE from 'three'
import { OrbitControls } from '@tresjs/cientos'
import { Pane } from 'tweakpane'
import { dilateBufferGeometry } from '../../common/utils'
import geometricGlowMesh from '../../components/geometricGlowMesh.vue'
const geometry = new THREE.TorusKnotGeometry(0.75, 0.25, 64)
const erodedGeometry = geometry.clone()
dilateBufferGeometry(erodedGeometry, -0.1)
const dilatedGeometry = geometry.clone()
dilateBufferGeometry(dilatedGeometry, 0.1)
const geometricGlowState = reactive({
inColor: '#0078ff',
outColor: '#ff00ba',
inPower: 1.4,
outPower: 1.2,
inCoeficient: 1.1,
outCoeficient: 0.1,
})
const pane = new Pane()
pane.addBinding(geometricGlowState, 'inColor', { label: '内发光色' })
pane.addBinding(geometricGlowState, 'inPower', { label: '内发光强度', step: 0.01, min: 0, max: 4 })
pane.addBinding(geometricGlowState, 'inCoeficient', { step: 0.01, min: 0, max: 4 })
pane.addBinding(geometricGlowState, 'outColor', { label: '外发光色' })
pane.addBinding(geometricGlowState, 'outPower', { label: '外发光强度', step: 0.01, min: 0, max: 6 })
pane.addBinding(geometricGlowState, 'outCoeficient', { step: 0.01, min: 0, max: 4 })
</script>

View File

@ -0,0 +1,14 @@
uniform vec3 glowColor;
uniform float coeficient;
uniform float power;
varying vec3 vVertexNormal;
varying vec3 vVertexWorldPosition;
varying vec4 vFragColor;
void main() {
vec3 worldCameraToVertex = vVertexWorldPosition - cameraPosition;
vec3 viewCameraToVertex = (viewMatrix * vec4(worldCameraToVertex, 0.0)).xyz;
viewCameraToVertex = normalize(viewCameraToVertex);
float intensity =
pow(coeficient + dot(vVertexNormal, viewCameraToVertex), power);
gl_FragColor = vec4(glowColor, intensity);
}

View File

@ -0,0 +1,8 @@
varying vec3 vVertexWorldPosition;
varying vec3 vVertexNormal;
varying vec4 vFragColor;
void main() {
vVertexNormal = normalize(normalMatrix * normal);
vVertexWorldPosition = (modelMatrix * vec4(position, 1.0)).xyz;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}