热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

UnityShader一个博主关于边缘光的总结

边缘光,内发光,外发光,轮廓边缘光,轮廓内边缘光,轮廓外边缘光::先上一张图片,看下实际效果1:黑色为模型主color2:白色为内发光,轮廓内边缘光3:红色为外发光,轮廓外边缘光S

边缘光,内发光,外发光,轮廓边缘光,轮廓内边缘光,轮廓外边缘光::

先上一张图片,看下实际效果
1:黑色为模型主color
2:白色为内发光,轮廓内边缘光
3:红色为外发光,轮廓外边缘光

Shader "Unlit/边缘光" {     Properties     {         _MainColor ("MainColor", Color) = (0,0,0,1) //模型主颜色           _InSideRimColor ("InSideRimColor", Color) = (1,1,1,1)//内边缘光颜色         _InSideRimPower("InSideRimPower", Range(0.0,5)) = 0 //边缘光强度  ,这个值可以控制菲涅尔影响范围的大小,这个值越大,效果上越边缘化         _InSideRimIntensity("InSideRimIntensity", Range(0.0, 10)) = 0  //边缘光强度系数 这个值是反射的强度, 值越大,返回的强度越大,导致边缘的颜色不那么明显           _OutSideRimColor ("OutSideRimColor", Color) = (1,1,1,1)//外边缘光颜色         _OutSideRimSize("OutSideRimSize", Float) = 0 //因为外边缘光,需要把模型外扩,这是外扩大小         _OutSideRimPower("OutSideRimPower", Range(0.0,5)) = 0 //边缘光强度  ,这个值可以控制菲涅尔影响范围的大小,这个值越大,效果上越边缘化         _OutSideRimIntensity("OutSideRimIntensity", Range(0.0, 10)) = 0  //边缘光强度系数 这个值是反射的强度, 值越大,返回的强度越大,导致边缘的颜色不那么明显       }     SubShader     {         Tags { "RenderType"="Opaque" }         LOD 100         Pass  //内边缘光pass         {             CGPROGRAM             #pragma vertex vert             #pragma fragment frag             #include "UnityCG.cginc"             #include "Lighting.cginc"             uniform float4 _MainColor;             uniform float4 _InSideRimColor;             uniform float  _InSideRimPower;             uniform float _InSideRimIntensity;               struct appdata             {                 float4 vertex : POSITION;                 float2 uv : TEXCOORD0;                 float3 normal : NORMAL;                 float4 tangent : TANGENT;             };             struct v2f             {                 float2 uv : TEXCOORD0;                 float3 normal : TEXCOORD1;                 float4 vertex : SV_POSITION;                 float4 vertexWorld : TEXCOORD2;             };             v2f vert (appdata v)             {                 v2f o;                 o.normal = mul(unity_ObjectToWorld, float4(v.normal,0)).xyz;                 o.vertex = UnityObjectToClipPos(v.vertex);                 o.vertexWorld = mul(unity_ObjectToWorld, v.vertex);                 o.uv = v.uv;                 return o;             }                          fixed4 frag (v2f i) : SV_Target             {                 i.normal = normalize(i.normal);//下面计算方式套用菲涅尔计算                 float3 worldViewDir = normalize(_WorldSpaceCameraPos.xyz - i.vertexWorld.xyz);//获取单位视角方向   相机世界空间位置减去顶点世界空间位置                 half NdotV = max(0, dot(i.normal, worldViewDir));//计算法线方向和视角方向点积,约靠近边缘夹角越大,值约小,那就是会越在圆球中间约亮,越边缘约暗                 NdotV = 1.0-NdotV;//这里需求是越边缘约亮,所以需要反一下,这里用1 减下                 float fresnel =pow(NdotV,_InSideRimPower)*_InSideRimIntensity;//使用上面的属性参数,这里不多说                 float3  Emissive=_InSideRimColor.rgb*fresnel; //配置上属性里面的内边缘光颜色                 return _MainColor+float4(Emissive,1);//最后加在本体主颜色就即可             }             ENDCG         }              Pass  //外边缘光pass         {             Cull Front   //需要正面剔除,否则模型主pass渲染会看不到             Blend SrcAlpha One // 需要设置成透明叠加             CGPROGRAM             #pragma vertex vert             #pragma fragment frag             #include "UnityCG.cginc"             #include "Lighting.cginc"              uniform float4 _OutSideRimColor;              uniform float  _OutSideRimSize;              uniform float  _OutSideRimPower;              uniform float  _OutSideRimIntensity;               struct appdata             {                 float4 vertex : POSITION;                 float2 uv : TEXCOORD0;                 float3 normal : NORMAL;                 float4 tangent : TANGENT;             };             struct v2f             {                 float2 uv : TEXCOORD0;                 float3 normal : TEXCOORD1;                 float4 vertex : SV_POSITION;                 float4 vertexWorld : TEXCOORD2;             };             v2f vert (appdata v)             {                 v2f o;                 o.normal = mul(unity_ObjectToWorld, float4(v.normal,0)).xyz;                 v.vertex.xyz += v.normal*_OutSideRimSize;  //顶点进行外扩                 o.vertex = UnityObjectToClipPos(v.vertex);                 o.vertexWorld = mul(unity_ObjectToWorld, v.vertex);                 o.uv = v.uv;                 return o;             }                          fixed4 frag (v2f i) : SV_Target             {                 i.normal = normalize(i.normal);//**下面计算方式套用菲涅尔计算区别在下面2点**                 //float3 worldViewDir = normalize(_WorldSpaceCameraPos.xyz - i.vertexWorld.xyz);                 float3 worldViewDir = normalize(i.vertexWorld.xyz-_WorldSpaceCameraPos.xyz );//**区别1**:因为顶点外扩,法线不变, 这里需要反过来,顶点世界空间位置减去相机世界空间位置                 half NdotV =  dot(i.normal, worldViewDir);                 //NdotV = 1.0-NdotV;//**区别2**:因为需求是发光内强外弱,在模型外扩之后,这里就不需要反了                 float fresnel =pow(saturate(NdotV),_OutSideRimPower)*_OutSideRimIntensity;//配置上属性里面的外边缘光颜色                 return float4(_OutSideRimColor.rgb,fresnel);//这里最终计算的值,只需要用来处理返回颜色的Alpha透明度             }             ENDCG         }              } }

 对比上面图片, 可以设置,光源在左右,还上下,代码如下, 多加一行,fresnel*=i.normal.x; (左右)或者fresnel*=i.normal.y;(上下)即可

     i.normal = normalize(i.normal);//下面计算方式套用菲涅尔计算      float3 worldViewDir = normalize(_WorldSpaceCameraPos.xyz - i.vertexWorld.xyz);//获取单位视角方向   相机世界空间位置减去顶点世界空间位置      half NdotV = max(0, dot(i.normal, worldViewDir));//计算法线方向和视角方向点积,约靠近边缘夹角越大,值约小,那就是会越在圆球中间约亮,越边缘约暗      NdotV = 1.0-NdotV;//这里需求是越边缘约亮,所以需要反一下,这里用1 减下      float fresnel =pow(NdotV,_InSideRimPower)*_InSideRimIntensity;//使用上面的属性参数,这里不多说      //********************************************************      //fresnel*=i.normal.x;  //左右      fresnel*=i.normal.y;//上下      //********************************************************      float3  Emissive=_InSideRimColor.rgb*fresnel; //配置上属性里面的内边缘光颜色      return _MainColor+float4(Emissive,1);//最后加在本体主颜色就即可


原文链接:https://blog.csdn.net/qqo_aa/article/details/108524116


推荐阅读
  • 计算 n 叉树中各节点子树的叶节点数量分析 ... [详细]
  • BZOJ4240 Gym 102082G:贪心算法与树状数组的综合应用
    BZOJ4240 Gym 102082G 题目 "有趣的家庭菜园" 结合了贪心算法和树状数组的应用,旨在解决在有限时间和内存限制下高效处理复杂数据结构的问题。通过巧妙地运用贪心策略和树状数组,该题目能够在 10 秒的时间限制和 256MB 的内存限制内,有效处理大量输入数据,实现高性能的解决方案。提交次数为 756 次,成功解决次数为 349 次,体现了该题目的挑战性和实际应用价值。 ... [详细]
  • 2019年后蚂蚁集团与拼多多面试经验详述与深度剖析
    2019年后蚂蚁集团与拼多多面试经验详述与深度剖析 ... [详细]
  • 状态模式在软件设计中的应用与实现
    本文以酒店管理系统为例,探讨了状态模式在软件设计中的应用与实现。酒店房间的状态包括空闲、已预订和已入住,这些状态之间可以相互转换。通过引入状态模式,系统能够更加灵活地管理和响应不同状态下的操作,提高了代码的可维护性和扩展性。此外,状态模式还简化了状态转换的逻辑处理,使得系统的整体架构更为清晰和高效。 ... [详细]
  • 在CentOS上部署和配置FreeSWITCH
    在CentOS系统上部署和配置FreeSWITCH的过程涉及多个步骤。本文详细介绍了从源代码安装FreeSWITCH的方法,包括必要的依赖项安装、编译和配置过程。此外,还提供了常见的配置选项和故障排除技巧,帮助用户顺利完成部署并确保系统的稳定运行。 ... [详细]
  • RK算法通过比较两个字符串的哈希值来实现快速匹配,但即使哈希值相同,也不能确保两字符串完全一致,仍需进行逐字符对比以确认。此过程的时间复杂度为O(n)。此外,RK算法在文本搜索、模式识别等领域有广泛应用,并可通过多种优化策略提高其效率和准确性。 ... [详细]
  • 本文作为“实现简易版Spring系列”的第五篇,继前文深入探讨了Spring框架的核心技术之一——控制反转(IoC)之后,将重点转向另一个关键技术——面向切面编程(AOP)。对于使用Spring框架进行开发的开发者来说,AOP是一个不可或缺的概念。了解AOP的背景及其基本原理,对于掌握这一技术至关重要。本文将通过具体示例,详细解析AOP的实现机制,帮助读者更好地理解和应用这一技术。 ... [详细]
  • 本文深入探讨了 MXOTDLL.dll 在 C# 环境中的应用与优化策略。针对近期公司从某生物技术供应商采购的指纹识别设备,该设备提供的 DLL 文件是用 C 语言编写的。为了更好地集成到现有的 C# 系统中,我们对原生的 C 语言 DLL 进行了封装,并利用 C# 的互操作性功能实现了高效调用。此外,文章还详细分析了在实际应用中可能遇到的性能瓶颈,并提出了一系列优化措施,以确保系统的稳定性和高效运行。 ... [详细]
  • BZOJ1034 详细解析与算法优化
    本文深入解析了BZOJ1034问题,并提出了优化算法。通过借鉴广义田忌赛马的贪心策略,当己方当前最弱的马优于对方最弱的马时进行匹配;同样地,若己方当前最强的马优于对方最强的马,也进行匹配。此方法在保证胜率的同时,有效提升了算法效率。 ... [详细]
  • HBase在金融大数据迁移中的应用与挑战
    随着最后一台设备的下线,标志着超过10PB的HBase数据迁移项目顺利完成。目前,新的集群已在新机房稳定运行超过两个月,监控数据显示,新集群的查询响应时间显著降低,系统稳定性大幅提升。此外,数据消费的波动也变得更加平滑,整体性能得到了显著优化。 ... [详细]
  • 如何在 Java LinkedHashMap 中高效地提取首个或末尾的键值对? ... [详细]
  • 本文详细介绍了如何在Linux系统中搭建51单片机的开发与编程环境,重点讲解了使用Makefile进行项目管理的方法。首先,文章指导读者安装SDCC(Small Device C Compiler),这是一个专为小型设备设计的C语言编译器,适合用于51单片机的开发。随后,通过具体的实例演示了如何配置Makefile文件,以实现代码的自动化编译与链接过程,从而提高开发效率。此外,还提供了常见问题的解决方案及优化建议,帮助开发者快速上手并解决实际开发中可能遇到的技术难题。 ... [详细]
  • 【前端开发】深入探讨 RequireJS 与性能优化策略
    随着前端技术的迅速发展,RequireJS虽然不再像以往那样吸引关注,但其在模块化加载方面的优势仍然值得深入探讨。本文将详细介绍RequireJS的基本概念及其作为模块加载工具的核心功能,并重点分析其性能优化策略,帮助开发者更好地理解和应用这一工具,提升前端项目的加载速度和整体性能。 ... [详细]
  • 题目描述:小K不幸被LL邪教洗脑,洗脑程度之深使他决定彻底脱离这个邪教。在最终离开前,他计划再进行一次亚瑟王游戏。作为最后一战,他希望这次游戏能够尽善尽美。众所周知,亚瑟王游戏的结果很大程度上取决于运气,但通过合理的策略和算法优化,可以提高获胜的概率。本文将详细解析洛谷P3239 [HNOI2015] 亚瑟王问题,并提供具体的算法实现方法,帮助读者更好地理解和应用相关技术。 ... [详细]
  • Go语言实现Redis客户端与服务器的交互机制深入解析
    在前文对Godis v1.0版本的基础功能进行了详细介绍后,本文将重点探讨如何实现客户端与服务器之间的交互机制。通过具体代码实现,使客户端与服务器能够顺利通信,赋予项目实际运行的能力。本文将详细解析Go语言在实现这一过程中的关键技术和实现细节,帮助读者深入了解Redis客户端与服务器的交互原理。 ... [详细]
author-avatar
小小小菜鸡
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有