学习threejs,使用Texture纹理贴图,测试repeat重复纹理贴图

news2025/4/7 17:25:09

👨‍⚕️ 主页: gis分享者
👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅!
👨‍⚕️ 收录于专栏:threejs gis工程师


文章目录

  • 一、🍀前言
    • 1.1 ☘️Texture 纹理贴图
      • 1.1.1 ☘️代码示例
      • 1.1.2 ☘️构造函数
      • 1.1.3 ☘️属性
      • 1.1.4 ☘️方法
  • 二、🍀使用Texture纹理贴图,测试repeat重复纹理贴图
    • 1. ☘️实现思路
    • 2. ☘️代码样例


一、🍀前言

本文详细介绍如何基于threejs在三维场景中使用Texture纹理贴图,测试repeat重复纹理贴图,亲测可用。希望能帮助到您。一起学习,加油!加油!

1.1 ☘️Texture 纹理贴图

Texture 创建一个纹理贴图,将其应用到一个表面,或者作为反射/折射贴图。

1.1.1 ☘️代码示例

const texture = new THREE.TextureLoader().load( "textures/water.jpg" );
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set( 4, 4 );

1.1.2 ☘️构造函数

Texture( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding )

1.1.3 ☘️属性

.id : Integer
只读 - 表示该纹理实例的唯一数字。

.isTexture : Boolean
只读标志,用于检查给定对象是否属于纹理类型。

.uuid : String
该对象实例的UUID。 这个值是自动分配的,因此不应当对其进行编辑。

.name : String
该对象的名称,可选,且无需唯一。默认值是一个空字符串。

.image : Image
一个图片对象,通常由TextureLoader.load方法创建。 该对象可以是被three.js所支持的任意图片(例如PNG、JPG、GIF、DDS)或视频(例如MP4、OGG/OGV)格式。

要使用视频来作为纹理贴图,你需要有一个正在播放的HTML5 Video元素来作为你纹理贴图的源图像, 并在视频播放时不断地更新这个纹理贴图。——VideoTexture 类会对此自动进行处理。

.mipmaps : Array
用户所给定的mipmap数组(可选)。

.mapping : number
图像将如何应用到物体(对象)上。默认值是THREE.UVMapping对象类型, 即UV坐标将被用于纹理映射。

.wrapS : number
这个值定义了纹理贴图在水平方向上将如何包裹,在UV映射中对应于U。

默认值是THREE.ClampToEdgeWrapping,即纹理边缘将被推到外部边缘的纹素。 其它的两个选项分别是THREE.RepeatWrapping和THREE.MirroredRepeatWrapping。

.wrapT : number
这个值定义了纹理贴图在垂直方向上将如何包裹,在UV映射中对应于V。

可以使用与 .wrapS : number相同的选项。

请注意:纹理中图像的平铺,仅有当图像大小(以像素为单位)为2的幂(2、4、8、16、32、64、128、256、512、1024、2048、……)时才起作用。 宽度、高度无需相等,但每个维度的长度必须都是2的幂。 这是WebGL中的限制,不是由three.js所限制的。

.magFilter : number
当一个纹素覆盖大于一个像素时,贴图将如何采样。默认值为THREE.LinearFilter, 它将获取四个最接近的纹素,并在他们之间进行双线性插值。 另一个选项是THREE.NearestFilter,它将使用最接近的纹素的值。

.minFilter : number
当一个纹素覆盖小于一个像素时,贴图将如何采样。默认值为THREE.LinearMipmapLinearFilter, 它将使用mipmapping以及三次线性滤镜。

.anisotropy : number
沿着轴,通过具有最高纹素密度的像素的样本数。 默认情况下,这个值为1。设置一个较高的值将会产生比基本的mipmap更清晰的效果,代价是需要使用更多纹理样本。 使用renderer.capabilities.getMaxAnisotropy() 来查询GPU中各向异性的最大有效值;这个值通常是2的幂。

.format : number
默认值为THREE.RGBAFormat。

.internalFormat : String
默认值是使用 .format 和 .type 的组合获得的。GPU 格式允许开发人员指定数据将如何存储在 GPU 上。

.type : number
这个值必须与.format相对应。默认值为THREE.UnsignedByteType, 它将会被用于绝大多数纹理格式。

.offset : Vector2
在 U 和 V 的每个方向上,纹理的单个重复从开始偏移多少。典型范围是 0.0 到 1.0。

以下纹理类型共享引擎中的第一个 uv 通道。偏移(和重复)设置根据以下优先级进行评估,然后由这些纹理共享:

color map
specular map
displacement map
normal map
bump map
roughness map
metalness map
alpha map
emissive map
clearcoat map
clearcoat normal map
clearcoat roughnessMap map

以下纹理类型共享引擎中的第二个 uv 通道。偏移(和重复)设置根据以下优先级进行评估,然后由这些纹理共享:

ao map
light map
.repeat : Vector2

纹理在 U 和 V 的每个方向上在整个表面上重复多少次。如果在任一方向上将 repeat 设置为大于 1,则相应的 Wrap 参数也应设置为 THREE.RepeatWrapping 或 THREE.MirroredRepeatWrapping 以实现所需的平铺影响。为纹理设置不同的重复值与 .offset 一样受到限制。

.rotation : number
纹理将围绕中心点旋转多少度,单位为弧度(rad)。正值为逆时针方向旋转,默认值为0。

.center : Vector2
旋转中心点。(0.5, 0.5)对应纹理的正中心。默认值为(0,0),即左下角。

.matrixAutoUpdate : Boolean
是否从纹理的.offset、.repeat、.rotation和.center属性更新纹理的UV变换矩阵(uv-transform .matrix)。 默认值为true。 如果你要直接指定纹理的变换矩阵,请将其设为false。

.matrix : Matrix3
纹理的UV变换矩阵。 当纹理的.matrixAutoUpdate属性为true时, 由渲染器从纹理的.offset、.repeat、.rotation和.center属性中进行更新。 当.matrixAutoUpdate属性为false时,该矩阵可以被手动设置。 默认值为单位矩阵。

.generateMipmaps : Boolean
是否为纹理生成mipmap(如果可用)。默认为true。 如果你手动生成mipmap,请将其设为false。

.premultiplyAlpha : Boolean
如果设置为 true,alpha 通道(如果存在)会在纹理上传到 GPU 时倍增到颜色通道中。默认为假。

请注意,此属性对 ImageBitmap 没有影响。您需要在创建位图时进行配置。

.flipY : Boolean
如果设置为 true,纹理在上传到 GPU 时沿垂直轴翻转。默认为真。

请注意,此属性对 ImageBitmap 没有影响。您需要在创建位图时进行配置。

.unpackAlignment : number
默认为4。指定内存中每个像素行起点的对齐要求。 允许的值为1(字节对齐)、2(行对齐到偶数字节)、4(字对齐)和8(行从双字边界开始)。

.encoding : number
默认值为THREE.LinearEncoding。

请注意,如果在材质被使用之后,纹理贴图中这个值发生了改变, 需要触发Material.needsUpdate,来使得这个值在着色器中实现。

.version : Integer
这个值起始值为0,计算 .needsUpdate : Boolean被设置为true的次数。

.onUpdate : Function
一个回调函数,在纹理被更新后调用。 (例如,当needsUpdate被设为true且纹理被使用。)

.needsUpdate : Boolean
将其设置为true,以便在下次使用纹理时触发一次更新。 这对于设置包裹模式尤其重要。

.userData : Object
可用于存储有关纹理的自定义数据的对象。它不应该包含对函数的引用,因为这些不会被克隆。

.source : Source
纹理的数据定义。可以跨纹理共享对数据源的引用。这在 spritesheet 的上下文中通常很有用,其中多个纹理渲染相同的数据但具有不同的纹理转换。

1.1.4 ☘️方法

EventDispatcher方法在这个类上可以使用。

.updateMatrix () : undefined
从纹理的.offset、.repeat、 .rotation和.center属性来更新纹理的UV变换矩阵(uv-transform .matrix)。

.clone () : Texture
拷贝纹理。请注意。这不是“深拷贝”,图像是共用的。 此外,克隆纹理不会自动将其标记为纹理上传。一旦其图像属性(数据源)完全加载或准备就绪,您必须将 Texture.needsUpdate 设置为 true。

.toJSON ( meta : Object ) : Object
meta – 可选,包含有元数据的对象。

将Texture对象转换为 three.js JSON Object/Scene format(three.js JSON 物体/场景格式)。

.dispose () : undefined
使用“废置”事件类型调用EventDispatcher.dispatchEvent。

.transformUv ( uv : Vector2 ) : Vector2
基于纹理的.offset、.repeat、 .wrapS、.wrapT和.flipY属性值来变换uv。

二、🍀使用Texture纹理贴图,测试repeat重复纹理贴图

1. ☘️实现思路

  • 1、初始化renderer渲染器。
  • 2、初始化Scene三维场景scene。
  • 3、初始化camera相机,定义相机位置 camera.position.set,设置相机方向camera.lookAt。
  • 4、创建THREE.AmbientLight环境光源ambiLight,创建DirectionalLight平行光源light,设置light位置,scene场景加入ambiLight和light。
  • 5、加载几何模型:定义createMesh方法(参数:geom 几何对象,texture 纹理贴图名称),方法内调用THREE.ImageUtils.loadTexture方法创建Texture纹理贴图texture,texture的wrapS和wrapT属性使用THREE.RepeatWrapping,使用THREE.MeshPhongMaterial高光材质mat,创建THREE.Mesh网格对象mesh,返回mesh。调用createMesh方法分别创建球体网格对象sphere和立方体网格对象cube,设置sphere、cube的位置,scene场景添加sphere和cube。定义controls方法,方法内定义gui控制项repeatX(x方向重复贴图数)、repeatY(y方向重复贴图数)和repeatWrapping(是否采用THREE.RepeatWrapping)以及updateRepeat方法(gui控制项变更更新方法)。定义render方法,实现sphere和mesh的旋转动画。具体代码参考下面代码样例。
  • 6、加入gui控制。加入stats监控器,监控帧数信息。

2. ☘️代码样例

<!DOCTYPE html>
<html>
<head>
    <title>学习threejs,使用Texture纹理贴图,测试repeat重复纹理贴图</title>
    <script type="text/javascript" src="../libs/three.js"></script>
    <script type="text/javascript" src="../libs/stats.js"></script>
    <script type="text/javascript" src="../libs/dat.gui.js"></script>
    <style>
        body {
            margin: 0;
            overflow: hidden;
        }
    </style>
</head>
<body>

<div id="Stats-output">
</div>
<div id="WebGL-output">
</div>

<!-- Js代码块 -->
<script type="text/javascript">

    // 初始化
    function init() {

        var stats = initStats();

        // 创建三维场景scene
        var scene = new THREE.Scene();

        // 创建相机
        var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);

        // 创建渲染器webGLRenderer,设置渲染器颜色和大小
        var webGLRenderer = new THREE.WebGLRenderer();
        webGLRenderer.setClearColor(new THREE.Color(0xEEEEEE, 1.0));
        webGLRenderer.setSize(window.innerWidth, window.innerHeight);
        webGLRenderer.shadowMapEnabled = true;

        var sphere = createMesh(new THREE.SphereGeometry(5, 20, 20), "floor-wood.jpg");
        scene.add(sphere);
        sphere.position.x = 7;

        var cube = createMesh(new THREE.BoxGeometry(6, 6, 6), "brick-wall.jpg");
        cube.position.x = -7;
        scene.add(cube);

        // 设置相机位置和方向
        camera.position.x = 00;
        camera.position.y = 12;
        camera.position.z = 20;
        camera.lookAt(new THREE.Vector3(0, 0, 0));

        var ambiLight = new THREE.AmbientLight(0x141414);
        scene.add(ambiLight);

        var light = new THREE.DirectionalLight();
        light.position.set(0, 30, 20);
        scene.add(light);

        // webGLRenderer渲染器绑定html页面要素
        document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement);

        var step = 0;

        var controls = new function () {
            this.repeatX = 1;
            this.repeatY = 1;
            this.repeatWrapping = true;

            this.updateRepeat = function (e) {

                cube.material.map.repeat.set(controls.repeatX, controls.repeatY);
                sphere.material.map.repeat.set(controls.repeatX, controls.repeatY);
				// 使用RepeatWrapping,纹理将简单地重复到无穷大。 使用 RepeatWrapping,纹理将简单地重复到无穷大。
				// ClampToEdgeWrapping是默认值,纹理中的最后一个像素将延伸到网格的边缘。
				//使用MirroredRepeatWrapping, 纹理将重复到无穷大,在每次重复时将进行镜像。
                if (controls.repeatWrapping) {
                    cube.material.map.wrapS = THREE.RepeatWrapping;
                    cube.material.map.wrapT = THREE.RepeatWrapping;
                    sphere.material.map.wrapS = THREE.RepeatWrapping;
                    sphere.material.map.wrapT = THREE.RepeatWrapping;
                } else {
                    cube.material.map.wrapS = THREE.ClampToEdgeWrapping;
                    cube.material.map.wrapT = THREE.ClampToEdgeWrapping;
                    sphere.material.map.wrapS = THREE.ClampToEdgeWrapping;
                    sphere.material.map.wrapT = THREE.ClampToEdgeWrapping;
                }

                cube.material.map.needsUpdate = true;
                sphere.material.map.needsUpdate = true;

            }
        };


        var gui = new dat.GUI();
        gui.add(controls, "repeatX", -4, 4).onChange(controls.updateRepeat);
        gui.add(controls, "repeatY", -4, 4).onChange(controls.updateRepeat);
        gui.add(controls, "repeatWrapping").onChange(controls.updateRepeat);


        render();

        function createMesh(geom, texture) {
            var texture = THREE.ImageUtils.loadTexture("../assets/textures/general/" + texture);
            texture.wrapS = THREE.RepeatWrapping;
            texture.wrapT = THREE.RepeatWrapping;

            geom.computeVertexNormals();
            var mat = new THREE.MeshPhongMaterial();
            mat.map = texture;
            var mesh = new THREE.Mesh(geom, mat);

            return mesh;
        }

        function render() {
            stats.update();
            step += 0.01;
            cube.rotation.y = step;
            cube.rotation.x = step;
            sphere.rotation.y = step;
            sphere.rotation.x = step;

            // render using requestAnimationFrame
            requestAnimationFrame(render);
            webGLRenderer.render(scene, camera);
        }

        function initStats() {

            var stats = new Stats();
            stats.setMode(0);

            stats.domElement.style.position = 'absolute';
            stats.domElement.style.left = '0px';
            stats.domElement.style.top = '0px';

            document.getElementById("Stats-output").appendChild(stats.domElement);

            return stats;
        }
    }
    window.onload = init;
</script>
</body>
</html>

效果如下:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2329974.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

蓝桥杯基础算法-字符串与集合

对集合的考察集中在集合的特性和功能。 set-唯一性 list-有序性 集合元素的个数 思路分析&#xff1a;set的唯一性&#xff0c;取出重复的子串 eg&#xff1a; 下标0截取的范围&#xff1a;【0&#xff0c;最大下标】 下标1截取的范围&#xff1a;【1&#xff0c;最大下标…

animals_classification动物分类

数据获取 深度学习训练中第一个是获取数据集&#xff0c;数据集的质量很重要&#xff0c;我们这里做的是动物分类&#xff0c;大致会选择几个动物&#xff0c;来做一个简单的多分类问题&#xff0c;数据获取的方法&#xff0c;鼠鼠我这里选择使用爬虫的方式来对数据进行爬取&a…

解决Oracle PL/SQL中“表或视图不存在“错误的完整指南

解决Oracle PL/SQL中"表或视图不存在"错误的完整指南 前言问题概述根本原因分析一、 编译时与运行时验证差异二、权限问题三、 Schema命名问题 实际案例演示案例1&#xff1a;动态分表查询案例2&#xff1a;权限不足的场景 实用排查步骤排查流程图最佳实践建议解决方…

SSH远程连接服务器(cursor)

安装Remote-SSH插件 Cursor是基于VSCode的&#xff0c;因此支持VSCode的Remote-SSH功能。打开Cursor&#xff0c;进入扩展市场&#xff08;左侧活动栏的“Extensions”图标&#xff09;。搜索“Remote - SSH”插件并安装&#xff08;由Microsoft提供&#xff09;。 配置SSH 在…

idea gitlab 操作

1.拉取脚本 账号登录 就可以获取git代码 2. 版本回退 hard暴力回退到暂存区 缓存区消失 3.版本合并 切换到目标分区 选择点击开发分区 进行合并

【MATLAB第113期】基于MATLAB的EFAST扩展傅里叶幅度敏感性分析方法(有目标函数)

【MATLAB第113期】基于MATLAB的EFAST扩展傅里叶幅度敏感性分析方法&#xff08;有目标函数&#xff09; 一、方法概述 扩展傅里叶幅度敏感性检验&#xff08;EFAST&#xff09;是一种基于频域分析的全局敏感性分析方法&#xff0c;能够同时评估模型参数的一阶敏感性&#xff…

Unity3D开发AI桌面精灵/宠物系列 【三】 语音识别 ASR 技术、语音转文本多平台 - 支持科大讯飞、百度等 C# 开发

Unity3D 交互式AI桌面宠物开发系列【三】ASR 语音识别 该系列主要介绍怎么制作AI桌面宠物的流程&#xff0c;我会从项目开始创建初期到最终可以和AI宠物进行交互为止&#xff0c;项目已经开发完成&#xff0c;我会仔细梳理一下流程&#xff0c;分步讲解。 这篇文章主要讲有关于…

Qt -信号与槽

博客主页&#xff1a;【夜泉_ly】 本文专栏&#xff1a;【暂无】 欢迎点赞&#x1f44d;收藏⭐关注❤️ 目录 前言引入connect调用链模板类型的connectQObject::connectImplQObjectPrivate::connectImpl qobject_p_p.hconnect作用总结ai对信号与槽的模拟实现 前言 面向对象&am…

Django中使用不同种类缓存的完整案例

Django中使用不同种类缓存的完整案例 推荐超级课程: 本地离线DeepSeek AI方案部署实战教程【完全版】Docker快速入门到精通Kubernetes入门到大师通关课AWS云服务快速入门实战目录 Django中使用不同种类缓存的完整案例步骤1:设置Django项目步骤2:设置URL路由步骤3:视图级别…

解锁健康密码,拥抱品质生活

在生活节奏不断加快的今天&#xff0c;健康养生已成为人们关注的焦点。它不仅关乎当下生活质量&#xff0c;更是对未来幸福的投资。从日常生活的点滴出发&#xff0c;掌握正确养生方法&#xff0c;我们就能轻松收获健康。​ 饮食是健康的基石。我们应当遵循 “食物多样&#x…

ABAP 新语法 - corresponding

在 ABAP 中&#xff0c;CORRESPONDING 操作符用于根据字段名称自动映射结构体&#xff08;Structure&#xff09;或内表&#xff08;Internal Table&#xff09;的字段值。它比传统的 MOVE-CORRESPONDING 语句更灵活&#xff0c;支持更多控制选项。 基础用法 data: begin of …

HTML零基础入门笔记:狂神版

前言 本笔记是学习狂神的java教程&#xff0c;建议配合视频&#xff0c;学习体验更佳。 【狂神说Java】HTML5完整教学通俗易懂_哔哩哔哩_bilibili 第1-2章&#xff1a;Java零基础入门笔记&#xff1a;(1-2)入门&#xff08;简介、基础知识&#xff09;-CSDN博客 第3章&…

FreeRTOS移植笔记:让操作系统在你的硬件上跑起来

一、为什么需要移植&#xff1f; FreeRTOS就像一套"操作系统积木"&#xff0c;但不同硬件平台&#xff08;如STM32、ESP32、AVR等&#xff09;的CPU架构和外设差异大&#xff0c;需要针对目标硬件做适配配置。移植工作就是让FreeRTOS能正确管理你的硬件资源。 二、…

c语言修炼秘籍 - - 禁(进)忌(阶)秘(技)术(巧)【第五式】动态内存管理

c语言修炼秘籍 - - 禁(进)忌(阶)秘(技)术(巧)【第五式】动态内存管理 【心法】 【第零章】c语言概述 【第一章】分支与循环语句 【第二章】函数 【第三章】数组 【第四章】操作符 【第五章】指针 【第六章】结构体 【第七章】const与c语言中一些错误代码 【禁忌秘术】 【第一式…

MySQL表的增删改查基础版

这一部分内容比较多&#xff0c;请大家结合目录查看&#x1f440; 增删改查 这一部分内容比较多&#xff0c;请大家结合目录查看&#x1f440; 一、新增1.插入2.指定列插入3.一次插入多行记录 二、查询1.全列查询2.指定列查询3.查询字段为表达式4.别名5.去重6.多列去重7.排序8.…

【备赛】蓝桥杯嵌入式实现led闪烁

原理 由于蓝桥杯的板子带有锁存器&#xff0c;并且与lcd屏幕有冲突&#xff0c;所以这个就成了考点。 主要就是用定时器来实现&#xff0c;同时也要兼顾lcd的冲突。 一、处理LCD函数 首先来解决与lcd屏幕冲突的问题&#xff0c;把我们所有用到的lcd函数改装一下。 以下是基…

【Python】贝叶斯,条件概率是怎么回事儿

【Python】贝叶斯&#xff0c;条件概率是怎么回事儿 一、原理简介1.1 贝叶斯定理1.2 朴素贝叶斯假设 二、算法实现过程2.1 数据准备与预处理2.2 模型训练与预测2.2.1 高斯朴素贝叶斯 - 对应连续型数据2.2.2 多项式朴素贝叶斯 - 离散型数据 2.3 模型评估 三、算法优缺点分析3.1 …

Flink介绍——实时计算核心论文之Storm论文详解

引入 我们通过以下两篇文章&#xff0c;深入探索了S4是如何抽象流式计算模型&#xff0c;如何设计架构和系统&#xff0c;存在那些局限&#xff1a; 论文详解论文总结 Yahoo推出的S4 并没有在历史舞台上站稳脚跟&#xff0c;在S4的论文发表的同一年&#xff0c;我们今天的主…

001 使用单片机实现的逻辑分析仪——吸收篇

本内容记录于韦东山老师的毕设级开源学习项目&#xff0c;含个人观点&#xff0c;请理性阅读。 个人笔记&#xff0c;没有套路&#xff0c;一步到位&#xff0c;欢迎交流&#xff01; 00单片机的逻辑分析仪与商业版FPGA的逻辑分析仪异同 对比维度自制STM32逻辑分析仪商业版逻…

11-产品经理-创建产品

在“产品”-“仪表盘”内&#xff0c;可以查看系统中关于产品及相关需求的统计。 在“产品”-“产品列表”页面&#xff0c;可以按项目集、项目查看其关联产品。还可以添加产品、编辑产品线、或者导出产品列表。 产品看板&#xff0c;通过看板方式查看产品、产品计划和产品下的…