mirror of
https://gitee.com/ice-gl/icegl-three-vue-tres.git
synced 2025-04-05 06:22:43 +08:00
增加了 基于geometric缩放加材质的 外发光案例
This commit is contained in:
parent
072bc40009
commit
a44f4e7737
BIN
public/plugins/basic/shine/preview/geometricGlow.png
Normal file
BIN
public/plugins/basic/shine/preview/geometricGlow.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 132 KiB |
46
src/plugins/basic/common/utils.js
Normal file
46
src/plugins/basic/common/utils.js
Normal 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 }
|
85
src/plugins/basic/components/geometricGlowMesh.vue
Normal file
85
src/plugins/basic/components/geometricGlowMesh.vue
Normal 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>
|
@ -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',
|
||||
|
66
src/plugins/basic/pages/shine/geometricGlow.vue
Normal file
66
src/plugins/basic/pages/shine/geometricGlow.vue
Normal 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>
|
14
src/plugins/basic/shader/geometricGlow.frag
Normal file
14
src/plugins/basic/shader/geometricGlow.frag
Normal 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);
|
||||
}
|
8
src/plugins/basic/shader/geometricGlow.vert
Normal file
8
src/plugins/basic/shader/geometricGlow.vert
Normal 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);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user