unity NPR 卡通渲染

文章目录

  • 一、 介绍
  • 二、 素材准备
  • 三、 步骤
  • 四、 shader代码
  • 五、工程链接


一、 介绍

NPR是计算机图形学中的一类,即非真实感绘制(Non-photorealistic rendering),主要用于模拟艺术式的绘制风格,也用于发展新绘制风格,形式一般是卡通造影。

NPR是Unity中的一种非真实渲染技术,它使用一种称为"NPR"的算法来模拟非真实渲染效果。这种技术可以用于制作各种类型的视觉效果,包括卡通效果、手绘效果、水彩画效果等等。

NPR算法的核心思想是将3D模型表面的每个点映射到一个二维平面上,这个平面上的每个像素点对应一个颜色。然后,NPR算法会根据这个颜色和周围像素点的颜色来计算这个像素点的最终颜色。这个过程可以看作是在这个二维平面上进行一次扫描,并且根据扫描到的每个像素点的颜色和周围像素点的颜色来生成最终的渲染结果。

NPR技术的优点在于它可以在保证画面美观的前提下,极大地降低了渲染的计算量和硬件要求,使得游戏能够在较低配置的设备上运行。此外,NPR技术还可以用于制作各种类型的视觉效果,使得游戏画面更加丰富和多样化。

本文将介绍如何将一个原始的3D角色通过NPR渲染技术转换成类似《原神》中的卡通角色。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


二、 素材准备


三、 步骤

前期角色外观:
在这里插入图片描述
在这里插入图片描述
显示纹理:
在这里插入图片描述
描边:
在这里插入图片描述
高光和边缘光:

在这里插入图片描述
最终渲染效果:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


四、 shader代码

Shader "Custom/ToonShader"
{Properties {[NoScaleOffset] _MainTex ("MainTex", 2D) = "white" {} // 主纹理,用于对象的颜色贴图_MainColor ("MainColor", Color) = (1,1,1,1)// 主颜色,用于设置对象的主要颜色_OutLineWidth ("OutlLineWidth", Range(0, 0.1)) = 0.002// 描边宽度_OutLineColor ("OutLineColor", Color) = (0,0,0,1)// 描边颜色[NoScaleOffset] _GradientTex ("GradientTex", 2D) = "white" {}// 用于阴影梯度采样的纹理,暂时就叫这个名词吧_GradientIntensity ("GradientIntensity", Range(0,1)) = 1// 阴影梯度采样纹理强度_SpecularPower ("SpecularPower", Range(1,100)) = 80// 高光平滑度_SpecularIntensity ("SpecularItensity", Range(0,1)) = 1// 高光强度_SpecularThreshold ("SpecularThreshold", Range(0,1)) = 0.3// 高光阈值_SpecularBrightness ("SpecularBrightness", Range(0,1)) = 0.1// 高光添加的亮度量_SpecularValue ("SpecularValue", Range(0,1)) = 1// 高光值_RimIntensity ("RimIntensity", Range(0,5)) = 1// 边缘光强度[Toggle] _RimShowAtBackToLight ("RimShowAtBackToLight", Float) = 0// 边缘光是否被光照时才显示的开关}SubShader {Tags { "RenderType"="Opaque" }LOD 100Pass { // solidName "Solid"Tags { "LightMode"="ForwardBase" }// 阴影需要,正向渲染光照基础passCGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"#include "AutoLight.cginc"#pragma multi_compile_fwdbase_fullshadows// 阴影需要#pragma fragmentoption ARB_precision_hint_fastest// 最快速精度struct appdata {float4 vertex : POSITION;float2 uv : TEXCOORD0;half3 normal : NORMAL;};struct v2f {float4 pos : SV_POSITION;float2 uv : TEXCOORD0;half3 worldNormal : TEXCOORD1;float3 worldPos : TEXCOORD2;UNITY_LIGHTING_COORDS(3,4)// 阴影需要};sampler2D _MainTex;fixed4 _MainColor;sampler2D _GradientTex;fixed _GradientIntensity;fixed _SpecularPower;fixed _SpecularIntensity;fixed _SpecularThreshold;fixed _SpecularBrightness;fixed _SpecularValue;fixed _RimIntensity;fixed _RimShowAtBackToLight;v2f vert (appdata v) {v2f o;o.pos = UnityObjectToClipPos(v.vertex);o.uv = v.uv;o.worldNormal = UnityObjectToWorldNormal(v.normal);o.worldPos = mul(unity_ObjectToWorld, v.vertex);TRANSFER_VERTEX_TO_FRAGMENT(o)// 阴影需要return o;}fixed4 frag (v2f i) : SV_Target {i.worldNormal = normalize(i.worldNormal);half3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos);half3 lightDir = normalize(_WorldSpaceLightPos0.xyz);UNITY_LIGHT_ATTENUATION(atten,i,i.worldPos);atten = atten * 0.5 + 0.5;fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;fixed LdotN = dot(lightDir, i.worldNormal);fixed halfLambert = LdotN * 0.5 + 0.5;fixed lightShadowCoef = halfLambert * atten;fixed3 diffuse = tex2D(_MainTex, i.uv).rgb * _MainColor;fixed3 dGradient = tex2D(_GradientTex, float2(lightShadowCoef, 0)).rgb;diffuse = lerp(diffuse,  diffuse * dGradient, _GradientIntensity);half3 hDir = normalize(viewDir + lightDir);fixed HdotN = max(0, dot(hDir, i.worldNormal));fixed specular = pow(HdotN, _SpecularPower) * _SpecularIntensity;specular *= atten;specular = step(_SpecularThreshold, specular) * _SpecularValue;fixed rimFactor = (1 - dot(viewDir, i.worldNormal)) * _RimIntensity;rimFactor = lerp(rimFactor, rimFactor * max(0, dot(-lightDir, viewDir)), _RimShowAtBackToLight);rimFactor *= atten;rimFactor = step(_SpecularThreshold, rimFactor) * _SpecularValue;specular = max(specular, rimFactor);return fixed4(ambient + diffuse + diffuse * specular + specular * _SpecularBrightness, 1);}ENDCG}Pass { // outlineName "Outline"Cull FrontCGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"#pragma fragmentoption ARB_precision_hint_fastestfixed _OutLineWidth;fixed4 _OutLineColor;float4 vert (float4 vertex : POSITION, float3 normal : NORMAL) : SV_POSITION {// 投影空间float4 pos = UnityObjectToClipPos(vertex);// 转换到视图空间的法线fixed3 vNormal = mul((float3x3)UNITY_MATRIX_IT_MV, normal);fixed2 offset = TransformViewToProjection(vNormal.xy);// 由于在顶点后处理会有透视除法,所以我们首先乘上pos.w以抵消透视,这样无论多远多近都可以按恒定的描边边宽来显示pos.xy += offset * _OutLineWidth * pos.w;return pos;}fixed4 frag () : SV_Target { return _OutLineColor; }ENDCG}}Fallback "Diffuse"
}

这个Unity卡通渲染的Shader代码使用了以下技术和功能:

  1. 主纹理和颜色属性:使用了主纹理 _MainTex 和主颜色 _MainColor 来控制对象的颜色。

  2. 描边效果:通过 _OutLineWidth_OutLineColor 控制描边的宽度和颜色。

  3. 阴影梯度采样:使用 _GradientTex_GradientIntensity 控制阴影梯度采样纹理和强度。

  4. 高光效果:通过 _SpecularPower_SpecularIntensity_SpecularThreshold_SpecularBrightness_SpecularValue 控制高光的平滑度、强度、阈值和亮度。

  5. 边缘光效果:使用 _RimIntensity 控制边缘光的强度,以及 _RimShowAtBackToLight 控制边缘光是否受光照方向影响。

  6. 正向渲染光照:使用 TagsCGPROGRAM 中的相关指令来支持正向渲染光照,包括阴影的处理。

  7. 顶点着色器和片元着色器:定义了顶点着色器 vert 和片元着色器 frag,并在这里执行了主要的渲染计算。

  8. 光照计算:计算了光照方向、光照强度、阴影、漫反射、高光等光照效果。

  9. 描边效果的后处理:在 Outline Pass 中,实现了对象的描边效果。

  10. Shader Fallback:如果渲染模式不支持这个Shader,会回退到使用 “Diffuse” Shader。

这个Shader包含了多种效果,包括卡通风格的渲染、高光、描边和阴影梯度,以及一些参数控制这些效果的强度和外观。这些效果可以用于实现卡通风格的游戏或动画渲染。


五、工程链接


https://download.csdn.net/download/qq_20179331/88454844

内含exe文件

1.滑动鼠标中键滚轮,可以放大、缩小视角

2.按一下q键,场景相机顺时针旋转90度;按一下w键,场景相机逆时针旋转90度。

在这里插入图片描述


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

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

相关文章

owasp top 10

1、访问控制的崩溃: 通过身份验证的用户可以访问其他用户的信息,越权 达成方式:通过修改url、内部应用程序状态或html页面绕过 防范:除了公有资源外,默认情况下拒绝访问,严格判断权限,记录失败的…

冰蝎默认加密的流量解密

破解冰蝎的默认加密 流量包分析 上传的冰蝎流量包 POST /web-zh/DVWA/vulnerabilities/upload/ HTTP/1.1 Host: 192.168.197.111 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/118.0 Accept: text/html,application/xhtmlxml,a…

Ansible定义各类变量,引用变量方式介绍及注册变量和vars_prompt的用法示例

目录 一.Ansible定义变量 1.用途 2.定义规则 3.变量优先级 二.命令行定义变量 三.定义主机和主机组变量 1.主机变量 (1)内置主机变量 (2)简单示例 2.主机组变量 四.定义playbook变量 1.通过vars表示定义变量&#xff…

HTML 实现 点击按钮切换 整张界面 点击按钮切换局部界面

点击按钮实现页面切换 点击按钮切换全局界面方法一: 使用a标签进行跳转连接 href方法二:在button标签中加上onclick属性,赋值为Javascript方法三:触发一个函数跳转方法四:表单的action定向提交跳转 点击按钮切换局部界…

shell条件测试与条件测试操作符

shell条件测试与条件测试操作符 条件测试变量#?test与条件测试语句方括号测试表达式字符串测试操作符逻辑测试操作符整数测试操作符双小括号的整数测试操作符与含义文件测试操作符条件测试举例 条件测试 条件测试是可以根据某个特定条件是否满足,来选择…

vscode调试container(进行rocksdb调试)+vscode比较git项目不同分支和fork的哪个分支

vscode调试container(进行rocksdb调试) 参考链接: https://blog.csdn.net/qq_29809823/article/details/128445308#t5 https://blog.csdn.net/qq_29809823/article/details/121978762#t7 使用vscode中的插件dev containners->点击左侧的…

zmq封装

ZmqBindlib zmq常用封装 使用方法 基本使用 1.简单请求回复 ZmqRequest request new ZmqRequest();request.RemoteAddress localaddes;request.PubClient "A";int num 0;while (true){// Thread.Sleep(1000);//string msg request.Request("hi"…

【微信小程序开发】小程序微信用户授权登录(用户信息手机号)

🥳🥳Welcome Huihuis Code World ! !🥳🥳 接下来看看由辉辉所写的关于小程序的相关操作吧 目录 🥳🥳Welcome Huihuis Code World ! !🥳🥳 授权流程讲解 一.用户信息授权登录 1.w…

MD-MTSP:粒子群优化算法PSO求解多仓库多旅行商问题MATLAB(可更改数据集,旅行商的数量和起点)

一、多仓库多旅行商问题MD-MTSP 多旅行商问题(Multiple Traveling Salesman Problem, MTSP)是著名的旅行商问题(Traveling Salesman Problem, TSP)的延伸,多旅行商问题定义为:给定一个𝑛座城市…

LabVIEW中管理大型数据

LabVIEW中管理大数据 LabVIEW的最大优势之一是自动内存管理。这种内存管理允许用户轻松创建字符串、数组和集群,而无需C/C用户经常担心。但是,这种内存管理设计为绝对安全,因此数据被非常频繁地复制。这通常不会造成任何问题,但是…

vue3 列表页开发【选择展示列】功能

目录 背景描述: 开发流程: 详细开发流程: 总结: 背景描述: 这个功能是基于之前写的 封装列表页 的功能继续写的,加了一个选择展示列的功能,可以随时控制表格里展示那些列的数据&#xf…

【算法教程】排列与组合的实现

数据准备 在讲排列与组合之前,我们先定义数据元素类型Fruit class Fruit{constructor(name,price){this.name namethis.price price} }排列 对N个不同元素进行排序,总共有多少不同的排列方式? Step1: 从N个元素中取1个,共N种…

Pandas 数据处理分析系列1--SeriesDataFrame数据结构详解

Pandas 概述 Pandas 是一个开源的数据分析和数据处理库,是基于 NumPy 开发的。它提供了灵活且高效的数据结构,使得处理和分析结构化、缺失和时间序列数据变得更加容易。其在数据分析和数据处理领域广泛应用,在金融、社交媒体、科学研究等领域都有很高的使用率和广泛的应用场…

系列十一、Redis中分布式缓存实现

一、缓存 1.1、什么是缓存 内存就是计算机内存中的一段数据。 1.2、内存中的数据特点 读写快断电数据丢失 1.3、缓存解决了什么问题 提高了网站的吞吐量和运行效率减轻了数据库的访问压力 1.4、哪些数据适合加缓存 使用缓存时,一定是数据库中的数据极少发生改…

【Vue】Element开发笔记

Element开发笔记 前言 官网 https://element.eleme.cn/#/zh-CN/component/upload 其它项目网站 https://www.cnblogs.com/qq2806933146xiaobai/p/17180878.html 表格 序号列添加 <el-table-column type"index" :index"handleIndexCalc" label&qu…

深度强化学习 第 4 章 DQN 与 Q 学习

4.1 DQN 最优动作价值函数的用途 假如我们知道 Q ⋆ Q_⋆ Q⋆​&#xff0c;我们就能用它做控制。 我们希望知道 Q ⋆ Q_⋆ Q⋆​&#xff0c;因为它就像是先知一般&#xff0c;可以预见未来&#xff0c;在 t t t 时刻就预见 t t t 到 n n n时刻之间的累计奖励的期望。假如…

5G来临,迎客莱带你探索运营商大数据的应用

随着5G时代的来临&#xff0c;不仅在算力的基础上得到了加强和保障&#xff0c;同时也丰富了计算的方式和模式&#xff0c;如边缘计算、霾计算等。计算方式和模式的改变&#xff0c;对于运营商来说&#xff0c;意味着更丰富的数据维度&#xff0c;更鲜活的数据和更强大的数据处…

无人机航拍图像拼接与目标识别

一、简介 无人机用来做图像侦察是常见功能&#xff0c;现有技术基本是无人机对某片区域进行飞行&#xff0c;人工实时监控飞行图像&#xff0c;将图像录制成视频供事后回放。此方法对人员业务要求比较高、反应速度足够快、不利于信息收集、录制视频丢失空间信息、对于后期开展区…

Qt判断一个点在多边形内还是外(支持凸边形和凹变形)

这里实现的方法是转载于https://blog.csdn.net/trj14/article/details/43190653和https://blog.csdn.net/WilliamSun0122/article/details/77994526 来实现的&#xff0c;并且按照Qt的规则进行了调整。 以下实现方法有四种&#xff0c;每种方法的具体讲解在转载的博客中有说明&…

Python之爬虫

目录 HTTP请求HTTP响应获得页面响应伪装用户访问打包数据爬取豆瓣top250 HTTP请求 HTTP&#xff1a;HypertextTransferProtcol 超文本传输协议 1、请求行 POST/user/info?new_usertrue HTTP/1.1#资源了路径user/info 查询参数new_usertrue 协议版本HTTP/1.1 2、请求头 Ho…