3.js - modelPosition.z = sin((modelPosition.x+uTime)*10.0)*0.05;

news2024/12/28 21:38:42

1、完整的动态波纹效果吧

main.js
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'

// 顶点着色器
import basicVertexShader from './shader/11-01/raw/vertex.glsl?raw'
// 片元着色器
import basicFragmentShader from './shader/11-01/raw/fragment.glsl?raw'

const scene = new THREE.Scene()

const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 700)
camera.position.set(0, 0, 10)

// const axesHelper = new THREE.AxesHelper(5)
// scene.add(axesHelper)

// --------------------------------------------------------------------

/*
  宽度,
  高度,
  宽度分段数:它决定了平面在宽度方向上被分割成多少个小矩形(或更准确地说,是顶点网格的宽度分辨率)。
             更高的值会创建更平滑的曲线(虽然对于平面来说,这主要体现在边缘的圆形或平滑处理上,如果有的话),但也会增加渲染的顶点和面数。
  高度分段数:与宽度分段数类似,它决定了平面在高度方向上被分割成多少个小矩形。
*/
const planeGeometry = new THREE.PlaneGeometry(1, 1, 64, 64)

// 普通材质
const material = new THREE.MeshBasicMaterial({
  color: 0x00ff00
})

// 着色器材质
// const shaderMaterial = new THREE.ShaderMaterial({
//   vertexShader: `
//     void main(){
//       gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.0);
//     }
//   `,
//   fragmentShader: `
//     void main(){
//       gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);
//     }
//   `
// })

const textureLoader = new THREE.TextureLoader()
const texture = textureLoader.load('../public/assets/texture/ca.jpeg')

/*
  原始着色器材质,
*/
const rawShaderMaterial = new THREE.RawShaderMaterial({
	vertexShader: basicVertexShader, // 顶点着色器的GLSL代码(一个字符串)
	fragmentShader: basicFragmentShader, // 片元着色器的GLSL代码(一个字符串)
	side: THREE.DoubleSide,
	`uniforms:一个对象,包含了在着色器代码中使用的全局变量,这些变量可以在JS中设置,并在着色器中被访问和修改。`
	uniforms: {
		`uTime:用于在着色器中模拟时间,其value属性被初始化为0,但可以在JS中随时间更新,以在着色器中创建【动态效果】。`
		uTime: {
			value: 0
		},
		`uTexture:用于将纹理传递给着色器`
		uTexture: {
			// value: texture
			value: null
		}
	}
})

const plane = new THREE.Mesh(planeGeometry, rawShaderMaterial)
scene.add(plane)

// --------------------------------------------------------------------

const renderer = new THREE.WebGLRenderer({
	antialias: true
})
renderer.shadowMap.enabled = true
renderer.toneMapping = THREE.ReinhardToneMapping
renderer.toneMappingExposure = 1
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)

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

const clock = new THREE.Clock()
const render = () => {
	// 获取,自Clock对象创建以来,经过的秒数
	const elapsedTime = clock.getElapsedTime()
	// 色器中的uTime变量,就会随着时间的推移而更新
	rawShaderMaterial.uniforms.uTime.value = elapsedTime
	
	controls.update()
	requestAnimationFrame(render)
	renderer.render(scene, camera)
}
render()

window.addEventListener('resize', () => {
	// 重置相机的宽高比
	camera.aspect = window.innerWidth / window.innerHeight
	// 更新相机的投影矩阵
	camera.updateProjectionMatrix()
	// 重置渲染器的宽高比
	renderer.setSize(window.innerWidth, window.innerHeight)
	// 更新渲染器的像素比
	renderer.setPixelRatio(window.devicePixelRatio)
})

vertex.glsl
/*
  precision关键字:设置着色器中使用的浮点数精度为lowp(低精度),有助于在不影响视觉效果的情况下提高渲染性能
      precision lowp float;   // 后续,所有浮点数的精度,为lowp(低精度:-2^8 - 2^8)
      precision lowp mediump; // 后续,所有浮点数的精度,为mediump(中精度:-2^10 - 2^10)
      precision lowp highp;   // 后续,所有浮点数的精度,为highp(高精度:-2^16 - 2^16)*/
precision lowp float;

/*
  attribute:在顶点着色器中声明变量(在较新的GLSL版本中,attribute已经被in关键字所取代)
  vec3:一个数据类型,代表一个三维向量 */
attribute vec3 position;

attribute vec2 uv; // uv:每个顶点的纹理坐标(u, v)

// 模型空间 -> 世界空间 -> 观察空间 -> 裁剪空间,然后,最终映射到屏幕坐标上,这是渲染管线中的标准变换顺序
uniform mat4 modelMatrix; // modelMatrix模型矩阵:用于将顶点,从模型空间 -> 世界空间
uniform mat4 viewMatrix; // viewMatrix视图矩阵:用于将顶点,从世界空间 -> 观察空间
uniform mat4 projectionMatrix; // projectionMatrix投影矩阵:用于将顶点,从观察空间 -> 裁剪空间,并最终映射到屏幕坐标上

// 获取时间
uniform float uTime; // uTime:一个统一变量,用于传递时间信息,可以用于动画效果

varying vec2 vUv; // vUv:传递给片段着色器的纹理坐标

varying float vElevation;

void main() {
  // 将输入的纹理坐标传递给片段着色器
  vUv = uv;

  // 顶点着色器处理的每个顶点,都有一个位置(position),这个位置是一个三维向量(vec3),包含x、y、z三个坐标

  // 用于,将顶点的位置,从模型空间啊 -> 世界空间
  vec4 modelPosition = modelMatrix*vec4(position, 1.0);

  // modelPosition.x += 1.0;
  // modelPosition.z += 1.0;
  // modelPosition.z += modelPosition.x;

 `
    1、
      通过,正弦函数sin,动态的调整,顶点的z坐标,创建一种基于时间和顶点位置的波动效果
      乘以0.05:基于顶点x坐标和时间的正弦波值,并将其幅度缩放为原始值的5%,
      意味着,
      随着uTime(时间)的增加,顶点的z坐标,将根据其在x轴上的位置以正弦波的形式变化。
    2、
      sin((modelPosition.x + uTime) * 10.0),为什么乘以10呢?
      因为,正弦函数sin的周期是2π,
      意味着,它完成一个完整的波形(从0到1,再到0)需要2π个单位
      但是,
      对(modelPosition.x + uTime)乘以10之后,
      实际上,是在对,正弦函数sin的周期,进行缩放,
      使得原本需要2π单位才能完成的波形,现在只需要(2π / 10) = 0.2π单位,就能完成一次完整的周期,
      所以,乘以10.0,
      意味着,
      波形在相同的空间或时间范围内,完成了更多的周期,从而增加了波形的频率`
  modelPosition.z = sin((modelPosition.x+uTime)*10.0)*0.05;
  modelPosition.z += sin((modelPosition.y+uTime)*10.0)*0.05;

  vElevation = modelPosition.z; // 将调整后的z值传递给片段着色器 

  `计算顶点在裁剪空间中的位置,gl_Position,是GLSL内置的输出变量,用于存储顶点的最终位置`
  gl_Position = projectionMatrix*viewMatrix*modelPosition;
}

fragment.glsl
precision lowp float; // 设置着色器中使用的浮点数精度为lowp(低精度),有助于在不影响视觉效果的情况下提高渲染性能

varying vec2 vUv; // 顶点着色器传过来的,表示,每个片段(像素)在纹理图像上的UV坐标

varying float vElevation; // 顶点着色器传过来的,表示,每个顶点的高度信息,这里用它来影响片段的颜色

uniform sampler2D uTexture; // 这是一个统一变量,指向一个二维纹理图像

void main() {
	// gl_FragColor = vec4(vUv, 0.0, 1.0);
	// float height = vElevation + 0.05 * 10.0;
	// gl_FragColor = vec4(1.0*height,0.0, 0.0, 1.0);
	
	/* 使用texture2D()函数,根据UV坐标,从uTexture纹理中采样颜色,
	   texture2D()函数,返回的是一个包含RGBA四个分量的vec4向量。 */
	vec4 textureColor = texture2D(uTexture, vUv);
	
	// 根据UV,取出对应的颜色
	float height = vElevation+(0.05*20.0); `将顶点的高度vElevation,增加了一个固定值`
	
	`将采样得到的纹理颜色(仅RGB部分)与计算出的高度值相乘,
	    意味着,
	    高度越高,纹理颜色会越亮(或越深,取决于纹理颜色的初始亮度)
	    这是一个简单的,颜色调制过程,
	    用于,根据高度信息,改变纹理的视觉效果。`
	textureColor.rgb *= height;
	
	
	`gl_FragColor:这是GLSL内置的输出变量,用于存储片元的最终颜色,将用于渲染到屏幕上`
	gl_FragColor = textureColor;
}


效果图(图是动态的)

在这里插入图片描述







2、modelPosition.z = sin((modelPosition.x+uTime)*10.0)*0.05;

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

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

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

相关文章

python OpenGL绘制正八面体代码

学习OpenGL过程中,先从绘制三角形开始逐渐对Opengl有一些了解,到现在进阶到绘制立方体。通过借鉴网友绘制六面体得到灵感,改了一下他的代码成功绘制出正八面体。不管是绘制三角形还是绘制立方体,对于空间坐标系要相当熟悉&#xf…

苍穹外卖项目前端DAY03

前端DAY03 1、套餐管理 1.1、套餐分页查询 1.1.1、需求分析和接口设计 产品原型: 业务规则: 根据页码展示套餐信息每页展示10条数据分页查询时可以根据需要,输入套餐名称、套餐分类、售卖状态进行查询 接口设计: 套餐分页查…

如何使用电商API接口?(淘宝|京东商品详情数据接口)

一、了解电商API接口: 如今,在电商市场中,电商API接口的广泛应用极大地提高了电商行业的工作效率,使得商家能够灵活集成多种服务,高效优化业务流程。 当前,电商平台中的多种业务都可以通过使用API接口来做…

Tomato靶场渗透测试

1.扫描靶机地址 可以使用nmap进行扫描 由于我这已经知道靶机地址 这里就不扫描了 2.打开网站 3.进行目录扫描 dirb http://172.16.1.113 发现有一个antibot_image目录 4.访问这个目录 可以看到有一个info.php 5.查看页面源代码 可以发现可以进行get传参 6.…

脉脉高聘:大模型算法岗平均月薪近7万元,位居高薪榜第一

9月5日,脉脉高聘人才智库数据显示,大模型领域整体供需比1.76,整体供大于求。同时,高技术岗位人才稀缺,云计算人才供需比仅为0.33,相当于3个岗位争夺1个人才。大模型算法岗位平均月薪最高,超过6.…

【STM32+HAL库】---- 驱动MAX30102心率血氧传感器

硬件开发板:STM32F407VET6 软件平台:cubemaxkeilVScode1 MAX30102心率血氧传感器工作原理 MAX30102传感器是一种集成了红外光源、光电检测器和信号处理电路的高度集成传感器,主要用于心率和血氧饱和度的测量。以下是MAX30102传感器的主要特点…

草料二维码功能上新!可以跨分区移动或复制内容了!

支持将 分区 下的内容移动或复制到其他分区。适用于将原初始分区下的内容按业务划分,移动到其他分区。或者当物品流转或业务变更时,可以及时将码及数据移动到对应分区,移动后,二维码图案不会发生变化。 目前仅表单、活码、批量模…

在修改文件 /ect/hosts时无法保存 can‘t open file for writing

输入:q! 即可 情境: 在Master节点中执行如下命令打开并修改Master节点中的“/etc/hosts”文件: sudo vim /etc/hosts 可以在hosts文件中增加如下两条IP和主机名映射关系: 192.168.1.121 Master 192.168.1.122 Slave1

解决App推广痛点:一键获取下载数据的秘诀

在App推广的过程中,获取准确的下载数据一直是一个令人头疼的问题。你知道吗?无法精确追踪用户来源和下载量,就像是在黑暗中摸索,让推广效果大打折扣。今天,我们就来揭秘如何轻松获取App下载数据,优化你的推…

BaseThreadStart代码分析

BaseThreadStart代码分析 第一部分: ​​​​​​​ 在调用CreateThead创建线程的时候,操作系统会为新线程创建线程内核对想象, 线程内核对象包含了线程的上下文(是一个C O N T E X T结构)以及一些其他属性和统计信息&…

计算机毕业设计 | SSM停车场管理系统(附源码)

1, 概述 1.1 课题背景 随着社会的快速发展,计算机的影响是全面且深入的。人们的生活水平不断提高,日常生活中用户对停车场管理系统方面的要求也在不断提高,需要的人数更是不断增加,使得停车场管理系统的开发成为必需…

【HarmonyOS】安装包报错,code:9568282 error: install releaseType target not same.

【HarmonyOS】安装包报错,code:9568282 error: install releaseType target not same. 报错信息 Install Failed: error: failed to install bundle. code:9568282 error: install releaseType target not same. You can also uninstall and reinstall the module…

使用Python读取Excel数据

目录 使用Python读取Excel数据 安装必要的库 读取Excel文件 基本步骤 代码案例 解释 其他常用操作 选择特定列 筛选数据 数据清洗 总结 使用Python读取Excel数据 在日常的数据处理工作中,Excel文件是非常常见的一种数据格式。Python提供了多种库来读取和…

SprinBoot+Vue新生报到微信小程序的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 application.yml3.5 SpringbootApplication3.5 Vue3.6 uniapp代码 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍:CSDN认证博客专家,CSDN平…

java重点学习-mybatis

4.1 MyBatis执行流程 ① 读取MyBatis配置文件:mybatis-config.xml加载运行环境和映射文件② 构造会话工厂SqlSessionFactory③ 会话工厂创建SqlSession对象(包含了执行SQL语句的所有方法)④ 操作数据库的接口,Executor执行器,同时负责查询缓存的维护⑤E…

人、货、场巨变,5G人工智能时代新的创业机会在哪?

随着5G元年的开启,人工智能的潜力被进一步激发,"人工智能"广泛应用于教育、无人驾驶、金融、银行、医疗、工业等领域,成为中国新的经济增长引擎,促进中国经济火爆增长。不仅促进了中国消费者的购买力,更萌发…

亚马逊卖家测评为什么要自己养账号呢?不懂快进来看看

亚马逊上的卖家为啥要自己养账号呢?咱们来聊聊这个事儿。 亚马逊特别看重用户的体验,所以买家的评论和打分对店铺的排名影响很大。平台对评论的审核很严格,这些评论直接关系到商品在平台上的表现和销量。 在亚马逊上,买家的评分和…

汽车制造商设备运维案例

汽车产线有很多传动设备需要长期在线运行,会出现老化、疲劳、磨损等问题,为了避免意外停机造成损失,需要加装一些健康监测设备,监测设备运行状态。天津三石峰科技采用无线温振传感器汇聚网关方案,将现场设备数据数据上…

springboot项目实现分库

本文是根据仓库编码 和 仓库id进行按仓库进行分库处理,可以根据例子自行按照业务需要进行分库 1.核心是实现 Spring 的 AbstractRoutingDataSource 抽象类,重写 determineCurrentLookupKey 方法,实现动态数据源的目的 @Slf4j public class DynamicDataSource extends Abst…

佳明运动相机SD存储卡被格式化?教你有效恢复数据的方法

在日常使用佳明运动相机的过程中,‌我们可能会不小心将SD存储卡格式化,‌导致珍贵的照片和视频数据丢失。‌面对这种情况,‌很多用户都感到十分焦虑和无助。‌但幸运的是,‌通过一些有效的方法,‌我们仍然有可能恢复这…