Unity | Shader基础知识(第十四集:简单效果练习)
目录
前言
一、效果预览
1.弧形边缘光
二、效果制作
1. 制作弧形边缘光
2.弧形边缘光进阶
3.弧形边缘光调节渐变范围
4.边缘光突变
5.同心圆
三、加入世界坐标做效果
1.绘制结界
2.斑马球
3.效果合并
四、作者的碎碎念
前言
有粉丝建议说,让我继续更新Shader,我可以出一些简单常用的效果,带着大家写一下,我觉得这是个好主意。
换句话说,带着大家看一下,学到的知识,应该怎么去应用。
我会把常见的调节的一些细致过程逐步写下来,如果遇见没讲过的知识点,就详细讲解一下。
一、效果预览
1.弧形边缘光
这个效果是,对于圆形或者圆弧形的物体,在边缘发光。(如图1所示)
二、效果制作
1. 制作弧形边缘光
我们先统一一下思路,发光用到的语义是自发光,之前有讲过,详情看链接。
Unity | Shader基础知识(第十二集:颜色混合)_shade 颜色混合接口-CSDN博客
边缘发光就是当我们的视线和法线的点乘的值在0附近,或0以下的时候,就发光,也是之前讲的,看链接。(如图2所示)Unity | Shader基础知识(第十三集:编写内置着色器阶段总结和表面着色器的补充介绍)_unity viewdir-CSDN博客
后面写代码,讲太多遍的就不重新注释了,只注释没讲过的。
Shader "Custom/010"
{Properties{//设置自发光的颜色_Color("Color",Color)=(0,0.5,0.5,0)}SubShader{CGPROGRAM#pragma surface surf Lambertfloat4 _Color;struct Input{//直接获取viewDirfloat3 viewDir;};void surf(Input IN,inout SurfaceOutput o){//点乘后,如果接近1,说明在视线正中,接近0则在视线边缘 half dotp =dot(IN.viewDir,o.Normal);//设置自发光,我们需要当正中时没有颜色,就是*0,在边缘有颜色,就是*1//和上面的数字刚好相反,所以我们用(1-dotp)来得到上面的效果o.Emission =_Color.rgb*(1-dotp);}ENDCG}
}
得到效果为(如图3所示)
2.弧形边缘光进阶
大部分模型都是有自己贴图的,所以我们在发光的基础上,加上贴图。
Shader "Custom/010"
{Properties{//放图片进入_MainTex("MainTex",2D)="white"{} //设置自发光的颜色_Color("Color",Color)=(0,0.5,0.5,0)}SubShader{CGPROGRAM#pragma surface surf Lambertsampler2D _MainTex;float4 _Color;struct Input{float2 uv_MainTex;//直接获取viewDirfloat3 viewDir;};void surf(Input IN,inout SurfaceOutput o){//这都是之前讲过的,不进行二次讲解了o.Albedo =tex2D(_MainTex,IN.uv_MainTex).rgb;//点乘后,如果接近1,说明在视线正中,接近0则在视线边缘 half dotp =dot(IN.viewDir,o.Normal);//设置自发光,我们需要当正中时没有颜色,就是*0,在边缘有颜色,就是*1//和上面的数字刚好相反,所以我们用(1-dotp)来得到上面的效果o.Emission =_Color.rgb*(1-dotp);}ENDCG}
}
得到的效果为(如图4所示)
3.弧形边缘光调节渐变范围
大部分时候,上面的发光范围都是有点大了,所以我们需要加个参数进行调节。
数学知识:
_Color.rgb*(1-dotp)中的(1-dotp)是一个线性变化的数据,变化是平均的,就像数数一样:0.1,0.2,0.3......
我们怎么才能让它的增长变快?前面一直比较小,越往后越大。
有一个非常简单的方法:平方
,
,
.......
如果你觉得平方变化不满意,可以是其他次方
所以我们增加一个参数,来改变光范围。
函数知识:
次方的公式是pow(底数,次方)
Shader "Custom/010"
{Properties{_MainTex("MainTex",2D)="white"{} _Color("Color",Color)=(0,0.5,0.5,0)//边缘光范围参数_Power("Power",Range(0.8,8)) = 3}SubShader{CGPROGRAM#pragma surface surf Lambertsampler2D _MainTex;float4 _Color;//接入参数float _Power;struct Input{float2 uv_MainTex;float3 viewDir;};void surf(Input IN,inout SurfaceOutput o){o.Albedo =tex2D(_MainTex,IN.uv_MainTex).rgb; half dotp =dot(IN.viewDir,o.Normal);//重新设置范围变化曲线o.Emission =_Color.rgb*pow((1-dotp),_Power);}ENDCG}
}
效果(如图5所示)
4.边缘光突变
截止到上图,虽然我们把边缘光可以锁定在非常边缘,但它的过度还是一个渐变的,如果我希望它不要渐变,而是突然出现,怎么办?
答:做条件判断(但在此之前,为了后面计算方便,我们对数据做一个简单的处理)
我们知道前面的乘积最终结果是(-1,1),但实际我们应用时,小于-1的部分,我们完全不需要,因为都是看不见的部分和0的效果一样。
函数知识:
当数据小于0时,直接取0,当数据大于1时,直接取1,其他数据不变。
saturate()
因为前面的代码没变,这里只复制修改过的代码块。(要么太长了)
void surf(Input IN,inout SurfaceOutput o){o.Albedo =tex2D(_MainTex,IN.uv_MainTex).rgb; //把小于0的数据都删掉half dotp =saturate(dot(IN.viewDir,o.Normal));o.Emission =_Color.rgb*pow((1-dotp),_Power);}
为了方便计算,我们把(1-dotp)也合并到上面。
void surf(Input IN,inout SurfaceOutput o){o.Albedo =tex2D(_MainTex,IN.uv_MainTex).rgb; //合并计算half dotp =1-saturate(dot(IN.viewDir,o.Normal));o.Emission =_Color.rgb*pow(dotp,_Power);}
我们可以进行突变判断,当dotp>0.8时,显示边缘光,反之不显示。
void surf(Input IN,inout SurfaceOutput o){o.Albedo =tex2D(_MainTex,IN.uv_MainTex).rgb; //合并计算half dotp =1-saturate(dot(IN.viewDir,o.Normal));//渐变边缘光(暂时废弃)//o.Emission =_Color.rgb*pow(dotp,_Power);//突变边缘光 //如果大于0.8,就等于1,反之等于0o.Emission =_Color.rgb*dotp>0.8?1:0;}
效果(如图6所示)
如果你还是希望有一点渐变,不太明显,哈哈~可以自己尝试。
//有一点渐变o.Emission =_Color.rgb*dotp>0.8?dotp:0;
5.同心圆
同样继续利用这个规律,我们可以做出同心圆。打了注释的地方是有增加,其他地方不变。
Shader "Custom/010"
{Properties{_MainTex("MainTex",2D)="white"{} //外圈颜色_Color("Color",Color)=(0,0.5,0.5,0)//内圈颜色_Color2("Color2",Color)=(0,0.5,0.5,0)_Power("Power",Range(0.8,8)) = 3}SubShader{CGPROGRAM#pragma surface surf Lambertsampler2D _MainTex;//外圈声明float4 _Color;//内圈声明float4 _Color2;float _Power;struct Input{float2 uv_MainTex;float3 viewDir;};void surf(Input IN,inout SurfaceOutput o){o.Albedo =tex2D(_MainTex,IN.uv_MainTex).rgb; half dotp =1-saturate(dot(IN.viewDir,o.Normal));//同心圆o.Emission =dotp>0.5?_Color.rgb:_Color2.rgb;}ENDCG}
}
效果(如图7所示)
备注:多层同心圆
//多层同心圆 //用了个绿色
o.Emission =dotp>0.8?_Color.rgb:dotp>0.5?_Color2.rgb:float4(0,1,0,0);
三、加入世界坐标做效果
1.绘制结界
动画片里经常有那种从地底下穿越上来,东西就变色了,这里也可以做这种效果,不过,我们需要先加入世界坐标。
其他的代码还是用之前的,改了改了哪里下面就替换哪部分!!!
struct Input{float2 uv_MainTex;float3 viewDir;//加入世界坐标float3 worldPos;};
当y>0时,变色~
void surf(Input IN,inout SurfaceOutput o){o.Albedo =tex2D(_MainTex,IN.uv_MainTex).rgb; half dotp =1-saturate(dot(IN.viewDir,o.Normal));//绘制结界o.Emission =IN.worldPos.y>0?_Color:float4(1,1,1,1);}
效果(如图9所示)
2.斑马球
我们继续对世界坐标做文章,无论我们球的y坐标是多少,我们把奇数染成白的,偶数染成黑的。
数学知识:
整数位是偶数,除以2,结果的小数位在0~0.5之间
整数位是奇数,除以2,结果的小数位在0.5~1之间
备注:你们可以验证一下
3.2/2=1.6,因为3.2的整数位3是奇数,所以结果的小数位0.6,在0.5~1之间。
函数知识:
取小数的函数。
frac()
例:frac(16.89)=0.89
因为我们的球目前本来就不大,所以我们把y坐标都乘10,然后再计算。
void surf(Input IN,inout SurfaceOutput o){half dotp =1-saturate(dot(IN.viewDir,o.Normal));//绘制斑马 //黑色 //白色o.Emission = frac(IN.worldPos.y*10/2)>0.5?float4(1,1,1,1):float4(0,0,0,0);}
效果(如图10所示)
3.效果合并
我们可以把之前的边缘光效果和贴图效果再打开。
void surf(Input IN,inout SurfaceOutput o){//打开贴图o.Albedo =tex2D(_MainTex,IN.uv_MainTex).rgb; half dotp =1-saturate(dot(IN.viewDir,o.Normal));//绘制斑马o.Emission = frac(IN.worldPos.y*10/2)>0.5?//颜色乘了边缘光那会的数值
float4(1,1,1,1)*dotp:float4(0,0,0,0)*dotp;}
效果(如图11所示)
是不是有那味了~
四、作者的碎碎念
考虑到好多宝宝,学了功能也不知道怎么去用, 专门出了这个简单应用专题,供大家练习。
喜欢的话希望大家给我点赞,收藏加关注哦~ღ( ´・ᴗ・` )比心
相关文章:
Unity | Shader基础知识(第十四集:简单效果练习)
目录 前言 一、效果预览 1.弧形边缘光 二、效果制作 1. 制作弧形边缘光 2.弧形边缘光进阶 3.弧形边缘光调节渐变范围 4.边缘光突变 5.同心圆 三、加入世界坐标做效果 1.绘制结界 2.斑马球 3.效果合并 四、作者的碎碎念 前言 有粉丝建议说,让我继续更新…...
Vue48-ref属性
一、需求:操作DOM元素 1-1、使用原生的id属性 不太好! 1-2、使用 ref属性 原生HTML中,用id属性给元素打标识,vue里面用ref属性。 给哪个元素加了ref属性,vc实例对象就收集哪个元素!!࿰…...
【SpringCloud学习笔记】RabbitMQ(中)
1. 交换机概述 前面《RabbitMQ上篇》我们使用SpringAMQP来演示如何用Java代码操作RabbitMQ,当时采用的是生产者直接将消息发布给队列,但是实际开发中不建议这么做,更加推荐生产者将消息发布到交换机(exchange),然后由exchange路由…...
【C++】类和对象的引入
文章目录 前言一、类的定义二、类的访问控制与封装三、类的作用域四、类的实例化五、类的存储方式及大小计算六、隐藏的this指针 前言 C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。 C是基于面向对象的&…...
11.5.k8s中pod的调度-cordon,drain,delete
目录 一、概念 二、使用 1.cordon 停止调度 1.1.停止调度 1.2.解除恢复 2.drain 驱逐节点 2.1.驱逐节点 2.2.参数介绍 2.3.解除恢复 3.delete 删除节点 一、概念 cordon节点,drain驱逐节点,delete 节点,在对k8s集群节点执行维护&am…...
Java中线程的创建方式
一、继承Thread类,重写run方法 public class MyThread{public static void main(String[] args) {Thread threadDome new ThreadDome();threadDome.start();} }class ThreadDome extends Thread{Overridepublic void run() {for (int i 0; i < 5; i) {try {Th…...
猫头虎推荐20个值得体验的通用大模型
猫头虎推荐20个值得体验的通用大模型 🚀 大家好,我是猫头虎,一名专注于科技领域的自媒体博主。今天是周一,新的开始,我们来深入探讨一下当前最值得体验的通用大模型。这些AI模型不仅功能强大,而且在各自领…...
Novartis诺华制药社招综合能力性格动机问卷入职测评笔试题库答案及包过助攻
【华东同舟求职】由资深各行业从业者建立的一站式人才服务网络平台,现阶段目标是“提升全市场各行业岗位信息的流动性和透明度”。我们接受众多行业机构的直接委托发布,并尽力通过各种方法搜寻高价值岗位信息。事实上,我们以发现不为人知的优…...
Adam优化算法
Adam优化算法 Adam(Adaptive Moment Estimation)是一种用于训练深度学习模型的优化算法,由Diederik P. Kingma和Jimmy Ba在2014年提出。Adam结合了动量和自适应学习率的方法,具有高效、稳定和适应性强的特点,被广泛应…...
MYSQL 三、mysql基础知识 7(MySQL8其它新特性)
一、mysql8新特性概述 MySQL从5.7版本直接跳跃发布了8.0版本 ,可见这是一个令人兴奋的里程碑版本。MySQL 8版本在功能上 做了显著的改进与增强,开发者对MySQL的源代码进行了重构,最突出的一点是多MySQL Optimizer优化器进行了改进。不仅在速度…...
git error: does not have a commit checked out fatal: adding files failed
git add net error: net/ does not have a commit checked out fatal: adding files failed这个错误是因为尝试将一个尚未被提交的文件夹添加到Git中。解决这个问题的方法是先将文件夹中的文件提交到Git仓库中,然后再将文件夹添加到Git中。 首先,需要进…...
Java Websocket分片发送
一、分片发送和接收(复杂) 如果数据量太大,需要分多次发送, 需要考虑数据划分和重组的问题。 二、具体思路 每次发送和接收用一个布尔值变量指定是否为最后一个分片。 三、具体使用 (一)字符串分片发送: sendText(文本, 布尔值)…...
vivado NODE、PACKAGE_PIN
节点是Xilinx部件上用于路由连接或网络的设备对象。它是一个 WIRE集合,跨越多个瓦片,物理和电气 连接在一起。节点可以连接到单个SITE_, 而是简单地将NETs携带进、携带出或携带穿过站点。节点可以连接到 任何数量的PIP,并且也可以…...
JavaEE、SSM基础框架、JavaWeb、MVC(认识)
目录 一、引言 (0)简要介绍 (1)主要涉及的学习内容 (2)学习的必要性 (3)适用学习的人群(最好有这个部分的知识基础) (4)这个基础…...
【漏洞复现】飞企互联-FE企业运营管理平台 treeXml.jsp SQL注入漏洞
0x01 产品简介 飞企互联-FE企业运营管理平台是一个基于云计算、智能化、大数据、物联网、移动互联网等技术支撑的云工作台。这个平台可以连接人、链接端、联通内外,支持企业B2B、C2B与020等核心需求,为不同行业客户的互联网转型提供支持。其特色在于提供…...
Android基础-运行时权限
一、引言 随着智能手机和移动互联网的普及,Android操作系统作为其中的佼佼者,其安全性问题日益受到关注。为了保障用户数据的安全和隐私,Android系统引入了权限机制来管理和控制应用程序对系统资源和用户数据的访问。特别是在Android 6.0&am…...
postman断言及变量及参数化
1:postman断言 断言:判断接口是否执行成功的过程 针对接口请求完成之后,针对他的响应状态码及响应信息进行判断,代码如下: //判断响应信息状态码是否正确 pm.test("Status code is 200", function () { pm.response.…...
安装和使用TrinityCore NPCBot
安装TrinityCore NPCBot 官网:GitHub - trickerer/Trinity-Bots: NPCBots for TrinityCore and AzerothCore 3.3.5 基本安装方法 Follow TrinityCore Installation Guide (https://TrinityCore.info/) to install the server firstDownload NPCBots.patch and put …...
Hvv--知攻善防应急响应靶机--Linux2
HW–应急响应靶机–Linux2 所有靶机均来自 知攻善防实验室 靶机整理: 夸克网盘:https://pan.quark.cn/s/4b6dffd0c51a#/list/share百度云盘:https://pan.baidu.com/s/1NnrS5asrS1Pw6LUbexewuA?pwdtxmy 官方WP:https://mp.weixin.…...
replaceAll is not a function 详解
先说说原因: 在chrome 浏览器中使用 replaceAll 报这个错误,是因为chrome 版本过低, 在chrome 85 以上版本才支持 用法 replaceAll(pattern, replacement)const paragraph "I think Ruths dog is cuter than your dog!"; console…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...
循环冗余码校验CRC码 算法步骤+详细实例计算
通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)࿰…...
[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?
论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...
ETLCloud可能遇到的问题有哪些?常见坑位解析
数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...
EtherNet/IP转DeviceNet协议网关详解
一,设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络,本网关连接到EtherNet/IP总线中做为从站使用,连接到DeviceNet总线中做为从站使用。 在自动…...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...
mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...
