unity NPR 卡通渲染

2023-10-24 23:30
文章标签 unity 渲染 卡通 npr

本文主要是介绍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度。

在这里插入图片描述


这篇关于unity NPR 卡通渲染的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/278485

相关文章

详解如何在React中执行条件渲染

《详解如何在React中执行条件渲染》在现代Web开发中,React作为一种流行的JavaScript库,为开发者提供了一种高效构建用户界面的方式,条件渲染是React中的一个关键概念,本文将深入探讨... 目录引言什么是条件渲染?基础示例使用逻辑与运算符(&&)使用条件语句列表中的条件渲染总结引言在现代

Unity Post Process Unity后处理学习日志

Unity Post Process Unity后处理学习日志 在现代游戏开发中,后处理(Post Processing)技术已经成为提升游戏画面质量的关键工具。Unity的后处理栈(Post Processing Stack)是一个强大的插件,它允许开发者为游戏场景添加各种视觉效果,如景深、色彩校正、辉光、模糊等。这些效果不仅能够增强游戏的视觉吸引力,还能帮助传达特定的情感和氛围。 文档

Unity协程搭配队列开发Tips弹窗模块

概述 在Unity游戏开发过程中,提示系统是提升用户体验的重要组成部分。一个设计良好的提示窗口不仅能及时传达信息给玩家,还应当做到不干扰游戏流程。本文将探讨如何使用Unity的协程(Coroutine)配合队列(Queue)数据结构来构建一个高效且可扩展的Tips弹窗模块。 技术模块介绍 1. Unity协程(Coroutines) 协程是Unity中的一种特殊函数类型,允许异步操作的实现

OpenGL ES 2.0渲染管线

http://codingnow.cn/opengles/1504.html Opengl es 2.0实现了可编程的图形管线,比起1.x的固定管线要复杂和灵活很多,由两部分规范组成:Opengl es 2.0 API规范和Opengl es着色语言规范。下图是Opengl es 2.0渲染管线,阴影部分是opengl es 2.0的可编程阶段。   1. 顶点着色器(Vert

Unity 资源 之 Super Confetti FX:点亮项目的璀璨粒子之光

Unity 资源 之 Super Confetti FX:点亮项目的璀璨粒子之光 一,前言二,资源包内容三,免费获取资源包 一,前言 在创意的世界里,每一个细节都能决定一个项目的独特魅力。今天,要向大家介绍一款令人惊艳的粒子效果包 ——Super Confetti FX。 二,资源包内容 💥充满活力与动态,是 Super Confetti FX 最显著的标签。它宛如一位

Unity数据持久化 之 一个通过2进制读取Excel并存储的轮子(4)

本文仅作笔记学习和分享,不用做任何商业用途 本文包括但不限于unity官方手册,unity唐老狮等教程知识,如有不足还请斧正​​ Unity数据持久化 之 一个通过2进制读取Excel并存储的轮子(3)-CSDN博客  这节就是真正的存储数据了   理清一下思路: 1.存储路径并检查 //2进制文件类存储private static string Data_Binary_Pa

Unity Adressables 使用说明(一)概述

使用 Adressables 组织管理 Asset Addressables 包基于 Unity 的 AssetBundles 系统,并提供了一个用户界面来管理您的 AssetBundles。当您使一个资源可寻址(Addressable)时,您可以使用该资源的地址从任何地方加载它。无论资源是在本地应用程序中可用还是存储在远程内容分发网络上,Addressable 系统都会定位并返回该资源。 您

Unity Adressables 使用说明(六)加载(Load) Addressable Assets

【概述】Load Addressable Assets Addressables类提供了加载 Addressable assets 的方法。你可以一次加载一个资源或批量加载资源。为了识别要加载的资源,你需要向加载方法传递一个键或键列表。键可以是以下对象之一: Address:包含你分配给资源的地址的字符串。Label:包含分配给一个或多个资源的标签的字符串。AssetReference Obj

在Unity环境中使用UTF-8编码

为什么要讨论这个问题         为了避免乱码和更好的跨平台         我刚开始开发时是使用VS开发,Unity自身默认使用UTF-8 without BOM格式,但是在Unity中创建一个脚本,使用VS打开,VS自身默认使用GB2312(它应该是对应了你电脑的window版本默认选取了国标编码,或者是因为一些其他的原因)读取脚本,默认是看不到在VS中的编码格式,下面我介绍一种简单快

Unity数据持久化 之 一个通过2进制读取Excel并存储的轮子(3)

本文仅作笔记学习和分享,不用做任何商业用途 本文包括但不限于unity官方手册,unity唐老狮等教程知识,如有不足还请斧正​​ Unity数据持久化 之 一个通过2进制读取Excel并存储的轮子(2) (*****生成数据结构类的方式特别有趣****)-CSDN博客 做完了数据结构类,该做一个存储类了,也就是生成一个字典类(只是声明)  实现和上一节的数据结构类的方式大同小异,所