【Unity云消散】简单理论基础:实现边缘光

news2024/11/26 19:31:02

写在前面

既然想要实现云的消散效果,那么边缘光如何计算也是一个重点。

在Unity Shader入门精要的14章,介绍轮廓线渲染就介绍了——轮廓边检测,而边缘光也是需要先检测出轮廓边再进行的。

Unity3D Shader系列之边缘光RimLight

这篇博客给了我很大的启发,引言部分说了为什么花了很长时间把渲染管线、坐标变换这些基础的东西学清楚了,想要实现某种效果的时候还是要重新学习——欠缺算法知识。感觉还是要去主动想实现某种东西再有针对性的学习,这样学习得才更加深刻。

...有些扯远了,这篇文章简简单单实现边缘光,为之后实现云消散做铺垫,当然,卡通渲染边缘光还有很多讲究,包括描边也有很多需要学习的,之后再涉及。

1 简单的算法介绍

判断边缘

边缘光跟轮廓线渲染异曲同工,其核心都是找到边缘,而找边缘的算法原理很简单:当视线看向物体边缘的时候,视线与边缘的顶点法线是垂直的(很好理解吧!),那么我们依靠视线方向和模型面片法线的点积就能实现边缘判断,所以一切的核心最终凝炼成了:

// 点积
dot(worldNormal, worldViewDir);

判断是边缘后,叠一层边缘光颜色就行。

2 shader中实现

写过一点点shader的或许都有这样一种感觉:有时候明明道理很简单,但在frag里实现时又需要添加一些范围限定的函数(pow/saturate那些),才能得到最终的效果,这里也不例外:

// 1.点积
dot(worldNormal, worldViewDir);
// 2.(1 - 点积结果)&&(加个saturate控制到0,1之间) 
saturate(1 - dot(worldNormal, worldViewDir));

叠加必要的_RimColor和_RimIntensity,这样的话在shader中就是:

fixed4 rimLight = _RimColor * saturate(1 - dot(worldNormal, worldViewDir));

Shader中代码:

Shader "Unlit/rim"
{
    Properties
    {
        _BaseColor ("Base Color", Color) = (0,0,0,0)
        _RimColor ("Rim Color", Color) = (0,0,0,0)
        _RimPower ("Rim Power", Range(0.0001, 5.0)) = 1.0
        _RimIntensity ("Rim Intensity", Range(0, 100.0)) = 1.0

    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                float3 normal : NORMAL;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                float3 worldNormal : TEXCOORD1;
                float3 worldViewDir : TEXCOORD2;
            };

            fixed4 _BaseColor;

            fixed4 _RimColor;
            float _RimIntensity;

            float _RimPower;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.worldNormal = UnityObjectToWorldNormal(v.normal);
                o.worldViewDir = WorldSpaceViewDir(v.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed3 worldNormal = normalize(i.worldNormal);
                fixed3 worldViewDir = normalize(i.worldViewDir);

                fixed4 diffuse = _BaseColor;

                fixed4 rimLight = _RimColor * saturate(1 - dot(worldNormal, worldViewDir)) * _RimIntensity;
                //fixed4 rimLight = _RimColor * pow(saturate(1 - dot(worldNormal, worldViewDir)), 1.0 / _RimPower) * _RimIntensity;

                fixed3 col = diffuse.rgb + rimLight.rgb;
                return fixed4(col,1.0);
            }
            ENDCG
        }
    }
}

效果:

衰减效果

原本的效果其实是没有什么衰减而言的,但是边缘光其实应该有个过渡效果,用上pow()就能实现啦。

算上pow:

fixed4 rimLight = _RimColor * pow(saturate(1 - dot(worldNormal, worldViewDir)), 1.0 / _RimPower) * _RimIntensity;

效果: 

【Cel-Shading】边缘光的实现 | Invictus maneo (x-wflo.github.io) 中有说遇到的问题

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/153728.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Go专家编程读书小记

文章目录协程进程和线程进程:进程间通信:线程:区别:协程GMP模型调度策略内存管理内存分配span:cache:central:heap:垃圾回收常见的垃圾回收算法:三色标记:垃圾…

【NI Multisim 14.0原理图设计基础——查找元器件】

目录 序言 一、查找元器件 🍍1.浏览元器件 🍍2.搜索元器件 🍍 3.显示找到的元器件及其所属元器件库 🍍 4.加载找到元器件的所属元器件库 序言 NI Multisim最突出的特点之一就是用户界面友好。它可以使电路设计者方便、快捷地…

大资金现金管理的利器:稳定币网格做市策略

数量技术宅团队在CSDN学院推出了量化投资系列课程 欢迎有兴趣系统学习量化投资的同学,点击下方链接报名: 量化投资速成营(入门课程) Python股票量化投资 Python期货量化投资 Python数字货币量化投资 C语言CTP期货交易系统开…

从一条记录说起—— InnoDB 记录结构

准备工作 到现在为止,MySQL对于我们来说还是一个黑盒,我们只负责使用客户端发送请求并等待服务器返回结果,表中的数据到底存到了哪里?以什么格式存放的?MySQL是以什么方式来访问的这些数据?这些问题我们统…

springboot构造树形结构数据并查询的方法

因为项目需要,页面上需要树形结构的数据进行展示(类似下图这样),因此需要后端返回相应格式的数据。 不说废话,直接开干!!! 我这里用的是springboot+mybatis-plus+mysql,示例的接口是查询一级权限以及二级权限、三级权限整个权限树… 下面是导入的maven依赖 <depe…

SSD核心设计

摘要本文介绍了此类设计选择的分类&#xff0c;并使用跟踪驱动的模拟器和从实际系统中提取的工作负载跟踪分析各种配置的可能性能。我们发现SSD性能和生命周期对工作负载非常敏感&#xff0c;并且通常较高的复杂系统问题出现在存储堆栈中甚至在分布式系统中&#xff0c;与设备固…

9. 回文数

文章目录题目描述方法一 转换为字符串方法二 转存入数组方法三 数学方法倒转数字方法四 对折参考文献题目描述 给你一个整数 x &#xff0c;如果 x 是一个回文整数&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 回文数是指正序&#xff08;从左向右&…

树脂吸附处理冶炼含钴丨废水四氯化三钴、草酸钴废水回收钴

生产过程中会产生含钴废水&#xff0c;现有技术中&#xff0c;处理含钴废水的方法主要有化学沉淀法、吸附法、膜分离法等。 对于化学沉淀法&#xff0c;原理是通过向废水中添加一定的沉淀剂&#xff0c;使其与废水中溶解性的钴离子反应生成沉淀&#xff0c;通过重力沉降去除钴…

ArcGIS 前端动态地图与要素服务符号化的区别小结

在ArcGIS中&#xff0c; 除了在桌面端做配图之外&#xff0c;一些符号化工作也可以在代码端去进行设置&#xff0c;这里简单的做了一些测试及小结。 一、服务的区别 在ArcGIS中最基础的两种数据服务就是动态地图服务&#xff08;MapServer&#xff09;和要素服务&#xff08;…

Spring Boot 教程

Spring Boot 教程Spring Boot 基础开发Spring Boot 简介Spring Boot 第一个项目Spring Boot 项目启动机制Spring Boot 数据访问Spring Boot 集成 MyBatisSpring Boot 运行管理Spring Boot 日志管理Spring Boot 异常处理Spring Boot 定时任务Spring Boot 使用拦截器Spring Boot …

C#汽车美容管理服务系统源码 功能强大代码完整,开源分享!

一套完整的汽车美容管理服务系统源码&#xff0c;专门服务于汽车美容4s店&#xff0c;终端功能强大而又简便实用&#xff0c;界面友好而美观&#xff0c;让用户更好的体验度,基于jquery技术实现页面无刷新,可广泛适用于大型以及小型汽车美容机修等公司&#xff0c;包含 洗车、机…

【异常】记一次前端因资源无法加载导致白屏异常问题

一、背景 自从运维同事强烈要求前端的环境要使用多套的&#xff0c;参考文章 【项目】参考若依的前端框架去多环境 于是一番捣鼓与改造之后&#xff0c;看似已经顺利了 但运维说&#xff0c;前端还是有问题&#xff0c;需要他帮我改下&#xff0c;于是改了如下内容 什么嘛&a…

常用的git管理逻辑

//首先创建新的分支 git branch new_branch//切换到另一个分支 git checkout new_branch//修改代码&#xff0c;添加新的文件 git add .//查看文件的状态 git status//打包自己的改变 git commit -m "comment"//推到远程服务器上 git push origin new_branch// 拉远程…

2022年度打印机行业数据报告:十大热门品牌销量排行榜

随着5G技术的发展&#xff0c;越来越多的设备与人员将通过网络实现互联互通&#xff0c;打印的输入端口与输出端口变得多样与兼容&#xff0c;打印机也在越来越多的领域发挥着强大的作用。并且&#xff0c;随着电子化教学的不断推进以及普及&#xff0c;加之线上办公等场景的需…

Hudi系列2:Hudi安装

文章目录编译环境准备一. 下载并解压hudi二. maven的下载和配置2.1 maven的下载和解压2.2 添加环境变量到/etc/profile中2.3 修改为阿里镜像三. 编译hudi3.1 修改pom文件3.2 修改源码兼容hadoop33.3 手动安装Kafka依赖3.4 解决spark模块依赖冲突3.4.1 修改hudi-spark-bundle的p…

LeetCode 3. 无重复字符的最长子串

&#x1f308;&#x1f308;&#x1f604;&#x1f604; 欢迎来到茶色岛独家岛屿&#xff0c;本期将为大家揭晓LeetCode 3. 无重复字符的最长子串&#xff0c;做好准备了么&#xff0c;那么开始吧。 &#x1f332;&#x1f332;&#x1f434;&#x1f434; 目录 一、题目名称…

(02)Cartographer源码无死角解析-(48) 2D点云扫描匹配→暴力搜索匹配原理讲解,扫面匹配总体框架梳理

讲解关于slam一系列文章汇总链接:史上最全slam从零开始&#xff0c;针对于本栏目讲解(02)Cartographer源码无死角解析-链接如下: (02)Cartographer源码无死角解析- (00)目录_最新无死角讲解&#xff1a;https://blog.csdn.net/weixin_43013761/article/details/127350885 文末…

2022消费市场并未降级?麦肯锡调研报告解读

近日全球知名咨询公司麦肯锡发布《2023中国消费者报告》&#xff0c;重磅发布重塑中国消费市场的五大趋势。 趋势一&#xff1a;中等收入人群继续壮大 MGI数据显示&#xff0c;2019~2021年&#xff0c;年收入超过16万元人民币&#xff08;2.18万美元&#xff09;的中国城镇家…

nacos配置动态刷新及监听到变化触发一些方法

介绍在使用spring 时&#xff0c;动态更新配置是常见的&#xff0c;属性值更新&#xff0c;但是需要开启支持刷新功能&#xff0c;一个是spring.cloud.nacos.config.isRefreshEnabledtrue; 这个值一般是默认的&#xff0c;可以在nacosConfigProperties这个类中看到。还要在扩展…

【C++】list介绍及使用模拟实现对比vector

文章目录1. list的介绍及使用1.1 list的介绍1.2 list的使用1.2.1 list的构造1.2.2 list iterator以及insert和erase的使用1.2.3 list的迭代器失效2. list的模拟实现2.1 模拟实现list3.&#xff08;本文精华&#xff09;list与vector的对比1. list的介绍及使用 1.1 list的介绍 …