Threejs 自定义片元着色器 做UV动画

引入threejs库

javascript 复制代码
  <!--引入three.js三维引擎-->
  <script src="http://www.yanhuangxueyuan.com/versions/threejsR92/build/three.js"></script>
  <!-- 引入threejs扩展控件OrbitControls.js -->
  <script src="http://www.yanhuangxueyuan.com/versions/threejsR92/examples/js/controls/OrbitControls.js"></script>

顶点着色器

javascript 复制代码
  <!-- 顶点着色器 -->
  <script id="vertexShader" type="x-shader/x-vertex">
    // varying关键字声明一个变量表示顶点纹理坐标插值后的结果
    varying vec2 vUv;
    void main(){
      // 顶点纹理坐标uv数据进行插值计算
      vUv = uv;
      // 投影矩阵projectionMatrix、视图矩阵viewMatrix、模型矩阵modelMatrix
      gl_Position = projectionMatrix*viewMatrix*modelMatrix*vec4( position, 1.0 );
    }
  </script>

片元着色器

javascript 复制代码
  <!-- 片元着色器 -->
  <script id="fragmentShader" type="x-shader/x-fragment">
    // 声明一个时间变量用来控制UV动画
    uniform float time;
    // 声明一个纹理对象变量
    uniform sampler2D texture;
    // 顶点片元化后有多少个片元就有多少个纹理坐标数据vUv
    varying vec2 vUv;
    void main() {
      vec2 newT= vUv + vec2( -0.02, 0.02 ) * time;
      //通过偏移后的纹理坐标newT采样像素
      gl_FragColor = texture2D( texture, newT );
      // 大气层整体透明度增加
      gl_FragColor.a *=0.6;
    }
  </script>

scene代码

javascript 复制代码
    /**
     * 创建场景对象Scene
     */
    var scene = new THREE.Scene();

    // 创建一个纹理贴图加载器
    var textureLoader = new THREE.TextureLoader()

    // 创建一个组对象,用来插入地球、大气层网格模型
    var group = new THREE.Group()

    /**
     * 地球网格模型
     */
    var earthGeometry = new THREE.SphereBufferGeometry(100, 30, 30);
    var earthMaterial = new THREE.MeshPhongMaterial({
      map: textureLoader.load('Earth.png'),
      normalMap: textureLoader.load('EarthNormal.png'),
      normalScale: new THREE.Vector2(2.9, 2.9),
      specularMap: textureLoader.load('EarthSpec.png'),
      transparent: true,
      opacity: 0.7,
    });
    var earthMesh = new THREE.Mesh(earthGeometry, earthMaterial);
    // 地球网格模型插入组对象中
    group.add(earthMesh);

    // 创建一个大气层几何体,注意比地球几何体的半径略大一些
    var geometry = new THREE.SphereBufferGeometry(100.1, 30, 30); //球体
    var texture = textureLoader.load('./大气.png');
    // 设置重复的作用是:能够让一个效果循环
    texture.wrapS = THREE.RepeatWrapping;
    texture.wrapT = THREE.RepeatWrapping;

    // 自定义顶点着色器对象
    var material = new THREE.ShaderMaterial({
      uniforms: {
        // texture对应顶点着色器中uniform声明的texture变量
        texture: {
          value: texture,
        },
        time: {
          value: 0.0
        },
      },
      // 顶点着色器
      vertexShader: document.getElementById('vertexShader').textContent,
      // 片元着色器
      fragmentShader: document.getElementById('fragmentShader').textContent,
      // 开启透明度
      transparent: true,
    });
    // 创建大气层网格模型
    var mesh = new THREE.Mesh(geometry, material);
    group.add(mesh); //大气层网格模型对象插入组对象中
    scene.add(group);
    /**
     * 光源设置
     */
    // 方向光1
    var directionalLight = new THREE.DirectionalLight(0xffffff, 0.9);
    directionalLight.position.set(400, 200, 300);
    scene.add(directionalLight);
    // 方向光2
    var directionalLight2 = new THREE.DirectionalLight(0xffffff, 0.9);
    directionalLight2.position.set(-400, -200, -300);
    scene.add(directionalLight2);
    //环境光
    var ambient = new THREE.AmbientLight(0xffffff, 0.6);
    scene.add(ambient);
    /**
     * 相机设置
     */
    var width = window.innerWidth; //窗口宽度
    var height = window.innerHeight; //窗口高度
    var k = width / height; //窗口宽高比
    var s = 150; //三维场景显示范围控制系数,系数越大,显示的范围越大
    //创建相机对象
    var camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
    camera.position.set(0, 100, 200); //设置相机位置
    camera.lookAt(scene.position); //设置相机方向(指向的场景对象)
    /**
     * 创建渲染器对象
     */
    var renderer = new THREE.WebGLRenderer({
      antialias: true
    });
    renderer.setSize(width, height); //设置渲染区域尺寸
    document.body.appendChild(renderer.domElement); //body元素中插入canvas对象

    // 创建一个时钟对象Clock
    var clock = new THREE.Clock();
    // 渲染函数
    function render() {

      // 获得两次渲染的时间间隔deltaTime
      var deltaTime = clock.getDelta();
      // 更新uniforms中时间,这样就可以更新着色器中time变量的值
      material.uniforms.time.value += deltaTime;

      group.rotateY(-0.005)
      renderer.render(scene, camera); //执行渲染操作
      requestAnimationFrame(render); //请求再次执行渲染函数render,渲染下一帧
    }
    render();
    //创建控件对象  相机对象camera作为参数   控件可以监听鼠标的变化,改变相机对象的属性
    var controls = new THREE.OrbitControls(camera,renderer.domElement);
相关推荐
a11177614 小时前
坦克大战3D Three.js 3D (开源项目)
开发语言·javascript·3d
接针16 小时前
UV 常用命令
python·uv
用户831348593069819 小时前
Cesium 实现行政区内部遮罩
vue.js·webgl·cesium
凯尔31521 小时前
Unity简单涂料实现
unity·游戏引擎·图形渲染
a1117761 天前
Web 3D 肌肉车展示项目 开源
前端·3d
dalong101 天前
WPF:3D立方体
3d·wpf
寒水馨2 天前
macOS下载、安装godot-4.7.1-stable(附安装包Godot_v4.7.1-stable_macos.universal.zip)
macos·3d·游戏引擎·godot·跨平台·游戏开发·2d
人工智能培训2 天前
AI如何学习知识?与人类学习的本质差异
大数据·网络·数据库·人工智能·学习·3d
lxw18449125143 天前
Python uv 完整使用教程
python·conda·pip·uv
3D小将3 天前
3D格式转换之Rhino(Rhinoceros)转 CATIA 标准化转换技术
3d·solidworks模型·ug模型·rhino模型·catia模型