Three.js之顶点UV坐标、纹理贴图

参考资料

知识点

注:基于Three.jsv0.155.0

  • 纹理贴图加载器:TextureLoader
  • 纹理对象:Texture
  • 颜色贴图属性.map
  • 顶点UV坐标
  • 圆形平面设置纹理贴图:CircleGeometry
  • 设置阵列模式:THREE.RepeatWrapping
  • 网格地面辅助观察:GridHelper
  • 纹理对象.offset属性

代码实现

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Three.js</title>
</head>
  <body>
  </body>
  <!-- 具体路径配置,你根据自己文件目录设置,我的是课件中源码形式 -->
  <script type="importmap">
    {
      "imports": {
        "three": "./js/three.module.js",
        "three/addons/": "../three.js/examples/jsm/"
      }
    }
  </script>
  <script type="module">
    import * as THREE from 'three';
    import { OrbitControls } from 'three/addons/controls/OrbitControls.js';

    const width = 800
    const height = 500

    // 场景
    const scene = new THREE.Scene();

    // ********** 本章知识点示例代码 Start **********
    // 1. 创建纹理贴图
    // 几何体
    const geometry = new THREE.SphereGeometry(100);
    // const geometry = new THREE.BoxGeometry(100, 100 ,100);
    // 文理贴图
    const textureLoader = new THREE.TextureLoader();
    const texture = textureLoader.load('./img/6.JPG');

    // 材质 
    const material = new THREE.MeshLambertMaterial({
      // color:0x0000ff,
      map: texture,
    });

    material.map = texture;

    const mesh1 = new THREE.Mesh(geometry, material);
    scene.add(mesh1);

    // 2. 自定义顶点UV坐标
    scene.remove(mesh1);

    const geometry2 = new THREE.PlaneGeometry(200, 100);
    console.log('🚀 ~ file: 5顶点UV坐标、纹理贴图.html:29 ~ geometry.attributes.uv:', geometry.attributes.uv);
    console.log('🚀 ~ file: 5顶点UV坐标、纹理贴图.html:29 ~ geometry.attributes.position:', geometry.attributes.position);
    const textureLoader2 = new THREE.TextureLoader();
    const texture2 = textureLoader2.load('./img/6.JPG');

    geometry2.attributes.uv = new THREE.Float32BufferAttribute([
      0, 1,
      1, 1,
      0, 0,
      1, 0,
    ], 2);

    // 材质 
    const material2 = new THREE.MeshLambertMaterial({
      // color:0x0000ff,
      map: texture2,
    });

    const mesh2 = new THREE.Mesh(geometry2, material2);
    scene.add(mesh2);

    // 3. 圆形平面设置纹理贴图
    scene.remove(mesh2);

    const geometry3 = new THREE.CircleGeometry(100);
    const textureLoader3 = new THREE.TextureLoader();
    const texture3 = textureLoader3.load('./img/6.JPG');

    // 材质 
    const material3 = new THREE.MeshLambertMaterial({
      // color:0x0000ff,
      map: texture3,
    });

    const mesh3 = new THREE.Mesh(geometry3, material3);
    scene.add(mesh3);

    // 4. 纹理对象Texture阵列
    scene.remove(mesh3);

    const geometry4 = new THREE.PlaneGeometry(400, 400);
    const textureLoader4 = new THREE.TextureLoader();
    const texture4 = textureLoader4.load('./img/6.JPG');
    texture4.wrapS = THREE.RepeatWrapping;
    texture4.wrapT = THREE.RepeatWrapping;
    texture4.repeat.set(10, 10);

    // 材质 
    const material4 = new THREE.MeshLambertMaterial({
      // color:0x0000ff,
      map: texture4,
      side: THREE.DoubleSide,
    });

    const mesh4 = new THREE.Mesh(geometry4, material4);
    mesh4.rotateX(-Math.PI / 2);
    scene.add(mesh4);

    
    // 5. 矩形Mesh+背景透明png贴图
    scene.remove(mesh4);

    const geometry5 = new THREE.PlaneGeometry(600, 200);
    const textureLoader5 = new THREE.TextureLoader();
    const texture5 = textureLoader5.load('./img/6.JPG');
    texture5.wrapS = THREE.RepeatWrapping;

    // 材质 
    const material5 = new THREE.MeshLambertMaterial({
      // color:0x0000ff,
      map: texture5,
      side: THREE.DoubleSide,
      transparent: true,
    });

    const mesh5 = new THREE.Mesh(geometry5, material5);
    mesh5.rotateX(-Math.PI / 2);
    scene.add(mesh5);

    // 网格地面辅助观察
    const grid = new THREE.GridHelper(500, 10);
    grid.position.set(0, -0.01, 0);
    scene.add(grid);
    mesh5.position.y = 1

    // ********** 本章知识点示例代码 End **********
    
    

    // 光源
    const pointLight = new THREE.PointLight(0xffffff, 1.0, 0, 0);
    pointLight.position.set(200, 200, 200 );
    scene.add(pointLight);

    // 环境光
    const ambientLight = new THREE.AmbientLight( 0xffffff, 0.2);
    scene.add( ambientLight );

    // 坐标系
    const axes = new THREE.AxesHelper(200);
    scene.add(axes);

    // 相机
    const camera = new THREE.PerspectiveCamera(75, width/height, 0.1, 1000);
    camera.position.set(200, 200, 200);
    camera.lookAt(scene.position);

    // 渲染器
    const renderer = new THREE.WebGLRenderer();
    renderer.setSize(width, height);
    renderer.render(scene, camera);
    document.body.appendChild(renderer.domElement);

    // 控制器
    const controls = new OrbitControls(camera, renderer.domElement);
    controls.addEventListener('change', () => {
      renderer.render(scene, camera);
    });

    // 渲染循环
    function render() {
        texture5.offset.x += 0.005;
        renderer.render(scene, camera);
        requestAnimationFrame(render);
    }
    render();
  </script>
</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要实现线路流动和建筑物纹理流动,需要使用Three.js中的ShaderMaterial和自定义的着色器代码。下面是一个简单的示例代码: HTML: ``` <div id="container"></div> ``` JavaScript: ```javascript // 创建场景和渲染器 var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); var renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(window.innerWidth, window.innerHeight); document.getElementById('container').appendChild(renderer.domElement); // 添加灯光 var ambientLight = new THREE.AmbientLight(0xffffff, 0.5); scene.add(ambientLight); var pointLight = new THREE.PointLight(0xffffff, 0.5); pointLight.position.set(10, 10, 10); scene.add(pointLight); // 创建建筑物和线路材质 var buildingGeometry = new THREE.BoxGeometry(1, 1, 1); var buildingMaterial = new THREE.MeshPhongMaterial({ color: 0xCCCCCC, shininess: 10 }); var lineMaterial = new THREE.LineBasicMaterial({ color: 0x00FF00 }); var time = 0; // 自定义着色器代码 var vertexShader = ` uniform float time; varying vec2 vUv; void main() { vUv = uv; vec3 position = position; position.x += sin(position.z * 10.0 + time) * 0.1; position.y += sin(position.z * 20.0 + time) * 0.1; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); } `; var fragmentShader = ` uniform float time; uniform sampler2D texture; varying vec2 vUv; void main() { vec2 uv = vUv; uv.x += sin(uv.y * 10.0 + time) * 0.1; uv.y += sin(uv.x * 20.0 + time) * 0.1; gl_FragColor = texture2D(texture, uv); } `; // 创建着色器材质 var shaderMaterial = new THREE.ShaderMaterial({ uniforms: { time: { value: 0 }, texture: { value: new THREE.TextureLoader().load('https://threejs.org/examples/textures/uv_grid_opengl.jpg') } }, vertexShader: vertexShader, fragmentShader: fragmentShader }); // 添加建筑物和线路 for (var i = 0; i < 10; i++) { var building = new THREE.Mesh(buildingGeometry, buildingMaterial); building.position.set(i - 5, 0, 0); scene.add(building); var lineGeometry = new THREE.Geometry(); lineGeometry.vertices.push(new THREE.Vector3(i - 5, -0.5, 0), new THREE.Vector3(i - 5, -0.5, -5)); var line = new THREE.Line(lineGeometry, lineMaterial); scene.add(line); } // 渲染循环 function render() { requestAnimationFrame(render); time += 0.1; shaderMaterial.uniforms.time.value = time; renderer.render(scene, camera); } render(); ``` 这个示例代码中,我们创建了一个包含10个方块和10条线路的场景。我们使用了一个自定义的着色器代码来实现建筑物和线路的流动效果。建筑物使用了Phong材质,线路使用了LineBasicMaterial。 在自定义的着色器代码中,我们使用了一个uniform变量time来控制时间流逝。在顶点着色器中,我们根据时间调整建筑物的位置。在片元着色器中,我们根据时间调整纹理UV坐标来实现纹理的流动效果。 如果你需要进一步了解ShaderMaterial和自定义着色器代码的使用,可以参考Three.js的官方文档。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值