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);
相关推荐
yyt3630458414 小时前
KLineChartQuant:GLSL 的精度问题及 RTC 解法
前端·vue.js·react.js·交互·图形渲染·webgl·数据可视化
weixin_468466856 小时前
从“建模城市”到“按需查询”:D4RT如何用200+FPS重新定义动态3D世界
人工智能·3d·具身智能·d4rt·4d重建
拿我格子衫来1 天前
Beam Studio:矢量图与位图如何变成 G-code
图像处理·图形渲染
灵境(虚幻知音)1 天前
WebGL 不支持>1px的线绘制,那 Cesium 的带宽度的线是怎么画出来的?
webgl·cesium·着色器
maybeyaluokenai1 天前
unity build in渲染管线概述
unity·图形渲染
云登指纹浏览器2 天前
浏览器指纹检测原理演进:从Canvas到WebGL的4轮风控升级
webgl
DolitD2 天前
实时云渲染多应用并发:CELL容器技术突破3D隔离瓶颈
云原生·容器·实时互动·图形渲染·数据可视化
PhotonixBay2 天前
3D共聚焦显微镜与探针式粗糙度仪:谁更适合亚表面损伤检测?
图像处理·人工智能·测试工具·3d
自动化监测Learner2 天前
Cesium 加载大雁塔 3D Tiles 实录:从模型结构剖析到局部虚拟化(剖切 + 骨架线)实现
3d
FOORIR 客流统计2 天前
智能客流系统未来趋势:3D视觉、AI识别与数据分析的融合架构
人工智能·3d·数据分析