Unity中Shader法线贴图(上)

news2024/9/24 15:23:56

文章目录

  • 前言
  • 一、法线纹理的作用
  • 二、为什么法线贴图长这样?(蓝色)
  • 三、法线贴图能使纹理采样时,进行偏移采样
  • 四、在Shader中使用法线贴图
    • 1、在属性面板定义一个变量来接收法线贴图
    • 2、在使用前声明 _NormalTex
    • 3、在片元着色器中,对法线贴图进行纹理采样使用
    • 4、法线贴图采样后,用来替换Lermbert光照模型中的法线
    • 5、把模型换成方块,会发现一个Bug


前言

Unity中Shader法线贴图


一、法线纹理的作用

为了给几何物体添加细节

在这里插入图片描述
如果不使用法线贴图,我们在做一些凹凸不平的模型时,就需要在建模的时候,给模型建出凹凸不平的效果。但是,这样的话,就需要很多的面来达到效果,这是极其消耗性能的。


二、为什么法线贴图长这样?(蓝色)

在这里插入图片描述

  • 法线贴图是模拟几何表面的空间感的信息
  • 即储存的是 xyz 三个轴向上的偏移数据
  • 而z轴表示的就是几何表面的高度信息
  • 当存储成一张贴图时会将 xyz 变换为 RGB
  • 而 xyz 的取值范围是(-1,1)
  • 所以需要使用简单的算法 xyz * 0.5 + 0.5 来变换到 (0,1) 间
  • 通常情况下 xyz = (0,0,1) 转化为 RGB = (0.5,0.5,1)

RGB = (0.5,0.5,1) 时,的颜色如下:
在这里插入图片描述


三、法线贴图能使纹理采样时,进行偏移采样

在这里插入图片描述


四、在Shader中使用法线贴图

我们继续使用上一篇文章的Shader来继续测试

  • Unity中Shader立方体纹理Cubemap

1、在属性面板定义一个变量来接收法线贴图

[Normal]_NormalTex(“NormalTex”,2D) = “bump” {}

  • [Normal]:专门用来限制纹理类型的,当纹理类型不是法线贴图时,会给出警告
  • “bump” : 默认的法线贴图颜色

这是我用来测试的法线贴图:
在这里插入图片描述

2、在使用前声明 _NormalTex

sampler2D _NormalTex;

3、在片元着色器中,对法线贴图进行纹理采样使用

fixed3 normalTex = UnpackNormal(tex2D(_NormalTex,i.uv));

  • UnpackNormal(half4 XX);该函数用来对法线贴图采样后,进行转化处理。

这里输出看一下效果

请添加图片描述

4、法线贴图采样后,用来替换Lermbert光照模型中的法线

  • Unity中Shader的Lambert光照的实现

//法线纹理
fixed3 normalTex = UnpackNormal(tex2D(_NormalTex,i.uv));
//max(0,dot(N,L))
fixed3 N1 = normalize(normalTex);
fixed3 L = _WorldSpaceLightPos0.xyz;
return max(0,dot(N1,L));

看一下现在的效果:(已经可以受光照的影响了)

请添加图片描述
测试代码:

//纹理的多级渐远 Mipmap
//纹理的环绕方式
Shader "MyShader/P2_1_6"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        
        [KeywordEnum (Repeat,Clamp)]_WrapMode("WrapMode",int) = 0
        [IntRange]_Mipmap ("Mipmap",Range(0,10)) = 0
        
        //法线贴图
        [Normal]_NormalTex("NormalTex",2D) = "bump" {}
        //在属性面板定义立方体纹理
        _CubeMap("CubeMap",Cube) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma shader_feature _WRAPMODE_REPEAT _WRAPMODE_CLAMP
            #include "UnityCG.cginc"
            
            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                half3 normal : NORMAL;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                float3 localPos : TEXCOORD1;
                float3 worldPos : TEXCOORD2;
                half3 worldNormal : NORMAL;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            half _Mipmap;
            samplerCUBE _CubeMap;
            sampler2D _NormalTex;
            v2f vert (appdata v)
            {
                v2f o;
                
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                o.localPos = v.vertex.xyz;
                o.worldPos = mul(unity_ObjectToWorld,v.vertex);
                o.worldNormal = UnityObjectToWorldNormal(v.normal);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                //WrapMode
                #if _WRAPMODE_REPEAT
                i.uv = frac(i.uv);
                #elif _WRAPMODE_CLAMP
                    //法一:
                    //i.uv = clamp(i.uv,0,1);
                    //法二:
                    i.uv = saturate(i.uv);
                #endif
                float4 uvMipmap = fixed4(i.uv,0,_Mipmap);
                fixed4 col = tex2Dlod(_MainTex, uvMipmap);

                //法线纹理
                fixed3 normalTex = UnpackNormal(tex2D(_NormalTex,i.uv));
                //max(0,dot(N,L))
                fixed3 N1 = normalize(normalTex);
                fixed3 L = _WorldSpaceLightPos0.xyz;
                return max(0,dot(N1,L));
                
                
                return fixed4(normalTex,1);
                
                //CubeMap
                fixed4 cubemap = texCUBE(_CubeMap,i.localPos);
                //V,N,R
                fixed3 V = normalize(i.worldPos - _WorldSpaceCameraPos);
                fixed3 N = normalize(i.worldNormal);
                fixed3 R = reflect(V,N);
                cubemap = texCUBE(_CubeMap,R);
                
                return cubemap;
                
                return col;
            }
            ENDCG
        }
    }
}

5、把模型换成方块,会发现一个Bug

部分面,是符合法线贴图的凹凸的,但是部分面,会与法线贴图的凹凸完全相反
原因:这里采样没有使用法线纹理的坐标,即切线坐标,这个Bug在下篇文章解决

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

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

相关文章

git使用及常用命令

在初入公司中,若使用的是git管理工具,需要做以下步骤: 1,常用命令在: (1),git config --global user.name xxx(名字) //若不设置 那么下次提交代码时会报错 其次该设置名字和…

华为模拟器dhcp实验

实验需求,pc1 pc2 pc3 获取到地址且能ping通,pc1 pc2 为地址池模式,pc3为接口模式 上配置 #sysname AR1# dhcp enable # interface GigabitEthernet0/0/0ip address 10.0.47.254 255.255.255.0 dhcp select relaydhcp relay server-ip 10.0…

李宏毅2023机器学习作业HW05解析和代码分享

ML2023Spring - HW5 相关信息: 课程主页 课程视频 Sample code HW05 视频 HW05 PDF 个人完整代码分享: GitHub | Gitee | GitCode 运行日志记录: wandb P.S. HW05/06 是在 Judgeboi 上提交的,完全遵循 hint 就可以达到预期效果。 因为无法在 Judgeboi 上…

windows上安装MySQL Server.

进入官网 MySQL 找到 下载,并点进入。 往下翻,找到社区下载,进入页面 选择 Mysql community Server 选择系统,下载 之后解压。 将解压文件夹下的bin路径添加到变量值中 配置初始化的my.ini文件 [mysqld] # 设置3306端口 port330…

YOLOv5 学习记录

文章目录 整体概况数据增强与前处理自适应Anchor的计算Lettorbox 架构SiLU激活函数YOLOv5改进点SSPF 模块 正负样本匹配损失函数 整体概况 YOLOv5 是一个基于 Anchor 的单阶段目标检测,其主要分为以下 5 个阶段: 1、输入端:Mosaic 数据增强、…

Parity Game——种类并查集、权值并查集、离散化

题目描述 思路 怎么得到这个序列中每一段的关系? 我们可以把这个只包含0和1的序列看作一个数组,0表示当前位置为0,1表示当前位置为1,利用前缀和的性质可以知道某一段中所包含的1的数量sum1 a[r] - a[l-1] 如果sum1为偶数&…

【0到1学习Unity脚本编程】第一人称视角的角色控制器

👨‍💻个人主页:元宇宙-秩沅 👨‍💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍💻 本文由 秩沅 原创 👨‍💻 收录于专栏:【0…

深信服AC流量管理技术

拓扑图 一.保证通道针对修仙部,访问网站,邮件,DNS,IM,办工 OA,微博论坛网上银行等常见应用保证带宽最低 50%,最高 100% 1. 先新建线路带宽 2.新增流量管理通道(保证关键应用&#x…

吾爱破解置顶的“太极”,太好用了吧!

日常工作和娱乐,都需要用到不同类型的软件,哪怕软件体积不大,也必须安装,否则到用时找不到就非常麻烦了。 其实,很多软件不一定一样不剩地全部安装一遍,一方面原因是用的不多,另一方面多少有点…

安装第三方包报错 error: Microsoft Visual C++ 14.0 or greater is required——解决办法

1、问题描述 手动安装第三方软件时,可以使用setup.py,来安装已经下载的第三方包。一般文件下会存在setup,在所要安装库的目录下的cmd执行:python setup.py install报错:error: Microsoft Visual C 14.0 or greater i…

【LeetCode】二叉树OJ

目录 一、根据二叉树创建字符串 二、二叉树的层序遍历 三、二叉树的层序遍历 II 四、二叉树的最近公共祖先 五、二叉搜索树与双向链表 六、从前序与中序遍历序列构造二叉树 七、从中序与后序遍历序列构造二叉树 一、根据二叉树创建字符串 606. 根据二叉树创建字符串 - …

window上Clion配置C++版本的opencv

window上Clion配置opencv 注意版本一定要对的上,否则可能会出错,亲测 widnows 11mingw 8.1.0opencv 4.5.5 mingw8.1下载地址https://sourceforge.net/projects/mingw/ 配置环境变量 cmake下载 安装完添加环境变量 来到官网,下载 windows 对…

【华为HCIP | 华为数通工程师】刷题日记1116(一个字惨)

个人名片: 🐼作者简介:一名大三在校生,喜欢AI编程🎋 🐻‍❄️个人主页🥇:落798. 🐼个人WeChat:hmmwx53 🕊️系列专栏:🖼️…

真心建议看看这个盈亏平衡点计算方法及要点解析!

说实话,进行产品动态盈亏平衡计算是非常考验人的,因为不是人人都具备评估不同产品组合的盈利能力和掌握风险的方法。 当然最简单的方式就是套用诸如单产品动态盈亏平衡表之类的现成模板进行测算,可以实现以下三点基本需求: 弹性输…

AI实践与学习1_Milvus向量数据库实践与原理分析

前言 随着NLP预训练模型(大模型)以及多模态研究领域的发展,向量数据库被使用的越来越多。 在XOP亿级题库业务背景下,对于试题召回搜索单单靠着ES集群已经出现性能瓶颈,因此需要预研其他技术方案提高试题搜索召回率。…

OpenAI 董事会与 Sam Altman 讨论重返 CEO 岗位事宜

The Verge 援引多位知情人士消息称,OpenAI 董事会正在与 Sam Altman 讨论他重新担任首席执行官的可能性。 有一位知情人士表示,Altman 对于回归公司一事的态度暧昧,尤其是在他没有任何提前通知的情况下被解雇后。他希望对公司的治理模式进行重…

系列三、GC垃圾回收算法和垃圾收集器的关系?分别是什么请你谈谈

一、关系 GC算法(引用计数法、复制算法、标记清除算法、标记整理算法)是方法论,垃圾收集器是算法的落地实现。 二、4种主要垃圾收集器 4.1、串行垃圾收集器(Serial) 它为单线程环境设计,并且只使用一个线程…

【论文阅读】基于隐蔽带宽的汽车控制网络鲁棒认证(二)

文章目录 第三章 识别CAN中的隐藏带宽信道3.1 隐蔽带宽vs.隐藏带宽3.1.1 隐蔽通道3.1.2 隐藏带宽通道 3.2 通道属性3.3 CAN隐藏带宽信道3.3.1 CAN帧ID字段3.3.2 CAN帧数据字段3.3.3 帧错误检测领域3.3.4 时间通道3.3.5 混合通道 3.4 构建信道带宽公式3.5通道矩阵3.6 结论 第四章…

基于Vue+SpringBoot的大病保险管理系统 开源项目

项目编号: S 031 ,文末获取源码。 \color{red}{项目编号:S031,文末获取源码。} 项目编号:S031,文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 系统配置维护2.2 系统参保管理2.3 大…