当前位置: 首页 > article >正文

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

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.kler.cn/a/291175.html

相关文章:

  • Clojure语言的正则表达式
  • Spring——依赖注入之p命名空间和c命名空间
  • 自动化构音障碍严重程度分类:基于声学特征与深度学习的研究 学习技术
  • 数据结构与算法之二叉树: LeetCode 543. 二叉树的直径 (Ts版)
  • SQL-leetcode-584. 寻找用户推荐人
  • django基于Python的智能停车管理系统
  • # Windows下配置Redis以服务方式启动
  • 创新大赛国赛路演:如何准备一份打动人心的路演稿
  • 数学建模笔记
  • 8月29日wpf
  • vue原理分析(四)Vue实例挂载到app上面
  • C++系列-STL容器的应用举例
  • AI自动生成PPT哪个软件好?如何自动生成专业级PPT?
  • 浙大数据结构:01-复杂度1 最大子列和问题
  • 解决el-table中使用el-input无法聚焦问题
  • OpenAI transcription API bad request
  • ubuntu20.04 colmap安装
  • 假期学习-- iOS runloop了解和使用
  • 【STM32】寄存器点灯
  • 比特币客户端和API
  • 日程安排组件DHTMLX Scheduler v7.1 - 支持RFC-5545格式
  • VSCode中多行文本的快速前后缩进
  • kitti深度估计数据集介绍
  • Python知识点:Python开发中,如何使用Git进行版本控制
  • WEB渗透Linux提权篇-可写文件提权
  • 集成电路学习:什么是MOSFET(MOS管)