本文分享基于兰伯特漫反射的色散(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)效果解析相关推荐

  1. Unity shader学习-漫反射-兰伯特光照模型和半兰伯特光照模型

    兰伯特漫反射公式:Diffuse = 直射光颜色 *物体颜色* max(0,cos夹角(光和法线的夹角) ) 下面给出顶点漫反射代码:   Shader "Unlit/005" { ...

  2. Unity shader 使用 半兰伯特 (Half-Lambert)漫反射会使得模型在没有直射光的情况下漆黑一片

    问题: Unity shader 使用 半兰伯特 (Half-Lambert)漫反射会使得模型在没有直射光的情况下漆黑一片,原因不得而知. 使用半兰伯特漫反射代码如下: *************** ...

  3. Shader学习2——兰伯特

    本以为写个兰伯特很简单,但是仔细考虑了一下,不光要受场景中光源影响,还需要受环境光影响,然后发现单个pass通道只能实现单光源.因此前期我们都只考虑单平行光. 兰伯特:漫反射颜色 = 光源颜色 x 材 ...

  4. Shader学习3——半兰伯特

    半兰伯特其实就是把暗的地方提亮了一些,在数值上就是获取到的光源强度* 0.5 + 0.5,也就是原来是0的会变成0.5,原来是1的还是1. 半兰伯特:漫反射颜色 = 光源颜色 x 材质的漫反射颜色 x ...

  5. Lambert (兰伯特)光照模型

    Lambert (兰伯特)光照模型 是光源照射到物体表面后,向四面八方反射,产生的漫反射效果.这是一种理想的漫反射光照模型.如下图:这个是顶点函数处理后的该光照模型,因此看起来像素不够平滑. 漫反射 ...

  6. Shader学习第六篇:Lambert (兰伯特)光照模型

    漫反射的定义 漫反射是投射在粗糙表面上的光向各个方向反射的现象.当一束平行的入射光线射到粗糙的表面时,表面会把光线向着四面八方反射,所以入射线虽然互相平行,由于各点的法线方向不一致,造成反射光线向不同 ...

  7. Paxos算法是莱斯利·兰伯特(Leslie Lamport)1990年提出的一种基于消息传递的一致性算法。

    Paxos算法是莱斯利·兰伯特(Leslie Lamport)1990年提出的一种基于消息传递的一致性算法.Paxos算法解决的问题是一个分布式系统如何就某个值(决议)达成一致.在工程实践意义上来说, ...

  8. 漫反射:兰伯特和半兰伯特

    兰伯特定律(Lambert is law); 反射光线的强度与表面法线和光源方向之间夹角的余弦值成正比: 漫反射公式:C diffuse=(C light * M diffuse)max(0, < ...

  9. 6.2 漫反射-半兰伯特

    //漫反射 半兰伯特 diffuse = (c.m)(0.5(n.i)+0.5) //模型背光面有可以有明暗变化 Shader "Unity shader book/Chapter 6/Ha ...

最新文章

  1. RabbitMQ 消费端限流、TTL、死信队列
  2. 计算机制图国家规范,竣工图绘制相关国家规范
  3. std::mutex
  4. 与WebXR共同创建者Diego Marcos一起探讨沉浸式Web的未来(上)
  5. python初学者用什么编辑器好_新人学 python 选什么编辑器比较好呢??
  6. 在ASP.NET Core中编写合格的中间件
  7. 每个人都应该使用的Python 3中被忽略的3个功能
  8. i茅台app上线首日,直接冲到了App Store免费榜第一
  9. Spring MVC DispatcherServlet介绍
  10. Protobuf简单编写与使用
  11. java day60【 Spring 中的 JdbcTemplate[会用] 、Spring 中的事务控制 、Spring5 的新特性[了解] 】...
  12. 从零基础入门Tensorflow2.0 ----八、39.1 gpu1
  13. Bootstrap 3.2.0 源码试读 2014/08/14
  14. C语言 汉字ASCII转Unicode
  15. sql server 代理权限问题
  16. VC++使用管道重定向进程输入输出(附源码)
  17. matlab示波器有毛刺,在使用示波器时如何消除毛刺?
  18. 2022-06-26 笔记本新机重装系统
  19. phalcon mysql_phalcon数据库操作
  20. 关于虚拟机.vmdk与.ovf 磁盘装载问题

热门文章

  1. 快上车!攻击全球电视、银行大盗火线追踪、黑客篡改支付金额,雷锋网带你闯进 SyScan 360...
  2. 用代码来理解MapReduce2_分组分区和combin优化
  3. python抓包遇到Status 400 - Required String parameter ‘params‘ is not present错误
  4. win10永久关闭自动更新的方法
  5. 华院计算|维托里斯—最长寿的数学家
  6. jansson库double精度控制
  7. codeforces 124A The number of positions
  8. 如何理解信息隐蔽和局部化?
  9. Docker 镜像概念及操作
  10. idea html注释,IntelliJ IDEA文档注释