【Unity Shader入门精要 第7章】基础纹理(一)

1. 纹理映射

每一张纹理可以看作拥有一个属于自己的2D坐标空间,其横轴用U表示,纵轴用V表示,因此也称为UV坐标空间。

UV空间的坐标范围为[0,0]到[1,1],在Unity中,UV空间也是从左下到右上,即纹理的左下角对应的UV坐标为[0,0],纹理右上角对应的UV坐标为[1,1]

在美术导出模型资源时,会通过UV展开将模型每个顶点对应的UV坐标存储到顶点信息中。渲染时通过顶点(或片元)的UV坐标映射到纹理上的某一点,这样就可以通过采样每一个顶点(或片元)对应的纹理上的颜色将纹理显示出来。

2. 纹理基础设置

以Unity 2021为例,一张纹理的Inspector面板大致如下
在这里插入图片描述
其中红框部分是本节主要关注的部分

  • Generate Mip Maps

    • 勾选后会提前进行滤波,生成不同采样等级的Mip Map纹理
    • 渲染时根据屏幕像素对应的纹理范围从对应等级的Mip Map纹理中进行采样
    • 由于生成了新的纹理,因此会占用更多的内存空间
  • Wrap Mode
    UV坐标空间自身的范围虽然只有0到1,但实际采样时,顶点映射的UV坐标可能超过这个范围,WrapMode属性决定了采样的UV坐标超过[0, 1]范围时的处理方式

    • Repeat:重复采样,即超过范围时舍弃整数部分只按小数部分采样,比如(1.1, 1.2)实际会按照(0.1, 0.2)采样
    • Clamp:超过[0, 1]的部分延用相应边缘的值(0或者1)
  • Filter Mode
    决定纹理采样的滤波方式

    • Point:就近点采样
    • Bilinear:双线性插值
    • Trilinear:三线性插值

关于MipMap和滤波的原理可以参照【Unity Shader入门精要 第7章】基础纹理补充内容:MipMap原理

3. 在Shader中使用纹理

  • 创建Chapter_7_BaseTexture_Mat 作为测试材质
  • 创建Chapter_7_BaseTexture作为测试shader,并赋给Chapter_7_BaseTexture_Mat 材质
  • 场景中创建胶囊体,将Chapter_7_BaseTexture_Mat 材质赋给胶囊体
  • 场景中添加一盏平行光,并调整平行光角度

在Shader中,我们通过对纹理采样得到的颜色来代替之前固定的漫反射颜色,并在片元着色器中进行逐像素的光照计算,得到最终的效果:

  • 在Properties中添加属性 _MainTex(“MainTex”, 2D) = “white”{} 用于设置纹理,此时选中胶囊体可在Inspector面板中看到如下纹理设置选项
    在这里插入图片描述
    • Tiling:平铺数量,可以理解为反向的缩放度,值越大单位空间平铺数量越多,相当于对纹理缩小,反之相当与放大
    • Offset:偏移
  • 在CG代码段中添加与属性同名的变量 _MainTex来使用面板中设置的纹理,其类型为 sampler2D
  • 顶点着色器中输入的uv坐标是模型导出时顶点对应的uv坐标,为了能够得到正确的纹理采样结果,除了考虑顶点自身的uv坐标外,还需要考虑面板中对要采样的纹理设置的缩放和偏移,这部分信息可通过在Shader中声明 XXX_ST 的变量获得,其中XXX为纹理属性的名字,当前Shader中也就是 _MainTex_ST,该变量类型为float4,其中xy表示缩放,zw表示平移
  • 通过 input.uv.xy * _MainTex_ST.xy + _MainTex_ST.zw 即可得到实际采样使用的uv坐标,也可以通过内置的TRANSFORM_TEX(_MainTex, input.uv)方法获得,此时引擎会自己使用名为 _MainTex_ST 的变量进行上述计算,因此即使使用内置方法计算uv也需要声明_ST变量
  • 最后在着色器中通过 tex2D(_MainTex, i.uv) 方法即可对纹理进行采样获得颜色,我们以该颜色作为物体自身的漫反射颜色系数带入漫反射光照计算

Shader如下:

Shader "MyShader/Chapter_7/Chapter_7_BaseTexture"
{
    Properties
    {
        _MainTex("MainTex", 2D) = "white"{}
        _Specular("Specular", Color) = (1,1,1,1)
        _Gloss("Gloss", Range(1.0, 256.0)) = 10
    }
    
    SubShader
    {
        Pass
        {
            Tags {"LightMode" = "ForwardBase"}
        
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            
            struct a2v
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
                float2 uv : TEXCOORD0;
            };
            
            struct v2f
            {
                float4 vertex : SV_POSITION;
                float2 uv : TEXCOORD0;
                float3 worldPos : TEXCOORD1;
                float3 worldNormal : TEXCOORD2;
            };
            
            sampler2D _MainTex;
            float4 _MainTex_ST;
            fixed4 _Specular;
            half _Gloss;
            
            v2f vert(a2v i)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(i.vertex);
                o.worldPos = mul(unity_ObjectToWorld, i.vertex);
                o.worldNormal = mul(i.normal, (float3x3)unity_WorldToObject);
                o.uv = TRANSFORM_TEX(i.uv, _MainTex);
                return o;
            }
            
            fixed4 frag(v2f i) : SV_Target
            {
                fixed3 _ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;
                
                float3 _worldNormal = normalize(i.worldNormal);
                float3 _worldLight = normalize(_WorldSpaceLightPos0.xyz);
                fixed4 _albedo = tex2D(_MainTex, i.uv);
                fixed3 _diffuse = _LightColor0.rgb * _albedo.rgb * saturate(dot(_worldNormal, _worldLight));
                
                float3 _worldRefl = normalize(reflect(-_worldLight, _worldNormal));
                float3 _worldView = normalize(_WorldSpaceCameraPos.xyz - i.worldPos);
                fixed3 _specular = _LightColor0.rgb * _Specular.xyz * pow( saturate(dot(_worldRefl, _worldView)),_Gloss);
                
                return fixed4(_ambient + _diffuse + _specular, 1);
            }
            
            ENDCG
        }
    
    }

}

效果如下:
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

神经网络复习--卷积神经网络及其扩展

文章目录 卷积卷积网络反向传播已知池化层误差,反向求上一层隐藏层误差已知卷积层的误差,推导该层的W, b的梯度 注意力机制Transformer卷积变体 卷积 卷积神经网络是一个多层的神经网络,每层由多个二维平面组成,每个平面由多个独…

免费pr相册模板mogrt|手机壁纸AI绘画摄影作品照片展示模板视频素材

pr相册模板mogrt,手机壁纸、电脑桌面壁纸、AI绘画、摄影作品、照片展示模板视频素材。 Premiere Pro 2023及以上版本。 全高清(19201080)分辨率/30fps。 通用表达式(适用于所有特效语言)。 免费下载:https…

防火墙技术的演进,什么是下一代防火墙(NGFW)?

防火墙技术的演进 防火墙技术的演进经历了不同阶段,从包过滤防火墙到状态检测防火墙,再到集成多种安全功能的UTM(统一威胁管理)设备,最终发展到具备应用识别能力的NGFW(下一代防火墙)。 包过滤…

49.乐理基础-拍号的类型-单拍子、复拍子

当前写的东西,如果只是想要看懂乐谱的话,它是没什么意义的,就像我们要把 0,1,2,3,4,5。。。称为自然数,1,2,3,4,5称为正整…

鸿蒙OS开发:【Stage模型应用程序包结构】

Stage模型应用程序包结构 为了让开发者能对应用程序包在不同阶段的形态更有清晰的认知,分别对开发态、编译态、发布态的应用程序结构展开介绍。 开发态包结构 在DevEco Studio上[创建一个项目工程],并尝试创建多个不同类型的Module。根据实际工程中的…

MongoDB 推出新项目,助力企业构建生成式 AI 现代应用程序

MongoDB AI Applications Program可为组织提供战略路线图、行业专业知识及所需技术,加速从构思到大规模部署生成式 AI 应用程序 MongoDB (纳斯达克股票代码:MDB) 近日宣布推出 MongoDB AI Applications Program (MongoDB AI应用项目,简称&am…

使用VSCode生成代码、查询数据表

利用VSCode中百度生成 一、 1、输入内容:“给我生成一个student表,要求有id,createDate,userName,phone,age,sex,introduce的列信息,给我DDL与DML,5条信息都为中文信息,并且有一个userName必须等于张先生” 2、将生成的语句复制粘贴到数据库…

SpringBoot 3.2.5 + ElasticSearch 8.12.0 - SpringData 开发指南

目录 一、SpringData ElasticSearch 1.1、环境配置 1.2、创建实体类 1.3、ElasticSearchTemplate 的使用 1.3.1、创建索引库,设置映射 1.3.2、创建索引映射注意事项 1.3.3、简单的 CRUD 1.3.4、三种构建搜索条件的方式 1.3.5、NativeQuery 搜索实战 1.3.6…

Optional用法

说明:Optional和Stream一样,是Java8引入的特性,本文介绍Optional的几个实际用法。Steam流使用,参考下面这篇文章: Stream流使用 使用 1.保证值存在 // 1.保证值存在,pageNumber,pageSizeInte…

PR标题模板,视频内容要点提示文字列表模板剪辑素材

Premiere Pro的要点列表标题模板。 主要特点: 可以无限制地添加任意数量的列表项。 使用直观的控件轻松自定义列表的各个方面。只需点击几下,即可调整颜色、大小、位置等。 轻松调整颜色,享受完全的创作自由。 可以轻松调整列表项之间的间距…

mybatis-plus之数据源切换事务失效问题

为什么存在数据源切换和食物时效问题? 由于业务数据来源不同 需要配置多个数据源来进行数据的查询 编辑等操作 这一切换业务对数据的一致性要求很高那就要保证ACID啦 也就是数据的有效性 要么是成功的 要么是失败的。 数据源切换采用mybatisplus支持 多数据源配置&a…

Linux下VMamba 环境复现+环境测试

# 1. 创建自己的虚拟环境 conda create -n VMamba python3.10.13 conda activate VMamba # 2. cuda-11.8 conda install cudatoolkit11.8 -c nvidia # 3. torch torchvision torchaudio 与 官网命令一致 pip install torch2.1.1 torchvision0.16.1 torchaudio2.1.1 --index-url…

自集成式 HTTP 代理方案

前言 大部分程序员,想必都会有一个常用的抓包代理工具; 但在座的各位,可曾见过这样一款集成在 Web 应用中的代理工具? ​,时长00:45 它是明显区别于传统代理工具的,有以下特性: 零安装、零配…

解决AdaptiveAvgPool2d部署算子不支持问题

一、Pytorch中AdaptiveAvgPool2d函数详解 torch.nn.AdaptiveAvgPool2d()接受两个参数,分别为输出特征图的长和宽,其通道数前后不发生变化。如以下: self.global_avgpool nn.AdaptiveAvgPool2d(1) # 输出N*C*1*1 self.global_avgpool …

AcWing166. 数独-DFS剪枝与优化

题目 思路 思考问题:搜索顺序->考虑剪枝搜索顺序:先随意选择一个空格子,枚举该格子可填写的数字,当所有格子都填完的时候,说明可以退出了剪枝: 优化搜索顺序:随意选择一个空格子&#xff1a…

【讲解下iCloud如何高效利用】

🎥博主:程序员不想YY啊 💫CSDN优质创作者,CSDN实力新星,CSDN博客专家 🤗点赞🎈收藏⭐再看💫养成习惯 ✨希望本文对您有所裨益,如有不足之处,欢迎在评论区提出…

C++实战演练---负载均衡在线oj项目 || 编译服务模块设计

顾得泉:个人主页 个人专栏:《Linux操作系统》 《C从入门到精通》 《LeedCode刷题》 键盘敲烂,年薪百万! 前言 上一篇预热文章简单说过我们的编写思路,首先要实现的是编译功能,那么在编译功能版块中&…

Java面试八股之float和double的区别

Java中float和double的区别 存储空间与精度: double:占据64位(8字节)存储空间,属于双精度浮点数。它可以提供较高的精度,通常能够精确表示大约15到17位十进制数字,适合用于需要较高精度计算或…

SSM【Spring SpringMVC Mybatis】—— Spring(二)

如果对于Spring的一些基础理论感兴趣可见👇 SSM【Spring SpringMVC Mybatis】—— Spring(一) 目录 1、Spring中bean的作用域 1.1 语法 1.2 四个作用域 2、Spring中bean的生命周期 2.1 bean的生命周期 2.2 bean的后置处理器 2.3 添加后…

upload-labs靶场通关详解(1-15)

1.pass-01 查看源代码 是js,属于前端校验 可以通过禁用js来上传文件 2.pass-02 根据提示是MIME绕过 MIME:是设定某种扩展名的文件 用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来…