基于兰伯特漫反射的色散(Dispersion)效果解析
本文分享基于兰伯特漫反射的色散(Dispersion)效果解析
我们知道, 兰伯特漫反射可以表现渐变的明暗效果, 而这种明暗效果可以结合一些手段来实现很多有意思的效果, 今天就给大家介绍其中一种.
先看看最终效果:
效果解析
可以看到, 颜色分布由暗到明, 分别是: 黑色->蓝色->天蓝->白色.
我们使用兰伯特漫反射表现明暗变化, 为了比较清晰的观察变化, 这里使用球的模型:
Shader "Custom/Dispersion" {Properties {_RangeColor ("RangeColor", Color) = (0.5,0.8,0.2,1)_node_6044 ("node_6044", Color) = (0.5,0.5,0.5,1)}SubShader {Tags {"RenderType"="Opaque"}Pass {Name "FORWARD"Tags {"LightMode"="ForwardBase"}CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"#pragma multi_compile_fwdbase_fullshadows#pragma target 3.0struct VertexInput {float4 vertex : POSITION;float3 normal : NORMAL;};struct VertexOutput {float4 pos : SV_POSITION;float4 posWorld : TEXCOORD0;float3 normalDir : TEXCOORD1;};VertexOutput vert (VertexInput v) {VertexOutput o = (VertexOutput)0;o.normalDir = UnityObjectToWorldNormal(v.normal);o.posWorld = mul(unity_ObjectToWorld, v.vertex);o.pos = UnityObjectToClipPos( v.vertex );return o;}float4 frag(VertexOutput i) : COLOR {i.normalDir = normalize(i.normalDir);float3 normalDirection = i.normalDir;float3 lightDirection = normalize(_WorldSpaceLightPos0.xyz);// 着色代码--beginfloat nDotl = saturate(dot(i.normalDir,lightDirection));float3 finalColor = nDotl;// 着色代码--endreturn fixed4(finalColor,1);}ENDCG}}FallBack "Diffuse"
}
效果如下:
可以看到, 大概从一半的位置往右上角渐变, 越来越白.
一次分割
接下来使用step
函数来分散明暗色:
// 着色代码--begin
float nDotl = max(0,dot(i.normalDir,lightDirection));
float color = step(0.6,nDotl);
float3 finalColor = float3(color,color,color);
return fixed4(finalColor,1);
// 着色代码--end
step(a, b)
是一个内置函数, 其作用为a <= b
时返回1, a > b
时返回0.
如果其中的参数是向量, 则每个分量分别处理, 如:
step(float2(0.5, 0.8), 0.6)
// 则得到二维向量 => (1, 0)
// 0.5 <= 0.6 => 1
// 0.8 > 0.6 => 0
漫反射值超过0.6的部分将显示为纯白, 其它部分为纯黑, 当前阶段效果如下:
二次分割
使用二维向量来分散明暗色:
// 着色代码--begin
float nDotl = max(0,dot(i.normalDir,lightDirection));
float2 color = step(float2(0.6, 0.2),nDotl);
float3 finalColor = float3(color,0);
return fixed4(finalColor,1);
// 着色代码--end
漫反射值超过0.6的部分将显示为纯黄, 0.2到0.6之间的部分将显示为纯绿, 当前阶段效果如下:
这是最容易让人迷惑的部分, 为什么是黄色和绿色呢?
首先我们要明白一点: step
函数的第一个参数的维度数代表要对球进行"分割"的次数, 比如本阶段的第一个参数为二维向量, 表示要将球"分割"两次, 变成三个部分.
然后我们分别分析其颜色构成:
明暗值大于0.6的部分, 肯定也是大于0.2的, 所以大于0.6的部分, 经过step
后会输出(1, 1, 0)
也就是纯黄色.
也就是说:
step(float2(0.6, 0.2), 0.8)
// => float2(1, 1)
而0.2到0.6的部分, 经过step
后会输出(0, 1, 0)
也就是纯绿色.
同理可得:
step(float2(0.6, 0.2), 0.5)
// => float2(0, 1)
最后小于0.2的部分将输出(0, 0, 0)
, 即纯黑色:
step(float2(0.6, 0.2), 0.1)
// => float2(0, 0)
三次分割
然后使用三维向量进行分割:
// 着色代码--begin
float nDotl = max(0,dot(i.normalDir,lightDirection));
float3 color = step(float3(0.8, 0.5, 0.2),nDotl);
float3 finalColor = float3(color);
return fixed4(finalColor,1);
// 着色代码--end
效果如下:
超过0.8的部分显示为白色:
step(float2(0.8, 0.5, 0.2), 0.9)
// => float2(1, 1, 1)
0.5到0.8的部分显示为天蓝色:
step(float2(0.8, 0.5, 0.2), 0.6)
// => float2(0, 1, 1)
0.2到0.5的部分显示为纯蓝色:
step(float2(0.8, 0.5, 0.2), 0.6)
// => float2(0, 0, 1)
小于0.2的部分为纯黑色:
step(float2(0.8, 0.5, 0.2), 0.6)
// => float2(0, 0, 0)
切换模型后就可得到图1的效果.
总结
今天分享在兰伯特漫反射的基础上进行色散的效果, 利用漫反射的明暗过度, 使用step
来分区颜色达到想要的效果.
因为step
函数的输出只有0和1, 所以该效果的颜色是有限的, 当然, 我们也可以在这个基础上进一步做更多的效果.
step
的分割次数和最后输出颜色的关系:
- 一次分割: 只能得到纯黑(0, 0, 0)和纯白(1, 1, 1)
- 二次分割: 能得到纯黑(0, 0, 0), 纯红(1, 0, 0), 纯绿(0, 1, 0), 纯黄(1, 1, 0)
- 三次分割: 能得到纯蓝(0, 0, 1), 天蓝(0, 1, 1), 纯白(1, 1, 1), 粉红(1, 0, 1)
可以将step
的结果理解为分割颜色后得到某个颜色遮罩, 然后按照区间计算颜色.
好了, 今天分享就这么多, 希望对大家有所帮助.
基于兰伯特漫反射的色散(Dispersion)效果解析相关推荐
- Unity shader学习-漫反射-兰伯特光照模型和半兰伯特光照模型
兰伯特漫反射公式:Diffuse = 直射光颜色 *物体颜色* max(0,cos夹角(光和法线的夹角) ) 下面给出顶点漫反射代码: Shader "Unlit/005" { ...
- Unity shader 使用 半兰伯特 (Half-Lambert)漫反射会使得模型在没有直射光的情况下漆黑一片
问题: Unity shader 使用 半兰伯特 (Half-Lambert)漫反射会使得模型在没有直射光的情况下漆黑一片,原因不得而知. 使用半兰伯特漫反射代码如下: *************** ...
- Shader学习2——兰伯特
本以为写个兰伯特很简单,但是仔细考虑了一下,不光要受场景中光源影响,还需要受环境光影响,然后发现单个pass通道只能实现单光源.因此前期我们都只考虑单平行光. 兰伯特:漫反射颜色 = 光源颜色 x 材 ...
- Shader学习3——半兰伯特
半兰伯特其实就是把暗的地方提亮了一些,在数值上就是获取到的光源强度* 0.5 + 0.5,也就是原来是0的会变成0.5,原来是1的还是1. 半兰伯特:漫反射颜色 = 光源颜色 x 材质的漫反射颜色 x ...
- Lambert (兰伯特)光照模型
Lambert (兰伯特)光照模型 是光源照射到物体表面后,向四面八方反射,产生的漫反射效果.这是一种理想的漫反射光照模型.如下图:这个是顶点函数处理后的该光照模型,因此看起来像素不够平滑. 漫反射 ...
- Shader学习第六篇:Lambert (兰伯特)光照模型
漫反射的定义 漫反射是投射在粗糙表面上的光向各个方向反射的现象.当一束平行的入射光线射到粗糙的表面时,表面会把光线向着四面八方反射,所以入射线虽然互相平行,由于各点的法线方向不一致,造成反射光线向不同 ...
- Paxos算法是莱斯利·兰伯特(Leslie Lamport)1990年提出的一种基于消息传递的一致性算法。
Paxos算法是莱斯利·兰伯特(Leslie Lamport)1990年提出的一种基于消息传递的一致性算法.Paxos算法解决的问题是一个分布式系统如何就某个值(决议)达成一致.在工程实践意义上来说, ...
- 漫反射:兰伯特和半兰伯特
兰伯特定律(Lambert is law); 反射光线的强度与表面法线和光源方向之间夹角的余弦值成正比: 漫反射公式:C diffuse=(C light * M diffuse)max(0, < ...
- 6.2 漫反射-半兰伯特
//漫反射 半兰伯特 diffuse = (c.m)(0.5(n.i)+0.5) //模型背光面有可以有明暗变化 Shader "Unity shader book/Chapter 6/Ha ...
最新文章
- RabbitMQ 消费端限流、TTL、死信队列
- 计算机制图国家规范,竣工图绘制相关国家规范
- std::mutex
- 与WebXR共同创建者Diego Marcos一起探讨沉浸式Web的未来(上)
- python初学者用什么编辑器好_新人学 python 选什么编辑器比较好呢??
- 在ASP.NET Core中编写合格的中间件
- 每个人都应该使用的Python 3中被忽略的3个功能
- i茅台app上线首日,直接冲到了App Store免费榜第一
- Spring MVC DispatcherServlet介绍
- Protobuf简单编写与使用
- java day60【 Spring 中的 JdbcTemplate[会用] 、Spring 中的事务控制 、Spring5 的新特性[了解] 】...
- 从零基础入门Tensorflow2.0 ----八、39.1 gpu1
- Bootstrap 3.2.0 源码试读 2014/08/14
- C语言 汉字ASCII转Unicode
- sql server 代理权限问题
- VC++使用管道重定向进程输入输出(附源码)
- matlab示波器有毛刺,在使用示波器时如何消除毛刺?
- 2022-06-26 笔记本新机重装系统
- phalcon mysql_phalcon数据库操作
- 关于虚拟机.vmdk与.ovf 磁盘装载问题
热门文章
- 快上车!攻击全球电视、银行大盗火线追踪、黑客篡改支付金额,雷锋网带你闯进 SyScan 360...
- 用代码来理解MapReduce2_分组分区和combin优化
- python抓包遇到Status 400 - Required String parameter ‘params‘ is not present错误
- win10永久关闭自动更新的方法
- 华院计算|维托里斯—最长寿的数学家
- jansson库double精度控制
- codeforces 124A The number of positions
- 如何理解信息隐蔽和局部化?
- Docker 镜像概念及操作
- idea html注释,IntelliJ IDEA文档注释