Unity | Shader基础知识(第十四集:简单效果练习)

news2024/11/27 8:35:24

目录

前言

一、效果预览

1.弧形边缘光

二、效果制作

1. 制作弧形边缘光

2.弧形边缘光进阶

3.弧形边缘光调节渐变范围

4.边缘光突变

5.同心圆

 三、加入世界坐标做效果

1.绘制结界

2.斑马球

3.效果合并

 四、作者的碎碎念


前言

有粉丝建议说,让我继续更新Shader,我可以出一些简单常用的效果,带着大家写一下,我觉得这是个好主意。

换句话说,带着大家看一下,学到的知识,应该怎么去应用。

我会把常见的调节的一些细致过程逐步写下来,如果遇见没讲过的知识点,就详细讲解一下。

一、效果预览

1.弧形边缘光

这个效果是,对于圆形或者圆弧形的物体,在边缘发光。(如图1所示)

图1 边缘光

二、效果制作

1. 制作弧形边缘光

我们先统一一下思路,发光用到的语义是自发光,之前有讲过,详情看链接。

Unity | Shader基础知识(第十二集:颜色混合)_shade 颜色混合接口-CSDN博客

边缘发光就是当我们的视线和法线的点乘的值在0附近,或0以下的时候,就发光,也是之前讲的,看链接。(如图2所示)Unity | Shader基础知识(第十三集:编写内置着色器阶段总结和表面着色器的补充介绍)_unity viewdir-CSDN博客

图2 viewDir

后面写代码,讲太多遍的就不重新注释了,只注释没讲过的。

Shader "Custom/010"
{
     Properties
    {
    //设置自发光的颜色
    _Color("Color",Color)=(0,0.5,0.5,0)
    }

    SubShader
    {
    CGPROGRAM
    #pragma surface surf Lambert

    float4 _Color;

    struct Input
    {
        //直接获取viewDir
        float3 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所示)

图3 发光球

2.弧形边缘光进阶

大部分模型都是有自己贴图的,所以我们在发光的基础上,加上贴图

Shader "Custom/010"
{
     Properties
    {
    //放图片进入
    _MainTex("MainTex",2D)="white"{} 
    //设置自发光的颜色
    _Color("Color",Color)=(0,0.5,0.5,0)
    }

    SubShader
    {
    CGPROGRAM
    #pragma surface surf Lambert

    sampler2D _MainTex;
    float4 _Color;

    struct Input
    {
        float2 uv_MainTex;

        //直接获取viewDir
        float3 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所示)

图4 弧形边缘光进阶

3.弧形边缘光调节渐变范围

大部分时候,上面的发光范围都是有点大了,所以我们需要加个参数进行调节。

数学知识:

_Color.rgb*(1-dotp)中的(1-dotp)是一个线性变化的数据,变化是平均的,就像数数一样:0.1,0.2,0.3......

我们怎么才能让它的增长变快?前面一直比较小,越往后越大。

有一个非常简单的方法:平方

{0.1^{2}}{0.2^{2}}{0.3^{2}}.......

如果你觉得平方变化不满意,可以是其他次方

 所以我们增加一个参数,来改变光范围。

函数知识:

次方的公式是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 Lambert

    sampler2D _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所示)

图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,反之等于0
        o.Emission =_Color.rgb*dotp>0.8?1:0;
    }

效果(如图6所示)

图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 Lambert

    sampler2D _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所示)

图7 同心圆

备注:多层同心圆

//多层同心圆                                            //用了个绿色
o.Emission =dotp>0.8?_Color.rgb:dotp>0.5?_Color2.rgb:float4(0,1,0,0);
图8 多层同心圆

 三、加入世界坐标做效果

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所示)

图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所示)

图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所示)

图11 效果合并

是不是有那味了~ 

 四、作者的碎碎念

考虑到好多宝宝,学了功能也不知道怎么去用, 专门出了这个简单应用专题,供大家练习。

喜欢的话希望大家给我点赞,收藏加关注哦~ღ( ´・ᴗ・` )比心

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

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

相关文章

R可视化:微生物相对丰度或富集热图可视化

欢迎大家关注全网生信学习者系列: WX公zhong号:生信学习者Xiao hong书:生信学习者知hu:生信学习者CDSN:生信学习者2介绍 热图(Heatmap)是一种数据可视化方法,它通过颜色的深浅或色调的变化来展示数据的分布和密度。在微生物学领域,热图常用于表示微生物在不同分组(如…

代发考生战报:HCIP H12-725安全变题了

代发考生战报:HCIP H12-725安全变题了,幸好当天找客服办理的包过服务,听同考场的考生说,考试全是新题,只有1-2个是题库上的题,自己考的都考挂了,帮我答题的老师很厉害,很赞&#xff…

Web后端开发的学习

REST风格 GET:查询用户POST:新增用户POT:修改用户DELETE:删除用户 前后端交互统一的响应结果 记录日志 SLf4j 注解: PathVariable:获取路径的参数ResponseBody :方法的返回值直接作为 HTTP 响应的正文返回,将响应的实体类转为json发送给前端Request…

qml自定义组件

不管是component还是分文件编写的一个自定义组件,遵循如下: a:不管哪一级的子对象 都可以直接调根节点下的方法和属性 b:不管哪一级的子对象 调用非根节点的方法和属性,前面要加上该节点的id,即id.方法()或id.属性的形式 import QtQuick 2.…

《Java2实用教程》 期末考试整理

作用域 当前类 当前包 子类 其他包 public √ √ √ √ protected √ √ √ default √ √ private √ 三、问答题(每小题4分,共8分) 1.类与对象的关系 对象:对象是类的一个实例,有状…

Oracle--数据字典

1.介绍 数据字典是Oracle存储数据库内部信息的地方,描述了数据库内部的运行和管理情况 Oracle数据字典的名称由前缀和后缀组成,使用下划线_连接: dba_:包含数据库实例的所有对象信息v$_:当前实例的动态视图&#xff0…

成龙“参战”暑期档,2024会成为博纳的爆发之年吗?

作为全年最长的档期,暑期档即将迎来观影高峰期,电影市场的竞争已然打响。 根据猫眼数据,目前共有79部影片预计在暑期档上映,且数量仍在持续攀升,这个暑假线下影院势必会非常热闹。 不过电影数量虽多,却依…

RTOS笔记--资源管理

资源管理 资源管理,其实就是前面介绍过的通知方式中的队列信号量互斥量等是如何访问临界资源的,如何做到完全互斥。 在之前举过一个例子:当我们使用全局变量来进行互斥操作时,有可能在改写全局变量时被切换使得不再互斥&#xff0…

一、开发环境安装 Avalonia

1、概述 官网中是这么介绍Avalonia的,Avalonia是一个强大的框架,使开发人员能够使用.NET创建跨平台应用程序。它使用自己的渲染引擎绘制UI控件,确保在Windows、macOS、Linux、Android、iOS和WebAssembly等不同平台上具有一致的外观和行为。这…

黄金价格与美元的关系变了?

在一些传统的定价框架中,现货黄金的价格走势取,决于美元的实际利率水平——实际利率越高,黄金价格越低,反之亦然。在大多数的时候,美元的实际利率决定了美元指数的高低所以人们通常认为,现货金价与美元呈反…

装机后操作纪录

刚刚装完机 什么都没有 就像在一片一望无际的草原 要恢复原来笔记本的“秩序” 就像在这个草原建立全新的王国 1、关于显示器电脑屏幕图标巨大且糊的处理方法 用一台可正常使用的电脑,到主板官网下载相关驱动。(铭瑄B760M D4 WIFI驱动下载) 2、关于桌面没有显示“…

电感的本质是什么

什么是电感? 电感器件一般是指螺线圈,由导线圈一圈靠一圈地绕在绝缘管上,绝缘管可以是空心的,也可以包含铁芯或磁粉芯。 为什么把’线’绕成’圈’就是电感? 电感的工作原理非常抽象,为了解释什么是电感…

货代小白快来收藏‼️普货与非普货的区别

普货是指不属于以下类别的普通货物 危险品 冷冻/冷藏品 违禁品 仿牌货 敏感货 危险品 危险品具体分为九类: 爆炸品 压缩气体 易燃液体 易燃固体、易燃物品和遇湿易燃物品 氧化剂和有机氧化物 有毒和感染性物品 放射性 腐蚀性 杂类 冷冻/冷藏品 主要是指以食品为主的…

AzureDataFactory 在不同的订阅间迁移Pipeline

前面的博文中的POC是客户向微软申请的试用环境,POC结束客户也购买了Azure订阅,需要复用试用环境中的Pipeline,此时就需要将Pipeline进行迁移。 目之所及有两种方式,第一种是通过导入导出模版,选择需要迁移的Pipeline&a…

Digital Video Repair3.7.1.0 --一款免费的视频文件修复工具,供大家学习研究参考

下载地址: https://download.csdn.net/download/weixin_43097956/89431959

Vector | Graph:蚂蚁首个开源Graph RAG框架设计解读

作者:范志东 检索增强生成(RAG:Retrieval Augmented Generation)技术旨在把信息检索与大模型结合,以缓解大模型推理“幻觉”的问题。近来关于RAG的研究如火如荼,支持RAG的开源框架也层出不穷,并…

spring:深入理解@EnableAspectJAutoProxy

Hi~!这里是奋斗的小羊,很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~~ 💥💥个人主页:奋斗的小羊 💥💥所属专栏:C语言 🚀本系列文章为个人学习…

旋转的六边形

【题目描述】 输入一个整数n,绘制出n个不断旋转的六边形,如图1所示。 图1 旋转的六边形图形 【要求】 -绘制速度设为最快,画笔粗细为3。 -六边形每次旋转10度,边长增加10%。 【分析】 这是一个同心正六边,六边形边…

自定义Unity组件——ABManager(AB包管理器)

需求描述 在Unity3D引擎中,AB包作为常用的游戏资源存储格式之一。而对于资源管理我们就不得不谈到集中管理的优势了,通过统一的接口加载和卸载AB包及其中的资源将进一步提升我们的编程效率。本文将围绕这个需求进行尝试。 功能描述 1. AB包的加载包括同…

从 Solana 课程顺利毕业获得高潜岗位,他的 Web3 开发探险之旅

在 TinTinLand 的学习,给了我入门 Web3 行业的 Entry Ticket,我认为这张 Ticket 是非常宝贵和重要的。 Alex,一位从某家知名研究所毅然辞职,踏入Web3世界的年轻开发者,凭借在 TinTinLand 推出的「Solana 黑客松先锋训练…