Unity3d Shader篇(七)— 纹理采样

news2024/11/22 1:05:10

文章目录

  • 前言
  • 一、什么是纹理采样?
    • 1. 纹理采样的工作原理
    • 2. 纹理采样的优缺点
      • 优点
      • 缺点
  • 二、使用步骤
    • 1. Shader 属性定义
    • 2. SubShader 设置
    • 3. 渲染 Pass
    • 4. 定义结构体和顶点着色器函数
    • 5. 片元着色器函数
  • 三、效果
  • 四、总结
    • 使用场景


前言

纹理采样是一种常用的图形学技术,它可以让我们在渲染物体表面时,使用一张图片来提供颜色信息,从而增强物体的细节和真实感。在本文中,我们将介绍纹理采样的基本概念,原理和实现方法,以及在 Unity Shader 中如何使用纹理采样来实现一个简单的高光反射着色器。


一、什么是纹理采样?

1. 纹理采样的工作原理

纹理采样,就是通过 uv 获取贴图对应位置的颜色。uv 是一种二维坐标系,它的取值范围是 [0,1],表示了贴图上的相对位置。例如,uv 值是 (0.5,0.5),此时采样到的就是贴图中心点的颜色值。

在 Unity Shader 中,我们可以使用 tex2D 函数来进行纹理采样,它的参数有两个,一个是纹理对象,一个是 uv 坐标,它的返回值是一个 fixed4 类型的颜色值,表示了纹理上的纹素(texel)的颜色。例如:

fixed4 col = tex2D (_MainTex, i.uv);

这段代码表示,从 _MainTex 这个纹理对象中,采样 i.uv 这个坐标处的颜色,赋值给 col 变量。

2. 纹理采样的优缺点

优点

可以大大提高物体表面的细节和真实感,使物体看起来更加美观和逼真。
可以减少顶点数据的传输和处理,提高渲染效率和性能。
可以灵活地调整和修改物体表面的颜色和效果,不需要重新编译着色器或者修改代码。

缺点

需要占用额外的内存空间和带宽,增加资源的加载和管理的开销。
需要考虑纹理的分辨率和质量,以及纹理坐标的映射和过滤,避免出现失真和锯齿的现象。
需要考虑纹理的环绕和过滤模式,以及纹理的压缩和优化,以适应不同的渲染需求和设备。

二、使用步骤

1. Shader 属性定义

// 定义属性
Properties
{
   _MainTex("MainTex",2D)="white"{}
   _Diffuse("Diffuse",Color)=(1,1,1,1) // 漫反射颜色属性,默认白色
   _Specular("Specular",Color)=(1,1,1,1) // 高光颜色属性,默认白色
   _Gloss("Gloss",Range(1,256))=5 // 高光反射系数
}

这段代码定义了Shader的属性,其中:
_MainTex: 表示图片属性,它的默认值是白色,表示如果没有指定贴图,就使用白色填充。
_Diffuse: 表示漫反射颜色属性,使用RGBA格式表示颜色,默认为白色 (1, 1, 1, 1)。
_Specular: 表示高光颜色属性,同样使用RGBA格式表示颜色,默认为白色 (1, 1, 1, 1)。
_Gloss: 表示高光反射系数属性,使用Range声明范围为1到256,默认值为5。

2. SubShader 设置

SubShader
{
    Tags
    {
        "RenderType" = "Opaque" // 渲染类型为不透明
    }
    
    LOD 100 // 细节级别
}

SubShader 定义了一组渲染设置,包括标签和细节级别。在这里,我们将渲染类型标签设置为 “Opaque”,表示物体是不透明的。

3. 渲染 Pass

Pass
{
    CGPROGRAM
    #pragma vertex vert
    #pragma fragment frag

    #include "UnityCG.cginc"
    #include "Lighting.cginc"
}

这里开始了渲染 Pass 部分。在这里,我们使用了 CGPROGRAM 指令来声明顶点着色器和片元着色器函数。#pragma vertex vert 和 #pragma fragment frag 分别指定了顶点着色器函数和片元着色器函数的名称。

然后,我们包含了 UnityCG.cginc 和 Lighting.cginc,它们提供了许多有用的函数和宏,用于简化编写 Shader。

4. 定义结构体和顶点着色器函数

// 定义结构体:从顶点到片元的数据传递
struct v2f
{
    float4 vertex:SV_POSITION; // 顶点位置
    fixed3 worldNormal:TEXCOORD0; // 世界空间法线
    fixed3 worldPos:TEXCOORD1;// 世界空间位置
    float2 uv:TEXCOORD2;
};

// 顶点着色器函数
v2f vert(appdata_base v)
{
    v2f o;
    o.vertex = UnityObjectToClipPos(v.vertex); // 顶点位置变换到裁剪空间
    fixed3 worldNormal = UnityObjectToWorldNormal(v.normal); // 世界空间法线
    o.worldNormal = worldNormal;

    //让外面的属性可以影响到uv
    //o.uv = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
    //uv计算简化函数
    o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
    o.worldPos=mul(unity_ObjectToWorld,v.vertex);
    return o;
}

顶点着色器的输入是一个结构体 appdata_base ,它包含了顶点的位置和法线信息等。顶点着色器的输出是一个结构体 v2f ,它包含了顶点的裁剪空间位置和世界空间法线和位置信息等。

顶点着色器的主要逻辑是:

  1. 使用 UnityObjectToClipPos 函数,将顶点的位置从对象空间变换到裁剪空间,这是渲染管线的必要步骤。

  2. 使用 UnityObjectToWorldNormal 函数,将顶点的法线从对象空间变换到世界空间,这是为了计算光照效果所需的方向向量。

  3. 使用 TRANSFORM_TEX 函数,将顶点的贴图坐标根据 _MainTex_ST 的值进行缩放和偏移,这是为了让贴图的属性可以影响到贴图的显示。

  4. 使用 unity_ObjectToWorld 矩阵,将顶点的位置从对象空间变换到世界空间,这是为了计算光照效果所需的坐标系。

5. 片元着色器函数

// 片元着色器函数
fixed4 frag(v2f i) : SV_Target
{
    //获取环境光
    fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;

    //纹理采样
    fixed3 albedo = tex2D(_MainTex, i.uv).rgb;

    //漫反射
    fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
    fixed3 diffuse = _LightColor0.rgb * albedo * _Diffuse.rgb * max(0, dot(worldLightDir, i.worldNormal) * 0.5 + 0.5);

    // 高光反射
    // 计算视角方向
    fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
    // 计算半向量
    fixed3 halfDir = normalize(worldLightDir + viewDir);
    // 计算高光颜色   
    fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(i.worldNormal, halfDir)), _Gloss);

    // 组合最终颜色
    fixed3 color = diffuse + ambient + specular;
    return fixed4(color, 1); // 输出颜色
}


片元着色器的输入是一个结构体 v2f ,它包含了顶点的裁剪空间位置和世界空间法线和位置信息。片元着色器的输出是一个 fixed4 类型的颜色值,它表示了片元的颜色。

片元着色器的主要逻辑是:

  1. 使用 UNITY_LIGHTMODEL_AMBIENT 宏,获取环境光的颜色,这是 Phong 光照模型的第一个分量。

  2. 使用 tex2D 函数,对 _MainTex 进行纹理采样,根据 i 的 uv 值获取对应的像素颜色,它是物体的表面颜色。

  3. 使用 UnityWorldSpaceLightDir 函数,获取光源的方向向量,这是为了计算漫反射和高光效果所需的角度。

  4. 使用 _LightColor0 和 _Diffuse 变量,获取光源的颜色和物体的漫反射颜色,然后使用 max 和 dot 函数,计算光源和法线的夹角的余弦值,然后乘以 0.5 并加上 0.5,这是为了将 [-1, 1] 的范围映射到 [0, 1] 的范围,这是 Phong 光照模型的第二个分量

  5. 使用 UnityWorldSpaceViewDir 函数,根据 i 的 worldPos 值获取视线的方向向量,这是为了计算高光效果所需的角度。

  6. 使用 normalize 函数,计算视线方向和光源方向的半向量,这是为了简化高光效果的计算。

  7. 使用 _LightColor0 和 _Specular 变量,获取光源的颜色和物体的高光颜色,然后使用 max 和 dot 函数,计算法线和半向量的夹角的余弦值,然后使用 pow 函数,根据 _Gloss 的值计算高光的强度,这是 Phong 光照模型的第三个分量。

  8. 将环境光、漫反射和高光的颜色相加,得到最终的光照颜色,作为片元着色器的输出。

三、效果

在这里插入图片描述

四、总结

纹理采样是从一张纹理图片中获取颜色值的过程,它需要指定一个纹理坐标(uv)和一个采样器(sampler)。采样器定义了纹理的过滤方式(filter)和寻址模式(wrap)。过滤方式决定了当纹理坐标不是整数时,如何插值得到颜色值,常见的有邻近点(point)、线性(linear)和各向异性(anisotropic)三种。寻址模式决定了当纹理坐标超出[0,1]范围时,如何处理边界情况,常见的有重复(repeat)、钳位(clamp)、边框(border)和镜像(mirror)四种。

使用场景

纹理采样的应用场景非常广泛,几乎所有的图形渲染都会用到纹理采样。例如:
基础颜色:我们可以使用一张彩色图片作为纹理,来为物体表面提供基础的颜色信息,从而使物体看起来更加丰富和多样。
法线贴图:我们可以使用一张法线图片作为纹理,来为物体表面提供法线信息,从而使物体看起来更加凹凸和立体。
高光贴图:我们可以使用一张灰度图片作为纹理,来为物体表面提供高光信息,从而使物体看起来更加光滑和反光。
遮罩贴图:我们可以使用一张黑白图片作为纹理,来为物体表面提供遮罩信息,从而使物体看起来更加复杂和多层次。

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

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

相关文章

Ubuntu 23.10:内网安装rapidocr_paddle(GPU)及其前置准备

Ubuntu 23.10:内网安装rapidocr_paddle(GPU)及其前置准备 – WhiteNights Site 标签:Linux, ocr, ubuntu, 系统相关 安装NVIDIA驱动、安装CUDA&&CUDNN、安装… rapidocr_paddle主要是用于ocr识别的引擎。本文主要针对于…

2024年抖店的市场已经饱和,小白不适合入局了?真实现状如下

我是王路飞。 如今的抖店,在整个电商行业,并不算是个“新人”了,毕竟已经上线四五年时间了。 每个项目都有自己的红利期、爆发期,最后基本都会进入到发展期。 抖店亦是如此,你要说流量红利期吧,确实已经…

如何选择最适合的图纸加密软件?用户体验及性价比

安秉网盾图纸加密软件是一款功能强大的图纸加密工具,具有以下特点和优势: 全盘加密:安秉网盾采用先进的加密算法,能对文件、文件夹、磁盘等数据进行全面加密,确保数据在存储和传输过程中的安全性。 监控与审计&#…

k-means聚类、GMM高斯聚类、canopy聚类、DBSCAN聚类、FCM聚类、ISODATA聚类、k-medoid聚类、层次聚类、谱聚类 对比

k-means聚类、GMM高斯聚类、canopy聚类、DBSCAN聚类、FCM聚类、ISODATA聚类、k-medoid聚类、层次聚类、谱聚类 对比 标 代码获取代码获取代码获取代码获取代码获取代码获取代码获取代码获取代码获取代码获取题 GMM(高斯混合模型)是一种聚类算法&#xff…

UE蓝图 入口(FunctionEntry)节点和源码

系列文章目录 UE蓝图 Get节点和源码 UE蓝图 Set节点和源码 UE蓝图 Cast节点和源码 UE蓝图 分支(Branch)节点和源码 UE蓝图 入口(FunctionEntry)节点和源码 文章目录 系列文章目录一、FunctionEntry节点功能二、入口节点用法1. 创建函数2. 命名函数3. 定义参数4. 编写函数逻辑5…

【Deep Learning 6】可变形卷积

🌞欢迎来到Pytorch的世界 🌈博客主页:卿云阁 💌欢迎关注🎉点赞👍收藏⭐️留言📝 🌟本文由卿云阁原创! 📆首发时间:🌹2024年2月20日&a…

想了解黄金代理的资质应该看什么?

投资者要选择黄金代理为自己开户和服务,自然关于代理的资质是很重要的,那怎么判断黄金代理的资质是好是坏呢?下面我们就来讨论一下。我们主要可以从以下这几个方面来讨论黄金代理的资质。 首先就是黄金代理背后的黄金交易平台的牌照是什么&am…

java—泛型编程

文章目录 什么是泛型为什么需要泛型 泛型的使用泛型的上界 泛型方法的使用引出泛型方法 泛型是如何编译的擦除机制 什么是泛型 首先什么是泛型呢?从字面上我们可以理解为广泛的类型,有一定c基础的程序猿们应该了解,java中的泛型其实就是c的模…

C#_索引器

索引器的作用:令对象可像数组一般被索引 索引器 internal class TestClass {public int[] arr { 1, 2, 3, 4, 5 };public string this[int index] // 前者为返回类型,后者为索引类型// 返回类型代表get函数的返回值类型、set函数的value类型&#xff0…

java 使用documents4j将XML转为pdf文件的方式

1.背景: 通过spire.doc.free将word转换成PDF时存在缺陷:只能获取前3页。获取全文另外需支付费用。 2.解决办法 使用documents4j,documents4j会保留原word文件中更多的样式,如修订模式下的差异化字体颜色、文档右侧修订记录等。 …

PHP实践:Laravel中事件使用讲解

🏆作者简介,黑夜开发者,CSDN领军人物,全栈领域优质创作者✌,CSDN博客专家,阿里云社区专家博主,2023年6月CSDN上海赛道top4。 🏆数年电商行业从业经验,历任核心研发工程师…

js设计模式:适配器模式

作用: 可以将某种不同格式的数据转化为自己所期待的数据格式 或者对于一些存在兼容或者特殊处理的业务逻辑,可以进行一个适配 示例: //原始数据let oldData1 [{name: 王惊涛,age: 29},{name: 孙悟空,age: 800},{name: 嘉文四世,age: 27},{name: 关羽,age: 40},{name: 伊利丹…

【Oracle】玩转Oracle数据库(三):数据库的创建和管理

前言 嘿,各位数据库小能手们!今天我们要进入数据库的创世纪,探索Oracle数据库的创建和管理!🔧💻 在这篇博文【Oracle】玩转Oracle数据库(三):数据库的创建和管理中&#…

判断一个dll/exe是32位还是64位

通过记事本判断(可判断C或者C#) 64位、将dll用记事本打开,可以看到一堆乱码,但是找到乱码行的第一个PE,如果后面是d?则为64位 32位、将dll用记事本打开,可以看到一堆乱码,但是找到乱码行的第…

第二证券:可转债怎么套利?可转债常见的六种套利方法

可转债是上市公司为了融资向社会公众所发行的一种债券,其间投资者可以在二级市场上进行套利操作,存在以下六种套利办法: 1、折价转股套利 只有在溢价率为负时,可转债才有套利空间,转股溢价率为正,则不存在…

SmartBi--配置BI启动为后台服务

目录 1. 在service.bat目录下打开cmd 2. 运行 service.bat install 服务名 命令 3.在服务中找到设置的服务名,设置成自启,启动服务即可 4.在tomcat logs目录下查看日志 5. 移除服务 1. 在service.bat目录下打开cmd 2. 运行 service.bat install …

短视频内容如何吸引用户?媒介盒子揭秘

不管是什么行业,在宣传中都会用到短视频这种类型,然而有许多品牌方在宣传时总会面临找不着发力点,宣传内容同质化等问题,今天媒介盒子就来和大家聊聊:什么样的短视频内容能够吸引用户。 一、 制造强烈对比&#xff0c…

python 批量创建的目录和文件、同时写入文件内容、为短视频做基础模板准备

图: 代码: import os def create_directory(path):if not os.path.exists(path):os.makedirs(path)print("已创建目录:", path)else:print("该路径下已存在相同名称的目录")def create_file(filename):with open(filena…

柔顺控制笔记

参资料: 【1】https://zhuanlan.zhihu.com/p/620918453 【2】https://blog.csdn.net/a735148617/article/details/108564836 【3】https://zhuanlan.zhihu.com/p/126338809 【4】机器人与环境间力_位置控制技术研究与应用_李正义 【5】水下机械臂建模及柔顺控制方法…

【快速搞定Webpack5】处理字体图标资源(六)

介绍 在实际开发中,几乎每个项目都需要用户icon图标以及部分项目会用到有特色的字体需求。 今天我们学习的内容就是如何在webpack中处理字体及icon图标的使用。 一、下载字体图标文件 1、打开 阿里巴巴矢量图库 2、登录或注册账号 3、选择想要的图标添加到购物车…