Pre Merge pull request !5 from 何贤/master
BIN
public/plugins/earthSample/image/pointsEarth/00_earthmap1k.jpg
Normal file
After Width: | Height: | Size: 336 KiB |
BIN
public/plugins/earthSample/image/pointsEarth/01_earthbump1k.jpg
Normal file
After Width: | Height: | Size: 89 KiB |
BIN
public/plugins/earthSample/image/pointsEarth/02_earthspec1k.jpg
Normal file
After Width: | Height: | Size: 114 KiB |
After Width: | Height: | Size: 83 KiB |
BIN
public/plugins/earthSample/image/pointsEarth/04_rainbow1k.jpg
Normal file
After Width: | Height: | Size: 320 KiB |
BIN
public/plugins/earthSample/image/pointsEarth/circle.png
Normal file
After Width: | Height: | Size: 4.7 KiB |
BIN
public/plugins/earthSample/preview/pointsEarth.png
Normal file
After Width: | Height: | Size: 370 KiB |
@ -22,5 +22,6 @@ export default {
|
||||
{ src: 'plugins/earthSample/preview/pointsScan.png', type: 'img', name: 'pointsScan', title: '点扫描' },
|
||||
{ src: 'plugins/earthSample/preview/highlightScan.png', type: 'img', name: 'highlightScan', title: '高光扫描' },
|
||||
{ src: 'plugins/earthSample/preview/smokeEarth.png', type: 'img', name: 'smokeEarth', title: '烟雾球' },
|
||||
{ src: 'plugins/earthSample/preview/pointsEarth.png', type: 'img', name: 'pointsEarth', title: '粒子球' },
|
||||
],
|
||||
}
|
||||
|
119
src/plugins/earthSample/pages/pointsEarth.vue
Normal file
@ -0,0 +1,119 @@
|
||||
<script setup lang="ts">
|
||||
import * as THREE from 'three'
|
||||
import { shallowRef } from 'vue'
|
||||
import { useTexture, useRenderLoop } from '@tresjs/core'
|
||||
import { OrbitControls } from '@tresjs/cientos'
|
||||
// import loading from 'PLS/UIdemo/components/loading/default.vue'
|
||||
import { Pane } from 'tweakpane'
|
||||
import ParticalMesh from '@/plugins/UIdemo/components/particalMesh.vue'
|
||||
import vertex from '../shaders/pointsEarth.vert?raw'
|
||||
import fragment from '../shaders/pointsEarth.frag?raw'
|
||||
|
||||
const params = {
|
||||
color: '#17c5a9',
|
||||
pointSize: 4.0,
|
||||
}
|
||||
|
||||
const gl = {
|
||||
clearColor: '#122148',
|
||||
shadows: false,
|
||||
alpha: false,
|
||||
outputColorSpace: THREE.SRGBColorSpace,
|
||||
}
|
||||
|
||||
const wireframeMaterial = {
|
||||
color: params.color,
|
||||
wireframe: true,
|
||||
transparent: true,
|
||||
opacity: 0.2,
|
||||
}
|
||||
|
||||
const textures = await useTexture([
|
||||
'./plugins/earthSample/image/pointsEarth/00_earthmap1k.jpg',
|
||||
'./plugins/earthSample/image/pointsEarth/circle.png',
|
||||
'./plugins/earthSample/image/pointsEarth/04_rainbow1k.jpg',
|
||||
'./plugins/earthSample/image/pointsEarth/01_earthbump1k.jpg',
|
||||
'./plugins/earthSample/image/pointsEarth/02_earthspec1k.jpg',
|
||||
])
|
||||
|
||||
const earthMap = textures[0]
|
||||
const starSprite = textures[1]
|
||||
const colorMap = textures[2]
|
||||
const elevMap = textures[3]
|
||||
const alphaMap = textures[4]
|
||||
|
||||
const pointsShader = {
|
||||
uniforms: {
|
||||
size: { type: 'f', value: params.pointSize },
|
||||
uTime: { type: 'f', value: 0.0 },
|
||||
uWaveHeight: { type: 'f', value: 0.075 },
|
||||
uWaveSpeed: { type: 'f', value: 0.2 },
|
||||
colorTexture: { type: 't', value: colorMap },
|
||||
elevTexture: { type: 't', value: elevMap },
|
||||
alphaTexture: { type: 't', value: alphaMap },
|
||||
earthTexture: { type: 't', value: earthMap },
|
||||
starTexture: { type: 't', value: starSprite },
|
||||
},
|
||||
vertexShader: vertex,
|
||||
fragmentShader: fragment,
|
||||
transparent: true,
|
||||
side: THREE.FrontSide,
|
||||
}
|
||||
|
||||
const groupRef = shallowRef()
|
||||
const wireframeMaterialRef = shallowRef()
|
||||
|
||||
const pane = new Pane()
|
||||
const debugFolder = pane.addFolder({ title: 'Debug' })
|
||||
debugFolder.addBinding(params, 'color', { type: 'color' }).on('change', ({ value }) => {
|
||||
wireframeMaterialRef.value.color.set(value)
|
||||
})
|
||||
debugFolder.addBinding(pointsShader.uniforms.size, 'value', {
|
||||
min: 0.1,
|
||||
max: 10,
|
||||
step: 0.1,
|
||||
label: '粒子大小',
|
||||
})
|
||||
|
||||
debugFolder.addBinding(pointsShader.uniforms.uWaveHeight, 'value', {
|
||||
min: 0.01,
|
||||
max: 0.5,
|
||||
step: 0.01,
|
||||
label: '海浪高度',
|
||||
})
|
||||
|
||||
debugFolder.addBinding(pointsShader.uniforms.uWaveSpeed, 'value', {
|
||||
min: 0.01,
|
||||
max: 1,
|
||||
step: 0.01,
|
||||
label: '海浪变化速度',
|
||||
})
|
||||
|
||||
const { onLoop } = useRenderLoop()
|
||||
|
||||
onLoop(({ delta }) => {
|
||||
if (groupRef.value) {
|
||||
groupRef.value.rotation.y += 0.002
|
||||
pointsShader.uniforms.uTime.value += 10 * delta
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- <loading /> -->
|
||||
<TresCanvas v-bind="gl" window-size>
|
||||
<TresPerspectiveCamera :position="[0, 0, 3.5]" :fov="45" :near="0.1" :far="20" />
|
||||
<OrbitControls :autoRotate="true" :autoRotateSpeed="2" />
|
||||
<TresGroup ref="groupRef">
|
||||
<TresMesh>
|
||||
<TresIcosahedronGeometry :args="[1, 4]" />
|
||||
<TresMeshBasicMaterial ref="wireframeMaterialRef" v-bind="wireframeMaterial"> </TresMeshBasicMaterial>
|
||||
</TresMesh>
|
||||
<TresPoints>
|
||||
<TresIcosahedronGeometry :args="[1, 128]" />
|
||||
<TresShaderMaterial v-bind="pointsShader" />
|
||||
</TresPoints>
|
||||
</TresGroup>
|
||||
<TresHemisphereLight :args="['#ffffff', '#080820', 3]" />
|
||||
</TresCanvas>
|
||||
</template>
|
33
src/plugins/earthSample/shaders/pointsEarth.frag
Normal file
@ -0,0 +1,33 @@
|
||||
uniform sampler2D colorTexture;
|
||||
// uniform sampler2D alphaTexture;
|
||||
uniform sampler2D earthTexture;
|
||||
uniform sampler2D starTexture;
|
||||
|
||||
varying vec2 vUv;
|
||||
varying float vVisible;
|
||||
varying float vAlpha;
|
||||
varying float vElevation;
|
||||
|
||||
void main() {
|
||||
if (floor(vVisible + 0.1) == 0.0) discard;
|
||||
vec2 coord = gl_PointCoord;
|
||||
float alpha = texture2D(starTexture, coord).a;
|
||||
// 根据 alpha 值来裁剪形状
|
||||
if (alpha < 0.1) discard;
|
||||
|
||||
// float alphaLand = 1.0 - texture2D(alphaTexture, vUv).r;
|
||||
vec3 color = texture2D(colorTexture, vUv).rgb;
|
||||
vec3 earth = texture2D(earthTexture, vUv).rgb;
|
||||
color = mix(color, earth, 0.65);
|
||||
if(
|
||||
vAlpha > 0.5
|
||||
) {
|
||||
gl_FragColor = vec4(color, vAlpha);
|
||||
}else {
|
||||
// 对于海洋部分,根据 vElevation 调整颜色
|
||||
float elevationEffect = clamp(vElevation*30.0, -1.0, 1.0); // 将 vElevation 限制在 [-1, 1] 范围内
|
||||
vec3 deep_sea_blue = vec3(0.004, 0.227, 0.388);
|
||||
vec3 adjustedColor = mix(deep_sea_blue, earth*1.75, (elevationEffect + 1.0) * 0.5); // 根据 vElevation 调整颜色
|
||||
gl_FragColor = vec4(adjustedColor, 1.0-vAlpha);
|
||||
}
|
||||
}
|
78
src/plugins/earthSample/shaders/pointsEarth.vert
Normal file
@ -0,0 +1,78 @@
|
||||
uniform float size;
|
||||
uniform sampler2D elevTexture;
|
||||
uniform sampler2D alphaTexture;
|
||||
uniform float uTime;
|
||||
uniform float uWaveHeight;
|
||||
uniform float uWaveSpeed;
|
||||
|
||||
varying vec2 vUv;
|
||||
varying float vVisible;
|
||||
varying float vAlpha;
|
||||
varying float vElevation;
|
||||
// Function to generate fBm with vec3 input
|
||||
float random(vec3 st) {
|
||||
return fract(sin(dot(st.xyz, vec3(12.9898,78.233,45.164))) * 43758.5453123);
|
||||
}
|
||||
|
||||
float noise(vec3 st) {
|
||||
vec3 i = floor(st);
|
||||
vec3 f = fract(st);
|
||||
|
||||
// Eight corners in 3D of a tile
|
||||
float a = random(i);
|
||||
float b = random(i + vec3(1.0, 0.0, 0.0));
|
||||
float c = random(i + vec3(0.0, 1.0, 0.0));
|
||||
float d = random(i + vec3(1.0, 1.0, 0.0));
|
||||
float e = random(i + vec3(0.0, 0.0, 1.0));
|
||||
float f1 = random(i + vec3(1.0, 0.0, 1.0));
|
||||
float g = random(i + vec3(0.0, 1.0, 1.0));
|
||||
float h = random(i + vec3(1.0, 1.0, 1.0));
|
||||
|
||||
vec3 u = f * f * (3.0 - 2.0 * f);
|
||||
|
||||
return mix(mix(mix(a, b, u.x), mix(c, d, u.x), u.y),
|
||||
mix(mix(e, f1, u.x), mix(g, h, u.x), u.y), u.z);
|
||||
}
|
||||
|
||||
float fbm(vec3 st) {
|
||||
float value = 0.0;
|
||||
float amplitude = 0.5;
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
value += amplitude * noise(st);
|
||||
st *= 2.0;
|
||||
amplitude *= 0.5;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vUv = uv;
|
||||
float alphaLand = 1.0 - texture2D(alphaTexture, vUv).r;
|
||||
vAlpha = alphaLand;
|
||||
vec3 newPosition = position;
|
||||
|
||||
if(alphaLand < 0.5) {
|
||||
// Sea
|
||||
// fBm for wave-like displacement
|
||||
float waveHeight = uWaveHeight; // Adjust wave height as needed
|
||||
float waveSpeed = uWaveSpeed; // Adjust wave speed as needed
|
||||
float displacement = (fbm(newPosition * 5.0 + uTime * waveSpeed) * 2.0 - 1.0) * waveHeight;
|
||||
vElevation = displacement;
|
||||
newPosition += normal * displacement ;
|
||||
}
|
||||
|
||||
vec4 mvPosition = modelViewMatrix * vec4( newPosition, 1.0 );
|
||||
float elv = texture2D(elevTexture, vUv).r;
|
||||
vec3 vNormal = normalMatrix * normal;
|
||||
vVisible = step(0.0, dot( -normalize(mvPosition.xyz), normalize(vNormal)));
|
||||
mvPosition.z += 0.45 * elv;
|
||||
|
||||
// 求出 mvPosition 距离相机的距离
|
||||
float dist = length(mvPosition.xyz);
|
||||
// 根据距离调整 size
|
||||
float pointSize = size * (1.0 - dist / 10.0);
|
||||
gl_PointSize = max(pointSize, 1.0);
|
||||
gl_PointSize = pointSize;
|
||||
gl_Position = projectionMatrix * mvPosition;
|
||||
}
|