广州网站制作到诺然/网络营销师报名官网
Unity引擎动态法线贴图制作球滚动轨迹
大家好,我是阿赵。
之前说了一个使用局部UV采样来实现轨迹的方法。这一篇在之前的基础上,使用法线贴图进行凹凸轨迹的绘制。
一、实现的目标
先来回顾一下,上一篇最终我们已经绘制了一个轨迹的贴图
可以思考一下,假如现在我绘制的不是黑白的遮罩,而是一张法线贴图,会怎样呢?比如这样:
如果是这样,剩下的问题就非常简单了,使用局部的UV采样,然后正常的通过法线贴图读取法线方向,最后通过光照模型来表现出法线的凹凸感。
二、动态法线贴图的绘制和融合
说起来好像很简单,但绘制灰度图简单,绘制法线贴图应该怎样做呢?
在球的位置上,实际上我是用了这么一张法线贴图的,还是用顶部摄像机拍摄需要局部采样UV的范围。
在球没有移动的时候,顶部摄像机拍摄到的应该是这样一个情况:
除了球以外,这一片平整的纯色,是算出来的。
这里涉及到一些法线贴图的计算方式。
需要知道的是,法线贴图是一张RGB颜色的贴图,所以它的每一个通道的取值范围是0到1,但法线方向的取值范围是-1到1的,所以如果得到一张法线贴图,需要转换成法线方向时,需要对它乘以2再减1。然后想将一个法线方向转成RGB值,方法是把法线方向乘以0.5再加0.5。
所以当一个正常朝向上方的法线方向是(0,0,1),它转换成RGB值之后,就是(0.5,0.5,1),也就是上图看到占了大部分面积的颜色了。
由于我使用的是打一个正交摄像机在头顶的做法来渲染球所在的区域,这个摄像机通过layer过滤只看得到球所在的法线面片,所以除了球以外,其他区域应该是黑色的:
想要把黑色的部分都填充成(0,0,1)法线方向的颜色,有2种方法:
1、把摄像机的颜色设置成这种颜色
2、在混合的shader里面判断,传入的图片是黑色的部分就填充成这张颜色。
我这里是简单的使用第一种方式,修改摄像机的颜色。
用上一篇说的方法,在移动的过程中,通过求出上一帧球的位置和当前球的位置作为偏移值,然后传入通过Graphics.Blit融合两帧的画面的材质球里面,就可以对两张法线贴图进行混合了。
接下来需要混合两帧之间产生的法线贴图。
混合法线的方法非常多,我常用的消耗比较低的法线混合方式有这么几种:
假设n1和n2是需要混合的2个法线方向,n3是混合后的结果
1、线性混合
公式很简单:
float3 n3 = normalize(n1+n2);
这种方式混合法线,优点是实现简单,而且同一个法线贴图不停的叠加,效果都不会发生变化。缺点也很明显,会减淡本身法线贴图的特征,如果每帧都不停的和(0,0,1)混合,最终所有法线的特征都会被抹平了。
2、偏导混合
公式是:
float3 n3 = normalize( float3(n1.xy/n1.z+n2.xy/n2.z,1));
从效果上看,法线的特征保留会比线性混合要好很多。
如果把公式改一下,
float2 n0 = lerp(n1.xy/n1.z+n2.xy/n2.z,_blendVal);
float3 n3 = normalize( float3(n0,1));
还可以做出混合插值的效果。
3、Whiteout混合
和偏导的结果比较类似
公式:
n3 = normalize( float3( n1.xy+n2.xy,n1.z*n2.z));
三、绘制频率问题和解决
虽然偏导和Whiteout的效果会比线性的好,但如果物体停留在同一个位置,每帧都不停的叠加同一个法线贴图,偏导和Whiteout都会对法线效果越来越加深,到最后就会出现和原来贴图比较偏差的效果,比如刚才那个球的法线如果每一帧不停的用Whiteout算法去叠加,最后就会变成这样
为了解决这个问题,实际上是需要控制绘制的次数。基本思想很简单,就是物体移动的时候,并且移动的距离大于一定长度时,才会去绘制。
这样,就出现了多种解决的方案:
1、还是用顶部摄像机,但只有主角移动的时候,才会调用Graphics.Blit方法去混合。这个方案的问题在于,如果只判断主角移动,那么产生这个法线贴图的主体也只能是主角,方便的其他角色是不能产生法线混合效果的。
2、不用顶部摄像机,而是每个可以产生轨迹的物体身上都挂上脚本,当物体移动的时候,主动的把自己的法线贴图通过Graphics.Blit混合到局部UV的法线贴图里面。这样做相当于每个角色有一个笔刷。不过这样做的问题是,需要逐个角色分别传入混合,还要计算每个角色相对于主角位置的偏移。如果场景里面的角色很多的情况下,这样做性能可能不是特别好。
3、还是用顶部摄像机,每个角色身上有一张法线贴图,只有当角色开始移动时,这张法线贴图才会变成激活可显示状态。那么,我们还是用顶部摄像机来渲染一张RenderTexture就够了,而这张RenderTexture看到的,只会是在绘制局部UV的范围内的正在移动的物体的法线贴图。
4、不管法线叠加变形的问题。实际上如果不是对混合后的法线要求特别精确,比如角色踩出的脚印要清晰到连鞋底都看得清,而只是需要一个大致的范围的话,我觉得直接叠加也无所谓,毕竟法线的大致方向是对的。
四、源码:
1、法线混合的Shader代码
和上一篇差不多的,只是修改一下片段着色器就行
half4 frag(v2f i) : SV_Target{//当前帧传入的法线笔刷half4 col = tex2D(_MainTex, i.uv);half3 curNormal = col.rgb * 2 - 1;//上一帧绘制的法线贴图half4 lastCol = tex2D(_lastTex, i.uv - _offset);half3 lastNormal = lastCol.rgb * 2 - 1; //默认的法线方向float3 defaultNormal = float3(0,0,1);//用于保持边缘是默认法线方向的遮罩half4 maskCol = tex2D(_maskTex, i.uv);//使用whiteout法线混合float3 finalNormal = normalize(half3(curNormal.xy + lastNormal.xy, curNormal.z*lastNormal.z));//计算边缘遮罩finalNormal = normalize(finalNormal * maskCol.r + _defaultDir.xyz*(1 - maskCol.r));//转RGB颜色finalNormal = finalNormal * 0.5 + 0.5;return half4(finalNormal, 1);}
2、地面上的局部UV采样包含法线贴图的Shader
Shader "azhao/GroundFootStepNormalTex"
{Properties{_MainTex("Texture", 2D) = "white" {}_Color("Color", Color) = (1,1,1,1)_centerPos("CenterPos", Vector) = (0,0,0,0)_footstepRect("footstepRect",Vector) = (0,0,0,0)_footstepTex("footstepTex",2D) = "gray"{}_footstepColor("footstepColor",Color) = (1,1,1,1)_NormalTex("Normal Tex", 2D) = "black"{}_normalScale("normalScale", Range(-5 , 5)) = 0_normalFootStepScale("normalFootStepScale", Range(-5 , 5)) = 0_specColor("SpecColor",Color) = (1,1,1,1)_shininess("shininess", Range(1 , 100)) = 1_specIntensity("specIntensity",Range(0,1)) = 1_ambientIntensity("ambientIntensity",Range(0,1)) = 1}SubShader{Tags { "RenderType"="Opaque" }LOD 100Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"sampler2D _MainTex;float4 _MainTex_ST;fixed4 _Color;uniform float3 _centerPos;float4 _footstepRect;sampler2D _footstepTex;float4 _footstepColor;sampler2D _NormalTex;float4 _NormalTex_ST;float _normalScale;float _normalFootStepScale;float4 _specColor;float _shininess;float _specIntensity;float _ambientIntensity;struct appdata{float4 pos : POSITION;float2 uv : TEXCOORD0;float3 normal:NORMAL;float3 tangent:TANGENT;};struct v2f{float4 pos : SV_POSITION;float3 worldPos : TEXCOORD0;float2 uv : TEXCOORD1;float2 footstepUV : TEXCOORD2;float3 worldNormal : TEXCOORD3;float3 worldTangent :TEXCOORD4;float3 worldBitangent : TEXCOORD5;};half3 UnpackScaleNormal(half4 packednormal, half bumpScale){half3 normal;//由于法线贴图代表的颜色是0到1,而法线向量的范围是-1到1//所以通过*2-1,把色值范围转换到-1到1normal = packednormal * 2 - 1;//对法线进行缩放normal.xy *= bumpScale;//向量标准化normal = normalize(normal);return normal;}//获取HalfLambert漫反射值float GetHalfLambertDiffuse(float3 worldPos, float3 worldNormal){float3 lightDir = UnityWorldSpaceLightDir(worldPos);float NDotL = saturate(dot(worldNormal, lightDir));NDotL = NDotL * 0.5 + 0.5;return NDotL;}//获取BlinnPhong高光float GetBlinnPhongSpec(float3 worldPos, float3 worldNormal){float3 viewDir = normalize(UnityWorldSpaceViewDir(worldPos));float3 halfDir = normalize((viewDir + _WorldSpaceLightPos0.xyz));float specDir = max(dot(normalize(worldNormal), halfDir), 0);float specVal = pow(specDir, _shininess);return specVal;}float RemapUV(float min, float max, float val){return (val - min) / (max - min);}v2f vert(appdata i){v2f o;o.pos = UnityObjectToClipPos(i.pos);o.worldPos = mul(unity_ObjectToWorld,i.pos.xyz);o.uv = i.uv*_MainTex_ST.xy+ _MainTex_ST.zw;o.footstepUV = float2(RemapUV(_footstepRect.x, _footstepRect.z, o.worldPos.x), RemapUV(_footstepRect.y, _footstepRect.w, o.worldPos.z));o.worldNormal = UnityObjectToWorldNormal(i.normal);o.worldTangent = UnityObjectToWorldDir(i.tangent);o.worldBitangent = cross(o.worldNormal, o.worldTangent);return o;}fixed4 frag (v2f i) : SV_Target{//采样漫反射贴图的颜色half4 col = tex2D(_MainTex, i.uv*_MainTex_ST.xy + _MainTex_ST.zw);//计算法线贴图的UVhalf2 normalUV = i.uv * _NormalTex_ST.xy + _NormalTex_ST.zw;//采样法线贴图的颜色half4 normalCol = tex2D(_NormalTex, normalUV);fixed4 footstepCol = tex2D(_footstepTex, i.footstepUV);fixed3 footstepRGB = UnpackScaleNormal(footstepCol, _normalFootStepScale).rgb;half3 normalVal = UnpackScaleNormal(normalCol, _normalScale).rgb;//normalVal = footstepRGB;normalVal = normalize(normalVal + footstepRGB);//构建TBN矩阵float3 tanToWorld0 = float3(i.worldTangent.x, i.worldBitangent.x, i.worldNormal.x);float3 tanToWorld1 = float3(i.worldTangent.y, i.worldBitangent.y, i.worldNormal.y);float3 tanToWorld2 = float3(i.worldTangent.z, i.worldBitangent.z, i.worldNormal.z);//通过切线空间的法线方向和TBN矩阵,得出法线贴图代表的物体世界空间的法线方向float3 worldNormal = float3(dot(tanToWorld0, normalVal), dot(tanToWorld1, normalVal), dot(tanToWorld2, normalVal));//用法线贴图的世界空间法线,算漫反射half diffuseVal = GetHalfLambertDiffuse(i.worldPos, worldNormal);//diffuseVal = clamp(diffuseVal, 0.5, 1);//用法线贴图的世界空间法线,算高光角度half3 specCol = _specColor * GetBlinnPhongSpec(i.worldPos, worldNormal)*_specIntensity;//最终颜色 = 环境色+漫反射颜色+高光颜色half3 finalCol = UNITY_LIGHTMODEL_AMBIENT * _ambientIntensity + saturate(col.rgb*diffuseVal) + specCol;return half4(finalCol, 1);}ENDCG}}
}
相关文章:

Unity地面交互效果——2、动态法线贴图实现轨迹效果
Unity引擎动态法线贴图制作球滚动轨迹 大家好,我是阿赵。 之前说了一个使用局部UV采样来实现轨迹的方法。这一篇在之前的基础上,使用法线贴图进行凹凸轨迹的绘制。 一、实现的目标 先来回顾一下,上一篇最终我们已经绘制了一个轨迹的贴图…...

视频剪辑达人教您:如何运用嵌套合并技巧制作固定片尾
在视频剪辑的过程中,嵌套合并技巧是一种非常实用的技术,可以帮助您将多个素材叠加在一起,制作出更加丰富多彩的视频。本文将由视频剪辑达人为您详细介绍如何运用云炫AI智剪嵌套合并技巧制作固定片尾,让您的视频剪辑水平更上一层楼…...

【腾讯云 TDSQL-C Serverless 产品体验】TDSQL-C MySQL Serverless最佳实践
一、引言: 随着云计算技术的不断发展,越来越多的企业开始选择将自己的数据库部署在云上,以更好了的支持企业数字化转型以及业务创新,在这个过程中,很多客户会遇到这样一个问题,业务会存在高峰期和低谷期&a…...

SQLyog连接数据库报plugin caching_sha2_password could not be loaded......解决方案
问题描述 问题分析 因为MySQL新版默认使用caching_sha2_password作为身份验证的插件,而旧版本使用的是mysql_native_password。当出现plugin caching_sha2_password could not be loaded报错,我们更换为旧版本 如何解决 先使用cmd命令登录MySQL&a…...

linux应急排查
常用命令 查看登录用户和活动 whoami:显示当前登录用户的用户名。 w:显示当前登录到系统上的用户列表和他们正在执行的命令。 last:显示最近登录到系统的用户列表、登录时间和来源IP地址。 ps aux:列出当前正在运行的所有进程&…...

Apache POI及easyExcel读取及写入excel文件
目录 1.excel 2.使用场景 3.Apache POI 4.easyExcel 5.总结 1.excel excel分为两版,03版和07版。 03版的后缀为xls,最大有65536行。 07版的后缀为xlsx,最大行数没有限制。 2.使用场景 将用户信息导出到excel表格中。 将excel中的数…...

为什么写作
1记录生活,表达自己的想法和情感,提高沟通能力。 2年轻的时候就有写作的意愿,一直未动笔。 3想突破自己看看自己能写到什么程度。锻炼自己更好组织思路,提高逻辑思维能力。 4给自己的生活增添一些爱好,更好地理解和…...

python基于VGG19实现图像风格迁移
目录 1、原理 2、代码实现 1、原理 图像风格迁移是一种将一张图片的内容与另一张图片的风格进行合成的技术。 风格(style)是指图像中不同空间尺度的纹理、颜色和视觉图案,内容(content)是指图像的高级宏观结构。 实…...

BoredHackerBlog: Cloud AV RT日记
目录 信息搜集 WEB漏洞攻击 拿shell 信息搜集 首先ifconfig查看自己IP, netdiscover查看同网段下主机 第三个应该是目标靶机。用nmap查看靶机开放端口: 开放22和8080,看看8080开的啥服务 WEB漏洞攻击 看到让我们输入邀请码。有输入框的第…...

数据结构之“初窥门径”
目录 前言: 一,数据结构起源 二,基本概念和术语 2.1数据 2.2数据元素 2.3数据项 2.4数据对象 2.5数据结构 三,逻辑结构与物理结构 3.1逻辑结构 3.1.1集合结构 3.1.2线性结构 3.1.3树形结构 3.1.4图形结构 3.2物理结…...

css:transform实现平移、旋转、缩放、倾斜元素
目录 文档语法示例旋转元素 transform-rotate旋转过渡旋转动画 参考文章 文档 https://developer.mozilla.org/zh-CN/docs/Web/CSS/transform 语法 /* Keyword values */ transform: none;/* Function values */ transform: matrix(1, 2, 3, 4, 5, 6); transform: translate…...

如何理解AutoGPT
AutoGPT和GPT-4都是OpenAI公司的产品。AutoGPT是一个实验性开源应用程序,展示了GPT-4语言模型的能力。GPT-4是OpenAI研发的人工智能语言模型。 AutoGPT在GitHub主页上有151k星(151k星代表了151,000个用户点赞了该项目),AutoGPT获…...

【网络知识必知必会】聊聊网络层IP协议
文章目录 前言IP 协议格式总结 前言 在之前的博文中, 我们聊过了传输层中的两个重点协议 TCP 和 UDP, 本文我们再来聊聊网络层中的一个协议IP, 简单认识一下 IP 协议格式. IP 协议与 TCP 协议的复杂度也不妨多让, 不过我们在这里只是简单的聊一聊 IP 协议的报文格式就行, 毕竟…...

66. 加一
给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。 最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。 你可以假设除了整数 0 之外,这个整数不会以零开头。 示例 1: 输入: digits …...

逻辑(css3)_强制不换行
需求 如上图做一个跑马灯数据,时间、地点、姓名、提示文本字数都不是固定的。 逻辑思想 个人想法是给四个文本均设置宽度,不然会出现不能左对齐的现象。 此时四个文本均左对齐, 垂直排列样式也比较好看,但是出现一个缺点&#…...

营收净利双降、股价下跌四成,敷尔佳带伤闯关“双11”
今年双11预售已经开启,敷尔佳在天猫、抖音等电商平台火热营销;营销热业绩冷,敷尔佳的三季报不及预期。 10月23日,哈尔滨敷尔佳科技发展有限公司(下称“敷尔佳”,301371SZ)公布2023年三季报,其三季度营收净…...

C语言KR圣经笔记 2.8自增和自减 2.9位运算 2.10赋值
2.8 自增和自减操作符 C提供了两个不同寻常的操作符,用于对变量进行自增和自减。自增操作符对操作数加上1,而自减操作符 -- 对操作数减去1。我们已经频繁使用 对变量进行自增,如: if (c \n)nl; 不寻常之处在于 和 -- 既能用作…...

PHP的Excel导出与导入
下载地址(注意php版本大于7.3可能会报错) GitHub - PHPOffice/PHPExcel: ARCHIVED 解压 1、导出 Excel $data[[name>a,age>11],[name>b,age>22],[name>d,age>33], ]; $fileds["name">"名称","age"…...

Ubuntu自建git服务器
Ubuntu 安装 gitlab-ce sudo apt-get update sudo apt-get install gitlab-ce 安装成功 sudo apt-get install gitlab-ce 正在读取软件包列表... 完成 正在分析软件包的依赖关系树 正在读取状态信息... 完成 下列【新】软件包将被安装:gitlab-ce 升…...

【面试专题】并发编程篇①
📃个人主页:个人主页 🔥系列专栏:Java面试专题 1.线程和进程的区别 线程和进程都是操作系统中的概念,它们的主要区别如下: 资源分配:进程是操作系统中的资源分配的基本单位,每个进程…...

Linux Centos7安装后,无法查询到IP地址,无ens0,只有lo和ens33的解决方案
文章目录 前言1 查看network-scripts目录2 创建并配置 ifcfg-ens33 文件3 禁用NetworkManager4 重新启动网络服务总结 前言 在VMware中,安装Linux centos7操作系统后,想查询本机的IP地址,执行ifconfig命令 ifconfig结果如下: 结…...

行为型模式-访问者模式
在访问者模式中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模式。根据模式,元素对象已接受访问者对象,这样访问者对象就…...

go-kit中如何开启websocket服务
在Go-Kit中,可以使用github.com/go-kit/kit/transport/http包来开启WebSocket服务。以下是一个简单的示例代码,演示了如何在Go-Kit中开启WebSocket服务: package mainimport ("context""fmt""net/http""…...

私有网络的安全保障,WorkPlus Meet内网视频会议助力企业高效会议
在企业内部沟通与协作中,视频会议成为了一种必不可少的沟通方式。然而,传统的互联网视频会议往往受制于网络不稳定因素,给企业带来不便与困扰。WorkPlus Meet作为一款专注内网视频会议的软件,致力于为企业打造高效、稳定的内网视频…...

国际权威媒体聚焦:孙宇晨和波场TRON在迪拜荣获加密行业重磅奖项
近日,在迪拜举行的区块链生态大会(Blockchain Life Conference)上,波场TRON创始人、火币HTX全球顾问委员会委员孙宇晨斩获“年度加密企业家”称号,波场TRON荣膺“年度最佳 Layer 1”大奖。这一消息迅速得到彭博社、雅虎财经、美联社和法国最大媒体之一Le Figaro等国际权威媒体的…...

新闻详情。
<!DOCTYPE html> <html><head><title>新闻</title><meta http-equiv"content-type" content"text/html; charsetutf-8"/><meta name"apple-mobile-web-app-capable" content"yes"/><lin…...

Java面试题-Redis-第二天(Redis持久化、过期键删除策略、内存淘汰策略)
目录 一、Redis持久化机制 二、Redis过期键删除策略 三、Redis内存淘汰策略 一、Redis持久化机制 为了能重用Redis数据,防止系统故障造成数据丢失,我们就需要将Redis中的数据写入到磁盘中,也就是持久化 1. 有哪些方式 有rdb和aof两种方式…...

ElasticSearch快速入门实战
全文检索 什么是全文检索 全文检索是一种通过对文本内容进行全面索引和搜索的技术。它可以快速地在大量文本数据中查找包含特定关键词或短语的文档,并返回相关的搜索结果。全文检索广泛应用于各种信息管理系统和应用中,如搜索引擎、文档管理系统、电子…...

揭秘MySQL数据同步至Elasticsearch的最佳方案与技巧
本文介绍下当前常见的场景之一:Mysql数据同步Elasticsearch的实现方案,这里以电商为例,其实所有相关搜索内容都可以使用此方案。 对于搜索,应该是所有APP必备的基础功能,不同时期有不同的解决方案,本次重点…...

正点原子嵌入式linux驱动开发——Linux RTC驱动
RTC也就是实时时钟,用于记录当前系统时间,对于Linux系统而言时间是非常重要的,就和使用Windows电脑或手机查看时间一样,在使用Linux设备的时候也需要查看时间。本章就来学习一下如何编写Linux下的RTC驱动程序。 Linux内核RTC驱动…...