Unity3d Shader篇(十四)— 卡通着色

文章目录

  • 前言
  • 一、什么是卡通着色?
    • 1. 卡通着色原理
    • 2. 卡通着色优缺点
        • 优点:
        • 缺点:
  • 二、使用步骤
    • 1. Shader 属性定义
    • 2. SubShader 设置
    • 3. 卡通轮廓 Pass
    • 4. 卡通主 Pass
  • 三、效果
  • 四、总结


前言

卡通着色是一种常见的图形渲染效果,它将物体的光照和颜色处理成简单的、扁平的色块,以模拟漫画或动画中的风格。本篇博客将介绍如何在Unity中使用Shader实现卡通着色效果。


一、什么是卡通着色?

1. 卡通着色原理

简化光照:卡通着色将光照计算简化为基于表面法线和光源方向的漫反射模型,通常忽略了光源的阴影和反射等复杂效果,使得渲染结果更加扁平。
颜色平滑处理:卡通着色通过将颜色分段处理或应用简单的插值,使得颜色之间的过渡更加平滑,呈现出类似于印刷品的色彩效果。
轮廓加粗
:为了突出物体的轮廓,卡通着色通常会在物体的边缘添加黑色或彩色的轮廓线,增强了整体的辨识度和艺术感。
卡通效果增强:通过调整卡通效果的参数,可以控制渲染结果的卡通程度,从而满足不同风格的需求。

2. 卡通着色优缺点

优点:

独特的艺术风格:卡通着色能够产生独特的艺术效果,使得场景或物体呈现出类似于漫画或动画的视觉风格,增加了趣味性和表现力。
渲染速度快:相比于传统的真实感渲染技术,卡通着色通常需要计算的光照和材质参数较少,因此渲染速度较快,适用于实时渲染和移动平台。
简单易用:实现卡通着色的技术和工具已经比较成熟,开发者可以通过使用现成的着色器或工具包,快速实现卡通效果,降低了开发成本。

缺点:

失去真实感:卡通着色通常会忽略真实世界中的光照、阴影和材质细节,因此渲染结果可能缺乏真实感,无法满足某些场景或项目的需求。
局限性较大:卡通着色的艺术风格和效果相对固定,适用范围较窄,无法满足所有类型的项目或用户需求。
易产生过度简化:为了追求卡通效果,有时候可能会过度简化场景或物体的细节,导致渲染结果显得过于平面化或单调。

二、使用步骤

1. Shader 属性定义

首先,我们定义Shader中所需的属性,包括主纹理贴图、渐变纹理贴图、漫反射颜色、轮廓大小、轮廓颜色、卡通效果步数、卡通效果强度、边缘光颜色和边缘光强度等。

// 定义属性
Shader "Unlit/ToonShader"
{
    Properties
    {
        _MainTex ("Main Texture", 2D) = "white" // 主纹理贴图
        _RampTex ("Ramp Texture", 2D) = "white" // 渐变纹理贴图
        _Diffuse("Diffuse Color",Color)=(1,1,1,1) // 漫反射颜色属性,默认白色
        _OutlineScale("Outline Scale",Range(0,1))=0.5 // 轮廓大小属性
        _OutlineColor("Outline Color",Color)=(0,0,0,1) // 轮廓颜色属性
        _Steps("Steps",Range(1,30))=1 // 卡通效果步数
        _ToonEffect("Toon Effect",Range(0,1))=0.5 // 卡通效果强度
        _RimColor("Rim Color",Color)=(1,1,1,1) // 边缘光颜色
        _RimPower("Rim Power",Range(0.001,3))=1 // 边缘光强度
    }

    // 其他SubShader和Pass部分省略
}

2. SubShader 设置

SubShader
{
    Tags
    {
        "Queue"="Geometry+1000"// 在其他不透明物体后面渲染
        "RenderType"="Opaque" // 渲染类型为Opaque
    }
    
    LOD 100 // 细节级别
}

3. 卡通轮廓 Pass

卡通着色常常伴随着黑色轮廓,我们首先实现轮廓效果。在Shader中,通过对顶点位置进行外扩,并在片元着色器中输出轮廓颜色来实现。

// 轮廓Pass
Pass
{
    Name "Outline" // Pass名称为Outline
    Cull Front // 剔除正面

    CGPROGRAM
    #pragma vertex vert // 顶点着色器函数声明
    #pragma fragment frag // 片元着色器函数声明
    #include "UnityCG.cginc" // 包含Unity宏

    float _OutlineScale; // 轮廓大小
    float4 _OutlineColor; // 轮廓颜色

    struct v2f
    {
        float4 vertex:SV_POSITION; // 顶点位置
    };

    // 顶点着色器
    v2f vert(appdata_base v)
    {
        v2f o;
        o.vertex = UnityObjectToClipPos(v.vertex); // 将顶点位置从对象空间转换到裁剪空间

        float3 normal = normalize(mul((float3x3)UNITY_MATRIX_IT_MV, v.normal)); // 计算变换后的法线
        float2 viewNormal = TransformViewToProjection(normal.xy); // 将法线转换到投影空间
        o.vertex.xy += viewNormal * _OutlineScale; // 根据轮廓大小调整顶点位置

        return o;
    }

    // 片元着色器
    fixed4 frag(v2f i):SV_Target
    {
        return _OutlineColor; // 输出轮廓颜色
    }
    ENDCG
}

剔除正面: 轮廓 Pass 会设置剔除正面(Cull Front),这意味着只有物体的背面会被渲染,而正面将被剔除。
顶点着色器处理: 顶点着色器会对物体的顶点进行处理,通常会通过一定的方式扩大或缩小顶点的位置,以产生轮廓效果。这可以通过将顶点从对象空间转换到裁剪空间后,根据一定的算法调整顶点的位置来实现。
片元着色器处理: 片元着色器负责输出轮廓的颜色。通常轮廓的颜色是黑色或者是与物体主色彩对比较大的颜色,以便与主 Pass 渲染的物体区分开来。

4. 卡通主 Pass

接下来,我们实现卡通着色的主要效果。在片元着色器中,根据光照和漫反射计算出最终颜色,并加入卡通效果和边缘光效果。

// 主Pass
Pass
{
    CGPROGRAM
    #pragma vertex vert // 顶点着色器函数声明
    #pragma fragment frag // 片元着色器函数声明
    #include "UnityCG.cginc" // 包含Unity宏
    #include "Lighting.cginc" // 包含光照宏

    struct v2f
    {
        float4 vertex : SV_POSITION; // 顶点位置
        float2 uv : TEXCOORD0; // 纹理坐标
        fixed3 worldNormal : TEXCOORD1; // 世界空间法线
        float3 worldPos : TEXTCOORD2; // 世界空间位置
    };

    sampler2D _MainTex; // 主纹理贴图
    sampler2D _RampTex; // 渐变纹理贴图
    float4 _MainTex_ST; // 主纹理贴图的缩放和偏移参数
    float4 _Diffuse; // 漫反射颜色
    float _Steps; // 卡通效果步数
    float _ToonEffect; // 卡通效果强度
    float4 _RimColor; // 边缘光颜色
    float _RimPower; // 边缘光强度

    // 顶点着色器
    v2f vert(appdata_base v)
    {
        v2f o;
        o.vertex = UnityObjectToClipPos(v.vertex); // 将顶点位置从对象空间转换到裁剪空间
        o.worldNormal = UnityObjectToWorldNormal(v.normal); // 将法线从对象空间转换到世界空间
        o.worldPos = mul(unity_ObjectToWorld, v.vertex); // 将顶点位置从对象空间转换到世界空间
        o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); // 转换纹理坐标
        return o;
    }

    // 片元着色器
    fixed4 frag(v2f i) : SV_Target
    {
        fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz; // 环境光
        fixed4 albedo = tex2D(_MainTex, i.uv); // 纹理采样
        fixed3 worldLightDir = UnityWorldSpaceLightDir(i.worldPos); // 光源方向
        fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos)); // 视角方向

        // 求半兰伯特模型
        float difLight = dot(worldLightDir, i.worldNormal) * 0.5 + 0.5; // 计算漫反射光强度

        // 卡通颜色处理
        difLight = smoothstep(0, 1, difLight); // 平滑过渡
        float toon = floor(difLight * _Steps) / _Steps; // 卡通效果
        difLight = lerp(difLight, toon, _ToonEffect); // 混合卡通效果

        // 边缘光计算
        float rim = 1 - dot(i.worldNormal, viewDir); // 边缘光强度
        fixed3 rimColor = _RimColor * pow(rim, 1 / _RimPower); // 边缘光颜色

        // 漫反射计算
        fixed3 diffuse = _LightColor0.rgb * albedo * _Diffuse.rgb * difLight; // 漫反射光颜色

        fixed3 color = diffuse + ambient + rimColor; // 最终颜色
        return fixed4(color, 1); // 输出最终颜色
    }
    ENDCG
}

顶点着色器处理: 主 Pass 的顶点着色器会对物体的顶点进行一些必要的计算和变换,如将顶点从对象空间转换到裁剪空间、将法线从对象空间转换到世界空间等。
片元着色器处理: 主 Pass 的片元着色器负责处理每个像素的渲染。这包括对物体表面的光照计算、纹理采样、漫反射计算、卡通效果处理、边缘光计算等。最终输出的颜色会结合光照、材质、纹理等信息,生成最终的渲染结果。
光照计算: 主 Pass 会根据场景中的光源信息以及物体的法线等属性,计算每个像素的光照效果。这可以是简化的漫反射光照模型,也可以包括其他光照效果,如环境光、辐射光等。
卡通效果处理: 主 Pass 也可能包含卡通效果的处理。这通常是通过调整颜色、平滑度等参数,使渲染结果呈现出卡通风格的效果。
边缘光计算: 一些主 Pass 也会包含边缘光效果的计算。这是为了增强物体的轮廓,使得物体在渲染结果中更加清晰可辨。

三、效果

在这里插入图片描述

四、总结

卡通着色是一种特殊的渲染技术,通过简化光照和色彩处理,模拟出类似于漫画或动画的视觉风格。

动画和游戏设计: 在动画片、电子游戏以及其他媒体制作中,卡通着色常常用于呈现特定的艺术风格,如日本动漫、欧美卡通等。这种风格能够增加作品的趣味性和独特性,使得角色和场景更加生动活泼。

虚拟现实和增强现实: 在虚拟现实(VR)和增强现实(AR)应用中,卡通着色可以帮助创建出具有沉浸感和趣味性的虚拟环境。通过简化的色彩和光照处理,可以减少硬件的渲染负担,提高应用的性能和稳定性。

教育和培训: 在教育领域,卡通着色常被用于制作教学动画、交互式课件等教育资料。这种风格通常更容易吸引学生的注意力,使得知识传递更加生动有趣。

广告和营销: 在广告和营销领域,卡通着色可以用于创建具有吸引力和记忆点的广告宣传片或品牌形象。这种风格的广告更容易引起观众的共鸣,增强品牌形象和产品识别度。

艺术创作和表现: 艺术家们也常常利用卡通着色技术来创作艺术作品,表达个人风格和情感。通过简化的色彩和线条处理,可以创造出独特的艺术风格,表达作者的创意和情感。

总的来说,卡通着色具有广泛的应用范围,可以在各种媒体制作、虚拟环境、教育培训、广告营销以及艺术创作等领域发挥重要作用。其独特的艺术风格和易于吸引观众的特点,使得它成为许多项目和应用中的首选渲染技术之一。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

大语言模型:Query Rewriting for Retrieval-Augmented Large Language Models

总体思路 作者首先指出大语言模型虽然取得了很好的效果,但是仍然存在幻觉和时间顺序混乱的问题,因此需要额外知识库和LLM内部知识库相结合,来修正;因此优化传统的retriever-reader的方案成为需要;目前的研究方案当中使…

Nginx的日志怎么看,在哪看,access.log日志内容详解

Nginx 的日志文件通常位于服务器的文件系统中,具体位置可能因配置而异。以下是查看 Nginx 日志的几种方法: 1、查看访问日志:在默认配置下,Nginx 的访问日志文件路径为 /var/log/nginx/access.log。您可以通过命令 sudo cat /var…

前端框架vue的样式操作,以及vue提供的属性功能应用实战

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,…

【2024-完整版】python爬虫 批量查询自己所有CSDN文章的质量分:附整个实现流程

【2024】批量查询CSDN文章质量分 写在最前面一、分析获取步骤二、获取文章列表1. 前期准备2. 获取文章的接口3. 接口测试(更新重点) 三、查询质量分1. 前期准备2. 获取文章的接口3. 接口测试 四、python代码实现1. 分步实现2. 批量获取文章信息3. 从exce…

必看 11个AI自动写作神器

AI自动写作神器是当今科技发展中的重大突破,能够以人工智能技术为基础,自动生成高质量的文章。下面将介绍10个AI自动写作神器,看看他们有哪些值得推荐的地方? 一、爱制作ai写作生成器 爱制作AI运用先进的文字生成式AI技术&#xf…

visualvm连接到远程服务

启动命令 java -Dcom.sun.management.jmxremote.rmi.port1232 \ -Dcom.sun.management.jmxremote.port1232 \ -Dcom.sun.management.jmxremote.sslfalse \ -Dcom.sun.management.jmxremote.authenticatefalse \ -jar ${你的jar包名}.jar参数说明 java \ #指定JMX RMI (Re…

2048.神、上帝以及老天爷

典型的错排问题 题解:计算所有人错排的种类数/阶乘 错排种类数: 1——0 2——1 3——2 第一个人两种选择假设1拿了2的,那么2只能拿3,因为2如果拿1,3就会拿3就不会拿错 4——9 3(12) 5——44 f(n)(n-1)*[f(n-1)…

尝试搭建谷粒商城 记录(二)

1、后台管理系统 1.整合renren-fast 在记录(一)中,我们已经基本配置好了一些环境 ,后续有需要再补充吧 下载renren-fast ,把文件夹复制到gulimall文件夹下, 然后修改父pom.xml文件加入这个module 修改renre…

如何使用vscode创建Node.js服务并结合内网穿透实现远程访问本地服务

文章目录 前言1.安装Node.js环境2.创建node.js服务3. 访问node.js 服务4.内网穿透4.1 安装配置cpolar内网穿透4.2 创建隧道映射本地端口 5.固定公网地址 前言 Node.js 是能够在服务器端运行 JavaScript 的开放源代码、跨平台运行环境。Node.js 由 OpenJS Foundation&#xff0…

如何在Linux系统部署APITable容器并实现无公网IP远程管理本地数据

文章目录 前言1. 部署APITable2. cpolar的安装和注册3. 配置APITable公网访问地址4. 固定APITable公网地址 前言 vika维格表作为新一代数据生产力平台,是一款面向 API 的智能多维表格。它将复杂的可视化数据库、电子表格、实时在线协同、低代码开发技术四合为一&am…

优思学院|六西格玛实验设计(DOE)咖啡冲泡案例

在追求完美咖啡口感的过程中,了解不同冲泡参数如何影响最终成品是至关重要的。六西格玛中的实验设计(DOE)是一种强大的统计方法,能帮助我们系统地研究这些参数,并优化我们的冲泡过程。今天,优思学院将通过一…

Springboot中Redis的配置使用

新建 向pom.xml中添加依赖&#xff0c;这个可以不用标注版本号 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency> 配置yml文件&#xff08;文件名不可以错…

C语言例2-1:从键盘输入两个整数,计算其乘积

代码如下&#xff1a; //从键盘输入两个整数&#xff0c;计算其乘积 #include<stdio.h> int main(void) /*主函数*/ {int n1, n2, result; /*定义保存两个整数及其乘积的变量*/printf("please inp…

畅捷通T+ InitServerInfo.aspx SQL漏洞(2024年3月发布)

漏洞简介 由于畅捷通T的InitServerInfo.aspx接口处未对用户的输入进行过滤和校验&#xff0c;未经身份验证的攻击者除了可以利用 SQL 注入漏洞获取数据库中的信息&#xff08;例如&#xff0c;管理员后台密码、站点的用户个人信息&#xff09;之外&#xff0c;甚至在高权限的情…

LDA 关键词提取

目录 介绍 主题数确认 代码实现 普通关键词提取 TF-IDF&#xff0c;textRank 实现链接&#xff1a;gensim 实现 TF-IDF&#xff1b;textRank 关键词提取_gensim tfidf关键词-CSDN博客 它们是直接从文本中提取关键词&#xff0c;如果想基于一些潜在语义&#xff0c;可以用 L…

从零开始利用MATLAB进行FPGA设计(二)用于HDL代码生成的Simulink模型并用于流水线设计

文章灵感来源于MATLAB官方免费教程&#xff1a;HDL Coder Self-Guided Tutorial 考虑到MATLAB官网的英文看着慢&#xff0c;再加上视频讲解老印浓浓的咖喱味&#xff0c;我决定记录利用MATLAB&Simulink&SystemGenerator进行FPGA数字信号处理的学习过程。 往期回顾&am…

C语言柔性数组详解:让你的程序更灵活

柔性数组 一、前言二、柔性数组的用法三、柔性数组的内存分布四、柔性数组的优势五、总结 一、前言 仔细观察下面的代码&#xff0c;有没有看出哪里不对劲&#xff1f; struct S {int i;double d;char c;int arr[]; };还有另外一种写法&#xff1a; struct S {int i;double …

全球首个 AI 软件工程师 Devin它来了!

如果您想每日获取AI最新新闻,欢迎关注文章底部的公众号 Cognition AI 发布 AI 软件工程师 Devin 初创公司 Cognition 近日发布公告,宣布推出全球首个 AI 软件工程师 Devin,并号称会彻底改变人类构建软件的方式。Devin 擅长长期推理能力,可以自主规划和完成软件项目,并在此…

国产开源数据库厂商

这是ren_dong的第36篇原创 前言 开源数据库即免费的社区数据库&#xff0c;其源代码可供公众使用&#xff0c;并且可以在其原始设计中进行修改或使用。开源数据库的流行示例包括 MySQL&#xff0c;PostgreSQL和MongoDB。 image 开源数据库用户托管数据库部署的方式有 内部部署、…