首页 > 其他分享 >three.js教程5-几何体顶点UV坐标、纹理贴图

three.js教程5-几何体顶点UV坐标、纹理贴图

时间:2023-02-09 20:11:26浏览次数:58  
标签:贴图 const UV THREE texture 纹理 new 几何体

1、纹理贴图

纹理贴图,是给MeshLambertMaterial等材质一些纹理图片,以达到更好的视觉效果。

使用方法:通过纹理贴图加载器TextureLoaderload()方法加载一张图片可以返回一个纹理对象Texture,纹理对象Texture可以作为模型材质颜色贴图.map属性的值。

const geometry = new THREE.PlaneGeometry(200, 100); 
//纹理贴图加载器TextureLoader
const texLoader = new THREE.TextureLoader();
// .load()方法加载图像,返回一个纹理对象Texture
const texture = texLoader.load('./earth.jpg');
const material = new THREE.MeshLambertMaterial({
    // color: 0x00ffff,color和map颜色值会混合,因此设置map后color一般不用设置
    // 设置纹理贴图:Texture对象作为材质map属性的属性值
    map: texture,//map表示材质的颜色贴图属性
});

color和map颜色值会混合,因此设置map后color一般不用设置

2、顶点uv坐标

顶点uv坐标,是二维顶点坐标,顶点UV坐标geometry.attributes.uv和顶点位置坐标geometry.attributes.position是一一对应的。

作用:纹理贴图上提取像素映射到网格模型Mesh的几何体表面上。

顶点UV坐标,可以在0~1.0之间任意取值(是百分比值,比如0.3,对应是30%的位置),纹理贴图左下角对应的UV坐标是(0,0)右上角对应的坐标(1,1)

/**纹理坐标0~1之间随意定义*/
const uvs = new Float32Array([
    0, 0, //图片左下角
    1, 0, //图片右下角
    1, 1, //图片右上角
    0, 1, //图片左上角
]);
// 设置几何体attributes属性的位置normal属性
geometry.attributes.uv = new THREE.BufferAttribute(uvs, 2); //2个为一组,表示一个顶点的纹理坐标

获取纹理贴图左下角四分之一部分:

const uvs = new Float32Array([
    0, 0, 
    0.5, 0, 
    0.5, 0.5, 
    0, 0.5, 
]);

3、实现瓷砖地面效果

// .load()方法加载图像,返回一个纹理对象Texture
const texture = texLoader.load('./瓷砖.jpg');
// 设置阵列包裹模式,S对应U,T对应V
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
// uv两个方向纹理重复数量
texture.repeat.set(12,12);//注意选择合适的阵列数量

4、背景透明的png图片贴图-transparent

如果不做处理,直接贴图,透明部分会有颜色填充,因此要设置transparent: true解决

const material = new THREE.MeshBasicMaterial({
    map: textureLoader.load('./指南针.png'),        
    transparent: true, //使用背景透明的png贴图,注意开启透明计算
});

5、创建uv动画(利用offset属性)

通过纹理对象的偏移属性.offset实现一个UV动画效果。offset是Vector2对象。

texture.offset.x +=0.5;//纹理U方向偏移
// 设置.wrapS也就是U方向,纹理映射模式(包裹模式)
texture.wrapS = THREE.RepeatWrapping;//对应offste.x偏移

texture.offset.y +=0.5;//纹理V方向偏移
// 设置.wrapT也就是V方向,纹理映射模式
texture.wrapT = THREE.RepeatWrapping;//对应offste.y偏移

把上面代码放到渲染循环函数中执行即可实现动画。

记住对应关系:X:S:U这3个对应,Y:T:V这3个对应。

下面展示一个示例:

 实例完整代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Three.js中文网:www.webgl3d.cn</title>
    <style>
        body{
            overflow: hidden;
             margin: 0px;
        }
    </style>
</head>
<body>
    <!-- type="importmap"功能:.html文件中也能和nodejs开发环境中一样方式,引入npm安装的js库 -->
    <script type="importmap">
        {
            "imports": {
                "three": "../../../three.js/build/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 geometry = new THREE.PlaneGeometry(200, 20);
    //纹理贴图加载器TextureLoader
    const texLoader = new THREE.TextureLoader();
    // .load()方法加载图像,返回一个纹理对象Texture
    const texture = texLoader.load('./纹理3.jpg');

    const material = new THREE.MeshLambertMaterial({
        map: texture,//map表示材质的颜色贴图属性
    });
    const mesh = new THREE.Mesh(geometry, material);
    mesh.rotateX(-Math.PI/2);

    // 设置阵列
    texture.wrapS = THREE.RepeatWrapping;
    // uv两个方向纹理重复数量
    texture.repeat.x=50;//注意选择合适的阵列数量

    //场景
    const scene = new THREE.Scene();
    scene.add(mesh); //模型对象添加到场景中

    //辅助观察的坐标系
    const axesHelper = new THREE.AxesHelper(100);
    scene.add(axesHelper);

    //光源设置
    const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
    directionalLight.position.set(100, 60, 50);
    scene.add(directionalLight);
    const ambient = new THREE.AmbientLight(0xffffff, 0.4);
    scene.add(ambient);


    //渲染器和相机
    const width = window.innerWidth;
    const height = window.innerHeight;
    const camera = new THREE.PerspectiveCamera(30, width / height, 1, 3000);
    camera.position.set(292, 223, 185);
    camera.lookAt(0, 0, 0);

    const renderer = new THREE.WebGLRenderer();
    renderer.setSize(width, height);
    document.body.appendChild(renderer.domElement);



    // 渲染循环
    function render() {
        texture.offset.x +=0.1;//设置纹理动画
        renderer.render(scene, camera);
        requestAnimationFrame(render);
    }
    render();


    const controls = new OrbitControls(camera, renderer.domElement);

    // 画布跟随窗口变化
    window.onresize = function () {
        renderer.setSize(window.innerWidth, window.innerHeight);
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
    };
    </script>
</body>

</html>

 

 文章中部分素材选取自Threejs中文网:http://www.webgl3d.cn/

标签:贴图,const,UV,THREE,texture,纹理,new,几何体
From: https://www.cnblogs.com/tiandi/p/17059347.html

相关文章

  • Pbr学习 没有环境贴图的pbr部分
    从learnOpenGL学习的D部分正态分布函数DD,或者说镜面分布,从统计学上近似的表示了与某些(中间)向量hh取向一致的微平面的比率。举例来说,假设给定向量hh,如果我们的微平面中有35%......
  • three.js教程2-几何体BufferGeomety顶点
    1、网格模型(三角形概念)网格模型Mesh其实就一个一个三角形(面)拼接构成。使用使用网格模型Mesh渲染几何体geometry,就是几何体所有顶点坐标三个为一组,构成一个三角形,多组......
  • UVA11991 Easy Problem from Rujia Liu? map+vector的妙用
    题目描述​​PDF​​输入输出格式输入格式:  输出格式:  输入输出样例输入样例#1: 复制841322432113243242输出样例#1: 复制2070思路来自:刘汝佳:......
  • UVA12096 The SetStack Computer 栈的应用 好题
    题意翻译对于一个以集合为元素的栈,初始时栈为空。输入的命令有如下几种:PUSH:将空集{}压栈DUP:将栈顶元素复制一份压入栈中UNION:先进行两次弹栈,将获得的集合A和B取并集,将结......
  • UVA540 Team Queue 队列入门经典
    题意翻译有t个团队的人正在排一个长队。每次新来一个人时,如果他有队友在排队,那么新人会插队到最后一个队友的身后。如果没有任何一个队友排队,则他会被排到长队的队尾。输入......
  • rpm -Uvh升级包报错:error: db5 error(11) from dbenv->open: Resource temporarily un
    问题背景针对系统漏洞扫描,对部分包进行rpm-Uvh升级时报如下的错误:[root]#rpm-Uvhpolkit-0.112-26.el7_9.1.x86_64.rpmerror:db5error(11)fromdbenv->open:Res......
  • UVA227--谜题
    #include<iostream>#include<cstdio>usingnamespacestd;intmain(){chara[5][7],t;intn,m,i,j,k;intcases=0;charmodol[1001];while(gets(......
  • 【UVA1645】Count
    找递推式。设\(f_i\)为\(i\)个节点的满足要求的树的数量,由于同一深度下每个节点子树相同,那么也就是说,根节点的若干个儿子都要分到同样的节点数。设总共有\(m\)个儿......
  • 洛谷P9035 Pont des souvenirs 题解
    题面很简洁,这里不做多说。70pts做法首先考虑到\(a_{n-1}\)和\(a_n\)两项是整个数列\(a\)中的最大的两项,所以若\(a_{n-1}+a_n\)不超过\(k+1\),则数列中任意两项......
  • 【UVA1485】Permutation Counting
    典中典题。由于\(0\lek\len\le1000\),能猜到做法大概是\(n^2\)的动态规划,接下来写方程。以排列长度划分阶段,该长度下\(E\)值划分子问题,容易想到定义\(f[i][j]\)......