three.js 实现一个心形的着色器

three.js 实现一个心形的着色器

源链接:https://z2586300277.github.io/three-cesium-examples/#/codeMirror?navigation=ThreeJS&classify=shader&id=heartShader

国内站点预览:http://threehub.cn

github地址: https://github.com/z2586300277/three-cesium-examples

bash 复制代码
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import { UnrealBloomPass } from 'three/examples/jsm/postprocessing/UnrealBloomPass.js';
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js';
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js';

const box = document.getElementById('box')

const scene = new THREE.Scene()

const camera = new THREE.PerspectiveCamera(75, box.clientWidth / box.clientHeight, 0.1, 1000)

camera.position.set(0, 0, 20)

const renderer = new THREE.WebGLRenderer()

renderer.setSize(box.clientWidth, box.clientHeight)

box.appendChild(renderer.domElement)

new OrbitControls(camera, renderer.domElement)

const composer = new EffectComposer(renderer);

const renderPass = new RenderPass(scene, camera);

composer.addPass(renderPass);

const bloomPass = new UnrealBloomPass(new THREE.Vector2(window.innerWidth, window.innerHeight), 5, 1.2, 0)

composer.addPass(bloomPass);

window.onresize = () => {

    renderer.setSize(box.clientWidth, box.clientHeight)

    camera.aspect = box.clientWidth / box.clientHeight

    camera.updateProjectionMatrix()

}

class HeartCurve extends THREE.Curve {
    constructor(scale = 1) {
        super();
        this.scale = scale;
    }

    getPoint(a, optionalTarget = new THREE.Vector3()) {
        const t = a * Math.PI * 2;
        const tx = 16 * Math.pow(Math.sin(t), 3);
        const ty = 13 * Math.cos(t) - 5 * Math.cos(2 * t) - 2 * Math.cos(3 * t) - Math.cos(4 * t);
        const tz = 0;

        return optionalTarget.set(tx, ty, tz).multiplyScalar(this.scale);
    }
}

const geometry = new THREE.TubeGeometry(new HeartCurve(0.5), 100, 0.1, 30, false);

const vertexShader = `
    varying vec2 vUv;
    void main(void) {
        vUv = uv;
        gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    }`;
const fragmentShader = `
    varying vec2 vUv;
    uniform float uSpeed;
    uniform float uTime;
    uniform vec2 uFade;
    uniform vec3 uColor;
    uniform float uDirection;
    void main() {
    vec3 color =uColor;
    float s=0.0;
    float v=0.0;
    if(uDirection==1.0){
    v=vUv.x;
    s=-uTime*uSpeed;
    }else{
    v= -vUv.x;
    s= -uTime*uSpeed;
    }
    float d=mod(  (v + s) ,1.0) ;
    if(d>uFade.y)discard;
    else{
    float alpha = smoothstep(uFade.x, uFade.y, d);
    if (alpha < 0.0001) discard;
    gl_FragColor =  vec4(color,alpha);
    }
} `;

const getMaterial = (uniforms) => {
    return new THREE.ShaderMaterial({
        uniforms,
        vertexShader,
        fragmentShader,
        transparent: true
    });
}

const material1 = getMaterial({
    uColor: { value: new THREE.Color('pink') },
    uTime: { value: 0 },
    uDirection: { value: 1 },
    uSpeed: { value: 1 },
    uFade: { value: new THREE.Vector2(0, 0.5) },
    uDirection: { value: 1 },
    uSpeed: { value: 1 }
})

const material2 = getMaterial({
    uColor: { value: new THREE.Color('#00BFFF') },
    uTime: { value: 0.5 },
    uDirection: { value: 1 },
    uSpeed: { value: 1 },
    uFade: { value: new THREE.Vector2(0, 0.5) },
    uDirection: { value: 1 },
    uSpeed: { value: 1 }
})


const mesh = new THREE.Mesh(geometry, material1)
const mesh2 = new THREE.Mesh(geometry, material2)

scene.add(mesh);

scene.add(mesh2)


animate()

function animate() {

    material1.uniforms.uTime.value += 0.002
    material2.uniforms.uTime.value += 0.002

    requestAnimationFrame(animate)

    renderer.render(scene, camera)

    composer.render();

}

/**
 * 名称: 心
 * 作者: 优雅永不过时 https://github.com/z2586300277
 * 参照来源:https://github.com/xiaolidan00/my-earth?tab=readme-ov-file 
 */
相关推荐
传人once21 分钟前
悬停旋转放大和位移效果如何写
javascript·css·动画
库拉镜像AI牛牛35 分钟前
短剧内容自动化生产:知漫剧工作室落地教程
大数据·服务器·前端·人工智能·语音识别
律宏阔36 分钟前
Flutter 列表图片内存优化:CachedNetworkImage 与 ClipRRect 的取舍
前端·flutter
行者全栈架构师37 分钟前
【鸿蒙心迹】相册文搜图工程化落地:HarmonyOS 7.0 端侧 AI 检索全链路实战与 5 个踩坑解法
前端
律宏阔1 小时前
Dart 3 Record:解决 Future.wait 异构返回值的类型问题
前端·flutter
Seraphina361 小时前
DVWA(XSS Reflected/Stored High,CSRF Low)
前端·xss·csrf
默_笙2 小时前
🍔 中间件不只是打日志:四个钩子、一次短路,和自带的工具
前端·javascript
程序员老赵3 小时前
Docker 部署 Dolibarr:轻松搭建开源 ERP/CRM 平台
运维·前端·后端
星禾元亨3 小时前
同一件事有三份资料,AI 该信哪一份?冲突判定、优先级链与处置流程
前端·人工智能
Dovis(誓平步青云)3 小时前
家里设备越来越多,如何用一张空间地图控制灯光和温度![
android·java·前端·javascript·人工智能·电脑