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

07.three官方示例+编辑器+AI快速学习webgl_buffergeometry_attributes_integer

本实例主要讲解内容

这个Three.js示例展示了WebGL 2环境下的整数属性渲染技术。通过创建大量随机分布的三角形,并为每个三角形分配不同的整数索引,实现了基于索引动态选择纹理的效果。

核心技术包括:

  • WebGL 2环境下的整数属性支持
  • 顶点着色器与片段着色器中的整数变量传递
  • 多纹理动态切换
  • 几何体与材质的自定义着色器实现

在这里插入图片描述

完整代码注释

<!DOCTYPE html>
<html lang="en"><head><title>three.js WebGL 2 - buffergeometry - integer attributes</title><meta charset="utf-8"><meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"><link type="text/css" rel="stylesheet" href="main.css"></head><body><div id="container"></div><div id="info"><a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> WebGL 2 - buffergeometry - integer attributes</div><script type="importmap">{"imports": {"three": "../build/three.module.js","three/addons/": "./jsm/"}}</script><script type="module">import * as THREE from 'three';let camera, scene, renderer, mesh;init();function init() {// 初始化相机camera = new THREE.PerspectiveCamera( 27, window.innerWidth / window.innerHeight, 1, 3500 );camera.position.z = 2500;// 初始化场景scene = new THREE.Scene();scene.background = new THREE.Color( 0x050505 );scene.fog = new THREE.Fog( 0x050505, 2000, 3500 );// 创建几何体const triangles = 10000; // 三角形数量const geometry = new THREE.BufferGeometry();// 存储顶点位置、UV坐标和纹理索引const positions = [];const uvs = [];const textureIndices = [];// 三角形分布范围和大小const n = 800, n2 = n / 2; // 三角形分布的立方体范围const d = 50, d2 = d / 2; // 单个三角形的大小// 生成随机三角形for ( let i = 0; i < triangles; i ++ ) {// 随机位置const x = Math.random() * n - n2;const y = Math.random() * n - n2;const z = Math.random() * n - n2;// 三角形的三个顶点const ax = x + Math.random() * d - d2;const ay = y + Math.random() * d - d2;const az = z + Math.random() * d - d2;const bx = x + Math.random() * d - d2;const by = y + Math.random() * d - d2;const bz = z + Math.random() * d - d2;const cx = x + Math.random() * d - d2;const cy = y + Math.random() * d - d2;const cz = z + Math.random() * d - d2;// 添加顶点位置positions.push( ax, ay, az );positions.push( bx, by, bz );positions.push( cx, cy, cz );// 添加UV坐标uvs.push( 0, 0 );uvs.push( 0.5, 1 );uvs.push( 1, 0 );// 添加纹理索引(0,1,2 循环)const t = i % 3;textureIndices.push( t, t, t );}// 设置几何体属性geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( positions, 3 ) );geometry.setAttribute( 'uv', new THREE.Float32BufferAttribute( uvs, 2 ) );geometry.setAttribute( 'textureIndex', new THREE.Int16BufferAttribute( textureIndices, 1 ) );geometry.attributes.textureIndex.gpuType = THREE.IntType; // 指定GPU使用整数类型geometry.computeBoundingSphere(); // 计算边界球体// 加载纹理const loader = new THREE.TextureLoader();const map1 = loader.load( 'textures/crate.gif' );const map2 = loader.load( 'textures/floors/FloorsCheckerboard_S_Diffuse.jpg' );const map3 = loader.load( 'textures/terrain/grasslight-big.jpg' );// 创建自定义着色器材质const material = new THREE.ShaderMaterial( {uniforms: {uTextures: {value: [ map1, map2, map3 ] // 纹理数组}},vertexShader: /* glsl */`in int textureIndex; // 从几何体传入的纹理索引(整数)flat out int vIndex; // "flat" 表示不进行插值(整数属性必须)out vec2 vUv; // UV坐标void main()	{vIndex = textureIndex;vUv = uv;gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );}`,fragmentShader: /* glsl */`flat in int vIndex; // 从顶点着色器传入的纹理索引in vec2 vUv; // UV坐标uniform sampler2D uTextures[ 3 ]; // 纹理数组out vec4 outColor; // 输出颜色void main()	{// 根据索引选择不同的纹理if ( vIndex == 0 ) outColor = texture( uTextures[ 0 ], vUv );else if ( vIndex == 1 ) outColor = texture( uTextures[ 1 ], vUv );else if ( vIndex == 2 ) outColor = texture( uTextures[ 2 ], vUv );}`,side: THREE.DoubleSide, // 双面渲染glslVersion: THREE.GLSL3 // 使用GLSL 3.0} );// 创建网格并添加到场景mesh = new THREE.Mesh( geometry, material );scene.add( mesh );// 初始化渲染器(必须支持WebGL 2)renderer = new THREE.WebGLRenderer( { antialias: true } );renderer.setPixelRatio( window.devicePixelRatio );renderer.setSize( window.innerWidth, window.innerHeight );renderer.setAnimationLoop( animate );document.body.appendChild( renderer.domElement );}// 动画循环function animate() {const time = Date.now() * 0.001;// 旋转网格mesh.rotation.x = time * 0.25;mesh.rotation.y = time * 0.5;renderer.render( scene, camera );}</script></body>
</html>

WebGL 2整数属性技术解析

WebGL 2与整数属性

WebGL 2相比WebGL 1提供了更强大的功能,包括对整数数据类型的直接支持:

  1. 整数顶点属性:WebGL 2允许在顶点着色器中使用整数类型的属性,这在WebGL 1中是受限的
  2. 更高的精度:支持16位和32位整数,提供更精确的数据表示
  3. 更高效的数据传输:整数数据可以更高效地从CPU传输到GPU
  4. 简化的着色器逻辑:避免了在WebGL 1中需要将整数编码为浮点数的复杂操作

在本示例中,我们使用了Int16BufferAttributeTHREE.IntType来定义和指定整数属性。

顶点着色器与片段着色器通信

在着色器编程中,数据从顶点着色器传递到片段着色器需要特别注意:

  1. 插值行为:默认情况下,顶点着色器输出的变量会在光栅化阶段进行插值,这对于浮点数是合适的,但对于整数会导致错误
  2. flat限定符:使用flat限定符可以禁止插值,确保每个片段接收到的是顶点的原始整数值
  3. 数据类型匹配:顶点着色器和片段着色器中的变量类型必须严格匹配

在本示例中,我们使用了flat out int vIndexflat in int vIndex来确保整数数据正确传递。

多纹理动态选择

本示例展示了如何基于整数属性动态选择不同的纹理:

  1. 纹理数组:在着色器中定义uniform sampler2D uTextures[3]来存储多个纹理
  2. 条件判断:在片段着色器中使用if-else语句根据整数索引选择相应的纹理
  3. 高效切换:通过整数索引直接访问纹理数组,避免了使用多个材质的开销

这种技术在需要大量不同纹理的场景中非常有用,比如地形渲染、角色换装系统等。

性能优化考虑

使用整数属性和自定义着色器时,需要注意以下几点:

  1. 数据类型选择:根据实际需求选择合适的整数类型(Byte, Short, Int),避免浪费GPU内存
  2. 批处理:将多个具有相同材质的对象合并为一个,减少Draw Call
  3. 纹理管理:确保纹理尺寸合理,并考虑使用纹理图集(Texture Atlas)减少纹理切换
  4. 着色器复杂度:避免在片段着色器中使用复杂的条件判断,可能影响性能

这种技术适用于需要在单个几何体上应用多种纹理或材质属性的场景,通过减少材质和Draw Call数量来提高渲染性能。

http://www.xdnf.cn/news/390313.html

相关文章:

  • Python-UV多环境管理
  • 5G-A来了!5G信号多个A带来哪些改变?
  • 经典音乐播放器——完美歌词 Poweramp Music Player 3 build
  • MyBatis进阶:掌握动态SQL,实现灵活的数据库查询
  • 实战项目5(08)
  • 【网络安全】——大端序(Big-Endian)​​和​​小端序(Little-Endian)
  • 【Linux系列】bash_profile 与 zshrc 的编辑与加载
  • 大语言模型通过MCP控制STM32-支持Ollama、DeepSeek、openai等
  • 大模型在肾肿瘤诊疗全流程预测及方案制定中的应用研究
  • 【英语笔记(三)】介绍谓语动词的分类,初步讲解四种基本状态:一般、进行、完成、完成进行
  • C#游戏开发中的注意事项
  • 淘宝19块钱激光雷达SDK转ROS2架构
  • 低代码开发:开启软件开发的新篇章
  • RAID磁盘阵列的概念(自用留档)
  • Redis BigKey 问题是什么
  • 卷积神经网络-从零开始构建一个卷积神经网络
  • PDF2zh插件在zotero中安装并使用
  • FramePack AI图片生成视频 v1.1 整合包
  • c++STL-string的使用
  • Java面试常见技术问题解析
  • 软考冲刺——案例分析题Super VLAN
  • BGP基础配置实验
  • OceanBase性能关键参数配置最佳实践
  • 5.1.1 WPF中Command使用介绍
  • 菜鸟之路day31一一MySQL之多表设计
  • windows怎么修改DNS
  • Bash 字符串语法糖详解
  • Kubernetes 集群部署应用
  • Web 性能优化三:页面首屏加载优化全流程:从服务器到骨架屏
  • Model Context Protocol(MCP)入门