unity NPR 卡通渲染

这篇具有很好参考价值的文章主要介绍了unity NPR 卡通渲染。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


一、 介绍

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

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

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

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

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

unity 卡通渲染,项目,unity,游戏引擎

unity 卡通渲染,项目,unity,游戏引擎

unity 卡通渲染,项目,unity,游戏引擎


二、 素材准备


三、 步骤

前期角色外观:
unity 卡通渲染,项目,unity,游戏引擎
unity 卡通渲染,项目,unity,游戏引擎
显示纹理:
unity 卡通渲染,项目,unity,游戏引擎
描边:
unity 卡通渲染,项目,unity,游戏引擎
高光和边缘光:

unity 卡通渲染,项目,unity,游戏引擎
最终渲染效果:

unity 卡通渲染,项目,unity,游戏引擎
unity 卡通渲染,项目,unity,游戏引擎
unity 卡通渲染,项目,unity,游戏引擎
unity 卡通渲染,项目,unity,游戏引擎
unity 卡通渲染,项目,unity,游戏引擎


四、 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 100
        Pass { // solid
            Name "Solid"
            Tags { "LightMode"="ForwardBase" }
            // 阴影需要,正向渲染光照基础pass
            CGPROGRAM
            #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 { // outline
            Name "Outline"
            Cull Front
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            #pragma fragmentoption ARB_precision_hint_fastest
            fixed _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 卡通渲染,项目,unity,游戏引擎文章来源地址https://www.toymoban.com/news/detail-754405.html


到了这里,关于unity NPR 卡通渲染的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Unity制作二次元卡通渲染角色材质——5、脸部的特殊处理

    Unity制作二次元材质角色 回到目录 大家好,我是阿赵。 这里继续讲二次元角色材质的制作。这次是讲头部的做法。 之前在分析资源的时候,其实已经发现了这个模型的脸部法线有问题,导致在做光照模型的时候,脸部很奇怪。 把fbx文件导入到3DsMax里面,可以发现 这个模型

    2024年02月09日
    浏览(40)
  • Unity制作二次元卡通渲染角色材质——4 、内外描边和细节添加

    Unity制作二次元材质角色 回到目录 大家好,我是阿赵。 这里继续讲二次元角色材质。这次打算讲一下描边和细节的添加。 外描边的做法也不止一种,比如后处理方法的偏导数ddx/ddy之类的,也能整个屏幕的求出边缘。但一般来说单模型渲染常用的描边方式,是写多一个Pass,

    2024年02月08日
    浏览(40)
  • Unity制作二次元卡通渲染角色材质——3、高光反射与ILM贴图

    Unity制作二次元材质角色 回到目录 大家好,我是阿赵。 这里继续来讲二次元角色的材质。上次讲了光影的色阶化问题,这次继续讲光照模型效果的问题。 之前我们说过,光照模型的最后效果是: 环境色+漫反射+高光+反射。 这里我们可以先忽略环境光,然后之前做了漫反射

    2024年02月11日
    浏览(65)
  • Unity制作二次元卡通渲染角色材质——2、色阶化光影的多种做法对比

    Unity制作二次元材质角色 回到目录 大家好,我是阿赵。 这里继续讲二次元角色渲染。之前说过,最基本的卡通渲染,包含了色阶化光影和描边二个元素。所以这里先来说一下色阶化光影的多种做法对比。 从上一篇文章里面可以知道,这个模型提供了2套贴图,分别是baseMap和

    2024年02月14日
    浏览(39)
  • 游戏引擎技术——前向渲染与延迟渲染

    作者:yangkuKO 一、前言 2015年5月,3A巨作《巫师3:狂猎(The Witcher 3:Wild Hunt)》横空出世,该游戏作为一款开放世界的角色扮演游戏,其巨大的开放世界、绵长的剧情故事、画面精美的表现力深深吸引着大量玩家,并在当年一举拿下 年度最佳游戏、最佳RPG、金操纵杆奖、最

    2024年04月27日
    浏览(35)
  • 【GAMES-104现代游戏引擎】4、引擎渲染基础(渲染基础数据、全局光照、PBR、阴影)

    游戏渲染的挑战 一个场景包含成千上万的GO需要的材质、shader、效果都不尽相同,因此 复杂度极高 当代各种硬件的适配难度高,硬件架构一直在变化 高帧率、高分辨率的要求下,使得绘制算法绘制一帧的时间越来越短, 算法效率要求高 绘制系统可以100%的使用显卡,但CPU只

    2023年04月09日
    浏览(50)
  • 一文读懂Unreal Engine游戏引擎如何提高数字孪生场景渲染能力

    以下案例来自于《数字孪生世界白皮书(2023版)》 领取方式:公众号「EasyV数字孪生」后台回复「白皮书」即可领取! Unreal Engine(下文简称为UE),是一款由Epic Games开发的游戏引擎,用于创建电子游戏、虚拟现实和增强现实应用、数字孪生等内容。UE支持实时渲染、高品质

    2024年02月12日
    浏览(48)
  • 游戏引擎UE如何革新影视行业?创意云全面支持UE云渲染

     虚幻引擎UE(Unreal Engine)作为一款“殿堂级”的游戏引擎,占据了全球80%的商用游戏引擎市场,但如果仅仅将其当做游戏开发的工具,显然是低估了它的能力。比如迪士尼出品的电视剧《曼达洛人》、电影《狮子王》等等都使用了虚幻的虚拟场景。  可见 游戏行业与影视行

    2024年02月16日
    浏览(34)
  • 最全中级Unity面试题(引擎,渲染,Lua等)

    打算年底找工作,所以趁着年前整理波面试题。下面是部分内容,更多内容可以通过底部关注我的公众号获取。 1.UI的优化方案 记录最全面的ugui优化策略_bommy游戏的博客-CSDN博客 2.图集的压缩格式 3.减少GC的方式 Unity优化之GC——合理优化Unity的GC - zblade - 博客园 Unity GC垃圾回

    2024年02月01日
    浏览(48)
  • 【Unity URP】PBR转NPR风格化场景01:描边

    写在前面 风格化不像PBR,好像没有套路可言,,,简直是《怎么好看怎么来》的最大化实践了!感觉出的PBR+NPR也是为了更好地利用PBR资产才诞生的这样一个渲染方案。(当然我的评价非常非常的片面,瞎说的) 偶然间看到了b站一位大佬在blender里实现的效果(原链接【blen

    2023年04月09日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包