可视化/数字孪生专业社区
资源中心
问答
文章
实用工具
ByteVCharts
开源中台
申请建模
申请帮助
登录
注册
申请协助
此单为
付费
协助
×
为协助帮威客用户快速入门,帮威客平台可损供用户特定项目的框架代码开发服务。该服务可为用户快速构建符合项目基本需求的3D可视化框架代码资源(包括源码、3D模型、贴图、数据等),用户的技术团队可在此基础上快速上手,大幅提高3D可视化项目成功基础。
预算金额
公司名称
联系人
微信号
手机号码
提交申请
申请协助
此单为
付费
协助
×
为协助帮威客用户快速入门,帮威客平台可损供用户特定项目的框架代码开发服务。该服务可为用户快速构建符合项目基本需求的3D可视化框架代码资源(包括源码、3D模型、贴图、数据等),用户的技术团队可在此基础上快速上手,大幅提高3D可视化项目成功基础。
预算金额
公司名称
联系人
微信号
手机号码
提交申请
业务咨询
开发咨询
微信咨询
杜老师
黄老师
熊老师
支付信息
×
购买文章
ThreeJs 使用法线贴图 (法向贴图)
订单金额
¥
0
实付金额
¥
0
我已阅读并同意ByteV组件购买协议
取消
提交订单
支付宝支付
微信支付
提交订单
0
点赞
0
评论
收藏
分享
举报
ThreeJs 使用法线贴图 (法向贴图)
Terry
关注
已关注
0
0
0
2631
发表于 2020-08-11 18:47:31
皮肤的皱纹,砖墙表面的凹凸,衣服的褶皱,树皮的纹路… 这些丰富的细节在计算机的3D世界中,最常用的展现方式就是法相贴图了。 对于高模来说,如果精度足够高,近似认为一个面就是一个点,那么将其贴图揭下就是一张图片。 这张高模贴图上的**每个点拥有一个法向量**,反应出高模上的细节。 对于低模来说,一个面对应高模中的很多个面,每个面看作是一面镜子,将其贴图揭下来就是一张很多三角形镜子拼接的图,**每个三角形内的所有点拥有相同的法向量**。 ![低模贴图示意图](https://img-blog.csdn.net/20180426133326038?watermark/2/text/Ly9ibG9nLmNzZG4ubmV0L3UwMTA2NjQyNDc=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast) ### []()[]()为什么需要法向贴图 因为面数量越大,需要计算的量和内存需求就越大,CPU的计算能力是有限的。要让低模也能体现出很多的光照细节,就有人想出赋予低模上的点对应高模上的的法向量,不就可以让低模看起来逼真生动了吗。 将这些法向量存在图片上每个点的rgb值中,让计算机在解析贴图的时候就可以读到每个点的法向量,这样的图片就叫作法向贴图。 ### []()[]()高模贴图的法线信息如何映射到低模贴图中 不用解释,高模贴图总面积肯定是比低模贴图的总面积大的,在做映射的时候,高模贴图就是一张凹凸不平的图了。 ![法向贴图示意图](https://img-blog.csdn.net/20180426133357781?watermark/2/text/Ly9ibG9nLmNzZG4ubmV0L3UwMTA2NjQyNDc=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)法向贴图示意图 想象一下,将高模贴图包住低模贴图,然后用针垂直于低模贴图插下去,针连接的高低贴图上的点就是对应点,将高模贴图上的点的x值存入r中,y值存入g中,z值存入b中,就完成了一个点的映射。 颜色的分量取值范围为0到1,而向量的分量取值范围是-1到1;可以建立从纹素到法线的简单映射: ``` normal = (2*color)-1 // on each component ``` 由于法线基本都是指向”曲面外侧”的(按照惯例,X轴朝右,Y轴朝上),因此得到的法相贴图看上去就是蓝紫色调。 ![法向贴图](https://img-blog.csdn.net/20180426133432974?watermark/2/text/Ly9ibG9nLmNzZG4ubmV0L3UwMTA2NjQyNDc=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast) ### []()[]()没有高模贴图怎么得到法向贴图 理论上讲,法向贴图离不开高模贴图和低模贴图,缺其一就不能得到一个正确的法向贴图。 但是,很多人都知道Photoshop的nVidia插件就可以生成diffuse贴图,并没有用到高模贴图,这是怎么回事呢? 其实,Photoshop的做法,是分析图片的亮度,越黑表示越深,越白表示越浅。这样的打开方式是不正确的。 更好的方式是根据特定规则将物体实际高低手动画成一张黑白的图片,再结合原图来制作diffuse贴图。 ![制作diffuse映射图](https://img-blog.csdn.net/20180426133500041?watermark/2/text/Ly9ibG9nLmNzZG4ubmV0L3UwMTA2NjQyNDc=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast) - 50%的灰色意思是高度不变(水平参考线)。 - 白色意思是最高的突起部分。 - 黑色表示最低的凹下部分。 ### []()[]()js代码怎么使用法向贴图 ```js hljs has-numbering var mesh, scene = new THREE.Scene(), textureLoader = new THREE.TextureLoader(); textureLoader.load( "./texture/cloud.png", function( texture ){ // 加载法向贴图 textureLoader.load("./texture/normal.png", function( normalTexture ){ var geometry = new THREE.BoxGeometry( 50, 50, 50 ); var material = new THREE.MeshPhongMaterial({ map: texture, normalMap: normalTexture // 只要将法向贴图赋给材质的normalMap属性即可 }); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); } ); }); mesh, scene = new THREE.Scene(), textureLoader = new THREE.TextureLoader(); textureLoader.load( "./texture/cloud.png", function( texture ){ // 加载法向贴图 textureLoader.load("./texture/normal.png", function( normalTexture ){ var geometry = new THREE.BoxGeometry( 50, 50, 50 ); var material = new THREE.MeshPhongMaterial({ map: texture, normalMap: normalTexture // 只要将法向贴图赋给材质的normalMap属性即可 }); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); } ); });new THREE.Scene(), textureLoader = new THREE.TextureLoader(); textureLoader.load( "./texture/cloud.png", function( texture ){ // 加载法向贴图 textureLoader.load("./texture/normal.png", function( normalTexture ){ var geometry = new THREE.BoxGeometry( 50, 50, 50 ); var material = new THREE.MeshPhongMaterial({ map: texture, normalMap: normalTexture // 只要将法向贴图赋给材质的normalMap属性即可 }); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); } ); }); THREE.Scene(), textureLoader = new THREE.TextureLoader(); textureLoader.load( "./texture/cloud.png", function( texture ){ // 加载法向贴图 textureLoader.load("./texture/normal.png", function( normalTexture ){ var geometry = new THREE.BoxGeometry( 50, 50, 50 ); var material = new THREE.MeshPhongMaterial({ map: texture, normalMap: normalTexture // 只要将法向贴图赋给材质的normalMap属性即可 }); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); } ); });new THREE.TextureLoader(); textureLoader.load( "./texture/cloud.png", function( texture ){ // 加载法向贴图 textureLoader.load("./texture/normal.png", function( normalTexture ){ var geometry = new THREE.BoxGeometry( 50, 50, 50 ); var material = new THREE.MeshPhongMaterial({ map: texture, normalMap: normalTexture // 只要将法向贴图赋给材质的normalMap属性即可 }); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); } ); }); THREE.TextureLoader(); textureLoader.load( "./texture/cloud.png", function( texture ){ // 加载法向贴图 textureLoader.load("./texture/normal.png", function( normalTexture ){ var geometry = new THREE.BoxGeometry( 50, 50, 50 ); var material = new THREE.MeshPhongMaterial({ map: texture, normalMap: normalTexture // 只要将法向贴图赋给材质的normalMap属性即可 }); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); } ); });"./texture/cloud.png", function( texture ){ // 加载法向贴图 textureLoader.load("./texture/normal.png", function( normalTexture ){ var geometry = new THREE.BoxGeometry( 50, 50, 50 ); var material = new THREE.MeshPhongMaterial({ map: texture, normalMap: normalTexture // 只要将法向贴图赋给材质的normalMap属性即可 }); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); } ); });, function( texture ){ // 加载法向贴图 textureLoader.load("./texture/normal.png", function( normalTexture ){ var geometry = new THREE.BoxGeometry( 50, 50, 50 ); var material = new THREE.MeshPhongMaterial({ map: texture, normalMap: normalTexture // 只要将法向贴图赋给材质的normalMap属性即可 }); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); } ); });function( texture ){ // 加载法向贴图 textureLoader.load("./texture/normal.png", function( normalTexture ){ var geometry = new THREE.BoxGeometry( 50, 50, 50 ); var material = new THREE.MeshPhongMaterial({ map: texture, normalMap: normalTexture // 只要将法向贴图赋给材质的normalMap属性即可 }); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); } ); }); // 加载法向贴图 textureLoader.load("./texture/normal.png", function( normalTexture ){ var geometry = new THREE.BoxGeometry( 50, 50, 50 ); var material = new THREE.MeshPhongMaterial({ map: texture, normalMap: normalTexture // 只要将法向贴图赋给材质的normalMap属性即可 }); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); } ); });// 加载法向贴图 textureLoader.load("./texture/normal.png", function( normalTexture ){ var geometry = new THREE.BoxGeometry( 50, 50, 50 ); var material = new THREE.MeshPhongMaterial({ map: texture, normalMap: normalTexture // 只要将法向贴图赋给材质的normalMap属性即可 }); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); } ); }); textureLoader.load("./texture/normal.png", function( normalTexture ){ var geometry = new THREE.BoxGeometry( 50, 50, 50 ); var material = new THREE.MeshPhongMaterial({ map: texture, normalMap: normalTexture // 只要将法向贴图赋给材质的normalMap属性即可 }); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); } ); });"./texture/normal.png", function( normalTexture ){ var geometry = new THREE.BoxGeometry( 50, 50, 50 ); var material = new THREE.MeshPhongMaterial({ map: texture, normalMap: normalTexture // 只要将法向贴图赋给材质的normalMap属性即可 }); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); } ); });, function( normalTexture ){ var geometry = new THREE.BoxGeometry( 50, 50, 50 ); var material = new THREE.MeshPhongMaterial({ map: texture, normalMap: normalTexture // 只要将法向贴图赋给材质的normalMap属性即可 }); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); } ); });function( normalTexture ){ var geometry = new THREE.BoxGeometry( 50, 50, 50 ); var material = new THREE.MeshPhongMaterial({ map: texture, normalMap: normalTexture // 只要将法向贴图赋给材质的normalMap属性即可 }); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); } ); }); var geometry = new THREE.BoxGeometry( 50, 50, 50 ); var material = new THREE.MeshPhongMaterial({ map: texture, normalMap: normalTexture // 只要将法向贴图赋给材质的normalMap属性即可 }); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); } ); });var geometry = new THREE.BoxGeometry( 50, 50, 50 ); var material = new THREE.MeshPhongMaterial({ map: texture, normalMap: normalTexture // 只要将法向贴图赋给材质的normalMap属性即可 }); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); } ); }); geometry = new THREE.BoxGeometry( 50, 50, 50 ); var material = new THREE.MeshPhongMaterial({ map: texture, normalMap: normalTexture // 只要将法向贴图赋给材质的normalMap属性即可 }); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); } ); });new THREE.BoxGeometry( 50, 50, 50 ); var material = new THREE.MeshPhongMaterial({ map: texture, normalMap: normalTexture // 只要将法向贴图赋给材质的normalMap属性即可 }); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); } ); }); THREE.BoxGeometry( 50, 50, 50 ); var material = new THREE.MeshPhongMaterial({ map: texture, normalMap: normalTexture // 只要将法向贴图赋给材质的normalMap属性即可 }); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); } ); });50, 50, 50 ); var material = new THREE.MeshPhongMaterial({ map: texture, normalMap: normalTexture // 只要将法向贴图赋给材质的normalMap属性即可 }); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); } ); });, 50, 50 ); var material = new THREE.MeshPhongMaterial({ map: texture, normalMap: normalTexture // 只要将法向贴图赋给材质的normalMap属性即可 }); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); } ); });50, 50 ); var material = new THREE.MeshPhongMaterial({ map: texture, normalMap: normalTexture // 只要将法向贴图赋给材质的normalMap属性即可 }); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); } ); });, 50 ); var material = new THREE.MeshPhongMaterial({ map: texture, normalMap: normalTexture // 只要将法向贴图赋给材质的normalMap属性即可 }); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); } ); });50 ); var material = new THREE.MeshPhongMaterial({ map: texture, normalMap: normalTexture // 只要将法向贴图赋给材质的normalMap属性即可 }); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); } ); }); ); var material = new THREE.MeshPhongMaterial({ map: texture, normalMap: normalTexture // 只要将法向贴图赋给材质的normalMap属性即可 }); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); } ); });var material = new THREE.MeshPhongMaterial({ map: texture, normalMap: normalTexture // 只要将法向贴图赋给材质的normalMap属性即可 }); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); } ); }); material = new THREE.MeshPhongMaterial({ map: texture, normalMap: normalTexture // 只要将法向贴图赋给材质的normalMap属性即可 }); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); } ); });new THREE.MeshPhongMaterial({ map: texture, normalMap: normalTexture // 只要将法向贴图赋给材质的normalMap属性即可 }); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); } ); }); THREE.MeshPhongMaterial({ map: texture, normalMap: normalTexture // 只要将法向贴图赋给材质的normalMap属性即可 }); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); } ); });// 只要将法向贴图赋给材质的normalMap属性即可 }); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); } ); }); }); mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); } ); });new THREE.Mesh( geometry, material ); scene.add( mesh ); } ); }); THREE.Mesh( geometry, material ); scene.add( mesh ); } ); }); ```
点击查看更多
全部评论
登录
|
注册
关于作者
Terry
TA的个人主页
关注
已关注
文章
52
粉丝
32
获赞
15
评论
8
访问
90472
ThreeJS 轮廓线特效 OutLinePath
创建海洋特效组件 THREEJS 海洋效果 Shader实现
ThreeJS后期处理通道
Three.js物理材质MeshStandardMaterial和MeshPhysicalMaterial
ThreeJs光效流转特效
推荐文章
ThreeJS 轮廓线特效 OutLinePath
(3)、React中使用ECharts——柱状图
31个惊艳的数据可视化作品,让你感受“数据之美”!
防抖节流
创建海洋特效组件 THREEJS 海洋效果 Shader实现
文章目录
文章分享
×
扫一扫分享
复制链接