前部分知识复习05

一、多级渐远贴图MipMap

 选择贴图,可以勾选贴图的多级渐远效果

[IntRange]_MipMap("MipMap",Range(0,12))=0     //多级渐远贴图的LOD调节滑杆

_MipMapTexture("MipMapTexture",2D)="white"{}   //定义多级渐远贴图

多级渐远贴图的采样:

float4 Mipmap=tex2Dlod(_MipMapTexture,float4(i.uv.xy,0,_MipMap));

二、立方体纹理 CubeMap

  利用立方体纹理制作反射效果:

反射效果的形成:

float3 R=reflect(-V,N);

reflect函数根据入射向量和法向量求反射向量

而向量V是从模型指向摄像机的方向的向量,所以此时的入射向量为-V

_CubeMap("CubeMap",Cube)="white"{}

samplerCUBE _Cubemap;       //声明立方体纹理

float4 Cubemap=texCUBE(_CubeMap,R);   //立方体纹理的采样

Shader"unity/Texture03"
{Properties{_MipMapTexture("MipMapTexture",2D)="white"{}[IntRange]_MipMap("MipMap",Range(0,12))=0_CubeMap("CubeMap",Cube)="white"{}}SubShader{Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"sampler2D _MipMapTexture;int _MipMap;samplerCUBE _CubeMap;struct appdate {float4 vertex : POSITION;float4 uv : TEXCOORD;float3 normal : NORMAL;};struct v2f {float4 pos : SV_POSITION;float4 uv : TEXCOORD;float3 worldNormal:TEXCOORD1;float3 worldPos : TEXCOORD2;};v2f vert(appdate v){v2f o;o.pos=UnityObjectToClipPos(v.vertex);o.worldNormal=UnityObjectToWorldNormal(v.normal);o.worldPos=mul(unity_ObjectToWorld,v.vertex);o.uv=v.uv;return o;}float4 frag(v2f i):SV_Target{float4 Mipmap=tex2Dlod(_MipMapTexture,float4(i.uv.xy,0,_MipMap));float3 N=normalize(i.worldNormal);float3 V =normalize(_WorldSpaceCameraPos-i.worldPos);float3 R=reflect(-V,N);float4 Cubemap=texCUBE(_CubeMap,R);return Cubemap;}ENDCG}}}

三、法线纹理

 法线贴图中存储的是每个像素点在切线空间下的法线向量信息

   所以采样法线贴图后的值为切线空间下的法线值

//采样法线贴图 (采样结果为切线空间下的法线值)  UnpackNormal函数通常用于解压纹理中压缩的法线信息,以获取其正确的法线
float3 normalTex=UnpackNormal(tex2D(_NormalTex,i.uv));

但是光照计算所需要的法线值为世界空间下的法线信息,所以就需要将采样后的法线值转换到世界空间下

这时就需要使用到切线空间变换矩阵,将法线信息由切线空间转换到世界空间


其中 切线 tangent 是一个四维的向量

flaot4 tangent ;   //tangent.w代表切线的方向,tangent.xyz代表坐标

  • 在顶点着色器中将模型顶点的切线由本地空间转换到世界空间

float3 worldTangent=UnityObjectToWorldDir(v.tangent);

  • 再计算切线的方向

float tangentSign=v.tangent.w*unity_WorldTransformParams.w;

  • 由世界空间法线向量和世界空间切线向量的叉值算法来计算副切线向量

(注意:此时的世界空间法线向量为模型上各像素点的法线向量,而非采样后的法线值)

//副切线由切线向量和法线向量的叉积所得
float3 worldBinormal=cross(worldNormal,worldTangent)*tangentSign;

  • 然后构建切线空间变换矩阵

//给切线空间变换矩阵赋值
o.tSpace0=float3(worldTangent.x,worldBinormal.x,worldNormal.x);
o.tSpace1=float3(worldTangent.y,worldBinormal.y,worldNormal.y);
o.tSpace2=float3(worldTangent.z,worldBinormal.z,worldNormal.z);

  • 最后在片元着色器中将采样后的法线值和变换矩阵进行点积操作得到世界空间下法线贴图中的法线值

fixed3 worldN=float3(dot(normalTex,i.tSpace0),dot(normalTex,i.tSpace1),dot(normalTex,i.tSpace2));

Shader"unity/Texture02"
{Properties{//定义法线纹理  [Normal]标签的作用是使得该纹理贴图的位置只能装载法线贴图[Normal]_NormalTex("NormalTex",2D)="white"{}}SubShader{Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"sampler2D _NormalTex;float4 _NormalTex_ST;struct appdate{float4 vertex:POSITION;float2 uv:TEXCOORD;float3 normal:NORMAL;//(tangent四维向量,xyz代表坐标,w代表切线的方向)float4 tangent:TANGENT;};struct v2f{float4 pos:SV_POSITION;float2 uv:TEXCOORD;//定义切线空间变换矩阵float3 tSpace0:TEXCOORD1;float3 tSpace1:TEXCOORD2;float3 tSpace2:TEXCOORD3;};v2f vert(appdate v){v2f o;o.uv=TRANSFORM_TEX(v.uv,_NormalTex);o.pos=UnityObjectToClipPos(v.vertex);//世界空间法线float3 worldNormal=UnityObjectToWorldNormal(v.normal);//将模型顶点的切线由本地空间转换为世界空间float3 worldTangent=UnityObjectToWorldDir(v.tangent);//决定切线的方向float tangentSign=v.tangent.w*unity_WorldTransformParams.w;//副切线由切线向量和法线向量的叉积所得float3 worldBinormal=cross(worldNormal,worldTangent)*tangentSign;//给切线空间变换矩阵赋值o.tSpace0=float3(worldTangent.x,worldBinormal.x,worldNormal.x);o.tSpace1=float3(worldTangent.y,worldBinormal.y,worldNormal.y);o.tSpace2=float3(worldTangent.z,worldBinormal.z,worldNormal.z);return o;}float4 frag(v2f i):SV_TARGET{	//法线纹理的采样(切线空间下的法线值)//采样法线贴图后的值为一个三维向量fixed3 normalTex=UnpackNormal(tex2D(_NormalTex,i.uv));//worldN是基于切线变换矩阵和切线空间下的法线值所计算得到的世界空间下的法线值fixed3 worldN=float3(dot(normalTex,i.tSpace0),dot(normalTex,i.tSpace1),dot(normalTex,i.tSpace2));fixed3 L=normalize(_WorldSpaceLightPos0);//lamber光照模型 max(0,dot(N,L)fixed NdotL=max(0,dot(worldN,L));return NdotL;}ENDCG}}}

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

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

相关文章

解锁反序列化漏洞:从原理到防护的安全指南

目录 前言 一、什么是反序列化 二、反序列化漏洞原理 三、反序列化漏洞的危害 (一)任意代码执行 (二)权限提升 (三)数据泄露与篡改 四、常见的反序列化漏洞场景 (一)PHP 反…

理解 C 与 C++ 中的 const 常量与数组大小的关系

博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C语言 文章目录 💯前言💯数组大小的常量要求💯C 语言中的数组大小要求💯C 中的数组大小要求💯为什么 C 中 const 变量可以作为数组大小💯进一步的…

MAC OS安装Homebrew

文章目录 1.下载Homebrew2.完成安装3.验证安装4.更新 Homebrew作为一个包管理器,提供了一种简便的方式来安装、更新和卸载各种命令行工具和应用程序。相比于手动下载和编译源代码,或者从不同的网站下载安装包,使用Homebrew可以显著减少这些操…

深入解析:如何利用 Python 爬虫获取商品 SKU 详细信息

在电商领域,SKU(Stock Keeping Unit,库存单位)详细信息是电商运营的核心数据之一。它不仅包含了商品的规格、价格、库存等关键信息,还直接影响到库存管理、价格策略和市场分析等多个方面。本文将详细介绍如何利用 Pyth…

OKHttp拦截器解析

OKHttp涉及到拦截器大概的执行步骤为: 1.通过newCall生成RealCall对象 具体代码如下: Override public Call newCall(Request request) {return new RealCall(this, request, false /* for web socket */);}2.调用Call的execute方法 当然这也可以是执…

深度学习系列--04.梯度下降以及其他优化器

目录 一.梯度概念 1.一元函数 2.二元函数 3.几何意义上的区别 二.梯度下降 1.原理 2.步骤 3.示例代码(Python) 4.不同类型的梯度下降 5.优缺点 三.动量优化器(Momentum) 适用场景 1.复杂地形的优化问题 2.数据具有噪声的问…

编程AI深度实战:给vim装上AI

系列文章: 编程AI深度实战:私有模型deep seek r1,必会ollama-CSDN博客 编程AI深度实战:自己的AI,必会LangChain-CSDN博客 编程AI深度实战:给vim装上AI-CSDN博客 编程AI深度实战:火的编程AI&…

深入解析 JPA 的 EntityManager#refresh 方法

在 Java 持久化领域,JPA(Java Persistence API)是一个非常重要的技术,它为开发者提供了一种便捷的方式来操作数据库。今天,我们来深入探讨一下 JPA 中 EntityManager#refresh 方法的使用和原理。 一、refresh 方法的作…

2025年2月6日(anaconda cuda 学习 基本命令)

查看电脑的显卡型号是否支持CUDA的安装 https://developer.nvidia.com/zh-cn/cuda-gpus 查看可以安装的CUDA版本 https://docs.nvidia.com/cuda/cuda-toolkit-release-notes/index.html CUDA安装地址 https://developer.nvidia.com/cuda-toolkit-archive Anaconda下载地址 htt…

自动化构建——make/makefile

目录 背景使用推导过程如果多个文件呢?? 背景 会不会写makefile,从侧面可以说明一个人是否具有完成大型工程的能力makefile带来的好处就是——”自动化编译“,一旦写好,只需要一个make命令,整个工程完全自…

深度整理总结MySQL——SQL的执行顺序和流程

SQL的执行顺序和流程 SQL的执行顺序执行一条select语句,发生了什么呢连接器查询缓存解析SQL执行SQL预处理器优化器执行器 总结 SQL的执行顺序 这是一条标准的查询语句: 但实际上并不是从上到下去解析的,真实的执行顺序是: 我们先执行from,join来确定表之间的连接关系&#x…

R语言 | 使用 ComplexHeatmap 绘制热图,分区并给对角线分区加黑边框

目的:画热图,分区,给对角线分区添加黑色边框 建议直接看0和4。 0. 准备数据 # 安装并加载必要的包 #install.packages("ComplexHeatmap") # 如果尚未安装 library(ComplexHeatmap)# 使用 iris 数据集 #data(iris)# 选择数值列&a…

11 享元(Flyweight)模式

享元模式 1.1 分类 (对象)结构型 1.2 提出问题 做一个车管所系统,将会产生大量的车辆实体,如果每一个实例都保存自己的所有信息,将会需要大量内存,甚至导致程序崩溃。 1.3 解决方案 运用共享技术有效…

脚本批量重启openstack虚拟机并加上启动编号、脚本批量验证openstack虚拟机状态并加上编号

文章目录 说明脚本批量重启openstack虚拟机并加上启动编号脚本准备uuid文件准备测试脚本批量验证openstack虚拟机虚拟机状态为并加上编号脚本准备uuid文件准备测试说明 用uuid批量重启openstack虚拟机并带上编号,执行效果分别如下# 重启 [root@controller01 ccx]# sh start_fo…

Jetpack ViewModel

private val deviceViewModel: IDeviceViewModel by viewModels<DeviceViewModel>() 这句代码是 Jetpack ViewModel 在 Fragment 或 Activity 中的标准用法&#xff0c;它的作用是 创建并获取 ViewModel 实例&#xff0c;同时确保 ViewModel 的生命周期与 UI 组件保持一…

线程池如何知道一个线程的任务已经执行完成

一、线程池内部任务执行状态监控 在线程池内部&#xff0c;当我们提交一个任务后&#xff0c;线程池会调度一个工作线程来执行该任务的run方法。确实&#xff0c;当run方法正常结束时&#xff0c;意味着任务已经完成。线程池中的工作线程是同步调用任务的run方法&#xff0c;并…

2025年Android NDK超全版本下载地址

Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列Scratch编程案例软考全系列Unity3D学习专栏蓝桥系列ChatGPT和AIGC &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分…

【CPP】CPP经典面试题

文章目录 引言1. C 基础1.1 C 中的 const 关键字1.2 C 中的 static 关键字 2. 内存管理2.1 C 中的 new 和 delete2.2 内存泄漏 3. 面向对象编程3.1 继承和多态3.2 多重继承 4. 模板和泛型编程4.1 函数模板4.2 类模板 5. STL 和标准库5.1 容器5.2 迭代器 6. 高级特性6.1 移动语义…

使用ES5和ES6求函数参数的和、解析URL Params为对象

文章目录 1 使用ES5和ES6求函数参数的和1.1 ES51.2 ES6 2 解析URL Params为对象 1 使用ES5和ES6求函数参数的和 1.1 ES5 function sum() {let sum 0;Array.prototype.forEach.call(arguments, function(item) {sum item * 1;})return sum; }1.2 ES6 function sum(...nums)…

安卓开发,打开PDF文件

1、把PDF文件复制到raw目录下 &#xff08;1&#xff09;新建一个Android Resource Directory (2)Resource type 改成 raw (3) 把PDF文件复制到raw目录下 2、activity_main.xml <?xml version"1.0" encoding"utf-8"?> <LinearLayoutxmlns:and…