Unity3d Shader篇(七)— 纹理采样

文章目录

  • 前言
  • 一、什么是纹理采样?
    • 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.mzph.cn/news/694412.shtml

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

相关文章

打造智能物品租赁平台:Java与SpringBoot的实践

✍✍计算机编程指导师 ⭐⭐个人介绍:自己非常喜欢研究技术问题!专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目:有源码或者技术上的问题欢迎在评论区一起讨论交流! ⚡⚡ Java实战 |…

SparkSQL学习01

目录 1.SparkSQL特点1.1易整合1.2统一的数据访问1.3兼容Hive1.4标准的数据连接 2 SparkSQL编程模型DataFrameDataSet2.1 SQL2.2 DataFrame是什么2.3 DataSet是什么2.4 RDD,DataSet,DataFrame 3 SparkSQL核心编程3.1 编程入口3.2 SparkSQL基本编程3.2.1编…

掌握web控件定位技巧,提升页面操作效率!

简介 在做 Web 自动化时,最根本的就是操作页面上的元素,首先要能找到这些元素,然后才能操作这些元素。工具或代码无法像测试人员一样用肉眼来分辨页面上的元素。那么要如何定位到这些元素,本章会介绍各种定位元素的方法。 web 控…

【前端】前端三要素之DOM

写在前面:本文仅包含DOM内容,JavaScript传送门在这里,BOM传送门在这里。 本文内容是假期中刷的黑马Pink老师视频(十分感谢Pink老师),原文保存在个人的GitLab中,如果需要写的网页内容信息等可以评…

vue3 + ts + echart 实现柱形图表

首先封装Echart一个文件 代码如下 <script setup lang"ts"> import { ECharts, EChartsOption, init } from echarts; import { ref, watch, onMounted, onBeforeUnmount } from vue;// 定义props interface Props {width?: string;height?: string;optio…

pclpy 窗口可视化多个点云

pclpy 窗口可视化多个点云 一、算法原理二、代码三、结果1.可视化结果 四、相关数据五、问题与解决方案1.问题2.解决 一、算法原理 原理看一下代码写的很仔细的。。目前在同一个窗口最多可视化两个点云。。 二、代码 from pclpy import pcldef CloudShow(cloud1, cloud2):&q…

04 动力云客之登录后获取用户信息+JWT存进Redis+Filter验证Token + token续期

1. 登录后获取用户信息 非常好实现. 只要新建一个controller, 并调用SS提供的Authentication对象即可 package com.sunsplanter.controller;RestController public class UserController {GetMapping(value "api/login/info")public R loginInfo(Authentication a…

C++ 基础算法 双指针 数组元素的目标和

给定两个升序排序的有序数组 A 和 B &#xff0c;以及一个目标值 x 。 数组下标从 0 开始。 请你求出满足 A[i]B[j]x 的数对 (i,j) 。 数据保证有唯一解。 输入格式 第一行包含三个整数 n,m,x &#xff0c;分别表示 A 的长度&#xff0c;B 的长度以及目标值 x 。 第二行包…

使用静态CRLSP配置MPLS TE隧道

正文共&#xff1a;1591 字 13 图&#xff0c;预估阅读时间&#xff1a;4 分钟 静态CRLSP&#xff08;Constraint-based Routed Label Switched Paths&#xff0c;基于约束路由的LSP&#xff09;是指在报文经过的每一跳设备上&#xff08;包括Ingress、Transit和Egress&#xf…

使用alist连接百度网盘和阿里云盘挂载到本地磁盘

1、下载alist软件 alist软件下载地址&#xff1a;https://github.com/alist-org/alist 跳转后&#xff0c;找到对应的windows版本 2 、下载后解压&#xff0c;并启动服务 注意&#xff1a;alist的启动方式不是传统的双击启动&#xff0c;需要用命令提示符,启动服务 下载完成…

平时积累的FPGA知识点(9)

平时在FPGA群聊等积累的FPGA知识点&#xff0c;第9期&#xff1a; 31 ldpc的license是什么&#xff1f; 解释&#xff1a;Xilinx公司的Zynq UltraScale RFSoC系列芯片进行项目开发&#xff0c;在某些芯片型号中&#xff0c;自身带有SD-FEC硬核资源&#xff0c;具体查询方式&a…

Aster实现一台电脑当两台使——副屏搭配键鼠

前言&#xff1a;笔者每年回家&#xff0c;都面临着想要和小伙伴一起玩游戏&#xff0c;但小伙伴没有电脑/只有低配电脑的问题。与此同时&#xff0c;笔者自身的电脑是高配置的电脑&#xff0c;因此笔者想到&#xff0c;能否在自己的电脑上运行游戏&#xff0c;在小伙伴的电脑上…

MKS T3BI集成蝶阀说明T3B-T3PRS-232Supplement

MKS T3BI集成蝶阀说明T3B-T3PRS-232Supplement

Vue自定义指令的三个方法

目录 ​编辑 介绍 创建方法&#xff1a; min.js注册 script setup中使用 script中使用&#xff1a; 指令钩子 钩子参数 简化形式 对象字面量 在组件上使用 介绍 除了 Vue 内置的一系列指令 (比如 v-model 或 v-show) 之外&#xff0c;Vue 还允许你注册自定义的指令…

Codeforces Round 927 (Div. 3) LR-remainders的题解

原题描述&#xff1a; C.LR-remains 每次测试时限&#xff1a;2 秒 每次测试的内存限制&#xff1a;256 兆字节 输入&#xff1a;标准输入 输出&#xff1a;标准输出 样例1输入&#xff1a; 4 4 6 3 1 4 2 LRRL 5 1 1 1 1 1 1 LLLLL 6 8 1 2 3 4 5 6 RLLLRR 1 10000 1000…

MySQL初识——安装配置

文章目录 1. MySQL卸载2. 获取MySQL官方yum源安装包3. 安装4. 启动MySQL5. 登录6. 配置配置文件 Tips&#xff1a; 本章是Centos 7安装配置myql&#xff0c;配置操作用的是root权限 1. MySQL卸载 首先我们先查看一下系统中是否有mysql服务 ps axj | grep mysql如果有&#xf…

Vue2路由组件练习

Vue2路由组件练习 1. 演示效果 2. 代码分析 2.1. 安装 vue-router 命令&#xff1a;npm i vue-router 应用插件&#xff1a;Vue.use(VueRouter) 2.2. 创建路由文件 在 src 文件夹下&#xff0c;创建router文件夹&#xff0c;并在该文件夹创建index.js文件 2.3. 导入依赖…

K8S实战:Centos7部署Kubernetes1.20.0集群

目录 一、准备工作1.1、创建3台虚拟机1.1.1、下载虚拟机管理工具1.1.2、安装虚拟机管理工具1.1.3、下载虚Centos镜像1.1.4、创建3台虚拟机1.1.5、设置虚拟机网络环境 1.2、虚拟机基础配置&#xff08;3台虚拟机进行相同处理&#xff09;1.2.1、配置host1.2.2、关闭防火墙1.2.3、…

String字符串,FastJson常用操作方法

JSON字符串操作 1、创建配置环境 # 引入测试包testImplementation group: org.springframework.boot, name: spring-boot-starter-test, version: 2.2.6.RELEASE # 创建测试类RunWith(SpringRunner.class)SpringBootTestpublic class JsonTest {Testpublic void test(){Syste…

关于Linux中使用退格键出现^H的问题解决

关于Linux中使用退格键出现^H的问题解决 今天在Linux下执行脚本和监听端口的输入时候&#xff0c;不小心输错内容想要删除用退格键发现变成了^H&#xff0c;从网上查了资料并且实际应用了一下&#xff08;我的虚拟机是CentOS7&#xff09;。 使用ctrl退格键即可成功删除内容 …